diff --git a/application/ui.linksdirectwidget.class.inc.php b/application/ui.linksdirectwidget.class.inc.php
index aebb5d710..1dd95da23 100644
--- a/application/ui.linksdirectwidget.class.inc.php
+++ b/application/ui.linksdirectwidget.class.inc.php
@@ -228,7 +228,7 @@ JS
<<
diff --git a/application/ui.searchformforeignkeys.class.inc.php b/application/ui.searchformforeignkeys.class.inc.php
index 1d858e998..cdc75a633 100644
--- a/application/ui.searchformforeignkeys.class.inc.php
+++ b/application/ui.searchformforeignkeys.class.inc.php
@@ -68,7 +68,7 @@ class UISearchFormForeignKeys
<<
diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php
index 36b4e93de..1f900d9b5 100644
--- a/lib/composer/autoload_classmap.php
+++ b/lib/composer/autoload_classmap.php
@@ -134,6 +134,7 @@ return array(
'Combodo\\iTop\\Application\\Helper\\CKEditorHelper' => $baseDir . '/sources/Application/Helper/CKEditorHelper.php',
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => $baseDir . '/sources/Application/Helper/ExportHelper.php',
'Combodo\\iTop\\Application\\Helper\\FormHelper' => $baseDir . '/sources/Application/Helper/FormHelper.php',
+ 'Combodo\\iTop\\Application\\Helper\\SearchHelper' => $baseDir . '/sources/Application/Helper/SearchHelper.php',
'Combodo\\iTop\\Application\\Helper\\Session' => $baseDir . '/sources/Application/Helper/Session.php',
'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => $baseDir . '/sources/Application/Helper/WebResourcesHelper.php',
'Combodo\\iTop\\Application\\Newsroom\\iTopNewsroomProvider' => $baseDir . '/sources/Application/Newsroom/iTopNewsroomProvider.php',
diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php
index 32cfdf46c..5422872d6 100644
--- a/lib/composer/autoload_static.php
+++ b/lib/composer/autoload_static.php
@@ -520,6 +520,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685
'Combodo\\iTop\\Application\\Helper\\CKEditorHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/CKEditorHelper.php',
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/ExportHelper.php',
'Combodo\\iTop\\Application\\Helper\\FormHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/FormHelper.php',
+ 'Combodo\\iTop\\Application\\Helper\\SearchHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/SearchHelper.php',
'Combodo\\iTop\\Application\\Helper\\Session' => __DIR__ . '/../..' . '/sources/Application/Helper/Session.php',
'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/WebResourcesHelper.php',
'Combodo\\iTop\\Application\\Newsroom\\iTopNewsroomProvider' => __DIR__ . '/../..' . '/sources/Application/Newsroom/iTopNewsroomProvider.php',
diff --git a/pages/UI.php b/pages/UI.php
index 02f02738e..276191508 100644
--- a/pages/UI.php
+++ b/pages/UI.php
@@ -5,6 +5,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
+use Combodo\iTop\Application\Helper\SearchHelper;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
@@ -126,72 +127,6 @@ function SetObjectBreadCrumbEntry(DBObject $oObj, WebPage $oPage)
$oPage->SetBreadCrumbEntry("ui-details-$sClass-".$oObj->GetKey(), $oObj->Get('friendlyname'), MetaModel::GetName($sClass).': '.$oObj->Get('friendlyname'), '', $sIcon, $sIconType);
}
-/**
- * Displays the result of a search request
- * @param $oP WebPage Web page for the output
- * @param $oFilter DBSearch The search of objects to display
- * @param $bSearchForm boolean Whether or not to display the search form at the top the page
- * @param $sBaseClass string The base class for the search (can be different from the actual class of the results)
- * @param $sFormat string The format to use for the output: csv or html
- * @param $bDoSearch bool True to display the search results below the search form
- * @param $bSearchFormOpen bool True to display the search form fully expanded (only if $bSearchForm of course)
- * @throws \CoreException
- * @throws \DictExceptionMissingString
- */
-function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true, $aParams = [])
-{
- //search block
- $oBlockForm = null;
- if ($bSearchForm) {
- $aParams['open'] = $bSearchFormOpen;
- if (false === isset($aParams['table_id'])) {
- $aParams['table_id'] = 'result_1';
- }
- if (!empty($sBaseClass)) {
- $aParams['baseClass'] = $sBaseClass;
- }
- $oBlockForm = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams);
-
- if (!$bDoSearch) {
- $oBlockForm->Display($oP, 0);
- }
- }
- if ($bDoSearch) {
- if (strtolower($sFormat) == 'csv') {
- $oBlock = new DisplayBlock($oFilter, 'csv', false);
- // Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
- $oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block
- } else {
- $oBlock = new DisplayBlock($oFilter, 'list', false);
-
- // Breadcrumb
- //$iCount = $oBlock->GetDisplayedCount();
- $sPageId = "ui-search-".$oFilter->GetClass();
- $sLabel = MetaModel::GetName($oFilter->GetClass());
- $oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
- }
- if ($bSearchForm) {
- //add search block
- $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
- if ($sTableId == '') {
- $sTableId = 'result_1';
- }
- $aExtraParams['table_id'] = $sTableId;
- $aExtraParams['submit_on_load'] = false;
- $oUIBlockForm = $oBlockForm->GetDisplay($oP, 'search_1', $aExtraParams);
- //add result block
- $oUIBlock = $oBlock->GetDisplay($oP, $sTableId);
- $oUIBlock->AddCSSClasses(['display_block', 'sf_results_area']);
- $oUIBlock->AddDataAttribute('target', 'search_results');
- //$oUIBlockForm->AddSubBlock($oUIBlock);
- $oP->AddUiBlock($oUIBlockForm);
- $oUIBlockForm->AddSubBlock($oUIBlock);
- } else {
- $oBlock->Display($oP, 1);
- }
- }
-}
-
/**
* Displays a form (checkboxes) to select the objects for which to apply a given action
* Only the objects for which the action is valid can be checked. By default all valid objects are checked
@@ -460,7 +395,7 @@ try {
$sOQL = "SELECT $sOQLClass $sOQLClause";
try {
$oFilter = DBObjectSearch::FromOQL($sOQL);
- DisplaySearchSet($oP, $oFilter, $bSearchForm, $sBaseClass, $sFormat);
+ SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, $sBaseClass, $sFormat);
} catch (CoreException $e) {
$oFilter = new DBObjectSearch($sOQLClass);
$oSet = new DBObjectSet($oFilter);
@@ -487,7 +422,7 @@ try {
}
$oP->set_title(Dict::S('UI:SearchResultsPageTitle'));
$oFilter = new DBObjectSearch($sClass);
- DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat, $bDoSearch, true /* Search Form Expanded */);
+ SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat, $bDoSearch, true /* Search Form Expanded */);
break;
///////////////////////////////////////////////////////////////////////////////////////////
@@ -509,7 +444,7 @@ try {
// $sParams = utils::ReadParam('aParams', '{}', false, \utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
// $aParams = json_decode($sParams, true);
- DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); //, true, true, $aParams
+ SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); //, true, true, $aParams
break;
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/sources/Application/Helper/SearchHelper.php b/sources/Application/Helper/SearchHelper.php
new file mode 100644
index 000000000..d2ac70174
--- /dev/null
+++ b/sources/Application/Helper/SearchHelper.php
@@ -0,0 +1,87 @@
+Display($oP, 0);
+ }
+ }
+ if ($bDoSearch) {
+ if (strtolower($sFormat) == 'csv') {
+ $oBlock = new DisplayBlock($oFilter, 'csv', false);
+ // Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
+ $oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block
+ } else {
+ $oBlock = new DisplayBlock($oFilter, 'list', false);
+
+ // Breadcrumb
+ //$iCount = $oBlock->GetDisplayedCount();
+ $sPageId = "ui-search-".$oFilter->GetClass();
+ $sLabel = MetaModel::GetName($oFilter->GetClass());
+ $oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
+ }
+ if ($bSearchForm) {
+ //add search block
+ $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
+ if ($sTableId == '') {
+ $sTableId = 'result_1';
+ }
+ $aExtraParams['table_id'] = $sTableId;
+ $aExtraParams['submit_on_load'] = false;
+ $oUIBlockForm = $oBlockForm->GetDisplay($oP, 'search_1', $aExtraParams);
+
+ // If the class is not high cardinality, we can display the results directly in the same page
+ if (!utils::IsHighCardinality($oFilter->GetClass())) {
+ //add result block
+ $oUIBlock = $oBlock->GetDisplay($oP, $sTableId);
+ $oUIBlock->AddCSSClasses(['display_block', 'sf_results_area']);
+ $oUIBlock->AddDataAttribute('target', 'search_results');
+ $oUIBlockForm->AddSubBlock($oUIBlock);
+ }
+
+ $oP->AddUiBlock($oUIBlockForm);
+ } else {
+ $oBlock->Display($oP, 1);
+ }
+ }
+ }
+}
diff --git a/templates/application/links/direct/block-direct-linkset-edit-table/layout.js.twig b/templates/application/links/direct/block-direct-linkset-edit-table/layout.js.twig
index 400cce7b7..c7149e147 100644
--- a/templates/application/links/direct/block-direct-linkset-edit-table/layout.js.twig
+++ b/templates/application/links/direct/block-direct-linkset-edit-table/layout.js.twig
@@ -7,6 +7,6 @@ oWidget{{ oUIBlock.oUILinksDirectWidget.GetInputId() }} = $('#{{ oUIBlock.oUILin
input_name: '{{ oUIBlock.sInputName }}',
submit_to: '{{ oUIBlock.sSubmitUrl }}',
oWizardHelper: {{ oUIBlock.sWizHelper }},
- do_search: '{{ oUIBlock.sJSDoSearch }}'
+ do_search: {{ oUIBlock.sJSDoSearch }}
});
{% endapply %}
\ No newline at end of file
diff --git a/tests/php-unit-tests/unitary-tests/application/Helper/SearchHelperTest.php b/tests/php-unit-tests/unitary-tests/application/Helper/SearchHelperTest.php
new file mode 100644
index 000000000..efed1a857
--- /dev/null
+++ b/tests/php-unit-tests/unitary-tests/application/Helper/SearchHelperTest.php
@@ -0,0 +1,87 @@
+Get('high_cardinality_classes');
+ self::$bSearchManualSubmit = MetaModel::GetConfig()->Get('search_manual_submit');
+ }
+
+ protected function tearDown(): void
+ {
+ parent::tearDown();
+ MetaModel::GetConfig()->Set('high_cardinality_classes', static::$aHighCardinalityClasses);
+ MetaModel::GetConfig()->Set('search_manual_submit', static::$bSearchManualSubmit);
+ }
+
+ public function testDisplaySearchSetWithNoHighCardinalityClassesAddsResultSubBlock(): void
+ {
+ MetaModel::GetConfig()->Set('high_cardinality_classes', []);
+ MetaModel::GetConfig()->Set('search_manual_submit', false);
+
+ $oP = new iTopWebPage('SearchHelperTest');
+ $oFilter = DBSearch::FromOQL('SELECT UserRequest');
+ SearchHelper::DisplaySearchSet($oP, $oFilter);
+ $oContentLayout = $oP->GetContentLayout();
+ $this->assertTrue($oContentLayout->HasSubBlock('search_1'));
+ $oSearchBlock = $oContentLayout->getSubBlock('search_1');
+ $this->assertTrue($oSearchBlock->HasSubBlock('result_1'));
+
+ if (ob_get_level() > 0) {
+ ob_end_clean();
+ }
+ }
+
+ public function testDisplaySearchSetWithHighCardinalityClassesDoesNotAddResultSubBlock(): void
+ {
+ MetaModel::GetConfig()->Set('high_cardinality_classes', ['UserRequest']);
+ MetaModel::GetConfig()->Set('search_manual_submit', false);
+
+ $oP = new iTopWebPage('SearchHelperTest');
+ $oFilter = DBSearch::FromOQL('SELECT UserRequest');
+ SearchHelper::DisplaySearchSet($oP, $oFilter);
+ $oContentLayout = $oP->GetContentLayout();
+ $this->assertTrue($oContentLayout->HasSubBlock('search_1'));
+ $oSearchBlock = $oContentLayout->getSubBlock('search_1');
+ $this->assertFalse($oSearchBlock->HasSubBlock('result_1'));
+
+ if (ob_get_level() > 0) {
+ ob_end_clean();
+ }
+ }
+
+ public function testDisplaySearchSetWithSearchManualSubmitAndWithoutHighCardinalityClassesDoesNotAddResultSubBlock(): void
+ {
+ MetaModel::GetConfig()->Set('high_cardinality_classes', []);
+ MetaModel::GetConfig()->Set('search_manual_submit', true);
+
+ $oP = new iTopWebPage('SearchHelperTest');
+ $oFilter = DBSearch::FromOQL('SELECT UserRequest');
+ SearchHelper::DisplaySearchSet($oP, $oFilter);
+ $oContentLayout = $oP->GetContentLayout();
+ $this->assertTrue($oContentLayout->HasSubBlock('search_1'));
+ $oSearchBlock = $oContentLayout->getSubBlock('search_1');
+ $this->assertFalse($oSearchBlock->HasSubBlock('result_1'));
+
+ if (ob_get_level() > 0) {
+ ob_end_clean();
+ }
+ }
+}