1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
pgsql.php
См. документацию.
1<?php
3
5{
6 protected $error = '';
7 protected $errorno = 0;
8
9 public function connect($connectionString = '')
10 {
11 global $APPLICATION;
12 $DB = CDatabase::GetModuleConnection('search');
13
14 if (!$DB->IndexExists('b_search_content_text', ['SEARCHABLE_CONTENT']))
15 {
16 $r = $DB->Query('CREATE INDEX tx_b_search_content_text_searchable_content ON b_search_content_text USING GIN (to_tsvector(\'english\', searchable_content))', true);
17 if (!$r)
18 {
19 $APPLICATION->ThrowException(GetMessage('SEARCH_PGSQL_INDEX_CREATE_ERROR', ['#ERRSTR#' => $DB->db_Error]));
20 return false;
21 }
22 }
23
24 return true;
25 }
26
27 public function truncate()
28 {
29 $DB = CDatabase::GetModuleConnection('search');
30 $DB->Query('TRUNCATE TABLE b_search_content_text');
31 }
32
33 public function deleteById($ID)
34 {
35 $DB = CDatabase::GetModuleConnection('search');
36 $DB->Query('DELETE FROM b_search_content_text WHERE SEARCH_CONTENT_ID = ' . $ID);
37 }
38
39 public function update($ID, $arFields)
40 {
41 return $this->replace($ID, $arFields);
42 }
43
44 public function replace($ID, $arFields)
45 {
46 $DB = CDatabase::GetModuleConnection('search');
47
48 if (array_key_exists('SEARCHABLE_CONTENT', $arFields))
49 {
50 $text_md5 = md5($arFields['SEARCHABLE_CONTENT']);
51 $rsText = $DB->Query('SELECT SEARCH_CONTENT_MD5 FROM b_search_content_text WHERE SEARCH_CONTENT_ID = ' . $ID);
52 $arText = $rsText->Fetch();
53 if (!$arText || $arText['SEARCH_CONTENT_MD5'] !== $text_md5)
54 {
55 $DB->Query('
56 INSERT INTO b_search_content_text
57 (SEARCH_CONTENT_ID, SEARCH_CONTENT_MD5, SEARCHABLE_CONTENT)
58 values
59 (' . $ID . ", '" . $DB->ForSql($text_md5) . "', '" . $DB->ForSql($arFields['SEARCHABLE_CONTENT']) . "')
60 ON CONFLICT (SEARCH_CONTENT_ID)
61 DO UPDATE SET SEARCH_CONTENT_MD5 = excluded.SEARCH_CONTENT_MD5
62 ,SEARCHABLE_CONTENT = excluded.SEARCHABLE_CONTENT
63 ");
64 }
65 }
66 }
67
68 public function search($arParams, $aSort, $aParamsEx, $bTagsCloud)
69 {
70 $DB = CDatabase::GetModuleConnection('search');
71 $helper = $DB->getConnection()->getSqlHelper();
72
73 $queryObject = $aParamsEx['QUERY_OBJECT'];
74 if ($queryObject->m_parsed_query == '( )' || $queryObject->m_parsed_query == '')
75 {
76 $this->error = GetMessage('SEARCH_ERROR3');
77 $this->errorno = 3;
78 return [];
79 }
80
81 $strQuery = $this->PrepareQuery($queryObject, $queryObject->m_parsed_query);
82 if ($strQuery == '(())' || $queryObject->m_parsed_query == '')
83 {
84 $this->error = GetMessage('SEARCH_ERROR3');
85 $this->errorno = 3;
86 return [];
87 }
88
89 $strTags = '';
90 if (array_key_exists('TAGS', $arParams))
91 {
92 $this->strTagsText = $arParams['TAGS'];
93 $arTags = explode(',', $arParams['TAGS']);
94 foreach ($arTags as $i => $strTag)
95 {
96 $strTag = str_replace(['"', "'"], ' ', $strTag);
97 $strTag = trim($strTag);
98 $strTag = "('" . preg_replace('/\s+/', "' <-> '", $strTag) . "')";
99 $arTags[$i] = $strTag;
100 }
101
102 if ($arTags)
103 {
104 $strTags = '& (' . implode(' & ', $arTags) . ')';
105 }
106 }
107
108 if (($strQuery == '') && ($strTags <> ''))
109 {
110 $strQuery = $strTags;
111 $bTagsSearch = true;
112 }
113 else
114 {
115 $strQuery = preg_replace_callback('/&#(\\d+);/', 'chr', $strQuery);
116 $bTagsSearch = false;
117 }
118
119 $query = $helper->getMatchFunction('sct.SEARCHABLE_CONTENT', "'" . $DB->ForSql($strQuery) . "'");
120
121 $arSqlWhere = [];
122 if (is_array($aParamsEx) && !empty($aParamsEx))
123 {
124 foreach ($aParamsEx as $aParamEx)
125 {
126 $strSqlWhere = CSearch::__PrepareFilter($aParamEx, $bIncSites);
127 if ($strSqlWhere != '')
128 {
129 $arSqlWhere[] = $strSqlWhere;
130 }
131 }
132 }
133 if (!empty($arSqlWhere))
134 {
135 $arSqlWhere = [
136 "\n\t\t\t\t(" . implode(")\n\t\t\t\t\tOR(", $arSqlWhere) . "\n\t\t\t\t)",
137 ];
138 }
139
140 $strSqlWhere = CSearch::__PrepareFilter($arParams, $bIncSites);
141 if ($strSqlWhere != '')
142 {
143 array_unshift($arSqlWhere, $strSqlWhere);
144 }
145
146 $strSqlOrder = $this->__PrepareSort($aSort, 'sc.', $bTagsCloud);
147
148 if (!empty($arSqlWhere))
149 {
150 $strSqlWhere = "\n\t\t\t\tAND (\n\t\t\t\t\t(" . implode(")\n\t\t\t\t\tAND(", $arSqlWhere) . ")\n\t\t\t\t)";
151 }
152
153 if ($bTagsCloud)
154 {
155 $strSql = '
156 SELECT
157 stags.NAME
158 ,COUNT(DISTINCT stags.SEARCH_CONTENT_ID) as CNT
159 ,MAX(sc.DATE_CHANGE) DC_TMP
160 ,' . $DB->DateToCharFunction('MAX(sc.DATE_CHANGE)') . ' as FULL_DATE_CHANGE
161 ,' . $DB->DateToCharFunction('MAX(sc.DATE_CHANGE)', 'SHORT') . ' as DATE_CHANGE
162 FROM b_search_tags stags
163 INNER JOIN b_search_content sc ON (stags.SEARCH_CONTENT_ID=sc.ID)
164 INNER JOIN b_search_content_text sct ON sct.SEARCH_CONTENT_ID = sc.ID
165 INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
166 WHERE
167 ' . CSearch::CheckPermissions('sc.ID') . '
168 AND (' . $query . ')
169 AND stags.SITE_ID = scsite.SITE_ID
170 ' . $strSqlWhere . '
171 GROUP BY
172 stags.NAME
173 ' . $strSqlOrder . '
174 ';
175 }
176 else
177 {
178 $strSql = '
179 SELECT
180 sct.SEARCH_CONTENT_ID
181 ,scsite.SITE_ID
182 ,' . $query . ' RANK
183 FROM
184 b_search_content_text sct
185 INNER JOIN b_search_content sc ON sc.ID = sct.SEARCH_CONTENT_ID
186 INNER JOIN b_search_content_site scsite ON sc.ID = scsite.SEARCH_CONTENT_ID
187 WHERE
188 ' . CSearch::CheckPermissions('sc.ID') . '
189 AND (' . $query . ')
190 ' . $strSqlWhere . '
191 ' . $strSqlOrder;
192 }
193
194 $r = $DB->Query($strSql);
195 $result = [];
196 while ($a = $r->Fetch())
197 {
198 $result[] = $a;
199 }
200
201 return $result;
202 }
203
204 function searchTitle($phrase = '', $arPhrase = [], $nTopCount = 5, $arParams = [], $bNotFilter = false, $order = '')
205 {
206 return false;
207 }
208
209 public function getErrorText()
210 {
211 return $this->error;
212 }
213
214 public function getErrorNumber()
215 {
216 return $this->errorno;
217 }
218
220 {
221 return new CSearchPgSqlFormatter();
222 }
223
224 function __PrepareSort($aSort = [], $strSearchContentAlias = 'sc.', $bTagsCloud = false)
225 {
226 $arOrder = [];
227 if (!is_array($aSort))
228 {
229 $aSort = [$aSort => 'ASC'];
230 }
231
232 if ($bTagsCloud)
233 {
234 foreach ($aSort as $key => $ord)
235 {
236 $ord = mb_strtoupper($ord) <> 'ASC' ? 'DESC' : 'ASC';
237 $key = mb_strtoupper($key);
238 switch ($key)
239 {
240 case 'DATE_CHANGE':
241 $arOrder[] = 'DC_TMP ' . $ord;
242 break;
243 case 'NAME':
244 case 'CNT':
245 $arOrder[] = $key . ' ' . $ord;
246 break;
247 }
248 }
249 if (!$arOrder)
250 {
251 $arOrder[] = 'NAME ASC';
252 }
253 }
254 else
255 {
256 $this->flagsUseRatingSort = 0;
257 foreach ($aSort as $key => $ord)
258 {
259 $ord = mb_strtoupper($ord) <> 'ASC' ? 'DESC' : 'ASC';
260 $key = mb_strtoupper($key);
261 switch ($key)
262 {
263 case 'DATE_CHANGE':
264 if (!($this->flagsUseRatingSort & 0x01))
265 {
266 $this->flagsUseRatingSort = 0x02;
267 }
268 $arOrder[] = $strSearchContentAlias . $key . ' ' . $ord;
269 break;
270 case 'RANK':
271 if (!($this->flagsUseRatingSort & 0x02))
272 {
273 $this->flagsUseRatingSort = 0x01;
274 }
275 $arOrder[] = 'RANK ' . $ord;
276 break;
277 case 'TITLE_RANK':
278 $arOrder[] = 'RANK ' . $ord;
279 break;
280 case 'CUSTOM_RANK':
281 $arOrder[] = $strSearchContentAlias . $key . ' ' . $ord;
282 break;
283 case 'ID':
284 case 'MODULE_ID':
285 case 'ITEM_ID':
286 case 'TITLE':
287 case 'PARAM1':
288 case 'PARAM2':
289 case 'UPD':
290 case 'DATE_FROM':
291 case 'DATE_TO':
292 case 'URL':
293 if (!($this->flagsUseRatingSort & 0x01))
294 {
295 $this->flagsUseRatingSort = 0x02;
296 }
297 $arOrder[] = $strSearchContentAlias . $key . ' ' . $ord;
298 break;
299 }
300 }
301
302 if (!$arOrder)
303 {
304 $arOrder[] = 'CUSTOM_RANK DESC';
305 $arOrder[] = 'RANK DESC';
306 $arOrder[] = $strSearchContentAlias . 'DATE_CHANGE DESC';
307 $this->flagsUseRatingSort = 0x01;
308 }
309 }
310
311 return ' ORDER BY ' . implode(', ', $arOrder);
312 }
313
314 function PrepareQuery($queryObject, $q)
315 {
316 $state = 0;
317 $qu = [];
318 $n = 0;
319 $this->error = '';
320 $this->errorno = 0;
321
322 foreach (preg_split('/ +/', $q) as $t)
323 {
324 if ($state === 0)
325 {
326 if (($t === '||') || ($t === '&&') || ($t === ')'))
327 {
328 $this->error = GetMessage('SEARCH_ERROR2') . ' ' . $t;
329 $this->errorno = 2;
330 break;
331 }
332 elseif ($t === '!')
333 {
334 $qu[] = ' !';
335 }
336 elseif ($t === '(')
337 {
338 $n++;
339 $qu[] = '(';
340 }
341 else
342 {
343 $state = 1;
344 if (isset($queryObject->m_kav[$t]))
345 {
346 $kav = str_replace(['"', "'"], ' ', $queryObject->m_kav[$t]);
347 $kav = trim($kav);
348 $kav = "('" . preg_replace('/\s+/', "' <-> '", $kav) . "')";
349 $t = $kav;
350 }
351 else
352 {
353 if (preg_match('/[^\w\d]/u', $t))
354 {
355 $t = preg_replace('/[^\w\d]+$/u', '', $t);
356 $t = preg_replace('/^[^\w\d]+/u', '', $t);
357 if ($t === '')
358 {
359 continue;
360 }
361 $t = '(' . preg_replace('/[^\w\d]+/u', ' & ', $t) . ($queryObject->bStemming ? ':*' : '') . ')';
362 }
363 elseif ($queryObject->bStemming)
364 {
365 $t .= ':*';
366 }
367 }
368 $qu[] = $t;
369 }
370 }
371 else
372 {
373 if (($t === '||') || ($t === '&&'))
374 {
375 $state = 0;
376 if ($t === '||')
377 {
378 $qu[] = ' | ';
379 }
380 else
381 {
382 $qu[] = ' & ';
383 }
384 }
385 elseif ($t === ')')
386 {
387 $n--;
388 $qu[] = ')';
389 }
390 else
391 {
392 $this->error = GetMessage('SEARCH_ERROR2') . ' ' . $t;
393 $this->errorno = 2;
394 break;
395 }
396 }
397 }
398
399 if (($this->error === '') && ($n !== 0))
400 {
401 $this->error = GetMessage('SEARCH_ERROR1');
402 $this->errorno = 1;
403 }
404
405 if ($this->error != '')
406 {
407 return '';
408 }
409
410 return implode($qu);
411 }
412}
413
415{
416 function format($r)
417 {
418 if ($r)
419 {
420 if (array_key_exists('CNT', $r))
421 {
422 return $r;
423 }
424 elseif (array_key_exists('SEARCH_CONTENT_ID', $r))
425 {
426 return $this->formatRow($r);
427 }
428 }
429 }
430
431 function formatRow($r)
432 {
433 $DB = CDatabase::GetModuleConnection('search');
434
435 $rs = $DB->Query('
436 select
437 sc.ID
438 ,sc.MODULE_ID
439 ,sc.ITEM_ID
440 ,sc.TITLE
441 ,sc.TAGS
442 ,sc.BODY
443 ,sc.PARAM1
444 ,sc.PARAM2
445 ,sc.UPD
446 ,sc.DATE_FROM
447 ,sc.DATE_TO
448 ,sc.URL
449 ,sc.CUSTOM_RANK
450 ,' . $DB->DateToCharFunction('sc.DATE_CHANGE') . ' as FULL_DATE_CHANGE
451 ,' . $DB->DateToCharFunction('sc.DATE_CHANGE', 'SHORT') . ' as DATE_CHANGE
452 ,scsite.SITE_ID
453 ,scsite.URL SITE_URL
454 ,sc.USER_ID
455 from b_search_content sc
456 INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
457 where ID = ' . $r['SEARCH_CONTENT_ID'] . "
458 and scsite.SITE_ID = '" . $r['SITE_ID'] . "'
459 ");
460 $r = $rs->Fetch();
461
462 return $r;
463 }
464}
$arParams
Определения access_dialog.php:21
global $APPLICATION
Определения include.php:80
static __PrepareFilter($arFilter, &$bIncSites, $strSearchContentAlias='sc.')
Определения search.php:2149
static CheckPermissions($FIELD='sc.ID')
Определения search.php:2660
Определения full_text.php:105
Определения full_text.php:4
Определения pgsql.php:415
format($r)
Определения pgsql.php:416
formatRow($r)
Определения pgsql.php:431
Определения pgsql.php:5
searchTitle($phrase='', $arPhrase=[], $nTopCount=5, $arParams=[], $bNotFilter=false, $order='')
Определения pgsql.php:204
getErrorNumber()
Определения pgsql.php:214
update($ID, $arFields)
Определения pgsql.php:39
getErrorText()
Определения pgsql.php:209
PrepareQuery($queryObject, $q)
Определения pgsql.php:314
getRowFormatter()
Определения pgsql.php:219
$errorno
Определения pgsql.php:7
connect($connectionString='')
Определения pgsql.php:9
__PrepareSort($aSort=[], $strSearchContentAlias='sc.', $bTagsCloud=false)
Определения pgsql.php:224
deleteById($ID)
Определения pgsql.php:33
truncate()
Определения pgsql.php:27
replace($ID, $arFields)
Определения pgsql.php:44
$error
Определения pgsql.php:6
search($arParams, $aSort, $aParamsEx, $bTagsCloud)
Определения pgsql.php:68
$arFields
Определения dblapprove.php:5
$result
Определения get_property_values.php:14
$arPhrase
Определения get_search.php:37
$query
Определения get_search.php:11
if($ajaxMode) $ID
Определения get_user.php:27
global $DB
Определения cron_frame.php:29
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$order
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
else $a
Определения template.php:137
$rs
Определения action.php:82
$n
Определения update_log.php:107