/** * Set terms on search_did given * * @param string $terms_string Comma-separated list of terms from input form * @param string $prefix Search engine prefix * @param string $course_code Course code * @param string $tool_id Tool id from mainapi.lib.php * @param int $ref_id_high_level Main id of the entity to index (Ex. lp_id) * @param int $ref_id_second_level Secondary id of the entity to index (Ex. lp_item) * @param int $search_did Search engine document id from search_engine_ref table * @return boolean False on error or nothing to do, true otherwise */ function set_terms($terms_string, $prefix, $course_code, $tool_id, $ref_id_high_level, $ref_id_second_level, $search_did) { $terms_string = trim($terms_string); $terms = explode(',', $terms_string); array_walk($terms, 'trim_value'); $stored_terms = $this->get_terms_on_db($prefix, $course_code, $tool_id, $ref_id_high_level); // don't do anything if no change, verify only at DB, not the search engine if (count(array_diff($terms, $stored_terms)) == 0 && count(array_diff($stored_terms, $terms)) == 0) { return FALSE; } require_once api_get_path(LIBRARY_PATH) . 'search/xapian/XapianQuery.php'; // compare terms $doc = $this->get_document($search_did); $xapian_terms = xapian_get_doc_terms($doc, $prefix); $xterms = array(); foreach ($xapian_terms as $xapian_term) { $xterms[] = substr($xapian_term['name'], 1); } $dterms = $terms; $missing_terms = array_diff($dterms, $xterms); $deprecated_terms = array_diff($xterms, $dterms); // save it to search engine foreach ($missing_terms as $term) { $this->add_term_to_doc($prefix . $term, $doc); } foreach ($deprecated_terms as $term) { $this->remove_term_from_doc($prefix . $term, $doc); } // don't do anything if no change if (count($missing_terms) > 0 || count($deprecated_terms) > 0) { $this->replace_document($doc, (int) $search_did); } return TRUE; }
/** * Set index specified prefix terms for all items in this path * @param string Comma-separated list of terms * @param char Xapian term prefix * @return boolean False on error, true otherwise */ function set_terms_by_prefix($terms_string, $prefix) { if (api_get_setting('search_enabled') !== 'true') { return FALSE; } $terms_string = trim($terms_string); $terms = explode(',', $terms_string); array_walk($terms, 'trim_value'); $stored_terms = $this->get_common_index_terms_by_prefix($prefix); //var_dump($stored_terms); //var_dump($terms); // don't do anything if no change, verify only at DB, not the search engine if (count(array_diff($terms, $stored_terms)) == 0 && count(array_diff($stored_terms, $terms)) == 0) { return FALSE; } require_once 'xapian.php'; //TODO try catch every xapian use or make wrappers on api require_once api_get_path(LIBRARY_PATH) . 'search/DokeosIndexer.class.php'; require_once api_get_path(LIBRARY_PATH) . 'search/xapian/XapianQuery.php'; require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php'; $items_table = Database::get_course_table(TABLE_LP_ITEM); //TODO: make query secure agains XSS : use member attr instead of post var $lp_id = intval($_POST['lp_id']); $sql = "SELECT * FROM {$items_table} WHERE lp_id = {$lp_id}"; $result = Database::query($sql); $di = new DokeosIndexer(); while ($lp_item = Database::fetch_array($result)) { // get search_did $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s AND ref_id_second_level=%d LIMIT 1'; $sql = sprintf($sql, $tbl_se_ref, $this->cc, TOOL_LEARNPATH, $lp_id, $lp_item['id']); $res = Database::query($sql, __FILE__, __LINE__); if (Database::num_rows($res) > 0) { $se_ref = Database::fetch_array($res); // compare terms $doc = $di->get_document($se_ref['search_did']); $xapian_terms = xapian_get_doc_terms($doc, $prefix); //var_dump($xapian_terms); $xterms = array(); foreach ($xapian_terms as $xapian_term) { $xterms[] = substr($xapian_term['name'], 1); } $dterms = $terms; //var_dump($xterms); //var_dump($dterms); $missing_terms = array_diff($dterms, $xterms); $deprecated_terms = array_diff($xterms, $dterms); // save it to search engine foreach ($missing_terms as $term) { $doc->add_term($prefix . $term, 1); } foreach ($deprecated_terms as $term) { $doc->remove_term($prefix . $term); } $di->getDb()->replace_document((int) $se_ref['search_did'], $doc); $di->getDb()->flush(); } } return true; }
/** * Set index specified prefix terms for all items in this path * @param string Comma-separated list of terms * @param char Xapian term prefix * @return boolean False on error, true otherwise */ public function set_terms_by_prefix($terms_string, $prefix) { $em = Database::getManager(); $course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id()); if (api_get_setting('search.search_enabled') !== 'true') { return false; } if (!extension_loaded('xapian')) { return false; } $terms_string = trim($terms_string); $terms = explode(',', $terms_string); array_walk($terms, 'trim_value'); $stored_terms = $this->get_common_index_terms_by_prefix($prefix); // Don't do anything if no change, verify only at DB, not the search engine. if (count(array_diff($terms, $stored_terms)) == 0 && count(array_diff($stored_terms, $terms)) == 0) { return false; } require_once 'xapian.php'; // TODO: Try catch every xapian use or make wrappers on API. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php'; require_once api_get_path(LIBRARY_PATH) . 'search/xapian/XapianQuery.php'; require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php'; $items_table = Database::get_course_table(TABLE_LP_ITEM); // TODO: Make query secure agains XSS : use member attr instead of post var. $lp_id = intval($_POST['lp_id']); $sql = "SELECT * FROM {$items_table} WHERE c_id = {$course->getId()} AND lp_id = {$lp_id}"; $result = Database::query($sql); $di = new ChamiloIndexer(); while ($lp_item = Database::fetch_array($result)) { $lpCourse = $em->getRepository('ChamiloCoreBundle:Course')->findOneBy(['code' => $this->cc]); // Get search_did. $se_ref = $em->getRepository('ChamiloCoreBundle:SearchEngineRef')->findOneBy(['course' => $lpCourse, 'toolId' => TOOL_LEARNPATH, 'refIdHighLevel' => $lp_id, 'refIdSecondLevel' => $lp_item['id']]); if ($se_ref) { // Compare terms. $doc = $di->get_document($se_ref->getSearchDid()); $xapian_terms = xapian_get_doc_terms($doc, $prefix); $xterms = array(); foreach ($xapian_terms as $xapian_term) { $xterms[] = substr($xapian_term['name'], 1); } $dterms = $terms; $missing_terms = array_diff($dterms, $xterms); $deprecated_terms = array_diff($xterms, $dterms); // Save it to search engine. foreach ($missing_terms as $term) { $doc->add_term($prefix . $term, 1); } foreach ($deprecated_terms as $term) { $doc->remove_term($prefix . $term); } $di->getDb()->replace_document($se_ref->getSearchDid(), $doc); $di->getDb()->flush(); } else { //@todo What we should do here? } } return true; }
/** * Queries the database. * The xapian_query function queries the database using both a query string * and application-defined terms. Based on drupal-xapian * * @param string $query_string The search string. This string will * be parsed and stemmed automatically. * @param XapianDatabase $db Xapian database to connect * @param int $start An integer defining the first * document to return * @param int $length The number of results to return. * @param array $extra An array containing arrays of * extra terms to search for. * @param int $count_type Number of items to retrieve * @return array An array of nids corresponding to the results. */ function xapian_query($query_string, $db = NULL, $start = 0, $length = 10, $extra = array(), $count_type = 0) { try { if (!is_object($db)) { $db = new XapianDatabase(XAPIAN_DB); } // Build subqueries from $extra array. Now only used by tags search filter on search widget $subqueries = array(); foreach ($extra as $subquery) { if (!empty($subquery)) { $subqueries[] = new XapianQuery($subquery); } } $query = NULL; $enquire = new XapianEnquire($db); if (!empty($query_string)) { $query_parser = new XapianQueryParser(); //TODO: choose stemmer $stemmer = new XapianStem("english"); $query_parser->set_stemmer($stemmer); $query_parser->set_database($db); $query_parser->set_stemming_strategy(XapianQueryParser::STEM_SOME); $query_parser->add_boolean_prefix('courseid', XAPIAN_PREFIX_COURSEID); $query_parser->add_boolean_prefix('toolid', XAPIAN_PREFIX_TOOLID); $query = $query_parser->parse_query($query_string); $final_array = array_merge($subqueries, array($query)); $query = new XapianQuery(XapianQuery::OP_AND, $final_array); } else { $query = new XapianQuery(XapianQuery::OP_OR, $subqueries); } $enquire->set_query($query); $matches = $enquire->get_mset((int) $start, (int) $length); $specific_fields = get_specific_field_list(); $results = array(); $i = $matches->begin(); // Display the results. //echo $matches->get_matches_estimated().'results found'; $count = 0; while (!$i->equals($matches->end())) { $count++; $document = $i->get_document(); if (is_object($document)) { // process one item terms $courseid_terms = xapian_get_doc_terms($document, XAPIAN_PREFIX_COURSEID); $results[$count]['courseid'] = substr($courseid_terms[0]['name'], 1); $toolid_terms = xapian_get_doc_terms($document, XAPIAN_PREFIX_TOOLID); $results[$count]['toolid'] = substr($toolid_terms[0]['name'], 1); // process each specific field prefix foreach ($specific_fields as $specific_field) { $results[$count]['sf-' . $specific_field['code']] = xapian_get_doc_terms($document, $specific_field['code']); } // rest of data $results[$count]['xapian_data'] = unserialize($document->get_data()); $results[$count]['score'] = $i->get_percent(); } $i->next(); } switch ($count_type) { case 1: // Lower bound $count = $matches->get_matches_lower_bound(); break; case 2: // Upper bound $count = $matches->get_matches_upper_bound(); break; case 0: // Best estimate // Best estimate default: $count = $matches->get_matches_estimated(); break; } return array($count, $results); } catch (Exception $e) { display_xapian_error($e->getMessage()); return NULL; } }
/** * Set index specified prefix terms for all items in this path * @param string Comma-separated list of terms * @param char Xapian term prefix * @return boolean False on error, true otherwise */ public function set_terms_by_prefix($terms_string, $prefix) { $course_id = api_get_course_int_id(); if (api_get_setting('search_enabled') !== 'true') return false; if (!extension_loaded('xapian')) { return false; } $terms_string = trim($terms_string); $terms = explode(',', $terms_string); array_walk($terms, 'trim_value'); $stored_terms = $this->get_common_index_terms_by_prefix($prefix); // Don't do anything if no change, verify only at DB, not the search engine. if ((count(array_diff($terms, $stored_terms)) == 0) && (count(array_diff($stored_terms, $terms)) == 0)) return false; require_once 'xapian.php'; // TODO: Try catch every xapian use or make wrappers on API. require_once api_get_path(LIBRARY_PATH).'search/ChamiloIndexer.class.php'; require_once api_get_path(LIBRARY_PATH).'search/xapian/XapianQuery.php'; require_once api_get_path(LIBRARY_PATH).'search/IndexableChunk.class.php'; $items_table = Database :: get_course_table(TABLE_LP_ITEM); // TODO: Make query secure agains XSS : use member attr instead of post var. $lp_id = intval($_POST['lp_id']); $sql = "SELECT * FROM $items_table WHERE c_id = $course_id AND lp_id = $lp_id"; $result = Database::query($sql); $di = new ChamiloIndexer(); while ($lp_item = Database :: fetch_array($result)) { // Get search_did. $tbl_se_ref = Database :: get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s AND ref_id_second_level=%d LIMIT 1'; $sql = sprintf($sql, $tbl_se_ref, $this->cc, TOOL_LEARNPATH, $lp_id, $lp_item['id']); //echo $sql; echo '<br>'; $res = Database::query($sql); if (Database::num_rows($res) > 0) { $se_ref = Database :: fetch_array($res); // Compare terms. $doc = $di->get_document($se_ref['search_did']); $xapian_terms = xapian_get_doc_terms($doc, $prefix); $xterms = array(); foreach ($xapian_terms as $xapian_term) { $xterms[] = substr($xapian_term['name'], 1); } $dterms = $terms; $missing_terms = array_diff($dterms, $xterms); $deprecated_terms = array_diff($xterms, $dterms); // Save it to search engine. foreach ($missing_terms as $term) { $doc->add_term($prefix . $term, 1); } foreach ($deprecated_terms as $term) { $doc->remove_term($prefix . $term); } $di->getDb()->replace_document((int) $se_ref['search_did'], $doc); $di->getDb()->flush(); } else { //@todo What we should do here? } } return true; }