Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/search/tools/ |
Upload File : |
<?php IncludeModuleLangFile(__FILE__); class CSearchOpenSearch extends CSearchFullText { public $arForumTopics = []; private $errorText = ''; private $errorNumber = 0; public $tags = ''; public $SITE_ID = ''; public $connectionString = ''; protected $user = ''; protected $password = ''; public $indexName = ''; public $siteAnalyzerMap = []; public function connect($connectionString, $user = '', $password = '', $indexName = '', $ignoreErrors = false, $siteAnalyzerMap = '') { global $APPLICATION; if (!preg_match('/^[a-zA-Z0-9_-]+$/', $indexName)) { if ($ignoreErrors) { $APPLICATION->ThrowException(GetMessage('SEARCH_OPENSEARCH_CONN_ERROR_INDEX_NAME')); } else { throw new \Bitrix\Main\Db\ConnectionException('OpenSearch connect error', GetMessage('SEARCH_OPENSEARCH_CONN_ERROR_INDEX_NAME')); } return false; } $error = ''; $server = new Bitrix\Main\Web\HttpClient([ 'disableSslVerification' => true, ]); $server->setAuthorization($user, $password); $strJson = $server->get($connectionString); if ($server->getStatus() !== 200 || !is_array(json_decode($strJson, true))) { $error = $strJson; if ($ignoreErrors) { $APPLICATION->ThrowException(GetMessage('SEARCH_OPENSEARCH_CONN_ERROR', ['#ERRSTR#' => $error])); } else { throw new \Bitrix\Main\Db\ConnectionException('OpenSearch connect error', GetMessage('SEARCH_OPENSEARCH_CONN_ERROR', ['#ERRSTR#' => $error])); } return false; } $this->connectionString = $connectionString; $this->user = $user; $this->password = $password; $this->siteAnalyzerMap = $siteAnalyzerMap ?: []; if (!$this->siteAnalyzerMap) { $langs = CLang::GetList(); while ($site = $langs->Fetch()) { $analyzer = COption::GetOptionString('search', 'opensearch_analyzer_' . $site['ID']); if (!$analyzer) { $analyzer = array_search($site['LANGUAGE_ID'], static::getLanguageAnalyzers()) ?: 'english'; } $this->siteAnalyzerMap[$site['ID']] = $analyzer; } } if ($ignoreErrors) { foreach ($this->siteAnalyzerMap as $siteId => $analyzer) { if (!$this->checkIndexTemplate($indexName, $siteId, $analyzer)) { $APPLICATION->ThrowException(GetMessage('SEARCH_OPENSEARCH_CONN_ERROR', ['#ERRSTR#' => $this->getError()])); return false; } } } $this->indexName = $indexName; $this->connectionIndex = $connectionIndex; return true; } // https://opensearch.org/docs/latest/analyzers/supported-analyzers/index/ public static function getLanguageAnalyzers() { return [ 'arabic' => 'ar', 'armenian' => '', 'basque' => '', 'bengali' => '', 'brazilian' => 'br', 'bulgarian' => '', 'catalan' => '', 'czech' => '', 'danish' => '', 'dutch' => '', 'english' => 'en', 'estonian' => '', 'finnish' => '', 'french' => 'fr', 'galician' => '', 'german' => 'de', 'greek' => '', 'hindi' => '', 'hungarian' => '', 'indonesian' => 'ms', 'irish' => '', 'italian' => 'it', 'latvian' => '', 'lithuanian' => 'lt', 'norwegian' => '', 'persian' => '', 'portuguese' => '', 'romanian' => '', 'russian' => 'ru', 'sorani' => '', 'spanish' => 'la', 'swedish' => '', 'thai' => 'th', 'turkish' => 'tr', ]; } protected $version = 27; protected function checkIndexTemplate($indexName, $siteId, $analyzer, $adminNotify = true) { $templateName = $indexName . '-' . $siteId. '-template'; $result = $this->query('GET', '/_index_template/' . $templateName); if (!$result && $this->errorNumber !== 404) { return false; } $versionMatch = ( isset($result['index_templates'][0]['index_template']['version']) && $result['index_templates'][0]['index_template']['version'] === $this->version ); $analyzerMatch = true; if ($analyzer) { $analyzerMatch = ( isset($result['index_templates'][0]['index_template']['template']['mappings']['properties']['body']['analyzer']) && $result['index_templates'][0]['index_template']['template']['mappings']['properties']['body']['analyzer'] === $analyzer ); } else { $analyzerMatch = !isset($result['index_templates'][0]['index_template']['template']['mappings']['properties']['body']['analyzer']); } $updateNeeded = !$versionMatch || !$analyzerMatch; if ($updateNeeded) { $result = $this->query('DELETE', '/_index_template/' . $templateName); } if ($this->errorNumber === 404 || $updateNeeded) { $template = [ 'mappings' => [ 'properties' => [ 'id' => [ 'type' => 'integer', ], 'date_change' => [ 'type' => 'date', 'format' => 'date_time_no_millis', ], 'date_change_ts' => [ 'type' => 'integer', ], 'module_id' => [ 'type' => 'keyword', ], 'item_id' => [ 'type' => 'keyword', ], 'custom_rank' => [ 'type' => 'integer', ], // user_id // entity_type_id // entity_id // url 'title' => [ 'type' => 'text', ], 'body' => [ 'type' => 'text', ], // tags 'param1' => [ 'type' => 'keyword', ], 'param2' => [ 'type' => 'keyword', ], // upd 'date_from' => [ 'type' => 'date', 'format' => 'date_time_no_millis', ], 'date_from_ts' => [ 'type' => 'integer', ], 'date_to' => [ 'type' => 'date', 'format' => 'date_time_no_millis', ], 'date_to_ts' => [ 'type' => 'integer', ], 'tag' => [ 'type' => 'keyword', // array ], 'xright' => [ // Can not use right here because sql plugin makes it uppercase 'type' => 'keyword', // array ], 'param' => [ 'properties' => [], 'dynamic' => true, ], ] ] ]; if ($analyzer) { $template['mappings']['properties']['body']['analyzer'] = $analyzer; } $result = $this->query('PUT', '/_index_template/' . $templateName, [ 'index_patterns' => [ $indexName . '-' . $siteId, ], 'version' => $this->version, 'template' => $template ]); if ($adminNotify) { $error = [ 'MESSAGE' => GetMessage("SEARCH_OPENSEARCH_REINDEX", ['#LINK#' => '/bitrix/admin/search_reindex.php?lang=' . LANGUAGE_ID]), 'TAG' => 'SEARCH_REINDEX', 'MODULE_ID' => 'SEARCH', 'NOTIFY_TYPE' => CAdminNotify::TYPE_ERROR, ]; CAdminNotify::Add($error); } return $result; } return true; } static $siteIdChecked = []; protected function checkTemplateBySiteId($siteId) { global $CACHE_MANAGER; if (isset(static::$siteIdChecked[$siteId])) { return; } static::$siteIdChecked[$siteId] = true; $cacheId = 'opensearch-template-' . $siteId; if ($CACHE_MANAGER->Read(CACHED_opensearch_template, $cacheId, 'opensearch')) { return; } if (isset($this->siteAnalyzerMap[$siteId])) { $this->checkIndexTemplate($this->indexName, $siteId, $this->siteAnalyzerMap[$siteId], false); } $CACHE_MANAGER->Set($cacheId, true); } public function truncate() { $this->query('DELETE', '/' . $this->indexName . '-*?expand_wildcards=all'); } public function deleteById($ID) { foreach ($this->siteAnalyzerMap as $siteId => $_) { $this->query('DELETE', '/' . $this->indexName . '-' . $siteId . '/_doc/' . intval($ID)); } } public function replace($ID, $arFields) { $DB = CDatabase::GetModuleConnection('search'); if (array_key_exists('~DATE_CHANGE', $arFields)) { $arFields['DATE_CHANGE'] = $arFields['~DATE_CHANGE']; unset($arFields['~DATE_CHANGE']); } elseif (array_key_exists('LAST_MODIFIED', $arFields)) { $arFields['DATE_CHANGE'] = $arFields['LAST_MODIFIED']; unset($arFields['LAST_MODIFIED']); } elseif (array_key_exists('DATE_CHANGE', $arFields)) { $arFields['DATE_CHANGE'] = $DB->FormatDate($arFields['DATE_CHANGE'], 'DD.MM.YYYY HH:MI:SS', CLang::GetDateFormat()); } $DATE_FROM = intval(MakeTimeStamp($arFields['DATE_FROM'])); $DATE_TO = intval(MakeTimeStamp($arFields['DATE_TO'])); $DATE_CHANGE = intval(MakeTimeStamp($arFields['DATE_CHANGE'])); $BODY = ($arFields['TITLE'] ? CSearch::KillEntities($arFields['TITLE']) . "\n" : '') . CSearch::KillEntities($arFields['BODY']) . ($arFields['TAGS'] ? "\n" . $arFields['TAGS'] : '') ; $sites = $this->sites($arFields['SITE_ID']); foreach ($this->siteAnalyzerMap as $siteId => $_) { if (in_array($siteId, $sites)) { $doc = [ 'id' => $ID, 'date_change' => $DATE_CHANGE ? date('c', $DATE_CHANGE) : null, 'date_change_ts' => $DATE_CHANGE ? $DATE_CHANGE - CTimeZone::GetOffset() : 0, 'module_id' => $arFields['MODULE_ID'], 'item_id' => $arFields['ITEM_ID'], 'custom_rank' => intval($arFields['CUSTOM_RANK']), 'title' => $arFields['TITLE'], 'body' => $BODY, 'param1' => $arFields['PARAM1'], 'param2' => $arFields['PARAM2'], 'date_from' => $DATE_FROM ? date('c', $DATE_FROM) : null, 'date_from_ts' => $DATE_FROM ? $DATE_FROM - CTimeZone::GetOffset() : 0, 'date_to' => $DATE_TO ? date('c', $DATE_TO) : null, 'date_to_ts' => $DATE_TO ? $DATE_TO - CTimeZone::GetOffset() : 0, 'tag' => $this->tags($arFields['SITE_ID'], $arFields['TAGS']), 'xright' => $this->rights($arFields['PERMISSIONS']), 'param' => $this->params($arFields['PARAMS']), ]; $this->checkTemplateBySiteId($siteId); $result = $this->query('PUT', '/' . $this->indexName . '-' . $siteId . '/_doc/' . intval($ID), $doc); if (!$result) { throw new \Bitrix\Main\Db\SqlQueryException('OpenSearch index error', $this->getError(), ''); } } else { $result = $this->query('DELETE', '/' . $this->indexName . '-' . $siteId . '/_doc/' . intval($ID)); } } } public function update($ID, $arFields) { $DB = CDatabase::GetModuleConnection('search'); $ID = intval($ID); $arUpdate = []; $bReplace = array_key_exists('TITLE', $arFields) || array_key_exists('BODY', $arFields) || array_key_exists('MODULE_ID', $arFields) || array_key_exists('ITEM_ID', $arFields) || array_key_exists('PARAM1', $arFields) || array_key_exists('PARAM2', $arFields) ; if (array_key_exists('~DATE_CHANGE', $arFields)) { $arFields['DATE_CHANGE'] = $arFields['~DATE_CHANGE']; unset($arFields['~DATE_CHANGE']); } elseif (array_key_exists('LAST_MODIFIED', $arFields)) { $arFields['DATE_CHANGE'] = $arFields['LAST_MODIFIED']; unset($arFields['LAST_MODIFIED']); } elseif (array_key_exists('DATE_CHANGE', $arFields)) { $arFields['DATE_CHANGE'] = $DB->FormatDate($arFields['DATE_CHANGE'], 'DD.MM.YYYY HH:MI:SS', CLang::GetDateFormat()); } if (array_key_exists('DATE_CHANGE', $arFields)) { $DATE_CHANGE = intval(MakeTimeStamp($arFields['DATE_CHANGE'])); $arUpdate['date_change'] = $DATE_CHANGE > 0 ? date('c', $DATE_CHANGE - CTimeZone::GetOffset()) : null; $arUpdate['date_change_ts'] = $DATE_CHANGE > 0 ? $DATE_CHANGE : 0; } if (array_key_exists('DATE_FROM', $arFields)) { $DATE_FROM = intval(MakeTimeStamp($arFields['DATE_FROM'])); $arUpdate['date_from'] = $DATE_FROM > 0 ? date('c', $DATE_FROM - CTimeZone::GetOffset()) : null; $arUpdate['date_from_ts'] = $DATE_FROM > 0 ? $DATE_FROM : 0; } if (array_key_exists('DATE_TO', $arFields)) { $DATE_TO = intval(MakeTimeStamp($arFields['DATE_TO'])); $arUpdate['date_to'] = $DATE_TO > 0 ? date('c', $DATE_TO - CTimeZone::GetOffset()) : null; $arUpdate['date_to_ts'] = $DATE_TO > 0 ? $DATE_TO : 0; } if (array_key_exists('CUSTOM_RANK', $arFields)) { $arUpdate['custom_rank'] = $arFields['CUSTOM_RANK'] > 0 ? intval($arFields['CUSTOM_RANK']) : 0; } if (array_key_exists('TAGS', $arFields)) { $arUpdate['tag'] = $this->tags($arFields['SITE_ID'], $arFields['TAGS']); } if (array_key_exists('PERMISSIONS', $arFields)) { $arUpdate['xright'] = $this->rights($arFields['PERMISSIONS']); } if (array_key_exists('PARAMS', $arFields)) { $arUpdate['param'] = $this->params($arFields['PARAMS']); } if (array_key_exists('SITE_ID', $arFields)) { $sites = $this->sites($arFields['SITE_ID']); } else { $sites = []; $dbSites = $DB->Query('SELECT * from b_search_content_site WHERE SEARCH_CONTENT_ID=' . $ID); while ($site = $dbSites->fetch()) { $sites[$site['SITE_ID']] = $site['SITE_ID']; } } if (!empty($arUpdate) && !$bReplace) { foreach ($this->siteAnalyzerMap as $siteId => $_) { if (in_array($siteId, $sites)) { $result = $this->query('POST', '/' . $this->indexName . '-' . $siteId . '/_update/' . intval($ID), [ 'doc' => $arUpdate, ]); } else { $result = $this->query('DELETE', '/' . $this->indexName . '-' . $siteId . '/_doc/' . intval($ID)); } } } elseif ($bReplace) { $dbItem = $DB->Query('SELECT * FROM b_search_content WHERE ID = ' . $ID); $searchItem = $dbItem->fetch(); if ($searchItem) { $arTags = []; $dbTags = $DB->Query('SELECT * from b_search_tags WHERE SEARCH_CONTENT_ID=' . $ID); while ($tag = $dbTags->fetch()) { $arTags[] = $tag['NAME']; } $searchItem['TAGS'] = $arTags ? implode(',', $arTags) : null; $searchItem['PERMISSIONS'] = []; $dbRights = $DB->Query('SELECT * from b_search_content_right WHERE SEARCH_CONTENT_ID=' . $ID); while ($right = $dbRights->fetch()) { $searchItem['PERMISSIONS'][] = $right['GROUP_CODE']; } $searchItem['SITE_ID'] = []; $dbSites = $DB->Query('SELECT * from b_search_content_site WHERE SEARCH_CONTENT_ID=' . $ID); while ($site = $dbSites->fetch()) { $searchItem['SITE_ID'][$site['SITE_ID']] = $site['URL']; } $searchItem['PARAMS'] = []; $dbParams = $DB->Query('SELECT * from b_search_content_param WHERE SEARCH_CONTENT_ID=' . $ID); while ($param = $dbParams->fetch()) { $searchItem['PARAMS'][$param['PARAM_NAME']][] = $param['PARAM_VALUE']; } $this->replace($ID, $searchItem); } } } function tags($arLID, $sContent) { $tags = []; if (is_array($arLID)) { foreach ($arLID as $site_id => $url) { $arTags = tags_prepare($sContent, $site_id); foreach ($arTags as $tag) { $tags[$tag] = $tag; } } } return array_values($tags); } function rights($arRights) { $rights = []; if (is_array($arRights)) { foreach ($arRights as $group_id) { if (is_numeric($group_id)) { $rights[$group_id] = 'G' . intval($group_id); } else { $rights[$group_id] = $group_id; } } } return array_values($rights); } function sites($arSites) { $sites = []; if (is_array($arSites)) { foreach ($arSites as $site_id => $url) { $sites[$site_id] = $site_id; } } else { $sites[$arSites] = $arSites; } return array_values($sites); } function params($arParams) { $params = []; if (is_array($arParams)) { foreach ($arParams as $k1 => $v1) { $name = trim($k1); if ($name != '') { if (!is_array($v1)) { $v1 = [$v1]; } foreach ($v1 as $v2) { $value = trim($v2); if ($value != '') { $params[$name] = $value; } } } } } return $params; } public function getErrorText() { return $this->errorText; } public function getErrorNumber() { return $this->errorNumber; } public function search($arParams, $aSort, $aParamsEx, $bTagsCloud) { $DB = CDatabase::GetModuleConnection('search'); $result = []; $this->errorText = ''; $this->errorNumber = 0; $this->tags = trim($arParams['TAGS']); $limit = 0; if (is_array($aParamsEx) && isset($aParamsEx['LIMIT'])) { $limit = intval($aParamsEx['LIMIT']); unset($aParamsEx['LIMIT']); } if ($limit <= 0) { $limit = intval(COption::GetOptionInt('search', 'max_result_size')); } if ($limit <= 0) { $limit = 500; } $offset = 0; if (is_array($aParamsEx) && isset($aParamsEx['OFFSET'])) { $offset = intval($aParamsEx['OFFSET']); unset($aParamsEx['OFFSET']); } if (is_array($aParamsEx) && !empty($aParamsEx)) { $aParamsEx['LOGIC'] = 'OR'; $arParams[] = $aParamsEx; } $this->SITE_ID = $arParams['SITE_ID']; unset($arParams['SITE_ID']); $query = [ '_source' => false, 'query' => [ 'bool' => [ 'must' => [ ], ], ], 'from' => $offset, 'size' => $limit, ]; $strQuery = trim($arParams['QUERY']); if ($strQuery != '') { $query['query']['bool']['must'][] = [ 'match' => [ 'body' => [ 'query' => $strQuery, ], ], ]; } $rights = $this->CheckPermissions(); if ($rights) { $query['query']['bool']['filter'] = [ 'bool' => [ 'must' => [ [ 'terms' => [ 'xright' => $rights, ], ], ], ], ]; } $arWhere = $this->prepareFilter($arParams); if ($arWhere) { $query['query']['bool']['must'][] = $arWhere; } if ($strQuery || $this->tags || $bTagsCloud) { if ($bTagsCloud) { $query['size'] = 0; // we don't need hits $query['aggregations'] = [ 'tags' => [ 'terms' => [ 'field' => 'tag', 'size' => $limit, ], 'aggregations' => [ 'max_dc' => [ 'max' => [ 'field' => 'date_change_ts', ], ], ], ], ]; $r = $this->query('GET', '/' . $this->indexName . '-' . $this->SITE_ID . '/_search', $query); if (!$r) { throw new \Bitrix\Main\Db\SqlQueryException('OpenSearch select error', $this->getError(), $sql); } else { if ( is_array($r) && isset($r['aggregations']) && is_array($r['aggregations']) && isset($r['aggregations']['tags']) && is_array($r['aggregations']['tags']) ) { foreach ($r['aggregations']['tags']['buckets'] as $searcBucket) { $result[] = [ 'NAME' => $searcBucket['key'], 'CNT' => $searcBucket['doc_count'], 'FULL_DATE_CHANGE' => ConvertTimeStamp($searcBucket['max_dc']['value'] + CTimeZone::GetOffset(), 'FULL'), 'DATE_CHANGE' => ConvertTimeStamp($searcBucket['max_dc']['value'] + CTimeZone::GetOffset(), 'SHORT'), ]; } } } } else { $order = $this->__PrepareSort($order); if ($order) { $query['sort'] = $order; } $query['fields'] = ['id', 'module_id', 'param2']; $r = $this->query('GET', '/' . $this->indexName . '-' . $this->SITE_ID . '/_search', $query); if (!$r) { throw new \Bitrix\Main\Db\SqlQueryException('OpenSearch select error', $this->getError(), json_encode($query)); } else { $this->arForumTopics = []; if ( is_array($r) && isset($r['hits']) && is_array($r['hits']) && isset($r['hits']['hits']) && is_array($r['hits']['hits']) ) { foreach ($r['hits']['hits'] as $searchHit) { if ($searchHit['fields']['module_id'][0] == 'FORUM') { if (array_key_exists($searchHit['fields']['param2'][0], $this->arForumTopics)) { continue; } $this->arForumTopics[$searchHit['fields']['param2'][0]] = true; } $result[] = [ 'ID' => $searchHit['fields']['id'][0], ]; } } } } } else { $this->errorText = GetMessage('SEARCH_ERROR3'); $this->errorNumber = 3; } return $result; } function searchTitle($phrase = '', $arPhrase = [], $nTopCount = 5, $arParams = [], $bNotFilter = false, $order = '') { $query = [ '_source' => false, 'fields' => ['id'], 'query' => [ 'bool' => [ 'must' => [ [ 'match_phrase_prefix' => [ 'title' => $phrase, ], ], ], ], ], 'size' => $nTopCount, ]; $site_id = SITE_ID; if (is_array($arParams) && isset($arParams['SITE_ID'])) { $site_id = $arParams['SITE_ID']; unset($arParams['SITE_ID']); } $arWhere = $this->prepareFilter($arParams); if ($arWhere) { $query['query']['bool']['must'][] = $arWhere; } $rights = $this->CheckPermissions(); if ($rights) { $query['query']['bool']['filter'] = [ 'bool' => [ 'must' => [ [ 'terms' => [ 'xright' => $rights, ], ], ], ], ]; } $order = $this->__PrepareSort($order); if ($order) { $query['sort'] = $order; } $r = $this->query('GET', '/' . $this->indexName . '-' . $site_id . '/_search', $query); if (!$r) { throw new \Bitrix\Main\Db\SqlQueryException('OpenSearch query error', $this->getError(), json_encode($query)); } else { $result = []; if ( is_array($r) && isset($r['hits']) && is_array($r['hits']) && isset($r['hits']['hits']) && is_array($r['hits']['hits']) ) { foreach ($r['hits']['hits'] as $searchHit) { $result[] = $searchHit['fields']['id'][0]; } } return $result; } } function getRowFormatter() { return new CSearchOpenSearchFormatter($this); } function filterField($field, $value, $logic = 'should') { $DB = CDatabase::GetModuleConnection('search'); $arWhere = []; if (is_array($value)) { if (!empty($value)) { $arWhere = [ 'bool' => [ $logic => [ ] ] ]; foreach ($value as $i => $v) { $arWhere['bool'][$logic][] = [ 'term' => [ $field => [ 'value' => $v ] ] ]; } } } else { if ($value !== false) { $arWhere = [ 'bool' => [ $logic => [ 'term' => [ $field => [ 'value' => $value ] ] ] ] ]; } } return $arWhere; } function prepareFilter($arFilter) { $DB = CDatabase::GetModuleConnection('search'); if (!is_array($arFilter)) { $arFilter = []; } if (array_key_exists('LOGIC', $arFilter) && $arFilter['LOGIC'] == 'OR') { $logic = 'should'; unset($arFilter['LOGIC']); } else { $logic = 'must'; } $arWhere = [ 'bool' => [ $logic => [ ] ] ]; foreach ($arFilter as $field => $val) { $field = mb_strtoupper($field); if ( is_array($val) && count($val) == 1 && $field !== 'URL' && $field !== 'PARAMS' && !is_numeric($field) ) { $val = $val[0]; } switch ($field) { case 'ITEM_ID': case '=ITEM_ID': $cond = $this->filterField('item_id', $val); if ($cond) { array_push($arWhere['bool'][$logic], $cond); } break; case '!ITEM_ID': if ( $val !== false && !is_array($val) ) { array_push($arWhere['bool'][$logic], $this->filterField('item_id', $val, 'must_not')); } break; case 'MODULE_ID': case '=MODULE_ID': if ($val !== false && $val !== 'no') { $cond = $this->filterField('module_id', $val); if ($cond) { array_push($arWhere['bool'][$logic], $cond); } } break; case '!MODULE_ID': case '!=MODULE_ID': if ( $val !== false && !is_array($val) ) { array_push($arWhere['bool'][$logic], $this->filterField('module_id', $val, 'must_not')); } break; case 'PARAM1': case '=PARAM1': $cond = $this->filterField('param1', $val); if ($cond) { array_push($arWhere['bool'][$logic], $cond); } break; case '!PARAM1': case '!=PARAM1': if ( $val !== false && !is_array($val) ) { array_push($arWhere['bool'][$logic], $this->filterField('param1', $val, 'must_not')); } break; case 'PARAM2': case '=PARAM2': $cond = $this->filterField('param2', $val); if ($cond) { array_push($arWhere['bool'][$logic], $cond); } break; case '!PARAM2': case '!=PARAM2': if ( $val !== false && !is_array($val) ) { array_push($arWhere['bool'][$logic], $this->filterField('param2', $val, 'must_not')); } break; case 'DATE_CHANGE': case '>=DATE_CHANGE': if ($val <> '') { $ts = MakeTimeStamp($val) - CTimeZone::GetOffset(); $arWhere['bool'][$logic][] = [ 'range' => [ 'date_change_ts' => [ 'from' => $ts, 'to' => null, 'include_lower' => true, 'include_upper' => true, ] ] ]; } break; case '<=DATE_CHANGE': if ($val <> '') { $ts = MakeTimeStamp($val) - CTimeZone::GetOffset(); $arWhere['bool'][$logic][] = [ 'range' => [ 'date_change_ts' => [ 'from' => null, 'to' => $ts, 'include_lower' => true, 'include_upper' => true, ] ] ]; } break; case 'CHECK_DATES': if ($val == 'Y') { $ts = time() - CTimeZone::GetOffset(); $arWhere['bool'][$logic][] = [ 'bool' => [ 'must' => [ [ 'bool' => [ 'should' => [ [ 'term' => [ 'date_from_ts' => [ 'value' => 0, ] ] ], [ 'range' => [ 'date_from_ts' => [ 'from' => null, 'to' => $ts, 'include_lower' => true, 'include_upper' => true, ] ] ], ] ] ], [ 'bool' => [ 'should' => [ [ 'term' => [ 'date_to_ts' => [ 'value' => 0, ] ] ], [ 'range' => [ 'date_to_ts' => [ 'from' => $ts, 'to' => null, 'include_lower' => true, 'include_upper' => true, ] ] ], ] ] ], ] ] ]; } break; case 'TAGS': $arTags = explode(',', $val); foreach ($arTags as $i => &$strTag) { $strTag = trim($strTag, " \n\r\t\""); if ($strTag == '') { unset($arTags[$i]); } } unset($strTag); $cond = $this->filterField('tag', $arTags, 'must'); if ($cond) { array_push($arWhere['bool'][$logic], $cond); } break; case 'PARAMS': if (is_array($val)) { $params = []; foreach ($this->params($val) as $key => $value) { $params[] = [ 'term' => [ 'param.' . $key => [ 'value' => $value, ] ] ]; } if ($params) { array_push($arWhere['bool'][$logic], [ 'bool' => [ 'must' => $params ] ]); } } break; case 'URL': //TODO case 'QUERY': case 'LIMIT': case 'USE_TF_FILTER': break; default: if (is_numeric($field) && is_array($val)) { $subFilter = $this->prepareFilter($val); if ($subFilter) { $arWhere['bool'][$logic][] = $subFilter; } } else { //AddMessage2Log("field: $field; val: ".print_r($val, 1)); } break; } } if (!$arWhere['bool'][$logic]) { return []; } return $arWhere; } function CheckPermissions() { global $USER; $DB = CDatabase::GetModuleConnection('search'); $arResult = []; if (!$USER->IsAdmin()) { if ($USER->GetID() > 0) { CSearchUser::CheckCurrentUserGroups(); $rs = $DB->Query('SELECT GROUP_CODE FROM b_search_user_right WHERE USER_ID = ' . $USER->GetID()); while ($ar = $rs->Fetch()) { $arResult[] = $ar['GROUP_CODE']; } } else { $arResult[] = 'G2'; } } return $this->rights($arResult); } function __PrepareSort($aSort = []) { $arOrder = []; if (!is_array($aSort)) { $aSort = [$aSort => 'ASC']; } $this->flagsUseRatingSort = 0; foreach ($aSort as $key => $ord) { $ord = mb_strtoupper($ord) <> 'ASC' ? 'desc' : 'asc'; $key = mb_strtoupper($key); switch ($key) { case 'ID': case 'DATE_CHANGE': case 'MODULE_ID': case 'ITEM_ID': case 'CUSTOM_RANK': case 'PARAM1': case 'PARAM2': case 'DATE_FROM': case 'DATE_TO': $arOrder[mb_strtolower($key)] = ['order' => $ord]; break; case 'RANK': $arOrder['_score'] = ['order' => $ord]; break; } } if (count($arOrder) == 0) { return $this->__PrepareSort([ 'CUSTOM_RANK' => 'DESC', 'RANK' => 'DESC', 'DATE_CHANGE' => 'DESC', ]); } return $arOrder; } public function query($verb, $url, $params = []) { $this->errorText = ''; $this->errorNumber = 0; $result = false; $server = new Bitrix\Main\Web\HttpClient([ 'disableSslVerification' => true, ]); if ($this->user) { $server->setAuthorization($this->user, $this->password); } if ($params) { $server->setHeader('Content-Type', 'application/json'); } $server->query($verb, $this->connectionString . $url, $params ? json_encode($params) : false); if ( $server->getStatus() === 200 || $server->getStatus() === 201 ) { $result = json_decode($server->getResult(), true); } // AddMessage2Log([$verb . ' ' . $url, $server->getStatus(), $result ?: $server->getResult()]); if (!is_array($result)) { if ($server->getStatus()) { $this->errorText = $server->getResult(); $this->errorNumber = $server->getStatus(); } else { $errors = $server->getError(); $this->errorText = $errors ? implode(' ', $errors) : '-1'; } } elseif (isset($result['error'])) { $this->errorText = $result['error']; $this->errorNumber = $result['status']; } return $result; } public function getError() { if ($this->errorText) { $result = '[' . $this->errorNumber . '] ' . $this->errorText; } else { $result = ''; } return $result; } } class CSearchOpenSearchFormatter extends CSearchFormatter { /** @var CSearchOpenSearch */ private $search = null; function __construct($search) { $this->search = $search; } function format($r) { if ($r) { if (array_key_exists('CNT', $r)) { return $r; } elseif (array_key_exists('ID', $r)) { return $this->formatRow($r); } } } function formatRow($r) { $DB = CDatabase::GetModuleConnection('search'); $ID = intval($r['ID']); if ($this->search->SITE_ID) { $rs = $DB->Query(' select sc.ID ,sc.MODULE_ID ,sc.ITEM_ID ,sc.TITLE ,sc.TAGS ,sc.BODY ,sc.PARAM1 ,sc.PARAM2 ,sc.UPD ,sc.DATE_FROM ,sc.DATE_TO ,sc.URL ,sc.CUSTOM_RANK ,' . $DB->DateToCharFunction('sc.DATE_CHANGE') . ' as FULL_DATE_CHANGE ,' . $DB->DateToCharFunction('sc.DATE_CHANGE', 'SHORT') . ' as DATE_CHANGE ,scsite.SITE_ID ,scsite.URL SITE_URL ,sc.USER_ID from b_search_content sc INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID where ID = ' . $ID . " and scsite.SITE_ID = '" . $DB->ForSql($this->search->SITE_ID) . "' "); } else { $rs = $DB->Query(' select sc.ID ,sc.MODULE_ID ,sc.ITEM_ID ,sc.TITLE ,sc.TAGS ,sc.BODY ,sc.PARAM1 ,sc.PARAM2 ,sc.UPD ,sc.DATE_FROM ,sc.DATE_TO ,sc.URL ,sc.CUSTOM_RANK ,' . $DB->DateToCharFunction('sc.DATE_CHANGE') . ' as FULL_DATE_CHANGE ,' . $DB->DateToCharFunction('sc.DATE_CHANGE', 'SHORT') . ' as DATE_CHANGE ,\'\' as SITE_ID from b_search_content sc where ID = ' . $ID . ' '); } $r = $rs->Fetch(); return $r; } }