Beispiel #1
0
 /**
  * Запланировать запуск переиндексирования области или правила в указанное время
  * @param string $area_string
  * @param integer $timestamp
  */
 public static function schedule_indexing($area_string, $timestamp)
 {
     // Если данная область уже поставлена в очередь на более раннее или ближайшее
     // время, не нужно добавлять ещё раз
     $interval = $timestamp + nc_search::get_setting('MinScheduleInterval');
     $intent = nc_search::load('nc_search_scheduler_intent', "SELECT * FROM `%t%`" . " WHERE `StartTime` <= {$interval}" . "   AND `AreaString` = '" . nc_search_util::db_escape($area_string) . "'")->first();
     // type is ignored
     if ($intent) {
         // уже есть такое расписание!
         if ($intent->get('start_time') > $timestamp) {
             $intent->set('start_time', $timestamp);
             // let's run it sooner
         }
     } else {
         $intent = new nc_search_scheduler_intent(array('start_time' => $timestamp, 'type' => nc_search_scheduler_intent::ON_REQUEST, 'area_string' => $area_string));
     }
     $intent->save();
 }
Beispiel #2
0
 /**
  * @param array $terms
  * @return array
  */
 public function filter(array $terms)
 {
     if (!nc_search::should('RemoveStopwords')) {
         return $terms;
     }
     $language = $this->context->get('language');
     if (!isset(self::$lists[$language])) {
         $query = "SELECT * FROM `%t%` WHERE `Language`='" . nc_search_util::db_escape($language) . "'";
         self::$lists[$language] = nc_search::load('nc_search_language_stopword', $query, 'word');
     }
     $stop_list = self::$lists[$language];
     if (!count($stop_list)) {
         return $terms;
     }
     $result = array();
     foreach ($terms as $term) {
         if (is_array($term)) {
             // alternative forms
             foreach ($term as $i => $t) {
                 if ($stop_list->has_key($t)) {
                     unset($term[$i]);
                 }
             }
             $terms_left = count($term);
             if ($terms_left == 1) {
                 $result[] = $term[0];
             } elseif ($terms_left > 1) {
                 $result[] = $term;
             }
         } elseif (!$stop_list->has_key($term)) {
             // ordinary term
             $result[] = $term;
         }
     }
     return $result;
 }
Beispiel #3
0
 /**
  * Обработать следующую ссылку из очереди
  * @return integer 
  *   nc_search_indexer::TASK_STEP_SKIPPED (ничего не сделано),
  *   nc_search_indexer::TASK_STEP_FINISHED (сделан и обработан запрос),
  *   nc_search_indexer::TASK_FINISHED (задача завершена)
  */
 public function next()
 {
     $link = $this->task->get_next_link();
     if (!$link) {
         return $this->finalize();
     }
     // ССЫЛОК БОЛЬШЕ НЕТ
     $done_something = true;
     // флажок, означающий, что после выполнения задачи, возможно,
     // следует сделать паузу (в соответствии с настройками)
     $url = $link->get('url');
     $is_disallowed = $this->task->is_url_disallowed($url);
     if (!$is_disallowed && $this->get_area()->includes($url)) {
         $response = $this->crawler->get($url);
     } elseif (!$is_disallowed && nc_search::should("CrawlerCheckLinks") && ($this->is_internal_link($url) || nc_search::should("CrawlerCheckOutsideLinks"))) {
         // так нам её проверить, да?
         $response = $this->crawler->head($url);
     } else {
         $response = false;
         $done_something = false;
     }
     if ($response) {
         $code = $response->get_code();
         // 0, если ничего не получено (напр., не резолвится домен)
         $max_doc_size = nc_search::get_setting("CrawlerMaxDocumentSize");
         if (!$code || $code == 400 || $code >= 402) {
             // их разыскивает пилиция  (401==Authorization required)
             $link->set('is_broken', true);
             $this->task->increment('total_not_found');
         } elseif ($response->has_body() && (!$max_doc_size || $response->get_body_length() <= $max_doc_size)) {
             // есть ответ и он не слишком длинный для нас
             $this->process_response($response, $link);
             $this->task->increment('total_processed');
         } else {
             $this->task->increment('total_checked');
         }
     }
     $link->set('is_processed', true);
     if ($link->get_id()) {
         // save the link status (broken, processed)
         $link->save();
         // set ToDelete for the broken links from this page
         try {
             $this->query_db("UPDATE `Search_BrokenLink`\n                                    SET `ToDelete` = 1\n                                  WHERE `Referrer_URL` = '" . nc_search_util::db_escape($link->get('url')) . "'");
         } catch (Exception $e) {
             trigger_error($e->getMessage(), E_USER_WARNING);
         }
     }
     return $done_something ? self::TASK_STEP_FINISHED : self::TASK_STEP_SKIPPED;
 }
