Наверх

mSearch2 с поиском по точному вхождению

/** @var modX $modx */
/** @var array $scriptProperties */
/** @var mSearch2 $mSearch2 */

if (!$modx->loadClass('msearch2', MODX_CORE_PATH . 'components/msearch2/model/msearch2/', false, true)) {return false;}
$mSearch2 = new mSearch2($modx, $scriptProperties);
$mSearch2->pdoTools->setConfig($scriptProperties);
$mSearch2->pdoTools->addTime('pdoTools loaded.');

if (empty($queryVar)) {$queryVar = 'query';}
if (empty($parentsVar)) {$parentsVar = 'parents';}
if (empty($minQuery)) {$minQuery = $modx->getOption('index_min_words_length', null, 3, true);}
if (empty($htagOpen)) {$htagOpen = '';}
if (empty($htagClose)) {$htagClose = '';}
if (empty($outputSeparator)) {$outputSeparator = "\n";}
if (empty($plPrefix)) {$plPrefix = 'mse2_';}
$returnIds = !empty($returnIds);
$fastMode = !empty($fastMode);

$class = 'modResource';
$found = array();
$output = null;
$query = !empty($_REQUEST[$queryVar])
	? $mSearch2->getQuery(rawurldecode($_REQUEST[$queryVar]))
	: '';

if (empty($resources)) {
	if (empty($query) && isset($_REQUEST[$queryVar])) {
		$output = $modx->lexicon('mse2_err_no_query');
	}
	elseif (empty($query) && !empty($forceSearch)) {
		$output = $modx->lexicon('mse2_err_no_query_var');
	}
	elseif (!empty($query) && !preg_match('/^[0-9]{2,}$/', $query) && mb_strlen($query,'UTF-8') < $minQuery) {
		$output = $modx->lexicon('mse2_err_min_query');
	}

	$modx->setPlaceholder($plPrefix.$queryVar, $query);

	if (!empty($output)) {
		return !$returnIds
			? $output
			: '';
	}
	elseif (!empty($query)) {
        $decodedQuery = str_replace(' ', '%', rawurldecode($_REQUEST[$queryVar]));
		$q = $modx->newQuery('modResource');
		$q->leftJoin('msProductData', 'Data', 'modResource.id = Data.id');
		$q->where([
			[
				'deleted' => false,
				'published' => true,
			],
			[
				'pagetitle:LIKE' => '%' . $decodedQuery . '%',
				'OR:longtitle:LIKE' => '%' . $decodedQuery . '%',
				'OR:description:LIKE' => '%' . $decodedQuery . '%',
				'OR:introtext:LIKE' => '%' . $decodedQuery . '%',
				'OR:content:LIKE' => '%' . $decodedQuery . '%',
				'OR:Data.article:LIKE' => '%' . $decodedQuery . '%'
			]
		]);
		$q->select('`modResource`.`id`');
		if ($q->prepare() && $q->stmt->execute()) {
        	$exact = $q->stmt->fetchAll(PDO::FETCH_COLUMN);
        }
		
		$found = $mSearch2->Search($query);
		$ids = array_merge($exact, array_keys($found));
		$resources = implode(',', $ids);
		if (empty($ids)) {
			if ($returnIds) {
				return '';
			}
			elseif (!empty($query)) {
				$output = $modx->lexicon('mse2_err_no_results');
			}
			if (!empty($tplWrapper) && !empty($wrapIfEmpty)) {
				$output = $mSearch2->pdoTools->getChunk(
					$tplWrapper,
					array(
						'output' => $output,
						'total' => 0,
						'query' => $query,
						'parents' => $modx->getPlaceholder($plPrefix.$parentsVar),
					),
					$fastMode
				);
			}
			if ($modx->user->hasSessionContext('mgr') && !empty($showLog)) {
				$output .= '<pre class="mSearchLog">' . print_r($mSearch2->pdoTools->getTime(), 1) . '</pre>';
			}
			if (!empty($toPlaceholder)) {
				$modx->setPlaceholder($toPlaceholder, $output);
				return;
			}
			else {
				return $output;
			}
		}
	}
}
elseif (strpos($resources, '{') === 0) {
	$found = $modx->fromJSON($resources);
	$resources = implode(',', array_keys($found));
	unset($scriptProperties['resources']);
}
/*----------------------------------------------------------------------------------*/
if (empty($returnIds)) {
	// Joining tables
	$leftJoin = array(
		'mseIntro' => array(
			'class' => 'mseIntro',
			'alias' => 'Intro',
			'on' => $class . '.id = Intro.resource'
		)
	);
	// Fields to select
	$resourceColumns = !empty($includeContent)
		? $modx->getSelectColumns($class, $class)
		: $modx->getSelectColumns($class, $class, '', array('content'), true);
	$select = array(
		$class => $resourceColumns,
		'Intro' => 'intro'
	);
	$groupby = $class.'.id, Intro.intro';
} else {
	$leftJoin = array();
	$select = array($class . 'id');
	$groupby = $class.'.id';
}

