7 require_once(
'base/Ego_Search.php');
8 require_once(
'composer/vendor/autoload.php');
30 private $officeImport =
false;
44 private $throwException =
false;
58 public function __construct($table =
'', $param = [],
bool $checkHealthy =
false) {
59 $this->throwException = $GLOBALS[
'egotec_conf'][
'elastic'][
'throw_exception'] || $param[
'throw_exception'];
62 throw new Exception(
"missing licence");
67 if ($GLOBALS[
'egotec_conf'][
'elastic'][
'maxclause']) {
68 $this->maxClauseCount = (int) $GLOBALS[
'egotec_conf'][
'elastic'][
'maxclause'];
73 'leading_wildcard' => true
77 $table = $GLOBALS[
'site']->pageTable;
80 if (!$GLOBALS[
'egotec_conf'][
'elastic'][
'max_results']) {
81 $GLOBALS[
'egotec_conf'][
'elastic'][
'max_results'] = 10000;
89 for ($i = 0; $i < 4; $i++) {
90 if ($GLOBALS[
'egotec_conf'][
'elastic'][
'host' . $i]) {
91 $hosts[] = trim($GLOBALS[
'egotec_conf'][
'elastic'][
'host' . $i],
'/');
96 throw new Exception(
"missing hosts for elastic");
99 $this->client = Elasticsearch\ClientBuilder::create()
100 ->setHandler(Elasticsearch\ClientBuilder::multiHandler())
104 $this->config[
'index'] = strtolower($table);
105 $this->config[
'table'] = $table;
106 $this->config[
'param'] = $param;
111 }
catch (Exception $e) {
119 $this->createPipeline();
129 public function delete($id) {
131 'index' => $this->config[
'index'],
135 $this->client->delete($params);
147 $GLOBALS[
'monitor'][
'search_reset']++;
153 }
catch (Exception $e) {
167 $GLOBALS[
'monitor'][
'search_reset_all']++;
182 'index' => $this->config[
'index']
185 if (!$this->client->indices()->exists($params)) {
186 $language = preg_match(
'/_([^_]{2})$/', $params[
'index'], $matches) ? $matches[1] :
'';
189 'br' =>
'_brazilian_',
190 'bg' =>
'_bulgarian_',
207 'hu' =>
'_hungarian_',
208 'id' =>
'_indonesian_',
212 'lt' =>
'_lithuanian_',
213 'no' =>
'_norwegian_',
214 'pt' =>
'_portuguese_',
215 'ro' =>
'_romanian_',
228 $sortable_fields =
function() {
236 'release_from' =>
'date',
237 'release_until' =>
'date',
238 'order_field' =>
'long',
239 'structure' =>
'nested',
240 'main_category' =>
'long'
241 ] as $name => $type) {
242 $params = [
'type' => $type];
243 if ($name ==
'structure') {
244 $params[
'properties'] = [
263 $params[
'fields'] = [
269 if ($type ==
'date') {
270 $params[
'format'] =
'epoch_second';
272 $arr[$name] = $params;
277 'index' => $this->config[
'index'],
278 'include_type_name' =>
true,
281 'number_of_shards' => $GLOBALS[
'egotec_conf'][
'elastic'][
'number_of_shards'],
282 'number_of_replicas' => $GLOBALS[
'egotec_conf'][
'elastic'][
'number_of_replicas'] ?: 0,
283 'index.mapping.ignore_malformed' =>
true,
289 'tokenizer' =>
'standard',
290 'filter' => [
'lowercase',
'stop']
294 'tokenizer' =>
'standard',
295 'filter' => [
'lowercase',
'shingle']
301 'min_shingle_size' => 2,
302 'max_shingle_size' => 3
306 'ignore_case' =>
true,
307 'stopwords' => $stopwords[$language] ?? $stopwords[
'en']
314 'properties' => array_merge($sortable_fields(), [
316 'type' =>
'completion',
318 'name' =>
'ignore_search',
319 'type' =>
'category',
320 'path' =>
'ignore_search'
331 'analyzer' =>
'trigram'
342 $this->client->indices()->create($params);
343 }
catch (Exception $e) {
344 if (strpos($e->getMessage(),
'resource_already_exists_exception') ===
false) {
345 throw new Exception($e->getMessage(), $e->getCode());
359 return $this->client->indices()->exists([
360 'index' => $this->config[
'index']
373 'index' => $all ?
"_all" : $this->config[
'index'],
374 'client' => [
'ignore' => [400, 404]]
377 if ($this->client->indices()->exists($params)) {
378 $this->client->indices()->delete($params);
386 foreach ($pages as $page) {
387 $page = $this->indexFiles($page);
389 $params[
'body'][] = [
391 '_index' => $this->config[
'index'],
392 '_id' => $page->field[
'id']
396 $params[
'body'][] = $this->getBody($page);
400 foreach ($page->getChildren([], [
'auth_or' =>
'1=1']) as $child) {
401 $child->updateIndex($this,
true,
false);
406 $this->client->bulk($params);
407 }
catch (Exception $e) {
408 foreach ($pages as $page) {
409 Ego_Action::add(Ego_Action::PAGE_UPDATE_INDEX, [
410 'identity' => $page->getIdentity(),
411 'recursive' => $recursive
414 Ego_Action::throw($e);
427 public function update($index, $page, $count = [], $recursive =
true) {
429 $page = $this->indexFiles($page);
431 $GLOBALS[
'monitor'][
'search_update_count']++;
434 'index' => $this->config[
'index'],
436 'body' => $this->getBody($page),
437 'client' => [
'ignore' => 404]
440 $this->client->index($params);
441 }
catch (Exception $e) {
442 Ego_Action::add(Ego_Action::PAGE_UPDATE_INDEX, [
443 'identity' => $page->getIdentity(),
444 'recursive' => $recursive
450 foreach ($page->getChildren([], [
'auth_or' =>
'1=1']) as $child) {
451 $child->updateIndex($this,
true,
false);
463 private function getBody($page) {
466 $keywords = $this->_getContent($page,
'keywords');
467 $name = $this->_getContent($page,
'name');
468 $title = $this->_getContent($page,
'title');
469 $short = $this->_getContent($page,
'short');
470 $content = $this->_getContent($page,
'content');
473 $extra = $this->_getExtra($page);
474 unset($page->extra[
'_contents']);
475 $extra_values = $this->_getExtra($page,
true);
477 $suggestions = array_values(
483 preg_replace(
'/[^a-zA-Z0-9äöüÄÖÜß-]/',
'', $value),
493 [$keywords, $name, $title, $short, $content]
502 && strlen($value) > 2
503 && !preg_match(
'/^[a-z0-9]{32}$/i', $value)
516 $convert_date =
function($date) {
517 if (!$date || $date ==
'0000-00-00 00:00:00') {
520 return strtotime($date);
525 $db = new_db_connection([
526 'table' => $page->getSite()->pageTable .
'_children',
527 'where' =>
'child = :id',
529 'id' => $page->field[
'id']
532 while ($db->nextRecord()) {
534 'parent' => $db->Record[
'page_id'],
535 'position' => $db->Record[
'idx']
540 'id' => $page->field[
'id'],
541 'keywords' => $keywords,
542 'url' => $this->_getContent($page,
'url'),
546 'content' => $content,
547 'a_date' => $convert_date($page->field[
'a_date']),
548 'c_date' => $convert_date($page->field[
'c_date']),
549 'release_from' => $convert_date($page->field[
'release_from']),
550 'release_until' => $convert_date($page->field[
'release_until']),
552 'extra_values' => trim(
558 return implode(
' ', $value);
565 'type' => $page->field[
'type'],
566 'ignore_search' => (($page->field[
'nav_hide'] & 4) == 4) ?
'1' :
'0',
567 'inactive' => (int)$page->field[
'inactive'],
568 'deleted' => (
int)$page->field[
'deleted'],
569 'order_field' => (int)$page->field[
'order_field'],
570 'structure' => $structure,
571 'main_category' => (
int)$page->extra[
'main_category'],
573 'input' => $page->isActive() ? $suggestions : []
591 private function getSearchParam($tables, $search, $filter, $fuzzy, $id_list = [], $limit =
'', $order =
'', $where =
'') {
592 $fields = [
'keywords',
'url',
'name',
'title',
'short',
'content',
'extra_values'];
593 $indexes = $tables ? $tables : [$this->config[
'index']];
596 $rewrite =
'top_terms_' . $this->maxClauseCount;
599 $search = trim(mb_strtolower($search));
602 $search = trim(preg_replace([
611 if (empty($GLOBALS[
'elastic'][
'stop_words'])) {
612 $search_phrases = [];
613 $search_no_phrases = $search;
614 if (preg_match_all(
'/".*?"/', $search, $matches)) {
615 $search_phrases = $matches[0];
616 $search_no_phrases = trim(preg_replace([
'/".*?"/',
'/\s+/'], [
'',
' '], $search));
620 $language = $GLOBALS[
'site'] ? $GLOBALS[
'site']->language :
'de';
621 if (
Ego_System::file_exists($file = $GLOBALS[
'egotec_conf'][
'lib_dir'] .
'base/search/' . $language .
'.txt')) {
624 $search_no_phrases = implode(
' ', array_filter(explode(
' ', $search_no_phrases),
function($value) use ($stop_words) {
625 return !in_array($value, $stop_words);
627 $search = $search_no_phrases . (!empty($search_phrases) ?
' ' . implode(
' ', $search_phrases) :
'');
633 $search_no_phrases = trim(preg_replace([
'/".*?"/',
'/\s+/'], [
'',
' '], $search));
634 if (preg_match_all(
'/( |^)([^+-][^ "]+-[^ "]+)/is', $search_no_phrases, $matches)) {
635 foreach ($matches[2] as $word) {
636 $search .=
' ' . str_replace(
'-',
' ', $word);
642 if ($tables ===
null) {
644 [$name, $lang] = preg_split(
'/_(?=[^_]*$)/', $this->config[
'table']);
645 $site =
new Site($name, $lang);
646 $count = $site->getSearchCount();
657 if (preg_match_all(
'/(".*?"|[^ ]+)/is', $search, $matches)) {
659 $match_phrase =
sizeof($matches[0]) > 1 && !preg_match(
'/(^| )["*+-]/', $search);
661 foreach ($fields as $field) {
663 if ($field ==
'extra_values' && isset($count[
'extra'])) {
664 $boost = (int)$count[
'extra'];
665 } elseif (isset($count[$field])) {
666 $boost = (int)$count[$field];
670 $filtered_query = array_filter($matches[0],
function($s) {
671 return mb_strlen(trim($s,
'"+-*')) >= (isset($GLOBALS[
'egotec_conf'][
'elastic'][
'minlength'])
672 ? (int) $GLOBALS[
'egotec_conf'][
'elastic'][
'minlength']
676 foreach ($filtered_query as $query) {
678 if (!in_array($query[0], [
'"',
'-']) && strpos($query,
'-') !==
false) {
679 $query =
"\"$query\"";
682 if ($query[0] ==
'"') {
684 $query = trim($query,
'"');
700 'rewrite' => $rewrite,
705 } elseif (preg_match(
'/^(.*?)~([0-9.]+|)$/', $query, $match)) {
708 $fuzziness = floatval($match[2] !==
'' ? $match[2] : 1);
714 'rewrite' => $rewrite,
716 'fuzziness' => round(2 * $fuzziness)
722 $wildcard =
function ($query) {
723 if (strpos($query,
'*') ===
false) {
731 $query = ltrim($query,
'+');
732 $must_should[md5($query)][] = [
735 'value' => $wildcard($query),
736 'rewrite' => $rewrite,
743 $query = ltrim($query,
'-');
747 'value' => $wildcard($query),
748 'rewrite' => $rewrite,
758 'value' => $wildcard($query),
759 'rewrite' => $rewrite,
774 'query' => trim($search),
775 'boost' => $boost + 1
783 $minimum_should_match = $search ==
'' && (!empty($filter) || !empty($this->extraQuery)) ? 0 : 1;
785 if (
sizeof($must_should)) {
786 $minimum_should_match = 0;
788 foreach ($must_should as $items) {
792 'minimum_should_match' => 1
798 if ($this->config[
'param'][
'only_active']) {
805 if (!$this->config[
'param'][
'deleted'] && !$this->config[
'param'][
'deleted_or']) {
812 if ($this->config[
'param'][
'search']) {
815 'ignore_search' =>
'0'
821 if (!empty($id_list)) {
823 'constant_score' => [
834 if (!empty($this->extraQuery)) {
837 'query' => $this->extraQuery
843 if (!empty($filter)) {
866 $limit_parts = explode(
',', $limit);
868 if (count($limit_parts) > 1) {
869 $from = trim($limit_parts[0]);
870 $size = trim($limit_parts[1]);
873 $size = trim($limit_parts[0]);
877 $size = (int) $GLOBALS[
'egotec_conf'][
'elastic'][
'max_results'];
882 $score_sorted =
false;
885 foreach (explode(
',', $order) as $order_part) {
886 $parts = explode(
' ', trim($order_part), 2);
887 $key = trim($parts[0]);
890 if ($key ===
'score') {
891 $sort[] = [
'_score' => [
'order' => $parts[1]]];
892 $score_sorted =
true;
897 if (strpos($key,
'.') !==
false) {
898 foreach ($indexes as $index) {
899 if (strpos($key,
"{$index}.") === 0) {
900 $key = substr($key, strlen(
"{$index}."));
904 && $key ==
"{$index}_children.idx"
905 && preg_match(
'/' . $index .
'_children\.page_id\s*=\s*(\d+)/', $where, $match)
907 $key =
'structure.position';
908 $parent_id = $match[1];
915 if (!preg_match(
'/\.keyword$/i', $key)) {
921 if ($parent_id && strpos($key,
'structure.') === 0) {
922 $params[
'nested'] = [
923 'path' =>
'structure',
925 'term' => [
'structure.parent' => $parent_id]
931 $key => array_merge([
932 'order' => strtolower(trim($parts[1]))
939 if (!$score_sorted) {
940 $sort[] = [
'_score' => [
954 'track_scores' =>
true,
962 'must_not' => $must_not,
965 'minimum_should_match' => $minimum_should_match
975 private function createPipeline() {
976 if ($this->officeImport) {
978 'id' =>
'attachment',
980 'description' =>
'Extract attachment information',
985 'indexed_chars' => -1
992 $this->client->ingest()->putPipeline($params);
1009 @ini_set(
"memory_limit",
"-1");
1011 $pageTable = strtolower($page->
getSite()->pageTable);
1015 'index' => $pageTable,
1017 'pipeline' =>
'attachment',
1024 $result = $this->client->index($params);
1025 }
catch (Exception $e) {
1026 egotec_error_log(
'Elasticsearch: error while indexing file of ' . $page->
getIdentity() .
' (' . $e->getMessage() .
')');
1031 $content = $this->getIndexFile($pageTable, $identity);
1032 $this->
delete($identity);
1048 private function getIndexFile($pageTable, $identity) {
1050 'index' => strtolower($pageTable),
1054 $response = $this->client->get($params);
1055 return $response[
'_source'][
'attachment'][
'content'];
1065 private function indexFiles(
Page $page) {
1066 if (!$this->officeImport || $page->extra[
'quarantine']) {
1071 $page->field[
'type'] ==
'multimedia/file'
1072 && !$page->extra[
'_indexed']
1074 if (!preg_match(
'/(image|video|audio|zip|exe|rar|octet-stream|postscript)/is', $page->extra[
'mime_type'])) {
1075 $page->extra[
'_indexed'] =
true;
1077 $content = $this->indexFile($page, $GLOBALS[
'egotec_conf'][
'var_dir'] .
'media/' . $page->
getSite()->name .
'/' . $page->
getMediaFilename());
1079 }
catch (Exception $e) {
1082 strpos($e->getMessage(),
'EncryptedDocumentException') ===
false
1083 && strpos($e->getMessage(),
'TikaException') ===
false
1085 egotec_error_log(
'Elasticsearch: error while indexing file of ' . $page->
getIdentity() .
' (' . $e->getMessage() .
')');
1089 $page->
update([],
true,
true);
1107 public function search($search, $relation, $query, $filter =
'', $fuzzy =
false) {
1108 $this->checkSearch($search);
1110 $GLOBALS[
'monitor'][
'search_count']++;
1111 $GLOBALS[
'monitor'][
'search_length'] += mb_strlen($search);
1112 $GLOBALS[
'monitor'][
'search_words'] += substr_count($search,
' ') + 1;
1114 $params = $this->getSearchParam(
null, $search, $filter, $fuzzy, $query[
'id_list'], $query[
'limit'] ??
'', $query[
'order'] ??
'', $query[
'where'] ??
'');
1116 $start = microtime(
true);
1118 $results = $this->client->search($params);
1119 }
catch (Exception $e) {
1123 $hits = $results[
"hits"][
"hits"];
1124 $stop = microtime(
true);
1126 $duration = (int)(($stop - $start) * 1000);
1127 $GLOBALS[
'monitor'][
'search_duration'] += $duration;
1130 unset($query[
'order']);
1131 unset($query[
'limit']);
1132 unset($query[
'bind']);
1133 $query[
'where'] =
'1=0';
1139 foreach ($hits as $key => $value) {
1140 $ids[$value[
"_id"]] = $query[
'order'] ? count($hits) - $key : $value[
"_score"];
1143 if ($query[
'order']) {
1147 $max_value = $results[
"hits"][
"max_score"];
1148 $min_value = min(array_values($ids));
1149 if ($max_value == $min_value) {
1150 $multiply = 4 / $max_value;
1153 $multiply = 4 / ($max_value - $min_value);
1157 return $this->buildQuery($ids, $relation, $query, $min_value, $multiply);
1172 public function globalSearch($search, $sites = [], $query = [], $param = [], $sort = [], $filter =
'') {
1173 $this->checkSearch($search);
1175 $start1 = microtime(
true);
1176 $GLOBALS[
'monitor'][
'search_global_count']++;
1177 $GLOBALS[
'monitor'][
'search_global_length'] += mb_strlen($search);
1178 $GLOBALS[
'monitor'][
'search_global_words'] += substr_count($search,
' ') + 1;
1181 if (!isset($param[
'search']) && empty($GLOBALS[
'admin_area'])) {
1182 $param[
'search'] =
true;
1186 $lang = $_REQUEST[
'lang'] ? $_REQUEST[
'lang'] : ($GLOBALS[
'site'] ? $GLOBALS[
'site']->language :
null);
1188 if (empty($sites)) {
1192 $tables = $this->getTables($sites, $lang, $relations);
1195 $start2 = microtime(
true);
1196 $params = $this->getSearchParam($tables, $search, $filter, (
bool)$param[
'fuzzy']);
1198 $results = $this->client->search($params);
1199 }
catch (Exception $e) {
1202 $stop2 = microtime(
true);
1203 $duration = (int)(($stop2 - $start2) * 1000);
1204 $GLOBALS[
'monitor'][
'search_global_d2'] += $duration;
1206 $hits = $results[
"hits"][
"hits"];
1212 $min_value = PHP_INT_MAX;
1215 foreach ($hits as $key => $hit) {
1216 if (!isset($sorted_hits[$hit[
'_index']])) {
1217 $sorted_hits[$hit[
'_index']] = [];
1219 $sorted_hits[$hit[
'_index']][$hit[
'_id']] = $query[
'order'] ? count($hits) - $key : $hit[
'_score'];
1220 if ($hit[
'_score'] < $min_value) {
1221 $min_value = $hit[
'_score'];
1225 if ($query[
'order']) {
1229 $max_value = $results[
"hits"][
"max_score"];
1230 if ($max_value == $min_value) {
1231 $multiply = 4 / $max_value;
1234 $multiply = 4 / ($max_value - $min_value);
1240 foreach ($sorted_hits as $table => $ids) {
1241 $site = $relations[$table];
1242 foreach ($site->getPages($this->buildQuery($ids, $site->pageTable .
'.id', $query, $min_value, $multiply), $param) as $page) {
1246 $pages = $this->sortPages($pages, $query[
'order'], $sort);
1248 $stop1 = microtime(
true);
1249 $duration = (int)(($stop1 - $start1) * 1000);
1250 $GLOBALS[
'monitor'][
'search_global_d1'] += $duration;
1265 $tables = $this->config[
'index'];
1266 if (!empty($sites)) {
1267 $tables = $this->getTables($sites);
1270 $results = $this->client->search([
1274 'sort' => [
'_score'],
1280 'field' =>
'suggest',
1281 'skip_duplicates' =>
true,
1284 'ignore_search' => [
'0']
1291 }
catch (Exception $e) {
1296 if (is_array($results[
'suggest'][
'suggest'][0][
'options'])) {
1297 foreach ($results[
'suggest'][
'suggest'][0][
'options'] as $result) {
1298 if (mb_strtolower($query) != mb_strtolower($result[
'text'])) {
1299 if (preg_match(
'/^(.*?)_([^_]+)$/', $result[
'_index'], $match)) {
1302 $site =
new Site($match[1], $match[2]);
1303 $page = $site->getPage($result[
'_id']);
1305 if ($page && $page->
hasRights([
'view'])) {
1306 $suggestions[] = $result[
'text'];
1312 $suggestions[] = $result[
'text'];
1318 return $suggestions;
1331 $tables = $this->config[
'index'];
1332 if (!empty($sites)) {
1333 $tables = $this->getTables($sites);
1336 $results = $this->client->search([
1341 'simple_phrase' => [
1343 'field' =>
'title.trigram',
1346 'direct_generator' => [[
1347 'field' =>
'title.trigram',
1348 'suggest_mode' =>
'always'
1351 'pre_tag' =>
'<em>',
1352 'post_tag' =>
'</em>'
1359 }
catch (Exception $e) {
1364 if (is_array($results[
'suggest'][
'simple_phrase'][0][
'options']) && !empty($results[
'suggest'][
'simple_phrase'][0][
'options'])) {
1365 $corrections = $results[
'suggest'][
'simple_phrase'][0][
'options'];
1368 return $corrections;
1382 private function buildQuery($result, $relation, $query, $min_value, $multiply) {
1383 if (!empty($result)) {
1384 $ids = array_keys($result);
1385 if (empty($query[
'where'])) {
1386 $query[
'where'] =
'';
1388 $query[
'where'] .=
' AND ';
1393 foreach (array_chunk($ids, 999) as $id_group) {
1394 $id_groups[] =
"$relation IN (" . implode(
', ', $id_group) .
")";
1396 $query[
'where'] .=
'(' . implode(
' OR ', $id_groups) .
')';
1399 foreach ($result as $id => $value) {
1400 $field2 .=
"WHEN $relation = $id THEN " . (str_replace(
',',
'.', ($value - $min_value) * $multiply)) .
" ";
1402 $field2 .=
'ELSE 0 END AS score';
1403 $query[
'fields2'][] = $field2;
1404 $query[
'order'] =
'score DESC';
1406 unset($query[
'order']);
1407 unset($query[
'limit']);
1408 unset($query[
'bind']);
1409 $query[
'where'] =
'1=0';
1424 if (is_array($bind)) {
1426 $reserved_characters = preg_quote(
'+-&|!(){}[]^"~*?:\\');
1427 foreach ($bind as $key => $value) {
1428 $query = str_replace(
1430 preg_replace_callback(
1431 '/[' . $reserved_characters .
']/',
1432 function ($matches) {
1433 return '\\' . $matches[0];
1443 $Elastic_query = $query;
1444 $sub_queries = preg_split(
'/\s+(and|or)\s+/si', $query);
1445 foreach ($sub_queries as $sub_query) {
1446 if (preg_match(
'/(!?(extra\.)?[^ !=<>]+)(\s*(like|>=|<=|!=|=|>|<)\s*(.*?))?$/si', trim($sub_query,
'() '), $matches)) {
1447 $param = $matches[1];
1448 $operator = mb_strtolower($matches[4]);
1449 $value = trim($matches[5],
'\'"');
1451 // Feld darf nicht im Dokument gesetzt sein
1453 if ($param[0] == '!') {
1455 $param = substr($param, 1);
1460 $replace = "-$param:*
" . (sizeof($sub_queries) == 1 ? ' AND *' : '');
1462 // Elastic Syntax schreiben
1463 $replace = "$param:
";
1464 if (!is_numeric($value)) {
1465 if ($operator == 'like') {
1466 $value = $this->prepareSearch(str_replace('%', '', $value), '', true);
1468 $value = '"' . $value . '"';
1473 switch ($operator) {
1479 $replace = "($param:* NOT $param:$value)
";
1482 $replace .= '{' . $value . ' TO *}';
1485 $replace .= '[' . $value . ' TO *]';
1488 $replace .= '{* TO ' . $value . '}';
1491 $replace .= '[* TO ' . $value . ']';
1498 $Elastic_query = str_replace($matches[0], $replace, $Elastic_query);
1502 $this->extraQuery = $Elastic_query;
1510 public function getConfig() {
1511 return $this->config;
1519 public function clearCache() {
1520 foreach ($this->hosts as $host) {
1521 @file_get_contents($host . '_cache/clear');
1533 private function getTables($sites, $lang = '', &$relations = []) {
1536 $lang = $_REQUEST['lang'] ? $_REQUEST['lang'] : ($GLOBALS['site'] ? $GLOBALS['site']->language : null);
1538 foreach ($sites as $site) {
1540 if (is_string($site)) {
1541 $site = new Site($site);
1544 $site->setLanguage($lang);
1546 } catch (Exception $e) {
1547 // Mandant existiert nicht in dieser Sprache, ignorieren
1550 $table = strtolower($site->pageTable);
1551 $tables = $tables . ',' . $table;
1552 $relations[$table] = $site;
1554 return ltrim($tables, ',');
1564 private function error($e) {
1565 if ($this->throwException) {
1566 $class = get_class($e);
1567 throw new $class($e->getMessage(), $e->getCode());
1569 $response = @json_decode($e->getMessage(), true);
1571 if ($response['error']) {
1572 if ($response['error']['root_cause']) {
1573 foreach ($response['error']['root_cause'] as $cause) {
1574 $messages[] = $cause['type'] . ' for index ' . $cause['index'];
1577 if ($response['error']['failed_shards']) {
1578 foreach ($response['error']['failed_shards'] as $shard) {
1579 if (!empty($shard['reason']['caused_by'])) {
1580 $messages[] = 'caused by ' . $shard['reason']['caused_by']['type'] . ' (reason: ' . $shard['reason']['caused_by']['reason'] . ')';
1585 if (empty($messages)) {
1586 $messages[] = $e->getMessage();
1588 egotec_error_log('Elastic Exception thrown (' . get_class($e) . ', Code ' . $e->getCode() . '): ' . implode('; ', $messages));
1589 Ego_System::header($response['status'] ?? 400);
setExtraQuery($query, $bind=[])
getCorrections($query, $sites=[], $max=3)
indexFile(Page $page, $path)
getSuggestions($query, $sites=[], $max=5)
__construct($table='', $param=[], bool $checkHealthy=false)
updateBulk($pages, $recursive=true)
update($index, $page, $count=[], $recursive=true)
globalSearch($search, $sites=[], $query=[], $param=[], $sort=[], $filter='')
search($search, $relation, $query, $filter='', $fuzzy=false)
static filterNonUtf8($s, $substitute="", $strict=false)
static checkLicence($ini_path)
static getAllSites($username='', $perm='', $table=false, $type='')
static file_exists($file)
static file_get_contents($filename, $utf8=true, $context=null)
static stringEncode($string, $from='UTF-8', $to='UTF-8')
getMediaFilename($force_lang=false, $suffix="")
hasRights($rights, $user_id=false, $cache=true)
update($param=array(), $matrix_flag=true, $asis=false, $silent=false)