/**
  * 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;
 }
Example #2
0
 /**
  * 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;
    }