Beispiel #4
0
 /**
  * Сохраняет поле индекса в указанной таблице (Search_Index или Search_Index_FieldX),
  * при необходимости разбивает запрос на части таким образом, чтобы запрос
  * был не более mysql.max_allowed_packet
  * @param string $table_name
  * @param int $doc_id
  * @param string $all_content
  * @param string $all_raw_data
  */
 protected function store_index_data($table_name, $doc_id, $all_content, $all_raw_data = '')
 {
     $db = $this->get_db();
     $overhead = 1024;
     // команды SQL etc.
     $chunk_size = $this->max_allowed_packet - $overhead;
     $content_chunks = str_split($all_content, $chunk_size);
     $raw_chunks = strlen($all_raw_data) ? str_split($all_raw_data, $chunk_size) : array();
     $doc_id = (int) $doc_id;
     unset($all_content, $all_raw_data);
     $n_content = $n_raw = 0;
     while (count($content_chunks) || count($raw_chunks)) {
         $update = $n_content || $n_raw;
         $query = ($update ? "UPDATE" : "REPLACE INTO") . " `{$table_name}` SET `Document_ID` = {$doc_id}";
         $content = array_shift($content_chunks);
         if (strlen($content)) {
             $content = nc_search_util::db_escape($content);
             $query .= ", `Content` = " . ($n_content ? "CONCAT(`Content`, '{$content}')" : "'{$content}'");
             $n_content++;
         }
         $add_raw = count($content_chunks) == 0 && isset($raw_chunks[0]) && strlen($content) + strlen($raw_chunks[0]) < $chunk_size;
         // adding raw_data will not cause overflow
         if ($add_raw) {
             $raw_data = nc_search_util::db_escape(array_shift($raw_chunks));
             $query .= ", `RawData` = " . ($n_raw ? "CONCAT(`RawData`, '{$raw_data}')" : "'{$raw_data}'");
             $n_raw++;
         }
         if ($update) {
             $query .= " WHERE `Document_ID` = {$doc_id}";
         }
         $db->query($query);
     }
 }
Beispiel #5
0
 /**
  * @param $table
  * @param $fts_qry
  * @return string
  */
 protected function make_match($table, $fts_qry)
 {
     return "MATCH(`{$table}`.`Content`) AGAINST ('" . nc_search_util::db_escape($fts_qry) . "' IN BOOLEAN MODE)";
 }
Beispiel #6
0
 /**
  * @param $value
  * @return int|string
  */
 protected function escape_number($value)
 {
     if (!is_numeric($value)) {
         $value = "'" . nc_search_util::db_escape($value) . "'";
     }
     return $value;
 }
Beispiel #7
0
        clear_link.click(function() { inp.val(''); clear_link.css('visibility', 'hidden'); });
        update();
    })($nc);
</script>

