N°8796 - Add PHP code style validation in iTop and extensions - format whole code base

This commit is contained in:
odain
2025-11-07 15:39:53 +01:00
parent 12f23113f5
commit 890a2568c8
2110 changed files with 53099 additions and 63885 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -38,7 +39,7 @@ $oP->LinkScriptFromAppRoot("js/wizardhelper.js");
$oP->LinkScriptFromAppRoot("js/wizard.utils.js");
$oP->LinkScriptFromAppRoot("js/extkeywidget.js");
$oP->LinkScriptFromAppRoot("js/jquery.blockUI.js");
// From now on the context is limited to the the selected organization ??
// Now render the content of the page
@@ -50,11 +51,9 @@ $sOperation = utils::ReadParam('operation', '');
$oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
//$sSearchHeaderForceDropdown
$sSearchHeaderForceDropdown = '<select id="select_class" name="baseClass" onChange="this.form.submit();">';
$aClassLabels = array();
$aClassLabels = [];
foreach (MetaModel::GetClasses('bizmodel, grant_by_profile') as $sCurrentClass) {
if ((MetaModel::HasCategory($sCurrentClass, 'grant_by_profile') && UserRights::IsActionAllowed($sCurrentClass, UR_ACTION_BULK_MODIFY))
|| (MetaModel::HasCategory($sCurrentClass, 'bizmodel') && UserRights::IsActionAllowed($sCurrentClass, UR_ACTION_BULK_READ))) {
@@ -62,8 +61,7 @@ foreach (MetaModel::GetClasses('bizmodel, grant_by_profile') as $sCurrentClass)
}
}
asort($aClassLabels);
foreach($aClassLabels as $sCurrentClass => $sLabel)
{
foreach ($aClassLabels as $sCurrentClass => $sLabel) {
$sDescription = MetaModel::GetClassDescription($sCurrentClass);
$sSelected = ($sCurrentClass == $sBaseClass) ? " SELECTED" : "";
$sSearchHeaderForceDropdown .= "<option value=\"$sCurrentClass\" title=\"$sDescription\"$sSelected>$sLabel</option>";
@@ -71,35 +69,24 @@ foreach($aClassLabels as $sCurrentClass => $sLabel)
$sSearchHeaderForceDropdown .= "</select>\n";
//end of $sSearchHeaderForceDropdown
try
{
if ($sOperation == 'search_form')
{
$sOQL = "SELECT $sClass $sOQLClause";
$oFilter = DBObjectSearch::FromOQL($sOQL);
}
else
{
try {
if ($sOperation == 'search_form') {
$sOQL = "SELECT $sClass $sOQLClause";
$oFilter = DBObjectSearch::FromOQL($sOQL);
} else {
// Second part: advanced search form:
if (!empty($sFilter))
{
if (!empty($sFilter)) {
$oFilter = DBSearch::unserialize($sFilter);
}
else if (!empty($sClass))
{
} elseif (!empty($sClass)) {
$oFilter = new DBObjectSearch($sClass);
}
}
}
catch (CoreException $e)
{
} catch (CoreException $e) {
$oFilter = new DBObjectSearch($sClass);
$oP->P("<b>".Dict::Format('UI:UniversalSearch:Error', $e->getHtmlDesc())."</b>");
}
if ($oFilter != null)
{
if ($oFilter != null) {
$oSet = new CMDBObjectSet($oFilter);
$oBlock = new DisplayBlock($oFilter, 'search', false);
$aExtraParams = $oAppContext->GetAsHash();
@@ -111,7 +98,7 @@ if ($oFilter != null)
$aExtraParams['submit_on_load'] = false;
$oBlock->Display($oP, 0, $aExtraParams);
// Search results
// Search results
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
$oResultBlock->Display($oP, 1);

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -34,14 +35,10 @@ require_once(APPROOT.'/application/ui.linkswidget.class.inc.php');
function IsIdField($sClassName, $sFieldCode)
{
$bResult = false;
if (!empty($sFieldCode))
{
if ($sFieldCode == 'id')
{
if (!empty($sFieldCode)) {
if ($sFieldCode == 'id') {
$bResult = true;
}
else if (strpos($sFieldCode, '->') === false)
{
} elseif (strpos($sFieldCode, '->') === false) {
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sFieldCode);
$bResult = $oAttDef->IsExternalKey();
}
@@ -61,26 +58,22 @@ function IsIdField($sClassName, $sFieldCode)
*/
function GetMappingsForExtKey($sAttCode, AttributeDefinition $oExtKeyAttDef, $bAdvanced)
{
$aResult = array();
$aResult = [];
$sTargetClass = $oExtKeyAttDef->GetTargetClass();
foreach(MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef)
{
if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode))
{
foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) {
if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode)) {
$bExtKey = $oTargetAttDef->IsExternalKey();
$sSuffix = '';
if ($bExtKey)
{
if ($bExtKey) {
$sSuffix = '->id';
}
if ($bAdvanced || !$bExtKey)
{
if ($bAdvanced || !$bExtKey) {
// When not in advanced mode do not allow to use reconciliation keys (on external keys) if they are themselves external keys !
$aResult[$sAttCode.'->'.$sTargetAttCode] = $oExtKeyAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel().$sSuffix;
}
}
}
return $aResult;
return $aResult;
}
/**
@@ -102,15 +95,15 @@ function GetMappingsForExtKey($sAttCode, AttributeDefinition $oExtKeyAttDef, $bA
*/
function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode, $sDefaultChoice)
{
$aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
$aChoices = ['' => Dict::S('UI:CSVImport:MappingSelectOne')];
$aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
$sFieldCode = ''; // Code of the attribute, if there is a match
$aMatches = array();
$aMatches = [];
if (preg_match('/^(.+)\*$/', $sFieldName, $aMatches)) {
// Remove any trailing "star" character.
// A star character at the end can be used to indicate a mandatory field
$sFieldName = $aMatches[1];
} else if (preg_match('/^(.+)\*->(.+)$/', $sFieldName, $aMatches)) {
} elseif (preg_match('/^(.+)\*->(.+)$/', $sFieldName, $aMatches)) {
// Remove any trailing "star" character before the arrow (->)
// A star character at the end can be used to indicate a mandatory field
$sFieldName = $aMatches[1].'->'.$aMatches[2];
@@ -135,7 +128,7 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo
// Note: Could not use "MetaModel::GetFriendlyNameAttributeCode($sTargetClass) === $sTargetAttCode" as it would return empty because the friendlyname is composite.
if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode) || ($oTargetAttDef instanceof AttributeFriendlyName)) {
$bExtKey = $oTargetAttDef->IsExternalKey();
$aSignatures = array();
$aSignatures = [];
$aSignatures[] = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel();
$aSignatures[] = $sAttCode.'->'.$sTargetAttCode;
if ($bExtKey) {
@@ -154,8 +147,7 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo
}
}
}
}
else if (
} elseif (
($oAttDef->IsWritable() && (!$oAttDef->IsLinkset() || ($bAdvancedMode && $oAttDef->IsIndirect())))
|| ($oAttDef instanceof AttributeFriendlyName)
) {
@@ -171,18 +163,17 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo
$bIsIdField = IsIdField($sClassName, $sFieldCode);
foreach ($aChoices as $sAttCode => $sLabel) {
$bSelected = false;
if ($bIsIdField && (!$bAdvancedMode)) // When not in advanced mode, ID are mapped to n/a
{
if ($bIsIdField && (!$bAdvancedMode)) { // When not in advanced mode, ID are mapped to n/a
if ($sAttCode == ':none:') {
$bSelected = true;
}
} else if (empty($sFieldCode) && (strpos($sFieldName, '->') !== false)) {
} elseif (empty($sFieldCode) && (strpos($sFieldName, '->') !== false)) {
if ($sAttCode == ':none:') {
$bSelected = true;
}
} else if (is_null($sDefaultChoice) && ($sFieldCode == $sAttCode)) {
} elseif (is_null($sDefaultChoice) && ($sFieldCode == $sAttCode)) {
$bSelected = true;
} else if (!is_null($sDefaultChoice) && ($sDefaultChoice == $sAttCode)) {
} elseif (!is_null($sDefaultChoice) && ($sDefaultChoice == $sAttCode)) {
$bSelected = true;
}
$oOption = SelectOptionUIBlockFactory::MakeForSelectOption($sAttCode, $sLabel, $bSelected);
@@ -192,19 +183,16 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo
return $oSelect;
}
try
{
try {
require_once(APPROOT.'/application/startup.inc.php');
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST);
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
$sOperation = utils::ReadParam('operation', '');
switch($sOperation)
{
switch ($sOperation) {
case 'parser_preview':
$oPage = new AjaxPage("");
$oPage->SetContentType('text/html');
@@ -245,7 +233,7 @@ try
$aColumns[] = '';
// first line as header
if($bFirstLineAsHeader){
if ($bFirstLineAsHeader) {
foreach ($aRow as $sCell) {
$aColumns[] = ["label" => utils::EscapeHtml($sCell)];
}
@@ -254,7 +242,7 @@ try
// default headers
for ($iDataColumnNumber = 0 ; $iDataColumnNumber < count($aRow) ; $iDataColumnNumber++) {
$aColumns[] = ["label" => Dict::Format('UI:CSVImport:Column', $iDataColumnNumber+1)];
$aColumns[] = ["label" => Dict::Format('UI:CSVImport:Column', $iDataColumnNumber + 1)];
}
}
@@ -289,8 +277,8 @@ try
$sInitFieldMapping = utils::ReadParam('init_field_mapping', '', false, 'raw_data');
$sInitSearchField = utils::ReadParam('init_search_field', '', false, 'raw_data');
$aInitFieldMapping = empty($sInitFieldMapping) ? array() : json_decode($sInitFieldMapping, true);
$aInitSearchField = empty($sInitSearchField) ? array() : json_decode($sInitSearchField, true);
$aInitFieldMapping = empty($sInitFieldMapping) ? [] : json_decode($sInitFieldMapping, true);
$aInitSearchField = empty($sInitSearchField) ? [] : json_decode($sInitSearchField, true);
$oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier, MetaModel::GetConfig()->Get('max_execution_time_per_loop'));
$aData = $oCSVParser->ToArray($iLinesToSkip, null, 3 /* Max: 1 header line + 2 lines of sample data */);
@@ -349,7 +337,7 @@ try
// Propose a reconciliation scheme
//
$aReconciliationKeys = MetaModel::GetReconcKeys($sClassName);
$aMoreReconciliationKeys = array(); // Store: key => void to automatically remove duplicates
$aMoreReconciliationKeys = []; // Store: key => void to automatically remove duplicates
foreach ($aReconciliationKeys as $sAttCode) {
if (!MetaModel::IsValidAttCode($sClassName, $sAttCode)) {
continue;
@@ -371,7 +359,7 @@ try
} else {
// The reconciliation scheme is given (navigating back in the wizard)
//
$aDefaultKeys = array();
$aDefaultKeys = [];
foreach ($aInitSearchField as $iSearchField => $void) {
$sAttCodeEx = $aInitFieldMapping[$iSearchField];
$aDefaultKeys[] = $sAttCodeEx;
@@ -380,7 +368,7 @@ try
}
// Read only attributes (will be forced to "search")
$aReadOnlyKeys = array();
$aReadOnlyKeys = [];
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
if (!$oAttDef->IsWritable()) {
$aReadOnlyKeys[] = $sAttCode;
@@ -397,7 +385,7 @@ try
EOF
);
}
break;
break;
case 'get_csv_template':
$sClassName = utils::ReadParam('class_name');
@@ -406,7 +394,7 @@ EOF
$oSearch = new DBObjectSearch($sClassName);
$oSearch->AddCondition('id', 0, '='); // Make sure we create an empty set
$oSet = new CMDBObjectSet($oSearch);
$sResult = cmdbAbstractObject::GetSetAsCSV($oSet, array('showMandatoryFields' => true));
$sResult = cmdbAbstractObject::GetSetAsCSV($oSet, ['showMandatoryFields' => true]);
$sClassDisplayName = MetaModel::GetName($sClassName);
$sDisposition = utils::ReadParam('disposition', 'inline');
@@ -419,8 +407,8 @@ EOF
require_once(APPROOT.'/application/excelexporter.class.inc.php');
$writer = new XLSXWriter();
$writer->setAuthor(UserRights::GetUserFriendlyName());
$aHeaders = array(0 => explode(',', $sResult)); // comma is the default separator
$writer->writeSheet($aHeaders, $sClassDisplayName, array());
$aHeaders = [0 => explode(',', $sResult)]; // comma is the default separator
$writer->writeSheet($aHeaders, $sClassDisplayName, []);
$oPage->add($writer->writeToString());
break;
@@ -446,9 +434,6 @@ EOF
break;
}
$oPage->output();
}
catch (Exception $e)
{
} catch (Exception $e) {
IssueLog::Error($e->getMessage());
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -22,16 +23,13 @@ use Combodo\iTop\Application\WebPage\DownloadPage;
require_once('../approot.inc.php');
require_once(APPROOT.'application/utils.inc.php');
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) && (strlen($_SERVER['HTTP_IF_MODIFIED_SINCE']) > 0))
{
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) && (strlen($_SERVER['HTTP_IF_MODIFIED_SINCE']) > 0)) {
// The content is garanteed to be unmodified since the URL includes a signature based on the contents of the document
header('Last-Modified: Mon, 1 January 2018 00:00:00 GMT', true, 304); // Any date in the past
exit;
}
try
{
try {
require_once(APPROOT.'/application/application.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
@@ -48,19 +46,14 @@ try
LoginWebPage::DoLoginEx('backoffice', false);
$id = utils::ReadParam('id', '');
$sField = utils::ReadParam('field', '');
if ($sClass == 'Attachment')
{
if ($sClass == 'Attachment') {
$iCacheSec = 31556926; // One year ahead: an attachment cannot change
}
else
{
} else {
$iCacheSec = (int)utils::ReadParam('cache', 0);
}
if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField))
{
if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField)) {
ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'attachment');
if ($iCacheSec > 0)
{
if ($iCacheSec > 0) {
$oPage->set_cache($iCacheSec);
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
@@ -88,7 +81,7 @@ try
$oPage->add_header("Last-Modified: Wed, 15 Jun 2016 13:21:15 GMT"); // An arbitrary date in the past is ok
}
break;
case 'dict':
$sSignature = Utils::ReadParam('s', ''); // Sanitization prevents / and ..
$oPage->SetContentType('text/javascript');
@@ -100,17 +93,14 @@ try
$oPage->add(file_get_contents(Utils::GetCachePath().$sSignature.'.js'));
break;
default:
$oPage->p("Invalid query.");
$oPage->p("Invalid query.");
}
$oPage->output();
}
catch (Exception $e)
{
} catch (Exception $e) {
// note: transform to cope with XSS attacks
echo utils::EscapeHtml($e->GetMessage());
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,8 +15,7 @@ require_once('../approot.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST);
try
{
try {
$oKPI = new ExecutionKPI();
$oKPI->ComputeAndReport('Data model loaded');
$oKPI = new ExecutionKPI();
@@ -23,8 +23,7 @@ try
LoginWebPage::DoLogin();
$sParams = utils::ReadParam('params', '', false, 'raw_data');
if (!$sParams)
{
if (!$sParams) {
throw new AjaxSearchException("Invalid query (empty filter)", 400);
}
@@ -36,61 +35,47 @@ try
$aListParams = (array)json_decode($sListParams, true);
$aParams = json_decode($sParams, true);
if (array_key_exists('hidden_criteria', $aListParams))
{
if (array_key_exists('hidden_criteria', $aListParams)) {
$sHiddenCriteria = $aListParams['hidden_criteria'];
}
else
{
} else {
$sHiddenCriteria = '';
}
$oFilter = CriterionParser::Parse($aParams['base_oql'], $aParams['criterion'], $sHiddenCriteria);
$oDisplayBlock = new DisplayBlock($oFilter, 'list_search', false);
foreach($aListParams as $key => $value)
{
$aExtraParams[$key] = $value;
}
foreach ($aListParams as $key => $value) {
$aExtraParams[$key] = $value;
}
if (array_key_exists('table_inner_id', $aListParams))
{
$sListId = utils::Sanitize($aListParams['table_inner_id'], '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
}
if (array_key_exists('table_inner_id', $aListParams)) {
$sListId = utils::Sanitize($aListParams['table_inner_id'], '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
}
if (array_key_exists('json', $aListParams))
{
if (array_key_exists('json', $aListParams)) {
$aJson = $aListParams['json'];
$sJson = json_encode($aJson);
$oWizardHelper = WizardHelper::FromJSON($sJson);
$oObj = $oWizardHelper->GetTargetObject();
if (array_key_exists('query_params', $aExtraParams))
{
if (array_key_exists('query_params', $aExtraParams)) {
$aExtraParams['query_params']['this->object()'] = $oObj;
}
else
{
$aExtraParams['query_params'] = array('this->object()' => $oObj);
} else {
$aExtraParams['query_params'] = ['this->object()' => $oObj];
}
}
if (!isset($aExtraParams['update_history']))
{
if (!isset($aExtraParams['update_history'])) {
$aExtraParams['update_history'] = true;
}
$aExtraParams['display_limit'] = true;
if (isset($sListId))
{
if (isset($sListId)) {
$oPage->AddUiBlock($oDisplayBlock->GetDisplay($oPage, $sListId, $aExtraParams));
}
else
{
} else {
$oDisplayBlock->RenderContent($oPage, $aExtraParams);
}
if (isset($aListParams['debug']) || UserRights::IsAdministrator())
{
if (isset($aListParams['debug']) || UserRights::IsAdministrator()) {
$oCollapsible = CollapsibleSectionUIBlockFactory::MakeStandard(Dict::S('UI:RunQuery:MoreInfo'));
$oPage->AddSubBlock($oCollapsible);
@@ -123,4 +108,4 @@ try
// note: transform to cope with XSS attacks
echo '<html><head></head><body><div>'.utils::EscapeHtml($e->GetMessage()).'</div></body></html>';
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -30,44 +31,34 @@ use Combodo\iTop\Application\WebPage\iTopWebPage;
*/
function FilterByContext(DBSearch &$oFilter, ApplicationContext $oAppContext)
{
$sObjClass = $oFilter->GetClass();
$sObjClass = $oFilter->GetClass();
$aContextParams = $oAppContext->GetNames();
$aCallSpec = array($sObjClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
foreach($aContextParams as $sParamName)
{
$aCallSpec = [$sObjClass, 'MapContextParam'];
if (is_callable($aCallSpec)) {
foreach ($aContextParams as $sParamName) {
$sValue = $oAppContext->GetCurrentValue($sParamName, null);
if ($sValue != null)
{
if ($sValue != null) {
$sAttCode = call_user_func($aCallSpec, $sParamName); // Returns null when there is no mapping for this parameter
if ( ($sAttCode != null) && MetaModel::IsValidAttCode($sObjClass, $sAttCode))
{
if (($sAttCode != null) && MetaModel::IsValidAttCode($sObjClass, $sAttCode)) {
// Check if the condition points to a hierarchical key
$bConditionAdded = false;
if ($sAttCode == 'id')
{
$bConditionAdded = false;
if ($sAttCode == 'id') {
// Filtering on the objects themselves
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sObjClass);
if ($sHierarchicalKeyCode !== false)
{
if ($sHierarchicalKeyCode !== false) {
$oRootFilter = new DBObjectSearch($sObjClass);
$oRootFilter->AddCondition($sAttCode, $sValue);
$oFilter->AddCondition_PointingTo($oRootFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
$bConditionAdded = true;
}
}
else
{
} else {
$oAttDef = MetaModel::GetAttributeDef($sObjClass, $sAttCode);
$bConditionAdded = false;
if ($oAttDef->IsExternalKey())
{
if ($oAttDef->IsExternalKey()) {
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
if ($sHierarchicalKeyCode !== false)
{
if ($sHierarchicalKeyCode !== false) {
$oRootFilter = new DBObjectSearch($oAttDef->GetTargetClass());
$oRootFilter->AddCondition('id', $sValue);
$oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
@@ -77,8 +68,7 @@ function FilterByContext(DBSearch &$oFilter, ApplicationContext $oAppContext)
}
}
}
if (!$bConditionAdded)
{
if (!$bConditionAdded) {
$oFilter->AddCondition($sAttCode, $sValue);
}
}
@@ -105,37 +95,28 @@ function GetRuleResultFilter($iRuleId, $oDefinitionFilter, $oAppContext)
$oRuleFilter->UpdateContextFromUser();
FilterByContext($oRuleFilter, $oAppContext); // Not needed since this filter is a subset of the definition filter, but may speedup things
if ($oRule->Get('valid_flag') == 'false')
{
if ($oRule->Get('valid_flag') == 'false') {
// The query returns directly the invalid elements
$oFilter = $oRuleFilter->Intersect($oDefinitionFilter);
}
else
{
} else {
// The query returns only the valid elements, all the others are invalid
// Warning : we're generating a `WHERE ID IN`... query, and this could be very slow if there are lots of id !
$aValidRows = $oRuleFilter->ToDataArray(array('id'));
$aValidIds = array();
foreach($aValidRows as $aRow)
{
$aValidRows = $oRuleFilter->ToDataArray(['id']);
$aValidIds = [];
foreach ($aValidRows as $aRow) {
$aValidIds[] = $aRow['id'];
}
/** @var \DBObjectSearch $oFilter */
$oFilter = $oDefinitionFilter->DeepClone();
if (count($aValidIds) > 0)
{
$aInDefSet = array();
foreach($oDefinitionFilter->ToDataArray(array('id')) as $aRow)
{
if (count($aValidIds) > 0) {
$aInDefSet = [];
foreach ($oDefinitionFilter->ToDataArray(['id']) as $aRow) {
$aInDefSet[] = $aRow['id'];
}
$aInvalids = array_diff($aInDefSet, $aValidIds);
if (count($aInvalids) > 0)
{
if (count($aInvalids) > 0) {
$oFilter->AddConditionForInOperatorUsingParam('id', $aInvalids, true);
}
else
{
} else {
$oFilter->AddCondition('id', 0, '=');
}
}
@@ -143,8 +124,7 @@ function GetRuleResultFilter($iRuleId, $oDefinitionFilter, $oAppContext)
return $oFilter;
}
try
{
try {
require_once('../approot.inc.php');
require_once(APPROOT.'/application/application.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
@@ -153,85 +133,77 @@ try
$bSelectionAuditRulesByDefault = utils::GetConfig()->Get('audit.enable_selection_landing_page');
$operation = utils::ReadParam('operation', $bSelectionAuditRulesByDefault ? 'selection' : 'audit');
$oAppContext = new ApplicationContext();
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
$oP = new iTopWebPage(Dict::S('UI:Audit:Title'));
switch($operation)
{
switch ($operation) {
case 'csv':
$oP->DisableBreadCrumb();
// Big result sets cause long OQL that cannot be passed (serialized) as a GET parameter
// Therefore we don't use the standard "search_oql" operation of UI.php to display the CSV
$iCategory = utils::ReadParam('category', '');
$iRuleIndex = utils::ReadParam('rule', 0);
$oAuditCategory = MetaModel::GetObject('AuditCategory', $iCategory);
$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
$oDefinitionFilter->UpdateContextFromUser();
FilterByContext($oDefinitionFilter, $oAppContext);
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
$oFilter = GetRuleResultFilter($iRuleIndex, $oDefinitionFilter, $oAppContext);
$oErrorObjectSet = new CMDBObjectSet($oFilter);
$oAuditRule = MetaModel::GetObject('AuditRule', $iRuleIndex);
$sFileName = utils::ReadParam('filename', null, true, 'string');
$bAdvanced = utils::ReadParam('advanced', false);
$sAdvanced = $bAdvanced ? '&advanced=1' : '';
if ($sFileName != null)
{
$oP = new CSVPage("iTop - Export");
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oErrorObjectSet, array('localize_values' => true, 'fields_advanced' => $bAdvanced), $sCharset);
if ($sCharset == 'UTF-8')
{
$sOutputData = UTF8_BOM.$sCSVData;
}
else
{
$sOutputData = $sCSVData;
}
if ($sFileName == '')
{
// Plain text => Firefox will NOT propose to download the file
$oP->add_header("Content-type: text/plain; charset=$sCharset");
}
else
{
$sCSVName = basename($sFileName); // pseudo sanitization, just in case
// Force the name of the downloaded file, since windows gives precedence to the extension over of the mime type
$oP->add_header("Content-disposition: attachment; filename=\"$sCSVName\"");
$oP->add_header("Content-type: text/csv; charset=$sCharset");
}
$oP->add($sOutputData);
$oP->TrashUnexpectedOutput();
$oP->output();
exit;
} else {
$sTitle = Dict::S('UI:Audit:AuditErrors');
$oP->SetBreadCrumbEntry('ui-tool-auditerrors', $sTitle, '', '', 'fas fa-stethoscope', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->DisableBreadCrumb();
// Big result sets cause long OQL that cannot be passed (serialized) as a GET parameter
// Therefore we don't use the standard "search_oql" operation of UI.php to display the CSV
$iCategory = utils::ReadParam('category', '');
$iRuleIndex = utils::ReadParam('rule', 0);
$oBackButton = ButtonUIBlockFactory::MakeIconLink('fas fa-chevron-left', Dict::S('UI:Audit:InteractiveAudit:Back'), "./audit.php?".$oAppContext->GetForLink());
$oP->AddUiBlock($oBackButton);
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle.$oAuditRule->Get('description')));
$oAuditCategory = MetaModel::GetObject('AuditCategory', $iCategory);
$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
$oDefinitionFilter->UpdateContextFromUser();
FilterByContext($oDefinitionFilter, $oAppContext);
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
$oFilter = GetRuleResultFilter($iRuleIndex, $oDefinitionFilter, $oAppContext);
$oErrorObjectSet = new CMDBObjectSet($oFilter);
$oAuditRule = MetaModel::GetObject('AuditRule', $iRuleIndex);
$sFileName = utils::ReadParam('filename', null, true, 'string');
$bAdvanced = utils::ReadParam('advanced', false);
$sAdvanced = $bAdvanced ? '&advanced=1' : '';
$sBlockId = 'audit_errors';
$oP->p("<div id=\"$sBlockId\">");
$oBlock = DisplayBlock::FromObjectSet($oErrorObjectSet, 'csv', array('show_obsolete_data' => true));
$oBlock->Display($oP, 1);
$oP->p("</div>");
// Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
$oP->add_ready_script(" $('#1>textarea').height(400);"); // adjust the size of the block
$sExportUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey();
$oDownloadButton = ButtonUIBlockFactory::MakeForAlternativePrimaryAction('fas fa-chevron-left', Dict::S('UI:Audit:InteractiveAudit:Back'), "./audit.php?".$oAppContext->GetForLink());
if ($sFileName != null) {
$oP = new CSVPage("iTop - Export");
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oErrorObjectSet, ['localize_values' => true, 'fields_advanced' => $bAdvanced], $sCharset);
if ($sCharset == 'UTF-8') {
$sOutputData = UTF8_BOM.$sCSVData;
} else {
$sOutputData = $sCSVData;
}
if ($sFileName == '') {
// Plain text => Firefox will NOT propose to download the file
$oP->add_header("Content-type: text/plain; charset=$sCharset");
} else {
$sCSVName = basename($sFileName); // pseudo sanitization, just in case
// Force the name of the downloaded file, since windows gives precedence to the extension over of the mime type
$oP->add_header("Content-disposition: attachment; filename=\"$sCSVName\"");
$oP->add_header("Content-type: text/csv; charset=$sCharset");
}
$oP->add($sOutputData);
$oP->TrashUnexpectedOutput();
$oP->output();
exit;
} else {
$sTitle = Dict::S('UI:Audit:AuditErrors');
$oP->SetBreadCrumbEntry('ui-tool-auditerrors', $sTitle, '', '', 'fas fa-stethoscope', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oBackButton = ButtonUIBlockFactory::MakeIconLink('fas fa-chevron-left', Dict::S('UI:Audit:InteractiveAudit:Back'), "./audit.php?".$oAppContext->GetForLink());
$oP->AddUiBlock($oBackButton);
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle.$oAuditRule->Get('description')));
$sBlockId = 'audit_errors';
$oP->p("<div id=\"$sBlockId\">");
$oBlock = DisplayBlock::FromObjectSet($oErrorObjectSet, 'csv', ['show_obsolete_data' => true]);
$oBlock->Display($oP, 1);
$oP->p("</div>");
// Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
$oP->add_ready_script(" $('#1>textarea').height(400);"); // adjust the size of the block
$sExportUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey();
$oDownloadButton = ButtonUIBlockFactory::MakeForAlternativePrimaryAction('fas fa-chevron-left', Dict::S('UI:Audit:InteractiveAudit:Back'), "./audit.php?".$oAppContext->GetForLink());
$oP->add_ready_script("$('a[href*=\"webservices/export.php?expression=\"]').attr('href', '".$sExportUrl."&filename=audit.csv".$sAdvanced."');");
$oP->add_ready_script("$('#1 :checkbox').removeAttr('onclick').on('click', function() { var sAdvanced = ''; if (this.checked) sAdvanced = '&advanced=1'; window.location.href='$sExportUrl'+sAdvanced; } );");
}
break;
$oP->add_ready_script("$('a[href*=\"webservices/export.php?expression=\"]').attr('href', '".$sExportUrl."&filename=audit.csv".$sAdvanced."');");
$oP->add_ready_script("$('#1 :checkbox').removeAttr('onclick').on('click', function() { var sAdvanced = ''; if (this.checked) sAdvanced = '&advanced=1'; window.location.href='$sExportUrl'+sAdvanced; } );");
}
break;
case 'errors':
$sTitle = Dict::S('UI:Audit:AuditErrors');
$iCategory = utils::ReadParam('category', '');
@@ -253,7 +225,7 @@ try
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle.$oAuditRule->Get('description')));
$sBlockId = 'audit_errors';
$oP->p("<div id=\"$sBlockId\">");
$oBlock = DisplayBlock::FromObjectSet($oErrorObjectSet, 'list', array('show_obsolete_data' => true));
$oBlock = DisplayBlock::FromObjectSet($oErrorObjectSet, 'list', ['show_obsolete_data' => true]);
$oBlock->Display($oP, 1);
$oP->p("</div>");
$sExportUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey();
@@ -299,13 +271,13 @@ try
// Fetch all audit domains with at least on linked category
$oDomainSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT AuditDomain AS domain JOIN lnkAuditCategoryToAuditDomain AS lnk ON lnk.domain_id = domain.id"));
$oDomainSet->SetOrderBy(array('name' => true));
$oDomainSet->SetOrderBy(['name' => true]);
$iDomainCnt = 0;
/** @var AuditDomain $oAuditDomain */
while($oAuditDomain = $oDomainSet->Fetch()) {
while ($oAuditDomain = $oDomainSet->Fetch()) {
$sDomainUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit&domain=".$oAuditDomain->GetKey();
$sIconUrl = utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-puzzle.svg';
/** @var \ormDocument $oImage */
/** @var \ormDocument $oImage */
$oImage = $oAuditDomain->Get('icon');
if (!$oImage->IsEmpty()) {
$sIconUrl = $oImage->GetDisplayURL(get_class($oAuditDomain), $oAuditDomain->GetKey(), 'icon');
@@ -333,7 +305,7 @@ try
$sBreadCrumbTooltip = Dict::S('UI:Audit:Interactive:All:BreadCrumb+');
if (!empty($sCategories)) { // Case with a set of categories
$oCategoriesSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT AuditCategory WHERE id IN (:categories)", array('categories' => explode(',', $sCategories))));
$oCategoriesSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT AuditCategory WHERE id IN (:categories)", ['categories' => explode(',', $sCategories)]));
$sCategories = implode(", ", $oCategoriesSet->GetColumnAsArray('name'));
$oCategoriesSet->Rewind();
$sTitle = Dict::Format('UI:Audit:Interactive:Categories:Title', $sCategories);
@@ -343,7 +315,7 @@ try
} elseif (!empty($sDomainKey)) { // Case with a single Domain
$oAuditDomain = MetaModel::GetObject('AuditDomain', $sDomainKey);
$oCategoriesSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT AuditCategory AS c JOIN lnkAuditCategoryToAuditDomain AS lnk ON lnk.category_id = c.id WHERE lnk.domain_id = :domain", array('domain' => $oAuditDomain->GetKey())));
$oCategoriesSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT AuditCategory AS c JOIN lnkAuditCategoryToAuditDomain AS lnk ON lnk.category_id = c.id WHERE lnk.domain_id = :domain", ['domain' => $oAuditDomain->GetKey()]));
$sDomainName = $oAuditDomain->GetName();
$sTitle = Dict::Format('UI:Audit:Interactive:Domain:Title', $sDomainName);
$sSubTitle = Dict::Format('UI:Audit:Interactive:Domain:SubTitle', $sDomainName);
@@ -400,16 +372,16 @@ try
// Add a button in the above toolbar
$sAuditCategoryClass = get_class($oAuditCategory);
if (UserRights::IsActionAllowed($sAuditCategoryClass, UR_ACTION_READ)) {
$oToolbar->AddSubBlock(ButtonUIBlockFactory::MakeIconLink('fas fa-wrench fa-lg', Dict::S('UI:Audit:ViewRules'), ApplicationContext::MakeObjectUrl($sAuditCategoryClass, $oAuditCategory->GetKey()).'&#ObjectProperties=tab_ClassAuditCategoryAttributerules_list'),);
$oToolbar->AddSubBlock(ButtonUIBlockFactory::MakeIconLink('fas fa-wrench fa-lg', Dict::S('UI:Audit:ViewRules'), ApplicationContext::MakeObjectUrl($sAuditCategoryClass, $oAuditCategory->GetKey()).'&#ObjectProperties=tab_ClassAuditCategoryAttributerules_list'), );
}
$aResults = array();
$aResults = [];
try {
$iCount = 0;
$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
$oDefinitionFilter->UpdateContextFromUser();
FilterByContext($oDefinitionFilter, $oAppContext);
$aObjectsWithErrors = array();
$aObjectsWithErrors = [];
if (!empty($currentOrganization)) {
if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id')) {
$oDefinitionFilter->AddCondition('org_id', $currentOrganization, '=');
@@ -421,7 +393,7 @@ try
$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey(), '=');
$oRulesSet = new DBObjectSet($oRulesFilter);
while ($oAuditRule = $oRulesSet->fetch()) {
$aRow = array();
$aRow = [];
$aRow['description'] = $oAuditRule->GetName();
if ($iCount == 0) {
// nothing to check, really !
@@ -431,16 +403,15 @@ try
} else {
try {
$oFilter = GetRuleResultFilter($oAuditRule->GetKey(), $oDefinitionFilter, $oAppContext);
$aErrors = $oFilter->SelectAttributeToArray('id');
$aErrors = $oFilter->SelectAttributeToArray('id');
$iErrorsCount = count($aErrors);
foreach ($aErrors as $aErrorRow) {
$aObjectsWithErrors[$aErrorRow['id']] = true;
}
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey().$oAppContext->GetForLink(true)."\">$iErrorsCount</a> <a href=\"?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey().$oAppContext->GetForLink(true)."\"><img src=\"" . utils::GetAbsoluteUrlAppRoot() . "images/icons/icons8-export-csv.svg\" class=\"ibo-audit--audit-line--csv-download\"></a>";
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey().$oAppContext->GetForLink(true)."\">$iErrorsCount</a> <a href=\"?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey().$oAppContext->GetForLink(true)."\"><img src=\"".utils::GetAbsoluteUrlAppRoot()."images/icons/icons8-export-csv.svg\" class=\"ibo-audit--audit-line--csv-download\"></a>";
$aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount));
$aRow['class'] = $oAuditCategory->GetReportColor($iCount, $iErrorsCount);
}
catch (Exception $e) {
} catch (Exception $e) {
$aRow['nb_errors'] = Dict::S('UI:Audit:OqlError');
$aRow['percent_ok'] = Dict::S('UI:Audit:Error:ValueNA');
$aRow['class'] = 'red';
@@ -462,57 +433,50 @@ try
$oWorkingBlock->SetCount((int)$oWorkingBlock->GetCount() + ($iCount - $iTotalErrors));
$oAuditCategoryPanelBlock->SetSubTitle(Dict::Format('UI:Audit:AuditCategory:Subtitle', $iTotalErrors, $iCount, $sOverallPercentOk));
} catch (Exception $e) {
$sMessage = Dict::Format('UI:Audit:ErrorIn_Category_Reason', $oAuditCategory->GetHyperlink(), utils::HtmlEntities($e->getMessage()));
$oErrorAlert = AlertUIBlockFactory::MakeForFailure(Dict::S('UI:Audit:ErrorIn_Category'), $sMessage);
$oErrorAlert->AddCSSClass('ibo-audit--error-alert');
$oP->AddUiBlock($oErrorAlert);
continue;
}
catch(Exception $e)
{
$sMessage = Dict::Format('UI:Audit:ErrorIn_Category_Reason', $oAuditCategory->GetHyperlink(), utils::HtmlEntities($e->getMessage()));
$oErrorAlert = AlertUIBlockFactory::MakeForFailure(Dict::S('UI:Audit:ErrorIn_Category'), $sMessage);
$oErrorAlert->AddCSSClass('ibo-audit--error-alert');
$oP->AddUiBlock($oErrorAlert);
continue;
$oAuditCategoryPanelBlock->SetColorFromColorSemantic($sClass);
$oAuditCategoryPanelBlock->AddCSSClass('ibo-audit--audit-category--panel');
$aData = [];
foreach ($aResults as $aRow) {
$aData[] = [
'audit_rule' => $aRow['description'],
'nb_err' => $aRow['nb_errors'],
'percentage_ok' => $aRow['percent_ok'],
'@class' => 'ibo-is-'.$aRow['class'].'',
];
}
$aAttribs = [
'audit_rule' => ['label' => Dict::S('UI:Audit:HeaderAuditRule'), 'description' => Dict::S('UI:Audit:HeaderAuditRule')],
'nb_err' => ['label' => Dict::S('UI:Audit:HeaderNbErrors'), 'description' => Dict::S('UI:Audit:HeaderNbErrors')],
'percentage_ok' => ['label' => Dict::S('UI:Audit:PercentageOk'), 'description' => Dict::S('UI:Audit:PercentageOk')],
];
$oAttachmentTableBlock = DataTableUIBlockFactory::MakeForStaticData('', $aAttribs, $aData, null, [], "", ['pageLength' => -1]);
$oAuditCategoryPanelBlock->AddSubBlock($oAttachmentTableBlock);
$aAuditCategoryPanels[] = $oAuditCategoryPanelBlock;
}
$oAuditCategoryPanelBlock->SetColorFromColorSemantic($sClass);
$oAuditCategoryPanelBlock->AddCSSClass('ibo-audit--audit-category--panel');
$aData = [];
foreach($aResults as $aRow)
{
$aData[] = array(
'audit_rule' => $aRow['description'],
'nb_err' => $aRow['nb_errors'],
'percentage_ok' => $aRow['percent_ok'],
'@class' => 'ibo-is-'.$aRow['class'].'',
);
foreach ($aAuditCategoryPanels as $oAuditCategoryPanel) {
$oP->AddUiBlock($oAuditCategoryPanel);
}
$aAttribs = array(
'audit_rule' => array('label' => Dict::S('UI:Audit:HeaderAuditRule'), 'description' => Dict::S('UI:Audit:HeaderAuditRule')),
'nb_err' => array('label' => Dict::S('UI:Audit:HeaderNbErrors'), 'description' => Dict::S('UI:Audit:HeaderNbErrors')),
'percentage_ok' => array('label' => Dict::S('UI:Audit:PercentageOk'), 'description' => Dict::S('UI:Audit:PercentageOk')),
);
$oAttachmentTableBlock = DataTableUIBlockFactory::MakeForStaticData('', $aAttribs, $aData, null, [], "", array('pageLength' => -1));
$oAuditCategoryPanelBlock->AddSubBlock($oAttachmentTableBlock);
$aAuditCategoryPanels[] = $oAuditCategoryPanelBlock;
}
foreach ($aAuditCategoryPanels as $oAuditCategoryPanel) {
$oP->AddUiBlock($oAuditCategoryPanel);
}
}
$oP->output();
}
catch(CoreException $e)
{
} catch (CoreException $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc()));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -529,19 +493,15 @@ catch(CoreException $e)
// For debugging only
//throw $e;
}
catch(Exception $e)
{
} catch (Exception $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -549,7 +509,7 @@ catch(Exception $e)
$oLog->Set('issue', 'PHP Exception');
$oLog->Set('impact', 'Page could not be displayed');
$oLog->Set('callstack', $e->getTrace());
$oLog->Set('data', array());
$oLog->Set('data', []);
$oLog->DBInsertNoReload();
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -87,8 +88,8 @@ try {
$oSelectBlock = SelectUIBlockFactory::MakeForSelect($sName, 'select_'.$sName);
$oOption = SelectOptionUIBlockFactory::MakeForSelectOption("", Dict::S('UI:CSVImport:ClassesSelectOne'), false);
$oSelectBlock->AddSubBlock($oOption);
$aValidClasses = array();
$aClassCategories = array('bizmodel', 'addon/authentication');
$aValidClasses = [];
$aClassCategories = ['bizmodel', 'addon/authentication'];
if ($bAdvanced) {
$aClassCategories[] = 'grant_by_profile';
}
@@ -136,10 +137,9 @@ try {
*/
function CountCharsFromSet($sString, $aSet)
{
$aResult = array();
$aResult = [];
$aCount = count_chars($sString);
foreach($aSet as $sChar)
{
foreach ($aSet as $sChar) {
$aResult[$sChar] = isset($aCount[ord($sChar)]) ? $aCount[ord($sChar)] : 0;
}
return $aResult;
@@ -155,35 +155,33 @@ try {
{
$iLine = 0;
$iMaxLine = 20; // Process max 20 lines to guess the parameters
foreach($aPossibleSeparators as $sSep)
{
foreach ($aPossibleSeparators as $sSep) {
$aGuesses[$sSep]['total'] = $aGuesses[$sSep]['max'] = 0;
$aGuesses[$sSep]['min'] = 999;
}
$aStats = array();
while(($iLine < count($aCSVData)) && ($iLine < $iMaxLine) )
{
if (strlen($aCSVData[$iLine]) > 0)
{
$aStats = [];
while (($iLine < count($aCSVData)) && ($iLine < $iMaxLine)) {
if (strlen($aCSVData[$iLine]) > 0) {
$aStats[$iLine] = CountCharsFromSet($aCSVData[$iLine], $aPossibleSeparators);
}
$iLine++;
}
$iLine = 1;
foreach($aStats as $aLineStats)
{
foreach($aPossibleSeparators as $sSep)
{
foreach ($aStats as $aLineStats) {
foreach ($aPossibleSeparators as $sSep) {
$aGuesses[$sSep]['total'] += $aLineStats[$sSep];
if ($aLineStats[$sSep] > $aGuesses[$sSep]['max']) $aGuesses[$sSep]['max'] = $aLineStats[$sSep];
if ($aLineStats[$sSep] < $aGuesses[$sSep]['min']) $aGuesses[$sSep]['min'] = $aLineStats[$sSep];
if ($aLineStats[$sSep] > $aGuesses[$sSep]['max']) {
$aGuesses[$sSep]['max'] = $aLineStats[$sSep];
}
if ($aLineStats[$sSep] < $aGuesses[$sSep]['min']) {
$aGuesses[$sSep]['min'] = $aLineStats[$sSep];
}
}
$iLine++;
}
$aScores = array();
foreach($aGuesses as $sSep => $aData)
{
$aScores = [];
foreach ($aGuesses as $sSep => $aData) {
$aScores[$sSep] = $aData['total'] + $aData['max'] - $aData['min'];
}
arsort($aScores, SORT_NUMERIC); // Sort the array, higher scores first
@@ -200,10 +198,10 @@ try {
function GuessParameters($sCSVData)
{
$aData = explode("\n", $sCSVData);
$sSeparator = GuessFromFrequency($aData, array("\t", ',', ';', '|')); // Guess the most frequent (and regular) character on each line
$sQualifier = GuessFromFrequency($aData, array('"', "'")); // Guess the most frequent (and regular) character on each line
$sSeparator = GuessFromFrequency($aData, ["\t", ',', ';', '|']); // Guess the most frequent (and regular) character on each line
$sQualifier = GuessFromFrequency($aData, ['"', "'"]); // Guess the most frequent (and regular) character on each line
return array('separator' => $sSeparator, 'qualifier' => $sQualifier);
return ['separator' => $sSeparator, 'qualifier' => $sQualifier];
}
/**
@@ -212,10 +210,10 @@ try {
* @param string $sClass The class of objects to synchronize
* @param integer $iCount The number of objects to synchronize
*/
function DisplaySynchroBanner(WebPage $oP, $sClass, $iCount)
{
$oP->AddSubBlock(AlertUIBlockFactory::MakeForInformation(MetaModel::GetClassIcon($sClass)."&nbsp;".Dict::Format('UI:Title:BulkSynchro_nbItem_ofClass_class', $iCount, MetaModel::GetName($sClass))));
}
function DisplaySynchroBanner(WebPage $oP, $sClass, $iCount)
{
$oP->AddSubBlock(AlertUIBlockFactory::MakeForInformation(MetaModel::GetClassIcon($sClass)."&nbsp;".Dict::Format('UI:Title:BulkSynchro_nbItem_ofClass_class', $iCount, MetaModel::GetName($sClass))));
}
/**
* Process the CSV data, for real or as a simulation
@@ -232,11 +230,11 @@ try {
}
// CSRF transaction id verification
if(!utils::IsTransactionValid(utils::ReadPostedParam('transaction_id', '', 'raw_data'))){
if (!utils::IsTransactionValid(utils::ReadPostedParam('transaction_id', '', 'raw_data'))) {
throw new CoreException(Dict::S('UI:Error:InvalidToken'));
}
$aResult = array();
$aResult = [];
$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
@@ -244,23 +242,41 @@ try {
$bHeaderLine = (utils::ReadParam('header_line', '0') == 1);
$iNbSkippedLines = utils::ReadParam('nb_skipped_lines', '0');
$iBoxSkipLines = utils::ReadParam('box_skiplines', '0');
$aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
$aFieldsMapping = utils::ReadParam('field', [], false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', [], false, 'field_name');
$iCurrentStep = $bSimulate ? 4 : 5;
$bAdvanced = utils::ReadParam('advanced', 0);
$sEncoding = utils::ReadParam('encoding', 'UTF-8');
$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
$aSynchroUpdate = utils::ReadParam('synchro_update', array());
$aSynchroUpdate = utils::ReadParam('synchro_update', []);
$sDateTimeFormat = utils::ReadParam('date_time_format', 'default');
$sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', (string)AttributeDateTime::GetFormat(), false, 'raw_data');
return CSVImportPageProcessor::ProcessData($iBoxSkipLines, $iNbSkippedLines, $sDateTimeFormat, $sCustomDateTimeFormat, $sClassName, $oPage, $aSynchroUpdate, $sCSVData, $sSeparator, $sTextQualifier, $bHeaderLine, $aResult, $aSearchFields, $aFieldsMapping, $bSimulate, $sCSVDataTruncated,
$iCurrentStep, $sEncoding,
$bAdvanced, $sSynchroScope);
return CSVImportPageProcessor::ProcessData(
$iBoxSkipLines,
$iNbSkippedLines,
$sDateTimeFormat,
$sCustomDateTimeFormat,
$sClassName,
$oPage,
$aSynchroUpdate,
$sCSVData,
$sSeparator,
$sTextQualifier,
$bHeaderLine,
$aResult,
$aSearchFields,
$aFieldsMapping,
$bSimulate,
$sCSVDataTruncated,
$iCurrentStep,
$sEncoding,
$bAdvanced,
$sSynchroScope
);
}
/**
* Perform the actual load of the CSV data and display the results
* @param WebPage $oPage The web page to display the wizard
@@ -306,14 +322,14 @@ try {
$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
if ($sSeparator == 'tab') $sSeparator = "\t";
if ($sSeparator == 'other')
{
if ($sSeparator == 'tab') {
$sSeparator = "\t";
}
if ($sSeparator == 'other') {
$sSeparator = utils::ReadParam('other_separator', ',', false, 'raw_data');
}
$sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data');
if ($sTextQualifier == 'other')
{
if ($sTextQualifier == 'other') {
$sTextQualifier = utils::ReadParam('other_qualifier', '"', false, 'raw_data');
}
$bHeaderLine = (utils::ReadParam('header_line', '0') == 1);
@@ -333,7 +349,7 @@ try {
$oClassesSelect = SelectUIBlockFactory::MakeForSelect("class_name", "select_class_name");
$oDefaultSelect = SelectOptionUIBlockFactory::MakeForSelectOption("$sClassName", MetaModel::GetName($sClassName), true);
$oClassesSelect->AddSubBlock($oDefaultSelect);
$aSynchroUpdate = utils::ReadParam('synchro_update', array());
$aSynchroUpdate = utils::ReadParam('synchro_update', []);
} else {
$oClassesSelect = GetClassesSelectUIBlock('class_name', $sClassName, UR_ACTION_BULK_MODIFY, (bool)$bAdvanced);
}
@@ -381,7 +397,7 @@ try {
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope));
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("date_time_format", $sDateTimeFormat));
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("custom_date_time_format", $sCustomDateTimeFormat));
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("transaction_id", utils::GetNewTransactionId(), "transaction_id")); // adding transaction_id field for next step (simulation)
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("transaction_id", utils::GetNewTransactionId(), "transaction_id")); // adding transaction_id field for next step (simulation)
if (!empty($sSynchroScope)) {
foreach ($aSynchroUpdate as $sKey => $value) {
@@ -403,10 +419,9 @@ try {
$('#advanced').on('click', function(ev) { DoReload(); } );
EOF
);
if ($sClassName != '')
{
$aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
if ($sClassName != '') {
$aFieldsMapping = utils::ReadParam('field', [], false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', [], false, 'field_name');
$sFieldsMapping = addslashes(json_encode($aFieldsMapping));
$sSearchFields = addslashes(json_encode($aSearchFields));
@@ -414,7 +429,7 @@ EOF
}
$oPage->add_script(
<<<EOF
<<<EOF
var aDefaultKeys = new Array();
var aReadOnlyKeys = new Array();
@@ -633,7 +648,7 @@ EOF
}
}
EOF
);
);
}
/**
@@ -645,35 +660,29 @@ EOF
{
$sOperation = utils::ReadParam('operation', 'csv_data');
$sCSVData = '';
switch($sOperation)
{
switch ($sOperation) {
case 'file_upload':
$oDocument = utils::ReadPostedDocument('csvdata');
if (!$oDocument->IsEmpty())
{
$sCSVData = $oDocument->GetData();
}
break;
$oDocument = utils::ReadPostedDocument('csvdata');
if (!$oDocument->IsEmpty()) {
$sCSVData = $oDocument->GetData();
}
break;
default:
$sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data');
$sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data');
}
$sEncoding = utils::ReadParam('encoding', 'UTF-8');
// Compute a subset of the data set, now that we know the charset
if ($sEncoding == 'UTF-8')
{
if ($sEncoding == 'UTF-8') {
// Remove the BOM if any
if (substr($sCSVData, 0, 3) == UTF8_BOM)
{
if (substr($sCSVData, 0, 3) == UTF8_BOM) {
$sCSVData = substr($sCSVData, 3);
}
// Clean the input
// Todo: warn the user if some characters are lost/substituted
$sUTF8Data = iconv('UTF-8', 'UTF-8//IGNORE//TRANSLIT', $sCSVData);
}
else
{
} else {
$sUTF8Data = iconv($sEncoding, 'UTF-8//IGNORE//TRANSLIT', $sCSVData);
}
@@ -682,16 +691,15 @@ EOF
$iSkippedLines = utils::ReadParam('nb_skipped_lines', '');
$bBoxSkipLines = utils::ReadParam('box_skiplines', 0);
$sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data');
if ($sTextQualifier == '') // May be set to an empty value by the previous page
{
if ($sTextQualifier == '') { // May be set to an empty value by the previous page
$sTextQualifier = $aGuesses['qualifier'];
}
$sOtherTextQualifier = in_array($sTextQualifier, array('"', "'")) ? '' : $sTextQualifier;
$sOtherTextQualifier = in_array($sTextQualifier, ['"', "'"]) ? '' : $sTextQualifier;
$bHeaderLine = utils::ReadParam('header_line', 0);
$sClassName = utils::ReadParam('class_name', '', false, 'class');
$bAdvanced = utils::ReadParam('advanced', 0);
$aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
$aFieldsMapping = utils::ReadParam('field', [], false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', [], false, 'field_name');
// Create a truncated version of the data used for the fast preview
// Take about 20 lines of data... knowing that some lines may contain carriage returns
@@ -721,7 +729,7 @@ EOF
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
DisplaySynchroBanner($oPage, $sClassName, $iCount);
$aSynchroUpdate = utils::ReadParam('synchro_update', array());
$aSynchroUpdate = utils::ReadParam('synchro_update', []);
}
$oPanel = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:CSVImportStep2'));
$oPage->AddSubBlock($oPanel);
@@ -729,7 +737,6 @@ EOF
$oForm = FormUIBlockFactory::MakeStandard('wizForm');
$oPage->AddSubBlock($oForm);
$oContainer = PanelUIBlockFactory::MakeNeutral('');
$oForm->AddSubBlock($oContainer);
@@ -741,20 +748,19 @@ EOF
$oFieldSetSeparator = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:SeparatorCharacter'));
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSeparator));
$aSep = array(
$aSep = [
';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'),
',' => Dict::S('UI:CSVImport:SeparatorComma+'),
'tab' => Dict::S('UI:CSVImport:SeparatorTab+'),
);
];
$sSeparator = utils::ReadParam('separator', '', false, 'raw_data');
if ($sSeparator == '') // May be set to an empty value by the previous page
{
if ($sSeparator == '') { // May be set to an empty value by the previous page
$sSeparator = $aGuesses['separator'];
}
if ($sSeparator == "\t") {
$sSeparator = "tab";
}
$sOtherSeparator = in_array($sSeparator, array(',', ';', "\t")) ? '' : $sSeparator;
$sOtherSeparator = in_array($sSeparator, [',', ';', "\t"]) ? '' : $sSeparator;
$aSep['other'] = Dict::S('UI:CSVImport:SeparatorOther').' <input type="text" size="3" maxlength="1" name="other_separator" id="other_separator" value="'.utils::EscapeHtml($sOtherSeparator).'" onChange="DoPreview()"/>';
foreach ($aSep as $sVal => $sLabel) {
@@ -772,10 +778,10 @@ EOF
$oFieldSetTextQualifier = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:TextQualifierCharacter'));
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetTextQualifier));
$aQualifiers = array(
$aQualifiers = [
'"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'),
'\'' => Dict::S('UI:CSVImport:QualifierSimpleQuote+'),
);
];
$aQualifiers['other'] = Dict::S('UI:CSVImport:QualifierOther').' <input type="text" size="3" maxlength="1" name="other_qualifier" value="'.utils::EscapeHtml($sOtherTextQualifier).'" onChange="DoPreview()/>';
foreach ($aQualifiers as $sVal => $sLabel) {
$oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "text_qualifier", $sVal, $sLabel, "radio");
@@ -798,8 +804,13 @@ EOF
$oFieldSetCommentsAndHeader->AddSubBlock($oCheckBoxHeader);
$oFieldSetCommentsAndHeader->AddSubBlock(new Html('</br>'));
$oCheckBoxSkip = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', '<input type="text" size=2 name="nb_skipped_lines" id="nb_skipped_lines" onChange="DoPreview()" value="'.$iSkippedLines.'">'), "box_skiplines", "1", "box_skiplines",
"checkbox");
$oCheckBoxSkip = InputUIBlockFactory::MakeForInputWithLabel(
Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', '<input type="text" size=2 name="nb_skipped_lines" id="nb_skipped_lines" onChange="DoPreview()" value="'.$iSkippedLines.'">'),
"box_skiplines",
"1",
"box_skiplines",
"checkbox"
);
$oCheckBoxSkip->GetInput()->AddCSSClass('ibo-input-checkbox');
$oCheckBoxSkip->GetInput()->SetIsChecked(($bBoxSkipLines == 1));
$oCheckBoxSkip->SetBeforeInput(false);
@@ -922,9 +933,9 @@ EOF
);
}
EOF
);
);
$oPage->add_ready_script(
<<<EOF
<<<EOF
DoPreview();
$('#custom_date_time_format').on('click', function() { $('#radio_date_time_custom').prop('checked', true); });
EOF
@@ -945,7 +956,7 @@ EOF
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
DisplaySynchroBanner($oPage, $sClassName, $iCount);
$aSynchroUpdate = utils::ReadParam('synchro_update', array());
$aSynchroUpdate = utils::ReadParam('synchro_update', []);
} else {
$aSynchroUpdate = null;
}
@@ -980,8 +991,8 @@ EOF
if ($sEncoding == '') {
$sEncoding = MetaModel::GetConfig()->Get('csv_file_default_charset');
}
$aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
$aFieldsMapping = utils::ReadParam('field', [], false, 'raw_data');
$aSearchFields = utils::ReadParam('search_field', [], false, 'field_name');
$aPossibleEncodings = utils::GetPossibleEncodings(MetaModel::GetConfig()->GetCSVImportCharsets());
foreach ($aPossibleEncodings as $sIconvCode => $sDisplayName) {
@@ -1016,7 +1027,6 @@ EOF
$oFormPaste = FormUIBlockFactory::MakeStandard();
$oTabPaste->AddSubBlock($oFormPaste);
$sCSVData = utils::ReadParam('csvdata', '', false, utils::ENUM_SANITIZATION_FILTER_STRING);
$oTextarea = new TextArea('csvdata', $sCSVData, '', 120, 30);
$oTextarea->AddCSSClasses(['ibo-input-text', 'ibo-is-code']);
@@ -1086,25 +1096,28 @@ ajax_request = $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.csvimport.php',
);
}
EOF
);
);
$oPage->add_ready_script(
<<<EOF
<<<EOF
$('#select_template_class').change( function() {
DisplayTemplate(this.value);
});
EOF
);
);
if (Utils::GetConfig()->Get('csv_import_history_display'))
{
if (Utils::GetConfig()->Get('csv_import_history_display')) {
$oPage->SetCurrentTabContainer('tabs1');
$oPage->AddAjaxTab('UI:History:BulkImports', utils::GetAbsoluteUrlAppRoot().'pages/csvimport.php?step=11', true /* bCache */,
null, AjaxTab::ENUM_TAB_PLACEHOLDER_MISC);
$oPage->AddAjaxTab(
'UI:History:BulkImports',
utils::GetAbsoluteUrlAppRoot().'pages/csvimport.php?step=11',
true /* bCache */,
null,
AjaxTab::ENUM_TAB_PLACEHOLDER_MISC
);
}
}
switch($iStep)
{
switch ($iStep) {
case 11:
// Asynchronous tab
$oPage = new AjaxPage('');
@@ -1142,19 +1155,15 @@ EOF
}
$oPage->output();
}
catch(CoreException $e)
{
} catch (CoreException $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -1171,19 +1180,15 @@ catch(CoreException $e)
// For debugging only
//throw $e;
}
catch(Exception $e)
{
} catch (Exception $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -1191,7 +1196,7 @@ catch(Exception $e)
$oLog->Set('issue', 'PHP Exception');
$oLog->Set('impact', 'Page could not be displayed');
$oLog->Set('callstack', $e->getTrace());
$oLog->Set('data', array());
$oLog->Set('data', []);
$oLog->DBInsertNoReload();
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -28,7 +29,6 @@ IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUE
utils::InitTimeZone();
/**
* @param string $sPagePath full path (if symlink, it will be resolved)
* @param array $aPossibleBasePaths list of possible base paths
@@ -51,7 +51,6 @@ function CheckPageExists(string $sPagePath, array $aPossibleBasePaths)
return false;
}
$sModule = utils::ReadParam('exec_module', '');
if ($sModule == '') {
echo "Missing argument 'exec_module'";
@@ -70,7 +69,6 @@ $sEnvironment = utils::ReadParam('exec_env', utils::GetCurrentEnvironment());
Session::WriteClose();
$oKPI->ComputeAndReport("Session Start");
$sEnvFullPath = APPROOT.'env-'.$sEnvironment;
$sPageRelativePath = $sModule.'/'.$sPage;
$sPageEnvFullPath = $sEnvFullPath.'/'.$sPageRelativePath;

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -41,17 +42,14 @@ function GraphvizEscape($s)
/**
* Helper to generate a Graphviz code for displaying the life cycle of a class
* @param string $sClass The class to display
* @return string The Graph description in Graphviz/Dot syntax
* @return string The Graph description in Graphviz/Dot syntax
*/
function GraphvizLifecycle($sClass)
{
$sDotFileContent = "";
if (!MetaModel::HasLifecycle($sClass))
{
if (!MetaModel::HasLifecycle($sClass)) {
//$oPage->p("no lifecycle for this class");
}
else
{
} else {
$aStates = MetaModel::EnumStates($sClass);
$aStimuli = MetaModel::EnumStimuli($sClass);
$sDotFileContent .= "digraph finite_state_machine {
@@ -60,18 +58,15 @@ function GraphvizLifecycle($sClass)
node [ fontname=Verdana style=filled fillcolor=\"#ffffff\" ];
edge [ fontname=Verdana ];
";
$aStatesLinks = array();
foreach ($aStates as $sStateCode => $aStateDef)
{
$aStatesLinks[$sStateCode] = array('in' => 0, 'out' => 0);
$aStatesLinks = [];
foreach ($aStates as $sStateCode => $aStateDef) {
$aStatesLinks[$sStateCode] = ['in' => 0, 'out' => 0];
}
foreach ($aStates as $sStateCode => $aStateDef)
{
foreach ($aStates as $sStateCode => $aStateDef) {
$sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode);
$sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode);
foreach(MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
{
foreach (MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) {
$aStatesLinks[$sStateCode]['out']++;
$aStatesLinks[$aTransitionDef['target_state']]['in']++;
$sStimulusLabel = $aStimuli[$sStimulusCode]->GetLabel();
@@ -79,19 +74,14 @@ function GraphvizLifecycle($sClass)
$sDotFileContent .= "\t$sStateCode -> {$aTransitionDef['target_state']} [ label=\"".GraphvizEscape($sStimulusLabel)."\"];\n";
}
}
foreach($aStates as $sStateCode => $aStateDef)
{
if (($aStatesLinks[$sStateCode]['out'] > 0) || ($aStatesLinks[$sStateCode]['in'] > 0))
{
foreach ($aStates as $sStateCode => $aStateDef) {
if (($aStatesLinks[$sStateCode]['out'] > 0) || ($aStatesLinks[$sStateCode]['in'] > 0)) {
// Show only reachable states
$sStateLabel = str_replace(' ', '\n', MetaModel::GetStateLabel($sClass, $sStateCode));
if ( ($aStatesLinks[$sStateCode]['in'] == 0) || ($aStatesLinks[$sStateCode]['out'] == 0))
{
if (($aStatesLinks[$sStateCode]['in'] == 0) || ($aStatesLinks[$sStateCode]['out'] == 0)) {
// End or Start state, make it look different
$sDotFileContent .= "\t$sStateCode [ shape=doublecircle,label=\"".GraphvizEscape($sStateLabel)."\"];\n";
}
else
{
} else {
$sDotFileContent .= "\t$sStateCode [ shape=circle,label=\"".GraphvizEscape($sStateLabel)."\"];\n";
}
}
@@ -108,39 +98,33 @@ $sModuleDir = dirname($sDeclarationFile);
$sImageFilePath = $sModuleDir."/lifecycle/".$sClass.".png";
$sDotExecutable = MetaModel::GetConfig()->Get('graphviz_path');
if (file_exists($sDotExecutable))
{
if (file_exists($sDotExecutable)) {
// create the file with Graphviz
$sImageFilePath = APPROOT."data/lifecycle/".$sClass.".svg";
if (!is_dir(APPROOT."data"))
{
if (!is_dir(APPROOT."data")) {
@mkdir(APPROOT."data");
}
if (!is_dir(APPROOT."data/lifecycle"))
{
if (!is_dir(APPROOT."data/lifecycle")) {
@mkdir(APPROOT."data/lifecycle");
}
$sDotDescription = GraphvizLifecycle($sClass);
$sDotFilePath = APPROOT."data/lifecycle/{$sClass}.dot";
$rFile = @fopen($sDotFilePath, "w");
@fwrite($rFile, $sDotDescription);
@fclose($rFile);
$aOutput = array();
$aOutput = [];
$CommandLine = "\"$sDotExecutable\" -v -Tsvg < \"$sDotFilePath\" -o \"$sImageFilePath\" 2>&1";
exec($CommandLine, $aOutput, $iRetCode);
if ($iRetCode != 0)
{
if ($iRetCode != 0) {
header('Content-type: text/html');
echo "<p><b>Error:</b></p>";
echo "<p>The command: <pre>$CommandLine</pre> returned $iRetCode</p>";
echo "<p>The output of the command is:<pre>\n".implode("\n", $aOutput)."</pre></p>";
echo "<hr>";
echo "<p>Content of the '".basename($sDotFilePath)."' file:<pre>\n$sDotDescription</pre>";
}
else
{
} else {
header('Content-type: image/svg+xml');
header('Content-Disposition: inline; filename="'.$sClass.'.svg"');
readfile($sImageFilePath);
@@ -148,9 +132,7 @@ if (file_exists($sDotExecutable))
@unlink($sDotFilePath);
// Image file is removed as well as there is no cache system yet
@unlink($sImageFilePath);
}
else
{
} else {
header('Content-type: image/png');
header('Content-Disposition: inline; filename="'.$sClass.'.png"');
readfile($sImageFilePath);

View File

@@ -1,3 +1,3 @@
<?php
header('Location: ../index.php');
?>

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -33,8 +34,7 @@ require_once(APPROOT.'/application/loginwebpage.class.inc.php');
$bPortal = utils::ReadParam('portal', false);
$sUrl = utils::GetAbsoluteUrlAppRoot();
if ($operation == 'do_logoff')
{
if ($operation == 'do_logoff') {
// Reload the same dummy page to let the "calling" page execute its 'onunload' method before performing the actual logoff.
// Note the redirection MUST NOT be made via an HTTP "header" since onunload is called only when the actual content of the DOM
// is replaced by some other content. So the "bouncing" page must provide some content (in our case a script making the redirection).
@@ -44,8 +44,7 @@ if ($operation == 'do_logoff')
exit;
}
if (Session::IsSet('auth_user'))
{
if (Session::IsSet('auth_user')) {
$sAuthUser = Session::Get('auth_user');
UserRights::Login($sAuthUser); // Set the user's language
}
@@ -53,15 +52,11 @@ if (Session::IsSet('auth_user'))
LoginWebPage::ResetSession();
$bLoginDebug = MetaModel::GetConfig()->Get('login_debug');
if ($bLoginDebug)
{
if ($bLoginDebug) {
IssueLog::Info("---------------------------------");
if (isset($sAuthUser))
{
if (isset($sAuthUser)) {
IssueLog::Info("--> Logout user: [$sAuthUser]");
}
else
{
} else {
IssueLog::Info("--> Logout");
}
$sSessionLog = session_id().' '.utils::GetSessionLog();
@@ -71,13 +66,10 @@ if ($bLoginDebug)
$aPluginList = LoginWebPage::GetLoginPluginList('iLogoutExtension');
/** @var iLogoutExtension $oLogoutExtension */
foreach ($aPluginList as $oLogoutExtension)
{
if ($bLoginDebug)
{
foreach ($aPluginList as $oLogoutExtension) {
if ($bLoginDebug) {
$sCurrSessionLog = session_id().' '.utils::GetSessionLog();
if ($sCurrSessionLog != $sSessionLog)
{
if ($sCurrSessionLog != $sSessionLog) {
$sSessionLog = $sCurrSessionLog;
IssueLog::Info("SESSION: $sSessionLog");
}
@@ -87,11 +79,9 @@ foreach ($aPluginList as $oLogoutExtension)
$oLogoutExtension->LogoutAction();
}
if ($bLoginDebug)
{
if ($bLoginDebug) {
$sCurrSessionLog = session_id().' '.utils::GetSessionLog();
if ($sCurrSessionLog != $sSessionLog)
{
if ($sCurrSessionLog != $sSessionLog) {
$sSessionLog = $sCurrSessionLog;
IssueLog::Info("SESSION: $sSessionLog");
}
@@ -100,8 +90,8 @@ if ($bLoginDebug)
LoginWebPage::ResetSession(true);
if ($bLoginDebug) {
$sSessionLog = session_id().' '.utils::GetSessionLog();
IssueLog::Info("SESSION: $sSessionLog");
$sSessionLog = session_id().' '.utils::GetSessionLog();
IssueLog::Info("SESSION: $sSessionLog");
}
$oPage = LoginWebPage::NewLoginWebPage();

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -17,7 +18,6 @@
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSection;
use Combodo\iTop\Application\UI\Base\Component\Html\HtmlFactory;
use Combodo\iTop\Application\UI\Base\Layout\PageContent\PageContentFactory;
@@ -49,8 +49,8 @@ function DisplayActionsTab(iTopWebPage &$oP, string $sClassToDisplay, array $aCl
return;
}
$aActionClasses = array();
foreach(MetaModel::EnumChildClasses($sClassToDisplay, ENUM_CHILD_CLASSES_ALL, true) as $sActionClass) {
$aActionClasses = [];
foreach (MetaModel::EnumChildClasses($sClassToDisplay, ENUM_CHILD_CLASSES_ALL, true) as $sActionClass) {
// Ignore abstract classes
if (MetaModel::IsAbstract($sActionClass)) {
continue;
@@ -74,12 +74,11 @@ function DisplayActionsTab(iTopWebPage &$oP, string $sClassToDisplay, array $aCl
$oP->SetCurrentTab('UI:NotificationsMenu:Actions:'.$sClassToDisplay);
$iBlock = 0;
foreach($aActionClasses as $sActionClass)
{
foreach ($aActionClasses as $sActionClass) {
$oFilter = new DBObjectSearch($sActionClass);
$oFilter->AddCondition('finalclass', $sActionClass); // derived classes will be further processed
$aParams = array('panel_title' => MetaModel::GetName($sActionClass));
$aParams = ['panel_title' => MetaModel::GetName($sActionClass)];
$sBlockId = 'block_'.utils::Sanitize($sClassToDisplay, '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER).'_'.$iBlock;
$oBlock = new DisplayBlock($oFilter, 'list', false, $aParams);
@@ -91,8 +90,14 @@ function DisplayActionsTab(iTopWebPage &$oP, string $sClassToDisplay, array $aCl
// Main program
//
$oP = new iTopWebPage(Dict::S('Menu:NotificationsMenu+'));
$oP->SetBreadCrumbEntry('ui-tool-notifications', Dict::S('Menu:NotificationsMenu'), Dict::S('Menu:NotificationsMenu+'), '', 'fas fa-bell',
iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->SetBreadCrumbEntry(
'ui-tool-notifications',
Dict::S('Menu:NotificationsMenu'),
Dict::S('Menu:NotificationsMenu+'),
'',
'fas fa-bell',
iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES
);
$oPageContentLayout = PageContentFactory::MakeStandardEmpty();
$oP->SetContentLayout($oPageContentLayout);
@@ -115,7 +120,7 @@ $oP->SetCurrentTabContainer('Tabs_0');
$oP->SetCurrentTab('UI:NotificationsMenu:Triggers');
$oFilter = new DBObjectSearch('Trigger');
$aParams = array('panel_title' => Dict::S('UI:NotificationsMenu:AvailableTriggers'));
$aParams = ['panel_title' => Dict::S('UI:NotificationsMenu:AvailableTriggers')];
$oBlock = new DisplayBlock($oFilter, 'list', false, $aParams);
$oBlock->Display($oP, 'block_0', $aParams);

View File

@@ -1,6 +1,5 @@
<?php
use Combodo\iTop\Controller\OAuth\OAuthLandingController;
require_once('../approot.inc.php');

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -143,19 +144,18 @@ JS
// Notifications
//
//////////////////////////////////////////////////////////////////////////
$oNotificationsBlock = new Panel(Dict::S('UI:Preferences:Notifications'), array(), Panel::ENUM_COLOR_SCHEME_GREY, 'ibo-notifications');
$oNotificationsBlock = new Panel(Dict::S('UI:Preferences:Notifications'), [], Panel::ENUM_COLOR_SCHEME_GREY, 'ibo-notifications');
$sNotificationsCenterUrl = Router::GetInstance()->GenerateUrl(NotificationsCenterController::ROUTE_NAMESPACE.'.display_page', [], true);
$oNotificationsBlock->AddSubBlock(new Html('<p>'.Dict::Format('UI:Preferences:Notifications+', $sNotificationsCenterUrl).'</p>'));
$oContentLayout->AddMainBlock($oNotificationsBlock);
//////////////////////////////////////////////////////////////////////////
//
// Favorite Organizations
//
//////////////////////////////////////////////////////////////////////////
$oFavoriteOrganizationsBlock = new Panel(Dict::S('UI:FavoriteOrganizations'), array(), 'grey', 'ibo-favorite-organizations');
$oFavoriteOrganizationsBlock = new Panel(Dict::S('UI:FavoriteOrganizations'), [], 'grey', 'ibo-favorite-organizations');
$oFavoriteOrganizationsBlock->SetSubTitle(Dict::S('UI:FavoriteOrganizations+'));
$oFavoriteOrganizationsBlock->AddCSSClass('ibo-datatable-panel');
$oFavoriteOrganizationsForm = new Form();
@@ -210,7 +210,7 @@ JS
//
//////////////////////////////////////////////////////////////////////////
$oShortcutsBlock = new BlockShortcuts(Dict::S('Menu:MyShortcuts'), array(), 'grey', 'ibo-shortcuts');
$oShortcutsBlock = new BlockShortcuts(Dict::S('Menu:MyShortcuts'), [], 'grey', 'ibo-shortcuts');
$oShortcutsBlock->AddCSSClass('ibo-datatable-panel');
$oShortcutsBlock->sIdShortcuts = 'shortcut_list';
@@ -234,12 +234,22 @@ JS
$oShortcutsToolBar = ToolbarUIBlockFactory::MakeForButton();
$oShortcutsBlock->AddSubBlock($oShortcutsToolBar);
// - Rename button
$oShortcutsRenameButton = ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Rename'), null, null, false,
"shortcut_btn_rename");
$oShortcutsRenameButton = ButtonUIBlockFactory::MakeForSecondaryAction(
Dict::S('UI:Button:Rename'),
null,
null,
false,
"shortcut_btn_rename"
);
$oShortcutsToolBar->AddSubBlock($oShortcutsRenameButton);
// - Delete button
$oShortcutsDeleteButton = ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Delete'), null, null, false,
"shortcut_btn_delete");
$oShortcutsDeleteButton = ButtonUIBlockFactory::MakeForSecondaryAction(
Dict::S('UI:Button:Delete'),
null,
null,
false,
"shortcut_btn_delete"
);
$oShortcutsToolBar->AddSubBlock($oShortcutsDeleteButton);
}
$oContentLayout->AddMainBlock($oShortcutsBlock);
@@ -253,26 +263,27 @@ JS
$oUser = UserRights::GetUserObject();
/** @var iNewsroomProvider[] $aProviders */
$aProviders = InterfaceDiscovery::GetInstance()->FindItopClasses(iNewsroomProvider::class);
foreach($aProviders as $cProvider)
{
foreach ($aProviders as $cProvider) {
$oProvider = new $cProvider();
if ($oProvider->IsApplicable($oUser))
{
if ($oProvider->IsApplicable($oUser)) {
$iCountProviders++;
}
}
$bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false);
if ($bNewsroomEnabled && ($iCountProviders > 0))
{
$oNewsroomBlock = new Panel(Dict::S('UI:Newsroom:Preferences'), array(), 'grey', 'ibo-newsroom');
if ($bNewsroomEnabled && ($iCountProviders > 0)) {
$oNewsroomBlock = new Panel(Dict::S('UI:Newsroom:Preferences'), [], 'grey', 'ibo-newsroom');
$sNewsroomHtml = '';
$sNewsroomHtml .= '<form method="post">';
$iNewsroomDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', 7);
if ($iNewsroomDisplaySize < 1) $iNewsroomDisplaySize = 1;
if ($iNewsroomDisplaySize > 20) $iNewsroomDisplaySize = 20;
if ($iNewsroomDisplaySize < 1) {
$iNewsroomDisplaySize = 1;
}
if ($iNewsroomDisplaySize > 20) {
$iNewsroomDisplaySize = 20;
}
$sInput = '<input min="1" max="20" id="newsroom_display_size" type="number" size="2" name="newsroom_display_size" value="'.$iNewsroomDisplaySize.'">';
$sIcon = '<i id="newsroom_menu_icon" class="top-right-icon icon-additional-arrow fas fa-bell" style="top: 0;"></i>';
$sNewsroomHtml .= Dict::Format('UI:Newsroom:DisplayAtMost_X_Messages', $sInput, $sIcon);
@@ -281,22 +292,16 @@ JS
* @var iNewsroomProvider[] $aProviders
*/
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
foreach($aProviders as $cProvider)
{
foreach ($aProviders as $cProvider) {
$oProvider = new $cProvider();
if ($oProvider->IsApplicable($oUser))
{
if ($oProvider->IsApplicable($oUser)) {
$sUrl = $oProvider->GetPreferencesUrl();
$sProviderClass = get_class($oProvider);
$sPreferencesLink = '';
if ($sUrl !== null)
{
if(substr($sUrl, 0, strlen($sAppRootUrl)) === $sAppRootUrl)
{
if ($sUrl !== null) {
if (substr($sUrl, 0, strlen($sAppRootUrl)) === $sAppRootUrl) {
$sTarget = ''; // Internal link, open in the same window
}
else
{
} else {
$sTarget = ' target="_blank"'; // External link, open in new window
}
$sPreferencesLink = ' - <a class=".newsroom-configuration-link" href="'.$sUrl.'"'.$sTarget.'>'.Dict::S('UI:Newsroom:ConfigurationLink').'</a>';
@@ -306,8 +311,10 @@ JS
// Forbid disabling internal newsroom provider
$sDisabledForHtml = $sProviderClass === iTopNewsroomProvider::class ? 'disabled' : '';
$sNewsroomHtml .= '<div><input type="checkbox" id="newsroom_provider_'.$sProviderClass.'" value="on" '.$sCheckedForHtml.' '.$sDisabledForHtml.' name="newsroom_provider_'.$sProviderClass.'"><label for="newsroom_provider_'.$sProviderClass.'">'.Dict::Format('UI:Newsroom:DisplayMessagesFor_Provider',
$oProvider->GetLabel()).'</label> '.$sPreferencesLink.'</div>';
$sNewsroomHtml .= '<div><input type="checkbox" id="newsroom_provider_'.$sProviderClass.'" value="on" '.$sCheckedForHtml.' '.$sDisabledForHtml.' name="newsroom_provider_'.$sProviderClass.'"><label for="newsroom_provider_'.$sProviderClass.'">'.Dict::Format(
'UI:Newsroom:DisplayMessagesFor_Provider',
$oProvider->GetLabel()
).'</label> '.$sPreferencesLink.'</div>';
}
}
@@ -317,7 +324,8 @@ JS
// - Reset button
$oNewsroomResetCacheButton = ButtonUIBlockFactory::MakeForAlternativeDestructiveAction(Dict::S('UI:Newsroom:ResetCache'));
$oNewsroomResetCacheButton->SetOnClickJsCode(<<<JS
$oNewsroomResetCacheButton->SetOnClickJsCode(
<<<JS
$('#ibo-navigation-menu--notifications-menu').newsroom_menu('clearCache')
CombodoToast.OpenSuccessToast(Dict.S('UI:Newsroom:ResetCache:Success:Message'));
JS
@@ -328,11 +336,14 @@ JS
$oNewsroomCancelButton->SetOnClickJsCode("window.location.href = '$sURL'");
$oNewsroomToolbar->AddSubBlock($oNewsroomCancelButton);
// - Submit button
$oNewsroomSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation',
'apply_newsroom_preferences', true);
$oNewsroomSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(
Dict::S('UI:Button:Apply'),
'operation',
'apply_newsroom_preferences',
true
);
$oNewsroomToolbar->AddSubBlock($oNewsroomSubmitButton);
$sNewsroomEndHtml = '</form>';
$oNewsroomEndHtmlBlock = new Html($sNewsroomEndHtml);
@@ -350,7 +361,7 @@ JS
//////////////////////////////////////////////////////////////////////////
// Panel
$oKeyboardShortcutBlock = new Panel(Dict::S('UI:Preferences:PersonalizeKeyboardShortcuts:Title'), array(), 'grey', 'ibo_keyboard_shortcuts');
$oKeyboardShortcutBlock = new Panel(Dict::S('UI:Preferences:PersonalizeKeyboardShortcuts:Title'), [], 'grey', 'ibo_keyboard_shortcuts');
// Form
$oKeyboardShortcutForm = new Form('ibo-form-for-user-interface-preferences');
$oKeyboardShortcutForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'apply_keyboard_shortcuts'))
@@ -412,7 +423,6 @@ JS
$oKeyboardShortcutSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation', 'apply_keyboard_shortcuts', true);
$oKeyboardShortcutToolbar->AddSubBlock($oKeyboardShortcutSubmitButton);
$oContentLayout->AddMainBlock($oKeyboardShortcutBlock);
//////////////////////////////////////////////////////////////////////////
@@ -421,23 +431,20 @@ JS
//
//////////////////////////////////////////////////////////////////////////
$oUserPicturePlaceHolderBlock = new Panel(Dict::S('UI:Preferences:ChooseAPlaceholder'), array(), 'grey', 'ibo-user-picture-placeholder');
$oUserPicturePlaceHolderBlock = new Panel(Dict::S('UI:Preferences:ChooseAPlaceholder'), [], 'grey', 'ibo-user-picture-placeholder');
$sUserPicturesFolderRelPath = 'images/user-pictures/';
$sUserPicturesFolderAbsPath = APPROOT . $sUserPicturesFolderRelPath;
$sUserPicturesFolderAbsUrl = utils::GetAbsoluteUrlAppRoot() . $sUserPicturesFolderRelPath;
$sUserPicturesFolderAbsPath = APPROOT.$sUserPicturesFolderRelPath;
$sUserPicturesFolderAbsUrl = utils::GetAbsoluteUrlAppRoot().$sUserPicturesFolderRelPath;
$sUserDefaultPicture = appUserPreferences::GetPref('user_picture_placeholder', 'default-placeholder.png');
$sUserPicturePlaceHolderHtml = '';
$sUserPicturePlaceHolderHtml .= '<p>'.Dict::S('UI:Preferences:ChooseAPlaceholder+').'</p> <div class="ibo-preferences--user-preferences--picture-placeholder">';
foreach (scandir($sUserPicturesFolderAbsPath) as $sUserPicture)
{
if ($sUserPicture === '.' || $sUserPicture === '..')
{
foreach (scandir($sUserPicturesFolderAbsPath) as $sUserPicture) {
if ($sUserPicture === '.' || $sUserPicture === '..') {
continue;
}
$sAdditionalClass = '';
if ($sUserDefaultPicture === $sUserPicture)
{
if ($sUserDefaultPicture === $sUserPicture) {
$sAdditionalClass = ' ibo-is-active';
}
$sUserPicturePlaceHolderHtml .= '<a class="ibo-preferences--user-preferences--picture-placeholder--image'.$sAdditionalClass.'" data-image-name="'.$sUserPicture.'" data-role="ibo-preferences--user-preferences--picture-placeholder--image" href="#"> <img src="'.$sUserPicturesFolderAbsUrl.$sUserPicture.'"/> </a>';
@@ -473,7 +480,7 @@ $('[data-role="ibo-preferences--user-preferences--picture-placeholder--image"]')
});
});
JS
);
);
$sUserPicturePlaceHolderHtml .=
<<<HTML
</div>
@@ -484,8 +491,7 @@ HTML
$oContentLayout->AddMainBlock($oUserPicturePlaceHolderBlock);
/** @var iPreferencesExtension $oLoginExtensionInstance */
foreach (MetaModel::EnumPlugins('iPreferencesExtension') as $oPreferencesExtensionInstance)
{
foreach (MetaModel::EnumPlugins('iPreferencesExtension') as $oPreferencesExtensionInstance) {
$oPreferencesExtensionInstance->DisplayPreferences($oP);
}
@@ -503,7 +509,7 @@ HTML
function GetLanguageFieldBlock(): iUIBlock
{
$aAvailableLanguages = Dict::GetLanguages();
$aSortedLanguages = array();
$aSortedLanguages = [];
foreach ($aAvailableLanguages as $sCode => $aLang) {
if (MetaModel::GetConfig()->Get('demo_mode') && ($sCode !== Dict::GetUserLanguage())) {
// Demo mode: only the current user language is listed in the available choices
@@ -582,10 +588,12 @@ function GetTabsLayoutFieldBlock(): iUIBlock
];
$oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('tab_layout', Dict::S('UI:Preferences:Tabs:Layout:Label'));
foreach ($aOptionsValues as $sValue) {
$oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption(
$sValue,
Dict::S('UI:Preferences:Tabs:Layout:'.ucfirst($sValue)),
$sValue === $sCurrentValue)
$oSelect->AddSubBlock(
SelectOptionUIBlockFactory::MakeForSelectOption(
$sValue,
Dict::S('UI:Preferences:Tabs:Layout:'.ucfirst($sValue)),
$sValue === $sCurrentValue
)
);
}
@@ -610,10 +618,12 @@ function GetTabsNavigationFieldBlock(): iUIBlock
];
$oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('tab_scrollable', Dict::S('UI:Preferences:Tabs:Scrollable:Label'));
foreach ($aOptionsValues as $sValue => $sDictEntrySuffix) {
$oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption(
$sValue,
Dict::S('UI:Preferences:Tabs:Scrollable:'.$sDictEntrySuffix),
$sValue === $sCurrentValueAsString)
$oSelect->AddSubBlock(
SelectOptionUIBlockFactory::MakeForSelectOption(
$sValue,
Dict::S('UI:Preferences:Tabs:Scrollable:'.$sDictEntrySuffix),
$sValue === $sCurrentValueAsString
)
);
}
@@ -678,7 +688,6 @@ HTML;
return new Html($sHtml);
}
/**
* @return \Combodo\iTop\Application\UI\Base\iUIBlock
* @throws \CoreException
@@ -717,7 +726,7 @@ function GetToastsPositionFieldBlock(): iUIBlock
$sPosition = appUserPreferences::GetPref('toasts_vertical_position', "bottom");
$oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('toasts_vertical_position', Dict::S('UI:Preferences:General:Toasts'));
$oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption("bottom", Dict::S('UI:Preferences:General:Toasts:Bottom'), $sPosition === "bottom"));
$oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption("top", Dict::S('UI:Preferences:General:Toasts:Top'), $sPosition === "top"));
@@ -754,7 +763,7 @@ try {
case 'apply':
$oFilter = DBObjectSearch::FromOQL('SELECT Organization');
$sSelectionMode = utils::ReadParam('selectionMode', '');
$aExceptions = utils::ReadParam('storedSelection', array());
$aExceptions = utils::ReadParam('storedSelection', []);
if (($sSelectionMode == 'negative') && (count($aExceptions) == 0)) {
// All Orgs selected
appUserPreferences::SetPref('favorite_orgs', null);
@@ -816,17 +825,17 @@ try {
// - Obsolete data
$bShowObsoleteData = (bool)utils::ReadParam('show_obsolete_data', 0);
appUserPreferences::SetPref('show_obsolete_data', $bShowObsoleteData);
// - Summary cards
$bShowSummaryCards = (bool)utils::ReadParam('show_summary_cards', 0);
appUserPreferences::SetPref('show_summary_cards', $bShowSummaryCards);
// - Toast notifications
$sToastsVerticalPosition = utils::ReadParam('toasts_vertical_position', "bottom");
if(utils::IsNotNullOrEmptyString($sToastsVerticalPosition) && in_array($sToastsVerticalPosition, ["bottom", "top"], true)) {
if (utils::IsNotNullOrEmptyString($sToastsVerticalPosition) && in_array($sToastsVerticalPosition, ["bottom", "top"], true)) {
appUserPreferences::SetPref('toasts_vertical_position', $sToastsVerticalPosition);
}
// Redirect to force a reload/display of the page in case language has been changed
$oAppContext = new ApplicationContext();
$sURL = utils::GetAbsoluteUrlAppRoot().'pages/preferences.php?'.$oAppContext->GetForLink();
@@ -878,29 +887,25 @@ try {
}
}
$bProvidersModified = false;
foreach ($aProviders as $cProvider)
{
foreach ($aProviders as $cProvider) {
// Forbid disabling internal newsroom provider
if ($cProvider === iTopNewsroomProvider::class) {
continue;
}
$oProvider = new $cProvider();
if ($oProvider->IsApplicable($oUser))
{
if ($oProvider->IsApplicable($oUser)) {
$sProviderClass = get_class($oProvider);
$bProviderEnabled = (utils::ReadParam('newsroom_provider_'.$sProviderClass, 'off') == 'on');
$bCurrentValue = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true);
if ($bCurrentValue != $bProviderEnabled)
{
if ($bCurrentValue != $bProviderEnabled) {
// Save the preference only if it differs from the current value
$bProvidersModified = true;
appUserPreferences::SetPref('newsroom_provider_'.$sProviderClass, $bProviderEnabled);
}
}
}
if ($bProvidersModified)
{
if ($bProvidersModified) {
$oPage->add_ready_script(
<<<JS
$('#ibo-navigation-menu--notifications-menu').newsroom_menu("clearCache");
@@ -913,26 +918,28 @@ JS
case 'display':
default:
$oPage->SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '',
'fas fa-user-cog', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oPage->SetBreadCrumbEntry(
'ui-tool-preferences',
Dict::S('UI:Preferences'),
Dict::S('UI:Preferences'),
'',
'fas fa-user-cog',
iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES
);
DisplayPreferences($oPage);
}
}
$oPage->output();
}
catch(CoreException $e)
{
} catch (CoreException $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc()));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -949,19 +956,15 @@ catch(CoreException $e)
// For debugging only
//throw $e;
}
catch(Exception $e)
{
} catch (Exception $e) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
$oP->output();
if (MetaModel::IsLogEnabledIssue())
{
if (MetaModel::IsValidClass('EventIssue'))
{
if (MetaModel::IsLogEnabledIssue()) {
if (MetaModel::IsValidClass('EventIssue')) {
$oLog = new EventIssue();
$oLog->Set('message', $e->getMessage());
@@ -969,7 +972,7 @@ catch(Exception $e)
$oLog->Set('issue', 'PHP Exception');
$oLog->Set('impact', 'Page could not be displayed');
$oLog->Set('callstack', $e->getTrace());
$oLog->Set('data', array());
$oLog->Set('data', []);
$oLog->DBInsertNoReload();
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -41,26 +42,26 @@ function ShowExamples($oP, $sExpression)
{
$bUsingExample = false;
$aExamples = array(
'Pedagogic examples' => array(
$aExamples = [
'Pedagogic examples' => [
"Person" => "SELECT Person",
"Person having an 'A' in their name" => "SELECT Person AS B WHERE B.name LIKE '%A%'",
"Organization having a name beginning by 'My'" => "SELECT Organization WHERE name REGEXP '^My .*$'",
"Changes planned on new year's day" => "SELECT Change AS ch WHERE ch.start_date >= '2009-12-31' AND ch.end_date <= '2010-01-01'",
"IPs in a range" => "SELECT DatacenterDevice AS dev WHERE INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.managementip) < INET_ATON('10.22.32.255')",
"Persons below a given root organization" => "SELECT Person AS P JOIN Organization AS Node ON P.org_id = Node.id JOIN Organization AS Root ON Node.parent_id BELOW Root.id WHERE Root.id=1",
),
'Usefull examples' => array(
],
'Usefull examples' => [
"NW interfaces of equipment in production for customer 'Demo'" => "SELECT PhysicalInterface AS if JOIN DatacenterDevice AS dev ON if.connectableci_id = dev.id WHERE dev.status = 'production' AND dev.organization_name = 'Demo'",
"My tickets" => "SELECT Ticket AS t WHERE t.agent_id = :current_contact_id",
"People being owner of an active ticket" => "SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
"Contracts terminating in the next thirty days" => "SELECT Contract AS c WHERE c.end_date > NOW() AND c.end_date < DATE_ADD(NOW(), INTERVAL 30 DAY)",
"Orphan tickets (opened one hour ago, still not assigned)" => "SELECT UserRequest AS u WHERE u.start_date < DATE_SUB(NOW(), INTERVAL 60 MINUTE) AND u.status = 'new'",
"Long lasting incidents (duration > 8 hours)" => "SELECT UserRequest AS u WHERE u.close_date > DATE_ADD(u.start_date, INTERVAL 8 HOUR)",
),
);
],
];
$aDisplayData = array();
$aDisplayData = [];
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForForm();
foreach ($aExamples as $sTopic => $aQueries) {
@@ -81,23 +82,23 @@ function ShowExamples($oP, $sExpression)
$oFormButton->AddSubBlock($oButton);
$oFormButton->AddSubBlock(new Html($sContext));
//$aDisplayData[$sTopic][] = array(
$aDisplayData[Dict::S('UI:RunQuery:QueryExamples')][] = array(
$aDisplayData[Dict::S('UI:RunQuery:QueryExamples')][] = [
'desc' => "<div class=\"$sHighlight\">".utils::EscapeHtml($sDescription)."</div>",
'oql' => "<div class=\"$sHighlight\">".utils::EscapeHtml($sOql)."</div>",
'go' => BlockRenderer::RenderBlockTemplates($oFormButton),
);
];
}
}
$aDisplayConfig = array();
$aDisplayConfig['desc'] = array(
$aDisplayConfig = [];
$aDisplayConfig['desc'] = [
'label' => Dict::S('UI:RunQuery:HeaderPurpose'),
'description' => Dict::S('UI:RunQuery:HeaderPurpose+'),
);
$aDisplayConfig['oql'] = array(
];
$aDisplayConfig['oql'] = [
'label' => Dict::S('UI:RunQuery:HeaderOQLExpression'),
'description' => Dict::S('UI:RunQuery:HeaderOQLExpression+'),
);
$aDisplayConfig['go'] = array('label' => '', 'description' => '');
];
$aDisplayConfig['go'] = ['label' => '', 'description' => ''];
foreach ($aDisplayData as $sTopic => $aQueriesDisplayData) {
$bShowOpened = $bUsingExample;
@@ -120,8 +121,7 @@ $sEncoding = utils::ReadParam('encoding', 'oql');
ShowExamples($oP, $sExpression);
try
{
try {
if ($sEncoding == 'crypted') {
// Translate $sExpression into a oql expression
$oFilter = DBObjectSearch::unserialize($sExpression);
@@ -129,32 +129,23 @@ try
}
$oFilter = null;
$aArgs = array();
$aArgs = [];
$sSyntaxError = null;
if (!empty($sExpression))
{
try
{
if (!empty($sExpression)) {
try {
$oFilter = DBObjectSearch::FromOQL($sExpression);
}
catch(Exception $e)
{
if ($e instanceof OqlException)
{
} catch (Exception $e) {
if ($e instanceof OqlException) {
$sSyntaxError = $e->getHtmlDesc();
}
else
{
} else {
$sSyntaxError = $e->getMessage();
}
}
if ($oFilter)
{
$aArgs = array();
foreach($oFilter->GetQueryParams() as $sParam => $foo)
{
if ($oFilter) {
$aArgs = [];
foreach ($oFilter->GetQueryParams() as $sParam => $foo) {
$value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data');
if (!is_null($value)) {
$aArgs[$sParam] = $value;
@@ -180,7 +171,8 @@ try
$oQueryTextArea->AddCSSClasses(['ibo-input-text', 'ibo-query-oql', 'ibo-is-code']);
$oQueryForm->AddSubBlock($oQueryTextArea);
$oP->add_ready_script(<<<JS
$oP->add_ready_script(
<<<JS
$("#expression").select();
$("#expression").on('keyup', function (oEvent) {
if ((oEvent.ctrlKey || oEvent.metaKey) && oEvent.key === 'Enter') {
@@ -193,11 +185,11 @@ JS
if (count($aArgs) > 0) {
//--- Query arguments
$oQueryForm->AddSubBlock(TitleUIBlockFactory::MakeNeutral(Dict::S('UI:RunQuery:QueryArguments'), 3)->AddCSSClass("ibo-collapsible-section--title"));
$oQueryArgsContainer = UIContentBlockUIBlockFactory::MakeStandard(null,['wizContainer']);
$oQueryArgsContainer = UIContentBlockUIBlockFactory::MakeStandard(null, ['wizContainer']);
$oQueryForm->AddSubBlock($oQueryArgsContainer);
foreach ($aArgs as $sParam => $sValue) {
$oInput = InputUIBlockFactory::MakeStandard("text",'arg_'.$sParam, $sValue);
$oArgInput = \Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory::MakeFromObject($sParam,$oInput,Field::ENUM_FIELD_LAYOUT_SMALL);
$oInput = InputUIBlockFactory::MakeStandard("text", 'arg_'.$sParam, $sValue);
$oArgInput = \Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory::MakeFromObject($sParam, $oInput, Field::ENUM_FIELD_LAYOUT_SMALL);
$oArgInput->AddCSSClass("ibo-field--label-small");
//$oArgInput = InputUIBlockFactory::MakeForInputWithLabel( $sParam, 'arg_'.$sParam, $sValue );
$oQueryArgsContainer->AddSubBlock($oArgInput);
@@ -216,10 +208,9 @@ JS
$oQueryForm->AddSubBlock($oToolbarButtons);
$oToolbarButtons->AddSubBlock($oQuerySubmit);
if ($oFilter) {
//--- Query filter
$oPanelResult= PanelUIBlockFactory::MakeWithBrandingSecondaryColor(Dict::S('UI:RunQuery:QueryResults'));
$oPanelResult = PanelUIBlockFactory::MakeWithBrandingSecondaryColor(Dict::S('UI:RunQuery:QueryResults'));
$oP->AddSubBlock($oPanelResult);
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
$oPanelResult->AddSubBlock($oResultBlock->GetDisplay($oP, 'runquery'));
@@ -228,10 +219,10 @@ JS
//$iCount = $oResultBlock->GetDisplayedCount();
$sPageId = "ui-search-".$oFilter->GetClass();
$sLabel = MetaModel::GetName($oFilter->GetClass());
$aArgs = array();
$aArgs = [];
foreach (array_merge($_POST, $_GET) as $sKey => $value) {
if (is_array($value)) {
$aItems = array();
$aItems = [];
foreach ($value as $sItemKey => $sItemValue) {
$aArgs[] = $sKey.'['.$sItemKey.']='.urlencode($sItemValue);
}
@@ -242,7 +233,6 @@ JS
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs);
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
//--- More info
$aMoreInfoBlocks = [];
@@ -254,14 +244,13 @@ JS
$oSerializedQuerySet->AddSubBlock(UIContentBlockUIBlockFactory::MakeForCode($oFilter->serialize()));
$aMoreInfoBlocks[] = $oSerializedQuerySet;
$aModifierProperties = MetaModel::MakeModifierProperties($oFilter);
// Avoid adding all the fields for counts or "group by" requests
$aCountAttToLoad = array();
$aCountAttToLoad = [];
$sMainClass = null;
foreach ($oFilter->GetSelectedClasses() as $sClassAlias => $sClass) {
$aCountAttToLoad[$sClassAlias] = array();
$aCountAttToLoad[$sClassAlias] = [];
if (empty($sMainClass)) {
$sMainClass = $sClass;
}
@@ -279,7 +268,7 @@ JS
}
// SQL Count
$sSQL = $oFilter->MakeSelectQuery(array(), $aRealArgs, $aCountAttToLoad, null, 0, 0, true);
$sSQL = $oFilter->MakeSelectQuery([], $aRealArgs, $aCountAttToLoad, null, 0, 0, true);
$oCountResultQuerySet = new FieldSet(Dict::S('UI:RunQuery:ResultSQLCount'));
$oCountResultQuerySet->AddSubBlock(UIContentBlockUIBlockFactory::MakeForCode($sSQL));
$aMoreInfoBlocks[] = $oCountResultQuerySet;
@@ -324,13 +313,13 @@ JS
$sEscapedExpression = json_encode(utils::EscapeHtml($sFixedExpression));
$oUseSuggestedQueryButton = ButtonUIBlockFactory::MakeForDestructiveAction('Use this query');
$oUseSuggestedQueryButton->SetOnClickJsCode(
<<<JS
<<<JS
let \$oQueryTextarea = $('textarea[name=expression]');
\$oQueryTextarea.val($sEscapedExpression).focus();
\$oQueryTextarea.closest('form').submit();
JS
);
$oSyntaxErrorPanel->AddSubBlock($oUseSuggestedQueryButton);
$oSyntaxErrorPanel->AddSubBlock($oUseSuggestedQueryButton);
} else {
$oSyntaxErrorPanel->AddSubBlock(HtmlFactory::MakeParagraph($e->getHtmlDesc()));
}
@@ -341,8 +330,7 @@ JS
$oSyntaxErrorPanel->AddSubBlock(HtmlFactory::MakeParagraph($e->getMessage()));
}
}
}
catch (Exception $e) {
} catch (Exception $e) {
$oErrorAlert = AlertUIBlockFactory::MakeForFailure(
Dict::Format('UI:RunQuery:Error', $e->getMessage()),
'<pre>'.$e->getTraceAsString().'</pre>'
@@ -352,4 +340,3 @@ catch (Exception $e) {
}
$oP->output();

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -30,9 +31,11 @@ ApplicationMenu::CheckMenuIdEnabled('DataModelMenu');
*/
function MakeClassHLink($sClass, $sContext)
{
return "<a href=\"schema.php?operation=details_class&class=$sClass{$sContext}\" title=\"".html_entity_decode(MetaModel::GetClassDescription($sClass),
ENT_QUOTES,
'UTF-8')."\">".MetaModel::GetName($sClass)." (".$sClass.")</a>";
return "<a href=\"schema.php?operation=details_class&class=$sClass{$sContext}\" title=\"".html_entity_decode(
MetaModel::GetClassDescription($sClass),
ENT_QUOTES,
'UTF-8'
)."\">".MetaModel::GetName($sClass)." (".$sClass.")</a>";
}
/**
@@ -41,25 +44,20 @@ function MakeClassHLink($sClass, $sContext)
function DisplaySubclasses($oPage, $sClass, $sContext)
{
$aChildClasses = MetaModel::EnumChildClasses($sClass);
if (count($aChildClasses) != 0)
{
if (count($aChildClasses) != 0) {
$oPage->add("<ul>\n");
$aOrderedClasses = array();
foreach ($aChildClasses as $sClassName)
{
$aOrderedClasses = [];
foreach ($aChildClasses as $sClassName) {
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass)
{
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass) {
$aOrderedClasses[$sClassName] = MetaModel::GetName($sClassName);
}
}
// Sort on the display name
asort($aOrderedClasses);
foreach ($aOrderedClasses as $sClassName => $sDisplayName)
{
foreach ($aOrderedClasses as $sClassName => $sDisplayName) {
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass)
{
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass) {
$oPage->add("<li class=\"open\">".MakeClassHLink($sClassName, $sContext)."\n");
DisplaySubclasses($oPage, $sClassName, $sContext);
$oPage->add("</li>\n");
@@ -73,40 +71,33 @@ function DisplaySubclasses($oPage, $sClass, $sContext)
*/
function GetSubclasses($sClass, $sContext)
{
$sHtml = '';
try{
$aChildClasses = MetaModel::EnumChildClasses($sClass);
if (count($aChildClasses) != 0)
{
$sHtml .= "<ul>";
$aOrderedClasses = array();
foreach ($aChildClasses as $sClassName)
{
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass)
{
$aOrderedClasses[$sClassName] = MetaModel::GetName($sClassName);
$sHtml = '';
try {
$aChildClasses = MetaModel::EnumChildClasses($sClass);
if (count($aChildClasses) != 0) {
$sHtml .= "<ul>";
$aOrderedClasses = [];
foreach ($aChildClasses as $sClassName) {
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass) {
$aOrderedClasses[$sClassName] = MetaModel::GetName($sClassName);
}
}
}
// Sort on the display name
asort($aOrderedClasses);
foreach ($aOrderedClasses as $sClassName => $sDisplayName)
{
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass)
{
$sHtml .="<li class=\"open\">".MakeClassHLink($sClassName, $sContext);
$sHtml .= GetSubclasses($sClassName, $sContext);
$sHtml .= "</li>";
// Sort on the display name
asort($aOrderedClasses);
foreach ($aOrderedClasses as $sClassName => $sDisplayName) {
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass) {
$sHtml .= "<li class=\"open\">".MakeClassHLink($sClassName, $sContext);
$sHtml .= GetSubclasses($sClassName, $sContext);
$sHtml .= "</li>";
}
}
$sHtml .= "</ul>";
}
$sHtml .= "</ul>";
}
}
catch(Exception $e){
} catch (Exception $e) {
}
return $sHtml;
}
@@ -116,12 +107,9 @@ function GetSubclasses($sClass, $sContext)
*/
function DisplayLifecycle($oPage, $sClass)
{
if (!MetaModel::HasLifecycle($sClass))
{
if (!MetaModel::HasLifecycle($sClass)) {
$oPage->p(Dict::S('UI:Schema:NoLifeCyle'));
}
else
{
} else {
$aStates = MetaModel::EnumStates($sClass);
$aStimuli = MetaModel::EnumStimuli($sClass);
$oPage->add("<img id=\"img-lifecycle\" class=\"ibo-datamodel-viewer--lifecycle-image\" attr=\"$sClass lifecycle graph\" src=\"".utils::GetAbsoluteUrlAppRoot()."pages/graphviz.php?class=$sClass\">\n");
@@ -130,7 +118,6 @@ function DisplayLifecycle($oPage, $sClass)
$("#img-lifecycle").attr('href',$("#img-lifecycle").attr('src'));
$("#img-lifecycle").magnificPopup({type: 'image', closeOnContentClick: true});
EOF
);
$oOpenAllButton = ButtonUIBlockFactory::MakeForAlternativePrimaryAction('Open All', '', '', false, 'lifecycleOpenAll');
$oOpenAllButton->SetOnClickJsCode(
@@ -138,7 +125,6 @@ EOF
$('#LifeCycleList').find('.expandable-hitarea').click();
$('#LifeCycleAttrOptList').find('.expandable-hitarea').click();
JS
);
$oCloseAllButton = ButtonUIBlockFactory::MakeForAlternativePrimaryAction('Close All', '', '', false, 'lifecycleCloseAll');
$oCloseAllButton->SetOnClickJsCode(
@@ -146,46 +132,35 @@ JS
$('#LifeCycleList').find('.collapsable-hitarea').click();
$('#LifeCycleAttrOptList').find('.collapsable-hitarea').click();
JS
);
$oPage->AddUiBlock($oOpenAllButton);
$oPage->AddUiBlock($oCloseAllButton);
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral(Dict::S('UI:Schema:LifeCycleTransitions'), 3));
$oPage->add("<ul id=\"LifeCycleList\" >\n");
foreach ($aStates as $sStateCode => $aStateDef)
{
foreach ($aStates as $sStateCode => $aStateDef) {
$sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode);
$sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode);
$oPage->add("<li class=\"closed\">$sStateLabel <span class=\"ibo-datamodel-viewer--lifecycle--code\"> ($sStateCode) $sStateDescription</span>\n");
$oPage->add("<ul class=\"closed\">\n");
foreach (MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
{
foreach (MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) {
$sStimulusLabel = $aStimuli[$sStimulusCode]->GetLabel();
$sTargetState = $aTransitionDef['target_state'];
$sTargetStateLabel = MetaModel::GetStateLabel($sClass, $sTargetState);
if (count($aTransitionDef['actions']) > 0)
{
$aActionsDesc = array();
foreach ($aTransitionDef['actions'] as $actionHandler)
{
if (is_string($actionHandler))
{
if (count($aTransitionDef['actions']) > 0) {
$aActionsDesc = [];
foreach ($aTransitionDef['actions'] as $actionHandler) {
if (is_string($actionHandler)) {
$aActionsDesc[] = $actionHandler;
}
else
{
$aParamsDesc = array();
foreach ($actionHandler['params'] as $aParamData)
{
} else {
$aParamsDesc = [];
foreach ($actionHandler['params'] as $aParamData) {
$aParamsDesc[] = $aParamData['type'].':'.$aParamData['value'];
}
$aActionsDesc[] = $actionHandler['verb'].'('.implode(', ', $aParamsDesc).')';
}
}
$sActions = " <em>(".implode(', ', $aActionsDesc).")</em>";
}
else
{
} else {
$sActions = "";
}
@@ -199,55 +174,42 @@ JS
$oPage->add("</ul>\n");
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral(Dict::S('UI:Schema:LifeCyleAttributeOptions'), 3));
$oPage->add("<ul id=\"LifeCycleAttrOptList\">\n");
foreach ($aStates as $sStateCode => $aStateDef)
{
foreach ($aStates as $sStateCode => $aStateDef) {
$sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode);
$sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode);
$oPage->add("<li class=\"closed\">$sStateLabel<span class=\"ibo-datamodel-viewer--lifecycle--code\"> ($sStateCode) $sStateDescription</span>\n");
if (count($aStates[$sStateCode]['attribute_list']) > 0)
{
if (count($aStates[$sStateCode]['attribute_list']) > 0) {
$oPage->add("<ul>\n");
foreach ($aStates[$sStateCode]['attribute_list'] as $sAttCode => $iOptions)
{
foreach ($aStates[$sStateCode]['attribute_list'] as $sAttCode => $iOptions) {
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
$aOptions = array();
if ($iOptions & OPT_ATT_HIDDEN)
{
$aOptions = [];
if ($iOptions & OPT_ATT_HIDDEN) {
$aOptions[] = Dict::S('UI:Schema:LifeCycleHiddenAttribute');
}
if ($iOptions & OPT_ATT_READONLY)
{
if ($iOptions & OPT_ATT_READONLY) {
$aOptions[] = Dict::S('UI:Schema:LifeCycleReadOnlyAttribute');
}
if ($iOptions & OPT_ATT_MANDATORY)
{
if ($iOptions & OPT_ATT_MANDATORY) {
$aOptions[] = Dict::S('UI:Schema:LifeCycleMandatoryAttribute');
}
if ($iOptions & OPT_ATT_MUSTCHANGE)
{
if ($iOptions & OPT_ATT_MUSTCHANGE) {
$aOptions[] = Dict::S('UI:Schema:LifeCycleAttributeMustChange');
}
if ($iOptions & OPT_ATT_MUSTPROMPT)
{
if ($iOptions & OPT_ATT_MUSTPROMPT) {
$aOptions[] = Dict::S('UI:Schema:LifeCycleAttributeMustPrompt');
}
if (count($aOptions))
{
if (count($aOptions)) {
$sOptions = implode(', ', $aOptions);
}
else
{
} else {
$sOptions = "";
}
$oPage->add("<li class=\"closed\"><span class=\"ibo-datamodel-viewer--lifecycle--attribute-option\">$sAttLabel</span> $sOptions</li>\n");
}
$oPage->add("</ul></li>\n");
}
else
{
} else {
$oPage->p("<em>".Dict::S('UI:Schema:LifeCycleEmptyList')."</em>");
}
}
@@ -257,7 +219,6 @@ JS
}
}
/**
* Helper for the trigger
*/
@@ -265,7 +226,7 @@ function DisplayTriggers($oPage, $sClass)
{
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObject WHERE target_class IN ('$sClassList')"));
cmdbAbstractObject::DisplaySet($oPage, $oSet, array('block_id' => 'triggers'));
cmdbAbstractObject::DisplaySet($oPage, $oSet, ['block_id' => 'triggers']);
}
function DisplayEvents(WebPage $oPage, $sClass)
@@ -301,7 +262,7 @@ function DisplayEvents(WebPage $oPage, $sClass)
} else {
$oObject = MetaModel::NewObject($sClass);
foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, false) as $sParentClass) {
$aSources[] = $sParentClass;
$aSources[] = $sParentClass;
}
}
$aListeners = [];
@@ -345,7 +306,7 @@ function DisplayEvents(WebPage $oPage, $sClass)
}
}
$sListener = $sListenerClass.'->'.$aListener['callback'][1].'(\Combodo\iTop\Service\Events\EventData $oEventData)';
} else if (is_array($aListener['callback'])) {
} elseif (is_array($aListener['callback'])) {
$sListener = $aListener['callback'][0].'::'.$aListener['callback'][1];
} else {
$sListener = $aListener['callback'].'(\Combodo\iTop\Service\Events\EventData $oEventData)';
@@ -368,28 +329,24 @@ function DisplayEvents(WebPage $oPage, $sClass)
function DisplayClassesList($oPage, $oLayout, $sContext)
{
$sSelectedClass = utils::ReadParam('class', '', false, 'class');
$oLayout->AddSideHtml("<label for='search-model'>".Dict::S('UI:Schema:ClassFilter')."</label><br>");
$oListSearch = new Select("ibo-datamodel-viewer--class-search");
$oListSearch->SetName('aa');
// Get all the "root" classes for display
$aRootClasses = array();
$aRootClasses = [];
$aClassLabelAndCodeAsJSON = [];
$aClassLabelAsJSON = array();
$aClassCodeAsJSON = array();
$aClassLabelAsJSON = [];
$aClassCodeAsJSON = [];
$oOptionSearch = SelectOptionUIBlockFactory::MakeForSelectOption('', "select option", true);
$oListSearch->AddOption($oOptionSearch->SetDisabled(true));
foreach (MetaModel::GetClasses() as $sClassName)
{
if (MetaModel::IsRootClass($sClassName))
{
foreach (MetaModel::GetClasses() as $sClassName) {
if (MetaModel::IsRootClass($sClassName)) {
$aRootClasses[$sClassName] = MetaModel::GetName($sClassName);
}
elseif (MetaModel::IsStandaloneClass($sClassName))
{
} elseif (MetaModel::IsStandaloneClass($sClassName)) {
$aRootClasses[$sClassName] = MetaModel::GetName($sClassName);
}
$sLabelClassName = MetaModel::GetName($sClassName);
@@ -398,9 +355,9 @@ function DisplayClassesList($oPage, $oLayout, $sContext)
$oListSearch->AddOption($oOptionSearch);
//Fetch classes names for autocomplete purpose
// - Encode as JSON to escape quotes and other characters
array_push ($aClassLabelAndCodeAsJSON, ["value"=>$sClassName,"label"=>"$sLabelClassName ($sClassName)"]);
array_push ($aClassLabelAsJSON, ["value"=>$sClassName,"label"=>"$sLabelClassName"]);
array_push ($aClassCodeAsJSON, ["value"=>$sClassName,"label"=>"$sClassName"]);
array_push($aClassLabelAndCodeAsJSON, ["value" => $sClassName,"label" => "$sLabelClassName ($sClassName)"]);
array_push($aClassLabelAsJSON, ["value" => $sClassName,"label" => "$sLabelClassName"]);
array_push($aClassCodeAsJSON, ["value" => $sClassName,"label" => "$sClassName"]);
}
usort($aClassLabelAndCodeAsJSON, "Label_sort");
$oLayout->AddSideBlock($oListSearch);
@@ -457,22 +414,17 @@ JS
}
JS
);
// Sort them alphabetically on their display name
asort($aClassLabelAndCodeAsJSON);
//usort($aRootClasses,"Label_sort");
foreach ($aRootClasses as $sClassName => $sDisplayName)
{
if (MetaModel::IsRootClass($sClassName))
{
foreach ($aRootClasses as $sClassName => $sDisplayName) {
if (MetaModel::IsRootClass($sClassName)) {
$oLayout->AddSideHtml("<li class=\"open\">".MakeClassHLink($sClassName, $sContext)."\n");
$oLayout->AddSideHtml(GetSubclasses($sClassName, $sContext));
$oLayout->AddSideHtml("</li>\n");
}
elseif (MetaModel::IsStandaloneClass($sClassName))
{
} elseif (MetaModel::IsStandaloneClass($sClassName)) {
$oLayout->AddSideHtml("<li>".MakeClassHLink($sClassName, $sContext)."</li>\n");
}
}
@@ -480,8 +432,9 @@ JS
$oPage->add_ready_script('$("#ibo-datamodel-viewer--classes-list--list").treeview();');
}
function Label_sort($building_a, $building_b) {
return strnatcmp ($building_a["label"], $building_b["label"]);
function Label_sort($building_a, $building_b)
{
return strnatcmp($building_a["label"], $building_b["label"]);
}
/**
@@ -489,29 +442,23 @@ function Label_sort($building_a, $building_b) {
*/
function DisplayRelatedClassesGraph($oPage, $sClass)
{
try
{
try {
$bOnTheLeft = true;
$bSkipLinkingClasses = false;
// 1) Fetching referencing classes data
//
$aData = array();
$aOrigins = array('_' => true);
$aData = [];
$aOrigins = ['_' => true];
$aRefs = MetaModel::EnumReferencingClasses($sClass, $bSkipLinkingClasses);
$sSelfReference = "false";
if (count($aRefs) != 0)
{
foreach ($aRefs as $sRemoteClass => $aRemoteKeys)
{
foreach ($aRemoteKeys as $sExtKeyAttCode => $oExtKeyAttDef)
{
if ($sRemoteClass != $sClass)
{
if (count($aRefs) != 0) {
foreach ($aRefs as $sRemoteClass => $aRemoteKeys) {
foreach ($aRemoteKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
if ($sRemoteClass != $sClass) {
// ref_prefix to avoid collision between attributes labels that refer to this class and local attributes label that references other classes
$aAttribute = array('label' => 'ref_'.$sExtKeyAttCode);
$aAttribute = ['label' => 'ref_'.$sExtKeyAttCode];
// Test if a distant attribut exists and if it uses a link class
if (!($oExtKeyAttDef->GetMirrorLinkAttribute() == null ? false : $oExtKeyAttDef->GetMirrorLinkAttribute() instanceof AttributeLinkedSetIndirect))
{
if (!($oExtKeyAttDef->GetMirrorLinkAttribute() == null ? false : $oExtKeyAttDef->GetMirrorLinkAttribute() instanceof AttributeLinkedSetIndirect)) {
$aAttribute['related'] = $sRemoteClass;
$aAttribute['related_icon'] = MetaModel::GetClassIcon($aAttribute['related'], false);
$aAttribute['related_position'] = $bOnTheLeft ? -1 : 1;
@@ -529,24 +476,21 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
// 2) Fetching referenced classes data
//
$aDataRef = array(
array(
$aDataRef = [
[
'label' => $sClass,
'icon' => MetaModel::GetClassIcon($sClass, false),
'origin_index' => 0,
'alphabetical_index' => 0,
'origin' => '_',
),
);
],
];
$bOnTheLeft = true;
$aOriginsRef = array('_' => true);
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$aAttribute = array('label' => $sAttCode);
if ($oAttDef->IsLinkSet())
{
if ($oAttDef->IsIndirect())
{
$aOriginsRef = ['_' => true];
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
$aAttribute = ['label' => $sAttCode];
if ($oAttDef->IsLinkSet()) {
if ($oAttDef->IsIndirect()) {
$sRemoteAttDef = $oAttDef->GetExtKeyToRemote();
$aAttribute['related'] = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $sRemoteAttDef)->GetTargetClass();
$aAttribute['related_icon'] = MetaModel::GetClassIcon($aAttribute['related'], false);
@@ -557,9 +501,7 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
$aAttribute['tooltip_data']['to_me'] = $oAttDef->GetExtKeyToMe();
$bOnTheLeft = !$bOnTheLeft; // Toggle the side
}
else
{
} else {
$aAttribute['related'] = $oAttDef->GetLinkedClass();
$aAttribute['related_icon'] = MetaModel::GetClassIcon($aAttribute['related'], false);
$aAttribute['related_position'] = $bOnTheLeft ? 1 : -1;
@@ -567,22 +509,16 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
$bOnTheLeft = !$bOnTheLeft; // Toggle the side
}
}
else
{
if ($oAttDef->IsHierarchicalKey())
{
} else {
if ($oAttDef->IsHierarchicalKey()) {
$aAttribute['related'] = $sClass;
$aAttribute['related_icon'] = MetaModel::GetClassIcon($aAttribute['related'], false);
$aAttribute['related_position'] = $bOnTheLeft ? 1 : -1;
$aAttribute['relation_type'] = 2;
$bOnTheLeft = !$bOnTheLeft; // Toggle the side
$sSelfReference = "true";
}
else
{
if ($oAttDef->IsExternalKey())
{
} else {
if ($oAttDef->IsExternalKey()) {
$aAttribute['related'] = $oAttDef->GetTargetClass();
$aAttribute['related_icon'] = MetaModel::GetClassIcon($aAttribute['related'], false);
$aAttribute['related_position'] = $bOnTheLeft ? 1 : -1;
@@ -592,8 +528,7 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
}
}
}
if ($oAttDef->IsLinkSet() || $oAttDef->IsHierarchicalKey() || $oAttDef->IsExternalKey())
{
if ($oAttDef->IsLinkSet() || $oAttDef->IsHierarchicalKey() || $oAttDef->IsExternalKey()) {
$sOrigin = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
$aAttribute['origin'] = $sOrigin;
@@ -604,39 +539,31 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
}
//sort referencing data
$aOrigins = array_keys($aOrigins);
$idx = 0;
$bOnTheLeft = true;
foreach ($aData as $sAttCode => $aAttribute)
{
foreach ($aData as $sAttCode => $aAttribute) {
$is_also_referenced = false;
foreach ($aDataRef as $sAttCodeRef => $aAttributeRef)
{
if (!empty($aDataRef[$sAttCodeRef]['related']) && ($aData[$sAttCode]['related'] == $aDataRef[$sAttCodeRef]['related']))
{
foreach ($aDataRef as $sAttCodeRef => $aAttributeRef) {
if (!empty($aDataRef[$sAttCodeRef]['related']) && ($aData[$sAttCode]['related'] == $aDataRef[$sAttCodeRef]['related'])) {
$is_also_referenced = true;
}
}
if (!$is_also_referenced)
{
if (!$is_also_referenced) {
$aData[$sAttCode]['related_position'] = ($bOnTheLeft) ? -1 : 1;
$bOnTheLeft = !$bOnTheLeft;
$aData[$sAttCode]['origin_index'] = ($aData[$sAttCode]['related_position'] == -1) ? ++$idx : $idx;
}
else
{
} else {
unset($aData[$sAttCode]);
}
}
ksort($aData);
$idx = 0;
$aFinalDataReferencing = array();
foreach ($aData as $sAttCode => $aAttribute)
{
$aFinalDataReferencing = [];
foreach ($aData as $sAttCode => $aAttribute) {
$aData[$sAttCode]['alphabetical_index'] = $aAttribute['related_position'] == 1 ? ++$idx : $idx;
$aFinalDataReferencing[] = $aData[$sAttCode];
}
@@ -646,15 +573,13 @@ function DisplayRelatedClassesGraph($oPage, $sClass)
//sort referenced data
$idx = 1;
foreach ($aDataRef as $sAttCode => $aAttribute)
{
foreach ($aDataRef as $sAttCode => $aAttribute) {
$aDataRef[$sAttCode]['origin_index'] = $idx++;
}
$idx = 1;
$aFinalData = array();
foreach ($aDataRef as $sAttCode => $aAttribute)
{
$aFinalData = [];
foreach ($aDataRef as $sAttCode => $aAttribute) {
$aDataRef[$sAttCode]['alphabetical_index'] = $idx++;
$aFinalData[] = $aDataRef[$sAttCode];
}
@@ -960,9 +885,7 @@ if(window.IntersectionObserver) {
}
JS
);
}
catch (Exception $e)
{
} catch (Exception $e) {
$oPage->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->getMessage()).'</b>');
}
}
@@ -978,9 +901,8 @@ JS
*/
function DisplayClassDetails($oPage, $sClass, $sContext)
{
$aParentClasses = array();
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
$aParentClasses = [];
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) {
$aParentClasses[] = MakeClassHLink($sParentClass, $sContext);
}
if (count($aParentClasses) > 0) {
@@ -1004,9 +926,9 @@ function DisplayClassDetails($oPage, $sClass, $sContext)
$oPage->SetCurrentTabContainer('details');
// List the attributes of the object
$aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys($sClass);
$aDetails = array();
$aDetails = [];
$aOrigins = array();
$aOrigins = [];
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
if ($oAttDef->IsExternalKey()) {
$sValue = Dict::Format('UI:Schema:ExternalKey_To', MakeClassHLink($oAttDef->GetTargetClass(), $sContext));
@@ -1017,9 +939,7 @@ function DisplayClassDetails($oPage, $sClass, $sContext)
}
} elseif ($oAttDef->IsLinkSet()) {
$sValue = MakeClassHLink($oAttDef->GetLinkedClass(), $sContext);
}
else
{
} else {
$sValue = $oAttDef->GetDescription();
}
$sType = get_class($oAttDef);
@@ -1031,30 +951,25 @@ function DisplayClassDetails($oPage, $sClass, $sContext)
$sAllowedValues = "";
$sMoreInfo = "";
$sDefaultNullValue = '';
if (call_user_func(array(get_class($oAttDef), 'IsBasedOnDBColumns')))
{
if (call_user_func([get_class($oAttDef), 'IsBasedOnDBColumns'])) {
$aMoreInfo = array();
if ($oAttDef->IsNullAllowed())
{
$aMoreInfo = [];
if ($oAttDef->IsNullAllowed()) {
$aMoreInfo[] = Dict::S('UI:Schema:NullAllowed');
$sDefaultNullValue = (!is_null($oAttDef->GetNullValue()) ? $oAttDef->GetNullValue() : null);
if (!is_null($sDefaultNullValue) && !is_string($sDefaultNullValue))
{
if (!is_null($sDefaultNullValue) && !is_string($sDefaultNullValue)) {
$sDefaultNullValue = json_encode($sDefaultNullValue);
}
$sDefaultNullValue = (!is_null($sDefaultNullValue) ? Dict::Format('UI:Schema:DefaultNullValue',
$sDefaultNullValue) : '');
}
else
{
$sDefaultNullValue = (!is_null($sDefaultNullValue) ? Dict::Format(
'UI:Schema:DefaultNullValue',
$sDefaultNullValue
) : '');
} else {
$aMoreInfo[] = Dict::S('UI:Schema:NullNotAllowed');
}
if ($oAttDef->GetDefaultValue())
{
if ($oAttDef->GetDefaultValue()) {
$sDefaultValue = $oAttDef->GetDefaultValue();
if (!is_string($sDefaultValue))
{
if (!is_string($sDefaultValue)) {
$sDefaultValue = json_encode($sDefaultValue);
}
$aMoreInfo[] = Dict::Format("UI:Schema:Default_Description", $sDefaultValue);
@@ -1064,28 +979,22 @@ function DisplayClassDetails($oPage, $sClass, $sContext)
$sAttrCode = $oAttDef->GetCode();
$sIsEnumValues = 'false';
$sAllowedValuesEscpd = '""';
if ($oAttDef instanceof AttributeEnum)
{
if ($oAttDef instanceof AttributeEnum) {
// Display localized values for the enum (which depend on the localization provided by the class)
$aLocalizedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array());
$aDescription = array();
foreach ($aLocalizedValues as $val => $sDisplay)
{
$aLocalizedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, []);
$aDescription = [];
foreach ($aLocalizedValues as $val => $sDisplay) {
$aDescription[] = $sDisplay." (".$val.")";
}
$sAllowedValues = implode(', ', $aDescription);
$sIsEnumValues = 'true';
}
elseif (is_object($oAllowedValuesDef = $oAttDef->GetValuesDef()))
{
} elseif (is_object($oAllowedValuesDef = $oAttDef->GetValuesDef())) {
$sAllowedValues = str_replace("Filter: ", "", $oAllowedValuesDef->GetValuesDescription());
$sAllowedValuesEscpd = utils::HtmlEntities($sAllowedValues);
$sFilterURL = urlencode($sAllowedValues);
$sAllowedValues = '<span id="values'.$sAttrCode.'" data-tooltip-content="'.$sAllowedValuesEscpd.'"><a href="run_query.php?expression='.$sFilterURL.'" class="fas fa-search"></a> '.Dict::S('UI:Schema:Attribute/Filter')."</span>";
}
else
{
} else {
$sAllowedValues = '';
}
$sAttrValueEscpd = utils::HtmlEntities($sValue);
@@ -1093,29 +1002,29 @@ function DisplayClassDetails($oPage, $sClass, $sContext)
$sAttrOriginEscpd = utils::HtmlEntities($sOrigin);
$sDefaultNullValueEscpd = utils::HtmlEntities($sDefaultNullValue);
$aDetails[] = array(
$aDetails[] = [
'code' => '<span id="attr'.$sAttrCode.'" data-tooltip-content="'.$sAttrValueEscpd.'" data-tooltip-html-enabled="true">'.$oAttDef->GetLabel().' ('.$oAttDef->GetCode().')</span>',
'type' => '<span id="type'.$sAttrCode.'" data-tooltip-content="'.$sAttrTypeDescEscpd.'">'.$sTypeDict.' ('.$sType.')</span>',
'origincolor' => '<div class="originColor'.$sOrigin.'" data-tooltip-content="'.$sAttrOriginEscpd.'"></div>',
'origin' => "<span id=\"origin".$sAttrCode."\">$sOrigin</span>",
'values' => $sAllowedValues,
'moreinfo' => '<span id="moreinfo'.$sAttrCode.'" data-tooltip-content="'.$sDefaultNullValueEscpd.'">'.$sMoreInfo.'</span>',
);
];
}
$oPage->SetCurrentTab('UI:Schema:Attributes');
$aConfig = array(
'origincolor' => array('label' => "", 'description' => ""),
'code' => array('label' => Dict::S('UI:Schema:AttributeCode'), 'description' => Dict::S('UI:Schema:AttributeCode+')),
'type' => array('label' => Dict::S('UI:Schema:Type'), 'description' => Dict::S('UI:Schema:Type+')),
'values' => array('label' => Dict::S('UI:Schema:AllowedValues'), 'description' => Dict::S('UI:Schema:AllowedValues+')),
'moreinfo' => array('label' => Dict::S('UI:Schema:MoreInfo'), 'description' => Dict::S('UI:Schema:MoreInfo+')),
'origin' => array('label' => Dict::S('UI:Schema:Origin'), 'description' => Dict::S('UI:Schema:Origin+')),
);
$aConfig = [
'origincolor' => ['label' => "", 'description' => ""],
'code' => ['label' => Dict::S('UI:Schema:AttributeCode'), 'description' => Dict::S('UI:Schema:AttributeCode+')],
'type' => ['label' => Dict::S('UI:Schema:Type'), 'description' => Dict::S('UI:Schema:Type+')],
'values' => ['label' => Dict::S('UI:Schema:AllowedValues'), 'description' => Dict::S('UI:Schema:AllowedValues+')],
'moreinfo' => ['label' => Dict::S('UI:Schema:MoreInfo'), 'description' => Dict::S('UI:Schema:MoreInfo+')],
'origin' => ['label' => Dict::S('UI:Schema:Origin'), 'description' => Dict::S('UI:Schema:Origin+')],
];
$oTablePanel = PanelUIBlockFactory::MakeForClass($sClass, '');
$oTablePanel->AddCSSClass('ibo-datatable-panel');
$oAttributesTable = DataTableUIBlockFactory::MakeForStaticData('', $aConfig, $aDetails, 'ibo-datamodel-viewer--attributes-table', [], "", array('pageLength' => -1));
$oAttributesTable = DataTableUIBlockFactory::MakeForStaticData('', $aConfig, $aDetails, 'ibo-datamodel-viewer--attributes-table', [], "", ['pageLength' => -1]);
$oTablePanel->AddSubBlock($oAttributesTable);
$oPage->AddUiBlock($oTablePanel);
$sOrigins = json_encode(array_keys($aOrigins));
@@ -1140,9 +1049,8 @@ EOF
$oPage->SetCurrentTab('UI:Schema:RelatedClasses');
DisplayRelatedClassesGraph($oPage, $sClass);
if (MetaModel::HasChildrenClasses($sClass))
{
if (MetaModel::HasChildrenClasses($sClass)) {
$oPage->SetCurrentTab('UI:Schema:ChildClasses');
$oPage->add("<ul id=\"ClassHierarchy\">");
$oPage->add("<li class=\"closed\">".$sClass."\n");
@@ -1151,7 +1059,7 @@ EOF
$oPage->add("</ul>\n");
$oPage->add_ready_script('$("#ClassHierarchy").treeview({collapsed: false,});');
}
$oPage->SetCurrentTab('UI:Schema:LifeCycle');
DisplayLifecycle($oPage, $sClass);
@@ -1165,14 +1073,12 @@ EOF
$oPage->SetCurrentTabContainer();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MAIN BLOCK //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Display the menu on the left
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true);
$operation = utils::ReadParam('operation', '');
@@ -1184,8 +1090,14 @@ $oPage->SetContentLayout($oLayout);
$oPage->no_cache();
$oPage->SetBreadCrumbEntry('ui-tool-datamodel', Dict::S('Menu:DataModelMenu'), Dict::S('Menu:DataModelMenu+'), '',
'fas fa-book', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oPage->SetBreadCrumbEntry(
'ui-tool-datamodel',
Dict::S('Menu:DataModelMenu'),
Dict::S('Menu:DataModelMenu+'),
'',
'fas fa-book',
iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES
);
$oTitle = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Schema:Title'));
$oPage->AddUiBlock($oTitle);
@@ -1195,17 +1107,16 @@ $oLayout->AddSideHtml("</div>");
$oPage->add("<div id='ibo-datamodel-viewer'>");
$oPage->add("<div class='ibo-datamodel-viewer--details'>");
switch ($operation)
{
switch ($operation) {
case 'details_class':
$sClass = utils::ReadParam('class', '', false, 'class');
//if we want to see class details & class is given then display it, otherwise act default (just show the class list)
if ($sClass != '')
{
if ($sClass != '') {
$oPage->set_title(Dict::Format('UI:Schema:TitleForClass', $sClass));
DisplayClassDetails($oPage, $sClass, $sContext);
break;
}
// no break
default:
}
$oPage->add("</div>");

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -26,8 +27,7 @@ require_once(APPROOT.'application/startup.inc.php');
require_once(APPROOT.'application/loginwebpage.class.inc.php');
IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST);
try
{
try {
LoginWebPage::DoLogin();
// Check user rights and prompt if needed
ApplicationMenu::CheckMenuIdEnabled("TagAdminMenu");
@@ -56,16 +56,13 @@ try
$oP->SetBreadCrumbEntry('ui-tool-tag-admin', Dict::S('Menu:TagAdminMenu'), Dict::S('Menu:TagAdminMenu+'), '', 'fas fa-tags', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.submit();">';
$aClassLabels = array();
foreach(MetaModel::EnumChildClasses($sBaseClass, ENUM_CHILD_CLASSES_EXCLUDETOP) as $sCurrentClass)
{
$aClassLabels = [];
foreach (MetaModel::EnumChildClasses($sBaseClass, ENUM_CHILD_CLASSES_EXCLUDETOP) as $sCurrentClass) {
$aClassLabels[$sCurrentClass] = MetaModel::GetName($sCurrentClass);
}
asort($aClassLabels);
foreach($aClassLabels as $sCurrentClass => $sLabel)
{
if (empty($sClass))
{
foreach ($aClassLabels as $sCurrentClass => $sLabel) {
if (empty($sClass)) {
$sClass = $sCurrentClass;
}
$sSelected = ($sCurrentClass == $sClass) ? " SELECTED" : "";
@@ -73,34 +70,24 @@ try
}
$sSearchHeaderForceDropdown .= "</select>\n";
try
{
if ($sOperation == 'search_form')
{
try {
if ($sOperation == 'search_form') {
$sOQL = "SELECT $sClass $sOQLClause";
$oFilter = DBObjectSearch::FromOQL($sOQL);
}
else
{
} else {
// Second part: advanced search form:
if (!empty($sFilter))
{
if (!empty($sFilter)) {
$oFilter = DBSearch::unserialize($sFilter);
}
else if (!empty($sClass))
{
} elseif (!empty($sClass)) {
$oFilter = new DBObjectSearch($sClass);
}
}
}
catch (CoreException $e)
{
} catch (CoreException $e) {
$oFilter = new DBObjectSearch($sClass);
$oP->P("<b>".Dict::Format('UI:TagSetFieldData:Error', $e->getHtmlDesc())."</b>");
}
if (!empty($oFilter))
{
if (!empty($oFilter)) {
$oSearchContext = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
$oSet = new CMDBObjectSet($oFilter);
@@ -121,9 +108,7 @@ try
// Menu node
$sFilter = $oFilter->ToOQL();
$oP->add("\n<!-- $sFilter -->\n");
}
else
{
} else {
$oP->add("<p>");
$oP->add(Dict::S('UI:TagAdminMenu:NoTags'));
$oP->add("</p>");
@@ -131,9 +116,7 @@ try
$oP->add("</div>\n");
$oP->output();
}
catch (Exception $e)
{
} catch (Exception $e) {
require_once(APPROOT.'setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));