mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-20 17:18:51 +02:00
N°3200 Datatable "filter list" icon : specific query for 1,n and n,n objects relations
This specific query passes attcodes list to display to UI.php, but this endpoint doesn't handle it yet. Adding this enhancements would require too much time for now (datatables legacy code), hopefully a refactoring work will be done soon and we'll get back to it ! Note that dedicated ContextTag is renamed from Search to ObjectSearch
This commit is contained in:
@@ -2223,7 +2223,7 @@ class MenuBlock extends DisplayBlock
|
||||
$oActionsToolbar->AddSubBlock($oActionButton);
|
||||
} else {
|
||||
// - Filter list
|
||||
$sSearchUrl = utils::GetDataTableSearchUrl($this->m_oFilter);
|
||||
$sSearchUrl = utils::GetDataTableSearchUrl($this->m_oFilter, $aExtraParams);
|
||||
if (!empty($sSearchUrl)) {
|
||||
$oActionButton = ButtonUIBlockFactory::MakeIconLink(
|
||||
'fas fa-filter',
|
||||
|
||||
@@ -1111,6 +1111,7 @@ class OQLMenuNode extends MenuNode
|
||||
*/
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
ContextTag::AddContext(ContextTag::TAG_OBJECT_SEARCH);
|
||||
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
|
||||
OQLMenuNode::RenderOQLSearch
|
||||
(
|
||||
|
||||
@@ -1542,20 +1542,20 @@ class utils
|
||||
}
|
||||
|
||||
/**
|
||||
* We cannot use iMenuId (corresponding values in iPopupMenuExtension constants) as value is always \iPopupMenuExtension::MENU_OBJLIST_TOOLKIT
|
||||
* We cannot use iMenuId (corresponding values in {@see \iPopupMenuExtension} constants) as value is always {@see \iPopupMenuExtension::MENU_OBJLIST_TOOLKIT}
|
||||
* whenever we are in a datatable, whereas it is included in a object tab, a dashlet or a search.
|
||||
*
|
||||
* So a {@see \ContextTag} is set on the corresponding calls.
|
||||
*
|
||||
* @return bool true if we are in a search page context, either directly or by the datatable ajax call
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @since 3.1.0 N°3200
|
||||
*
|
||||
* @uses \ContextTag::TAG_SEARCH
|
||||
* @uses \ContextTag::TAG_OBJECT_SEARCH
|
||||
*/
|
||||
public static function IsCurrentPageASearch(): bool
|
||||
{
|
||||
if (ContextTag::Check(ContextTag::TAG_SEARCH)) {
|
||||
if (ContextTag::Check(ContextTag::TAG_OBJECT_SEARCH)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1564,30 +1564,113 @@ class utils
|
||||
|
||||
/**
|
||||
* @param \DBObjectSearch $oFilter object list
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return string|null null if we are already in a search, otherwise the URL to open this list in a search
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @uses utils::IsCurrentPageASearch()
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @since 3.1.0 N°3200
|
||||
*/
|
||||
public static function GetDataTableSearchUrl(DBSearch $oFilter): ?string
|
||||
public static function GetDataTableSearchUrl(DBSearch $oFilter, array $aExtraParams): ?string
|
||||
{
|
||||
if (static::IsCurrentPageASearch()) {
|
||||
// we don't want to add the link when already in a search page !
|
||||
return null;
|
||||
}
|
||||
|
||||
$bIsObjectRelation = isset($aExtraParams['object_id'], $aExtraParams['target_attr']);
|
||||
if ($bIsObjectRelation) {
|
||||
[$oDataTableSearchFilter, $aParams] = static::GetDataTableSearchForRelations($oFilter, $aExtraParams);
|
||||
} else {
|
||||
$oDataTableSearchFilter = $oFilter;
|
||||
$aParams = [];
|
||||
}
|
||||
|
||||
if (isset($aExtraParams['table_id'])) {
|
||||
$aParams['table_id'] = $aExtraParams['table_id'];
|
||||
}
|
||||
$sParams = json_encode($aParams);
|
||||
|
||||
$sAppRootUrl = static::GetAbsoluteUrlAppRoot();
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sUrl = $sAppRootUrl.'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($oFilter->serialize());
|
||||
|
||||
$sUrl = $sAppRootUrl
|
||||
.'pages/UI.php?operation=search&'
|
||||
.$oAppContext->GetForLink()
|
||||
.'&filter='.rawurlencode($oDataTableSearchFilter->serialize());
|
||||
$sUrl .= '&aParams='.rawurlencode($sParams); // Not working... yet, cause not handled by UI.php
|
||||
|
||||
return $sUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites filter for object relations, so that in the search page we will have the correct criteria and will be able to use "configure this list"
|
||||
*
|
||||
* @param \DBSearch $oFilter object list
|
||||
* @param array{link_attr: string, target_attr: string, object_id: string} $aExtraParams
|
||||
*
|
||||
* @return array{\DBObjectSearch, string[]}
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*
|
||||
* @since 3.1.0 N°3200
|
||||
*/
|
||||
private static function GetDataTableSearchForRelations(DBSearch $oFilter, array $aExtraParams): array
|
||||
{
|
||||
$sObjectId = $aExtraParams['object_id'];
|
||||
$bIsLinkedSetIndirect = isset($aExtraParams['link_attr']);
|
||||
if ($bIsLinkedSetIndirect) {
|
||||
//--- AttributeLinkedSetIndirect (n,n => lnk class)
|
||||
$sLnkClass = $oFilter->GetClass();
|
||||
$sExtKeyToObjectClass = $aExtraParams['link_attr'];
|
||||
$sExtKeyToRemoteClass = $aExtraParams['target_attr'];
|
||||
|
||||
/** @var \AttributeExternalKey $oLnkExtKeyToRemote */
|
||||
$oLnkExtKeyToRemote = MetaModel::GetAttributeDef($sLnkClass, $sExtKeyToRemoteClass);
|
||||
$sRemoteClass = $oLnkExtKeyToRemote->GetTargetClass();
|
||||
|
||||
/** @var \AttributeExternalKey $oLnkExtKeyToRemote */
|
||||
$oLnkExtKeyToObject = MetaModel::GetAttributeDef($sLnkClass, $sExtKeyToObjectClass);
|
||||
$sObjectClass = $oLnkExtKeyToObject->GetTargetClass();
|
||||
|
||||
/** @var \AttributeExternalKey $oLnkExtKeyToRemote */
|
||||
$oObjectExtKeyToLnk = $oLnkExtKeyToObject->GetMirrorLinkAttribute();
|
||||
$sObjectExtKeyToLnkClass = $oObjectExtKeyToLnk->GetCode();
|
||||
|
||||
$sRemoteClassAliasName = ormLinkSet::REMOTE_ALIAS;
|
||||
$sLnkClassAliasName = ormLinkSet::LINK_ALIAS;
|
||||
$sOql = <<<SQL
|
||||
SELECT {$sRemoteClassAliasName},{$sLnkClassAliasName}
|
||||
FROM {$sRemoteClass} AS {$sRemoteClassAliasName}
|
||||
JOIN {$sLnkClass} AS {$sLnkClassAliasName} ON {$sLnkClassAliasName}.$sExtKeyToRemoteClass = {$sRemoteClassAliasName}.id
|
||||
WHERE {$sLnkClassAliasName}.$sExtKeyToObjectClass = $sObjectId
|
||||
SQL;
|
||||
|
||||
$aAttCodesToDisplay = MetaModel::GetAttributeLinkedSetIndirectDatatableAttCodesToDisplay($sObjectClass, $sObjectExtKeyToLnkClass, $sRemoteClass, $sExtKeyToRemoteClass);
|
||||
/** @noinspection PhpUnnecessaryLocalVariableInspection */
|
||||
$sAttCodesToDisplay = implode(',', $aAttCodesToDisplay);
|
||||
$aParams = [
|
||||
'zlist' => false,
|
||||
'extra_fields' => $sAttCodesToDisplay,
|
||||
];
|
||||
} else {
|
||||
//--- AttributeLinkedSet (1,n => AttributeExternalKey)
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sExtKeyCode = $aExtraParams['target_attr'];
|
||||
|
||||
$sOql = "SELECT $sClass WHERE $sExtKeyCode = $sObjectId";
|
||||
|
||||
$aParams = [];
|
||||
}
|
||||
|
||||
$oDataTableSearchFilter = DBSearch::FromOQL($sOql);
|
||||
|
||||
return [$oDataTableSearchFilter, $aParams];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEnvironment
|
||||
*
|
||||
|
||||
@@ -52,13 +52,17 @@
|
||||
*/
|
||||
class ContextTag
|
||||
{
|
||||
public const TAG_PORTAL = 'GUI:Portal';
|
||||
public const TAG_CRON = 'CRON';
|
||||
public const TAG_PORTAL = 'GUI:Portal';
|
||||
public const TAG_CRON = 'CRON';
|
||||
public const TAG_CONSOLE = 'GUI:Console';
|
||||
public const TAG_SETUP = 'Setup';
|
||||
public const TAG_SETUP = 'Setup';
|
||||
public const TAG_SYNCHRO = 'Synchro';
|
||||
public const TAG_REST = 'REST/JSON';
|
||||
public const TAG_SEARCH = 'Search';
|
||||
public const TAG_REST = 'REST/JSON';
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.1.0 N°3200
|
||||
*/
|
||||
public const TAG_OBJECT_SEARCH = 'ObjectSearch';
|
||||
|
||||
protected static $aStack = array();
|
||||
|
||||
|
||||
@@ -2072,6 +2072,9 @@ abstract class MetaModel
|
||||
*
|
||||
* @return string[] attcodes to display, containing aliases
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @since 3.0.0 N°2334 added code for n-n relations in {@see BlockIndirectLinksViewTable::GetAttCodesToDisplay}
|
||||
* @since 3.1.0 N°3200 method creation so that it can be used elsewhere
|
||||
*/
|
||||
public static function GetAttributeLinkedSetIndirectDatatableAttCodesToDisplay(string $sObjectClass, string $sObjectLinkedSetIndirectAttCode, string $sRemoteClass, string $sLnkExternalKeyToRemoteClassAttCode):array
|
||||
{
|
||||
@@ -2079,17 +2082,17 @@ abstract class MetaModel
|
||||
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($sRemoteClass);
|
||||
$aLnkAttCodesToDisplay = array_map(
|
||||
function ($oLnkAttDef) {
|
||||
return \ormLinkSet::LINK_ALIAS.'.'.$oLnkAttDef->GetCode();
|
||||
return ormLinkSet::LINK_ALIAS.'.'.$oLnkAttDef->GetCode();
|
||||
},
|
||||
$aLnkAttDefsToDisplay
|
||||
);
|
||||
if (!in_array(\ormLinkSet::LINK_ALIAS.'.'.$sLnkExternalKeyToRemoteClassAttCode, $aLnkAttCodesToDisplay)) {
|
||||
if (!in_array(ormLinkSet::LINK_ALIAS.'.'.$sLnkExternalKeyToRemoteClassAttCode, $aLnkAttCodesToDisplay)) {
|
||||
// we need to display a link to the remote class instance !
|
||||
$aLnkAttCodesToDisplay[] = \ormLinkSet::LINK_ALIAS.'.'.$sLnkExternalKeyToRemoteClassAttCode;
|
||||
$aLnkAttCodesToDisplay[] = ormLinkSet::LINK_ALIAS.'.'.$sLnkExternalKeyToRemoteClassAttCode;
|
||||
}
|
||||
$aRemoteAttCodesToDisplay = array_map(
|
||||
function ($oRemoteAttDef) {
|
||||
return \ormLinkSet::REMOTE_ALIAS.'.'.$oRemoteAttDef->GetCode();
|
||||
return ormLinkSet::REMOTE_ALIAS.'.'.$oRemoteAttDef->GetCode();
|
||||
},
|
||||
$aRemoteAttDefsToDisplay
|
||||
);
|
||||
|
||||
17
pages/UI.php
17
pages/UI.php
@@ -143,12 +143,15 @@ function SetObjectBreadCrumbEntry(DBObject $oObj, WebPage $oPage)
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true)
|
||||
function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true, $aParams = [])
|
||||
{
|
||||
//search block
|
||||
$oBlockForm = null;
|
||||
if ($bSearchForm) {
|
||||
$aParams = array('open' => $bSearchFormOpen, 'table_id' => 'result_1');
|
||||
$aParams['open'] = $bSearchFormOpen;
|
||||
if (false === isset($aParams['table_id'])) {
|
||||
$aParams['table_id'] = 'result_1';
|
||||
}
|
||||
if (!empty($sBaseClass)) {
|
||||
$aParams['baseClass'] = $sBaseClass;
|
||||
}
|
||||
@@ -519,7 +522,7 @@ try
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
case 'search': // Serialized DBSearch
|
||||
$oSearchContext = new ContextTag(ContextTag::TAG_SEARCH);
|
||||
$oSearchContext = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
|
||||
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
|
||||
$sFormat = utils::ReadParam('format', '');
|
||||
$bSearchForm = utils::ReadParam('search_form', true);
|
||||
@@ -530,7 +533,13 @@ try
|
||||
$oP->set_title(Dict::S('UI:SearchResultsPageTitle'));
|
||||
$oFilter = DBSearch::unserialize($sFilter); // TO DO : check that the filter is valid
|
||||
$oFilter->UpdateContextFromUser();
|
||||
DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat);
|
||||
|
||||
//FIXME Params won't work as expected :(
|
||||
// During the ajax call fetching the datatable data, the URL is rewritten and the info are lost, and we are getting a worse result :(
|
||||
// $sParams = utils::ReadParam('aParams', '{}', false, \utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
// $aParams = json_decode($sParams, true);
|
||||
|
||||
DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat, ''); //, true, $aParams
|
||||
break;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -29,7 +29,7 @@ try
|
||||
throw new AjaxSearchException("Invalid query (empty filter)", 400);
|
||||
}
|
||||
|
||||
$oSearchContext = new ContextTag(ContextTag::TAG_SEARCH);
|
||||
$oSearchContext = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
|
||||
$oPage = new AjaxPage("");
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user