mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-02 15:08:45 +02:00
WIP - add type of AuditFilterField
This commit is contained in:
@@ -1,26 +1,19 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @since 3.3.0
|
||||
*/
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\HtmlFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
|
||||
|
||||
/**
|
||||
* This class allow to define placeholder to be used in the audit "rule" and audit "category" OQL queries.
|
||||
* This class allow to define placeholder to be used in the audit 'rule' and audit 'category' OQL queries.
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -32,27 +25,38 @@ class AuditFilterField extends cmdbAbstractObject
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "placeholder",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('placeholder'),
|
||||
"db_table" => "priv_auditfilterfield",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
'category' => 'application,grant_by_profile',
|
||||
'key_type' => 'autoincrement',
|
||||
'name_attcode' => 'placeholder',
|
||||
'state_attcode' => '',
|
||||
'reconc_keys' => array('placeholder'),
|
||||
'db_table' => 'priv_auditfilterfield',
|
||||
'db_key_field' => 'id',
|
||||
'db_finalclass_field' => '',
|
||||
'uniqueness_rules' => array(
|
||||
'no_duplicate' => array(
|
||||
'attributes' => array(
|
||||
0 => 'placeholder',
|
||||
),
|
||||
'filter' => '',
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
),
|
||||
),
|
||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-filtre.svg'),
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeString("placeholder", array("allowed_values" => null, "sql" => "placeholder", "default_value" => "", "is_null_allowed" => false, "depends_on" => array(), "validation_pattern"=>'^\w+$')));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("label", array("allowed_values" => null, "sql" => "label", "default_value" => "", "is_null_allowed" => false, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("allowed_values"=>new ValueSetEnum("select_oql,select_values,number,date" , true), "display_style"=>'list', "sql"=>'type', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false)));
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values" => null, "sql" => "oql", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("values", array("allowed_values" => null, "sql" => "values", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('label', 'placeholder', 'oql', 'values')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('label', 'placeholder', 'oql','values')); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', array('label', 'placeholder', 'type', 'oql', 'values')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('label', 'placeholder', 'type', 'oql','values')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('label', 'placeholder')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('standard_search', array('label', 'placeholder','type')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array('label', 'placeholder')); // Criteria of the advanced search form
|
||||
}
|
||||
/**
|
||||
@@ -75,4 +79,243 @@ class AuditFilterField extends cmdbAbstractObject
|
||||
$oPage->AddUiBlock(AlertUIBlockFactory::MakeForInformation('In OQL query, you can use this placeholders:', '')->AddSubBlock(new Html($sHtml)));
|
||||
}
|
||||
}
|
||||
|
||||
protected function RegisterEventListeners()
|
||||
{
|
||||
parent::RegisterEventListeners();
|
||||
|
||||
// listenerId = CheckUsersUpdate
|
||||
$this->RegisterCRUDListener('EVENT_DB_CHECK_TO_WRITE', 'CheckPlaceholderName', 1, 'itop-structure');
|
||||
$this->RegisterCRUDListener('EVENT_DB_CHECK_TO_WRITE', 'CheckMandatoryFields', 2, 'itop-structure');
|
||||
}
|
||||
|
||||
|
||||
public function CheckPlaceholderName(Combodo\iTop\Service\Events\EventData $oEventData)
|
||||
{
|
||||
$aChanges = $this->ListChanges();
|
||||
if (array_key_exists('placeholder', $aChanges)) {
|
||||
$sPlaceholder = $this->Get('placeholder');
|
||||
if (str_starts_with('this->', $sPlaceholder)) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:placeholder:Error:StartWith','this'));
|
||||
}
|
||||
if (str_starts_with('current_user', $sPlaceholder)) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:placeholder:Error:StartWith','current_user'));
|
||||
}
|
||||
if (str_starts_with('current_contact', $sPlaceholder)) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:placeholder:Error:StartWith','current_contact'));
|
||||
}
|
||||
if (in_array($sPlaceholder, ['current_user', 'current_contact']) ) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:placeholder:Error:ReservedWord', $sPlaceholder));
|
||||
}
|
||||
}
|
||||
}
|
||||
public function CheckMandatoryFields(Combodo\iTop\Service\Events\EventData $oEventData)
|
||||
{
|
||||
switch ($this->Get('type')) {
|
||||
case 'select_oql':
|
||||
if (utils::IsNullOrEmptyString($this->Get('oql'))) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:oql:Error:Empty'));
|
||||
}
|
||||
break;
|
||||
case 'select_values':
|
||||
if (utils::IsNullOrEmptyString($this->Get('values'))) {
|
||||
$this->AddCheckIssue(Dict::S('Class:AuditFilterField/Attribute:values:Error:Empty'));
|
||||
}
|
||||
break;
|
||||
// case 'number':
|
||||
// case 'date':
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
public function GetFieldBlock(WebPage $oPage, string $sCurrentValue = ''): UIBlock
|
||||
{
|
||||
switch ($this->Get('type')) {
|
||||
case 'select_oql':
|
||||
$sFieldName = $this->Get('placeholder');
|
||||
$sOql = $this->Get('oql');
|
||||
$sLabel = $this->Get('label');
|
||||
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
$oAllowedValues = new DBObjectSet($oSearch);
|
||||
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
$iMaxComboLength = MetaModel::GetConfig()->Get('max_combo_length');
|
||||
|
||||
$bIsAutocomplete = $oAllowedValues->CountExceeds($iMaxComboLength);
|
||||
$sWrapperCssClass = $bIsAutocomplete ? 'field_input_extkey ibo-input-wrapper ibo-input-select-wrapper--with-buttons ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper';
|
||||
$sHTMLValue = "<div class=\"field_input_zone $sWrapperCssClass\">";
|
||||
|
||||
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||
if (!$bIsAutocomplete) {
|
||||
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||
$sHelpText = '';
|
||||
$aOptions = [];
|
||||
$aOptions['value'] = "";
|
||||
$aOptions['label'] = Dict::S('UI:SelectOne');
|
||||
|
||||
$oAllowedValues->Rewind();
|
||||
$sClassAllowed = $oAllowedValues->GetClass();
|
||||
$bAddingValue = false;
|
||||
|
||||
$aFieldsToLoad = [];
|
||||
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($oAllowedValues->GetClass(), FriendlyNameType::COMPLEMENTARY);
|
||||
$sFormatAdditionalField = $aComplementAttributeSpec[0];
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
|
||||
if (count($aAdditionalField) > 0) {
|
||||
$bAddingValue = true;
|
||||
$aFieldsToLoad[$sClassAllowed] = $aAdditionalField;
|
||||
}
|
||||
$sObjectImageAttCode = MetaModel::GetImageAttributeCode($sClassAllowed);
|
||||
if (!empty($sObjectImageAttCode)) {
|
||||
$aFieldsToLoad[$sClassAllowed][] = $sObjectImageAttCode;
|
||||
}
|
||||
$aFieldsToLoad[$sClassAllowed][] = 'friendlyname';
|
||||
$oAllowedValues->OptimizeColumnLoad($aFieldsToLoad);
|
||||
|
||||
$oSelect = SelectUIBlockFactory::MakeForSelect($sFieldName, $sFieldName);
|
||||
$oSelect->AddCSSClass('ibo-input-field-wrapper');
|
||||
|
||||
while ($oChoiceItem = $oAllowedValues->Fetch()) {
|
||||
|
||||
$sOptionName = utils::HtmlEntityDecode($oChoiceItem->GetName());
|
||||
|
||||
if ($bAddingValue) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
array_push($aArguments, $oAllowedValues->Get($sAdditionalField));
|
||||
}
|
||||
$sOptionName .= '<br><i>' . utils::HtmlEntities(vsprintf($sFormatAdditionalField, $aArguments)) . '</i>';;
|
||||
}
|
||||
if (!empty($sObjectImageAttCode)) {
|
||||
// Try to retrieve image for contact
|
||||
/** @var \ormDocument $oImage */
|
||||
$oImage = $oAllowedValues->Get($sObjectImageAttCode);
|
||||
if (!$oImage->IsEmpty()) {
|
||||
$sPicturepictureUrl = $oImage->GetDisplayURL($sClassAllowed, $oChoiceItem->GetKey(), $sObjectImageAttCode);
|
||||
$sOptionName .= ' <span class="ibo-input-select--autocomplete-item-image" style="background-image: url(' . $sPicturepictureUrl . ');"></span>';
|
||||
} else {
|
||||
$sInitials = utils::FormatInitialsForMedallion(utils::ToAcronym($oChoiceItem->Get('friendlyname')));
|
||||
$sOptionName .= ' <span class="ibo-input-select--autocomplete-item-image" ">' . $sInitials . '</span>';
|
||||
}
|
||||
}
|
||||
$oOption = SelectOptionUIBlockFactory::MakeForSelectOption($oChoiceItem->GetKey(), $sOptionName, ($sCurrentValue == $oChoiceItem->GetKey()));
|
||||
$oSelect->AddOption($oOption);
|
||||
}
|
||||
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_DECORATED;
|
||||
|
||||
$sJsonOptions = str_replace("'", "\'", str_replace('\\', '\\\\', json_encode($aOptions)));
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
let select$sFieldName = $('#$sFieldName').selectize({
|
||||
plugins:['custom_itop', 'selectize-plugin-a11y'],
|
||||
});
|
||||
JS
|
||||
);
|
||||
return $oSelect;
|
||||
} else {
|
||||
// Too many choices, use an autocomplete
|
||||
// Check that the given value is allowed
|
||||
$oSearch = $oAllowedValues->GetFilter();
|
||||
$oSearch->AddCondition('id', $sCurrentValue);
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$sClass = $oSet->GetClass();
|
||||
if ($oSet->Count() == 0) {
|
||||
$sCurrentValue = null;
|
||||
}
|
||||
|
||||
if (is_null($sCurrentValue) || ($sCurrentValue == 0)) // Null values are displayed as ''
|
||||
{
|
||||
$sDisplayValue = '';
|
||||
} else {
|
||||
$sDisplayValue = MetaModel::GetObject($sClass, $sCurrentValue)->GetName();
|
||||
}
|
||||
$iMinChars = MetaModel::GetConfig()->Get('min_autocomplete_chars'); //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
||||
|
||||
// the input for the auto-complete
|
||||
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_AUTOCOMPLETE;
|
||||
$sHTMLValue .= "<input class=\"field_autocomplete ibo-input ibo-input-select ibo-input-select-autocomplete\" type=\"text\" id=\"label_$sFieldName\" value=\"$sDisplayValue\" placeholder='...'/>";
|
||||
|
||||
// another hidden input to store & pass the object's Id
|
||||
$sHTMLValue .= "<input type=\"hidden\" id=\"$sFieldName\" name=\"{$sFieldName}\" value=\"" . utils::HtmlEntities($sCurrentValue) . "\" />\n";
|
||||
|
||||
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
oACWidget_{$sFieldName} = new ExtKeyWidget('$sFieldName', '$sClass', '$sOql', '$sLabel', false, null, '{$sFieldName}', true, false);
|
||||
oACWidget_{$sFieldName}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||
oACWidget_{$sFieldName}.AddAutocomplete($iMinChars, '');
|
||||
if ($('#ac_dlg_{$sFieldName}').length == 0)
|
||||
{
|
||||
$('body').append('<div id="ac_dlg_{$sFieldName}"></div>');
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--clear ibo-is-hidden\" id=\"mini_clear_{$sFieldName}\" onClick=\"$('#$sFieldName').val('');$('#label_$sFieldName').val(''); $('#label_$sFieldName').data('selected_value', '');\" data-tooltip-content='" . Dict::S('UI:Button:Clear') . "'><i class=\"fas fa-times\"></i></a>";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$sFieldName}\" onClick=\"oACWidget_{$sFieldName}.Search();\" data-tooltip-content='" . Dict::S('UI:Button:Search') . "'><i class=\"fas fa-search\"></i></a>";
|
||||
if (MetaModel::IsHierarchicalClass($sClass) !== false) {
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$sFieldName}\" onClick=\"oACWidget_{$sFieldName}.HKDisplay();\" data-tooltip-content='" . Dict::S('UI:Button:SearchInHierarchy') . "'><i class=\"fas fa-sitemap\"></i></a>";
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
if ($('#ac_tree_{$sFieldName}').length == 0)
|
||||
{
|
||||
$('body').append('<div id="ac_tree_{$sFieldName}"></div>');
|
||||
}
|
||||
JS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$sHTMLValue .= "</div>";
|
||||
$sHTMLValue .= "</div>";
|
||||
|
||||
return new Html($sHTMLValue);
|
||||
break;
|
||||
|
||||
case 'select_values':
|
||||
$aListValues = explode(',',$this->Get('values'));
|
||||
$oSelect = SelectUIBlockFactory::MakeForSelect($this->Get('placeholder'), $this->Get('placeholder'));
|
||||
$oSelect->AddCSSClass('ibo-input-field-wrapper');
|
||||
|
||||
foreach($aListValues as $sValue) {
|
||||
$oSelect->AddOption(SelectOptionUIBlockFactory::MakeForSelectOption($sValue, $sValue, ($sCurrentValue == $sValue)));
|
||||
}
|
||||
|
||||
return $oSelect;
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
$oInput = HtmlFactory::MakeRaw('<input type="number" id="'.$this->Get('placeholder').'" name="'.$this->Get('placeholder').'" value="'.$sCurrentValue.'"/>');
|
||||
return $oInput;
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
|
||||
$sFieldName = $this->Get('placeholder');
|
||||
$sDateFormatDatePicker = AttributeDate::GetFormat()->ToDatePicker();
|
||||
|
||||
$oInput = HtmlFactory::MakeRaw('<input type="text" id="'.$sFieldName.'" name="'.$sFieldName.'" value="'.$sCurrentValue.'"/>');
|
||||
|
||||
$oPage->add_ready_script(<<<EOF
|
||||
$('i#$sFieldName').datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: '$sDateFormatDatePicker',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
});
|
||||
EOF);
|
||||
|
||||
return $oInput;
|
||||
break;
|
||||
|
||||
default:
|
||||
return new Html('Not implemented yet');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user