<?php

/**
 * AVE.cms - Модуль Поиск
 *
 * @package AVE.cms
 * @subpackage module_Search
 * @filesource
 */

class Search
{

/**
 *	СВОЙСТВА
 */

	var $_limit           = 15;
	var $_adminlimit      = 1000;
	var $_highlight       = 1;
	var $_allowed_tags    = '';
	var $_disallowed_tags = '';
	var $_search_string   = '';
	var $_stem_words      = array();
	var $_like_t = "(doc.document_title LIKE '%%%s%%')";
	var $_not_like_t = "(doc.document_title LIKE '%%%s%%')";
	var $_like = "(field_value LIKE '%%%s%%')";
	var $_not_like = "(field_value NOT LIKE '%%%s%%')";

/**
 *	ВНУТРЕННИЕ МЕТОДЫ
 */

	function _searchSpecialchars($string)
	{
		$string = stripslashes($string);
		$string = str_replace ( '"', '&quot;', $string );
		$string = addslashes($string);
		$string = urldecode($string);

		return $string;
	}

	function _create_string_like(&$word, $key, $type='')
	{
		global $stemmer;

		$type_search = (isset($_REQUEST['ts']) ? $_REQUEST['ts'] : 0);

		switch ($type)
		{
			case '-':
				$word = $stemmer->stem_word(mb_substr($word, 1));
				if (isset($type_search) && $type_search != 0){
					$format_string = $this->_not_like_t;
				} else {
					$format_string = $this->_not_like;
				}
				break;

			case '+':
				$word = $stemmer->stem_word(mb_substr($word, 1));
				if (isset($type_search) && $type_search != 0){
					$format_string = $this->_like_t;
				} else {
					$format_string = $this->_like;
				}
				$this->_stem_words[] = $word;
				break;

			default:
				$word = $stemmer->stem_word($word);
				if (isset($type_search) && $type_search != 0){
					$format_string = $this->_like_t;
				} else {
					$format_string = $this->_like;
				}
				$this->_stem_words[] = $word;
				break;
		}

		$word = sprintf($format_string, $word, $this->_searchSpecialchars($word));
	}

/**
 *	ВНЕШНИЕ МЕТОДЫ
 */

