Как убрать виртуальные копии из результатов поиска

Материал из Umicms
Перейти к:навигация, поиск

Актуально для версии 2.9.5 Начиная с версии 17 84049 в модуле "Поиск" добавлена настройка "Индексировать виртуальные копии".

Задача

Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Необходимо написать кастомный макрос, пример оного дан ниже.

Решение

%custom copy_free_search()%

Этот макрос полностью идентичен по всем параметрам и шаблонам системного макросу %search search_do()%, за исключением имени метода и того, что макрос, если он находит виртуальные копии, то в результате оставляет только одну копия, причем исходную.

Для применения этого макроса скопируйте код макроса в файл /classes/modules/custom.php.

Код макроса

public function copy_free_search($template = "default", $search_string = "", $search_types = "", $search_branches = "", $per_page = 0) {
	list(
		$template_block, $template_line, $template_empty_result, $template_line_quant
	) = self::loadTemplates("search/".$template,
		"search_block", "search_block_line", "search_empty_result", "search_block_line_quant"
	);

	if (!$search_string) $search_string = (string) getRequest('search_string');

	$block_arr = Array();
	$block_arr['last_search_string'] = $search_string;

	$search_string = urldecode($search_string);
	$search_string = htmlspecialchars($search_string);
	$search_string = str_replace(". ", " ", $search_string);
	$search_string = trim($search_string, " \t\r\n%");
	$search_string = str_replace(array('"', "'"), "", $search_string);

	$orMode = (bool) getRequest('search-or-mode');

	if (!$search_string) return search::insert_form($template);

	$arr_search_by_rels = array();
	if (!$search_branches) $search_branches = (string) getRequest('search_branches');
	$search_branches = trim(rawurldecode($search_branches));
	if (strlen($search_branches)) {
		$arr_branches = preg_split("/[\s,]+/", $search_branches);
		foreach ($arr_branches as $i_branch => $v_branch) {
			$arr_branches[$i_branch] = def_module::analyzeRequiredPath($v_branch);
		}
		$arr_branches = array_map('intval', $arr_branches);
		$arr_search_by_rels = array_merge($arr_search_by_rels, $arr_branches);
		$o_selection = new umiSelection;
		$o_selection->addHierarchyFilter($arr_branches, 100, true);
		$o_result = umiSelectionsParser::runSelection($o_selection);
		$sz = sizeof($o_result);
		for ($i = 0; $i < $sz; $i++) $arr_search_by_rels[] = intval($o_result[$i]);
	}

	if (!$search_types) $search_types = (string) getRequest('search_types');
	$search_types = rawurldecode($search_types);
	if (strlen($search_types)) {
		$search_types = preg_split("/[\s,]+/", $search_types);
		$search_types = array_map('intval', $search_types);
	}

	$lines = Array();
	$result = searchModel::getInstance()->runSearch($search_string, $search_types, $arr_search_by_rels, $orMode);
	$p = (int) getRequest('p');
	$total = sizeof($result);
	
	if($total != 0){
	
		if (!$per_page) $per_page = intval(getRequest('per_page'));
		if (!$per_page) $per_page = $this->per_page;
		
		$hierarchy_col = umiHierarchy::getInstance();
		
		foreach($result as $value){
			$objects_ids[] = $hierarchy_col->getElement($value)->getObjectId();
		}
		
		$objects_ids = array_unique($objects_ids);				
		unset($result);
		
		foreach($objects_ids as $value){
			$objects = $hierarchy_col->getObjectInstances($value);
			$result[] = $objects[0];
		}
		
		$result = array_slice($result, $per_page * $p, $per_page);

		$i = $per_page * $p;

		foreach($result as $num => $element_id) {
			$line_arr = Array();

			$element = $hierarchy_col->getElement($element_id);

			if(!$element) continue;

			$line_arr['void:num'] = ++$i;
			$line_arr['attribute:id'] = $element_id;
			$line_arr['attribute:name'] = $element->getName();
			$line_arr['attribute:link'] = $hierarchy_col->getPathById($element_id);
			$line_arr['xlink:href'] = "upage://" . $element_id;
			$line_arr['node:context'] = searchModel::getInstance()->getContext($element_id, $search_string);
			$line_arr['void:quant'] = ($num < count($result)-1? def_module::parseTemplate($template_line_quant, array()) : "");
			$lines[] = def_module::parseTemplate($template_line, $line_arr, $element_id);

			def_module::pushEditable(false, false, $element_id);

			$hierarchy_col->unloadElement($element_id);
		}

		$block_arr['subnodes:items'] = $block_arr['void:lines'] = $lines;
		$block_arr['total'] = $total;
		$block_arr['per_page'] = $per_page;

		return def_module::parseTemplate($template_block, $block_arr);
	}else{
		return def_module::parseTemplate($template_empty_result, $block_arr);
	}
}

Дополнительно

А для того, чтобы дублирование контента, вызываемое использованием виртуальных копий, не портило SEO, примените решение из статьи: Как_избежать_дублирования_контента_при_использовании_виртуальных_копий