Skip to content

Commit

Permalink
[FEATURE] Allow flexible search in Suggest Wizard
Browse files Browse the repository at this point in the history
The Suggest Wizard now allows to search for multiple
terms in field by splitting the searchterm by +.

This allows to search for a combination of values which
is helpful when dealing with large data sets.

Resolves: #61981
Releases: master
Change-Id: I764039a575ca5d9ccbd97dd3dc57f3947906a5c3
Reviewed-on: https://review.typo3.org/55546
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
  • Loading branch information
Mathias Schreiber authored and lolli42 committed Feb 4, 2018
1 parent 2e515c6 commit 6b7c038
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;

/**
* Default implementation of a handler class for an ajax record selector.
Expand Down Expand Up @@ -110,7 +112,7 @@ public function __construct($table, $config)
$depth = (int)$config['pidDepth'];
foreach ($pageIds as $pageId) {
if ($pageId > 0) {
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($allowedPages, $this->getAllSubpagesOfPage($pageId, $depth));
ArrayUtility::mergeRecursiveWithOverrule($allowedPages, $this->getAllSubpagesOfPage($pageId, $depth));
}
}
$this->allowedPages = array_unique($allowedPages);
Expand Down Expand Up @@ -213,26 +215,16 @@ public function queryTable(&$params, $recursionCounter = 0)
protected function prepareSelectStatement()
{
$expressionBuilder = $this->queryBuilder->expr();
$searchWholePhrase = !isset($this->config['searchWholePhrase']) || $this->config['searchWholePhrase'];
$searchString = $this->params['value'];
$searchUid = (int)$searchString;
if ($searchString !== '') {
$likeCondition = ($searchWholePhrase ? '%' : '') . $searchString . '%';
// Search in all fields given by label or label_alt
$selectFieldsList = $GLOBALS['TCA'][$this->table]['ctrl']['label'] . ',' . $GLOBALS['TCA'][$this->table]['ctrl']['label_alt'] . ',' . $this->config['additionalSearchFields'];
$selectFields = GeneralUtility::trimExplode(',', $selectFieldsList, true);
$selectFields = array_unique($selectFields);
$selectParts = $expressionBuilder->orX();
foreach ($selectFields as $field) {
$selectParts->add($expressionBuilder->like($field, $this->queryBuilder->createPositionalParameter($likeCondition)));
$splitStrings = $this->splitSearchString($searchString);
$constraints = [];
foreach ($splitStrings as $splitString) {
$constraints[] = $this->buildConstraintBlock($splitString);
}

$searchClause = $expressionBuilder->orX($selectParts);
if ($searchUid > 0 && $searchUid == $searchString) {
$searchClause->add($expressionBuilder->eq('uid', $searchUid));
foreach ($constraints as $constraint) {
$this->queryBuilder->andWhere($expressionBuilder->andX($constraint));
}

$this->queryBuilder->andWhere($expressionBuilder->orX($searchClause));
}
if (!empty($this->allowedPages)) {
$pidList = array_map('intval', $this->allowedPages);
Expand All @@ -248,6 +240,47 @@ protected function prepareSelectStatement()
}
}

/**
* Creates OR constraints for each split searchWord.
*
* @param string $searchString
* @return string|\TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
*/
protected function buildConstraintBlock(string $searchString)
{
$expressionBuilder = $this->queryBuilder->expr();
if (MathUtility::canBeInterpretedAsInteger($searchString) && (int)$searchString > 0) {
$searchClause = $expressionBuilder->eq('uid', (int)$searchString);
} else {
$searchWholePhrase = !isset($this->config['searchWholePhrase']) || $this->config['searchWholePhrase'];
$likeCondition = ($searchWholePhrase ? '%' : '') . $this->queryBuilder->escapeLikeWildcards($searchString) . '%';
// Search in all fields given by label or label_alt
$selectFieldsList = ($GLOBALS['TCA'][$this->table]['ctrl']['label'] ?? '') . ',' . ($GLOBALS['TCA'][$this->table]['ctrl']['label_alt'] ?? '') . ',' . $this->config['additionalSearchFields'];
$selectFields = GeneralUtility::trimExplode(',', $selectFieldsList, true);
$selectFields = array_unique($selectFields);
$selectParts = $expressionBuilder->orX();
foreach ($selectFields as $field) {
$selectParts->add($expressionBuilder->like($field, $this->queryBuilder->createPositionalParameter($likeCondition)));
}
$searchClause = $expressionBuilder->orX($selectParts);
}
return $searchClause;
}

/**
* Splits the search string by +
* This allows searching for "elements+basic" and will find results like
* "elements rte basic
*
* @param string $searchString
* @return array
*/
protected function splitSearchString(string $searchString): array
{
$spitStrings = GeneralUtility::trimExplode('+', $searchString, true);
return $spitStrings;
}

/**
* Selects all subpages of one page, optionally only up to a certain level
*
Expand Down Expand Up @@ -357,7 +390,7 @@ protected function makeWorkspaceOverlay(&$row)
* The path is returned uncut, cutting has to be done by calling function.
*
* @param array $row The row
* @param array $record The record
* @param int $uid UID of the record
* @return string The record-path
*/
protected function getRecordPath(&$row, $uid)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.. include:: ../../Includes.txt

=====================================================
Feature: #61981 - Search all fields in Suggest Wizard
=====================================================

See :issue:`61981`

Description
===========

Suggest Wizard search terms are split by +.
This allows to search for a combination of strings in any given field.


Impact
======

Searching for the term "elements+basic" will find the following results:

* elements basic
* elements rte basic
* basic rte elements

.. index:: Backend, TCA, NotScanned

0 comments on commit 6b7c038

Please sign in to comment.