<?php 
// составляем и выполняем запрос к БД
$order_by = "`QueryCount` DESC";
if ($sort_by == 'time') {
    $order_by = "`Timestamp` DESC";
} elseif ($sort_by == 'query') {
    $order_by = "`QueryString` ASC";
}
$where = array(1);
if (strlen($this->get_input('fragment'))) {
    $where[] = "`QueryString` LIKE '%" . nc_search_util::db_escape($this->get_input('fragment')) . "%'";
}
// если установлен день или час, считать, что речь идёт о текущем дне/месяце/годе
$from_today = $this->get_input('datetime_from_d') || $this->get_input('datetime_from_H');
$timestamp_from = call_user_func_array('mktime', array((int) $this->get_input('datetime_from_H', 0), (int) $this->get_input('datetime_from_M', 0), 0, (int) $this->get_input('datetime_from_m', $from_today ? date("m") : 1), (int) $this->get_input('datetime_from_d', $from_today ? date("d") : 1), (int) $this->get_input('datetime_from_Y', $from_today ? date("Y") : 2000)));
// если установлен день или час, считать, что речь идёт о текущем дне/месяце/годе
$to_today = $this->get_input('datetime_to_d') || $this->get_input('datetime_to_H');
$timestamp_to = call_user_func_array('mktime', array((int) $this->get_input('datetime_to_H', 23), (int) $this->get_input('datetime_to_M', 59), 59, (int) $this->get_input('datetime_to_m', $to_today ? date("m") : 12), (int) $this->get_input('datetime_to_d', $to_today ? date("d") : 31), (int) $this->get_input('datetime_to_Y', $to_today ? date("Y") : 2037)));
$sql_datetime_from = nc_search_util::sql_datetime($timestamp_from);
$sql_datetime_to = nc_search_util::sql_datetime($timestamp_to);
if ($sql_datetime_from != '2000-01-01 00:00:00' || $sql_datetime_to != '2037-12-31 23:59:59') {
    $where[] = "`Timestamp` BETWEEN '{$sql_datetime_from}' AND '{$sql_datetime_to}'";
}
if ($results == 'none') {
    $where[] = '`ResultsCount` = 0';
} elseif ($results == 'matched') {
Beispiel #8
0
 /**
  * @param string $input
  * @param string $language
  * @param integer $site_id
  * @return array
  */
 public function suggest_titles($input, $language, $site_id)
 {
     $suggestions = array();
     // собственно подсказки
     $titles = array();
     $limit = nc_search::get_setting('NumberOfSuggestions');
     // поиск в индексе (то есть будут варианты после обработки фильтрами - базовая форма)
     if (nc_search::should('SearchTitleBaseformsForSuggestions')) {
         $last_space = strrpos($input, " ");
         $as_phrase = nc_search::should('SearchTitleAsPhraseForSuggestions');
         $b1 = $as_phrase ? '"' : '(';
         $b2 = $as_phrase ? '"' : ')';
         /* @todo сделать проверку на то, что последнее слово является правильным/полным? */
         $query_string = "(title:{$b1}{$input}{$b2}" . ($last_space ? " OR title:{$b1}" . trim(substr($input, 0, $last_space)) . $b2 : '') . ") AND site_id:{$site_id}";
         $query = new nc_search_query($query_string);
         $query->set('limit', $limit)->set('options_to_fetch', array('title', 'site_id', 'path'))->set('language', $language);
         $documents = $this->find($query, false);
         foreach ($documents as $doc) {
             $suggestions[] = array("label" => $doc->get('title'), "url" => $doc->get('url'));
             $titles[] = '"' . nc_search_util::db_escape($doc->get('title')) . '"';
         }
         $titles = array_unique($titles);
     }
     // поиск точного соответствия в таблице с документами
     // по-хорошему следовало бы сначала сделать запрос к БД, а потом к индексу, однако
     // в случае запроса к индексу не получится так же просто отфильтровать уже совпавшие запросы
     $query = "SELECT `Catalogue_ID`, `Path`, `Title` FROM `%t%` " . ' WHERE `Title` LIKE "' . nc_search_util::db_escape($input) . '%" ' . ($titles ? " AND `Title` NOT IN (" . join(", ", $titles) . ") " : "") . " ORDER BY `Title` " . " LIMIT {$limit}";
     $documents = new nc_search_result();
     $documents->select_from_database($query);
     foreach ($documents as $doc) {
         array_unshift($suggestions, array("label" => $doc->get('title'), "url" => $doc->get('url')));
     }
     $suggestions = array_slice($suggestions, 0, $limit);
     return $suggestions;
 }
Beispiel #9
0
<?php

if (!class_exists("nc_system")) {
    die;
}
$this->get_ui()->add_lists_toolbar();
$query_string = $this->get_input('query');
if (!strlen($query_string)) {
    $this->redirect("?view=queries");
}
$per_page = 100;
$offset = (int) $this->get_input('offset');
$query = "SELECT SQL_CALC_FOUND_ROWS q.*, u.Login\n            FROM Search_Query AS q \n                 LEFT JOIN User AS u ON (q.User_ID = u.User_ID)\n           WHERE q.QueryString='" . nc_search_util::db_escape($query_string) . "'\n           ORDER BY Timestamp DESC\n           LIMIT {$per_page} OFFSET {$offset}";
$db = $this->get_db();
$db->query("SET NAMES utf8");
$res = $db->get_results($query, ARRAY_A);
$found_rows = $db->get_var("SELECT FOUND_ROWS()");
$db->query("SET NAMES " . nc_core('MYSQL_CHARSET'));
// this is actually incorrect:
echo "<div class='query_details_header'>", "<b>", sprintf(NETCAT_MODULE_SEARCH_ADMIN_QUERY_ALL_QUERIES, nc_search_util::convert($query_string)), "</b> (", NETCAT_MODULE_SEARCH_ADMIN_QUERY_OPEN_RESULTS_HINT, "):", "</div>";
// таблица с результатами
echo "<table class='nc-table nc--large nc--hovered nc--striped list'>\n", "<tr>", "<th class='nc-text-center'>", NETCAT_MODULE_SEARCH_ADMIN_QUERY_TIME, "</th>", "<th class='nc-text-center' width='40%'>", NETCAT_MODULE_SEARCH_ADMIN_QUERY_AREA, "</th>", "<th class='nc-text-center'>", NETCAT_MODULE_SEARCH_ADMIN_QUERY_RESULTS_COUNT, "</th>", "<th class='nc-text-center'>", NETCAT_MODULE_SEARCH_ADMIN_QUERY_USER, "</th>", "<th class='nc-text-center'>", NETCAT_MODULE_SEARCH_ADMIN_QUERY_IP, "</th>", "</tr>\n";
foreach ($res as $row) {
    $has_area = strlen($row['Area']) > 0;
    $site_area = new nc_search_area("site{$row['Catalogue_ID']}");
    list($site_description) = $site_area->get_description(false);
    if (!$has_area) {
        $area_cell = "<td>" . NETCAT_MODULE_SEARCH_ADMIN_RULE_AREA_DESCRIPTION_ALLSITES . "</td>";
    } else {
        $area = new nc_search_area($row['Area'], $row['Catalogue_ID']);
        $description = array("included" => $area->get_description(false), "excluded" => $area->get_description(true));
Beispiel #10
0
 protected function load_synonyms($language)
 {
     $query = "SELECT * FROM `%t%` WHERE `Language`='" . nc_search_util::db_escape($language) . "'";
     self::$lists[$language] = nc_search::load('nc_search_language_synonyms', $query);
 }
Beispiel #11
0
 /**
  * Получение кодов для массива терминов вынесено в отдельный метод для
  * удобства рекурсивного вызова, которое необходимо при обработке альтернативных
  * форм слов (когда значение в массиве $terms является массивом)
  * @param array $terms
  * @param boolean $create_new
  * @return array
  */
 protected function get_term_codes(array $terms, $create_new)
 {
     $codes = array();
     foreach ($terms as $t) {
         // skip empty terms (think nc_search_language_filter_stopwords)
         if ($t === null || is_scalar($t) && strlen($t) == 0 || is_array($t) && sizeof($t) == 0) {
             continue;
         }
         if (is_array($t)) {
             // "alternative forms"
             $res = join("|", $this->get_term_codes($t, $create_new));
             if ($res) {
                 $codes[] = $res;
             }
         } else {
             if (isset($this->terms[$t])) {
                 // this is a known term
                 $codes[] = $this->terms[$t];
             } else {
                 if ($create_new) {
                     // should create new records in Search_Index_Term
                     $new_code = $this->get_next_code();
                     $this->terms[$t] = $codes[] = $new_code;
                     $this->new_term_data[] = "('" . nc_search_util::db_escape($t) . "', '{$new_code}', " . mb_strlen($t, 'UTF-8') . ")";
                 }
             }
         }
         // else (i.e. $create_new == false and term is unknown): do not add entry to the $codes
     }
     return $codes;
 }
Beispiel #12
0
 /**
  * Получить документ из БД по URL (только поля 'id' и 'hash')
  * @static
  * @param $site_id
  * @param $path
  * @return self|FALSE
  */
 public static function get_hash_by_path($site_id, $path)
 {
     $doc = new self();
     return $doc->select_from_database("SELECT `Document_ID`, `Hash`\n                                        FROM `{$doc->get_table_name()}`\n                                       WHERE `Catalogue_ID` = " . (int) $site_id . "\n                                         AND `Path` = '" . nc_search_util::db_escape($path) . "'\n                                       LIMIT 1");
 }
Beispiel #13
0
 /**
  * @param $url
  * @return string
  */
 protected function make_hash_statement($url)
 {
     $unhex = nc_search_util::can_use_binary_columns() ? "UNHEX" : "";
     return "{$unhex}(SHA1('" . nc_search_util::db_escape($url) . "'))";
 }
Beispiel #14
0
<?php

/**
 * Входящие параметры:
 *  - term
 * 
 * @global $catalogue
 */
$NETCAT_FOLDER = realpath("../../../../");
require_once "{$NETCAT_FOLDER}/vars.inc.php";
require $INCLUDE_FOLDER . "index.php";
// получение параметров
$input = trim($nc_core->input->fetch_get('term'));
if (!nc_search::should('EnableQuerySuggest') || nc_search::get_setting('SuggestMode') != 'queries' || mb_strlen($input) < nc_search::get_setting('SuggestionsMinInputLength')) {
    die("[]");
}
$input = $nc_core->utf8->conv($nc_core->NC_CHARSET, 'utf-8', $input);
// поиск запросов, начинающихся с указанной подстроки
$db->query("SET NAMES 'utf8'");
$query = "SELECT DISTINCT(`QueryString`) AS `label` FROM `Search_Query` \n           WHERE `QueryString` LIKE '" . nc_search_util::db_escape($input) . "%'\n             AND `ResultsCount` > 0\n           ORDER BY `QueryString`\n           LIMIT " . (int) nc_search::get_setting('NumberOfSuggestions');
$suggestions = (array) $db->get_results($query, ARRAY_A);
if (!$nc_core->NC_UNICODE) {
    $suggestions = $nc_core->utf8->array_utf2win($suggestions);
}
print nc_array_json($suggestions);
Beispiel #15
0
 /**
  *
  */
 protected function get_path_sql_condition($operator = '=', $template = '')
 {
     $site_cond = array();
     foreach ($this->get_sites() as $site) {
         $site_cond[] = $site->get_sql_condition();
     }
     $q = $site_cond ? "(" . join(" OR ", $site_cond) . ")" : "1";
     $q .= " AND `{$this->document_table_name}`.`Path` {$operator} '" . nc_search_util::db_escape($this->get_path()) . $template . "'";
     return $q;
 }