// Add custom parameters
foreach (array('leftJoin', 'select') as $v) {
	if (!empty($scriptProperties[$v])) {
		$tmp = $modx->fromJSON($scriptProperties[$v]);
		if (is_array($tmp)) {
			$$v = array_merge($$v, $tmp);
		}
	}
	unset($scriptProperties[$v]);
}

// Default parameters
$default = array(
	'class' => $class,
	'leftJoin' => $leftJoin,
	'select' => $select,
	'groupby' => $groupby,
	'return' => !empty($returnIds)
		? 'ids'
		: 'data',
	'fastMode' => $fastMode,
	'nestedChunkPrefix' => 'msearch2_',
);
if (!empty($resources)) {
	$default['resources'] = is_array($resources)
		? implode(',', $resources)
		: $resources;
}

// Merge all properties and run!
$mSearch2->pdoTools->setConfig(array_merge($default, $scriptProperties), false);
$mSearch2->pdoTools->addTime('Query parameters are prepared.');
$rows = $mSearch2->pdoTools->run();

$log = '';
if ($modx->user->hasSessionContext('mgr') && !empty($showLog)) {
	$log .= '<pre class="mSearchLog">' . print_r($mSearch2->pdoTools->getTime(), 1) . '</pre>';
}

// Processing results
if (!empty($returnIds)) {
	$modx->setPlaceholder('mSearch.log', $log);
	if (!empty($toPlaceholder)) {
		$modx->setPlaceholder($toPlaceholder, $rows);
		return '';
	}
	else {
		return $rows;
	}
}
elseif (!empty($rows) && is_array($rows)) {
	$output = array();
	foreach ($rows as $k => $row) {
		// Processing main fields
		$row['weight'] = isset($found[$row['id']]) ? $found[$row['id']] : '';
		$row['intro'] = $mSearch2->Highlight($row['intro'], $query, $htagOpen, $htagClose);

		$row['idx'] = $mSearch2->pdoTools->idx++;
		$tplRow = $mSearch2->pdoTools->defineChunk($row);
		$output[] .= empty($tplRow)
			? $mSearch2->pdoTools->getChunk('', $row)
			: $mSearch2->pdoTools->getChunk($tplRow, $row, $fastMode);
	}
	$mSearch2->pdoTools->addTime('Returning processed chunks');
	if (!empty($toSeparatePlaceholders)) {
		$output['log'] = $log;
		$modx->setPlaceholders($output, $toSeparatePlaceholders);
	}
	else {
		$output = implode($outputSeparator, $output) . $log;
	}
}
else {
	$output = $modx->lexicon('mse2_err_no_results') . $log;
}

// Return output
if (!empty($tplWrapper) && (!empty($wrapIfEmpty) || !empty($output))) {
	$output = $mSearch2->pdoTools->getChunk(
		$tplWrapper,
		array(
			'output' => $output,
			'total' => $modx->getPlaceholder($mSearch2->pdoTools->config['totalVar']),
			'query' => $modx->getPlaceholder($plPrefix.$queryVar),
			'parents' => $modx->getPlaceholder($plPrefix.$parentsVar),
		),
		$fastMode
	);
}