	function searchResultGet($tpl_dir, $lang_file)
	{
		global $AVE_DB, $AVE_Template;

		$AVE_Template->config_load($lang_file);

		define('MODULE_TITLE', $AVE_Template->get_config_vars('SEARCH_RESULTS'));

		$stem_words = array();

		$tmp = preg_replace('/[^\x20-\xFF]|[><!?.,;=-]/', ' ', $_REQUEST['query']);

		$this->_search_string = trim(preg_replace('/  +/', ' ', stripslashes($tmp)));

		if (mb_strlen($this->_search_string) > 2)
		{
			// экранирование для LIKE
			$tmp = str_replace('\\', '\\\\', $this->_search_string);
			$tmp = addcslashes(addslashes($tmp), '%_');
			$tmp = preg_replace('/  +/', ' ', $tmp);
			$tmp = preg_split('/\s+/', $tmp);

			$where = '';

			if (sizeof($tmp))
			{
				$_tmp = preg_grep('/^[^\+|-].{3,}/', $tmp);
				array_walk($_tmp, array(&$this,'_create_string_like'));
				// +
				$__tmp = preg_grep('/^\+.{3,}/', $tmp);
				array_walk($__tmp, array(&$this,'_create_string_like'), '+');
				// -
				$___tmp = preg_grep('/^-.{3,}/', $tmp);
				array_walk($___tmp, array(&$this,'_create_string_like'), '-');

				if (!empty($_tmp))
				{
					$where = 'WHERE (' . implode((isset($_REQUEST['or']) && 1 == $_REQUEST['or']) ? ' OR ' : ' AND ', $_tmp) . ')';
					if (!empty($__tmp))
					{
						$where .= ' AND ' . implode(' AND ', array_merge($__tmp, $___tmp));
					}
				}
				elseif (!empty($__tmp))
				{
					$where = 'WHERE ' . implode(' AND ', array_merge($__tmp, $___tmp));
				}
			}

			$num = 0;
			if ($where != '')
			{

				$limit = $this->_limit;
				$start = get_current_page() * $limit - $limit;

				$query_feld = $AVE_DB->Query("
					SELECT SQL_CALC_FOUND_ROWS
						document_id,
						field_value,
						doc.document_title,
						doc.document_published,
						doc.document_in_search
					FROM " . PREFIX . "_document_fields
					LEFT JOIN " . PREFIX . "_documents AS doc
						ON document_id = doc.Id
					LEFT JOIN " . PREFIX . "_rubric_fields AS rub
						ON rubric_field_id = rub.Id
					" . $where . "
					AND doc.document_in_search = '1'
					AND doc.document_status = '1'
					AND rub.rubric_field_search = '1'
					GROUP BY doc.Id
					ORDER BY doc.document_published DESC
					LIMIT " . $start . "," . $limit
				);

				$num = $AVE_DB->NumAllRows();
				$pages = @ceil($num / $limit);

				$sw  = addslashes(mb_strtolower($this->_search_string));

				$exist = $AVE_DB->Query("
					SELECT 1
					FROM " . PREFIX . "_module_search
					WHERE search_query = '" . $sw . "'
					LIMIT 1
				")->NumRows();

				if ($exist)
				{
					$AVE_DB->Query("
						UPDATE " . PREFIX . "_module_search
						SET
							search_found = '" . (int)$num . "',
							search_count = search_count+1
						WHERE search_query = '" . $sw . "'
					");
				}
				else
				{
					$AVE_DB->Query("
						INSERT
						INTO " . PREFIX . "_module_search
						SET
							Id = '',
							search_found = '" . (int)$num . "',
							search_query = '" . $sw . "',
							search_count = 1
					");
				}
				if ($num > $limit)
				{
					$page_nav = '<a class="page_nav" href="index.php?module=search&amp;query='
						. urlencode($this->_search_string)
						. ($type_search ? '&amp;ts=1' : '')
						. ($_REQUEST['or'] ? '&amp;or=1' : '')
						. '&amp;page={s}">{t}</a>';
					$page_nav = get_pagination($pages, 'page', $page_nav);
				}
				$AVE_Template->assign('q_navi', $page_nav);
			}

			if ($num > 0)
			{
				$modul_search_results = array();

				array_walk($this->_stem_words, create_function('&$val','$val=preg_quote(stripslashes(stripslashes(str_replace("\"","&quot;",$val))),"/");'));
				$regex_snapshot  = '/.{0,100}[^\s]*' . implode('[^\s]*.{0,100}|.{0,100}[^\s]*', $this->_stem_words) . '[^\s]*.{0,100}/iu';
				$regex_highlight = '/[^\s]*' . implode('[^\s]*|[^\s]*', $this->_stem_words) . '[^\s]*/iu';

				$doctime = get_settings('use_doctime') ? ("AND document_published <= " . time() . " AND (document_expire = 0 OR document_expire >= " . time() . ")") : '';

				while ($row_feld = $query_feld->FetchRow())
				{
					$sql = $AVE_DB->Query("
						SELECT
							Id,
							document_title,
							document_alias,
							document_published,
							rubric_id
						FROM " . PREFIX . "_documents
						WHERE Id = '" . $row_feld->document_id . "'
						AND document_deleted = '0'
						AND document_status = '1'
						" . $doctime
					);
					while ($row = $sql->FetchRow())
					{
						$row->Text = $row_feld->field_value;
						$row->Text = strip_tags($row->Text, $this->_allowed_tags);

						$fo = array();

						preg_match($regex_snapshot, $row->Text, $fo);

						$row->Text = $type_search ? '' : '';

						while (list($key, $val) = @each($fo))
						{
							$row->Text .= $val . ($type_search ? '' : '');
						}

						if (1 == $this->_highlight && !empty($this->_stem_words))
						{
							$row->Text = @preg_replace($regex_highlight, "<strong class=\"mod_search_highlight\">$0</strong>", $row->Text);
						}
						$row->document_alias = rewrite_link('index.php?id=' . $row->Id . '&amp;doc=' . (empty($row->document_alias) ? prepare_url($row->document_title) : $row->document_alias));

						$modul_search_results[$row->Id] = $row;
					}
				}
				
				$AVE_Template->assign('searchresults', $modul_search_results);
			}
			else
			{
				$AVE_Template->assign('no_results', 1);
			}
		}
		else
		{
			$AVE_Template->assign('no_results', 1);
		}

		if (!defined('MODULE_CONTENT'))
		{
			$AVE_Template->assign('inc_path', BASE_DIR . '/modules/search/templates');
			define('MODULE_CONTENT', $AVE_Template->fetch($tpl_dir . 'results.tpl'));
		}
	}

	function searchWordsShow($tpl_dir)
	{
		global $AVE_DB, $AVE_Template;

		$limit = $this->_adminlimit;

		$sort      = ' ORDER BY search_query ASC';
		$sort_navi = '';

		if (!empty($_REQUEST['sort']))
		{
			switch ($_REQUEST['sort'])
			{
				case 'begriff_desc' :
					$sort      = ' ORDER BY search_query DESC';
					$sort_navi = '&amp;sort=begriff_desc';
					break;

				case 'begriff_asc' :
					$sort      = ' ORDER BY search_query ASC';
					$sort_navi = '&amp;sort=begriff_asc';
					break;

				case 'anzahl_desc' :
					$sort      = ' ORDER BY search_count DESC';
					$sort_navi = '&amp;sort=anzahl_desc';
					break;

				case 'anzahl_asc' :
					$sort      = ' ORDER BY search_count ASC';
					$sort_navi = '&amp;sort=anzahl_asc';
					break;

				case 'gefunden_desc' :
					$sort      = ' ORDER BY search_found DESC';
					$sort_navi = '&amp;sort=gefunden_desc';
					break;

				case 'gefunden_asc' :
					$sort      = ' ORDER BY search_found ASC';
					$sort_navi = '&amp;sort=gefunden_asc';
					break;
			}
		}

		$num = $AVE_DB->Query("
			SELECT Id
			FROM " . PREFIX . "_module_search
			" . $sort
		)->NumRows();

		$seiten = ceil($num / $limit);
		$start = get_current_page() * $limit - $limit;

		$items = array();
		$sql = $AVE_DB->Query("
			SELECT *
			FROM " . PREFIX . "_module_search
			" . $sort . "
			LIMIT " . $start . "," . $limit
		);
		while ($row = $sql->FetchRow())
		{
			array_push($items,$row);
		}

		if ($num > $limit)
		{
			$page_nav = " <a class=\"pnav\" href=\"index.php?do=modules&action=modedit&mod=search&moduleaction=1" . $sort_navi . "&cp=" . SESSION . "&page={s}\">{t}</a> ";
			$page_nav = get_pagination($seiten, 'page', $page_nav);
			$AVE_Template->assign('page_nav', $page_nav);
		}

		$AVE_Template->assign('items', $items);
		$AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'words.tpl'));
	}

	function searchWordsDelete()
	{
		global $AVE_DB;

		$AVE_DB->Query("DELETE FROM " . PREFIX . "_module_search");

		header('Location:index.php?do=modules&action=modedit&mod=search&moduleaction=1&cp=' . SESSION);
		exit;
	}
}
?>