[evolvis-commits] r9337: implemented a new search engine architect?==?UTF-8?Q?ure↵

mirabilos at evolvis.org mirabilos at evolvis.org
Thu Feb 24 17:23:16 CET 2011


Author: mirabilos
Date: 2011-02-24 17:23:15 +0100 (Thu, 24 Feb 2011)
New Revision: 9337

Added:
   trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants.php
   trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants/
   trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants/search.php
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ArtifactHtmlSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ForumHtmlSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/HtmlSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/PeopleHtmlSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectHtmlSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectRssSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/RssSearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SearchRenderer.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SkillHtmlSearchRenderer.class
Modified:
   trunk/gforge_base/evolvisforge-5.1/gforge/ChangeLog
   trunk/gforge_base/evolvisforge-5.1/gforge/www/export/rss_utils.inc
   trunk/gforge_base/evolvisforge-5.1/gforge/www/include/Layout.class
   trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/Base.tab
   trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/French.tab
   trunk/gforge_base/evolvisforge-5.1/gforge/www/include/pre.php
   trunk/gforge_base/evolvisforge-5.1/gforge/www/search/index.php
Log:
implemented a new search engine architecture


Modified: trunk/gforge_base/evolvisforge-5.1/gforge/ChangeLog
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/ChangeLog	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/ChangeLog	2011-02-24 16:23:15 UTC (rev 9337)
@@ -1,3 +1,7 @@
+2004-02-09  Guillaume Smet <guillaume-gforge at smet.org>
+
+	* Implemented a new search engine architecture
+
 2004-02-06  Tom Copeland <tom at infoether.com>
 	* Implemented RFE [ #672 ] X people are monitoring this package
 

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants/search.php
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants/search.php	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants/search.php	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,13 @@
+<?php
+
+define('SEARCH__TYPE_IS_ARTIFACT', 'artifact');
+define('SEARCH__TYPE_IS_SOFTWARE', 'soft');
+define('SEARCH__TYPE_IS_FORUM', 'forums');
+define('SEARCH__TYPE_IS_PEOPLE', 'people');
+define('SEARCH__TYPE_IS_SKILL', 'skill');
+define('SEARCH__TYPE_IS_DOCUMENT', 'document');
+define('SEARCH__TYPE_IS_ARTIFACT', 'artifact');
+
+define('SEARCH__DEFAULT_ROWS_PER_PAGE', 25);
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants.php
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants.php	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/include/constants.php	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,6 @@
+<?php
+
+require('common/include/constants/search.php');
+
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class ArtifactSearchQuery extends SearchQuery {
+	
+	/**
+	 * group id
+	 *
+	 * @var int $groupId
+	 */
+	var $groupId;
+	
+	/**
+	 * artifact id
+	 *
+	 * @var int $artifactId
+	 */
+	var $artifactId;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param int $groupId group id
+	 * @param int $artifactId artifact id
+	 */
+	function ArtifactSearchQuery($words, $offset, $isExact, $groupId, $artifactId) {
+		$this->groupId = $groupId;
+		$this->artifactId = $artifactId;
+		
+		$this->SearchQuery($words, $offset, $isExact);
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$sql = 'SELECT DISTINCT ON (a.group_artifact_id,a.artifact_id) a.group_artifact_id,a.artifact_id,a.summary,a.open_date,users.realname '
+			. 'FROM artifact a,users ' 
+			. 'WHERE a.group_artifact_id=\''.$this->artifactId.'\' '
+			. 'AND users.user_id=a.submitted_by '
+			. 'AND (('.$this->getIlikeCondition('a.details', $this->words).') ' 
+			. 'OR ('.$this->getIlikeCondition('a.summary', $this->words).')) '
+			. 'ORDER BY group_artifact_id ASC, artifact_id ASC';
+
+		return $sql;
+	}
+
+	/**
+	 * getSearchByIdQuery - get the sql query built to get the search results when we are looking for an int
+	 *
+	 * @return string sql query to execute
+	 */	
+	function getSearchByIdQuery() {
+		$sql = 'SELECT DISTINCT ON (a.group_artifact_id,a.artifact_id) a.group_artifact_id, a.artifact_id '
+			. 'FROM artifact a ' 
+			. 'WHERE a.group_artifact_id=\''.$this->artifactId.'\' '
+			. 'AND a.artifact_id=\''.$this->searchId.'\'';
+
+		return $sql;
+	}
+	
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class ExportProjectSearchQuery extends SearchQuery {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function ExportProjectSearchQuery($words, $offset, $isExact) {	
+		$this->SearchQuery($words, $offset, $isExact, 200);
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$groupNameCond = $this->getIlikeCondition('group_name', $this->words);
+		$groupDescriptionCond = $this->getIlikeCondition('short_description', $this->words);
+		$groupUnixNameCond = $this->getIlikeCondition('unix_group_name', $this->words);
+		
+		$sql = 'SELECT group_name,unix_group_name,type,groups.group_id, '
+			.'short_description,license,register_time '
+			.'FROM groups '
+			.'WHERE status IN (\'A\', \'H\') '
+			.'AND is_public=\'1\' '
+			.'AND groups.short_description<>\'\' '
+			.'AND (('.$groupNameCond.') OR ('.$groupDescriptionCond.') OR ('.$groupUnixNameCond.'))';
+
+		return $sql;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class ForumSearchQuery extends SearchQuery {
+	
+	/**
+	 * group id
+	 *
+	 * @var int $groupId
+	 */
+	var $groupId;
+	
+	/**
+	 * forum id
+	 *
+	 * @var int $groupId
+	 */
+	var $forumId;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param int $groupId group id
+	 * @param int $forumId forum id
+	 */
+	function ForumSearchQuery($words, $offset, $isExact, $groupId, $forumId) {
+		$this->groupId = $groupId;
+		$this->forumId = $forumId;
+		
+		$this->SearchQuery($words, $offset, $isExact);
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$sql = 'SELECT forum.msg_id, forum.subject, forum.post_date, users.realname '
+			. 'FROM forum,users '
+			. 'WHERE users.user_id=forum.posted_by '
+			. 'AND (('.$this->getIlikeCondition('forum.body', $this->words).') '
+			. 'OR ('.$this->getIlikeCondition('forum.subject', $this->words).')) '
+			. 'AND forum.group_forum_id=\''.$this->forumId.'\' '
+			. 'GROUP BY msg_id, subject, post_date, realname';
+
+		return $sql;
+	}
+	
+	/**
+	 * getSearchByIdQuery - get the sql query built to get the search results when we are looking for an int
+	 *
+	 * @return string sql query to execute
+	 */	
+	function getSearchByIdQuery() {
+		$sql = 'SELECT msg_id '
+			. 'FROM forum '
+			. 'WHERE msg_id=\''.$this->searchId.'\' '
+			. 'AND group_forum_id=\''.$this->forumId.'\'';
+
+		return $sql;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class PeopleSearchQuery extends SearchQuery {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function PeopleSearchQuery($words, $offset, $isExact) {	
+		$this->SearchQuery($words, $offset, $isExact);
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$sql = 'SELECT user_name,user_id,realname ' 
+			. 'FROM users ' 
+			. 'WHERE (('.$this->getIlikeCondition('user_name', $this->words).') ' 
+			. 'OR ('.$this->getIlikeCondition('realname', $this->words).')) ' 
+			. 'AND (status=\'A\') ' 
+			. 'ORDER BY user_name';
+		return $sql;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class ProjectSearchQuery extends SearchQuery {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function ProjectSearchQuery($words, $offset, $isExact) {	
+		$this->SearchQuery($words, $offset, $isExact);
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$groupNameCond = $this->getIlikeCondition('group_name', $this->words);
+		$groupDescriptionCond = $this->getIlikeCondition('short_description', $this->words);
+		$groupUnixNameCond = $this->getIlikeCondition('unix_group_name', $this->words);
+		
+		$sql = 'SELECT group_name, unix_group_name, type, group_id, short_description '
+			.'FROM groups '
+			.'WHERE status IN (\'A\', \'H\') '
+			.'AND is_public=\'1\' '
+			.'AND (('.$groupNameCond.') OR ('.$groupDescriptionCond.') OR ('.$groupUnixNameCond.'))';
+
+		return $sql;
+	}
+	
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,223 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+class SearchQuery extends Error {
+	/**
+	 * the operator between each part of the query. Can be AND or OR.
+	 *
+	 * @var string $operator
+	 */
+	var $operator;	
+	/**
+	 * Number of rows per page
+	 *
+	 * @var int $rowsPerPage
+	 */
+	var $rowsPerPage;
+	/**
+	 * Number of rows we will display on the page
+	 *
+	 * @var int $rowsCount
+	 */
+	var $rowsCount = 0;
+	/**
+	 * Number of rows returned by the query
+	 *
+	 * @var int $rowsTotalCount
+	 */
+	var $rowsTotalCount = 0;
+	/**
+	 * Offset
+	 *
+	 * @var int $offset
+	 */
+	var $offset = 0;
+	/**
+	 * Result handle
+	 *
+	 * @var resource $result
+	 */
+	var $result;
+	/**
+	 * When search by id is enabled, the id to search for
+	 *
+	 * @var int $searchId
+	 */
+	var $searchId = false;
+	/**
+	 * if we want to search for all the words or if only one is sufficient
+	 *
+	 * @var boolean $isExact
+	 */
+	 var $isExact = false;
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one is sufficient
+	 * @param int $rowsPerPage number of rows per page
+	 */
+	function SearchQuery($words, $offset, $isExact, $rowsPerPage = SEARCH__DEFAULT_ROWS_PER_PAGE) {
+		$this->cleanSearchWords($words);
+		
+		$this->rowsPerPage = $rowsPerPage;
+		$this->offset = $offset;
+		$this->isExact = $isExact;
+		$this->operator = $this->getOperator();
+	}
+	
+	/**
+	 * cleanSearchWords - clean the words we are searching for
+	 *
+	 * @param string $words words we are searching for
+	 */
+	function cleanSearchWords($words) {
+		$words = trim($words);
+		if(!$words) {
+			$this->setError('error_criteria_not_specified');
+			return;
+		}
+		if(is_numeric($words) && $this->implementsSearchById()) {
+			$this->searchId = (int) $words;
+		} else {
+			$words = htmlspecialchars($words);
+			$words = preg_replace("/[ \t]+/", ' ', $words);
+			if(strlen($words) < 3) {
+				$this->setError('error_search_minlength');
+				return;
+			}
+			$this->words = explode(' ', quotemeta($words));
+		}
+	}
+	
+	/**
+	 * executeQuery - execute the SQL query to get the results
+	 */ 
+	function executeQuery() {
+		if($this->searchId) {
+			$query = $this->getSearchByIdQuery();
+		} else {
+			$query = $this->getQuery();
+		}
+
+		$this->result = db_query(
+			$query,
+			$this->rowsPerPage + 1,
+			$this->offset,
+			SYS_DB_SEARCH
+		);
+		$this->rowsTotalCount = db_numrows($this->result);
+		$this->rowsCount = min($this->rowsPerPage, $this->rowsTotalCount);
+	}
+	
+	/**
+	 * getQuery - returns the sql query built to get the search results
+	 * This is an abstract method. It _MUST_ be implemented in children classes.
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		return;
+	}
+
+	/**
+	 * getIlikeCondition - build the ILIKE condition of the SQL query for a given field name
+	 *
+	 * @param string $fieldName name of the field in the ILIKE condition
+	 * @return string the condition
+	 */
+	function getIlikeCondition($fieldName) {
+		return $fieldName." ILIKE '%" . implode("%' ".$this->operator." ".$fieldName." ILIKE '%", $this->words) ."%'";
+	}
+	
+	/**
+	 * getOperator - get the operator we have to use in ILIKE condition
+	 *
+	 * @return string AND if it is an exact search, OR otherwise
+	 */
+	function getOperator() {
+		if($this->isExact) {
+			return 'AND';
+		} else {
+			return 'OR';
+		}
+	}
+	
+	/**
+	 * implementsSearchById - check if the current object implements the search by id feature by having a getSearchByIdQuery method
+	 *
+	 * @return boolean true if our object implements search by id, false otherwise.
+	 */
+	function implementsSearchById() {
+		return method_exists($this, 'getSearchByIdQuery');
+	}
+	
+	/**
+	 * getResult - returns the result set
+	 *
+	 * @return resource result set
+	 */
+	function & getResult() {
+		return $this->result;
+	}
+	
+	/**
+	 * getRowsCount - returns number of rows for the current page
+	 *
+	 * @return int rows count for the current page
+	 */
+	function getRowsCount() {
+		return $this->rowsCount;
+	}
+	
+	/**
+	 * getRowsTotalCount - returns total number of rows
+	 *
+	 * @return int rows count
+	 */
+	function getRowsTotalCount() {
+		return $this->rowsTotalCount;
+	}
+	
+	/**
+	 * getOffset - returns the offset
+	 *
+	 * @return int offset
+	 */
+	function getOffset() {
+		return $this->offset;
+	}
+	
+	/**
+	 * getRowsPerPage - returns number of rows per page
+	 *
+	 * @return int number of rows per page
+	 */
+	function getRowsPerPage() {
+		return $this->rowsPerPage;
+	}
+	
+	/**
+	 * getWords - returns the array containing words we are searching for
+	 *
+	 * @return array words we are searching for
+	 */
+	function getWords() {
+		return $this->words;
+	}
+
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('common/search/SearchQuery.class');
+
+class SkillSearchQuery extends SearchQuery {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function SkillSearchQuery($words, $offset, $isExact) {	
+		$this->SearchQuery($words, $offset, $isExact);	
+	}
+
+	/**
+	 * getQuery - get the sql query built to get the search results
+	 *
+	 * @return string sql query to execute
+	 */
+	function getQuery() {
+		$sql = 'SELECT * '
+			. 'FROM skills_data, users, skills_data_types '
+			. 'WHERE (('.$this->getIlikeCondition('skills_data.title', $this->words).') '
+			. 'OR ('.$this->getIlikeCondition('skills_data.keywords', $this->words).')) '
+			. 'AND (skills_data.user_id=users.user_id) '
+			. 'AND (skills_data.type=skills_data_types.type_id) '
+			. 'ORDER BY finish DESC';
+		return $sql;
+	}
+	
+}
+
+?>
\ No newline at end of file

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/export/rss_utils.inc
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/export/rss_utils.inc	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/export/rss_utils.inc	2011-02-24 16:23:15 UTC (rev 9337)
@@ -23,7 +23,7 @@
 function rss_description ($in) {
 	// if description_maxlen is defined, then truncate appropriately
 	// added for netscape rss schema compat
-	if ($GLOBALS['description_maxlen'] &&
+	if (isset($GLOBALS['description_maxlen']) && $GLOBALS['description_maxlen'] &&
 		(strlen($in) > $GLOBALS['description_maxlen'])) {
 		$in = substr($in,0,$GLOBALS['description_maxlen']);
 	}
@@ -54,10 +54,10 @@
                 	$addendum=$callback($row);
                 }
 		print "  <item>\n";
-		print "   <title>".htmlspecialchars($row[group_name])."</title>\n";
-		print "   <link>http://$GLOBALS[sys_default_domain]/projects/$row[unix_group_name]/</link>\n";
+		print "   <title>".htmlspecialchars($row['group_name'])."</title>\n";
+		print "   <link>http://".$GLOBALS['sys_default_domain']."/projects/".$row['unix_group_name']."/</link>\n";
 		print "   <description>";
-		print ereg_replace(" *\r*\n *"," ",rss_description($row[short_description]));
+		print ereg_replace(" *\r*\n *"," ",rss_description($row['short_description']));
                 print $addendum;
 		print "</description>\n";
 		print "  </item>\n";

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/include/Layout.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/include/Layout.class	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/include/Layout.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -705,23 +705,23 @@
 				$ath = new ArtifactTypeHtml($group,$atid);
 				if ($ath && is_object($ath)) {
 				print '
-				<option value="artifact"'.( $type_of_search == 'artifact' ? ' selected="selected"' : '' ).'>'. $ath->getName() .'</option>';
+				<option value="'.SEARCH__TYPE_IS_ARTIFACT.'"'.( $type_of_search == SEARCH__TYPE_IS_ARTIFACT ? ' selected="selected"' : '' ).'>'. $ath->getName() .'</option>';
 				}
 			}
 		} else if ($group_id && $forum_id) {
 			print '
-			<option value="forums"'.( $type_of_search == 'forums' ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','forum').'</OPTION>';
+			<option value="'.SEARCH__TYPE_IS_FORUM.'"'.( $type_of_search == SEARCH__TYPE_IS_FORUM ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','forum').'</option>';
 		} else if ($group_id && $group_project_id) {
 			print '
 			<option value="task"'. ( $type_of_search == 'tasks' ? ' selected="selected"' : '').'>'.$Language->getText('searchbox','task').'</option>';
 		}
 
 		print '
-			<option value="soft"'.( $type_of_search == 'soft' ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','softwaregroup').'</option>';
+			<option value="'.SEARCH__TYPE_IS_SOFTWARE.'"'.( $type_of_search == SEARCH__TYPE_IS_SOFTWARE ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','softwaregroup').'</option>';
 		print '
-			<option value="skill"'.( $type_of_search == 'skill' ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','skill').'</option>';
+			<option value="'.SEARCH__TYPE_IS_SKILL.'"'.( $type_of_search == SEARCH__TYPE_IS_SKILL ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','skill').'</option>';
 		print '
-			<option value="people"'.( $type_of_search == 'people' ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','people').'</option>';
+			<option value="'.SEARCH__TYPE_IS_PEOPLE.'"'.( $type_of_search == SEARCH__TYPE_IS_PEOPLE ? ' selected="selected"' : '' ).'>'.$Language->getText('searchbox','people').'</option>';
 		print '
 			</select></div>';
 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/Base.tab
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/Base.tab	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/Base.tab	2011-02-24 16:23:15 UTC (rev 9337)
@@ -1250,7 +1250,7 @@
 pm	cat_none	None
 pm	category	Category
 pm	date_note		The system will modify your start/end dates if you attempt to create a start date earlier than the end date of any tasks you depend on.
-pm	dependent	Dependend on Task
+pm	dependent	Dependent on Task
 pm	dependent_note			You should choose only tasks which must be completed before this task can start.
 pm	details	Task Details
 pm	end_date	End Date
@@ -1671,7 +1671,7 @@
 project_home	release_notes	Release Notes
 project_home	surveys	surveys
 project_home	title	Project Info
-project_home	tracker_open	$1 open /$2 total
+project_home	tracker_open	<strong>$1</strong> open /<strong>$2</strong> total
 project_home	view_members	View Members
 project_home	view_project_files	View All Project Files
 project_memberlist	developer	Developer
@@ -1785,6 +1785,31 @@
 scm_index	nohistory	This project has no CVS history.
 scm_index	section	Project: $1
 scm_index	title	CVS
+search	artifact_author	Submitted By
+search	artifact_date	Date
+search	artifact_id	#
+search	artifact_summary	Bug Summary
+search	error_criteria_not_specified	Enter Your Search Words Above
+search	error_invalid_search	Error - Invalid search
+search	error_search_minlength	Search must be at least three characters
+search	forum_author	Author
+search	forum_date	Date
+search	forum_thread	Thread
+search	group_name	Group Name
+search	group_description	Description
+search	next_results	Next Results
+search	no_matches_found	No matches found for <em>$1</em>
+search	people_real_name	Real Name
+search	people_user_name	User Name
+search	previous_results	Previous Results
+search	project_search	Project Search
+search	search_results	Search results for <em>$1</em>
+search	skill_from	From
+search	skill_keywords	Keywords
+search	skill_name	Name
+search	skill_title	Title
+search	skill_to	To
+search	skill_type	Type
 search	title	Search
 searchbox	forum	This forum
 searchbox	people	People

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/French.tab
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/French.tab	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/include/languages/French.tab	2011-02-24 16:23:15 UTC (rev 9337)
@@ -1268,7 +1268,7 @@
 pm	priority	Priorité
 pm	section	Projet : $1
 pm	start_date	Date de début
-pm	status	Statut
+pm	status	Etat
 pm	summary	Tâche
 pm	task_id	Numéro d'identification de tâche
 pm	tech_any	Tous
@@ -1372,7 +1372,7 @@
 pm_include_taskhtml	task_history	Historique de tâche
 pm_include_taskhtml	tracker	Traceur
 pm_modtask	add_comment	Ajouter un commentaire
-pm_modtask	assignee	responsable
+pm_modtask	assignee	Responsable
 pm_modtask	original_comment	Commentaire original
 pm_modtask	sort_on	Trier par
 pm_modtask	submitted_by	Demandée par
@@ -1532,7 +1532,7 @@
 project_admin_editrelease	step_3	Etape 3 : Editer les fichiers dans cette version
 project_admin_editrelease	submit_refresh	Soumettre/rafraîchir
 project_admin_editrelease	title	Editer les versions
-project_admin_editrelease	update_refresh	Mis à jour/Rafraîchir
+project_admin_editrelease	update_refresh	Mettre à jour/Rafraîchir
 project_admin_editrelease	upload_change_log	Télécharger les modifications 
 project_admin_editrelease	upload_new_file	Télécharger vers le serveur un nouveau fichier 
 project_admin_editrelease	upload_release_notes	Télécharger les notes 
@@ -1666,7 +1666,7 @@
 project_home	release_notes	Notes
 project_home	surveys	Sondages
 project_home	title	Information sur le projet
-project_home	tracker_open	$1 ouvert(s) sur un total de $2
+project_home	tracker_open	<strong>$1</strong> ouvert(s) sur un total de <strong>$2</strong>
 project_home	view_members	Voir les membres
 project_home	view_project_files	Voir tous les fichiers du projet
 project_memberlist	developer	Développeur
@@ -1779,6 +1779,31 @@
 scm_index	nohistory	Ce projet n'a pas d'historique CVS
 scm_index	section	Projet : $1
 scm_index	title	CVS
+search	artifact_author	Soumis par
+search	artifact_date	Date
+search	artifact_id	#
+search	artifact_summary	Résumé
+search	error_criteria_not_specified	Saisissez les mots à rechercher ci-dessus
+search	error_invalid_search	Erreur - Recherche non valide
+search	error_search_minlength	Le critère de recherche doit compter au moins 3 caractères
+search	forum_author	Auteur
+search	forum_date	Date
+search	forum_thread	Discussion
+search	group_name	Nom du groupe
+search	group_description	Description
+search	next_results	Résultats suivants
+search	no_matches_found	Aucun résultat trouvé pour <em>$1</em>
+search	people_real_name	Nom complet
+search	people_user_name	Nom d'utilisateur
+search	previous_results	Résultats précèdents
+search	project_search	Recherche de logiciel
+search	search_results	Résultats de la recherche de <em>$1</em>
+search	skill_from	Date de début
+search	skill_keywords	Mots-clés
+search	skill_name	Nom
+search	skill_title	Titre
+search	skill_to	Date de fin
+search	skill_type	Type
 search	title	Recherche
 searchbox	forum	Ce forum
 searchbox	people	Personne
@@ -2256,7 +2281,7 @@
 tracker	item_created	Élément créé avec succès
 tracker	item_group	Groupe 
 tracker	no_trackers	Aucun outil de suivi trouvé
-tracker	no_trackers_text	Aucun outil de suivi n'a été défini ou vous ne pouvez pas y accéder.</strong></p><p style="color:red">L'administrateur de ce projet doit préciser les types de données en utilisant la page d'administration $1 admin page $2
+tracker	no_trackers_text	Aucun outil de suivi n'a été défini ou vous ne pouvez pas y accéder.</strong></p><p style="color:red">L'administrateur de ce projet doit préciser les types de données en utilisant la $1 page d'administration $2 .
 tracker	open_date	Date d'ouverture
 tracker	pagetitle	Suivi 
 tracker	please_login	$1 Identifiez-vous $2

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/include/pre.php
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/include/pre.php	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/include/pre.php	2011-02-24 16:23:15 UTC (rev 9337)
@@ -20,6 +20,9 @@
 	require_once('/etc/gforge/custom/pre.php');
 } else {
 
+// get constants used for flags or status
+require('common/include/constants.php');
+
 // Defines all of the Source Forge hosts, databases, etc.
 // This needs to be loaded first because the lines below depend upon it.
 if (is_file('/etc/gforge/local.inc')) {

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ArtifactHtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ArtifactHtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ArtifactHtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/HtmlSearchRenderer.class');
+require_once('common/search/ArtifactSearchQuery.class');
+
+class ArtifactHtmlSearchRenderer extends HtmlSearchRenderer {
+	
+	/**
+	 * group id
+	 *
+	 * @var int $groupId
+	 */
+	var $groupId;
+	
+	/**
+	 * artifact id
+	 *
+	 * @var int $artifactId
+	 */
+	var $artifactId;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param int $groupId group id
+	 * @param int $artifactId artifact id
+	 */
+	function ArtifactHtmlSearchRenderer($words, $offset, $isExact, $groupId, $artifactId) {
+		$this->groupId = $groupId;
+		$this->artifactId = $artifactId;
+		
+		$searchQuery = new ArtifactSearchQuery($words, $offset, $isExact, $groupId, $artifactId);
+		
+		$this->HtmlSearchRenderer(SEARCH__TYPE_IS_ARTIFACT, $words, $isExact, $searchQuery);
+		
+		$this->tableHeaders = array(
+			$this->Language->getText('search', 'artifact_id'),
+			$this->Language->getText('search', 'artifact_summary'),
+			$this->Language->getText('search', 'artifact_author'),
+			$this->Language->getText('search', 'artifact_date')
+		);
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 * artifact search has a specific header
+	 */
+	function writeHeader() {
+		site_project_header(array('title' => $this->Language->getText('search', 'project_search'), 'group' => $this->groupId, 'pagename' => 'search', 'toptab' => 'tracker'));
+		parent::writeHeader();
+	}
+	
+	/**
+	 * getRows - get the html output for result rows
+	 *
+	 * @return string html output
+	 */
+	function getRows() {
+		$rowsCount = $this->searchQuery->getRowsCount();
+		$result =& $this->searchQuery->getResult();
+		$groupId = $this->groupId;
+		$dateFormat = $GLOBALS['sys_datefmt'];
+		
+		$return = '';
+		for($i = 0; $i < $rowsCount; $i++) {
+			$return .= '<tr '. $GLOBALS['HTML']->boxGetAltRowStyle($i) .'>'
+				.'<td>'.db_result($result, $i, 'artifact_id').'</td>'
+				.'<td><a href="/tracker/?group_id='.$groupId.'&atid='
+				. db_result($result, $i, 'group_artifact_id') 
+				. '&func=detail&aid='
+				. db_result($result, $i, 'artifact_id').'"> '
+				. html_image('ic/msg.png', '10', '12', array('border'=>'0'))
+				. ' '.db_result($result, $i, 'summary').'</a></td>'
+				. '<td>'.db_result($result, $i, 'realname')."</td>"
+				. '<td>'.date($dateFormat, db_result($result, $i, 'open_date')).'</td></tr>';
+		}
+		return $return;
+	}
+	
+	/**
+	 * getPreviousResultsUrl - get the url to go to see the previous results
+	 *
+	 * @return string url to previous results page
+	 */
+	function getPreviousResultsUrl() {
+		return parent::getPreviousResultsUrl().'&group_id='.$this->groupId.'&atid='.$this->artifactId;
+	}
+	
+	/**
+	 * getNextResultsUrl - get the url to go to see the next results
+	 *
+	 * @return string url to next results page
+	 */
+	function getNextResultsUrl() {
+		return parent::getNextResultsUrl().'&group_id='.$this->groupId.'&atid='.$this->artifactId;
+	}
+	
+	/**
+	 * redirectToResult - redirect the user  directly to the result when there is only one matching result
+	 */
+	function redirectToResult() {
+		header('Location: /tracker/?group_id='.$this->groupId.'&atid='.$this->artifactId.'&func=detail&aid='.$this->getResultId('artifact_id'));
+		exit();
+	}
+	
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ForumHtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ForumHtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ForumHtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/HtmlSearchRenderer.class');
+require_once('common/search/ForumSearchQuery.class');
+
+class ForumHtmlSearchRenderer extends HtmlSearchRenderer {
+	
+	/**
+	 * group id
+	 *
+	 * @var int $groupId
+	 */
+	var $groupId;
+	
+	/**
+	 * forum id
+	 *
+	 * @var int $groupId
+	 */
+	var $forumId;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param int $groupId group id
+	 * @param int $forumId forum id
+	 */
+	function ForumHtmlSearchRenderer($words, $offset, $isExact, $groupId, $forumId) {
+		$this->groupId = $groupId;
+		$this->forumId = $forumId;
+		
+		$searchQuery = new ForumSearchQuery($words, $offset, $isExact, $groupId, $forumId);
+		
+		$this->HtmlSearchRenderer(SEARCH__TYPE_IS_FORUM, $words, $isExact, $searchQuery);
+		
+		$this->tableHeaders = array(
+			$this->Language->getText('search', 'forum_thread'),
+			$this->Language->getText('search', 'forum_author'),
+			$this->Language->getText('search', 'forum_date')
+		);
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 */
+	function writeHeader() {
+		site_project_header(array('title' => $this->Language->getText('search', 'project_search'), 'group' => $this->groupId, 'pagename' => 'search', 'toptab' => 'forums'));
+		parent::writeHeader();
+	}
+	
+	/**
+	 * getRows - get the html output for result rows
+	 *
+	 * @return string html output
+	 */
+	function getRows() {
+		$rowsCount = $this->searchQuery->getRowsCount();
+		$result =& $this->searchQuery->getResult();
+		$dateFormat = $GLOBALS['sys_datefmt'];
+		
+		$return = '';
+		for($i = 0; $i < $rowsCount; $i++) {
+			$return .= '<tr '. $GLOBALS['HTML']->boxGetAltRowStyle($i) .'><td width="50%"><a href="/forum/message.php?msg_id='
+				. db_result($result, $i, 'msg_id').'">'
+				. html_image('ic/msg.png', '10', '12', array('border' => '0'))
+				. ' '.db_result($result, $i, 'subject').'</a></td>'
+				. '<td width="30%">'.db_result($result, $i, 'realname').'</td>'
+				. '<td width="20%">'.date($dateFormat, db_result($result, $i, 'post_date')).'</td></tr>';
+		}
+		return $return;
+	}
+
+	/**
+	 * getPreviousResultsUrl - get the url to go to see the previous results
+	 *
+	 * @return string url to previous results page
+	 */
+	function getPreviousResultsUrl() {
+		return parent::getPreviousResultsUrl().'&group_id='.$this->groupId.'&forum_id='.$this->forumId;
+	}
+	
+	/**
+	 * getNextResultsUrl - get the url to go to see the next results
+	 *
+	 * @return string url to next results page
+	 */
+	function getNextResultsUrl() {
+		return parent::getNextResultsUrl().'&group_id='.$this->groupId.'&forum_id='.$this->forumId;
+	}
+
+	/**
+	 * redirectToResult - redirect the user  directly to the result when there is only one matching result
+	 */
+	function redirectToResult() {
+		header('Location: /forum/message.php?msg_id='.$this->getResultId('msg_id'));
+		exit();
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/HtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/HtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/HtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,215 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/SearchRenderer.class');
+
+class HtmlSearchRenderer extends SearchRenderer {
+
+	/**
+	 * Localization BaseLanguage object
+	 *
+	 * @var object $Language
+	 */
+	var $Language;
+	
+	/**
+	 * Headers of the HTML results table
+	 *
+	 * @var array $tableHeaders
+	 */
+	var $tableHeaders = array();
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $typeOfSearch type of the search (Software, Forum, People and so on)
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param object $searchQuery SearchQuery instance
+	 */
+	function HtmlSearchRenderer($typeOfSearch, $words, $isExact, $searchQuery) {
+		global $Language;
+		$this->Language =& $GLOBALS['Language'];
+		
+		$this->SearchRenderer($typeOfSearch, $words, $isExact, $searchQuery);
+	}
+
+	/**
+	 * flush - flush the html output
+	 */
+	function flush() {
+		$searchQuery =& $this->searchQuery;
+		if($searchQuery->isError()) {
+			$this->writeHeader();
+			echo '<h2>'.$this->Language->getText('search', $searchQuery->getErrorMessage()).'</h2>';
+			$this->writeFooter();
+		} else {
+			$searchQuery->executeQuery();
+			if($searchQuery->getResult() && ($searchQuery->getRowsTotalCount() == 1 && $searchQuery->getOffset() == 0) && $this->implementsRedirectToResult()) {
+				$this->redirectToResult();
+			} else {
+				$this->writeHeader();
+				$this->writeBody();
+				$this->writeFooter();
+			}
+		}
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 */
+	function writeHeader() {
+		echo '<div align="center">';
+		echo $GLOBALS['HTML']->searchBox();
+		echo '</div>';
+	}
+
+	/**
+	 * writeBody - write the body
+	 */
+	function writeBody() {
+		echo $this->writeResults();
+	}
+
+	/**
+	 * writeFooter - write the footer
+	 */
+	function writeFooter() {
+		$GLOBALS['HTML']->footer(array());
+	}
+	
+	/**
+	 * getResults - get the html output which will display the search results
+	 *
+	 * @return string html output
+	 */
+	function writeResults() {
+		$searchQuery =& $this->searchQuery;
+		$query =& $this->query;
+		
+		$html = '';
+		
+		if(!$searchQuery->getResult() || $searchQuery->getRowsCount() < 1) {
+			$html .= '<h2>'.$this->Language->getText('search', 'no_matches_found', array(htmlspecialchars($query['words']))).'</h2>';
+			$html .= db_error();
+		} else {
+			$html .= '<h3>'.$this->Language->getText('search', 'search_results', array(htmlspecialchars($query['words']))).'</h3>';
+		
+			$html .= $GLOBALS['HTML']->listTableTop($this->tableHeaders);
+			$html .= $this->getRows();
+			$html .= $GLOBALS['HTML']->listTableBottom();
+		}
+		
+		if($searchQuery->getRowsCount() > 0 && ($searchQuery->getRowsTotalCount() > $searchQuery->getRowsCount() || $searchQuery->getOffset() != 0 )) {
+			$html .= $this->getNavigationPanel();
+		}
+		
+		return $html;
+	}
+
+	/**
+	 * getNavigationPanel - get the html output for the navigation panel
+	 *
+	 * @return string html output
+	 */ 
+	function getNavigationPanel() {
+		$searchQuery =& $this->searchQuery;
+		
+		$html = '';
+		$html .= '<br />';
+		$html .= '<table style="background-color:'.$GLOBALS['HTML']->COLOR_LTBACK1.'" width="100%" cellpadding="5" cellspacing="0">';
+		$html .= '<tr>';
+		$html .= '<td>';
+		if ($searchQuery->getOffset() != 0) {
+			$html .= '<a href="'.$this->getPreviousResultsUrl().'" style="text-decoration: none; font-weight:bold;">'
+				. html_image('t2.png', '15', '15', array('border'=>'0','align'=>'middle'))
+				. ' '.$this->Language->getText('search', 'previous_results').'</a>';
+		} else {
+			$html .= ' ';
+		}
+		$html .= '</td><td align="right">';
+		if ($searchQuery->getRowsTotalCount() > $searchQuery->getRowsCount()) {
+			$html .= '<a href="'.$this->getNextResultsUrl().'" style="text-decoration: none; font-weight:bold;">'
+				.$this->Language->getText('search', 'next_results').' '
+				. html_image('t.png', '15', '15', array('border'=>'0','align'=>'middle')) . '</a>';
+		} else {
+			$html .= ' ';
+		}
+		$html .= '</td></tr>';
+		$html .= '</table>';
+		return $html;
+	}
+	
+	/**
+	 * getPreviousResultsUrl - get the url to go to see the previous results
+	 *
+	 * @return string url to previous results page
+	 */
+	function getPreviousResultsUrl() {
+		$offset = $this->searchQuery->getOffset() - $this->searchQuery->getRowsPerPage();
+		$query =& $this->query;
+		
+		$url = '/search/?type='.$query['typeOfSearch'].'&exact='.$query['isExact'].'&q='.urlencode($query['words']);
+		if($offset > 0) {
+			$url .= '&offset='.$offset;
+		}
+		return $url;
+	}
+	
+	/**
+	 * getNextResultsUrl - get the url to go to see the next results
+	 *
+	 * @return string url to next results page
+	 */
+	function getNextResultsUrl() {
+		$query =& $this->query;
+		return '/search/?type='.$query['typeOfSearch'].'&exact='.$query['isExact'].'&q='.urlencode($query['words']).'&offset='.($this->searchQuery->getOffset() + $this->searchQuery->getRowsPerPage());
+	}
+
+	/**
+	 * highlightTargetWords - highlight the words we are looking for
+	 *
+	 * @param string $text text
+	 * @return string text with keywords highlighted
+	 */
+	function highlightTargetWords($text) {
+		if (empty($text)) {
+			return ' ';
+		}
+		$regexp = implode($this->searchQuery->getWords(), '|');
+		return preg_replace('/('.str_replace('/', '\/', $regexp).')/i','<span style="background-color:pink">\1</span>', $text);
+	}
+
+	/**
+	 * implementsRedirectToResult - check if the current object implements the redirect to result feature by having a redirectToResult method
+	 *
+	 * @return boolean true if our object implements search by id, false otherwise.
+	 */
+	function implementsRedirectToResult() {
+		return method_exists($this, 'redirectToResult');
+	}
+
+	/**
+	 * getResultId - get the field value for the first row of a result handle
+	 *
+	 * @param string $fieldName field name
+	 * @return string value of the field
+	 */
+	function getResultId($fieldName) {
+		return db_result($this->searchQuery->getResult(), 0, $fieldName);
+	}
+
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/PeopleHtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/PeopleHtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/PeopleHtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/HtmlSearchRenderer.class');
+require_once('common/search/PeopleSearchQuery.class');
+
+class PeopleHtmlSearchRenderer extends HtmlSearchRenderer {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function PeopleHtmlSearchRenderer($words, $offset, $isExact) {
+		
+		$searchQuery = new PeopleSearchQuery($words, $offset, $isExact);
+		
+		$this->HtmlSearchRenderer(SEARCH__TYPE_IS_PEOPLE, $words, $isExact, $searchQuery);
+		
+		$this->tableHeaders = array(
+			$this->Language->getText('search', 'people_user_name'),
+			$this->Language->getText('search', 'people_real_name')
+		);
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 */
+	function writeHeader() {
+		$GLOBALS['HTML']->header(array('title'=>$this->Language->getText('search', 'title'), 'pagename'=>'search'));
+		parent::writeHeader();
+	}
+	
+	/**
+	 * getRows - get the html output for result rows
+	 *
+	 * @return string html output
+	 */
+	function getRows() {
+		$rowsCount = $this->searchQuery->getRowsCount();
+		$result =& $this->searchQuery->getResult();
+		
+		$return = '';
+		for($i = 0; $i < $rowsCount; $i++) {
+			$return .= '<tr '. $GLOBALS['HTML']->boxGetAltRowStyle($i) .'>'.
+				'<td width="40%"><a href="/users/'.db_result($result, $i, 'user_name').'/">'.html_image('ic/msg.png', '10', '12', array('border'=>'0')).' '.db_result($result, $i, 'user_name').'</a></td>'.
+				'<td width="60%">'.db_result($result, $i, 'realname').'</td>'.
+				'</tr>';
+		}
+		return $return;
+	}
+	
+	/**
+	 * redirectToResult - redirect the user  directly to the result when there is only one matching result
+	 */
+	function redirectToResult() {
+		header('Location: /users/'.$this->getResultId('user_name').'/');
+		exit();
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectHtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectHtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectHtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/HtmlSearchRenderer.class');
+require_once('common/search/ProjectSearchQuery.class');
+
+class ProjectHtmlSearchRenderer extends HtmlSearchRenderer {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function ProjectHtmlSearchRenderer($words, $offset, $isExact) {
+		
+		$searchQuery = new ProjectSearchQuery($words, $offset, $isExact);
+		
+		$this->HtmlSearchRenderer(SEARCH__TYPE_IS_SOFTWARE, $words, $isExact, $searchQuery);
+		
+		$this->tableHeaders = array(
+			$this->Language->getText('search', 'group_name'),
+			$this->Language->getText('search', 'group_description')
+		);
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 */
+	function writeHeader() {
+		$GLOBALS['HTML']->header(array('title'=>$this->Language->getText('search', 'title'), 'pagename'=>'search'));
+		parent::writeHeader();
+	}
+
+	/**
+	 * getRows - get the html output for result rows
+	 *
+	 * @return string html output
+	 */
+	function getRows() {
+		$rowsCount = $this->searchQuery->getRowsCount();
+		$result =& $this->searchQuery->getResult();
+		
+		$return = '';
+		
+		for($i = 0; $i < $rowsCount; $i++) {
+			if (db_result($result, $i, 'type') == 2) {
+				$what = 'foundry';
+			} else {
+				$what = 'projects';
+			}		
+			$return .= '<tr '.$GLOBALS['HTML']->boxGetAltRowStyle($i).'>'
+				.'<td width="30%"><a href="/'.$what.'/'
+				.db_result($result, $i, 'unix_group_name').'/">'
+				.html_image('ic/msg.png', '10', '12', array('border'=>'0'))
+				.' '.$this->highlightTargetWords(db_result($result, $i, 'group_name')).'</a></td>'
+				.'<td width="70%">'.$this->highlightTargetWords(db_result($result, $i, 'short_description')).'</td></tr>';
+		}
+		
+		return $return;
+	}
+
+	/**
+	 * redirectToResult - redirect the user  directly to the result when there is only one matching result
+	 */
+	function redirectToResult() {
+		header('Location: /'.($this->getResultId('type') == 2 ? 'foundry' : 'projects').'/'.$this->getResultId('unix_group_name').'/');
+		exit();
+	}
+	
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectRssSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectRssSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/ProjectRssSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/RssSearchRenderer.class');
+require_once('common/search/ExportProjectSearchQuery.class');
+
+/**
+ * callback function used during the RSS export
+ *
+ * @param array $dataRow array containing data for the current row
+ * @return string additionnal information added in the RSS document
+ */
+function rssProjectCallback($dataRow) {
+	// $default_trove_cat defined in local.inc
+	$result = db_query('SELECT trove_cat.fullpath '
+		.'FROM trove_group_link, trove_cat '
+		.'WHERE trove_group_link.trove_cat_root='.$GLOBALS['default_trove_cat'].' '
+		.'AND trove_group_link.trove_cat_id=trove_cat.trove_cat_id '
+		.'AND group_id=\''.$dataRow['group_id'].'\'');
+	
+	$return = '';
+	$return .= ' | date registered: '.date('M jS Y', $dataRow['register_time']);
+	$return .= ' | category: '.str_replace(' ', '', implode(',', util_result_column_to_array($result)));
+	$return .= ' | license: '.$dataRow['license'];
+	
+	return $return;
+}
+
+class ProjectRssSearchRenderer extends RssSearchRenderer {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function ProjectRssSearchRenderer($words, $offset, $isExact) {
+		
+		$this->callbackFunction = 'rssProjectCallback';
+		
+		$searchQuery = new ExportProjectSearchQuery($words, $offset, $isExact);
+		
+		$this->RssSearchRenderer(SEARCH__TYPE_IS_SOFTWARE, $words, $isExact, $searchQuery);
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/RssSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/RssSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/RssSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/SearchRenderer.class');
+
+class RssSearchRenderer extends SearchRenderer {
+	
+	/**
+	 * callback function name used during the RSS export
+	 *
+	 * @var string $callbackFunction
+	 */
+	var $callbackFunction = '';
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $typeOfSearch type of the search (Software, Forum, People and so on)
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 * @param object $searchQuery SearchQuery instance
+	 */
+	function RssSearchRenderer($typeOfSearch, $words, $isExact, $searchQuery) {
+		$this->SearchRenderer($typeOfSearch, $words, $isExact, $searchQuery);
+	}
+
+	/**
+	 * flush - flush the RSS output
+	 */
+	function flush() {
+		$searchQuery =& $this->searchQuery;
+
+		header('Content-Type: text/plain');
+		
+		if($searchQuery->isError() || $this->isError()) {
+			echo '<channel></channel>';
+		} else {		
+			$searchQuery->executeQuery();
+			include_once('www/export/rss_utils.inc');
+	
+			rss_dump_project_result_set(
+				$searchQuery->getResult(),
+				'GForge Search Results',
+				'GForge Search Results for "'.$this->query['words'].'"',
+				$this->callbackFunction
+			);
+		}
+		exit();
+	}
+
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,43 @@
+<?php
+
+class SearchRenderer extends Error {
+	
+	/**
+	 * This is not the SQL query but elements from the HTTP query
+	 *
+	 * @var array $query
+	 */
+	var $query = array();
+
+	/**
+	 * This is the searchQuery. It's a SearchQuery instance.
+	 *
+	 * @var object $searchQuery
+	 */
+	var $searchQuery;
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $typeOfSearch type of search
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function SearchRenderer($typeOfSearch, $words, $isExact, $searchQuery) {
+		$this->query['typeOfSearch'] = $typeOfSearch;
+		$this->query['isExact'] = $isExact;
+		$this->query['words'] = $words;
+		
+		$this->searchQuery = $searchQuery;
+	}
+
+	/**
+	 * flush - flush the output
+	 * This is an abstract method. It _MUST_ be implemented in children classes.
+	 */
+	function flush() {}
+	
+}
+
+?>
\ No newline at end of file

Added: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SkillHtmlSearchRenderer.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SkillHtmlSearchRenderer.class	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/include/SkillHtmlSearchRenderer.class	2011-02-24 16:23:15 UTC (rev 9337)
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
+
+require_once('www/search/include/HtmlSearchRenderer.class');
+require_once('common/search/SkillSearchQuery.class');
+
+class SkillHtmlSearchRenderer extends HtmlSearchRenderer {
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $words words we are searching for
+	 * @param int $offset offset
+	 * @param boolean $isExact if we want to search for all the words or if only one matching the query is sufficient
+	 */
+	function SkillHtmlSearchRenderer($words, $offset, $isExact) {
+		
+		$searchQuery = new SkillSearchQuery($words, $offset, $isExact);
+		
+		$this->HtmlSearchRenderer(SEARCH__TYPE_IS_SKILL, $words, $isExact, $searchQuery);
+		
+		$this->tableHeaders = array(
+			$this->Language->getText('search', 'skill_name'),
+			$this->Language->getText('search', 'skill_type'),
+			$this->Language->getText('search', 'skill_title'),
+			$this->Language->getText('search', 'skill_keywords'),
+			$this->Language->getText('search', 'skill_from'),
+			$this->Language->getText('search', 'skill_to')
+		);
+	}
+
+	/**
+	 * writeHeader - write the header of the output
+	 */
+	function writeHeader() {
+		$GLOBALS['HTML']->header(array('title'=>$this->Language->getText('search', 'title'), 'pagename'=>'search'));
+		parent::writeHeader();
+	}
+	
+	/**
+	 * getRows - get the html output for result rows
+	 *
+	 * @return string html output
+	 */
+	function getRows() {
+		$rowsCount = $this->searchQuery->getRowsCount();
+		$result =& $this->searchQuery->getResult();
+		
+		$monthArray = array();
+		for($i = 1; $i <= 12; $i++) {
+			array_push($monthArray,date('M', mktime(0, 0, 0, $i, 10, 1980)));
+		}
+		
+		$return = '';
+		
+		for($i = 0; $i < $rowsCount; $i++) {
+			$start = db_result($result, $i, 'start');
+			$startYear = substr($start, 0, 4);
+			$startMonth = substr($start, 4, 2);
+
+			$finish = db_result($result, $i, 'finish');
+			$finishYear = substr($finish, 0, 4);
+			$finishMonth = substr($finish, 4, 2);
+				
+			$return .= '<tr '.$GLOBALS['HTML']->boxGetAltRowStyle($i).'>'
+				. '<td><a href="/users/'.db_result($result, $i, 'user_name').'/">'
+				. db_result($result, $i, 'realname').'</a></td>'
+				. '<td>'.db_result($result, $i, 'type_name').'</td>'
+				. '<td>'.db_result($result, $i, 'title').'</td>'
+				. '<td>'.db_result($result, $i, 'keywords').'</td>'
+				. '<td>'.$monthArray[$startMonth - 1].' '.$startYear.'</td>'
+				. '<td>'.$monthArray[$finishMonth - 1].' '.$finishYear.'</td>'
+				. '<tr>';
+		}
+		
+		return $return;
+	}
+	
+	/**
+	 * redirectToResult - redirect the user  directly to the result when there is only one matching result
+	 */
+	function redirectToResult() {
+		header('Location: /users/'.$this->getResultId('user_name').'/');
+		exit();
+	}
+}
+
+?>
\ No newline at end of file

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/www/search/index.php
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/www/search/index.php	2011-02-24 16:23:14 UTC (rev 9336)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/www/search/index.php	2011-02-24 16:23:15 UTC (rev 9337)
@@ -1,498 +1,77 @@
 <?php
+
 /**
-  *
-  * SourceForge Search Engine
-  *
-  * Parameters:
-  *   $type ($t)  = one of 'soft'[ware],'people','forums','bugs'
-  *   $words ($q) = target words to search
-  *   $exact	  = 1 for search ing all words (AND), 0 - for any word (OR)
-  *   $rss	  = 1 to export RSS
-  *
-  * SourceForge: Breaking Down the Barriers to Open Source Development
-  * Copyright 1999-2001 (c) VA Linux Systems
-  * http://sourceforge.net
-  *
-  * @version   $Id$
-  *
-  */
+ * GForge Search Engine
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2004 (c) Guillaume Smet / Open Wide
+ *
+ * http://gforge.org
+ *
+ * @version $Id$
+ */
 
 // Support for short aliases
+
 if (!$words) {
-	$words=$q;
+	$words = $q;
 }
 
 if (!$type_of_search) {
-	$type_of_search=$type;
+	$type_of_search = $type;
 }
 if (!$type_of_search) {
-	$type_of_search=$t;
+	$type_of_search = $t;
 }
 if (!$type_of_search) {
-	$type_of_search='soft';
+	$type_of_search = SEARCH__TYPE_IS_SOFTWARE;
 }
 
 require_once('pre.php');
+require_once('common/include/escapingUtils.php');
 require_once('www/tracker/include/ArtifactTypeHtml.class');
 
-function highlight_target_words($word_array,$text) {
-	if (!$text) {
-		return ' ';
-	}
-	$re=implode($word_array,'|');
-	return eregi_replace("($re)",'<span style="background-color:pink">\1</span>',$text);
-}
+$offset = getIntFromGet('offset');
 
-function error_while_in_rss($descr) {
-	header("Content-Type: text/plain");
-	print '<channel></channel>';
-	exit;
-}
-
-if (!$rss) {
-	// If search context is a project, show its toolbar
-	if ($type_of_search == "forums" || $type_of_search == "artifact") {
-		site_project_header(array('title'=>'Project Search','group'=>$group_id,'pagename'=>'search'));
+if($type_of_search == SEARCH__TYPE_IS_SOFTWARE) {
+	if($rss) {
+		require('include/ProjectRssSearchRenderer.class');
+		$searchQuery = new ProjectRssSearchRenderer($words, $offset, $exact);
 	} else {
-		$HTML->header(array('title'=>'Search','pagename'=>'search'));
+		require('include/ProjectHtmlSearchRenderer.class');
+		$searchQuery = new ProjectHtmlSearchRenderer($words, $offset, $exact);
 	}
+} elseif ($type_of_search == SEARCH__TYPE_IS_PEOPLE) {
+	
+	require('include/PeopleHtmlSearchRenderer.class');
+	$searchQuery = new PeopleHtmlSearchRenderer($words, $offset, $exact);
+	
+} elseif ($type_of_search == SEARCH__TYPE_IS_FORUM && $forum_id && $group_id) {
+	
+	require('include/ForumHtmlSearchRenderer.class');
+	$searchQuery = new ForumHtmlSearchRenderer($words, $offset, $exact, $group_id, $forum_id);
 
-	echo "<p align=\"center\">";
-
-	// show search box which will return results on
-	// this very page (default is to open new window)
-	echo $HTML->searchBox();
+} elseif ($type_of_search == SEARCH__TYPE_IS_ARTIFACT && $atid && $group_id) {
+	
+	require('include/ArtifactHtmlSearchRenderer.class');
+	$searchQuery = new ArtifactHtmlSearchRenderer($words, $offset, $exact, $group_id, $atid);
+	
+} elseif ($type_of_search == SEARCH__TYPE_IS_SKILL) {
+	
+	require('include/SkillHtmlSearchRenderer.class');
+	$searchQuery = new SkillHtmlSearchRenderer($words, $offset, $exact);
+	
 }
 
-/*
-	Force them to enter at least three characters
-*/
-
-$words = htmlspecialchars(trim($words));
-$words = ereg_replace("[ \t]+", ' ', $words);
-
-if ($words && (strlen($words) < 3)) {
-	if ($rss) {
-		error_while_in_rss('Search must be at least three characters');
-	} else {
-		echo "<h2>Search must be at least three characters</h2>";
-		$HTML->footer(array());
-		exit;
-	}
-}
-
-if (!$words) {
-	if ($rss) {
-		error_while_in_rss('Search criteria are not specified');
-	} else {
-		echo "<br />Enter Your Search Words Above</p>";
-		$HTML->footer(array());
-		exit;
-	}
-}
-
-$no_rows = 0;
-
-if ($exact) {
-	$crit='AND';
+if(isset($searchQuery)) {
+	$searchQuery->flush();
 } else {
-	$crit='OR';
-}
-
-if (!$offset || $offset < 0) {
-	$offset = 0;
-}
-
-if ($type_of_search == "soft") {
-	/*
-		Query to find software
-	*/
-
-	// If multiple words, separate them and put ILIKE (pgsql's 
-	// case-insensitive LIKE) in between
-	// XXX:SQL: this assumes db understands backslash-quoting
-
-	$array=explode(" ",quotemeta($words));
-	// we need to use double-backslashes in SQL
-	$array_re=explode(" ",addslashes(quotemeta($words)));
-
-	$words1="group_name ILIKE '%" . implode($array,"%' $crit group_name ILIKE '%") ."%'";
-	$words2="short_description ILIKE '%" . implode($array,"%' $crit short_description ILIKE '%") ."%'";
-	$words3="unix_group_name ILIKE '%" . implode($array,"%' $crit unix_group_name ILIKE '%") . "%'";
-
-	if (!$rss) {
-		$sql = "SELECT group_name,unix_group_name,type,group_id,short_description "
-			   ."FROM groups "
-			   ."WHERE status IN ('A','H') "
-			   ."AND is_public='1' "
-			   ."AND (($words1) OR ($words2) OR ($words3))";
-	} else {
-			// If it's RSS export, try to infer additional information, as
-			// shown by Freshmeat search. This means that only projects
-			// categorized under Trove will be exported - that's good, since
-			// cross-site search performed not to get junk results.
-			$sql = "SELECT group_name,unix_group_name,type,groups.group_id, "
-				   ."short_description,license,register_time "
-				   ."FROM groups "
-				   ."WHERE status IN ('A','H') "
-					   ."AND is_public='1' "
-				   ."AND groups.short_description<>'' "
-				   ."AND (($words1) OR ($words2) OR ($words3))";
-	}
-
-	if ($rss) {
-		$limit=200; 
-	} else {
-		$limit=25;
-	}
-	$result = db_query($sql, $limit+1, $offset, SYS_DB_SEARCH);
-	$rows = $rows_returned = db_numrows($result);
-
-	/*
-	 *  Dump RSS rendering of search results, date registered, 
-	 *  include trove categories, license.
-	 */
-	if ($rss) {
-		include_once('www/export/rss_utils.inc');
-		function callback($data_row) {
-						// trove_cat_root=18 - Topic subtree
-			// [CB] now $default_trove_cat defined in local.inc
-			$res = db_query("
-				SELECT trove_cat.fullpath 
-				FROM trove_group_link,trove_cat 
-				WHERE trove_group_link.trove_cat_root=$default_trove_cat 
-				AND trove_group_link.trove_cat_id=trove_cat.trove_cat_id 
-				AND group_id='".$data_row['group_id']."'");
-			$ret = ' | date registered: '.date('M jS Y',$data_row['register_time']);
-			$ret .= ' | category: '.str_replace(' ','',implode(util_result_column_to_array($res),','));
-			return $ret.' | license: '.$data_row['license'];
-		}
-		header("Content-Type: text/plain");
-		rss_dump_project_result_set($result, 'SourceForge Search Results', 
-			'SourceForge Search Results for "' .htmlspecialchars($words).'"', 'callback');
-		exit;
-	}
-
-	/*
-	 *  Else, render HTML
-	 */
-
-	if (!$result || $rows < 1) {
-		$no_rows = 1;
-		echo "<h2>No matches found for $words</h2>";
-		echo db_error();
-//		echo $sql;
-	} else {
-
-		if ( $rows_returned > $limit) {
-			$rows = $limit;
-		}
-
-		echo "<h3>Search results for $words</h3><p>\n\n";
-
-		$title_arr = array();
-		$title_arr[] = 'Group Name';
-		$title_arr[] = 'Description';
-
-		echo $GLOBALS['HTML']->listTableTop($title_arr);
-
-		for ( $i = 0; $i < $rows; $i++ ) {
-			if (db_result($result, $i, 'type') == 2) {
-				$what = 'foundry';
-			} else {
-				$what = 'projects';
-			}
-			
-			print	"<tr ". $HTML->boxGetAltRowStyle($i)."><td><a href=\"/$what/"
-				. db_result($result, $i, 'unix_group_name')."/\">"
-				. html_image("ic/msg.png","10","12",array("border"=>"0"))
-				. highlight_target_words($array,db_result($result, $i, 'group_name'))."</a></td>"
-				. "<td>".highlight_target_words($array,db_result($result,$i,'short_description'))."</td></tr>\n";
-		}
-
-		echo $GLOBALS['HTML']->listTableBottom();
-
-	}
-
-} else if ($type_of_search == "people") {
-	/*
-		Query to find users
-	*/
-
-	// If multiple words, separate them and put ILIKE in between
-	$array=explode(" ",$words);
-	$words1=implode($array,"%' $crit user_name ILIKE '%");
-	$words2=implode($array,"%' $crit realname ILIKE '%");
-
-	$sql =	"SELECT user_name,user_id,realname 
-		FROM users 
-		WHERE ((user_name ILIKE '%$words1%') 
-		OR (realname ILIKE '%$words2%')) 
-		AND (status='A') 
-		ORDER BY user_name";
-
-	$result = db_query($sql, 26, $offset, SYS_DB_SEARCH);
-
-	$rows = $rows_returned = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		$no_rows = 1;
-		echo "<h2>No matches found for $words</h2>";
-		echo db_error();
-	} else {
-
-		if ( $rows_returned > 25) {
-			$rows = 25;
-		}
-
-		echo "<h3>Search results for $words</h3><p>\n\n";
-
-		$title_arr = array();
-		$title_arr[] = 'User Name';
-		$title_arr[] = 'Real Name';
-
-		echo $GLOBALS['HTML']->listTableTop ($title_arr);
-
-		for ( $i = 0; $i < $rows; $i++ ) {
-			print	"<tr ". $HTML->boxGetAltRowStyle($i) ."><td><a href=\"/users/".db_result($result, $i, 'user_name')."/\">"
-				. html_image("ic/msg.png","10","12",array("border"=>"0")) . db_result($result, $i, 'user_name')."</a></td>"
-				. "<td>".db_result($result,$i,'realname')."</td></tr>\n";
-		}
-
-		echo $GLOBALS['HTML']->listTableBottom() . '</p>';
-
-	}
-
-} else if ($type_of_search == 'forums' && $forum_id && $group_id) {
-	/*
-		Query to search within forum messages
-	*/
-
-	$array=explode(" ",$words);
-	$words1=implode($array,"%' $crit forum.body ILIKE '%");
-	$words2=implode($array,"%' $crit forum.subject ILIKE '%");
-
-	$sql =	"SELECT forum.msg_id,forum.subject,forum.post_date,users.user_name 
-		FROM forum,users 
-		WHERE users.user_id=forum.posted_by AND ((forum.body ILIKE '%$words1%') 
-		OR (forum.subject ILIKE '%$words2%')) AND forum.group_forum_id='$forum_id' 
-		GROUP BY msg_id,subject,post_date,user_name";
-	$result = db_query($sql,26,$offset);
-	$rows = $rows_returned = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		$no_rows = 1;
-		echo "<h2>No matches found for $words</h2>";
-		echo db_error();
-	} else {
-
-		if ( $rows_returned > 25) {
-			$rows = 25;
-		}
-
-		echo "<h3>Search results for $words</h3><p>\n\n";
-
-		$title_arr = array();
-		$title_arr[] = 'Thread';
-		$title_arr[] = 'Author';
-		$title_arr[] = 'Date';
-
-		echo $GLOBALS['HTML']->listTableTop ($title_arr);
-
-		for ( $i = 0; $i < $rows; $i++ ) {
-			print	"<tr ". $HTML->boxGetAltRowStyle($i) ."><td><a href=\"/forum/message.php?msg_id="
-				. db_result($result, $i, "msg_id")."\">"
-				. html_image("ic/msg.png","10","12",array("border"=>"0"))
-				. db_result($result, $i, "subject")."</a></td>"
-				. "<td>".db_result($result, $i, "user_name")."</td>"
-				. "<td>".date($sys_datefmt,db_result($result,$i,"post_date"))."</td></tr>\n";
-		}
-
-		echo $GLOBALS['HTML']->listTableBottom() . '</p>';
-
-	}
-
-} else if ($type_of_search == 'artifact' && $atid && $group_id) {
-	/*
-		Query to search within a specific ArtifactType
-	*/
-
-	$array=explode(" ",$words);
-	$words1=implode($array,"%' $crit a.details ILIKE '%");
-	$words2=implode($array,"%' $crit a.summary ILIKE '%");
+	$HTML->header(array('title'=>$Language->getText('search', 'title'), 'pagename'=>'search'));
 	
-	if (ereg('^#?[0-9]+$', $words)) {
-		$no = ereg_replace('^#?([0-9]+)$', '\\1', $words);
-		$by_no_sql = "OR artifact_id=$no ";
-	}
-
-	$sql =	"SELECT DISTINCT ON (a.group_artifact_id,a.artifact_id) a.group_artifact_id,a.artifact_id,a.summary,a.open_date,users.user_name
-		FROM artifact a,users 
-		WHERE 
-		a.group_artifact_id='$atid'
-		AND users.user_id=a.submitted_by 
-		AND ((a.details ILIKE '%$words1%') 
-			OR (a.summary ILIKE '%$words2%')
-			$by_no_sql) 
-		ORDER BY group_artifact_id ASC,artifact_id ASC";
-
-		//GROUP BY group_artifact_id,artifact_id,summary,open_date,user_name
-/*
-
-create index art_groupartid_artifactid on artifact (group_artifact_id,artifact_id);
-
-*/
-
-	$result = db_query($sql,26,$offset);
-	$rows = $rows_returned = db_numrows($result);
-
-	if ( !$result || $rows < 1) {
-		$no_rows = 1;
-		echo "<h2>No matches found for $words</h2>";
-		echo db_error();
-	} else {
-
-		if ( $rows_returned > 25) {
-			$rows = 25;
-		}
-
-		echo "<h3>Search results for $words</h3><p>\n";
-
-		$title_arr = array();
-		$title_arr[] = '#';
-		$title_arr[] = 'Bug Summary';
-		$title_arr[] = 'Submitted By';
-		$title_arr[] = 'Date';
-
-		echo $GLOBALS['HTML']->listTableTop ($title_arr);
-
-		for ( $i = 0; $i < $rows; $i++ ) {
-			print	"\n<tr ". $HTML->boxGetAltRowStyle($i) .">
-				<td>".db_result($result, $i, "artifact_id")."</td>
-				<td><a href=\"/tracker/?group_id=$group_id&atid="
-				. db_result($result, $i, "group_artifact_id") 
-				. "&func=detail&aid="
-				. db_result($result, $i, "artifact_id")."\"> "
-				. html_image("ic/msg.png","10","12",array("border"=>"0"))
-				. db_result($result, $i, "summary")."</a></td>"
-				. "<td>".db_result($result, $i, "user_name")."</td>"
-				. "<td>". date($sys_datefmt,db_result($result,$i,"open_date"))."</td></tr>";
-		}
-
-		echo $GLOBALS['HTML']->listTableBottom() . '</p>';
-
-	}
-
-} else if ($type_of_search == "skill") {
-	/*
-		Query to find users with a particular skill
-	*/
-
-	// If multiple words, separate them and put LIKE in between
-	$array=explode(" ",$words);
-	$words1=implode($array,"%' $crit title ILIKE '%");
-	$words2=implode($array,"%' $crit keywords ILIKE '%");
-
-	$sql =	"SELECT * 
-		FROM skills_data,users, skills_data_types 
-		WHERE ((title ILIKE '%$words1%') OR (keywords ILIKE '%$words2%')) 
-		AND (skills_data.user_id=users.user_id) 
-		AND (skills_data.type=skills_data_types.type_id) ORDER BY finish DESC";
-	$result = db_query($sql);
-	$rows = $rows_returned = db_numrows($result);
-
-	if (!$result || $rows < 1) {
-		$no_rows = 1;
-		echo "<h2>No matches found for '$words'</h2>";
-		echo db_error();
-//		echo $sql;
-	} else {
-
-/*		if ( $rows_returned > 25) {
-			$rows = 25;
-		}
-*/
-		echo "<h3>Search results for <strong><em>$words</em></strong></h3><p>\n\n";
-
-		$title_arr = array();
-		$title_arr[] = 'Name';
-		$title_arr[] = 'Type';
-		$title_arr[] = 'Title';
-		$title_arr[] = 'Keywords';
-		$title_arr[] = 'From';
-		$title_arr[] = 'To';
-
-		echo $GLOBALS['HTML']->listTableTop ($title_arr);
-
-		$monthArray = array();
-		for($i = 1; $i <= 12; $i++) {
-			array_push($monthArray,date("M", mktime(0,0,0,$i,10,1980)));
-		}		
-		
-		for ( $i = 0; $i < $rows; $i++ ) {
-
-		   $start = db_result($result, $i, 'start');
-		   $startY = substr($start, 0, 4);
-		   $startM = substr($start, 4, 2);
-		   
-		   $finish = db_result($result, $i, 'finish');
-		   $finishY = substr($finish, 0, 4);
-		   $finishM = substr($finish, 4, 2);
-				
-		   echo '<tr '.$HTML->boxGetAltRowStyle($i+1).'>';
-		   echo '<td><a href="/users/'.db_result($result, $i, 'user_name').'/">'.
-				  db_result($result, $i, 'realname').'</a></td>';
-		   echo '<td>'.db_result($result, $i, 'type_name').'</td>';
-		   echo '<td>'.db_result($result, $i, 'title').'</td>';
-		   echo '<td>'.db_result($result, $i, 'keywords').'</td>';
-		   echo '<td>'.$monthArray[$startM-1].' '.$startY.'</td>';
-		   echo '<td>'.$monthArray[$finishM-1].' '.$finishY.'</td>';
-		   echo '<tr>';
-		}
-
-		echo $GLOBALS['HTML']->listTableBottom() . '</p>';
-
-	}
-
-} else {
-
-	echo "<h1>Invalid Search - ERROR!!!!</h1>";
-
+	echo '<h1>'.$Language->getText('search', 'error_invalid_search').'</h1>';
+	
+	$HTML->footer(array());
+	exit();
 }
 
-   // This code puts the nice next/prev.
-if ( !$no_rows && ( ($rows_returned > $rows) || ($offset != 0) ) ) {
-
-	echo "<br />\n";
-
-	echo "<table style=\"background-color:".$HTML->COLOR_LTBACK1."\" width=\"100%\" cellpadding=\"5\" cellspacing=\"0\">\n";
-	echo "<tr>\n";
-	echo "\t<td align=\"left\">";
-	if ($offset != 0) {
-		echo "<span style=\"font-family:arial, helvetica;text-decoration: none\">";
-		echo "<a href=\"javascript:history.back()\">"
-			. html_image("t2.png","15","15",array("border"=>"0","align"=>"middle"))
-			. " <strong>Previous Results</strong></a></span>";
-	} else {
-		echo " ";
-	}
-	echo "</td>\n\t<td align=\"right\">";
-	if ( $rows_returned > $rows) {
-		echo "<span style=\"font-family:arial, helvetica;text-decoration: none\">";
-		echo "<a href=\"/search/?type=$type_of_search&exact=$exact&q=".urlencode($words)."&offset=".($offset+25);
-		if ( $type_of_search == 'artifact' ) {
-			echo "&group_id=$group_id&atid=$atid";
-		} 
-		if ( $type_of_search == 'forums' ) {
-			echo "&group_id=$group_id&forum_id=$forum_id";
-		}
-		echo "\"><strong>Next Results " . html_image("t.png","15","15",array("border"=>"0","align"=>"middle")) . "</strong></a></span>";
-	} else {
-		echo " ";
-	}
-	echo "</td>\n</tr>\n";
-	echo "</table>\n";
-}
-
-$HTML->footer(array());
-?>
+?>
\ No newline at end of file



More information about the evolvis-commits mailing list