<commit_before><?php

class SearchLib extends TikiLib {
	function SearchLib($db) {
		# this is probably uneeded now
		if (!$db) {
			die ("Invalid db object passed to SearchLib constructor");
		}

		$this->db = $db;
	}

	function register_search($words) {
		$words = addslashes($words);

		$words = preg_split("/\s/", $words);

		foreach ($words as $word) {
			$word = trim($word);

			$cant = $this->getOne("select count(*) from tiki_search_stats where term='$word'");

			if ($cant) {
				$query = "update tiki_search_stats set hits=hits+1 where term='$word'";
			} else {
				$query = "insert into tiki_search_stats(term,hits) values('$word',1)";
			}

			$result = $this->query($query);
		}
	}

	function _find($h, $words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		$words = trim($words);

		$sql = sprintf(
			'SELECT %s AS name, LEFT(%s, 240) AS data, %s AS hits, %s AS lastModif, %s	AS pageName', $h['name'], $h['data'],
			$h['hits'], $h['lastModif'], $h['pageName']);
		$id = $h['id'];

		for ($i = 0; $i < count($id); ++$i)
			$sql .= ',' . $id[$i] . ' AS id' . ($i + 1);

		if (count($id) < 2)
			$sql .= ',1 AS id2';

		$sql2 = ' FROM ' . $h['from'] . ' WHERE 1';
		$search_fields = array($h['name']);

		if ($h['data'] && $h['name'] != $h['data'])
			array_push($search_fields, $h['data']);

		$orderby = (isset($h['orderby']) ? $h['orderby'] : $h['hits']);

		if ($fulltext) {
			if (count($h['search']))
				if (!preg_match('/\./', $h['search'][0]))
					$search_fields = array_merge($search_fields, $h['search']);

			$qwords = $this->db->quote($words);
			$sqlft = 'MATCH(' . join(',', $search_fields). ') AGAINST (' . $qwords . ')';
			$sql2 .= ' AND ' . $sqlft . ' >= 0';
			$sql .= ', ' . $sqlft . ' AS relevance';
			$orderby = 'relevance desc, ' . $orderby;
		#		if (count($h['search'])) {
		#	    	$sqlft = ' MATCH(' . join(',', $h['search']) . ') AGAINST (' . $qwords . ')';
		#	    	$sql2 .= ' OR ' . $sqlft . ' > 0';
		#	    	$sql .= ', ' . $sqlft . ' AS score2';
		#		}
		} else if ($words) {
			$sql .= ', -1 AS relevance';

			$vwords = split(' ', $words);

			foreach ($vwords as $aword) {
				//$aword = $this->db->quote('[[:<:]]' . strtoupper($aword) . '[[:>:]]');
				$aword = $this->db->quote('.*' . strtoupper($aword). '.*');

				$sql2 .= ' AND (';

				for ($i = 0; $i < count($search_fields); ++$i) {
					if ($i)
						$sql2 .= ' OR ';

					$sql2 .= 'UPPER(' . $search_fields[$i] . ') REGEXP ' . $aword;
				}

				$sql2 .= ')';
			}
		} else {
			$sql .= ', -1 AS relevance';
		}

		$cant = $this->getOne('SELECT COUNT(*)' . $sql2);

		if (!$cant) {
			return array(
				'data' => array(),
				'cant' => 0
			);
		}

		$sql .= $sql2 . ' ORDER BY ' . $orderby . ' DESC LIMIT ' . $offset . ',' . $maxRecords;
		$result = $this->query($sql);
		$ret = array();

		while ($res = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
			$href = sprintf($h['href'], $res['id1'], $res['id2']);

			$ret[] = array(
				'pageName' => $res["pageName"],
				'data' => $res["data"],
				'hits' => $res["hits"],
				'lastModif' => $res["lastModif"],
				'href' => $href,
				'relevance' => round($res["relevance"], 3),
			);
		}

		return array(
			'data' => $ret,
			'cant' => $cant
		);
	}

