Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.2] Smart Search: Allow fuzzy word matching #2457

Closed
jgerman-bot opened this issue Jun 3, 2022 · 0 comments · Fixed by #2466
Closed

[4.2] Smart Search: Allow fuzzy word matching #2457

jgerman-bot opened this issue Jun 3, 2022 · 0 comments · Fixed by #2466

Comments

@jgerman-bot
Copy link

New language relevant PR in upstream repo: joomla/joomla-cms#36752 Here are the upstream changes:

Click to expand the diff!
diff --git a/administrator/components/com_finder/config.xml b/administrator/components/com_finder/config.xml
index 93919b7a4cf3..0e5ed937a5d5 100644
--- a/administrator/components/com_finder/config.xml
+++ b/administrator/components/com_finder/config.xml
@@ -4,8 +4,18 @@
 	<fieldset
 		name="search"
 		label="COM_FINDER_FIELDSET_SEARCH_OPTIONS_LABEL"
-		description="COM_FINDER_FIELDSET_SEARCH_OPTIONS_DESCRIPTION"
 		>
+		<field
+			name="word_match"
+			type="list"
+			label="COM_FINDER_CONFIG_WORD_MATCH_LABEL"
+			description="COM_FINDER_CONFIG_WORD_MATCH_DESC"
+			default="exact"
+			>
+			<option value="exact">COM_FINDER_CONFIG_WORD_MATCH_OPTION_EXACT</option>
+			<option value="begin">COM_FINDER_CONFIG_WORD_MATCH_OPTION_BEGIN</option>
+			<option value="fuzzy">COM_FINDER_CONFIG_WORD_MATCH_OPTION_FUZZY</option>
+		</field>
 
 		<field
 			name="show_taxonomy"
diff --git a/administrator/components/com_finder/src/Indexer/Query.php b/administrator/components/com_finder/src/Indexer/Query.php
index 637455efbde5..531b8310ce04 100644
--- a/administrator/components/com_finder/src/Indexer/Query.php
+++ b/administrator/components/com_finder/src/Indexer/Query.php
@@ -17,6 +17,7 @@
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Uri\Uri;
 use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
+use Joomla\Database\ParameterType;
 use Joomla\Registry\Registry;
 use Joomla\String\StringHelper;
 use Joomla\Utilities\ArrayHelper;
@@ -174,6 +175,14 @@ class Query
 	 */
 	public $when2;
 
