Browse Source

#731 Full text search requires a string of at least three characters (configurable: full_text_needle_min)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3188 a333f486-631f-4898-b8df-5754b55c2be0
romainq 11 years ago
parent
commit
a748425db7

+ 8 - 0
core/config.class.inc.php

@@ -736,6 +736,14 @@ class Config
 			'source_of_value' => '',
 			'show_in_conf_sample' => false,
 		),
+		'full_text_needle_min' => array(
+			'type' => 'integer',
+			'description' => 'Minimum size of the full text needle.',
+			'default' => 3,
+			'value' => 3,
+			'source_of_value' => '',
+			'show_in_conf_sample' => false,
+		),
 		'tracking_level_linked_set_default' => array(
 			'type' => 'integer',
 			'description' => 'Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',

+ 1 - 0
dictionaries/dictionary.itop.ui.php

@@ -765,6 +765,7 @@ Dict::Add('EN US', 'English', 'English', array(
 	'UI:ObjectDoesNotExist' => 'Sorry, this object does not exist (or you are not allowed to view it).',
 	'UI:SearchResultsPageTitle' => 'iTop - Search Results',
 	'UI:Search:NoSearch' => 'Nothing to search for',
+	'UI:Search:NeedleTooShort' => 'The search string "%1$s" is too short. Please type at least %2$d characters.',
 	'UI:Search:Ongoing' => 'Searching for "%1$s"',
 	'UI:Search:Enlarge' => 'Broaden the search',
 	'UI:FullTextSearchTitle_Text' => 'Results for "%1$s":',

+ 1 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -635,6 +635,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
 	'UI:ObjectDoesNotExist' => 'Désolé cet objet n\'existe pas (où vous n\'êtes pas autorisé à l\'afficher).',
 	'UI:SearchResultsPageTitle' => 'iTop - Résultats de la recherche',
 	'UI:Search:NoSearch' => 'Rien à rechercher',
+	'UI:Search:NeedleTooShort' => 'La clé de recherche "%1$s" est trop courte. Veuillez saisir au moins %2$d caractères.',
 	'UI:Search:Ongoing' => 'Recherche de "%1$s"',
 	'UI:Search:Enlarge' => 'Elargir la recherche',
 	'UI:FullTextSearchTitle_Text' => 'Résultats pour "%1$s" :',

+ 42 - 3
pages/UI.php

@@ -535,8 +535,46 @@ try
 			}
 			else
 			{
-				// Sanity check of the accelerators
 				$iErrors = 0;
+
+				// Check if a class name/label is supplied to limit the search
+				$sClassName = '';
+				if (preg_match('/^([a-zA-Z]+):(.+)$/', $sFullText, $aMatches))
+				{
+					$sClassName = $aMatches[1];
+					if (MetaModel::IsValidClass($sClassName))
+					{
+						$sFullText = trim($aMatches[2]);
+					}
+					elseif ($sClassName = MetaModel::GetClassFromLabel($sClassName, false /* => not case sensitive */))
+					{
+						$sFullText = trim($aMatches[2]);
+					}
+				}
+				
+				if (preg_match('/^"(.*)"$/', $sFullText, $aMatches))
+				{
+					// The text is surrounded by double-quotes, remove the quotes and treat it as one single expression
+					$aFullTextNeedles = array($aMatches[1]);
+				}
+				else
+				{
+					// Split the text on the blanks and treat this as a search for <word1> AND <word2> AND <word3>
+					$aFullTextNeedles = explode(' ', $sFullText);
+				}
+
+				// Check the needle length
+				$iMinLenth = MetaModel::GetConfig()->Get('full_text_needle_min');
+				foreach ($aFullTextNeedles as $sNeedle)
+				{
+					if (strlen($sNeedle) < $iMinLenth)
+					{
+						$oP->p(Dict::Format('UI:Search:NeedleTooShort', $sNeedle, $iMinLenth));
+						$iErrors++;
+					}
+				}
+
+				// Sanity check of the accelerators
 				$aAccelerators = MetaModel::GetConfig()->Get('full_text_accelerators');
 				foreach ($aAccelerators as $sClass => $aAccelerator)
 				{
@@ -568,10 +606,11 @@ try
 					$oP->add("<h2>".Dict::Format('UI:FullTextSearchTitle_Text', htmlentities($sFullText, ENT_QUOTES, 'UTF-8'))."</h2>");
 					$oP->add("</div>\n");
 					$oP->add("</div>\n");
-					$sJSNeedle = addslashes($sFullText);
+					$sJSClass = addslashes($sClassName);
+					$sJSNeedles = json_encode($aFullTextNeedles);
 					$oP->add_ready_script(
 <<<EOF
-						var oParams = {operation: 'full_text_search', position: 0, text: '$sJSNeedle', tune: $iTune};
+						var oParams = {operation: 'full_text_search', position: 0, 'class': '$sJSClass', needles: $sJSNeedles, tune: $iTune};
 						$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
 							$('#full_text_results').append(data);
 						});

+ 3 - 27
pages/ajax.render.php

@@ -1294,7 +1294,9 @@ EOF
 		break;
 
 		case 'full_text_search':
-		$sFullText = trim(utils::ReadParam('text', '', false, 'raw_data'));
+		$aFullTextNeedles = utils::ReadParam('needles', array(), false, 'raw_data');
+		$sFullText = trim(implode(' ', $aFullTextNeedles));
+		$sClassName = utils::ReadParam('class', '');
 		$iCount = utils::ReadParam('count', 0);
 		$iCurrentPos = utils::ReadParam('position', 0);
 		$iTune = utils::ReadParam('tune', 0);
@@ -1306,32 +1308,6 @@ EOF
 
 		// Search in full text mode in all the classes
 		$aMatches = array();
-		$sClassName = '';
-		
-		// Check if a class name/label is supplied to limit the search
-		if (preg_match('/^(.+):(.+)$/', $sFullText, $aMatches))
-		{
-			$sClassName = $aMatches[1];
-			if (MetaModel::IsValidClass($sClassName))
-			{
-				$sFullText = $aMatches[2];
-			}
-			elseif ($sClassName = MetaModel::GetClassFromLabel($sClassName, false /* => not case sensitive */))
-			{
-				$sFullText = $aMatches[2];
-			}
-		}
-		
-		if (preg_match('/^"(.*)"$/', $sFullText, $aMatches))
-		{
-			// The text is surrounded by double-quotes, remove the quotes and treat it as one single expression
-			$aFullTextNeedles = array($aMatches[1]);
-		}
-		else
-		{
-			// Split the text on the blanks and treat this as a search for <word1> AND <word2> AND <word3>
-			$aFullTextNeedles = explode(' ', $sFullText);
-		}
 
 		// Build the ordered list of classes to search into
 		//