	function find_wikis($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_wikis = array(
			'from' => 'tiki_pages',
			'name' => 'pageName',
			'data' => 'data',
			'hits' => 'pageRank',
			'lastModif' => 'lastModif',
			'href' => 'tiki-index.php?page=%s',
			'id' => array('pageName'),
			'pageName' => 'pageName',
			'search' => array(),
		);

		// that pagerank re-calculation was speed handicap (timex30)
		//$this->pageRank();
		return $this->_find($search_wikis, $words, $offset, $maxRecords, $fulltext);
	}

	function find_galleries($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_galleries = array(
			'from' => 'tiki_galleries',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-browse_gallery.php?galleryId=%d',
			'id' => array('galleryId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_galleries, $words, $offset, $maxRecords, $fulltext);
	}

	function find_faqs($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_faqs = array(
			'from' => 'tiki_faqs f LEFT JOIN tiki_faq_questions q ON q.faqId = f.faqId',
			'name' => 'f.title',
			'data' => 'f.description',
			'hits' => 'f.hits',
			'lastModif' => 'f.created',
			'href' => 'tiki-view_faq.php?faqId=%d',
			'id' => array('f.faqId'),
			'pageName' => 'CONCAT(f.title, ": ", q.question)',
			'search' => array(
			'q.question',
			'q.answer'
		),
		);

		return $this->_find($search_faqs, $words, $offset, $maxRecords, $fulltext);
	}

	function find_directory($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_directory = array(
			'from' => 'tiki_directory_sites',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-directory_redirect.php?siteId=%d',
			'id' => array('siteId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_directory, $words, $offset, $maxRecords, $fulltext);
	}

	function find_images($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_images = array(
			'from' => 'tiki_images',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'created',
			'href' => 'tiki-browse_image.php?imageId=%d',
			'id' => array('imageId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_images, $words, $offset, $maxRecords, $fulltext);
	}

	function find_forums($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_forums = array(
			'from' => 'tiki_comments c LEFT JOIN tiki_forums f ON md5(concat("forum",f.forumId))=c.object',
			'name' => 'c.title',
			'data' => 'c.data',
			'hits' => 'c.hits',
			'lastModif' => 'c.commentDate',
			'href' => 'tiki-view_forum_thread.php?forumId=%d&amp;comments_parentId=%d',
			'id' => array(
			'f.forumId',
			'c.threadId'
		),
			'pageName' => 'CONCAT(name, ": ", title)',
			'search' => array(),
		);

		return $this->_find($search_forums, $words, $offset, $maxRecords, $fulltext);
	}

	function find_files($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_files = array(
			'from' => 'tiki_files',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'downloads',
			'lastModif' => 'created',
			'href' => 'tiki-download_file.php?fileId=%d',
			'id' => array('fileId'),
			'pageName' => 'filename',
			'search' => array(),
		);

		return $this->_find($search_files, $words, $offset, $maxRecords, $fulltext);
	}

	function find_blogs($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_blogs = array(
			'from' => 'tiki_blogs',
			'name' => 'title',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-view_blog.php?blogId=%d',
			'id' => array('blogId'),
			'pageName' => 'title',
			'search' => array(),
		);

		return $this->_find($search_blogs, $words, $offset, $maxRecords, $fulltext);
	}

	function find_articles($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_articles = array(
			'from' => 'tiki_articles',
			'name' => 'title',
			'data' => 'heading',
			'hits' => 'reads',
			'lastModif' => 'publishDate',
			'href' => 'tiki-read_article.php?articleId=%d',
			'id' => array('articleId'),
			'pageName' => 'title',
			'search' => array('body'),
		);

		return $this->_find($search_articles, $words, $offset, $maxRecords, $fulltext);
	}

	function find_posts($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		global $user;

		$site_timezone_shortname = $this->get_site_timezone_shortname();
		$site_time_difference = $this->get_site_time_difference($user);
		# TODO localize?
		$pagename = "CONCAT(b.title, ' [', " . "DATE_FORMAT(FROM_UNIXTIME(p.created + $site_time_difference), " . "'%M %d %Y %h:%i'), ' $site_timezone_shortname', '] by: ', p.user)";

		$search_posts = array(
			'from' => 'tiki_blog_posts p LEFT JOIN tiki_blogs b ON b.blogId = p.blogId',
			'name' => 'p.data', # to simplify the logic, won't hurt performance
			'data' => 'p.data',
			'hits' => '1',
			'orderby' => 'p.created',
			'lastModif' => 'p.created',
			# TODO double up %'s from urlencode() return value
			'href' => 'tiki-view_blog.php?blogId=%d&amp;find=' . urlencode($words),
			'id' => array('p.blogId'),
			'pageName' => $pagename,
			'search' => array(),
		);

		return $this->_find($search_posts, $words, $offset, $maxRecords, $fulltext);
	}

	function find_pages($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		$data = array();

		$cant = 0;
		$rv = $this->find_wikis($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Wiki');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_galleries($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Gallery');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_faqs($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('FAQ');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_images($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Image');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_forums($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Forum');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_files($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('File');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_blogs($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Blog');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_articles($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Article');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_posts($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Post');

			array_push($data, $a);
		}

		$cant += $rv['cant'];

		$rv = $this->find_directory($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Directory');

			array_push($data, $a);
		}

		$cant += $rv['cant'];

		if ($fulltext) {
			function find_pages_cmp($a, $b) {
				return ($a['relevance'] > $b['relevance']) ? -1 : (($a['relevance'] < $b['relevance']) ? 1 : 0);
			}

			usort($data, 'find_pages_cmp');
		/*	# this doesn't work, because 'hits' aren't the same across different sections, right?
	} else {
	  function find_pages_cmp ($a, $b) {
		return ($a['hits'] > $b['hits']) ? -1 : (($a['hits'] < $b['hits']) ? 1 : 0);
	  }

	  usort ($data, 'find_pages_cmp');
*/
		}

		return array(
			'data' => $data,
			'cant' => $cant,
		);
	}
} # class SearchLib

?><commit_msg>oops: forget to put in branch Head - search with accent in request<commit_after><?php

class SearchLib extends TikiLib {
	function SearchLib($db) {
		# this is probably uneeded now
		if (!$db) {
			die ("Invalid db object passed to SearchLib constructor");
		}

		$this->db = $db;
	}

	function register_search($words) {
		$words = addslashes($words);

		$words = preg_split("/\s/", $words);

		foreach ($words as $word) {
			$word = trim($word);

			$cant = $this->getOne("select count(*) from tiki_search_stats where term='$word'");

			if ($cant) {
				$query = "update tiki_search_stats set hits=hits+1 where term='$word'";
			} else {
				$query = "insert into tiki_search_stats(term,hits) values('$word',1)";
			}

			$result = $this->query($query);
		}
	}

	function _find($h, $words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		$words = trim($words);

		$sql = sprintf(
			'SELECT %s AS name, LEFT(%s, 240) AS data, %s AS hits, %s AS lastModif, %s	AS pageName', $h['name'], $h['data'],
			$h['hits'], $h['lastModif'], $h['pageName']);
		$id = $h['id'];

		for ($i = 0; $i < count($id); ++$i)
			$sql .= ',' . $id[$i] . ' AS id' . ($i + 1);

		if (count($id) < 2)
			$sql .= ',1 AS id2';

		$sql2 = ' FROM ' . $h['from'] . ' WHERE 1';
		$search_fields = array($h['name']);

		if ($h['data'] && $h['name'] != $h['data'])
			array_push($search_fields, $h['data']);

		$orderby = (isset($h['orderby']) ? $h['orderby'] : $h['hits']);

		if ($fulltext) {
			if (count($h['search']))
				if (!preg_match('/\./', $h['search'][0]))
					$search_fields = array_merge($search_fields, $h['search']);

			$qwords = $this->db->quote($words);
			$sqlft = 'MATCH(' . join(',', $search_fields). ') AGAINST (' . $qwords . ')';
			$sql2 .= ' AND ' . $sqlft . ' >= 0';
			$sql .= ', ' . $sqlft . ' AS relevance';
			$orderby = 'relevance desc, ' . $orderby;
		#		if (count($h['search'])) {
		#	    	$sqlft = ' MATCH(' . join(',', $h['search']) . ') AGAINST (' . $qwords . ')';
		#	    	$sql2 .= ' OR ' . $sqlft . ' > 0';
		#	    	$sql .= ', ' . $sqlft . ' AS score2';
		#		}
		} else if ($words) {
			$sql .= ', -1 AS relevance';

			$vwords = split(' ', $words);

			foreach ($vwords as $aword) {
				//$aword = $this->db->quote('[[:<:]]' . strtoupper($aword) . '[[:>:]]');
				$aword = $this->db->quote('.*' . strtoupper($aword). '.*');

				$sql2 .= ' AND (';

				for ($i = 0; $i < count($search_fields); ++$i) {
					if ($i)
						$sql2 .= ' OR ';

					$sql2 .= 'UPPER(' . $search_fields[$i] . ') REGEXP ' . $aword;
				}

				$sql2 .= ')';
			}
		} else {
			$sql .= ', -1 AS relevance';
		}

		$cant = $this->getOne('SELECT COUNT(*)' . $sql2);

		if (!$cant) {
			return array(
				'data' => array(),
				'cant' => 0
			);
		}

		$sql .= $sql2 . ' ORDER BY ' . $orderby . ' DESC LIMIT ' . $offset . ',' . $maxRecords;
		$result = $this->query($sql);
		$ret = array();

		while ($res = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
			$href = sprintf(urldecode($h['href']), $res['id1'], $res['id2']);

			$ret[] = array(
				'pageName' => $res["pageName"],
				'data' => $res["data"],
				'hits' => $res["hits"],
				'lastModif' => $res["lastModif"],
				'href' => $href,
				'relevance' => round($res["relevance"], 3),
			);
		}

		return array(
			'data' => $ret,
			'cant' => $cant
		);
	}

	function find_wikis($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_wikis = array(
			'from' => 'tiki_pages',
			'name' => 'pageName',
			'data' => 'data',
			'hits' => 'pageRank',
			'lastModif' => 'lastModif',
			'href' => 'tiki-index.php?page=%s',
			'id' => array('pageName'),
			'pageName' => 'pageName',
			'search' => array(),
		);

		// that pagerank re-calculation was speed handicap (timex30)
		//$this->pageRank();
		return $this->_find($search_wikis, $words, $offset, $maxRecords, $fulltext);
	}

	function find_galleries($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_galleries = array(
			'from' => 'tiki_galleries',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-browse_gallery.php?galleryId=%d',
			'id' => array('galleryId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_galleries, $words, $offset, $maxRecords, $fulltext);
	}

	function find_faqs($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_faqs = array(
			'from' => 'tiki_faqs f LEFT JOIN tiki_faq_questions q ON q.faqId = f.faqId',
			'name' => 'f.title',
			'data' => 'f.description',
			'hits' => 'f.hits',
			'lastModif' => 'f.created',
			'href' => 'tiki-view_faq.php?faqId=%d',
			'id' => array('f.faqId'),
			'pageName' => 'CONCAT(f.title, ": ", q.question)',
			'search' => array(
			'q.question',
			'q.answer'
		),
		);

		return $this->_find($search_faqs, $words, $offset, $maxRecords, $fulltext);
	}

	function find_directory($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_directory = array(
			'from' => 'tiki_directory_sites',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-directory_redirect.php?siteId=%d',
			'id' => array('siteId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_directory, $words, $offset, $maxRecords, $fulltext);
	}

	function find_images($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_images = array(
			'from' => 'tiki_images',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'created',
			'href' => 'tiki-browse_image.php?imageId=%d',
			'id' => array('imageId'),
			'pageName' => 'name',
			'search' => array(),
		);

		return $this->_find($search_images, $words, $offset, $maxRecords, $fulltext);
	}

	function find_forums($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_forums = array(
			'from' => 'tiki_comments c LEFT JOIN tiki_forums f ON md5(concat("forum",f.forumId))=c.object',
			'name' => 'c.title',
			'data' => 'c.data',
			'hits' => 'c.hits',
			'lastModif' => 'c.commentDate',
			'href' => 'tiki-view_forum_thread.php?forumId=%d&amp;comments_parentId=%d',
			'id' => array(
			'f.forumId',
			'c.threadId'
		),
			'pageName' => 'CONCAT(name, ": ", title)',
			'search' => array(),
		);

		return $this->_find($search_forums, $words, $offset, $maxRecords, $fulltext);
	}

	function find_files($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_files = array(
			'from' => 'tiki_files',
			'name' => 'name',
			'data' => 'description',
			'hits' => 'downloads',
			'lastModif' => 'created',
			'href' => 'tiki-download_file.php?fileId=%d',
			'id' => array('fileId'),
			'pageName' => 'filename',
			'search' => array(),
		);

		return $this->_find($search_files, $words, $offset, $maxRecords, $fulltext);
	}

	function find_blogs($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_blogs = array(
			'from' => 'tiki_blogs',
			'name' => 'title',
			'data' => 'description',
			'hits' => 'hits',
			'lastModif' => 'lastModif',
			'href' => 'tiki-view_blog.php?blogId=%d',
			'id' => array('blogId'),
			'pageName' => 'title',
			'search' => array(),
		);

		return $this->_find($search_blogs, $words, $offset, $maxRecords, $fulltext);
	}

	function find_articles($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_articles = array(
			'from' => 'tiki_articles',
			'name' => 'title',
			'data' => 'heading',
			'hits' => 'reads',
			'lastModif' => 'publishDate',
			'href' => 'tiki-read_article.php?articleId=%d',
			'id' => array('articleId'),
			'pageName' => 'title',
			'search' => array('body'),
		);

		return $this->_find($search_articles, $words, $offset, $maxRecords, $fulltext);
	}

	function find_posts($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		global $user;

		$site_timezone_shortname = $this->get_site_timezone_shortname();
		$site_time_difference = $this->get_site_time_difference($user);
		# TODO localize?
		$pagename = "CONCAT(b.title, ' [', " . "DATE_FORMAT(FROM_UNIXTIME(p.created + $site_time_difference), " . "'%M %d %Y %h:%i'), ' $site_timezone_shortname', '] by: ', p.user)";

		$search_posts = array(
			'from' => 'tiki_blog_posts p LEFT JOIN tiki_blogs b ON b.blogId = p.blogId',
			'name' => 'p.data', # to simplify the logic, won't hurt performance
			'data' => 'p.data',
			'hits' => '1',
			'orderby' => 'p.created',
			'lastModif' => 'p.created',
			# TODO double up %'s from urlencode() return value
			'href' => 'tiki-view_blog.php?blogId=%d&amp;find=' . urlencode($words),
			'id' => array('p.blogId'),
			'pageName' => $pagename,
			'search' => array(),
		);

		return $this->_find($search_posts, $words, $offset, $maxRecords, $fulltext);
	}

	function find_pages($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		$data = array();

		$cant = 0;
		$rv = $this->find_wikis($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Wiki');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_galleries($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Gallery');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_faqs($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('FAQ');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_images($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Image');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_forums($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Forum');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_files($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('File');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_blogs($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Blog');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_articles($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Article');

			array_push($data, $a);
		}

		$cant += $rv['cant'];
		$rv = $this->find_posts($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Post');

			array_push($data, $a);
		}

		$cant += $rv['cant'];

		$rv = $this->find_directory($words, $offset, $maxRecords, $fulltext);

		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Directory');

			array_push($data, $a);
		}

		$cant += $rv['cant'];

		if ($fulltext) {
			function find_pages_cmp($a, $b) {
				return ($a['relevance'] > $b['relevance']) ? -1 : (($a['relevance'] < $b['relevance']) ? 1 : 0);
			}

			usort($data, 'find_pages_cmp');
		/*	# this doesn't work, because 'hits' aren't the same across different sections, right?
	} else {
	  function find_pages_cmp ($a, $b) {
		return ($a['hits'] > $b['hits']) ? -1 : (($a['hits'] < $b['hits']) ? 1 : 0);
	  }

	  usort ($data, 'find_pages_cmp');
*/
		}

		return array(
			'data' => $data,
			'cant' => $cant,
		);
	}
} # class SearchLib

?>
{'fraction_non_alphanumeric': 0.24227300586638648, 'fraction_numerical': 0.005778828473863935, 'mean_word_length': 3.5631242508989214, 'pattern_counts': {'":': 4, '<': 17, '<?xml version=': 0, '>': 291, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3258961', 'n_tokens_mistral': 10269, 'n_tokens_neox': 8918, 'n_words': 1835}