/** * Checks the schema is properly set up. * * @throws \moodle_exception * @return void */ public function validate_setup() { $fields = \search_solr\document::get_default_fields_definition(); // Field id is already there. unset($fields['id']); $this->check_index(); $this->validate_fields($fields, true); }
/** * Prepares a new query object with needed limits, filters, etc. * * @param stdClass $filters Containing query and filters. * @param array $usercontexts Contexts where the user has access. True if the user can access all contexts. * @return SolrDisMaxQuery */ protected function create_user_query($filters, $usercontexts) { global $USER; // Let's keep these changes internal. $data = clone $filters; $query = new \SolrDisMaxQuery(); $this->set_query($query, $data->q); $this->add_fields($query); // Search filters applied, we don't cache these filters as we don't want to pollute the cache with tmp filters // we are really interested in caching contexts filters instead. if (!empty($data->title)) { $query->addFilterQuery('{!field cache=false f=title}' . $data->title); } if (!empty($data->areaids)) { // If areaids are specified, we want to get any that match. $query->addFilterQuery('{!cache=false}areaid:(' . implode(' OR ', $data->areaids) . ')'); } if (!empty($data->courseids)) { $query->addFilterQuery('{!cache=false}courseid:(' . implode(' OR ', $data->courseids) . ')'); } if (!empty($data->timestart) or !empty($data->timeend)) { if (empty($data->timestart)) { $data->timestart = '*'; } else { $data->timestart = \search_solr\document::format_time_for_engine($data->timestart); } if (empty($data->timeend)) { $data->timeend = '*'; } else { $data->timeend = \search_solr\document::format_time_for_engine($data->timeend); } // No cache. $query->addFilterQuery('{!cache=false}modified:[' . $data->timestart . ' TO ' . $data->timeend . ']'); } // Restrict to users who are supposed to be able to see a particular result. $query->addFilterQuery('owneruserid:(' . \core_search\manager::NO_OWNER_ID . ' OR ' . $USER->id . ')'); // And finally restrict it to the context where the user can access, we want this one cached. // If the user can access all contexts $usercontexts value is just true, we don't need to filter // in that case. if ($usercontexts && is_array($usercontexts)) { // Join all area contexts into a single array and implode. $allcontexts = array(); foreach ($usercontexts as $areaid => $areacontexts) { if (!empty($data->areaids) && !in_array($areaid, $data->areaids)) { // Skip unused areas. continue; } foreach ($areacontexts as $contextid) { // Ensure they are unique. $allcontexts[$contextid] = $contextid; } } if (empty($allcontexts)) { // This means there are no valid contexts for them, so they get no results. return array(); } $query->addFilterQuery('contextid:(' . implode(' OR ', $allcontexts) . ')'); } if ($this->file_indexing_enabled()) { // Now group records by solr_filegroupingid. Limit to 3 results per group. $query->setGroup(true); $query->setGroupLimit(3); $query->setGroupNGroups(true); $query->addGroupField('solr_filegroupingid'); } else { // Make sure we only get text files, in case the index has pre-existing files. $query->addFilterQuery('type:' . \core_search\manager::TYPE_TEXT); } return $query; }
public function test_export_file_for_engine() { // Get area to work with. $areaid = \core_search\manager::generate_areaid('core_mocksearch', 'mock_search_area'); $area = \core_search\manager::get_search_area($areaid); $record = $this->generator->create_record(); $doc = $area->get_document($record); $filerecord = new stdClass(); $filerecord->timemodified = 978310800; $file = $this->generator->create_file($filerecord); $doc->add_stored_file($file); $filearray = $doc->export_file_for_engine($file); $this->assertEquals(\core_search\manager::TYPE_FILE, $filearray['type']); $this->assertEquals($file->get_id(), $filearray['solr_fileid']); $this->assertEquals($file->get_contenthash(), $filearray['solr_filecontenthash']); $this->assertEquals(\search_solr\document::INDEXED_FILE_TRUE, $filearray['solr_fileindexstatus']); $this->assertEquals($file->get_filename(), $filearray['title']); $this->assertEquals(978310800, \search_solr\document::import_time_from_engine($filearray['modified'])); }
/** * Prepares a Solr query, applies filters and executes it returning its results. * * @throws \core_search\engine_exception * @param stdClass $filters Containing query and filters. * @param array $usercontexts Contexts where the user has access. True if the user can access all contexts. * @return \core_search\document[] Results or false if no results */ public function execute_query($filters, $usercontexts) { // Let's keep these changes internal. $data = clone $filters; // If there is any problem we trigger the exception as soon as possible. $this->client = $this->get_search_client(); $serverstatus = $this->is_server_ready(); if ($serverstatus !== true) { throw new \core_search\engine_exception('engineserverstatus', 'search'); } $query = new \SolrQuery(); $this->set_query($query, $data->q); $this->add_fields($query); // Search filters applied, we don't cache these filters as we don't want to pollute the cache with tmp filters // we are really interested in caching contexts filters instead. if (!empty($data->title)) { $query->addFilterQuery('{!field cache=false f=title}' . $data->title); } if (!empty($data->areaid)) { // Even if it is only supposed to contain PARAM_ALPHANUMEXT, better to prevent. $query->addFilterQuery('{!field cache=false f=areaid}' . $data->areaid); } if (!empty($data->timestart) or !empty($data->timeend)) { if (empty($data->timestart)) { $data->timestart = '*'; } else { $data->timestart = \search_solr\document::format_time_for_engine($data->timestart); } if (empty($data->timeend)) { $data->timeend = '*'; } else { $data->timeend = \search_solr\document::format_time_for_engine($data->timeend); } // No cache. $query->addFilterQuery('{!cache=false}modified:[' . $data->timestart . ' TO ' . $data->timeend . ']'); } // And finally restrict it to the context where the user can access, we want this one cached. // If the user can access all contexts $usercontexts value is just true, we don't need to filter // in that case. if ($usercontexts && is_array($usercontexts)) { if (!empty($data->areaid)) { $query->addFilterQuery('contextid:(' . implode(' OR ', $usercontexts[$data->areaid]) . ')'); } else { // Join all area contexts into a single array and implode. $allcontexts = array(); foreach ($usercontexts as $areacontexts) { foreach ($areacontexts as $contextid) { // Ensure they are unique. $allcontexts[$contextid] = $contextid; } } $query->addFilterQuery('contextid:(' . implode(' OR ', $allcontexts) . ')'); } } try { return $this->query_response($this->client->query($query)); } catch (\SolrClientException $ex) { debugging('Error executing the provided query: ' . $ex->getMessage(), DEBUG_DEVELOPER); $this->queryerror = $ex->getMessage(); return array(); } catch (\SolrServerException $ex) { debugging('Error executing the provided query: ' . $ex->getMessage(), DEBUG_DEVELOPER); $this->queryerror = $ex->getMessage(); return array(); } }