N°3238 - Fix multi-words search in FilterBrick and ManageBrick

This commit is contained in:
Eric
2020-09-04 17:34:59 +02:00
parent 9694e9848d
commit dbada2f72a
6 changed files with 72 additions and 51 deletions

View File

@@ -84,8 +84,9 @@ class BrowseBrickController extends BrickController
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $oRequestManipulator->ReadParam('sDataLoading',
$oBrick->GetDataLoading());
// Getting search value
$sSearchValue = $oRequestManipulator->ReadParam('sSearchValue', '');
if (!empty($sSearchValue))
$sRawSearchValue = $oRequestManipulator->ReadParam('sSearchValue', '');
$sSearchValue = html_entity_decode($sRawSearchValue);
if (strlen($sSearchValue) > 0)
{
$sDataLoading = AbstractBrick::ENUM_DATA_LOADING_LAZY;
}
@@ -167,13 +168,16 @@ class BrowseBrickController extends BrickController
// Adding search clause
// Note : For know the search is naive and looks only for the exact match. It doesn't search for words separately
if (!empty($sSearchValue))
if (strlen($sSearchValue) > 0)
{
// - Cleaning the search value by exploding and trimming spaces
$aSearchValues = explode(' ', $sSearchValue);
array_walk($aSearchValues, function (&$sSearchValue /*, $sKey*/) {
trim($sSearchValue);
});
$aExplodedSearchValues = explode(' ', $sSearchValue);
$aSearchValues = [];
foreach ($aExplodedSearchValues as $sValue) {
if (strlen($sValue) > 0) {
$aSearchValues[] = $sValue;
}
}
// - Retrieving fields to search
$aSearchFields = array($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['name_att']);
@@ -257,7 +261,7 @@ class BrowseBrickController extends BrickController
{
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->SetSelectedClasses($aLevelsClasses);
if (!empty($sSearchValue))
if (strlen($sSearchValue) > 0)
{
// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
$aQueryParams = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetInternalParams();
@@ -452,7 +456,7 @@ class BrowseBrickController extends BrickController
'sBrickId' => $sBrickId,
'sBrowseMode' => $sBrowseMode,
'aBrowseButtons' => $aBrowseButtons,
'sSearchValue' => $sSearchValue,
'sSearchValue' => $sRawSearchValue,
'sDataLoading' => $sDataLoading,
'aItems' => json_encode($aItems),
'iItemsCount' => count($aItems),

View File

@@ -894,64 +894,50 @@ class ManageBrickController extends BrickController
$oRequestManipulator = $this->get('request_manipulator');
// Getting search value
$sSearchValue = $oRequestManipulator->ReadParam('sSearchValue', '');
$sRawSearchValue = trim($oRequestManipulator->ReadParam('sSearchValue', ''));
$sSearchValue = html_entity_decode($sRawSearchValue);
// - Adding search clause if necessary
// Note : This is a very naive search at the moment
if (!empty($sSearchValue))
{
if (strlen($sSearchValue) > 0) {
// Putting only valid attributes as one can define attributes of leaf classes in the brick definition (<fields>), but at this stage we are working on the abstract class.
// Note: This won't fix everything as the search will not be looking in all fields.
$aSearchListItems = array();
foreach ($aColumnsAttrs as $sColumnAttr)
{
// Skip invalid attcodes
if (!MetaModel::IsValidAttCode($sClass, $sColumnAttr))
{
$aSearchListItems = [];
foreach ($aColumnsAttrs as $sColumnAttr) {
// Skip invalid attCodes
if (!MetaModel::IsValidAttCode($sClass, $sColumnAttr)) {
continue;
}
// For external key, force search on the friendlyname instead of the ID.
// This should be addressed more globally with the bigger issue, see N°1970
$oAttDef = MetaModel::GetAttributeDef($sClass, $sColumnAttr);
if($oAttDef instanceof AttributeExternalKey)
{
if ($oAttDef instanceof AttributeExternalKey) {
$sColumnAttr .= '_friendlyname';
}
$aSearchListItems[] = $sColumnAttr;
}
$oFullBinExpr = null;
foreach ($aSearchListItems as $sSearchItemAttr)
{
$oBinExpr = new BinaryExpression(new FieldExpression($sSearchItemAttr, $oQuery->GetClassAlias()),
'LIKE', new VariableExpression('search_value'));
// At each iteration we build the complete expression for the search like ( (field1 LIKE %search%) OR (field2 LIKE %search%) OR (field3 LIKE %search%) ...)
if (is_null($oFullBinExpr))
{
$oFullBinExpr = $oBinExpr;
}
else
{
$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oBinExpr);
if (preg_match('/^"(.*)"$/', $sSearchValue, $aMatches)) {
// The text is surrounded by double-quotes, remove the quotes and treat it as one single expression
$aSearchNeedles = [$aMatches[1]];
} else {
// Split the text on the blanks and treat this as a search for <word1> AND <word2> AND <word3>
$aExplodedSearchNeedles = explode(' ', $sSearchValue);
$aSearchNeedles = [];
foreach ($aExplodedSearchNeedles as $sValue) {
if (strlen($sValue) > 0) {
$aSearchNeedles[] = $sValue;
}
}
}
// Then add the complete expression to the query
if (!is_null($oFullBinExpr))
{
// - Adding expression to the query
$oQuery->AddConditionExpression($oFullBinExpr);
// - Setting expression parameters
// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
$aQueryParams = $oQuery->GetInternalParams();
$aQueryParams['search_value'] = '%'.$sSearchValue.'%';
$oQuery->SetInternalParams($aQueryParams);
foreach ($aSearchNeedles as $sSearchWord) {
$oQuery->AddCondition_FullTextOnAttributes($aSearchListItems, $sSearchWord);
}
}
$aData['sSearchValue'] = $sSearchValue;
$aData['sSearchValue'] = $sRawSearchValue;
}
/**