if (!empty($toPlaceholder)) {
	$modx->setPlaceholder($toPlaceholder, $output);
}
else {
	return $output;
}


1 комментарий

  1. Arahort 08 февраля 2022, 10:49 # 0
    Здравствуйте, правильно ли я понимаю что разница между оригинальным сниппетом и этим только в строках 46-63? Создал сниппет mSearch2_custom и вызываю его вместо mSearch2 на странице результатов поиска, но поиск по точному вхождению не работает :( Тестил по pagetitle. И ещё такой вопрос — в строках 53-57 как добавить параметр minishop2? Цель вообще искать по точному вхождению артикула.
    Вызов формы:
    [[!mSearchForm?
                        &class=`msProduct`
                        &element=`msProducts`
                        &tplForm=`my_tpl.mSearch2.form`
                        &where = `[[+template]] IN (6,31)`
                        &tpl=`my_tpl.mSearch2.ac`
                        &onlyIndex=`true`
                        &queryVar=`search`
                        &pageId=`14`
                        &autocomplete=`results`
                        &fields=`Data.article:10,article:10,tv_article:10,pagetitle:5,longtitle:3,content:1,description:1,introtext:1`
                    ]]
    
    Страница результатов:
    [[!mSearch2_custom?returnIds=`1`&limit=`0`&queryVar=`search`&fields=`Data.article:10,article:10,tv_article:10,pagetitle:5,longtitle:3,content:1,description:1,introtext:1` &toPlaceholder=`search.resources`]]
                            [[!+search.resources:is=``:then=`<style>.products_count, .pagination, .sorting, .views { display: none; }</style>`]]
                            [[!+search.resources:is=``:then=`По Вашему запросу ничего не найдено. Попробуйте изменить поисковый запрос.`:else=`
                                [[!pdoPage?
                                    &element=`msProducts`
                                    &parents=`2`
                                    &resources=`[[+search.resources]]`
                    
                                    &limit=`[[!#get.limit:is=``:then=`24`:else=`[[!#get.limit]]`]]`
                                    &sortby=`[[!#get.sortby:is=`price`:then=`Data.price`:else=`pagetitle`]]`
                                    &sortdir=`[[!#get.sortdir:is=`desc`:then=`desc`:else=`asc`]]`
                                    &wrapIfEmpty=`0`
                                    &includeContent=`1`
                                    &includeThumbs=`catalog`
                                    &includeTVs=`tovar_height,tovar_length,tovar_voltage,tovar_width,tovar_character,price_type`
                                    &tplWrapper=`[[!#get.view:is=`list`:then=`CATALOG_LIST_WRAPPER`:else=`CATALOG_GRID_WRAPPER`]]`
                                    &tpl=`[[!#get.view:is=`list`:then=`PRODUCT_LIST_ITEM_TPL`:else=`PRODUCT_ITEM_TPL`]]`
    
    
                                    &tplPage=`@INLINE <a href="[[+href]]">[[+pageNo]]</a>`
                                    &tplPageWrapper=`@INLINE [[+prev]][[+pages]][[+next]]`
                                    &tplPageActive=`@INLINE <a href="[[+href]]" class="active">[[+pageNo]]</a></li>`
                                    &tplPagePrev=`@INLINE <a href="[[+href]]" class="prev">‹</a>`
                                    &tplPageNext=`@INLINE <a href="[[+href]]" class="next">›</a>`
                                    &tplPageSkip=`@INLINE <span>...</span>`
                                    &tplPagePrevEmpty=`@INLINE `
                                    &tplPageNextEmpty=`@INLINE `
                                ]]
                            `]]
                            <div class="products_count left">[[!#get.page:isnot=``:then=`[[!#get.page]]`:else=`1`]] страница из [[+pageCount]]</div>
    

    Авторизация

    через сервис Loginza:


    Шаблоны MODX

    1 2 Дальше »

    Объектная
    модель
    MODX