+	/**
+	 * Match search terms exactly or with a LIKE scheme
+	 *
+	 * @var    string
+	 * @since  __DEPLOY_VERSION__
+	 */
+	public $wordmode;
+
 	/**
 	 * Method to instantiate the query object.
 	 *
@@ -196,6 +205,9 @@ public function __construct($options)
 		// Get the matching mode.
 		$this->mode = 'AND';
 
+		// Set the word matching mode
+		$this->wordmode = !empty($options['word_match']) ? $options['word_match'] : 'exact';
+
 		// Initialize the temporary date storage.
 		$this->dates = new Registry;
 
@@ -1343,8 +1355,33 @@ protected function getTokenData($token)
 		else
 		{
 			// Add the term to the query.
-			$query->where('(t.term = ' . $db->quote($token->term) . ' OR t.stem = ' . $db->quote($token->stem) . ')')
-				->where('t.phrase = 0')
+
+			$searchTerm = $token->term;
+			$searchStem = $token->stem;
+			$term = $query->quoteName('t.term');
+			$stem = $query->quoteName('t.stem');
+
+			if ($this->wordmode === 'begin')
+			{
+				$searchTerm .= '%';
+				$searchStem .= '%';
+				$query->where('(' . $term . ' LIKE :searchTerm OR ' . $stem . ' LIKE :searchStem)');
+			}
+			elseif ($this->wordmode === 'fuzzy')
+			{
+				$searchTerm = '%' . $searchTerm . '%';
+				$searchStem = '%' . $searchStem . '%';
+				$query->where('(' . $term . ' LIKE :searchTerm OR ' . $stem . ' LIKE :searchStem)');
+			}
+			else
+			{
+				$query->where('(' . $term . ' = :searchTerm OR ' . $stem . ' = :searchStem)');
+			}
+
+			$query->bind(':searchTerm', $searchTerm, ParameterType::STRING)
+				->bind(':searchStem', $searchStem, ParameterType::STRING);
+
+			$query->where('t.phrase = 0')
 				->where('t.language IN (\'*\',' . $db->quote($token->language) . ')');
 		}
 
diff --git a/administrator/language/en-GB/com_finder.ini b/administrator/language/en-GB/com_finder.ini
index aad338d0737b..ed6da336c89f 100644
--- a/administrator/language/en-GB/com_finder.ini
+++ b/administrator/language/en-GB/com_finder.ini
@@ -55,6 +55,11 @@ COM_FINDER_CONFIG_TITLE_MULTIPLIER_LABEL="Title Text Weight Multiplier"
 COM_FINDER_CONFIG_TUPLECOUNT_LABEL="Search for Phrases"
 COM_FINDER_CONFIG_TUPLECOUNT_PHRASE_DISABLED="Disabled (Improved performance)"
 COM_FINDER_CONFIG_TUPLECOUNT_PHRASE_ENABLED="Enabled (Improved search results)"
+COM_FINDER_CONFIG_WORD_MATCH_DESC="Set how search terms are matched in the index. By default a word is matched exactly, but when a language supports compound words, this allows to match the search term to the beginning or in a random place inside of words in the index."
+COM_FINDER_CONFIG_WORD_MATCH_LABEL="Word Match"
+COM_FINDER_CONFIG_WORD_MATCH_OPTION_BEGIN="Match words beginning with the search term"
+COM_FINDER_CONFIG_WORD_MATCH_OPTION_EXACT="Match exactly"
+COM_FINDER_CONFIG_WORD_MATCH_OPTION_FUZZY="Match words containing the search term anywhere"
 COM_FINDER_CONFIGURATION="Smart Search: Options"
 COM_FINDER_CONTENT_PLUGIN="Smart Search Content Plugin"
 COM_FINDER_CREATE_FILTER="Create a filter."
@@ -65,9 +70,8 @@ COM_FINDER_EMPTYSTATE_CONTENT="No content has been indexed or you have deleted a
 COM_FINDER_EMPTYSTATE_SEARCHES_CONTENT="There are no phrases used for site searching to view yet."
 COM_FINDER_FIELD_CREATED_BY_ALIAS_LABEL="Alias"
 COM_FINDER_FIELD_CREATED_BY_LABEL="Created By"
-COM_FINDER_FIELDSET_INDEX_OPTIONS_DESCRIPTION="Indexing options"
+COM_FINDER_FIELDSET_INDEX_OPTIONS_DESCRIPTION="These options influence how the content is indexed. After changing settings here, the index needs to be rebuilt."
 COM_FINDER_FIELDSET_INDEX_OPTIONS_LABEL="Index"
-COM_FINDER_FIELDSET_SEARCH_OPTIONS_DESCRIPTION="Smart Search options"
 COM_FINDER_FIELDSET_SEARCH_OPTIONS_LABEL="Smart Search"
 COM_FINDER_FILTER_BRANCH_LABEL="Search by %s"
 COM_FINDER_FILTER_EDIT_TOOLBAR_TITLE="Smart Search: Edit Filter"
diff --git a/components/com_finder/src/Model/SearchModel.php b/components/com_finder/src/Model/SearchModel.php
index 3092b2e51d8f..e21c822433c9 100644
--- a/components/com_finder/src/Model/SearchModel.php
+++ b/components/com_finder/src/Model/SearchModel.php
@@ -402,6 +402,9 @@ protected function populateState($ordering = null, $direction = null)
 		// Get the query language.
 		$options['language'] = $request->getCmd('l', $params->get('l', $language->getTag()));
 
+		// Set the word match mode
+		$options['word_match'] = $params->get('word_match', 'exact');
+
 		// Get the start date and start date modifier filters.
 		$options['date1'] = $request->getString('d1', $params->get('d1', ''));
 		$options['when1'] = $request->getString('w1', $params->get('w1', ''));
@@ -487,65 +490,4 @@ protected function populateState($ordering = null, $direction = null)
 		$this->setState('user.id', (int) $user->get('id'));
 		$this->setState('user.groups', $user->getAuthorisedViewLevels());
 	}
-
-	/**
-	 * Method to retrieve data from cache.
-	 *
-	 * @param   string   $id          The cache store id.
-	 * @param   boolean  $persistent  Flag to enable the use of external cache. [optional]
-	 *
-	 * @return  mixed  The cached data if found, null otherwise.
-	 *
-	 * @since   2.5
-	 */
-	protected function retrieve($id, $persistent = true)
-	{
-		$data = null;
-
-		// Use the internal cache if possible.
-		if (isset($this->cache[$id]))
-		{
-			return $this->cache[$id];
-		}
-
-		// Use the external cache if data is persistent.
-		if ($persistent)
-		{
-			$data = Factory::getCache($this->context, 'output')->get($id);
-			$data = $data ? unserialize($data) : null;
-		}
-
-		// Store the data in internal cache.
-		if ($data)
-		{
-			$this->cache[$id] = $data;
-		}
-
-		return $data;
-	}
-
-	/**
-	 * Method to store data in cache.
-	 *
-	 * @param   string   $id          The cache store id.
-	 * @param   mixed    $data        The data to cache.
-	 * @param   boolean  $persistent  Flag to enable the use of external cache. [optional]
-	 *
-	 * @return  boolean  True on success, false on failure.
-	 *
-	 * @since   2.5
-	 */
-	protected function store($id, $data, $persistent = true)
-	{
-		// Store the data in internal cache.
-		$this->cache[$id] = $data;
-
-		// Store the data in external cache if data is persistent.
-		if ($persistent)
-		{
-			return Factory::getCache($this->context, 'output')->store(serialize($data), $id);
-		}
-
-		return true;
-	}
 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants