neues modul :: sdlSearch

Gesperrt
kummer
Beiträge: 2423
Registriert: Do 6. Mai 2004, 09:17
Wohnort: Bern, Schweiz
Kontaktdaten:

neues modul :: sdlSearch

Beitrag von kummer » Do 16. Nov 2006, 11:50

für einen kunden habe ich eine suche erstellen dürfen, welche mandantenübergreifend sucht. die mandanten können bei der initialisierung der klasse angegeben werden (zeile 5). gesucht wird in allen online gestellten artikeln. die suche lässt alle von mysql in der volltextsuche vorgesehenen auszeichnungen zu (vgl. http://dev.mysql.com/doc/refman/5.1/de/ ... olean.html).

das modul benutzt das gleiche template wie die standard-suche. alles was man machen muss, ist ein weiteres modul anlegen und bei der suchausgabe statt des standard-moduls das sdlSearch auszuwählen.

die ganze suche sollte auch etwas performanter sein, als die standard-suche, da insgesamt nur drei selects auf die datenbank abgesetzt werden müssen, welche bei meinem kunden bei 7 mandanten und einer grossen seitenzahl ca. 100 ms benötigte. aber die einschätzung überlasse ich euch.

das modul hat primär eine bedingung. es läuft nur ab mysql in der version 4.1.X. darunter ist die volltextsuche nicht verfügbar.

viel spass!

Code: Alles auswählen

<?php

cInclude('includes', 'functions.api.string.php');

$suche = new sdlSearch($cfg, $sess, $client, $lang, $db, array(1, 4, 7, 10, 12, 13, 14));

class sdlSearch {

	var $client, $lang, $db, $sess, $cfg, $mandanten;

	function sdlSearch($cfg, & $sess, $client, $lang, & $db, $mandaten) {

		global $tpl, $idart, $idcat;

		$this->client = $client;
		$this->lang = $lang;
		$this->db = $db;
		$this->sess = $sess;
		$this->cfg = $cfg;
		$this->mandanten = implode(", ", $mandaten);

		/*
		* Initialisierung des TemplateObjektes
		*/
		if (!is_object($tpl)) {
			$tpl = new Template;
		}
		$tpl->reset();

		/*
		 * Mehrsprachigkeitseinstellungen
		 */
		$sYourSearchFor = mi18n("Ihre Suche nach");
		$sMore = mi18n("weiter");

		/*
		 * Suchbegriff einlesen und vorbearbeiten
		 */
		if (isset ($_GET['searchterm'])) {
			$searchterm = urldecode(strip_tags(htmlentities(stripslashes($_GET['searchterm']))));
		}
		elseif (isset ($_POST['searchterm'])) {
			$searchterm = urldecode(strip_tags(htmlentities(stripslashes($_POST['searchterm']))));
		}

		$action = $this->sess->url('front_content.php');

		if (strlen(trim($searchterm)) > 0) {
			/*
			 * Suche absetzen
			 */
			$searchString = $this->specialUrlEncode($searchterm);

			$this->db->query("" .
			"SELECT name FROM {$this->cfg['tab']['lang']} WHERE idlang = {$this->lang}");

			if ($this->db->next_record()) {
				$sprache = $this->db->f('name');
			} else {
				$sprache = 'Deutsch';
			}

			$this->db->query("" .
			"SELECT " .
			"	count(*) AS anzahl, " .
			"	MAX(score) AS maxscore " .
			"FROM (" .
			"	SELECT " .
			"		artlang.idart, " .
			"		catart.idcat, " .
			"		art.idclient, " .
			"		MATCH(con1.value) AGAINST ('{$searchString}' IN BOOLEAN MODE) AS score " .
			"	FROM {$this->cfg['tab']['content']} AS con1 " .
			"	LEFT JOIN {$this->cfg['tab']['art_lang']} AS artlang ON con1.idartlang = artlang.idartlang " .
			"	LEFT JOIN {$this->cfg['tab']['art']} AS art ON artlang.idart = art.idart " .
			"	LEFT JOIN {$this->cfg['tab']['cat_art']} AS catart ON art.idart = catart.idart " .
			"	LEFT JOIN {$this->cfg['tab']['lang']} AS lang ON artlang.idlang = lang.idlang " .
			"	WHERE artlang.online = 1 " .
			"	AND MATCH(con1.value) AGAINST ('{$searchString}' IN BOOLEAN MODE) > 0 " .
			"	AND art.idclient IN ({$this->mandanten}) " .
			"	AND lang.name = '{$sprache}' " .
			"	GROUP BY " .
			"		artlang.idart, " .
			"		catart.idcat, " .
			"		art.idclient" .
			"	) AS sub1 " .
			"");

			if ($this->db->next_record()) {
				$resultsCount = $this->db->f('anzahl');
				$maxScore = $this->db->f('maxscore');
			}

			$tpl->set('s', 'result_page', mi18n("Ergebnis-Seite") . ':');

			/*
			 * Nachricht zusammensetzen
			 */
			$message = $sYourSearchFor . " '" . htmlspecialchars(strip_tags($searchterm)) . "' " . mi18n("hat $$$ Treffer ergeben") . ":";
			$message = str_replace('$$$', $resultsCount, $message);
			$tpl->set('s', 'MESSAGE', $message);

			/*
			 * Anzahl Resultate je Seite
			 */
			$number_of_results = 10;

			/*
			 * Aktuelle Resulateseite ermitteln
			 */
			if (isset ($_GET['page']) AND is_numeric($_GET['page']) AND $_GET['page'] > 0) {
				$page = $_GET['page'];
			} else {
				$page = 1;
			}

			/*
			 * Gesamtzahl Seiten auf 10 beschränken
			 */
			$maxPages = (ceil($resultsCount / $number_of_results) > 10) ? (10) : (ceil($resultsCount / $number_of_results));

			/*
			 * Links zu folgenden Resultateseiten erstellen
			 */
			for ($i = 1; $i <= $maxPages; $i++) {
				$nextlink = $sess->url("front_content.php?idcat={$idcat}&idart={$idart}&searchterm={$searchterm}&page={$i}");
				if ($i == $page) {
					$nextlinks .= '<nobr>&nbsp<strong>' . $i . '</strong>&nbsp;</nobr>';
				} else {
					$nextlinks .= '<nobr>&nbsp;<a href="' . $nextlink . '" title="' . $i . '. ' . mi18n("Ergebnisseite anzeigen") . '">' . $i . '</a>&nbsp;</nobr>';
				}
			}
			$tpl->set('s', 'PAGES', $nextlinks);

			/*
			 * Link zur nächsten Resultateseite erstellen
			 */
			if ($page < $maxPages) {
				$n = $page +1;
				$next = $sess->url("front_content.php?idcat={$idcat}&idart={$idart}&searchterm={$searchterm}&page={$n}");
				$nextpage .= '&nbsp;<a href="' . $next . '" title="' . mi18n("nächste Ergebnisseite anzeigen") . '">' . mi18n("vor") . ' ></a>';
				$tpl->set('s', 'NEXT', $nextpage);
			} else {
				$tpl->set('s', 'NEXT', '');
			}

			/*
			 * Link zur vorherigen Resultateseite erstellen
			 */
			if ($page > 1) {
				$p = $page -1;
				$pre = $sess->url("front_content.php?idcat={$idcat}&idart={$idart}&searchterm={$searchterm}&page={$p}");
				$prevpage .= '<a href="' . $pre . '" title="' . mi18n("vorherige Ergebnisseite anzeigen") . '">< ' . mi18n("zurück") . '</a>&nbsp;';
				$tpl->set('s', 'PREV', $prevpage);
			} else {
				$tpl->set('s', 'PREV', '');
				$p = 0;
			}

			$lowerLimit = $p * $number_of_results;

			$this->db->query("" .
			"SELECT DISTINCT " .
			"	artlang.idart AS idart, " .
			"	art.idclient AS idclient, " .
			"	catart.idcat AS idcat, " .
			"	artlang.published AS published, " .
			"	title.value AS title, " .
			"	subtitle.value AS subtitle, " .
			"	text.value AS text, " .
			"	MATCH(con1.value) AGAINST ('{$searchString}' IN BOOLEAN MODE) AS score, " .
			"	client.name AS client, " .
			"	client.htmlpath AS path " .
			"FROM {$this->cfg['tab']['content']} AS con1 " .
			"LEFT JOIN {$this->cfg['tab']['art_lang']} AS artlang ON con1.idartlang = artlang.idartlang " .
			"LEFT JOIN {$this->cfg['tab']['content']} AS title ON artlang.idartlang = title.idartlang AND title.idtype = 1 AND title.typeid = 1 " .
			"LEFT JOIN {$this->cfg['tab']['content']} AS subtitle ON artlang.idartlang = subtitle.idartlang AND subtitle.idtype = 1 AND title.typeid = 2 " .
			"LEFT JOIN {$this->cfg['tab']['content']} AS text ON artlang.idartlang = text.idartlang AND text.idtype = 2 AND text.typeid = 1 " .
			"LEFT JOIN {$this->cfg['tab']['art']} AS art ON artlang.idart = art.idart " .
			"LEFT JOIN {$this->cfg['tab']['cat_art']} AS catart ON art.idart = catart.idart " .
			"LEFT JOIN {$this->cfg['tab']['clients']} AS client ON art.idclient = client.idclient " .
			"LEFT JOIN {$this->cfg['tab']['lang']} AS lang ON artlang.idlang = lang.idlang " .
			"WHERE artlang.online = 1 " .
			"AND MATCH(con1.value) AGAINST ('{$searchString}' IN BOOLEAN MODE) > 0 " .
			"AND art.idclient IN ({$this->mandanten}) " .
			"AND lang.name = '{$sprache}' " .
			"ORDER BY score DESC " .
			"LIMIT {$lowerLimit}, {$number_of_results}");

			/*
			 * Resultate fetchen
			 */
			$i = 1;
			while ($this->db->next_record()) {

				$idart = $this->db->f('idart');
				$idcat = $this->db->f('idcat');
				$href = $this->db->f('path') . "front_content.php?idart={$idart}&idcat={$idcat}";
				$headline = $this->emphasizeWords($this->stripTagsAndTrim($this->db->f('title'), 200), $searchString);
				$text = $this->emphasizeWords($this->stripTagsAndTrim($this->db->f('text'), 200), $searchString);
				$subheadline = $this->emphasizeWords($this->stripTagsAndTrim($this->db->f('subtitle'), 200), $searchString);
				$published = $this->db->f('published');
				$clientName = $this->db->f('client');
				$similarity = $this->db->f('score') * 100 / $maxScore;

				$tpl->set('d', 'more', $sMore);
				$tpl->set('d', 'HREF', $href);
				$tpl->set('d', 'TITLE', mi18n("Link zu Suchergebnis") . ' ' . $i);
				$tpl->set('d', 'NUM', $i + (($page -1) * $number_of_results));
				$tpl->set('d', 'CATNAME', $headline);
				$tpl->set('d', 'HEADLINE', $text);
				$tpl->set('d', 'SUBHEADLINE', $subheadline);
				$tpl->set('d', 'SIMILARITY', $similarity);
				$tpl->set('d', 'TARGET', '_self');
				$tpl->set('d', 'PUB_DATE', $published);
				$tpl->set('d', 'CLIENTNAME', $clientName);
				$tpl->next();
				$i++;
			}

			if ($resultsCount == 0) {
				/*
				 * Die Suche ergabe keine Resultate
				 */
				$tpl->set('s', 'MESSAGE', $sYourSearchFor." '".htmlspecialchars(strip_tags($searchterm))."' ".mi18n("hat leider keine Treffer ergeben").".");
				$tpl->set('s', 'NEXT', '');
				$tpl->set('s', 'PREV', '');
				$tpl->set('s', 'PAGES', '');
				$tpl->set('s', 'result_page', '');
			}

			$tpl->generate('templates/suchausgabe.html');
		}
	}

	function specialUrlEncode($searchwords) {

		$returnValue = array ();

		$words = explode(" ", $searchwords);
		foreach ($words as $word) {
			$returnValue[] = urlencode($word);
		}

		return implode(" ", $returnValue);
	}

	function stripTagsAndTrim($text, $length) {

		$tmp = strip_tags(str_replace("&nbsp;", " ", urldecode($text)));

		if (strlen($tmp) < $length) {
			return $tmp;
		}

		return capiStrTrimAfterWord($tmp, $length)."...";
	}

	function emphasizeWords($text, $searchTerm) {

		$tmp = str_replace("*", " ", $searchTerm);
		$tmp = str_replace("+", " ", $tmp);
		$tmp = str_replace("-", " ", $tmp);
		$tmp = str_replace("(", " ", $tmp);
		$tmp = str_replace(")", " ", $tmp);
		$tmp = str_replace("<", " ", $tmp);
		$tmp = str_replace(">", " ", $tmp);

		$terms = explode(" ", $tmp);

		foreach ($terms as $term) {
			preg_match("/$term/i", $text, $match);
			if (isset($match[0])) {
				$pattern = $match[0];
				if ($pattern != 'strong') {
					$text = str_replace($pattern, "<strong>$pattern</strong>", $text);
				}
			}
		}

		return $text;
	}
}
?>
EDIT: durch einen fehler im modul wurde die auszeichnung der suchbegriffe nahezu endlos wiederholt. in obigem code ist der fehler korrigiert.
aitsu.org :: schnell - flexibel - komfortabel :: Version 2.2.0 (since June 22, 2011) (jetzt mit dual license GPL/kommerziell)

Gesperrt