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

This commit is contained in:
odain
2025-11-07 20:39:38 +01:00
parent 7681c157ec
commit b0a792afab
369 changed files with 22041 additions and 26866 deletions

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -29,56 +30,52 @@ class UserRightsBaseClassGUI extends cmdbAbstractObject
}
}
class URP_Profiles extends UserRightsBaseClassGUI
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "addon/userrights,grant_by_profile,filter",
"key_type" => "autoincrement",
"name_attcode" => "name",
"complementary_name_attcode" => array('description'),
"complementary_name_attcode" => ['description'],
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_urp_profiles",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("name", ["allowed_values" => null, "sql" => "name", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("user_list", array("linked_class"=>"URP_UserProfile", "ext_key_to_me"=>"profileid", "ext_key_to_remote"=>"userid", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("user_list", ["linked_class" => "URP_UserProfile", "ext_key_to_me" => "profileid", "ext_key_to_remote" => "userid", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'user_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['name', 'description', 'user_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name','description')); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array ('name','description'));
MetaModel::Init_SetZListItems('standard_search', ['name','description']); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', ['name','description']);
}
protected static $m_aCacheProfiles = null;
public static function DoCreateProfile($sName, $sDescription)
{
if (is_null(self::$m_aCacheProfiles))
{
self::$m_aCacheProfiles = array();
if (is_null(self::$m_aCacheProfiles)) {
self::$m_aCacheProfiles = [];
$oFilterAll = new DBObjectSearch('URP_Profiles');
$oSet = new DBObjectSet($oFilterAll);
while ($oProfile = $oSet->Fetch())
{
while ($oProfile = $oSet->Fetch()) {
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
}
}
$sCacheKey = $sName;
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
{
if (isset(self::$m_aCacheProfiles[$sCacheKey])) {
return self::$m_aCacheProfiles[$sCacheKey];
}
$oNewObj = MetaModel::NewObject("URP_Profiles");
@@ -89,27 +86,21 @@ class URP_Profiles extends UserRightsBaseClassGUI
return $iId;
}
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
public function GetGrantAsHtml($oUserRights, $sClass, $sAction)
{
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
if (is_null($bGrant))
{
if (is_null($bGrant)) {
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
}
elseif ($bGrant)
{
} elseif ($bGrant) {
return '<span class="ibo-user-rights ibo-is-success">'.Dict::S('UI:UserManagement:ActionAllowed:Yes').'</span>';
}
else
{
} else {
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
}
}
function DoShowGrantSumary($oPage)
public function DoShowGrantSumary($oPage)
{
if ($this->GetRawName() == "Administrator")
{
if ($this->GetRawName() == "Administrator") {
// Looks dirty, but ok that's THE ONE
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
return;
@@ -118,21 +109,18 @@ class URP_Profiles extends UserRightsBaseClassGUI
// Note: for sure, we assume that the instance is derived from UserRightsProfile
$oUserRights = UserRights::GetModuleInstance();
$aDisplayData = array();
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
{
$aStimuli = array();
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
{
$aDisplayData = [];
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
$aStimuli = [];
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
if ($bGrant === true)
{
if ($bGrant === true) {
$aStimuli[] = '<span title="'.$sStimulusCode.': '.utils::EscapeHtml($oStimulus->GetDescription()).'">'.utils::EscapeHtml($oStimulus->GetLabel()).'</span>';
}
}
$sStimuli = implode(', ', $aStimuli);
$aDisplayData[] = array(
$aDisplayData[] = [
'class' => MetaModel::GetName($sClass),
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'),
@@ -141,22 +129,22 @@ class URP_Profiles extends UserRightsBaseClassGUI
'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'),
'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'),
'stimuli' => $sStimuli,
);
];
}
$aDisplayConfig = array();
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
$aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
$aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
$aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
$aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+'));
$aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+'));
$aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
$aDisplayConfig = [];
$aDisplayConfig['class'] = ['label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+')];
$aDisplayConfig['read'] = ['label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+')];
$aDisplayConfig['bulkread'] = ['label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+')];
$aDisplayConfig['write'] = ['label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+')];
$aDisplayConfig['bulkwrite'] = ['label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+')];
$aDisplayConfig['delete'] = ['label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+')];
$aDisplayConfig['bulkdelete'] = ['label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+')];
$aDisplayConfig['stimuli'] = ['label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+')];
$oPage->table($aDisplayConfig, $aDisplayData);
}
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
parent::DisplayBareRelations($oPage, $bEditMode);
@@ -166,10 +154,9 @@ class URP_Profiles extends UserRightsBaseClassGUI
public static function GetReadOnlyAttributes()
{
return array('name', 'description');
return ['name', 'description'];
}
// returns an array of id => array of column => php value(so-called "real value")
public static function GetPredefinedObjects()
{
@@ -181,15 +168,13 @@ class URP_Profiles extends UserRightsBaseClassGUI
protected function OnDelete()
{
// Don't remove admin profile
if ($this->Get('name') === ADMIN_PROFILE_NAME)
{
if ($this->Get('name') === ADMIN_PROFILE_NAME) {
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
}
// Note: this may break the rule that says: "a user must have at least ONE profile" !
$oLnkSet = $this->Get('user_list');
while($oLnk = $oLnkSet->Fetch())
{
while ($oLnk = $oLnkSet->Fetch()) {
$oLnk->DBDelete();
}
}
@@ -202,11 +187,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
* @return integer Flags: the binary combination of the flags applicable to this attribute
*/
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
public function GetAttributeFlags($sAttCode, &$aReasons = [], $sTargetState = '')
{
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
if (MetaModel::GetConfig()->Get('demo_mode'))
{
if (MetaModel::GetConfig()->Get('demo_mode')) {
$aReasons[] = 'Sorry, profiles are read-only in the demonstration mode!';
$iFlags |= OPT_ATT_READONLY;
}
@@ -214,52 +198,52 @@ class URP_Profiles extends UserRightsBaseClassGUI
}
}
class URP_UserProfile extends UserRightsBaseClassGUI
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "addon/userrights,grant_by_profile,filter",
"key_type" => "autoincrement",
"name_attcode" => array("userlogin", "profile"),
"name_attcode" => ["userlogin", "profile"],
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_urp_userprofile",
"db_key_field" => "id",
"db_finalclass_field" => "",
"is_link" => true, /** @since 3.1.0 N°6482 */
'uniqueness_rules' => array(
'no_duplicate' => array(
'attributes' => array(
'uniqueness_rules' => [
'no_duplicate' => [
'attributes' => [
0 => 'userid',
1 => 'profileid',
),
],
'filter' => '',
'disabled' => false,
'is_blocking' => true,
),
),
);
],
],
];
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid",
array("targetclass" => "URP_Profiles", "jointype" => "", "allowed_values" => null, "sql" => "profileid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array(), "allow_target_creation" => false)));
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values" => null, "extkey_attcode" => 'profileid', "target_attcode" => "name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey(
"profileid",
["targetclass" => "URP_Profiles", "jointype" => "", "allowed_values" => null, "sql" => "profileid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => [], "allow_target_creation" => false]
));
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", ["allowed_values" => null, "extkey_attcode" => 'profileid', "target_attcode" => "name"]));
MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('userid', 'profileid', 'reason')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('userid', 'profileid', 'reason')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['userid', 'profileid', 'reason']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['userid', 'profileid', 'reason']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
MetaModel::Init_SetZListItems('standard_search', ['userid', 'profileid']); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', ['userid', 'profileid']); // Criteria of the advanced search form
}
public function CheckToDelete(&$oDeletionPlan)
@@ -267,15 +251,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
if (MetaModel::GetConfig()->Get('demo_mode')) {
// Users deletion is NOT allowed in demo mode
$oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
$oDeletionPlan->ComputeResults();
return false;
}
try {
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
}
catch (SecurityException $e) {
} catch (SecurityException $e) {
// Users deletion is NOT allowed
$oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
@@ -292,15 +275,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
if (MetaModel::GetConfig()->Get('demo_mode')) {
// Users deletion is NOT allowed in demo mode
$oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
$oDeletionPlan->ComputeResults();
return false;
}
try {
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
}
catch (SecurityException $e) {
} catch (SecurityException $e) {
// Users deletion is NOT allowed
$oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
@@ -336,33 +318,30 @@ class URP_UserProfile extends UserRightsBaseClassGUI
protected function CheckIfProfileIsAllowed($iActionCode)
{
// When initializing or admin, we need to let everything pass trough
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
return;
}
// Only administrators can manage administrators
$iOrigUserId = $this->GetOriginal('userid');
if (!empty($iOrigUserId))
{
if (!empty($iOrigUserId)) {
$oUser = MetaModel::GetObject('User', $iOrigUserId, true, true);
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator())
{
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator()) {
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
}
}
$oUser = MetaModel::GetObject('User', $this->Get('userid'), true, true);
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator())
{
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator()) {
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
}
$oSet = new \ormLinkSet(get_class($oUser), 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
$oSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $this->GetKey(), 'reason' => 'CheckIfProfileIsAllowed']));
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, $oSet))
{
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, $oSet)) {
throw new SecurityException(Dict::Format('UI:Error:ObjectCannotBeUpdated'));
}
if (!UserRights::IsAdministrator() && ($this->Get('profile') === ADMIN_PROFILE_NAME))
{
if (!UserRights::IsAdministrator() && ($this->Get('profile') === ADMIN_PROFILE_NAME)) {
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
}
}
@@ -373,33 +352,33 @@ class URP_UserOrg extends UserRightsBaseClassGUI
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "addon/userrights,grant_by_profile",
"key_type" => "autoincrement",
"name_attcode" => array("userlogin", "allowed_org_name"),
"name_attcode" => ["userlogin", "allowed_org_name"],
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_urp_userorg",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("allowed_org_id", array("targetclass"=>"Organization", "jointype"=> "", "allowed_values"=>null, "sql"=>"allowed_org_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("allowed_org_name", array("allowed_values"=>null, "extkey_attcode"=> 'allowed_org_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("allowed_org_id", ["targetclass" => "Organization", "jointype" => "", "allowed_values" => null, "sql" => "allowed_org_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("allowed_org_name", ["allowed_values" => null, "extkey_attcode" => 'allowed_org_id', "target_attcode" => "name"]));
MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"reason", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "reason", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('userid', 'allowed_org_id', 'reason')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('allowed_org_id', 'reason')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['userid', 'allowed_org_id', 'reason']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['allowed_org_id', 'reason']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
MetaModel::Init_SetZListItems('standard_search', ['userid', 'allowed_org_id']); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', ['userid', 'allowed_org_id']); // Criteria of the advanced search form
}
protected function OnInsert()
@@ -422,40 +401,37 @@ class URP_UserOrg extends UserRightsBaseClassGUI
*/
protected function CheckIfOrgIsAllowed()
{
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
return;
}
$oUser = UserRights::GetUserObject();
$oAddon = UserRights::GetModuleInstance();
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
if (count($aOrgs) > 0)
{
if (count($aOrgs) > 0) {
$iOrigOrgId = $this->GetOriginal('allowed_org_id');
if ((!empty($iOrigOrgId) && !in_array($iOrigOrgId, $aOrgs)) || !in_array($this->Get('allowed_org_id'), $aOrgs))
{
if ((!empty($iOrigOrgId) && !in_array($iOrigOrgId, $aOrgs)) || !in_array($this->Get('allowed_org_id'), $aOrgs)) {
throw new SecurityException(Dict::Format('Class:User/Error:OrganizationNotAllowed'));
}
}
}
}
class UserRightsProfile extends UserRightsAddOnAPI
{
static public $m_aActionCodes = array(
public static $m_aActionCodes = [
UR_ACTION_READ => 'r',
UR_ACTION_MODIFY => 'w',
UR_ACTION_DELETE => 'd',
UR_ACTION_BULK_READ => 'br',
UR_ACTION_BULK_MODIFY => 'bw',
UR_ACTION_BULK_DELETE => 'bd',
);
];
/**
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
*/
/**
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
*/
private $aUsersProfilesList = [];
// Installation: create the very first user
@@ -476,8 +452,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
$oContact = MetaModel::NewObject('Person');
$oContact->Set('name', 'My last name');
$oContact->Set('first_name', 'My first name');
if (MetaModel::IsValidAttCode('Person', 'org_id'))
{
if (MetaModel::IsValidAttCode('Person', 'org_id')) {
$oContact->Set('org_id', $iOrgId);
}
$oContact->Set('email', 'my.email@foo.org');
@@ -485,20 +460,17 @@ class UserRightsProfile extends UserRightsAddOnAPI
}
}
$oUser = new UserLocal();
$oUser->Set('login', $sAdminUser);
$oUser->Set('password', $sAdminPwd);
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0))
{
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0)) {
$oUser->Set('contactid', $iContactId);
}
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
// Add this user to the very specific 'admin' profile
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true /*all data*/);
if (is_object($oAdminProfile))
{
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => ADMIN_PROFILE_NAME], true /*all data*/);
if (is_object($oAdminProfile)) {
$oSet = new \ormLinkSet(UserLocal::class, 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
$oSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $oAdminProfile->GetKey(), 'reason' => 'CreateAdministrator']));
$oUser->Set('profile_list', $oSet);
@@ -511,11 +483,11 @@ class UserRightsProfile extends UserRightsAddOnAPI
{
}
protected $m_aUserOrgs = array(); // userid -> array of orgid
protected $m_aUserOrgs = []; // userid -> array of orgid
protected $m_aAdministrators = null; // [user id]
// Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read)
protected $m_aObjectActionGrants = array();
protected $m_aObjectActionGrants = [];
/**
* Read and cache organizations allowed to the given user
@@ -530,31 +502,25 @@ class UserRightsProfile extends UserRightsAddOnAPI
public function GetUserOrgs($oUser, $sClass)
{
$iUser = $oUser->GetKey();
if (!array_key_exists($iUser, $this->m_aUserOrgs))
{
$this->m_aUserOrgs[$iUser] = array();
if (!array_key_exists($iUser, $this->m_aUserOrgs)) {
$this->m_aUserOrgs[$iUser] = [];
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
if ($sHierarchicalKeyCode !== false)
{
if ($sHierarchicalKeyCode !== false) {
$sUserOrgQuery = 'SELECT UserOrg, Org FROM Organization AS Org JOIN Organization AS Root ON Org.'.$sHierarchicalKeyCode.' BELOW Root.id JOIN URP_UserOrg AS UserOrg ON UserOrg.allowed_org_id = Root.id WHERE UserOrg.userid = :userid';
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), array(), array('userid' => $iUser));
while ($aRow = $oUserOrgSet->FetchAssoc())
{
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), [], ['userid' => $iUser]);
while ($aRow = $oUserOrgSet->FetchAssoc()) {
$oOrg = $aRow['Org'];
$this->m_aUserOrgs[$iUser][] = $oOrg->GetKey();
}
}
else
{
} else {
$oSearch = new DBObjectSearch('URP_UserOrg');
$oSearch->AllowAllData();
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
$oSearch->AddConditionExpression($oCondition);
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
while ($oUserOrg = $oUserOrgSet->Fetch())
{
$oUserOrgSet = new DBObjectSet($oSearch, [], ['userid' => $iUser]);
while ($oUserOrg = $oUserOrgSet->Fetch()) {
$this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id');
}
}
@@ -565,21 +531,19 @@ class UserRightsProfile extends UserRightsAddOnAPI
public function ResetCache()
{
// Loaded by Load cache
$this->m_aUserOrgs = array();
$this->m_aUserOrgs = [];
// Cache
$this->m_aObjectActionGrants = array();
$this->m_aObjectActionGrants = [];
$this->m_aAdministrators = null;
}
public function LoadCache()
{
static $bSharedObjectInitialized = false;
if (!$bSharedObjectInitialized)
{
if (!$bSharedObjectInitialized) {
$bSharedObjectInitialized = true;
if (self::HasSharing())
{
if (self::HasSharing()) {
SharedObject::InitSharedClassProperties();
}
}
@@ -617,45 +581,40 @@ class UserRightsProfile extends UserRightsAddOnAPI
*/
public function ListProfiles($oUser)
{
$aRet = array();
$aRet = [];
$oSearch = new DBObjectSearch('URP_UserProfile');
$oSearch->AllowAllData();
$oSearch->NoContextParameters();
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
$oProfiles = new DBObjectSet($oSearch);
while ($oUserProfile = $oProfiles->Fetch())
{
while ($oUserProfile = $oProfiles->Fetch()) {
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
}
return $aRet;
}
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
{
$this->LoadCache();
// Let us pass an administrator for bypassing the grant matrix check in order to test this method without the need to set up a complex profile
// In the nominal case Administrators never end up here (since they completely bypass GetSelectFilter)
if (!static::IsAdministrator($oUser) && (MetaModel::HasCategory($sClass, 'silo') || MetaModel::HasCategory($sClass, 'bizmodel')))
{
if (!static::IsAdministrator($oUser) && (MetaModel::HasCategory($sClass, 'silo') || MetaModel::HasCategory($sClass, 'bizmodel'))) {
// N°4354 - Categories 'silo' and 'bizmodel' do check the grant matrix. Whereas 'filter' always allows to read (but the result can be filtered)
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
{
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO) {
return false;
}
}
$oFilter = true;
$aConditions = array();
$aConditions = [];
// Determine if this class is part of a silo and build the filter for it
$sAttCode = self::GetOwnerOrganizationAttCode($sClass);
if (!is_null($sAttCode))
{
if (!is_null($sAttCode)) {
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
if (count($aUserOrgs) > 0)
{
if (count($aUserOrgs) > 0) {
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
}
// else: No org means 'any org'
@@ -664,20 +623,15 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Specific conditions to hide, for non-administrators, the Administrator Users, the Administrator Profile and related links
// Note: when logged as an administrator, GetSelectFilter is completely bypassed.
if ($this->AdministratorsAreHidden())
{
if ($sClass == 'URP_Profiles')
{
if ($this->AdministratorsAreHidden()) {
if ($sClass == 'URP_Profiles') {
$oExpression = new FieldExpression('id', $sClass);
$oScalarExpr = new ScalarExpression(1);
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
}
else if (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User')))
{
} elseif (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User'))) {
$aAdministrators = $this->GetAdministrators();
if (count($aAdministrators) > 0)
{
if (count($aAdministrators) > 0) {
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
$oExpression = new FieldExpression($sAttCode, $sClass);
$oListExpr = ListExpression::FromScalars($aAdministrators);
@@ -687,17 +641,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
}
// Handling of the added conditions
if (count($aConditions) > 0)
{
if($oFilter === true)
{
if (count($aConditions) > 0) {
if ($oFilter === true) {
// No 'silo' filter, let's build a clean one
$oFilter = new DBObjectSearch($sClass);
}
// Add the conditions to the filter
foreach($aConditions as $oCondition)
{
foreach ($aConditions as $oCondition) {
$oFilter->AddConditionExpression($oCondition);
}
}
@@ -712,10 +663,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
*/
private function GetAdministrators()
{
if ($this->m_aAdministrators === null)
{
if ($this->m_aAdministrators === null) {
// Find all administrators
$this->m_aAdministrators = array();
$this->m_aAdministrators = [];
$oAdministratorsFilter = new DBObjectSearch('User');
$oLnkFilter = new DBObjectSearch('URP_UserProfile');
$oExpression = new FieldExpression('profileid', 'URP_UserProfile');
@@ -725,9 +675,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
$oSet = new DBObjectSet($oAdministratorsFilter);
$oSet->OptimizeColumnLoad(array('User' => array('login')));
while($oUser = $oSet->Fetch())
{
$oSet->OptimizeColumnLoad(['User' => ['login']]);
while ($oUser = $oSet->Fetch()) {
$this->m_aAdministrators[] = $oUser->GetKey();
}
}
@@ -743,7 +692,6 @@ class UserRightsProfile extends UserRightsAddOnAPI
return ((bool)MetaModel::GetConfig()->Get('security.hide_administrators'));
}
// This verb has been made public to allow the development of an accurate feedback for the current configuration
public function GetProfileActionGrant($iProfile, $sClass, $sAction)
{
@@ -760,33 +708,29 @@ class UserRightsProfile extends UserRightsAddOnAPI
// load and cache permissions for the current user on the given class
//
$iUser = $oUser->GetKey();
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])){
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])) {
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
if (is_array($aTest)) return $aTest;
if (is_array($aTest)) {
return $aTest;
}
}
$sAction = self::$m_aActionCodes[$iActionCode];
$bStatus = null;
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
// Cache user's profiles
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
// Call the API of UserRights because it caches the list for us
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
if (!is_null($bGrant))
{
if ($bGrant)
{
if (is_null($bStatus))
{
if (!is_null($bGrant)) {
if ($bGrant) {
if (is_null($bStatus)) {
$bStatus = true;
}
}
else
{
} else {
$bStatus = false;
}
}
@@ -794,9 +738,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
$iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO;
$aRes = array(
$aRes = [
'permission' => $iPermission,
);
];
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
return $aRes;
}
@@ -811,20 +755,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: In most cases the object set is ignored because it was interesting to optimize for huge data sets
// and acceptable to consider only the root class of the object set
if ($iPermission != UR_ALLOWED_YES)
{
if ($iPermission != UR_ALLOWED_YES) {
// It is already NO for everyone... that's the final word!
}
elseif ($iActionCode == UR_ACTION_READ)
{
} elseif ($iActionCode == UR_ACTION_READ) {
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
}
elseif ($iActionCode == UR_ACTION_BULK_READ)
{
} elseif ($iActionCode == UR_ACTION_BULK_READ) {
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
}
elseif ($oInstanceSet)
{
} elseif ($oInstanceSet) {
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
// We have to answer NO for objects shared for reading purposes
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
@@ -888,8 +825,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: this code is VERY close to the code of IsActionAllowed()
$iUser = $oUser->GetKey();
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
// Cache user's profiles
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
@@ -897,20 +834,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
// and acceptable to consider only the root class of the object set
$bStatus = null;
// Call the API of UserRights because it caches the list for us
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
if (!is_null($bGrant))
{
if ($bGrant)
{
if (is_null($bStatus))
{
if (!is_null($bGrant)) {
if ($bGrant) {
if (is_null($bStatus)) {
$bStatus = true;
}
}
else
{
} else {
$bStatus = false;
}
}
@@ -934,22 +865,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
{
$sAttCode = null;
$aCallSpec = array($sClass, 'MapContextParam');
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization'))
{
$aCallSpec = [$sClass, 'MapContextParam'];
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization')) {
$sAttCode = 'id';
}
elseif (is_callable($aCallSpec))
{
} elseif (is_callable($aCallSpec)) {
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
// Skip silently. The data model checker will tell you something about this...
$sAttCode = null;
}
}
elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
{
} elseif (MetaModel::IsValidAttCode($sClass, 'org_id')) {
$sAttCode = 'org_id';
}
@@ -962,14 +887,11 @@ class UserRightsProfile extends UserRightsAddOnAPI
protected static function HasSharing()
{
static $bHasSharing;
if (!isset($bHasSharing))
{
if (!isset($bHasSharing)) {
$bHasSharing = class_exists('SharedObject');
}
return $bHasSharing;
}
}
UserRights::SelectModule('UserRightsProfile');

View File

@@ -74,7 +74,3 @@ require_once(APPROOT.'application/applicationextension/rest/iRestInputSanitizer.
require_once(APPROOT.'application/applicationextension/rest/iRestServiceProvider.php');
require_once(APPROOT.'application/applicationextension/rest/RestResult.php');
require_once(APPROOT.'application/applicationextension/rest/RestUtils.php');

View File

@@ -9,64 +9,64 @@
*/
abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
{
/**
* @inheritDoc
*/
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnFormSubmit($oObject, $sFormPrefix = '')
{
}
/**
* @inheritDoc
*/
public function OnFormSubmit($oObject, $sFormPrefix = '')
{
}
/**
* @inheritDoc
*/
public function OnFormCancel($sTempId)
{
}
/**
* @inheritDoc
*/
public function OnFormCancel($sTempId)
{
}
/**
* @inheritDoc
*/
public function EnumUsedAttributes($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function EnumUsedAttributes($oObject)
{
return [];
}
/**
* @inheritDoc
*/
public function GetIcon($oObject)
{
return '';
}
/**
* @inheritDoc
*/
public function GetIcon($oObject)
{
return '';
}
/**
* @inheritDoc
*/
public function GetHilightClass($oObject)
{
return HILIGHT_CLASS_NONE;
}
/**
* @inheritDoc
*/
public function GetHilightClass($oObject)
{
return HILIGHT_CLASS_NONE;
}
/**
* @inheritDoc
*/
public function EnumAllowedActions(DBObjectSet $oSet)
{
return array();
}
/**
* @inheritDoc
*/
public function EnumAllowedActions(DBObjectSet $oSet)
{
return [];
}
}
}

View File

@@ -9,27 +9,27 @@
*/
abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
{
/**
* @inheritDoc
*/
public function GetBannerBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetBannerBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetHeaderBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetHeaderBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetFooterBlock()
{
return null;
}
}
/**
* @inheritDoc
*/
public function GetFooterBlock()
{
return null;
}
}

View File

@@ -9,20 +9,20 @@
*/
abstract class AbstractPreferencesExtension implements iPreferencesExtension
{
/**
* @inheritDoc
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage)
{
// Do nothing
}
/**
* @inheritDoc
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage)
{
// Do nothing
}
/**
* @inheritDoc
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation)
{
// Do nothing
}
/**
* @inheritDoc
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation)
{
// Do nothing
}
}
}

View File

@@ -8,28 +8,28 @@
*/
abstract class AbstractWelcomePopupExtension implements iWelcomePopupExtension
{
/**
* @inheritDoc
*/
public function GetIconRelPath(): string
{
return \Combodo\iTop\Application\Branding::$aLogoPaths[\Combodo\iTop\Application\Branding::ENUM_LOGO_TYPE_MAIN_LOGO_COMPACT]['default'];
}
/**
* @inheritDoc
*/
public function GetIconRelPath(): string
{
return \Combodo\iTop\Application\Branding::$aLogoPaths[\Combodo\iTop\Application\Branding::ENUM_LOGO_TYPE_MAIN_LOGO_COMPACT]['default'];
}
/**
* @inheritDoc
*/
public function GetMessages(): array
{
return [];
}
/**
* @inheritDoc
*/
public function GetMessages(): array
{
return [];
}
/**
* @inheritDoc
*/
public function AcknowledgeMessage(string $sMessageId): void
{
// No need to process the acknowledgment notice by default
return;
}
}
/**
* @inheritDoc
*/
public function AcknowledgeMessage(string $sMessageId): void
{
// No need to process the acknowledgment notice by default
return;
}
}

View File

@@ -9,142 +9,141 @@
*/
abstract class ApplicationPopupMenuItem
{
/** @ignore */
protected $sUID;
/** @ignore */
protected $sLabel;
/** @ignore */
protected $sTooltip;
/** @ignore */
protected $sIconClass;
/** @ignore */
protected $aCssClasses;
/** @ignore */
protected $sUID;
/** @ignore */
protected $sLabel;
/** @ignore */
protected $sTooltip;
/** @ignore */
protected $sIconClass;
/** @ignore */
protected $aCssClasses;
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @api
*/
public function __construct($sUID, $sLabel)
{
$this->sUID = $sUID;
$this->sLabel = $sLabel;
$this->sTooltip = '';
$this->sIconClass = '';
$this->aCssClasses = array();
}
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @api
*/
public function __construct($sUID, $sLabel)
{
$this->sUID = $sUID;
$this->sLabel = $sLabel;
$this->sTooltip = '';
$this->sIconClass = '';
$this->aCssClasses = [];
}
/**
* Get the UID
*
* @return string The unique identifier
* @ignore
*/
public function GetUID()
{
return $this->sUID;
}
/**
* Get the UID
*
* @return string The unique identifier
* @ignore
*/
public function GetUID()
{
return $this->sUID;
}
/**
* Get the label
*
* @return string The label
* @ignore
*/
public function GetLabel()
{
return $this->sLabel;
}
/**
* Get the label
*
* @return string The label
* @ignore
*/
public function GetLabel()
{
return $this->sLabel;
}
/**
* Get the CSS classes
*
* @return array
* @ignore
*/
public function GetCssClasses()
{
return $this->aCssClasses;
}
/**
* Get the CSS classes
*
* @return array
* @ignore
*/
public function GetCssClasses()
{
return $this->aCssClasses;
}
/**
* @param $aCssClasses
* @api
*/
public function SetCssClasses($aCssClasses)
{
$this->aCssClasses = $aCssClasses;
}
/**
* @param $aCssClasses
* @api
*/
public function SetCssClasses($aCssClasses)
{
$this->aCssClasses = $aCssClasses;
}
/**
* Adds a CSS class to the CSS classes that will be put on the menu item
*
* @param $sCssClass
* @api
*/
public function AddCssClass($sCssClass)
{
$this->aCssClasses[] = $sCssClass;
}
/**
* Adds a CSS class to the CSS classes that will be put on the menu item
*
* @param $sCssClass
* @api
*/
public function AddCssClass($sCssClass)
{
$this->aCssClasses[] = $sCssClass;
}
/**
* @param $sTooltip
*
* @api
* @since 3.0.0
*/
public function SetTooltip($sTooltip)
{
$this->sTooltip = $sTooltip;
}
/**
* @param $sTooltip
*
* @api
* @since 3.0.0
*/
public function SetTooltip($sTooltip)
{
$this->sTooltip = $sTooltip;
}
/**
* @return string
*
* @api
* @since 3.0.0
*/
public function GetTooltip()
{
return $this->sTooltip;
}
/**
* @return string
*
* @api
* @since 3.0.0
*/
public function GetTooltip()
{
return $this->sTooltip;
}
/**
* @param $sIconClass
*
* @api
* @since 3.0.0
*/
public function SetIconClass($sIconClass)
{
$this->sIconClass = $sIconClass;
}
/**
* @param $sIconClass
*
* @api
* @since 3.0.0
*/
public function SetIconClass($sIconClass)
{
$this->sIconClass = $sIconClass;
}
/**
* @return string
*
* @api
* @since 3.0.0
*/
public function GetIconClass()
{
return $this->sIconClass;
}
/**
* @return string
*
* @api
* @since 3.0.0
*/
public function GetIconClass()
{
return $this->sIconClass;
}
/**
* Returns the components to create a popup menu item in HTML
*
* @return array A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
*/
abstract public function GetMenuItem();
/**
* Returns the components to create a popup menu item in HTML
*
* @return array A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
*/
abstract public function GetMenuItem();
/** @ignore */
public function GetLinkedScripts()
{
return array();
}
}
/** @ignore */
public function GetLinkedScripts()
{
return [];
}
}

View File

@@ -9,5 +9,4 @@
*/
class JSButtonItem extends JSPopupMenuItem
{
}
}

View File

@@ -11,60 +11,60 @@
*/
class JSPopupMenuItem extends ApplicationPopupMenuItem
{
/** @ignore */
protected $sJsCode;
/** @ignore */
protected $sUrl;
/** @ignore */
protected $aIncludeJSFiles;
/** @ignore */
protected $sJsCode;
/** @ignore */
protected $sUrl;
/** @ignore */
protected $aIncludeJSFiles;
/**
* Class for adding an item that triggers some Javascript code
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sJSCode In case the menu consists in executing some havascript code inside the page, pass it here. If supplied $sURL
* ans $sTarget will be ignored
* @param array $aIncludeJSFiles An array of file URLs to be included (once) to provide some JS libraries for the page.
* @api
*/
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = array())
{
parent::__construct($sUID, $sLabel);
$this->sJsCode = $sJSCode;
$this->sUrl = '#';
$this->aIncludeJSFiles = $aIncludeJSFiles;
}
/**
* Class for adding an item that triggers some Javascript code
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sJSCode In case the menu consists in executing some havascript code inside the page, pass it here. If supplied $sURL
* ans $sTarget will be ignored
* @param array $aIncludeJSFiles An array of file URLs to be included (once) to provide some JS libraries for the page.
* @api
*/
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = [])
{
parent::__construct($sUID, $sLabel);
$this->sJsCode = $sJSCode;
$this->sUrl = '#';
$this->aIncludeJSFiles = $aIncludeJSFiles;
}
/** @ignore */
public function GetMenuItem()
{
// Note: the semicolumn is a must here!
return array(
'label' => $this->GetLabel(),
'onclick' => $this->GetJsCode() . '; return false;',
'url' => $this->GetUrl(),
'css_classes' => $this->GetCssClasses(),
'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip
);
}
/** @ignore */
public function GetMenuItem()
{
// Note: the semicolumn is a must here!
return [
'label' => $this->GetLabel(),
'onclick' => $this->GetJsCode().'; return false;',
'url' => $this->GetUrl(),
'css_classes' => $this->GetCssClasses(),
'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip,
];
}
/** @ignore */
public function GetLinkedScripts()
{
return $this->aIncludeJSFiles;
}
/** @ignore */
public function GetLinkedScripts()
{
return $this->aIncludeJSFiles;
}
/** @ignore */
public function GetJsCode()
{
return $this->sJsCode;
}
/** @ignore */
public function GetJsCode()
{
return $this->sJsCode;
}
/** @ignore */
public function GetUrl()
{
return $this->sUrl;
}
}
/** @ignore */
public function GetUrl()
{
return $this->sUrl;
}
}

View File

@@ -10,20 +10,20 @@
*/
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
{
static $idx = 0;
public static $idx = 0;
/**
* Constructor
* @api
*/
public function __construct()
{
parent::__construct('_separator_' . (self::$idx++), '');
}
/**
* Constructor
* @api
*/
public function __construct()
{
parent::__construct('_separator_'.(self::$idx++), '');
}
/** @ignore */
public function GetMenuItem()
{
return array('label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses);
}
}
/** @ignore */
public function GetMenuItem()
{
return ['label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses];
}
}

View File

@@ -9,5 +9,4 @@
*/
class URLButtonItem extends URLPopupMenuItem
{
}
}

View File

@@ -11,48 +11,48 @@
*/
class URLPopupMenuItem extends ApplicationPopupMenuItem
{
/** @ignore */
protected $sUrl;
/** @ignore */
protected $sTarget;
/** @ignore */
protected $sUrl;
/** @ignore */
protected $sTarget;
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
* @api
*/
public function __construct($sUID, $sLabel, $sUrl, $sTarget = '_top')
{
parent::__construct($sUID, $sLabel);
$this->sUrl = $sUrl;
$this->sTarget = $sTarget;
}
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
* @api
*/
public function __construct($sUID, $sLabel, $sUrl, $sTarget = '_top')
{
parent::__construct($sUID, $sLabel);
$this->sUrl = $sUrl;
$this->sTarget = $sTarget;
}
/** @ignore */
public function GetMenuItem()
{
return array('label' => $this->GetLabel(),
'url' => $this->GetUrl(),
'target' => $this->GetTarget(),
'css_classes' => $this->aCssClasses,
'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip
);
}
/** @ignore */
public function GetMenuItem()
{
return ['label' => $this->GetLabel(),
'url' => $this->GetUrl(),
'target' => $this->GetTarget(),
'css_classes' => $this->aCssClasses,
'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip,
];
}
/** @ignore */
public function GetUrl()
{
return $this->sUrl;
}
/** @ignore */
public function GetUrl()
{
return $this->sUrl;
}
/** @ignore */
public function GetTarget()
{
return $this->sTarget;
}
}
/** @ignore */
public function GetTarget()
{
return $this->sTarget;
}
}

View File

@@ -27,147 +27,147 @@
*/
interface iApplicationUIExtension
{
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called right after the main tab has been displayed.
* You can add output to the page, either to change the display, or to add a form input
*
* Example:
* <code>
* if ($bEditMode)
* {
* $oPage->p('Age of the captain: &lt;input type="text" name="captain_age"/&gt;');
* }
* else
* {
* $oPage->p('Age of the captain: '.$iCaptainAge);
* }
* </code>
*
* @api
*
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
*
* @param DBObject $oObject The object being displayed
*
* @return void
*/
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called right after the main tab has been displayed.
* You can add output to the page, either to change the display, or to add a form input
*
* Example:
* <code>
* if ($bEditMode)
* {
* $oPage->p('Age of the captain: &lt;input type="text" name="captain_age"/&gt;');
* }
* else
* {
* $oPage->p('Age of the captain: '.$iCaptainAge);
* }
* </code>
*
* @api
*
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
*
* @param DBObject $oObject The object being displayed
*
* @return void
*/
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called rigth after all the tabs have been displayed
*
* @api
*
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
*
* @param DBObject $oObject The object being displayed
*
* @return void
*/
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called rigth after all the tabs have been displayed
*
* @api
*
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
*
* @param DBObject $oObject The object being displayed
*
* @return void
*/
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
/**
* Invoked when the end-user clicks on Modify from the object edition form
*
* The method is called after the changes from the standard form have been
* taken into account, and before saving the changes into the database.
*
* @param DBObject $oObject The object being edited
* @param string $sFormPrefix Prefix given to the HTML form inputs
*
* @return void
* @api
*/
public function OnFormSubmit($oObject, $sFormPrefix = '');
/**
* Invoked when the end-user clicks on Modify from the object edition form
*
* The method is called after the changes from the standard form have been
* taken into account, and before saving the changes into the database.
*
* @param DBObject $oObject The object being edited
* @param string $sFormPrefix Prefix given to the HTML form inputs
*
* @return void
* @api
*/
public function OnFormSubmit($oObject, $sFormPrefix = '');
/**
* Invoked when the end-user clicks on Cancel from the object edition form
*
* Implement here any cleanup. This is necessary when you have injected some
* javascript into the edition form, and if that code requires to store temporary data
* (this is the case when a file must be uploaded).
*
* @param string $sTempId Unique temporary identifier made of session_id and transaction_id. It identifies the object in a unique way.
*
* @return void
* @api
*/
public function OnFormCancel($sTempId);
/**
* Invoked when the end-user clicks on Cancel from the object edition form
*
* Implement here any cleanup. This is necessary when you have injected some
* javascript into the edition form, and if that code requires to store temporary data
* (this is the case when a file must be uploaded).
*
* @param string $sTempId Unique temporary identifier made of session_id and transaction_id. It identifies the object in a unique way.
*
* @return void
* @api
*/
public function OnFormCancel($sTempId);
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string[] desc
* @api
*/
public function EnumUsedAttributes($oObject); // Not yet implemented
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string[] desc
* @api
*/
public function EnumUsedAttributes($oObject); // Not yet implemented
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string Path of the icon, relative to the modules directory.
* @api
*/
public function GetIcon($oObject); // Not yet implemented
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string Path of the icon, relative to the modules directory.
* @api
*/
public function GetIcon($oObject); // Not yet implemented
/**
* Invoked when the object is displayed alone or within a list
*
* Returns a value influencing the appearance of the object depending on its
* state.
*
* Possible values are:
*
* * HILIGHT_CLASS_CRITICAL
* * HILIGHT_CLASS_WARNING
* * HILIGHT_CLASS_OK
* * HILIGHT_CLASS_NONE
*
* @param DBObject $oObject The object being displayed
*
* @return integer The value representing the mood of the object
* @api
*/
public function GetHilightClass($oObject);
/**
* Invoked when the object is displayed alone or within a list
*
* Returns a value influencing the appearance of the object depending on its
* state.
*
* Possible values are:
*
* * HILIGHT_CLASS_CRITICAL
* * HILIGHT_CLASS_WARNING
* * HILIGHT_CLASS_OK
* * HILIGHT_CLASS_NONE
*
* @param DBObject $oObject The object being displayed
*
* @return integer The value representing the mood of the object
* @api
*/
public function GetHilightClass($oObject);
/**
* Called when building the Actions menu for a single object or a list of objects
*
* Use this to add items to the Actions menu. You will have to specify a label and an URL.
*
* Example:
* <code>
* $oObject = $oSet->fetch();
* if ($oObject instanceof Sheep)
* {
* return array('View in my app' => 'http://myserver/view_sheeps?id='.$oObject->Get('name'));
* }
* else
* {
* return array();
* }
* </code>
*
* See also iPopupMenuExtension for greater flexibility
*
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
*
* @return array
* @api
*/
public function EnumAllowedActions(DBObjectSet $oSet);
}
/**
* Called when building the Actions menu for a single object or a list of objects
*
* Use this to add items to the Actions menu. You will have to specify a label and an URL.
*
* Example:
* <code>
* $oObject = $oSet->fetch();
* if ($oObject instanceof Sheep)
* {
* return array('View in my app' => 'http://myserver/view_sheeps?id='.$oObject->Get('name'));
* }
* else
* {
* return array();
* }
* </code>
*
* See also iPopupMenuExtension for greater flexibility
*
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
*
* @return array
* @api
*/
public function EnumAllowedActions(DBObjectSet $oSet);
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeDictEntriesExtension
{
/**
* @return array
* @see \iTopWebPage::a_dict_entries
* @api
*/
public function GetDictEntries(): array;
}
/**
* @return array
* @see \iTopWebPage::a_dict_entries
* @api
*/
public function GetDictEntries(): array;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeDictEntriesPrefixesExtension
{
/**
* @return array
* @see \iTopWebPage::a_dict_entries_prefixes
* @api
*/
public function GetDictEntriesPrefixes(): array;
}
/**
* @return array
* @see \iTopWebPage::a_dict_entries_prefixes
* @api
*/
public function GetDictEntriesPrefixes(): array;
}

View File

@@ -11,10 +11,10 @@
*/
interface iBackofficeEarlyScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_early_scripts
* @api
*/
public function GetEarlyScript(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_early_scripts
* @api
*/
public function GetEarlyScript(): string;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeInitScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_init_scripts
* @api
*/
public function GetInitScript(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_init_scripts
* @api
*/
public function GetInitScript(): string;
}

View File

@@ -10,11 +10,11 @@
*/
interface iBackofficeLinkedScriptsExtension
{
/**
* Each script will be included using this property
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_scripts
* @api
*/
public function GetLinkedScriptsAbsUrls(): array;
}
/**
* Each script will be included using this property
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_scripts
* @api
*/
public function GetLinkedScriptsAbsUrls(): array;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeLinkedStylesheetsExtension
{
/**
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_stylesheets
* @api
*/
public function GetLinkedStylesheetsAbsUrls(): array;
}
/**
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_stylesheets
* @api
*/
public function GetLinkedStylesheetsAbsUrls(): array;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeReadyScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_ready_scripts
* @api
*/
public function GetReadyScript(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_ready_scripts
* @api
*/
public function GetReadyScript(): string;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeSassExtension
{
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetSass(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetSass(): string;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_scripts
* @api
*/
public function GetScript(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_scripts
* @api
*/
public function GetScript(): string;
}

View File

@@ -10,10 +10,10 @@
*/
interface iBackofficeStyleExtension
{
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetStyle(): string;
}
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetStyle(): string;
}

View File

@@ -11,25 +11,25 @@
*/
interface iFieldRendererMappingsExtension
{
/**
* @return array {
* array: {
* field: string,
* form_renderer: string,
* field_renderer: string
* }
* } List of field renderer mapping: FQCN field class, FQCN Form Renderer class, FQCN Field Renderer class
*
* Example:
*
* ```php
* [
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ]
* ```
*/
public static function RegisterSupportedFields(): array;
}
/**
* @return array {
* array: {
* field: string,
* form_renderer: string,
* field_renderer: string
* }
* } List of field renderer mapping: FQCN field class, FQCN Form Renderer class, FQCN Field Renderer class
*
* Example:
*
* ```php
* [
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ]
* ```
*/
public static function RegisterSupportedFields(): array;
}

View File

@@ -21,27 +21,27 @@
*/
interface iPageUIBlockExtension
{
/**
* Add content to the "admin banner"
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetBannerBlock();
/**
* Add content to the "admin banner"
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetBannerBlock();
/**
* Add content to the header of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetHeaderBlock();
/**
* Add content to the header of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetHeaderBlock();
/**
* Add content to the footer of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetFooterBlock();
}
/**
* Add content to the footer of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetFooterBlock();
}

View File

@@ -13,100 +13,100 @@
*/
interface iPopupMenuExtension
{
/**
* Insert an item into the Actions menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
const MENU_OBJLIST_ACTIONS = 1;
/**
* Insert an item into the Toolkit menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
const MENU_OBJLIST_TOOLKIT = 2;
/**
* Insert an item into the Actions menu on an object details page
*
* $param is a DBObject instance: the object currently displayed
* @api
*/
const MENU_OBJDETAILS_ACTIONS = 3;
/**
* Insert an item into the Dashboard menu
*
* The dashboad menu is shown on the top right corner when a dashboard
* is being displayed.
*
* $param is a Dashboard instance: the dashboard currently displayed
* @api
*/
const MENU_DASHBOARD_ACTIONS = 4;
/**
* Insert an item into the User menu (upper right corner)
*
* $param is null
* @api
*/
const MENU_USER_ACTIONS = 5;
/**
* Insert an item into the Action menu on an object item in an objects list in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object on
* the current line)
* @api
*/
const PORTAL_OBJLISTITEM_ACTIONS = 7;
/**
* Insert an item into the Action menu on an object details page in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object
* currently displayed)
* @api
*/
const PORTAL_OBJDETAILS_ACTIONS = 8;
/**
* Insert an item into the Actions menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
public const MENU_OBJLIST_ACTIONS = 1;
/**
* Insert an item into the Toolkit menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
public const MENU_OBJLIST_TOOLKIT = 2;
/**
* Insert an item into the Actions menu on an object details page
*
* $param is a DBObject instance: the object currently displayed
* @api
*/
public const MENU_OBJDETAILS_ACTIONS = 3;
/**
* Insert an item into the Dashboard menu
*
* The dashboad menu is shown on the top right corner when a dashboard
* is being displayed.
*
* $param is a Dashboard instance: the dashboard currently displayed
* @api
*/
public const MENU_DASHBOARD_ACTIONS = 4;
/**
* Insert an item into the User menu (upper right corner)
*
* $param is null
* @api
*/
public const MENU_USER_ACTIONS = 5;
/**
* Insert an item into the Action menu on an object item in an objects list in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object on
* the current line)
* @api
*/
public const PORTAL_OBJLISTITEM_ACTIONS = 7;
/**
* Insert an item into the Action menu on an object details page in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object
* currently displayed)
* @api
*/
public const PORTAL_OBJDETAILS_ACTIONS = 8;
/**
* Insert an item into the Actions menu of a list in the portal
* Note: This is not implemented yet !
*
* $param is an array('portal_id' => $sPortalId, 'object_set' => $oSet) containing DBObjectSet containing the list of objects
*
* @todo
*/
const PORTAL_OBJLIST_ACTIONS = 6;
/**
* Insert an item into the user menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
const PORTAL_USER_ACTIONS = 9;
/**
* Insert an item into the navigation menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
const PORTAL_MENU_ACTIONS = 10;
/**
* Insert an item into the Actions menu of a list in the portal
* Note: This is not implemented yet !
*
* $param is an array('portal_id' => $sPortalId, 'object_set' => $oSet) containing DBObjectSet containing the list of objects
*
* @todo
*/
public const PORTAL_OBJLIST_ACTIONS = 6;
/**
* Insert an item into the user menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
public const PORTAL_USER_ACTIONS = 9;
/**
* Insert an item into the navigation menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
public const PORTAL_MENU_ACTIONS = 10;
/**
* Get the list of items to be added to a menu.
*
* This method is called by the framework for each menu.
* The items will be inserted in the menu in the order of the returned array.
*
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
* @param mixed $param Depends on $iMenuId, see the constants defined above
*
* @return object[] An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
* @api
*/
public static function EnumItems($iMenuId, $param);
}
/**
* Get the list of items to be added to a menu.
*
* This method is called by the framework for each menu.
* The items will be inserted in the menu in the order of the returned array.
*
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
* @param mixed $param Depends on $iMenuId, see the constants defined above
*
* @return object[] An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
* @api
*/
public static function EnumItems($iMenuId, $param);
}

View File

@@ -7,22 +7,22 @@
*/
interface iPreferencesExtension
{
/**
* @api
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage);
/**
* @api
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage);
/**
* @api
*
* @param string $sOperation
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
* @return bool true if the operation has been used
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation);
}
/**
* @api
*
* @param string $sOperation
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
* @return bool true if the operation has been used
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation);
}

View File

@@ -8,31 +8,31 @@
*/
interface iWelcomePopupExtension
{
// Importance for ordering messages
// Just two levels since less important messages have nothing to do in the welcome popup
public const ENUM_IMPORTANCE_CRITICAL = 0;
public const ENUM_IMPORTANCE_HIGH = 1;
public const DEFAULT_IMPORTANCE = self::ENUM_IMPORTANCE_HIGH;
// Importance for ordering messages
// Just two levels since less important messages have nothing to do in the welcome popup
public const ENUM_IMPORTANCE_CRITICAL = 0;
public const ENUM_IMPORTANCE_HIGH = 1;
public const DEFAULT_IMPORTANCE = self::ENUM_IMPORTANCE_HIGH;
/**
* Overload this method if you need to display an icon representing the provider (eg. your own company logo, module icon, ...)
*
* @return string Relative path (from app. root) of the icon representing the provider
* @api
*/
public function GetIconRelPath(): string;
/**
* Overload this method if you need to display an icon representing the provider (eg. your own company logo, module icon, ...)
*
* @return string Relative path (from app. root) of the icon representing the provider
* @api
*/
public function GetIconRelPath(): string;
/**
* @return \Combodo\iTop\Application\WelcomePopup\Message[]
* @api
*/
public function GetMessages(): array;
/**
* @return \Combodo\iTop\Application\WelcomePopup\Message[]
* @api
*/
public function GetMessages(): array;
/**
* Overload this method if the provider needs to do some additional processing after the message ($sMessageId) has been acknowledged by the current user
*
* @param string $sMessageId
* @api
*/
public function AcknowledgeMessage(string $sMessageId): void;
}
/**
* Overload this method if the provider needs to do some additional processing after the message ($sMessageId) has been acknowledged by the current user
*
* @param string $sMessageId
* @api
*/
public function AcknowledgeMessage(string $sMessageId): void;
}

View File

@@ -8,9 +8,9 @@
*/
interface iBackupExtraFilesExtension
{
/**
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
* @api
*/
public function GetExtraFilesRelPaths(): array;
}
/**
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
* @api
*/
public function GetExtraFilesRelPaths(): array;
}

View File

@@ -7,19 +7,19 @@
*/
interface iKPILoggerExtension
{
/**
* Init the statistics collected
*
* @return void
*/
public function InitStats();
/**
* Init the statistics collected
*
* @return void
*/
public function InitStats();
/**
* Add a new KPI to the stats
*
* @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData
*
* @return mixed
*/
public function LogOperation($oKpiLogData);
}
/**
* Add a new KPI to the stats
*
* @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData
*
* @return mixed
*/
public function LogOperation($oKpiLogData);
}

View File

@@ -9,8 +9,8 @@
*/
interface iModuleExtension
{
/**
* @api
*/
public function __construct();
}
/**
* @api
*/
public function __construct();
}

View File

@@ -16,144 +16,144 @@
*/
abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
{
/**
* @inheritDoc
*/
abstract public function ListSupportedLoginModes();
/**
* @inheritDoc
*/
abstract public function ListSupportedLoginModes();
/**
* @inheritDoc
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState) {
case LoginWebPage::LOGIN_STATE_START:
return $this->OnStart($iErrorCode);
/**
* @inheritDoc
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState) {
case LoginWebPage::LOGIN_STATE_START:
return $this->OnStart($iErrorCode);
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
return $this->OnModeDetection($iErrorCode);
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
return $this->OnModeDetection($iErrorCode);
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
return $this->OnReadCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
return $this->OnReadCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
return $this->OnCheckCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
return $this->OnCheckCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK:
return $this->OnCredentialsOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK:
return $this->OnCredentialsOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_USER_OK:
return $this->OnUsersOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_USER_OK:
return $this->OnUsersOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_CONNECTED:
return $this->OnConnected($iErrorCode);
case LoginWebPage::LOGIN_STATE_CONNECTED:
return $this->OnConnected($iErrorCode);
case LoginWebPage::LOGIN_STATE_ERROR:
return $this->OnError($iErrorCode);
}
case LoginWebPage::LOGIN_STATE_ERROR:
return $this->OnError($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Initialization
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnStart(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Initialization
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnStart(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Detect login mode explicitly without respecting configured order (legacy mode)
* In most case do nothing here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnModeDetection(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Detect login mode explicitly without respecting configured order (legacy mode)
* In most case do nothing here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnModeDetection(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Obtain the credentials either if login mode is empty or set to yours.
* This step can be called multiple times by the FSM:
* for example:
* 1 - display login form
* 2 - read the values posted by the user (store that in session)
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnReadCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Obtain the credentials either if login mode is empty or set to yours.
* This step can be called multiple times by the FSM:
* for example:
* 1 - display login form
* 2 - read the values posted by the user (store that in session)
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnReadCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Control the validity of the data from the session
* Automatic user provisioning can be done here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCheckCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Control the validity of the data from the session
* Automatic user provisioning can be done here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCheckCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCredentialsOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCredentialsOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnUsersOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnUsersOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnConnected(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnConnected(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnError(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnError(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
}

View File

@@ -7,11 +7,11 @@
*/
interface iLoginExtension
{
/**
* Return the list of supported login modes for this plugin
*
* @return array of supported login modes
* @api
*/
public function ListSupportedLoginModes();
}
/**
* Return the list of supported login modes for this plugin
*
* @return array of supported login modes
* @api
*/
public function ListSupportedLoginModes();
}

View File

@@ -7,18 +7,18 @@
*/
interface iLoginFSMExtension extends iLoginExtension
{
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
* if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
* if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
* if LoginWebPage::LOGIN_FSM_CONTINUE is returned then the FSM will proceed to next plugin or state
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
public function LoginAction($sLoginState, &$iErrorCode);
}
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
* if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
* if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
* if LoginWebPage::LOGIN_FSM_CONTINUE is returned then the FSM will proceed to next plugin or state
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
public function LoginAction($sLoginState, &$iErrorCode);
}

View File

@@ -9,9 +9,9 @@
*/
interface iLoginUIExtension extends iLoginExtension
{
/**
* @return LoginTwigContext
* @api
*/
public function GetTwigContext();
}
/**
* @return LoginTwigContext
* @api
*/
public function GetTwigContext();
}

View File

@@ -7,9 +7,9 @@
*/
interface iLogoutExtension extends iLoginExtension
{
/**
* Execute all actions to log out properly
* @api
*/
public function LogoutAction();
}
/**
* Execute all actions to log out properly
* @api
*/
public function LogoutAction();
}

View File

@@ -9,59 +9,59 @@
*/
abstract class AbstractPortalUIExtension implements iPortalUIExtension
{
/**
* @inheritDoc
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return array();
}
/**
* @inheritDoc
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return [];
}
/**
* @inheritDoc
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return array();
}
/**
* @inheritDoc
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return [];
}
/**
* @inheritDoc
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
}
/**
* @inheritDoc
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
}

View File

@@ -11,77 +11,77 @@
*/
interface iPortalUIExtension
{
const ENUM_PORTAL_EXT_UI_BODY = 'Body';
const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu';
const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent';
public const ENUM_PORTAL_EXT_UI_BODY = 'Body';
public const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu';
public const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent';
/**
* Returns an array of CSS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns an array of CSS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns inline (raw) CSS
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns inline (raw) CSS
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns an array of JS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns an array of JS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw JS code
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw JS code
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the <body> tag
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the <body> tag
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the #main-wrapper element
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the #main-wrapper element
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the #topbar and #sidebar elements
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
}
/**
* Returns raw HTML code to put at the end of the #topbar and #sidebar elements
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
}

View File

@@ -9,94 +9,94 @@
*/
class RestResult
{
/**
* Result: no issue has been encountered
* @api
*/
const OK = 0;
/**
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
* @api
*/
const UNAUTHORIZED = 1;
/**
* Result: the parameter 'version' is missing
* @api
*/
const MISSING_VERSION = 2;
/**
* Result: the parameter 'json_data' is missing
* @api
*/
const MISSING_JSON = 3;
/**
* Result: the input structure is not a valid JSON string
* @api
*/
const INVALID_JSON = 4;
/**
* Result: the parameter 'auth_user' is missing, authentication aborted
* @api
*/
const MISSING_AUTH_USER = 5;
/**
* Result: the parameter 'auth_pwd' is missing, authentication aborted
* @api
*/
const MISSING_AUTH_PWD = 6;
/**
* Result: no operation is available for the specified version
* @api
*/
const UNSUPPORTED_VERSION = 10;
/**
* Result: the requested operation is not valid for the specified version
* @api
*/
const UNKNOWN_OPERATION = 11;
/**
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
* @api
*/
const UNSAFE = 12;
/**
* Result: the request page number is not valid. It must be an integer greater than 0
* @api
*/
const INVALID_PAGE = 13;
/**
* Result: the operation could not be performed, see the message for troubleshooting
* @api
*/
const INTERNAL_ERROR = 100;
/**
* Result: no issue has been encountered
* @api
*/
public const OK = 0;
/**
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
* @api
*/
public const UNAUTHORIZED = 1;
/**
* Result: the parameter 'version' is missing
* @api
*/
public const MISSING_VERSION = 2;
/**
* Result: the parameter 'json_data' is missing
* @api
*/
public const MISSING_JSON = 3;
/**
* Result: the input structure is not a valid JSON string
* @api
*/
public const INVALID_JSON = 4;
/**
* Result: the parameter 'auth_user' is missing, authentication aborted
* @api
*/
public const MISSING_AUTH_USER = 5;
/**
* Result: the parameter 'auth_pwd' is missing, authentication aborted
* @api
*/
public const MISSING_AUTH_PWD = 6;
/**
* Result: no operation is available for the specified version
* @api
*/
public const UNSUPPORTED_VERSION = 10;
/**
* Result: the requested operation is not valid for the specified version
* @api
*/
public const UNKNOWN_OPERATION = 11;
/**
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
* @api
*/
public const UNSAFE = 12;
/**
* Result: the request page number is not valid. It must be an integer greater than 0
* @api
*/
public const INVALID_PAGE = 13;
/**
* Result: the operation could not be performed, see the message for troubleshooting
* @api
*/
public const INTERNAL_ERROR = 100;
/**
* Default constructor - ok!
* @api
*/
public function __construct()
{
$this->code = RestResult::OK;
}
/**
* Default constructor - ok!
* @api
*/
public function __construct()
{
$this->code = RestResult::OK;
}
/**
* Result code
* @var int
* @api
*/
public $code;
/**
* Result message
* @var string
* @api
*/
public $message;
/**
* Result code
* @var int
* @api
*/
public $code;
/**
* Result message
* @var string
* @api
*/
public $message;
/**
* Sanitize the content of this result to hide sensitive information
*/
public function SanitizeContent()
{
// The default implementation does nothing
}
}
/**
* Sanitize the content of this result to hide sensitive information
*/
public function SanitizeContent()
{
// The default implementation does nothing
}
}

View File

@@ -8,361 +8,357 @@
*/
class RestUtils
{
/**
* Registering tracking information. Any further object modification be associated with the given comment, when the modification gets
* recorded into the DB
*
* @param StdClass $oData Structured input data. Must contain 'comment'.
*
* @return void
* @throws Exception
* @api
*
*/
public static function InitTrackingComment($oData)
{
$sComment = self::GetMandatoryParam($oData, 'comment');
CMDBObject::SetTrackInfo($sComment);
}
/**
* Registering tracking information. Any further object modification be associated with the given comment, when the modification gets
* recorded into the DB
*
* @param StdClass $oData Structured input data. Must contain 'comment'.
*
* @return void
* @throws Exception
* @api
*
*/
public static function InitTrackingComment($oData)
{
$sComment = self::GetMandatoryParam($oData, 'comment');
CMDBObject::SetTrackInfo($sComment);
}
/**
* Read a mandatory parameter from from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
*
* @return mixed parameter value if present
* @throws Exception If the parameter is missing
* @api
*/
public static function GetMandatoryParam($oData, $sParamName)
{
if (isset($oData->$sParamName)) {
return $oData->$sParamName;
} else {
throw new Exception("Missing parameter '$sParamName'");
}
}
/**
* Read a mandatory parameter from from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
*
* @return mixed parameter value if present
* @throws Exception If the parameter is missing
* @api
*/
public static function GetMandatoryParam($oData, $sParamName)
{
if (isset($oData->$sParamName)) {
return $oData->$sParamName;
} else {
throw new Exception("Missing parameter '$sParamName'");
}
}
/**
* Read an optional parameter from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param mixed $default Default value if the parameter is not found in the input data
*
* @param StdClass $oData Structured input data.
*
* @return mixed
* @throws Exception
* @api
*/
public static function GetOptionalParam($oData, $sParamName, $default)
{
if (isset($oData->$sParamName)) {
return $oData->$sParamName;
} else {
return $default;
}
}
/**
* Read an optional parameter from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param mixed $default Default value if the parameter is not found in the input data
*
* @param StdClass $oData Structured input data.
*
* @return mixed
* @throws Exception
* @api
*/
public static function GetOptionalParam($oData, $sParamName, $default)
{
if (isset($oData->$sParamName)) {
return $oData->$sParamName;
} else {
return $default;
}
}
/**
* Read a class from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
*
* @return string
* @throws Exception If the parameter is missing or the class is unknown
* @api
*/
public static function GetClass($oData, $sParamName)
{
$sClass = self::GetMandatoryParam($oData, $sParamName);
if (!MetaModel::IsValidClass($sClass)) {
throw new Exception("$sParamName: '$sClass' is not a valid class'");
}
return $sClass;
}
/**
* Read a class from a Rest/Json structure.
*
* @param string $sParamName Name of the parameter to fetch from the input data
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
*
* @return string
* @throws Exception If the parameter is missing or the class is unknown
* @api
*/
public static function GetClass($oData, $sParamName)
{
$sClass = self::GetMandatoryParam($oData, $sParamName);
if (!MetaModel::IsValidClass($sClass)) {
throw new Exception("$sParamName: '$sClass' is not a valid class'");
}
/**
* Read a list of attribute codes from a Rest/Json structure.
*
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @param string $sClass Name of the class
*
* @return array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @throws Exception
* @api
*/
public static function GetFieldList($sClass, $oData, $sParamName)
{
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
$aShowFields = [];
if ($sFields == '*') {
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
$aShowFields[$sClass][] = $sAttCode;
}
} elseif ($sFields == '*+') {
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
$aShowFields[$sRefClass][] = $sAttCode;
}
}
} else {
foreach (explode(',', $sFields) as $sAttCode) {
$sAttCode = trim($sAttCode);
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
}
$aShowFields[$sClass][] = $sAttCode;
}
}
return $sClass;
}
return $aShowFields;
}
/**
* Read and interpret object search criteria from a Rest/Json structure
*
* @param string $sClass Name of the class
* @param StdClass $oCriteria Hash of attribute code => value (can be a substructure or a scalar, depending on the nature of the
* attriute)
*
* @return object The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
* @api
*/
protected static function FindObjectFromCriteria($sClass, $oCriteria)
{
$aCriteriaReport = [];
if (isset($oCriteria->finalclass)) {
if (!MetaModel::IsValidClass($oCriteria->finalclass)) {
throw new Exception("finalclass: Unknown class '".$oCriteria->finalclass."'");
}
if (!MetaModel::IsParentClass($sClass, $oCriteria->finalclass)) {
throw new Exception("finalclass: '".$oCriteria->finalclass."' is not a child class of '$sClass'");
}
$sClass = $oCriteria->finalclass;
}
$oSearch = new DBObjectSearch($sClass);
foreach ($oCriteria as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '=');
if (is_object($value) || is_array($value)) {
$value = json_encode($value);
}
$aCriteriaReport[] = "$sAttCode: $value ($realValue)";
}
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0) {
throw new Exception("No item found with criteria: ".implode(', ', $aCriteriaReport));
} elseif ($iCount > 1) {
throw new Exception("Several items found ($iCount) with criteria: ".implode(', ', $aCriteriaReport));
}
$res = $oSet->Fetch();
/**
* Read a list of attribute codes from a Rest/Json structure.
*
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @param string $sClass Name of the class
*
* @return array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @throws Exception
* @api
*/
public static function GetFieldList($sClass, $oData, $sParamName)
{
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
$aShowFields = array();
if ($sFields == '*') {
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
$aShowFields[$sClass][] = $sAttCode;
}
} elseif ($sFields == '*+') {
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
$aShowFields[$sRefClass][] = $sAttCode;
}
}
} else {
foreach (explode(',', $sFields) as $sAttCode) {
$sAttCode = trim($sAttCode);
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
}
$aShowFields[$sClass][] = $sAttCode;
}
}
return $res;
}
return $aShowFields;
}
/**
* Find an object from a polymorph search specification (Rest/Json)
*
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then
* @param string $sClass Name of the class
*
* @return DBObject The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
*
* @api
* @see DBObject::CheckChangedExtKeysValues() generic method to check that we can access the linked object isn't used in that use case because values can be literal, OQL, friendlyname
*/
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
{
if (is_object($key)) {
$res = static::FindObjectFromCriteria($sClass, $key);
} elseif (is_numeric($key)) {
if ($bAllowNullValue && ($key == 0)) {
$res = null;
} else {
$res = MetaModel::GetObject($sClass, $key, false);
if (is_null($res)) {
throw new Exception("Invalid object $sClass::$key");
}
}
} elseif (is_string($key)) {
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0) {
throw new Exception("No item found for query: $key");
} elseif ($iCount > 1) {
throw new Exception("Several items found ($iCount) for query: $key");
}
$res = $oSet->Fetch();
} else {
throw new Exception("Wrong format for key");
}
/**
* Read and interpret object search criteria from a Rest/Json structure
*
* @param string $sClass Name of the class
* @param StdClass $oCriteria Hash of attribute code => value (can be a substructure or a scalar, depending on the nature of the
* attriute)
*
* @return object The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
* @api
*/
protected static function FindObjectFromCriteria($sClass, $oCriteria)
{
$aCriteriaReport = array();
if (isset($oCriteria->finalclass)) {
if (!MetaModel::IsValidClass($oCriteria->finalclass)) {
throw new Exception("finalclass: Unknown class '" . $oCriteria->finalclass . "'");
}
if (!MetaModel::IsParentClass($sClass, $oCriteria->finalclass)) {
throw new Exception("finalclass: '" . $oCriteria->finalclass . "' is not a child class of '$sClass'");
}
$sClass = $oCriteria->finalclass;
}
$oSearch = new DBObjectSearch($sClass);
foreach ($oCriteria as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '=');
if (is_object($value) || is_array($value)) {
$value = json_encode($value);
}
$aCriteriaReport[] = "$sAttCode: $value ($realValue)";
}
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0) {
throw new Exception("No item found with criteria: " . implode(', ', $aCriteriaReport));
} elseif ($iCount > 1) {
throw new Exception("Several items found ($iCount) with criteria: " . implode(', ', $aCriteriaReport));
}
$res = $oSet->Fetch();
return $res;
}
return $res;
}
/**
* Search objects from a polymorph search specification (Rest/Json)
*
* @param string $sClass Name of the class
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @param int $iLimit The limit of results to return
* @param int $iOffset The offset of results to return
*
* @return DBObjectSet The search result set
* @throws Exception If the input structure is not valid
* @api
*/
public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0)
{
if (is_object($key)) {
if (isset($key->finalclass)) {
$sClass = $key->finalclass;
if (!MetaModel::IsValidClass($sClass)) {
throw new Exception("finalclass: Unknown class '$sClass'");
}
}
$oSearch = new DBObjectSearch($sClass);
foreach ($key as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '=');
}
} elseif (is_numeric($key)) {
$oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('id', $key);
} elseif (is_string($key)) {
// OQL
try {
$oSearch = DBObjectSearch::FromOQL($key);
} catch (Exception $e) {
throw new CoreOqlException('Query failed to execute', [
'query' => $key,
'exception_class' => get_class($e),
'exception_message' => $e->getMessage(),
]);
}
} else {
throw new Exception("Wrong format for key");
}
$oObjectSet = new DBObjectSet($oSearch, [], [], null, $iLimit, $iOffset);
/**
* Find an object from a polymorph search specification (Rest/Json)
*
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then
* @param string $sClass Name of the class
*
* @return DBObject The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
*
* @api
* @see DBObject::CheckChangedExtKeysValues() generic method to check that we can access the linked object isn't used in that use case because values can be literal, OQL, friendlyname
*/
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
{
if (is_object($key)) {
$res = static::FindObjectFromCriteria($sClass, $key);
} elseif (is_numeric($key)) {
if ($bAllowNullValue && ($key == 0)) {
$res = null;
} else {
$res = MetaModel::GetObject($sClass, $key, false);
if (is_null($res)) {
throw new Exception("Invalid object $sClass::$key");
}
}
} elseif (is_string($key)) {
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0) {
throw new Exception("No item found for query: $key");
} elseif ($iCount > 1) {
throw new Exception("Several items found ($iCount) for query: $key");
}
$res = $oSet->Fetch();
} else {
throw new Exception("Wrong format for key");
}
return $oObjectSet;
}
return $res;
}
/**
* Interpret the Rest/Json value and get a valid attribute value
*
* @param string $sAttCode Attribute code
* @param mixed $value Depending on the type of attribute (a scalar, or search criteria, or list of related objects...)
* @param string $sClass Name of the class
*
* @return mixed The value that can be used with DBObject::Set()
* @throws Exception If the specification of the value is not valid.
* @api
*/
public static function MakeValue($sClass, $sAttCode, $value)
{
try {
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
throw new Exception("Unknown attribute");
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey) {
$oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
} elseif ($oAttDef instanceof AttributeLinkedSet) {
if (!is_array($value)) {
throw new Exception("A link set must be defined by an array of objects");
}
$sLnkClass = $oAttDef->GetLinkedClass();
$aLinks = [];
foreach ($value as $oValues) {
$oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
// Fix for N°1939
if (($oAttDef instanceof AttributeLinkedSetIndirect) && ($oLnk->Get($oAttDef->GetExtKeyToRemote()) == 0)) {
continue;
}
$aLinks[] = $oLnk;
}
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
} elseif ($oAttDef instanceof AttributeTagSet) {
if (!is_array($value)) {
throw new Exception("A tag set must be defined by an array of tag codes");
}
$value = $oAttDef->FromJSONToValue($value);
} else {
$value = $oAttDef->FromJSONToValue($value);
}
} catch (Exception $e) {
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
}
/**
* Search objects from a polymorph search specification (Rest/Json)
*
* @param string $sClass Name of the class
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @param int $iLimit The limit of results to return
* @param int $iOffset The offset of results to return
*
* @return DBObjectSet The search result set
* @throws Exception If the input structure is not valid
* @api
*/
public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0)
{
if (is_object($key)) {
if (isset($key->finalclass)) {
$sClass = $key->finalclass;
if (!MetaModel::IsValidClass($sClass)) {
throw new Exception("finalclass: Unknown class '$sClass'");
}
}
return $value;
}
$oSearch = new DBObjectSearch($sClass);
foreach ($key as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '=');
}
} elseif (is_numeric($key)) {
$oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('id', $key);
} elseif (is_string($key)) {
// OQL
try {
$oSearch = DBObjectSearch::FromOQL($key);
} catch (Exception $e) {
throw new CoreOqlException('Query failed to execute', [
'query' => $key,
'exception_class' => get_class($e),
'exception_message' => $e->getMessage(),
]);
}
} else {
throw new Exception("Wrong format for key");
}
$oObjectSet = new DBObjectSet($oSearch, array(), array(), null, $iLimit, $iOffset);
/**
* Interpret a Rest/Json structure that defines attribute values, and build an object
*
* @param array $aFields A hash of attribute code => value specification.
* @param string $sClass Name of the class
*
* @return DBObject The newly created object
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function MakeObjectFromFields($sClass, $aFields)
{
$oObject = MetaModel::NewObject($sClass);
foreach ($aFields as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
try {
$oObject->Set($sAttCode, $realValue);
} catch (Exception $e) {
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
}
}
return $oObjectSet;
}
return $oObject;
}
/**
* Interpret the Rest/Json value and get a valid attribute value
*
* @param string $sAttCode Attribute code
* @param mixed $value Depending on the type of attribute (a scalar, or search criteria, or list of related objects...)
* @param string $sClass Name of the class
*
* @return mixed The value that can be used with DBObject::Set()
* @throws Exception If the specification of the value is not valid.
* @api
*/
public static function MakeValue($sClass, $sAttCode, $value)
{
try {
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
throw new Exception("Unknown attribute");
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey) {
$oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
} elseif ($oAttDef instanceof AttributeLinkedSet) {
if (!is_array($value)) {
throw new Exception("A link set must be defined by an array of objects");
}
$sLnkClass = $oAttDef->GetLinkedClass();
$aLinks = array();
foreach ($value as $oValues) {
$oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
// Fix for N°1939
if (($oAttDef instanceof AttributeLinkedSetIndirect) && ($oLnk->Get($oAttDef->GetExtKeyToRemote()) == 0)) {
continue;
}
$aLinks[] = $oLnk;
}
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
} elseif ($oAttDef instanceof AttributeTagSet) {
if (!is_array($value)) {
throw new Exception("A tag set must be defined by an array of tag codes");
}
$value = $oAttDef->FromJSONToValue($value);
} else {
$value = $oAttDef->FromJSONToValue($value);
}
} catch (Exception $e) {
throw new Exception("$sAttCode: " . $e->getMessage(), $e->getCode());
}
/**
* Interpret a Rest/Json structure that defines attribute values, and update the given object
*
* @param array $aFields A hash of attribute code => value specification.
* @param DBObject $oObject The object being modified
*
* @return DBObject The object modified
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function UpdateObjectFromFields($oObject, $aFields)
{
$sClass = get_class($oObject);
foreach ($aFields as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
try {
$oObject->Set($sAttCode, $realValue);
} catch (Exception $e) {
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
}
}
return $value;
}
/**
* Interpret a Rest/Json structure that defines attribute values, and build an object
*
* @param array $aFields A hash of attribute code => value specification.
* @param string $sClass Name of the class
*
* @return DBObject The newly created object
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function MakeObjectFromFields($sClass, $aFields)
{
$oObject = MetaModel::NewObject($sClass);
foreach ($aFields as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
try {
$oObject->Set($sAttCode, $realValue);
} catch (Exception $e) {
throw new Exception("$sAttCode: " . $e->getMessage(), $e->getCode());
}
}
return $oObject;
}
/**
* Interpret a Rest/Json structure that defines attribute values, and update the given object
*
* @param array $aFields A hash of attribute code => value specification.
* @param DBObject $oObject The object being modified
*
* @return DBObject The object modified
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function UpdateObjectFromFields($oObject, $aFields)
{
$sClass = get_class($oObject);
foreach ($aFields as $sAttCode => $value) {
$realValue = static::MakeValue($sClass, $sAttCode, $value);
try {
$oObject->Set($sAttCode, $realValue);
} catch (Exception $e) {
throw new Exception("$sAttCode: " . $e->getMessage(), $e->getCode());
}
}
return $oObject;
}
}
return $oObject;
}
}

View File

@@ -8,5 +8,5 @@
*/
interface iRestInputSanitizer
{
public function SanitizeJsonInput(string $sJsonInput): string;
}
public function SanitizeJsonInput(string $sJsonInput): string;
}

View File

@@ -9,25 +9,25 @@
*/
interface iRestServiceProvider
{
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
*
* @return array An array of hash 'verb' => verb, 'description' => description
* @api
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
*
* @return array An array of hash 'verb' => verb, 'description' => description
* @api
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param array $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @api
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param array $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @api
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}

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
@@ -53,7 +54,7 @@ abstract class Dashboard
$this->sLayoutClass = 'DashboardLayoutOneCol';
$this->bAutoReload = false;
$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
$this->aCells = array();
$this->aCells = [];
$this->oDOMNode = null;
$this->sId = $sId;
}
@@ -65,8 +66,8 @@ abstract class Dashboard
*/
public function FromXml($sXml)
{
$this->aCells = array(); // reset the content of the dashboard
set_error_handler(array('Dashboard', 'ErrorHandler'));
$this->aCells = []; // reset the content of the dashboard
set_error_handler(['Dashboard', 'ErrorHandler']);
$oDoc = new DOMDocument();
$oDoc->loadXML($sXml);
restore_error_handler();
@@ -79,87 +80,69 @@ abstract class Dashboard
public function FromDOMDocument(DOMDocument $oDoc)
{
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0))
{
if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0)) {
$this->sLayoutClass = $oLayoutNode->textContent;
}
else
{
} else {
$this->sLayoutClass = 'DashboardLayoutOneCol';
}
if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0))
{
if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0)) {
$this->sTitle = $oTitleNode->textContent;
}
else
{
} else {
$this->sTitle = '';
}
$this->bAutoReload = false;
$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0))
{
if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0))
{
if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0)) {
if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0)) {
$this->bAutoReload = ($oAutoReloadEnabled->textContent == 'true');
}
if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0))
{
if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0)) {
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$oAutoReloadInterval->textContent);
}
}
if ($oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0))
{
if ($oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0)) {
$oCellsList = $oCellsNode->getElementsByTagName('cell');
$aCellOrder = array();
$aCellOrder = [];
$iCellRank = 0;
/** @var \DOMElement $oCellNode */
foreach($oCellsList as $oCellNode)
{
foreach ($oCellsList as $oCellNode) {
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
if ($oCellRank)
{
if ($oCellRank) {
$iCellRank = (float)$oCellRank->textContent;
}
$oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0);
{
$oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
$iRank = 0;
$aDashletOrder = array();
$aDashletOrder = [];
/** @var \DOMElement $oDomNode */
foreach($oDashletList as $oDomNode)
{
foreach ($oDashletList as $oDomNode) {
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
if ($oRank)
{
if ($oRank) {
$iRank = (float)$oRank->textContent;
}
$oNewDashlet = $this->InitDashletFromDOMNode($oDomNode);
$aDashletOrder[] = array('rank' => $iRank, 'dashlet' => $oNewDashlet);
$aDashletOrder[] = ['rank' => $iRank, 'dashlet' => $oNewDashlet];
}
usort($aDashletOrder, array(get_class($this), 'SortOnRank'));
$aDashletList = array();
foreach($aDashletOrder as $aItem)
{
usort($aDashletOrder, [get_class($this), 'SortOnRank']);
$aDashletList = [];
foreach ($aDashletOrder as $aItem) {
$aDashletList[] = $aItem['dashlet'];
}
$aCellOrder[] = array('rank' => $iCellRank, 'dashlets' => $aDashletList);
$aCellOrder[] = ['rank' => $iCellRank, 'dashlets' => $aDashletList];
}
}
usort($aCellOrder, array(get_class($this), 'SortOnRank'));
foreach($aCellOrder as $aItem)
{
usort($aCellOrder, [get_class($this), 'SortOnRank']);
foreach ($aCellOrder as $aItem) {
$this->aCells[] = $aItem['dashlets'];
}
}
else
{
$this->aCells = array();
} else {
$this->aCells = [];
}
}
@@ -169,20 +152,20 @@ abstract class Dashboard
* @return mixed
*/
protected function InitDashletFromDOMNode($oDomNode)
{
$sId = $oDomNode->getAttribute('id');
{
$sId = $oDomNode->getAttribute('id');
$sDashletType = $oDomNode->getAttribute('xsi:type');
$sDashletType = $oDomNode->getAttribute('xsi:type');
// Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
$sClass = static::GetDashletClassFromType($sDashletType);
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet->SetDashletType($sDashletType);
$oNewDashlet->FromDOMNode($oDomNode);
// Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
$sClass = static::GetDashletClassFromType($sDashletType);
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet->SetDashletType($sDashletType);
$oNewDashlet->FromDOMNode($oDomNode);
return $oNewDashlet;
}
return $oNewDashlet;
}
/**
* @param array $aItem1
@@ -208,12 +191,9 @@ abstract class Dashboard
*/
public static function ErrorHandler($errno, $errstr, $errfile, $errline)
{
if ($errno == E_WARNING && (substr_count($errstr,"DOMDocument::loadXML()")>0))
{
if ($errno == E_WARNING && (substr_count($errstr, "DOMDocument::loadXML()") > 0)) {
throw new DOMException($errstr);
}
else
{
} else {
return false;
}
}
@@ -231,7 +211,7 @@ abstract class Dashboard
$oMainNode = $oDoc->createElement('dashboard');
$oMainNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
$oDoc->appendChild($oMainNode);
$this->ToDOMNode($oMainNode);
$sXml = $oDoc->saveXML();
@@ -261,23 +241,21 @@ abstract class Dashboard
$oCellsNode = $oDoc->createElement('cells');
$oDefinition->appendChild($oCellsNode);
$iCellRank = 0;
foreach ($this->aCells as $aCell)
{
foreach ($this->aCells as $aCell) {
$oCellNode = $oDoc->createElement('cell');
$oCellNode->setAttribute('id', $iCellRank);
$oCellsNode->appendChild($oCellNode);
$oCellRank = $oDoc->createElement('rank', $iCellRank);
$oCellNode->appendChild($oCellRank);
$iCellRank++;
$iDashletRank = 0;
$oDashletsNode = $oDoc->createElement('dashlets');
$oCellNode->appendChild($oDashletsNode);
/** @var \Dashlet $oDashlet */
foreach ($aCell as $oDashlet)
{
foreach ($aCell as $oDashlet) {
$oNode = $oDoc->createElement('dashlet');
$oDashletsNode->appendChild($oNode);
$oNode->setAttribute('id', $oDashlet->GetID());
@@ -296,16 +274,16 @@ abstract class Dashboard
public function FromParams($aParams)
{
$this->sLayoutClass = $aParams['layout_class'];
if (!is_subclass_of($this->sLayoutClass,DashboardLayout::class)) {
if (!is_subclass_of($this->sLayoutClass, DashboardLayout::class)) {
throw new InvalidParameterException('Invalid parameter layout_class "'.$aParams['layout_class'].'"');
}
$this->sTitle = $aParams['title'];
$this->bAutoReload = $aParams['auto_reload'] == 'true';
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']);
foreach($aParams['cells'] as $aCell) {
$aCellDashlets = array();
foreach($aCell as $aDashletParams) {
foreach ($aParams['cells'] as $aCell) {
$aCellDashlets = [];
foreach ($aCell as $aDashletParams) {
$sDashletClass = $aDashletParams['dashlet_class'];
$sId = $aDashletParams['dashlet_id'];
/** @var \Dashlet $oNewDashlet */
@@ -322,12 +300,12 @@ abstract class Dashboard
}
$this->aCells[] = $aCellDashlets;
}
}
public function Save()
{
}
/**
@@ -420,7 +398,7 @@ abstract class Dashboard
{
$sId = $this->GetNewDashletId();
$oDashlet->SetId($sId);
$this->aCells[] = array($oDashlet);
$this->aCells[] = [$oDashlet];
}
/**
@@ -430,7 +408,7 @@ abstract class Dashboard
* @throws \ReflectionException
* @throws \Exception
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function RenderProperties($oPage, $aExtraParams = [])
{
// menu to pick a layout and edit other properties of the dashboard
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashboard-editor--properties"><div class="ui-widget-header ui-corner-all ibo-dashboard-editor--properties-title">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
@@ -442,7 +420,7 @@ abstract class Dashboard
if (is_subclass_of($sLayoutClass, 'DashboardLayout')) {
$oReflection = new ReflectionClass($sLayoutClass);
if (!$oReflection->isAbstract()) {
$aCallSpec = array($sLayoutClass, 'GetInfo');
$aCallSpec = [$sLayoutClass, 'GetInfo'];
$aInfo = call_user_func($aCallSpec);
$sChecked = ($this->sLayoutClass == $sLayoutClass) ? 'checked' : '';
$oPage->add('<input type="radio" name="layout_class" '.$sChecked.' value="'.$sLayoutClass.'" id="layout_'.$sLayoutClass.'"><label for="layout_'.$sLayoutClass.'"><img src="'.$sUrl.$aInfo['icon'].'" class="ibo-dashboard--properties--icon" data-role="ibo-dashboard--properties--icon"/></label>'); // title="" on either the img or the label does nothing !
@@ -466,7 +444,6 @@ abstract class Dashboard
$oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit
$oForm->AddField($oField);
$this->SetFormParams($oForm, $aExtraParams);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
@@ -474,7 +451,7 @@ abstract class Dashboard
$sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval')));
$oPage->add_ready_script(
<<<EOF
<<<EOF
// Note: the title gets deleted by the validation mechanism
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
@@ -522,7 +499,7 @@ EOF
*
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
{
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
@@ -551,7 +528,8 @@ EOF
$oToolbar->AddHtml($sHtml);
} else {
$oPage->add_script(<<<JS
$oPage->add_script(
<<<JS
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML").attr("title", $('<div>').html("$sTitleForHTML").text());
JS
);
@@ -595,7 +573,7 @@ JS
* @param WebPage $oPage
* @param array $aExtraParams
*/
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = [])
{
// Toolbox/palette to edit the properties of each dashlet
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashlet--properties"><div class="ui-widget-header ui-corner-all ibo-dashlet--properties--title">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
@@ -604,13 +582,10 @@ JS
$oLayout = new $this->sLayoutClass();
$oPage->add('<div id="dashlet_properties">');
foreach($this->aCells as $iCellIdx => $aCell)
{
foreach ($this->aCells as $iCellIdx => $aCell) {
/** @var \Dashlet $oDashlet */
foreach($aCell as $oDashlet)
{
if ($oDashlet->IsVisible())
{
foreach ($aCell as $oDashlet) {
if ($oDashlet->IsVisible()) {
$oPage->add('<div class="dashlet_properties" id="dashlet_properties_'.$oDashlet->GetID().'" style="display:none">');
$oForm = $oDashlet->GetForm();
$this->SetFormParams($oForm, $aExtraParams);
@@ -632,18 +607,17 @@ JS
*/
protected function GetAvailableDashlets()
{
$aDashlets = array();
$aDashlets = [];
foreach( get_declared_classes() as $sDashletClass)
{
foreach (get_declared_classes() as $sDashletClass) {
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instantiated.
if (is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, array('DashletUnknown', 'DashletProxy'))) {
if (is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, ['DashletUnknown', 'DashletProxy'])) {
$oReflection = new ReflectionClass($sDashletClass);
if (!$oReflection->isAbstract()) {
$aCallSpec = array($sDashletClass, 'IsVisible');
$aCallSpec = [$sDashletClass, 'IsVisible'];
$bVisible = call_user_func($aCallSpec);
if ($bVisible) {
$aCallSpec = array($sDashletClass, 'GetInfo');
$aCallSpec = [$sDashletClass, 'GetInfo'];
$aInfo = call_user_func($aCallSpec);
$aDashlets[$sDashletClass] = $aInfo;
}
@@ -660,11 +634,9 @@ JS
protected function GetNewDashletId()
{
$iNewId = 0;
foreach($this->aCells as $aDashlets)
{
foreach ($this->aCells as $aDashlets) {
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
foreach ($aDashlets as $oDashlet) {
$iNewId = max($iNewId, (int)$oDashlet->GetID());
}
}
@@ -681,15 +653,15 @@ JS
*
* @return void
*/
abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = array());
abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = []);
/**
* @param \DesignerForm $oForm
* @param array $aExtraParams
*
* @return mixed
*/
abstract protected function SetFormParams($oForm, $aExtraParams = array());
/**
* @param \DesignerForm $oForm
* @param array $aExtraParams
*
* @return mixed
*/
abstract protected function SetFormParams($oForm, $aExtraParams = []);
/**
* @param string $sType
@@ -699,8 +671,7 @@ JS
*/
public static function GetDashletClassFromType($sType, $oFactory = null)
{
if (is_subclass_of($sType, 'Dashlet'))
{
if (is_subclass_of($sType, 'Dashlet')) {
return $sType;
}
return 'DashletUnknown';
@@ -723,14 +694,12 @@ JS
*/
public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletOrigId)
{
if(strpos($sDashletOrigId, '_ID_row') !== false)
{
if (strpos($sDashletOrigId, '_ID_row') !== false) {
return $sDashletOrigId;
}
$sDashletId = $sDashboardDivId."_ID_row".$iRow."_col".$iCol."_".$sDashletOrigId;
if ($bIsCustomized)
{
if ($bIsCustomized) {
$sDashletId = 'CUSTOM_'.$sDashletId;
}
@@ -782,9 +751,9 @@ class RuntimeDashboard extends Dashboard
* @inheritDoc
* @throws \Exception
*/
protected function SetFormParams($oForm, $aExtraParams = array())
protected function SetFormParams($oForm, $aExtraParams = [])
{
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property', 'extra_params' => $aExtraParams));
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', ['operation' => 'update_dashlet_property', 'extra_params' => $aExtraParams]);
}
/**
@@ -800,14 +769,11 @@ class RuntimeDashboard extends Dashboard
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
$bIsNew = false;
if ($oUDSet->Count() > 0)
{
if ($oUDSet->Count() > 0) {
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
$oUserDashboard->Set('contents', $sXml);
}
else
{
} else {
// No such customized dashboard for the current user, let's create a new record
$oUserDashboard = new UserDashboard();
$oUserDashboard->Set('user_id', UserRights::GetUserId());
@@ -838,8 +804,7 @@ class RuntimeDashboard extends Dashboard
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0)
{
if ($oUDSet->Count() > 0) {
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
utils::PushArchiveMode(false);
@@ -883,14 +848,11 @@ class RuntimeDashboard extends Dashboard
} else {
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
}
}
else
{
} else {
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
}
if ($sDashboardDefinition !== false)
{
if ($sDashboardDefinition !== false) {
$oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized);
@@ -937,7 +899,6 @@ class RuntimeDashboard extends Dashboard
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
}
if ($sDashboardDefinition !== false) {
$oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition);
@@ -954,11 +915,11 @@ class RuntimeDashboard extends Dashboard
* @inheritDoc
* @throws \Exception
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
{
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class'])) {
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
$aRenderParams = ['query_params' => $oObj->ToArgsForQuery()];
} else {
$aRenderParams = $aExtraParams;
}
@@ -968,7 +929,7 @@ class RuntimeDashboard extends Dashboard
if (isset($aExtraParams['query_params']['this->object()'])) {
/** @var \DBObject $oObj */
$oObj = $aExtraParams['query_params']['this->object()'];
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
$aAjaxParams = ['this->class' => get_class($oObj), 'this->id' => $oObj->GetKey()];
if (isset($aExtraParams['from_dashboard_page'])) {
$aAjaxParams['from_dashboard_page'] = $aExtraParams['from_dashboard_page'];
}
@@ -1001,9 +962,7 @@ class RuntimeDashboard extends Dashboard
}
JS
);
}
else
{
} else {
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
@@ -1032,7 +991,7 @@ EOF
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = array())
protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = [])
{
if (!$this->HasCustomDashboard()) {
return;
@@ -1092,8 +1051,7 @@ JS
*/
protected function HasCustomDashboard()
{
try
{
try {
// Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
@@ -1101,9 +1059,7 @@ JS
$oUDSet = new DBObjectSet($oUDSearch);
return ($oUDSet->Count() > 0);
}
catch (Exception $e)
{
} catch (Exception $e) {
return false;
}
}
@@ -1139,21 +1095,23 @@ JS
->AddCSSClass('ibo-action-button');
$oToolbar->AddSubBlock($oActionButton);
$aActions = array();
$aActions = [];
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
$sJSExtraParams = json_encode($aExtraParams);
if ($this->HasCustomDashboard()) {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:DeleteCustom'),
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
$oRevert = new JSPopupMenuItem(
'UI:Dashboard:RevertConfirm',
Dict::S('UI:Dashboard:DeleteCustom'),
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false"
);
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
} else {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
}
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
$oActionsMenu = $oPage->GetPopoverMenu($sPopoverMenuId, $aActions)
@@ -1193,12 +1151,12 @@ EOF
/**
* @inheritDoc
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function RenderProperties($oPage, $aExtraParams = [])
{
parent::RenderProperties($oPage, $aExtraParams);
$oPage->add_ready_script(
<<<EOF
<<<EOF
$('#select_layout input').on('click', function() {
var sLayoutClass = $(this).val();
$('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass});
@@ -1225,7 +1183,6 @@ EOF
);
}
/**
* @param WebPage $oPage
*
@@ -1236,11 +1193,11 @@ EOF
* @throws \ReflectionException
* @throws \Exception
*/
public function RenderEditor($oPage, $aExtraParams = array())
public function RenderEditor($oPage, $aExtraParams = [])
{
if (isset($aExtraParams['this->class'])) {
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
$aRenderParams = ['query_params' => $oObj->ToArgsForQuery()];
} else {
$aRenderParams = $aExtraParams;
}
@@ -1262,7 +1219,7 @@ EOF
$sDialogTitle = Dict::S('UI:DashboardEdit:Title');
$sOkButtonLabel = Dict::S('UI:Button:Save');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$sId = json_encode($this->sId);
$sLayoutClass = json_encode($this->sLayoutClass);
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
@@ -1275,9 +1232,9 @@ EOF
$sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage'));
$sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage'));
$sAutoApplyConfirmationMessage = addslashes(Dict::S('UI:AutoApplyConfirmationMessage'));
$oPage->add_ready_script(
<<<JS
<<<JS
window.bLeavingOnUserAction = false;
$('#dashboard_editor').dialog({
@@ -1385,104 +1342,89 @@ JS
$sContextMenuId = $oAppContext->GetCurrentValue('menu', null);
$oForm = new DesignerForm();
// Get the list of all 'dashboard' menus in which we can insert a dashlet
$aAllMenus = ApplicationMenu::ReflectionMenuNodes();
$sRootMenuId = ApplicationMenu::GetRootMenuId($sContextMenuId);
$aAllowedDashboards = array();
$aAllowedDashboards = [];
$sDefaultDashboard = null;
// Store the parent menus for acces check
$aParentMenus = array();
foreach($aAllMenus as $idx => $aMenu)
{
/** @var MenuNode $oMenu */
$oMenu = $aMenu['node'];
if (count(ApplicationMenu::GetChildren($oMenu->GetIndex())) > 0)
{
$aParentMenus[$oMenu->GetMenuId()] = $aMenu;
}
}
foreach($aAllMenus as $idx => $aMenu)
{
$aParentMenus = [];
foreach ($aAllMenus as $idx => $aMenu) {
/** @var MenuNode $oMenu */
$oMenu = $aMenu['node'];
if ($oMenu instanceof DashboardMenuNode)
{
// Get the root parent for access check
$sParentId = $aMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
while (isset($aParentMenus[$aParentMenu['parent']]))
{
// grand parent exists
$sParentId = $aParentMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
}
/** @var \MenuNode $oParentMenu */
$oParentMenu = $aParentMenu['node'];
if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled())
{
$sMenuLabel = $oMenu->GetTitle();
$sParentLabel = Dict::S('Menu:'.$sParentId);
if ($sParentLabel != $sMenuLabel)
{
$aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
}
else
{
$aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
}
if (empty($sDefaultDashboard) && ($sRootMenuId == ApplicationMenu::GetRootMenuId($oMenu->GetMenuId())))
{
$sDefaultDashboard = $oMenu->GetMenuId();
}
}
}
if (count(ApplicationMenu::GetChildren($oMenu->GetIndex())) > 0) {
$aParentMenus[$oMenu->GetMenuId()] = $aMenu;
}
}
asort($aAllowedDashboards);
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard);
$oField->SetAllowedValues($aAllowedDashboards);
$oField->SetMandatory(true);
$oForm->AddField($oField);
// Get the list of possible dashlets that support a creation from
// an OQL
$aDashlets = array();
foreach(get_declared_classes() as $sDashletClass)
{
if (is_subclass_of($sDashletClass, 'Dashlet'))
{
$oReflection = new ReflectionClass($sDashletClass);
if (!$oReflection->isAbstract())
{
$aCallSpec = array($sDashletClass, 'CanCreateFromOQL');
$bShorcutMode = call_user_func($aCallSpec);
if ($bShorcutMode)
{
$aCallSpec = array($sDashletClass, 'GetInfo');
$aInfo = call_user_func($aCallSpec);
$aDashlets[$sDashletClass] = array('label' => $aInfo['label'], 'class' => $sDashletClass, 'icon' => $aInfo['icon']);
foreach ($aAllMenus as $idx => $aMenu) {
$oMenu = $aMenu['node'];
if ($oMenu instanceof DashboardMenuNode) {
// Get the root parent for access check
$sParentId = $aMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
while (isset($aParentMenus[$aParentMenu['parent']])) {
// grand parent exists
$sParentId = $aParentMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
}
/** @var \MenuNode $oParentMenu */
$oParentMenu = $aParentMenu['node'];
if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled()) {
$sMenuLabel = $oMenu->GetTitle();
$sParentLabel = Dict::S('Menu:'.$sParentId);
if ($sParentLabel != $sMenuLabel) {
$aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
} else {
$aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
}
if (empty($sDefaultDashboard) && ($sRootMenuId == ApplicationMenu::GetRootMenuId($oMenu->GetMenuId()))) {
$sDefaultDashboard = $oMenu->GetMenuId();
}
}
}
}
asort($aAllowedDashboards);
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard);
$oField->SetAllowedValues($aAllowedDashboards);
$oField->SetMandatory(true);
$oForm->AddField($oField);
// Get the list of possible dashlets that support a creation from
// an OQL
$aDashlets = [];
foreach (get_declared_classes() as $sDashletClass) {
if (is_subclass_of($sDashletClass, 'Dashlet')) {
$oReflection = new ReflectionClass($sDashletClass);
if (!$oReflection->isAbstract()) {
$aCallSpec = [$sDashletClass, 'CanCreateFromOQL'];
$bShorcutMode = call_user_func($aCallSpec);
if ($bShorcutMode) {
$aCallSpec = [$sDashletClass, 'GetInfo'];
$aInfo = call_user_func($aCallSpec);
$aDashlets[$sDashletClass] = ['label' => $aInfo['label'], 'class' => $sDashletClass, 'icon' => $aInfo['icon']];
}
}
}
}
$oSelectorField = new DesignerFormSelectorField('dashlet_class', Dict::S('UI:DashletCreation:DashletType'), '');
$oForm->AddField($oSelectorField);
foreach($aDashlets as $sDashletClass => $aDashletInfo)
{
foreach ($aDashlets as $sDashletClass => $aDashletInfo) {
$oSubForm = new DesignerForm();
$oMetaModel = new ModelReflectionRuntime();
/** @var \Dashlet $oDashlet */
$oDashlet = new $sDashletClass($oMetaModel, 0);
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
$oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']);
}
$oField = new DesignerBooleanField('open_editor', Dict::S('UI:DashletCreation:EditNow'), true);
$oForm->AddField($oField);
return $oForm;
}
@@ -1501,11 +1443,11 @@ JS
$oForm->Render($oPage);
$oPage->add('</div>');
$sDialogTitle = Dict::S('UI:DashletCreation:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oPage->add_ready_script(
<<<JS
$('#dashlet_creation_dlg').dialog({
@@ -1603,7 +1545,7 @@ JS
/**
* @inheritDoc
*/
protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = array())
protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = [])
{
$sDashletIdOrig = $oDashlet->GetID();
$sDashboardSanitizedId = $this->GetSanitizedId();
@@ -1630,31 +1572,27 @@ JS
private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams)
{
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
if (!$bIsDashletWithListPref)
{
if (!$bIsDashletWithListPref) {
return;
}
/** @var \DashletObjectList $oDashlet */
$bDashletIdInNewFormat = ($sDashletIdOrig === $oDashlet->GetID());
if ($bDashletIdInNewFormat)
{
if ($bDashletIdInNewFormat) {
return;
}
$sNewPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $oDashlet->GetID());
$sPrefValueForNewKey = appUserPreferences::GetPref($sNewPrefKey, null);
$bHasPrefInNewFormat = ($sPrefValueForNewKey !== null);
if ($bHasPrefInNewFormat)
{
if ($bHasPrefInNewFormat) {
return;
}
$sOldPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $sDashletIdOrig);
$sPrefValueForOldKey = appUserPreferences::GetPref($sOldPrefKey, null);
$bHasPrefInOldFormat = ($sPrefValueForOldKey !== null);
if (!$bHasPrefInOldFormat)
{
if (!$bHasPrefInOldFormat) {
return;
}
@@ -1673,7 +1611,7 @@ JS
private function GetDashletObjectListAppUserPreferencesPrefix(DashletObjectList $oDashlet, $aExtraParams, $sDashletId)
{
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
$aClassAliases = array();
$aClassAliases = [];
try {
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
$aClassAliases = $oFilter->GetSelectedClasses();

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -104,7 +105,7 @@ class DisplayBlock
*/
public const ENUM_STYLE_CHART_AJAX = 'chart_ajax';
const TAG_BLOCK = 'itopblock';
public const TAG_BLOCK = 'itopblock';
/** @var \DBSearch */
protected $m_oFilter;
protected $m_aConditions; // Conditions added to the filter -> avoid duplicate conditions
@@ -137,20 +138,18 @@ class DisplayBlock
*
* @throws \ApplicationException
*/
public function __construct(DBSearch $oFilter, $sStyle = self::ENUM_STYLE_LIST, $bAsynchronous = false, $aParams = array(), $oSet = null)
public function __construct(DBSearch $oFilter, $sStyle = self::ENUM_STYLE_LIST, $bAsynchronous = false, $aParams = [], $oSet = null)
{
$this->m_oFilter = $oFilter->DeepClone();
$this->m_aConditions = array();
$this->m_aConditions = [];
$this->m_sStyle = $sStyle;
$this->m_bAsynchronous = $bAsynchronous;
$this->m_aParams = $aParams;
$this->m_oSet = $oSet;
if (array_key_exists('show_obsolete_data', $aParams))
{
if (array_key_exists('show_obsolete_data', $aParams)) {
$this->m_bShowObsoleteData = $aParams['show_obsolete_data'];
}
if ($this->m_bShowObsoleteData === null)
{
if ($this->m_bShowObsoleteData === null) {
// User defined
$this->m_bShowObsoleteData = utils::ShowObsoleteData();
}
@@ -412,22 +411,18 @@ class DisplayBlock
* @throws \CoreException
* @throws \Exception
*/
public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = array())
public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = [])
{
$oDummyFilter = new DBObjectSearch($oSet->GetClass());
$aKeys = array();
$oSet->OptimizeColumnLoad(array($oSet->GetClassAlias() => array())); // No need to load all the columns just to get the id
while($oObject = $oSet->Fetch())
{
$aKeys = [];
$oSet->OptimizeColumnLoad([$oSet->GetClassAlias() => []]); // No need to load all the columns just to get the id
while ($oObject = $oSet->Fetch()) {
$aKeys[] = $oObject->GetKey();
}
$oSet->Rewind();
if (count($aKeys) > 0)
{
if (count($aKeys) > 0) {
$oDummyFilter->AddCondition('id', $aKeys, 'IN');
}
else
{
} else {
$oDummyFilter->AddCondition('id', 0, '=');
}
$oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams); // DisplayBlocks built this way are synchronous
@@ -448,7 +443,7 @@ class DisplayBlock
$iStartPos = stripos($sTemplate, '<'.self::TAG_BLOCK.' ', 0);
$iEndPos = stripos($sTemplate, '</'.self::TAG_BLOCK.'>', $iStartPos);
$iEndTag = stripos($sTemplate, '>', $iStartPos);
$aParams = array();
$aParams = [];
if (($iStartPos === false) || ($iEndPos === false)) {
return null;
@@ -456,7 +451,7 @@ class DisplayBlock
$sITopData = substr($sTemplate, 1 + $iEndTag, $iEndPos - $iEndTag - 1);
$sITopTag = substr($sTemplate, $iStartPos + strlen('<'.self::TAG_BLOCK), $iEndTag - $iStartPos - strlen('<'.self::TAG_BLOCK));
$aMatches = array();
$aMatches = [];
$sBlockClass = "DisplayBlock";
$bAsynchronous = false;
$sBlockType = 'list';
@@ -522,25 +517,28 @@ class DisplayBlock
return new $sBlockClass($oFilter, $sBlockType, $bAsynchronous, $aParams);
}
public function DisplayIntoContentBlock(UIContentBlock $oContentBlock, WebPage $oPage, $sId, $aExtraParams = array())
public function DisplayIntoContentBlock(UIContentBlock $oContentBlock, WebPage $oPage, $sId, $aExtraParams = [])
{
$oContentBlock->AddSubBlock($this->GetDisplay($oPage, $sId, $aExtraParams));
}
public function Display(WebPage $oPage, $sId, $aExtraParams = array())
public function Display(WebPage $oPage, $sId, $aExtraParams = [])
{
$oPage->AddUiBlock($this->GetDisplay($oPage, $sId, $aExtraParams));
}
public function GetDisplay(WebPage $oPage, $sId, $aExtraParams = array()): UIContentBlock
public function GetDisplay(WebPage $oPage, $sId, $aExtraParams = []): UIContentBlock
{
$oHtml = new UIContentBlock($sId);
$oHtml->AddCSSClass("display_block");
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
$aExtraParams['currentId'] = $sId;
$sExtraParams = addslashes(str_replace('"', "'",
json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
$sExtraParams = addslashes(str_replace(
'"',
"'",
json_encode($aExtraParams)
)); // JSON encode, change the style of the quotes and escape them
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
@@ -549,9 +547,9 @@ class DisplayBlock
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
$aQueryParams = ['this->object()' => $oObj];
} else {
$aQueryParams = array();
$aQueryParams = [];
}
}
@@ -587,8 +585,7 @@ class DisplayBlock
');
}
if ($this->m_sStyle == static::ENUM_STYLE_LIST) // Search form need to extract result list extra data, the simplest way is to expose this configuration
{
if ($this->m_sStyle == static::ENUM_STYLE_LIST) { // Search form need to extract result list extra data, the simplest way is to expose this configuration
$listJsonExtraParams = json_encode(json_encode($aExtraParams));
$oPage->add_ready_script("
$('#$sId').data('sExtraParams', ".$listJsonExtraParams.");
@@ -608,7 +605,7 @@ class DisplayBlock
* @throws \DictExceptionMissingString
* @throws \MySQLException
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
if (!isset($aExtraParams['currentId'])) {
$sId = utils::GetUniqueId(); // Works only if the page is not an Ajax one !
@@ -640,7 +637,7 @@ class DisplayBlock
$this->CheckParams($this->m_sStyle, $aExtraParams);
// Add the extra params into the filter if they make sense for such a filter
$bDoSearch = utils::ReadParam('dosearch', false);
$aQueryParams = array();
$aQueryParams = [];
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
} else {
@@ -648,7 +645,7 @@ class DisplayBlock
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
$aQueryParams = ['this->object()' => $oObj];
}
}
if ($this->m_oSet == null) {
@@ -658,7 +655,7 @@ class DisplayBlock
$oAppContext = new ApplicationContext();
$sClass = $this->m_oFilter->GetClass();
$aFilterCodes = MetaModel::GetFiltersList($sClass);
$aCallSpec = array($sClass, 'MapContextParam');
$aCallSpec = [$sClass, 'MapContextParam'];
if (is_callable($aCallSpec)) {
foreach ($oAppContext->GetNames() as $sContextParam) {
$sParamCode = call_user_func($aCallSpec, $sContextParam); //Map context parameter to the value/filter code depending on the class
@@ -693,11 +690,9 @@ class DisplayBlock
}
}
if (!is_null($condition))
{
if (!is_null($condition)) {
$sOpCode = null; // default operator
if (is_array($condition))
{
if (is_array($condition)) {
// Multiple values, add them as AND X IN (v1, v2, v3...)
$sOpCode = 'IN';
}
@@ -705,26 +700,22 @@ class DisplayBlock
$this->AddCondition($sFilterCode, $condition, $sOpCode, $bParseSearchString);
}
}
if ($bDoSearch)
{
if ($bDoSearch) {
// Keep the table_id identifying this table if we're performing a search
$sTableId = utils::ReadParam('_table_id_', null, false, utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
if ($sTableId != null)
{
if ($sTableId != null) {
$aExtraParams['table_id'] = $sTableId;
}
}
}
$aOrderBy = array();
if (isset($aExtraParams['order_by']))
{
$aOrderBy = [];
if (isset($aExtraParams['order_by'])) {
// Convert the string describing the order_by parameter into an array
// The syntax is +attCode1,-attCode2
// attCode1 => ascending, attCode2 => descending
$aTemp = explode(',', $aExtraParams['order_by']);
foreach($aTemp as $sTemp)
{
$aMatches = array();
foreach ($aTemp as $sTemp) {
$aMatches = [];
if (preg_match('/^([+-])?(.+)$/', $sTemp, $aMatches)) {
$bAscending = true;
if ($aMatches[1] == '-') {
@@ -740,7 +731,7 @@ class DisplayBlock
}
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
switch($this->m_sStyle) {
switch ($this->m_sStyle) {
case static::ENUM_STYLE_LIST_SEARCH:
case static::ENUM_STYLE_LIST:
break;
@@ -770,7 +761,7 @@ class DisplayBlock
case static::ENUM_STYLE_LIST:
case static::ENUM_STYLE_LIST_IN_OBJECT:
$oBlock = $this->RenderList($aExtraParams, $oPage);
break;
break;
case static::ENUM_STYLE_ACTIONS:
$oBlock = $this->RenderActions($aExtraParams);
@@ -797,47 +788,39 @@ class DisplayBlock
break;
default:
// Unsupported style, do nothing.
$sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
// Unsupported style, do nothing.
$sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
}
$bAutoReload = false;
if (isset($aExtraParams['auto_reload']))
{
if ($aExtraParams['auto_reload'] === true)
{
if (isset($aExtraParams['auto_reload'])) {
if ($aExtraParams['auto_reload'] === true) {
// Note: does not work in the switch (case true) because a positive number evaluates to true!!!
$aExtraParams['auto_reload'] = 'standard';
}
switch($aExtraParams['auto_reload'])
{
switch ($aExtraParams['auto_reload']) {
case 'fast':
$bAutoReload = true;
$iReloadInterval = MetaModel::GetConfig()->GetFastReloadInterval()*1000;
$iReloadInterval = MetaModel::GetConfig()->GetFastReloadInterval() * 1000;
break;
case 'standard':
case 'true':
$bAutoReload = true;
$iReloadInterval = MetaModel::GetConfig()->GetStandardReloadInterval()*1000;
$iReloadInterval = MetaModel::GetConfig()->GetStandardReloadInterval() * 1000;
break;
default:
if (is_numeric($aExtraParams['auto_reload']) && ($aExtraParams['auto_reload'] > 0))
{
if (is_numeric($aExtraParams['auto_reload']) && ($aExtraParams['auto_reload'] > 0)) {
$bAutoReload = true;
$iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload'])*1000;
}
else
{
$iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload']) * 1000;
} else {
// incorrect config, ignore it
$bAutoReload = false;
}
}
}
if (($bAutoReload) && ($this->m_sStyle != static::ENUM_STYLE_SEARCH)) // Search form do NOT auto-reload
{
if (($bAutoReload) && ($this->m_sStyle != static::ENUM_STYLE_SEARCH)) { // Search form do NOT auto-reload
// Used either for asynchronous or auto_reload
// does a json_encode twice to get a string usable as function parameter
$sFilterBefore = $this->m_oFilter->serialize();
@@ -884,8 +867,7 @@ JS
{
// Workaround to an issue revealed whenever a condition on org_id is applied twice (with a hierarchy of organizations)
// Moreover, it keeps the query as simple as possible
if (isset($this->m_aConditions[$sFilterCode]) && $condition == $this->m_aConditions[$sFilterCode])
{
if (isset($this->m_aConditions[$sFilterCode]) && $condition == $this->m_aConditions[$sFilterCode]) {
// Skip
return;
}
@@ -895,53 +877,42 @@ JS
$bConditionAdded = false;
// If the condition is an external key with a class having a hierarchy, use a "below" criteria
if (MetaModel::IsValidAttCode($sClass, $sFilterCode))
{
if (MetaModel::IsValidAttCode($sClass, $sFilterCode)) {
$oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
if ($oAttDef->IsExternalKey())
{
if ($oAttDef->IsExternalKey()) {
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
if ($sHierarchicalKeyCode !== false)
{
if ($sHierarchicalKeyCode !== false) {
$oFilter = new DBObjectSearch($oAttDef->GetTargetClass());
if (($sOpCode == 'IN') && is_array($condition))
{
if (($sOpCode == 'IN') && is_array($condition)) {
$oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
}
else
{
} else {
$oFilter->AddCondition('id', $condition);
}
$oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
$this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode);
$bConditionAdded = true;
}
else if (($sOpCode == 'IN') && is_array($condition))
{
} elseif (($sOpCode == 'IN') && is_array($condition)) {
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true;
}
}
else if (($sOpCode == 'IN') && is_array($condition))
{
} elseif (($sOpCode == 'IN') && is_array($condition)) {
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true;
}
}
// In all other cases, just add the condition directly
if (!$bConditionAdded)
{
if (!$bConditionAdded) {
$this->m_oFilter->AddCondition($sFilterCode, $condition, null); // Use the default 'loose' operator
}
}
static protected function GetConditionIN($oFilter, $sFilterCode, $condition)
protected static function GetConditionIN($oFilter, $sFilterCode, $condition)
{
$oField = new FieldExpression($sFilterCode, $oFilter->GetClassAlias());
$oField = new FieldExpression($sFilterCode, $oFilter->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($condition)).')';
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
@@ -972,13 +943,10 @@ JS
protected function MakeGroupByQuery(&$aExtraParams, &$oGroupByExp, &$sGroupByLabel, &$aGroupBy, &$sAggregationFunction, &$sFctVar, &$sAggregationAttr, &$sSql)
{
$sAlias = $this->m_oFilter->GetClassAlias();
if (isset($aExtraParams['group_by_label']))
{
if (isset($aExtraParams['group_by_label'])) {
$oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
$sGroupByLabel = $aExtraParams['group_by_label'];
}
else
{
} else {
// Backward compatibility: group_by is simply a field id
$oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
$sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
@@ -986,61 +954,52 @@ JS
// Security filtering
$aFields = $oGroupByExp->ListRequiredFields();
foreach($aFields as $sFieldAlias)
{
$aMatches = array();
if (preg_match('/^([^.]+)\\.([^.]+)$/', $sFieldAlias, $aMatches))
{
foreach ($aFields as $sFieldAlias) {
$aMatches = [];
if (preg_match('/^([^.]+)\\.([^.]+)$/', $sFieldAlias, $aMatches)) {
$sFieldClass = $this->m_oFilter->GetClassName($aMatches[1]);
$oAttDef = MetaModel::GetAttributeDef($sFieldClass, $aMatches[2]);
if ($oAttDef instanceof AttributeOneWayPassword)
{
if ($oAttDef instanceof AttributeOneWayPassword) {
throw new Exception('Grouping on password fields is not supported.');
}
}
}
$aGroupBy = array();
$aGroupBy = [];
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$aQueryParams = array();
if (isset($aExtraParams['query_params']))
{
$aQueryParams = [];
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
}
$aFunctions = array();
$aFunctions = [];
$sAggregationFunction = 'count';
$sFctVar = '_itop_count_';
$sAggregationAttr = '';
if (isset($aExtraParams['aggregation_function']) && !empty($aExtraParams['aggregation_attribute']))
{
if (isset($aExtraParams['aggregation_function']) && !empty($aExtraParams['aggregation_attribute'])) {
$sAggregationFunction = $aExtraParams['aggregation_function'];
$sAggregationAttr = $aExtraParams['aggregation_attribute'];
$oAttrExpr = Expression::FromOQL('`'.$sAlias.'`.`'.$sAggregationAttr.'`');
$oFctExpr = new FunctionExpression(strtoupper($sAggregationFunction), array($oAttrExpr));
$oFctExpr = new FunctionExpression(strtoupper($sAggregationFunction), [$oAttrExpr]);
$sFctVar = '_itop_'.$sAggregationFunction.'_';
$aFunctions = array($sFctVar => $oFctExpr);
$aFunctions = [$sFctVar => $oFctExpr];
}
if (!empty($sAggregationAttr))
{
if (!empty($sAggregationAttr)) {
$sClass = $this->m_oFilter->GetClass();
$sAggregationAttr = MetaModel::GetLabel($sClass, $sAggregationAttr);
}
$iLimit = 0;
if (isset($aExtraParams['limit']))
{
if (isset($aExtraParams['limit'])) {
$iLimit = intval($aExtraParams['limit']);
}
$aOrderBy = array();
if (isset($aExtraParams['order_direction']) && isset($aExtraParams['order_by']))
{
switch ($aExtraParams['order_by'])
{
$aOrderBy = [];
if (isset($aExtraParams['order_direction']) && isset($aExtraParams['order_by'])) {
switch ($aExtraParams['order_by']) {
case 'attribute':
$aOrderBy = array('grouped_by_1' => ($aExtraParams['order_direction'] === 'asc'));
$aOrderBy = ['grouped_by_1' => ($aExtraParams['order_direction'] === 'asc')];
break;
case 'function':
$aOrderBy = array($sFctVar => ($aExtraParams['order_direction'] === 'asc'));
$aOrderBy = [$sFctVar => ($aExtraParams['order_direction'] === 'asc')];
break;
}
}
@@ -1076,31 +1035,31 @@ JS
$this->AddCondition($sFilterCode, $sContextParamValue);
}
}
$aQueryParams = array();
$aQueryParams = [];
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
}
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, [], $aQueryParams);
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
}
// Summary details
$aCounts = array();
$aStateLabels = array();
$aCounts = [];
$aStateLabels = [];
if (!empty($sStateAttrCode) && !empty($sStatesList)) {
$aStates = explode(',', $sStatesList);
// Generate one count + group by query [#1330]
$sClassAlias = $this->m_oFilter->GetClassAlias();
$oGroupByExpr = Expression::FromOQL($sClassAlias.'.'.$sStateAttrCode);
$aGroupBy = array('group1' => $oGroupByExpr);
$aGroupBy = ['group1' => $oGroupByExpr];
$oGroupBySearch = $this->m_oFilter->DeepClone();
if (isset($this->m_bShowObsoleteData)) {
$oGroupBySearch->SetShowObsoleteData($this->m_bShowObsoleteData);
}
$sCountGroupByQuery = $oGroupBySearch->MakeGroupByQuery($aQueryParams, $aGroupBy, false);
$aCountGroupByResults = CMDBSource::QueryToArray($sCountGroupByQuery);
$aCountsQueryResults = array();
$aCountsQueryResults = [];
foreach ($aCountGroupByResults as $aCountGroupBySingleResult) {
$aCountsQueryResults[$aCountGroupBySingleResult[0]] = $aCountGroupBySingleResult[1];
}
@@ -1114,7 +1073,8 @@ JS
: 0;
if ($aCounts[$sStateValue] == 0) {
$aCounts[$sStateValue] = ['link' => '-', 'label' => $aCounts[$sStateValue]];;
$aCounts[$sStateValue] = ['link' => '-', 'label' => $aCounts[$sStateValue]];
;
} else {
$oSingleGroupByValueFilter = $this->m_oFilter->DeepClone();
$oSingleGroupByValueFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
@@ -1164,7 +1124,7 @@ JS
$oBlock->AddSubBlock($oPill);
}
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
if(isset($aExtraParams['query_params']['this->object()'])){
if (isset($aExtraParams['query_params']['this->object()'])) {
$aExtraParams['query_params']['this->class'] = get_class($aExtraParams['query_params']['this->object()']);
$aExtraParams['query_params']['this->id'] = $aExtraParams['query_params']['this->object()']->GetKey();
unset($aExtraParams['query_params']['this->object()']);
@@ -1178,7 +1138,8 @@ JS
$('#".$oBlock->GetId()."').html(data);
$('#".$oBlock->GetId()."').unblock();
});
$('#".$oBlock->GetId()."').unblock();");
$('#".$oBlock->GetId()."').unblock();"
);
return $oBlock;
}
@@ -1188,7 +1149,7 @@ JS
*
* @return string[]
*/
protected function GetAllowedActionsParams(array $aExtraParams)
protected function GetAllowedActionsParams(array $aExtraParams)
{
return [
'context_filter', /** int if != 0 filter with user context */
@@ -1220,11 +1181,11 @@ JS
$this->AddCondition($sFilterCode, $sContextParamValue);
}
}
$aQueryParams = array();
$aQueryParams = [];
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
}
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, [], $aQueryParams);
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
}
$iCount = $this->m_oSet->Count();
@@ -1241,8 +1202,15 @@ JS
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
$sCreateActionUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class='.$sClass.$oAppContext->GetForLink(true);
$sCreateActionLabel = Dict::Format('UI:Button:Create');
$oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, $sCreateActionUrl,
$sCreateActionLabel, $aRefreshParams);
$oBlock = DashletFactory::MakeForDashletBadge(
$sClassIconUrl,
$sHyperlink,
$iCount,
$sClassLabel,
$sCreateActionUrl,
$sCreateActionLabel,
$aRefreshParams
);
} else {
$oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, null, null, $aRefreshParams);
}
@@ -1272,9 +1240,9 @@ JS
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();
$aLabels = array();
$aValues = array();
$aGroupBy = [];
$aLabels = [];
$aValues = [];
$iTotalCount = 0;
foreach ($aRes as $iRow => $aRow) {
$sValue = $aRow['grouped_by_1'];
@@ -1285,7 +1253,7 @@ JS
$iTotalCount += $aRow['_itop_count_'];
}
$aData = array();
$aData = [];
$oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink(true);
foreach ($aGroupBy as $iRow => $iCount) {
@@ -1296,22 +1264,22 @@ JS
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
} else {
$aQueryParams = array();
$aQueryParams = [];
}
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
$aData[] = array(
$aData[] = [
'group' => $aLabels[$iRow],
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1$sParams&filter=$sFilter\">$iCount</a>"
); // TO DO: add the context information
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1$sParams&filter=$sFilter\">$iCount</a>",
]; // TO DO: add the context information
}
$aAttribs = array(
'group' => array('label' => $sGroupByLabel, 'description' => ''),
'value' => array(
$aAttribs = [
'group' => ['label' => $sGroupByLabel, 'description' => ''],
'value' => [
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
),
);
],
];
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
@@ -1322,7 +1290,7 @@ JS
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
$oBlock->AddSubTitleBlock(new Html($sTitle));
$oBlock->AddCSSClass('ibo-datatable-panel');
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
if (isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0) {
$oBlock->SetIcon($aExtraParams["panel_icon"]);
}
$oDataTable = DataTableUIBlockFactory::MakeForStaticData("", $aAttribs, $aData, null, $aExtraParams, $this->m_oFilter->ToOQL(), $aOption);
@@ -1341,7 +1309,7 @@ JS
}
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
if (isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0) {
$oBlock->SetIcon($aExtraParams["panel_icon"]);
}
$oBlock->AddSubBlock(new Html('<p>'.Dict::Format($sFormat, $iCount).'</p>'));
@@ -1351,7 +1319,7 @@ JS
}
return $oBlock;
}
}
/**
* @param WebPage $oPage
@@ -1409,7 +1377,6 @@ JS
$oBlock->aExtraParams = $aExtraParams;
$oBlock->sFilter = $this->m_oFilter->ToOQL();
// Check the classes that can be read (i.e authorized) by this user...
foreach ($aClasses as $sAlias => $sClassName) {
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) {
@@ -1431,7 +1398,7 @@ JS
$sSearchFilter = $this->m_oSet->GetFilter()->serialize();
// Limit the size of the URL (N°1585 - request uri too long)
if (strlen($sSearchFilter) < SERVER_MAX_URL_LENGTH) {
$oBlock->sEventAttachedData = json_encode(array(
$oBlock->sEventAttachedData = json_encode([
'filter' => $sSearchFilter,
'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(),
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
@@ -1439,7 +1406,7 @@ JS
'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(),
'breadcrumb_icon' => 'fas fa-search',
'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES,
));
]);
}
}
@@ -1472,25 +1439,25 @@ JS
$oContentBlock = new UIContentBlock();
$oHtml = new Html();
$oContentBlock->AddSubBlock($oHtml);
$aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']) : array();
$aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']) : [];
if (!isset($aExtraParams['group_by'])) {
$oHtml->AddHtml('<p>'.Dict::S('UI:Error:MandatoryTemplateParameter_group_by').'</p>');
} else {
$aGroupByFields = array();
$aGroupByFields = [];
$aGroupBy = explode(',', $aExtraParams['group_by']);
foreach ($aGroupBy as $sGroupBy) {
$aMatches = array();
$aMatches = [];
if (preg_match('/^(.+)\.(.+)$/', $sGroupBy, $aMatches) > 0) {
$aGroupByFields[] = array('alias' => $aMatches[1], 'att_code' => $aMatches[2]);
$aGroupByFields[] = ['alias' => $aMatches[1], 'att_code' => $aMatches[2]];
}
}
if (count($aGroupByFields) == 0) {
$oHtml->AddHtml('<p>'.Dict::Format('UI:Error:InvalidGroupByFields', $aExtraParams['group_by']).'</p>');
} else {
$aResults = array();
$aCriteria = array();
$aResults = [];
$aCriteria = [];
while ($aObjects = $this->m_oSet->FetchAssoc()) {
$aKeys = array();
$aKeys = [];
foreach ($aGroupByFields as $aField) {
$sAlias = $aField['alias'];
if (is_null($aObjects[$sAlias])) {
@@ -1507,7 +1474,7 @@ JS
$oHtml->AddHtml("<table>\n");
// Construct a new (parametric) query that will return the content of this block
$oBlockFilter = $this->m_oFilter->DeepClone();
$aExpressions = array();
$aExpressions = [];
$index = 0;
foreach ($aGroupByFields as $aField) {
$aExpressions[] = '`'.$aField['alias'].'`.`'.$aField['att_code'].'` = :param'.$index++;
@@ -1519,7 +1486,7 @@ JS
foreach ($aResults as $sCategory => $aObjects) {
$oHtml->AddHtml("<tr><td><h1>$sCategory</h1></td></tr>\n");
if (count($aDisplayAliases) == 1) {
$aSimpleArray = array();
$aSimpleArray = [];
foreach ($aObjects as $aRow) {
$oObj = $aRow[$aDisplayAliases[0]];
if (!is_null($oObj)) {
@@ -1535,12 +1502,12 @@ JS
$oHtml->AddHtml("</td></tr>\n");
} else {
$index = 0;
$aArgs = array();
$aArgs = [];
foreach ($aGroupByFields as $aField) {
$aArgs['param'.$index] = $aCriteria[$sCategory][$aField['alias'].'.'.$aField['att_code']];
$index++;
}
$oSet = new CMDBObjectSet($oBlockFilter, array(), $aArgs);
$oSet = new CMDBObjectSet($oBlockFilter, [], $aArgs);
if (empty($aExtraParams['currentId'])) {
$iListId = utils::GetUniqueId(); // Works only if not in an Ajax page !!
} else {
@@ -1603,7 +1570,7 @@ JS
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
if (isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0) {
$oPanel->SetIcon($aExtraParams["panel_icon"]);
}
$oPanel->AddSubBlock($oBlock);
@@ -1627,7 +1594,7 @@ JS
{
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$sId = utils::ReadParam('id', '');
$aValues = array();
$aValues = [];
$oBlock = null;
$sJSURLs = '';
@@ -1638,21 +1605,18 @@ JS
$this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql);
$aRes = CMDBSource::QueryToArray($sSql);
$iTotalCount = 0;
$aURLs = array();
$aURLs = [];
foreach ($aRes as $iRow => $aRow) {
$sValue = $aRow['grouped_by_1'];
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
$iTotalCount += $aRow['_itop_count_'];
$aValues[] = array(
$aValues[] = [
'label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'),
'label_html' => $sHtmlValue,
'value' => (float)$aRow[$sFctVar],
);
];
// Build the search for this subset
$oSubsetSearch = $this->m_oFilter->DeepClone();
@@ -1691,7 +1655,7 @@ JS
$aColumns = [];
$aNames = [];
foreach ($aValues as $idx => $aValue) {
$aColumns[] = array('series_'.$idx, (float)$aValue['value']);
$aColumns[] = ['series_'.$idx, (float)$aValue['value']];
$aNames['series_'.$idx] = $aValue['label'];
}
@@ -1713,7 +1677,7 @@ JS
}
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
if (isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0) {
$oPanel->SetIcon($aExtraParams["panel_icon"]);
}
$oPanel->AddSubBlock($oBlock);
@@ -1740,12 +1704,12 @@ JS
$oBlock->sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($oBlock->sCsvFile);
$oBlock->sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search'.$oAppContext->GetForLink(true).'&filter='.rawurlencode($this->m_oFilter->serialize()).'&format=csv';
// Pass the parameters via POST, since expression may be very long
$aParamsToPost = array(
$aParamsToPost = [
'expression' => $this->m_oFilter->ToOQL(true),
'format' => 'csv',
'filename' => $oBlock->sCsvFile,
'charset' => 'UTF-8',
);
];
if ($oBlock->bAdvancedMode) {
$oBlock->sDownloadLink .= '&fields_advanced=1';
$aParamsToPost['fields_advanced'] = 1;
@@ -1804,8 +1768,7 @@ class MenuBlock extends DisplayBlock
$oRouter = Router::GetInstance();
$oRenderBlock = new UIContentBlock();
if ($this->m_sStyle == 'popup') // popup is a synonym of 'list' for backward compatibility
{
if ($this->m_sStyle == 'popup') { // popup is a synonym of 'list' for backward compatibility
$this->m_sStyle = static::ENUM_STYLE_LIST;
}
@@ -1813,7 +1776,7 @@ class MenuBlock extends DisplayBlock
$aSelectedClasses = $this->GetFilter()->GetSelectedClasses();
$bIsForLinkset = isset($aExtraParams['target_attr']);
$oSet = new CMDBObjectSet($this->GetFilter());
if(isset($aExtraParams['object_count'])){
if (isset($aExtraParams['object_count'])) {
$iSetCount = $aExtraParams['object_count'];
} else {
$iSetCount = $oSet->Count();
@@ -1844,7 +1807,6 @@ class MenuBlock extends DisplayBlock
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true);
$sFilter = $this->GetFilter()->serialize();
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass);
$sRootUrl = utils::GetAbsoluteUrlAppRoot();
@@ -1902,7 +1864,7 @@ class MenuBlock extends DisplayBlock
$iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
if (
($iSetCount > 0) && (false === $bLocked) && MetaModel::HasLifecycle($sClass) &&
( ($iLimit == 0) || ($iSetCount < $iLimit) )
(($iLimit == 0) || ($iSetCount < $iLimit))
) {
$aTransitions = [];
// Processing (optimizations) and endpoints are not exactly the same depending on if there is only 1 object or a set
@@ -1922,8 +1884,8 @@ class MenuBlock extends DisplayBlock
// Life cycle actions may be available... if all objects are in the same state
// Group by <state>
$oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias());
$aGroupBy = array('__state__' => $oGroupByExp);
$aQueryParams = array();
$aGroupBy = ['__state__' => $oGroupByExp];
$aQueryParams = [];
if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params'];
}
@@ -1955,10 +1917,10 @@ class MenuBlock extends DisplayBlock
switch ($iActionAllowed) {
case UR_ALLOWED_YES:
case UR_ALLOWED_DEPENDS:
$aTransitionActions[$sStimulusCode] = array(
$aTransitionActions[$sStimulusCode] = [
'label' => $aStimuli[$sStimulusCode]->GetLabel(),
'url' => "{$sRootUrl}pages/UI.php?stimulus=$sStimulusCode&class=$sLifecycleClass&{$sUrlQueryString}",
) + $aActionParams;
] + $aActionParams;
break;
default:
@@ -2020,16 +1982,16 @@ class MenuBlock extends DisplayBlock
// Just one object in the set, possible actions are "new / clone / modify and delete"
if (!isset($aExtraParams['link_attr'])) {
if ($bIsModifyAllowed) {
$aRegularActions['UI:Menu:Modify'] = array(
$aRegularActions['UI:Menu:Modify'] = [
'label' => Dict::S('UI:Menu:Modify'),
'url' => $oRouter->GenerateUrl('object.modify', ['class' => $sClass, 'id' => $id]) . "{$sContext}#",
) + $aActionParams;
'url' => $oRouter->GenerateUrl('object.modify', ['class' => $sClass, 'id' => $id])."{$sContext}#",
] + $aActionParams;
}
if ($bIsDeleteAllowed) {
$aRegularActions['UI:Menu:Delete'] = array(
$aRegularActions['UI:Menu:Delete'] = [
'label' => Dict::S('UI:Menu:Delete'),
'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$id{$sContext}",
) + $aActionParams;
] + $aActionParams;
}
// Relations...
@@ -2038,16 +2000,16 @@ class MenuBlock extends DisplayBlock
$this->AddMenuSeparator($aRegularActions);
foreach ($aRelations as $sRelationCode => $aRelationInfo) {
if (array_key_exists('down', $aRelationInfo)) {
$aRegularActions[$sRelationCode.'_down'] = array(
$aRegularActions[$sRelationCode.'_down'] = [
'label' => $aRelationInfo['down'],
'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}",
) + $aActionParams;
] + $aActionParams;
}
if (array_key_exists('up', $aRelationInfo)) {
$aRegularActions[$sRelationCode.'_up'] = array(
$aRegularActions[$sRelationCode.'_up'] = [
'label' => $aRelationInfo['up'],
'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}",
) + $aActionParams;
] + $aActionParams;
}
}
}
@@ -2059,7 +2021,7 @@ class MenuBlock extends DisplayBlock
$bCanKill = false;
$oUser = UserRights::GetUserObject();
$aUserProfiles = array();
$aUserProfiles = [];
if (!is_null($oUser)) {
$oProfileSet = $oUser->Get('profile_list');
while ($oProfile = $oProfileSet->Fetch()) {
@@ -2081,10 +2043,10 @@ class MenuBlock extends DisplayBlock
if ($bCanKill) {
$this->AddMenuSeparator($aRegularActions);
$aRegularActions['concurrent_lock_unlock'] = array(
$aRegularActions['concurrent_lock_unlock'] = [
'label' => Dict::S('UI:Menu:KillConcurrentLock'),
'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}",
);
];
}
}
}
@@ -2092,7 +2054,7 @@ class MenuBlock extends DisplayBlock
$this->AddMenuSeparator($aRegularActions);
$this->GetEnumAllowedActions($oSet, function ($sLabel, $data) use (&$aRegularActions, $aActionParams) {
$aRegularActions[$sLabel] = array('label' => $sLabel, 'url' => $data) + $aActionParams;
$aRegularActions[$sLabel] = ['label' => $sLabel, 'url' => $data] + $aActionParams;
});
}
break;
@@ -2299,7 +2261,7 @@ class MenuBlock extends DisplayBlock
$sTarget = isset($aAction['target']) ? $aAction['target'] : '';
if (!empty($aAction['onclick'])) {
$oActionButton = ButtonUIBlockFactory::MakeIconAction($sIconClass, $aAction['label'], $aAction['label'], $sLabel,false); //utils::Sanitize($sActionId.md5($aAction['onclick']), '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER))
$oActionButton = ButtonUIBlockFactory::MakeIconAction($sIconClass, $aAction['label'], $aAction['label'], $sLabel, false); //utils::Sanitize($sActionId.md5($aAction['onclick']), '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER))
$oActionButton->SetOnClickJsCode($aAction['onclick']);
} else {
$oActionButton = ButtonUIBlockFactory::MakeLinkNeutral($sUrl, $sLabel, $sIconClass, $sTarget, utils::Sanitize($sActionId, '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER));
@@ -2458,13 +2420,11 @@ class MenuBlock extends DisplayBlock
protected function AddMenuSeparator(&$aActions)
{
$sSeparator = '<hr class="menu-separator"/>';
if (count($aActions) > 0) // Make sure that the separator is not the first item in the menu
{
if (count($aActions) > 0) { // Make sure that the separator is not the first item in the menu
$aKeys = array_keys($aActions);
$sLastKey = array_pop($aKeys);
if ($aActions[$sLastKey]['label'] != $sSeparator) // Make sure there are no 2 consecutive separators
{
$aActions['sep_'.(count($aActions)-1)] = array('label' => $sSeparator, 'url' => '');
if ($aActions[$sLastKey]['label'] != $sSeparator) { // Make sure there are no 2 consecutive separators
$aActions['sep_'.(count($aActions) - 1)] = ['label' => $sSeparator, 'url' => ''];
}
}
}
@@ -2524,10 +2484,10 @@ class MenuBlock extends DisplayBlock
*/
protected function AddBulkDeleteObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:BulkDelete', $sActionLabel = 'UI:Menu:BulkDelete')
{
$aActions[$sActionIdentifier] = array(
$aActions[$sActionIdentifier] = [
'label' => Dict::S($sActionLabel),
'url' => $this->PrepareUrlForStandardMenuAction($sClass, "operation=select_for_deletion&filter=".urlencode($sFilter)),
) + $this->GetDefaultParamsForMenuAction();
] + $this->GetDefaultParamsForMenuAction();
}
/**
@@ -2564,6 +2524,6 @@ class MenuBlock extends DisplayBlock
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true);
return $sUrl . $sContext;
return $sUrl.$sContext;
}
}

View File

@@ -19,73 +19,67 @@ class ExcelExporter
protected $iPosition;
protected $sOutputFilePath;
protected $bAdvancedMode;
public function __construct($sToken = null)
{
$this->aStatistics = array(
$this->aStatistics = [
'objects_count' => 0,
'total_duration' => 0,
'data_retrieval_duration' => 0,
'excel_build_duration' => 0,
'excel_write_duration' => 0,
'peak_memory_usage' => 0,
);
'peak_memory_usage' => 0,
];
$this->fStartTime = microtime(true);
$this->oSearch = null;
$this->sState = 'new';
$this->aObjectsIDs = array();
$this->aObjectsIDs = [];
$this->iPosition = 0;
$this->aAuthorizedClasses = null;
$this->aTableHeaders = null;
$this->sOutputFilePath = null;
$this->bAdvancedMode = false;
$this->CheckDataDir();
if ($sToken == null)
{
if ($sToken == null) {
$this->sToken = $this->GetNewToken();
}
else
{
} else {
$this->sToken = $sToken;
$this->ReloadState();
}
}
public function __destruct()
{
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null))
{
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null)) {
// Operation in progress, save the state
$this->SaveState();
}
else
{
} else {
// Operation completed, cleanup the temp files
@unlink($this->GetStateFile());
@unlink($this->GetDataFile());
}
self::CleanupOldFiles();
self::CleanupOldFiles();
}
public function SetChunkSize($iChunkSize)
{
$this->iChunkSize = $iChunkSize;
$this->iChunkSize = $iChunkSize;
}
public function SetOutputFilePath($sDestFilePath)
{
$this->sOutputFilePath = $sDestFilePath;
}
public function SetAdvancedMode($bAdvanced)
{
$this->bAdvancedMode = $bAdvanced;
}
public function SaveState()
{
$aState = array(
$aState = [
'state' => $this->sState,
'statistics' => $this->aStatistics,
'filter' => $this->oSearch->serialize(),
@@ -94,31 +88,28 @@ class ExcelExporter
'object_ids' => $this->aObjectsIDs,
'output_file_path' => $this->sOutputFilePath,
'advanced_mode' => $this->bAdvancedMode,
);
];
file_put_contents($this->GetStateFile(), json_encode($aState));
return $this->sToken;
}
public function ReloadState()
{
if ($this->sToken == null)
{
if ($this->sToken == null) {
throw new Exception('ExcelExporter not initialized with a token, cannot reload state');
}
if (!file_exists($this->GetStateFile()))
{
if (!file_exists($this->GetStateFile())) {
throw new Exception("ExcelExporter: missing status file '".$this->GetStateFile()."', cannot reload state.");
}
$sJson = file_get_contents($this->GetStateFile());
$aState = json_decode($sJson, true);
if ($aState === null)
{
if ($aState === null) {
throw new Exception("ExcelExporter:corrupted status file '".$this->GetStateFile()."', not a JSON, cannot reload state.");
}
$this->sState = $aState['state'];
$this->aStatistics = $aState['statistics'];
$this->oSearch = DBObjectSearch::unserialize($aState['filter']);
@@ -128,206 +119,183 @@ class ExcelExporter
$this->sOutputFilePath = $aState['output_file_path'];
$this->bAdvancedMode = $aState['advanced_mode'];
}
public function SetObjectList($oSearch)
{
$this->oSearch = $oSearch;
}
public function Run()
{
$sCode = 'error';
$iPercentage = 100;
$sMessage = Dict::Format('ExcelExporter:ErrorUnexpected_State', $this->sState);
$fTime = microtime(true);
try
{
switch($this->sState)
{
try {
switch ($this->sState) {
case 'new':
$oIDSet = new DBObjectSet($this->oSearch);
$oIDSet->OptimizeColumnLoad(array('id'));
$this->aObjectsIDs = array();
while($oObj = $oIDSet->Fetch())
{
$this->aObjectsIDs[] = $oObj->GetKey();
}
$sCode = 'retrieving-data';
$iPercentage = 5;
$sMessage = Dict::S('ExcelExporter:RetrievingData');
$this->iPosition = 0;
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
// The first line of the file is the "headers" specifying the label and the type of each column
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
$sRow = json_encode($this->aTableHeaders);
$hFile = @fopen($this->GetDataFile(), 'ab');
if ($hFile === false)
{
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
}
fwrite($hFile, $sRow."\n");
fclose($hFile);
// Next state
$this->sState = 'retrieving-data';
break;
case 'retrieving-data':
$oCurrentSearch = clone $this->oSearch;
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
$hFile = @fopen($this->GetDataFile(), 'ab');
if ($hFile === false)
{
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
}
$oSet = new DBObjectSet($oCurrentSearch);
$this->GetFieldsList($oSet, $this->bAdvancedMode);
while($aObjects = $oSet->FetchAssoc())
{
$aRow = array();
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
{
$oObj = $aObjects[$sAlias];
if ($this->bAdvancedMode)
{
$aRow[] = $oObj->GetKey();
}
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
{
$value = $oObj->Get($sAttCodeEx);
if ($value instanceOf ormCaseLog)
{
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
}
else
{
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
}
$aRow[] = $sExcelVal;
}
$oIDSet = new DBObjectSet($this->oSearch);
$oIDSet->OptimizeColumnLoad(['id']);
$this->aObjectsIDs = [];
while ($oObj = $oIDSet->Fetch()) {
$this->aObjectsIDs[] = $oObj->GetKey();
}
$sRow = json_encode($aRow);
fwrite($hFile, $sRow."\n");
}
fclose($hFile);
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs))
{
// Next state
$this->sState = 'building-excel';
$sCode = 'building-excel';
$iPercentage = 80;
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
}
else
{
$sCode = 'retrieving-data';
$this->iPosition += $this->iChunkSize;
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
$sMessage = Dict::S('ExcelExporter:RetrievingData');
}
break;
$iPercentage = 5;
$sMessage = Dict::S('ExcelExporter:RetrievingData');
$this->iPosition = 0;
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
// The first line of the file is the "headers" specifying the label and the type of each column
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
$sRow = json_encode($this->aTableHeaders);
$hFile = @fopen($this->GetDataFile(), 'ab');
if ($hFile === false) {
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
}
fwrite($hFile, $sRow."\n");
fclose($hFile);
// Next state
$this->sState = 'retrieving-data';
break;
case 'retrieving-data':
$oCurrentSearch = clone $this->oSearch;
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
$hFile = @fopen($this->GetDataFile(), 'ab');
if ($hFile === false) {
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
}
$oSet = new DBObjectSet($oCurrentSearch);
$this->GetFieldsList($oSet, $this->bAdvancedMode);
while ($aObjects = $oSet->FetchAssoc()) {
$aRow = [];
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
$oObj = $aObjects[$sAlias];
if ($this->bAdvancedMode) {
$aRow[] = $oObj->GetKey();
}
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
$value = $oObj->Get($sAttCodeEx);
if ($value instanceof ormCaseLog) {
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
} else {
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
}
$aRow[] = $sExcelVal;
}
}
$sRow = json_encode($aRow);
fwrite($hFile, $sRow."\n");
}
fclose($hFile);
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs)) {
// Next state
$this->sState = 'building-excel';
$sCode = 'building-excel';
$iPercentage = 80;
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
} else {
$sCode = 'retrieving-data';
$this->iPosition += $this->iChunkSize;
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
$sMessage = Dict::S('ExcelExporter:RetrievingData');
}
break;
case 'building-excel':
$hFile = @fopen($this->GetDataFile(), 'rb');
if ($hFile === false)
{
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
}
$sHeaders = fgets($hFile);
$aHeaders = json_decode($sHeaders, true);
$aData = array();
while($sLine = fgets($hFile))
{
$aRow = json_decode($sLine);
$aData[] = $aRow;
}
fclose($hFile);
@unlink($this->GetDataFile());
$fStartExcel = microtime(true);
$writer = new XLSXWriter();
$writer->setAuthor(UserRights::GetUserFriendlyName());
$writer->writeSheet($aData,'Sheet1', $aHeaders);
$fExcelTime = microtime(true) - $fStartExcel;
$this->aStatistics['excel_build_duration'] = $fExcelTime;
$fTime = microtime(true);
$writer->writeToFile($this->GetExcelFilePath());
$fExcelSaveTime = microtime(true) - $fTime;
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
// Next state
$this->sState = 'done';
$sCode = 'done';
$iPercentage = 100;
$sMessage = Dict::S('ExcelExporter:Done');
break;
$hFile = @fopen($this->GetDataFile(), 'rb');
if ($hFile === false) {
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
}
$sHeaders = fgets($hFile);
$aHeaders = json_decode($sHeaders, true);
$aData = [];
while ($sLine = fgets($hFile)) {
$aRow = json_decode($sLine);
$aData[] = $aRow;
}
fclose($hFile);
@unlink($this->GetDataFile());
$fStartExcel = microtime(true);
$writer = new XLSXWriter();
$writer->setAuthor(UserRights::GetUserFriendlyName());
$writer->writeSheet($aData, 'Sheet1', $aHeaders);
$fExcelTime = microtime(true) - $fStartExcel;
$this->aStatistics['excel_build_duration'] = $fExcelTime;
$fTime = microtime(true);
$writer->writeToFile($this->GetExcelFilePath());
$fExcelSaveTime = microtime(true) - $fTime;
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
// Next state
$this->sState = 'done';
$sCode = 'done';
$iPercentage = 100;
$sMessage = Dict::S('ExcelExporter:Done');
break;
case 'done':
$this->sState = 'done';
$sCode = 'done';
$iPercentage = 100;
$sMessage = Dict::S('ExcelExporter:Done');
break;
$this->sState = 'done';
$sCode = 'done';
$iPercentage = 100;
$sMessage = Dict::S('ExcelExporter:Done');
break;
}
}
catch(Exception $e)
{
} catch (Exception $e) {
$sCode = 'error';
$sMessage = $e->getMessage();
}
$this->aStatistics['total_duration'] += microtime(true) - $fTime;
$peak_memory = memory_get_peak_usage(true);
if ($peak_memory > $this->aStatistics['peak_memory_usage'])
{
if ($peak_memory > $this->aStatistics['peak_memory_usage']) {
$this->aStatistics['peak_memory_usage'] = $peak_memory;
}
return array(
return [
'code' => $sCode,
'message' => $sMessage,
'percentage' => $iPercentage,
);
];
}
public function GetExcelFilePath()
{
if ($this->sOutputFilePath == null)
{
if ($this->sOutputFilePath == null) {
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.xlsx';
}
else
{
} else {
return $this->sOutputFilePath;
}
}
public static function GetExcelFileFromToken($sToken)
{
return @file_get_contents(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
}
public static function CleanupFromToken($sToken)
{
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.status');
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.data');
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
}
public function Cleanup()
{
self::CleanupFromToken($this->sToken);
}
/**
* Delete all files in the data/bulk_export directory which are older than 1 day
* unless a different delay is configured.
@@ -336,15 +304,12 @@ class ExcelExporter
{
$aFiles = glob(utils::GetDataPath().'bulk_export/*.*');
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
if($iDelay > 0)
{
foreach($aFiles as $sFile)
{
if ($iDelay > 0) {
foreach ($aFiles as $sFile) {
$iModificationTime = filemtime($sFile);
if($iModificationTime < (time() - $iDelay))
{
if ($iModificationTime < (time() - $iDelay)) {
// Temporary files older than one day are deleted
//echo "Supposed to delete: '".$sFile." (Unix Modification Time: $iModificationTime)'\n";
@unlink($sFile);
@@ -352,189 +317,155 @@ class ExcelExporter
}
}
}
public function DisplayStatistics(Page $oPage)
{
$aStats = array(
$aStats = [
'Number of objects exported' => $this->aStatistics['objects_count'],
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
);
if ($oPage instanceof CLIPage)
{
];
if ($oPage instanceof CLIPage) {
$oPage->add($this->GetStatistics('text'));
}
else
{
} else {
$oPage->add($this->GetStatistics('html'));
}
}
public function GetStatistics($sFormat = 'html')
{
$sStats = '';
$aStats = array(
$aStats = [
'Number of objects exported' => $this->aStatistics['objects_count'],
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
);
if ($sFormat == 'text')
{
foreach($aStats as $sLabel => $sValue)
{
];
if ($sFormat == 'text') {
foreach ($aStats as $sLabel => $sValue) {
$sStats .= "+------------------------------+----------+\n";
$sStats .= sprintf("|%-30s|%10s|\n", $sLabel, $sValue);
}
$sStats .= "+------------------------------+----------+";
}
else
{
} else {
$sStats .= '<table><tbody>';
foreach($aStats as $sLabel => $sValue)
{
foreach ($aStats as $sLabel => $sValue) {
$sStats .= "<tr><td>$sLabel</td><td>$sValue</td></tr>";
}
$sStats .= '</tbody></table>';
}
return $sStats;
}
public static function HumanDisplay($iSize)
{
$aUnits = array('B','KB','MB','GB','TB','PB');
return @round($iSize/pow(1024,($i=floor(log($iSize,1024)))),2).' '.$aUnits[$i];
$aUnits = ['B','KB','MB','GB','TB','PB'];
return @round($iSize / pow(1024, ($i = floor(log($iSize, 1024)))), 2).' '.$aUnits[$i];
}
protected function CheckDataDir()
{
if(!is_dir(utils::GetDataPath()."bulk_export"))
{
if (!is_dir(utils::GetDataPath()."bulk_export")) {
@mkdir(utils::GetDataPath()."bulk_export", 0777, true /* recursive */);
clearstatcache();
}
if (!is_writable(utils::GetDataPath()."bulk_export"))
{
if (!is_writable(utils::GetDataPath()."bulk_export")) {
throw new Exception('Data directory "'.utils::GetDataPath().'bulk_export" could not be written.');
}
}
protected function GetStateFile($sToken = null)
{
if ($sToken == null)
{
if ($sToken == null) {
$sToken = $this->sToken;
}
return utils::GetDataPath()."bulk_export/$sToken.status";
}
protected function GetDataFile()
{
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.data';
}
protected function GetNewToken()
{
$iNum = rand();
do
{
do {
$iNum++;
$sToken = sprintf("%08x", $iNum);
$sFileName = $this->GetStateFile($sToken);
$hFile = @fopen($sFileName, 'x');
}
while($hFile === false);
} while ($hFile === false);
fclose($hFile);
return $sToken;
}
protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
{
$this->aFieldsList = array();
$this->aFieldsList = [];
$oAppContext = new ApplicationContext();
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
$this->aAuthorizedClasses = array();
foreach($aClasses as $sAlias => $sClassName)
{
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO)
{
$this->aAuthorizedClasses = [];
foreach ($aClasses as $sAlias => $sClassName) {
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) {
$this->aAuthorizedClasses[$sAlias] = $sClassName;
}
}
$aAttribs = array();
$this->aTableHeaders = array();
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
{
$aList[$sAlias] = array();
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
{
if (is_null($aFields) || (count($aFields) == 0))
{
$aAttribs = [];
$this->aTableHeaders = [];
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
$aList[$sAlias] = [];
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
if (is_null($aFields) || (count($aFields) == 0)) {
// Standard list of attributes (no link sets)
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField()))
{
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) {
$sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode;
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
if ($bFieldsAdvanced)
{
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
if ($bFieldsAdvanced) {
$aList[$sAlias][$sAttCodeEx] = $oAttDef;
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE))
{
$sRemoteClass = $oAttDef->GetTargetClass();
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode)
{
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE)) {
$sRemoteClass = $oAttDef->GetTargetClass();
foreach (MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode) {
$this->aFieldsList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
}
}
}
}
}
else
{
} else {
// Any other attribute
$this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
}
}
}
else
{
} else {
// User defined list of attributes
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields))
{
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields)) {
$this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
}
}
}
if ($bFieldsAdvanced)
{
if ($bFieldsAdvanced) {
$this->aTableHeaders['id'] = '0';
}
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
{
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
$sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
if($oAttDef instanceof AttributeDateTime)
{
if ($oAttDef instanceof AttributeDateTime) {
$this->aTableHeaders[$sLabel] = 'datetime';
}
else
{
} else {
$this->aTableHeaders[$sLabel] = 'string';
}
}
}
}
}

View File

@@ -1,9 +1,10 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class InputOutputTask
*
@@ -28,42 +28,43 @@ require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
/**
* This class manages the input/output tasks
* for synchronizing information with external data sources
* for synchronizing information with external data sources
*/
class InputOutputTask extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "application",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_iotask",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("category", array("allowed_values" => new ValueSetEnum('Input, Ouput'), "sql" => "category", "default_value" => "Input", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("allowed_values" => new ValueSetEnum('File, Database, Web Service'), "sql" => "source_type", "default_value" => "File", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype",
array("allowed_values" => new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql" => "source_subtype", "default_value" => "CSV", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("source_path", array("allowed_values" => null, "sql" => "source_path", "default_value" => "", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeClass("objects_class", array("class_category" => "", "more_values" => "", "sql" => "objects_class", "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "class_exclusion_list" => null)));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "test_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "verbose_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("options", array("allowed_values" => new ValueSetEnum('Full, Update Only, Creation Only'), "sql" => "options", "default_value" => 'Full', "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("name", ["allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("category", ["allowed_values" => new ValueSetEnum('Input, Ouput'), "sql" => "category", "default_value" => "Input", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", ["allowed_values" => new ValueSetEnum('File, Database, Web Service'), "sql" => "source_type", "default_value" => "File", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum(
"source_subtype",
["allowed_values" => new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql" => "source_subtype", "default_value" => "CSV", "is_null_allowed" => false, "depends_on" => []]
));
MetaModel::Init_AddAttribute(new AttributeString("source_path", ["allowed_values" => null, "sql" => "source_path", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeClass("objects_class", ["class_category" => "", "more_values" => "", "sql" => "objects_class", "default_value" => null, "is_null_allowed" => true, "depends_on" => [], "class_exclusion_list" => null]));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", ["allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "test_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", ["allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "verbose_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("options", ["allowed_values" => new ValueSetEnum('Full, Update Only, Creation Only'), "sql" => "options", "default_value" => 'Full', "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path', 'options', 'test_mode', 'verbose_mode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path', 'options', 'test_mode', 'verbose_mode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the advanced search form
MetaModel::Init_SetZListItems('standard_search', ['name', 'category', 'objects_class', 'source_type', 'source_subtype']); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', ['name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype']); // Criteria of the advanced search form
}
}
?>

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -12,7 +13,6 @@ use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT."/application/user.dashboard.class.inc.php");
/**
* This class manipulates, stores and displays the navigation menu used in the application
* In order to improve the modularity of the data model and to ease the update/migration
@@ -51,43 +51,40 @@ class ApplicationMenu
/**
* @var bool
*/
static $bAdditionalMenusLoaded = false;
public static $bAdditionalMenusLoaded = false;
/**
* @var array
*/
static $aRootMenus = array();
public static $aRootMenus = [];
/**
* @var array
*/
static $aMenusIndex = array();
public static $aMenusIndex = [];
/**
* @var array
*/
static $aMenusById = [];
public static $aMenusById = [];
/**
* @var string
*/
static $sFavoriteSiloQuery = 'SELECT Organization';
public static $sFavoriteSiloQuery = 'SELECT Organization';
/**
* @return void
*/
public static function LoadAdditionalMenus()
{
if (!self::$bAdditionalMenusLoaded)
{
if (!self::$bAdditionalMenusLoaded) {
// Build menus from module handlers
//
/** @var \ModuleHandlerApiInterface $oPHPClass */
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMenuCreation();
}
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
$oPHPClass::OnMenuCreation();
}
// Build menus from the menus themselves (e.g. the ShortcutContainerMenuNode will do that)
//
foreach(self::$aRootMenus as $aMenu)
{
foreach (self::$aRootMenus as $aMenu) {
$oMenuNode = self::GetMenuNode($aMenu['index']);
$oMenuNode->PopulateChildMenus();
}
@@ -124,8 +121,7 @@ class ApplicationMenu
*/
public static function CheckMenuIdEnabled($sMenuId)
{
if (self::IsMenuIdEnabled($sMenuId) === false)
{
if (self::IsMenuIdEnabled($sMenuId) === false) {
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:Login:Error:AccessRestricted')."</h1>\n");
@@ -141,7 +137,7 @@ class ApplicationMenu
* @return bool true if the menu exists and current user is allowed to see the menu
* @since 3.2.0
*/
public static function IsMenuIdEnabled($sMenuId):bool
public static function IsMenuIdEnabled($sMenuId): bool
{
self::LoadAdditionalMenus();
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
@@ -159,22 +155,18 @@ class ApplicationMenu
public static function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
{
$index = self::GetMenuIndexById($oMenuNode->GetMenuId());
if ($index == -1)
{
if ($index == -1) {
// The menu does not already exist, insert it
$index = count(self::$aMenusIndex);
if ($iParentIndex == -1)
{
if ($iParentIndex == -1) {
$sParentId = '';
self::$aRootMenus[] = array ('rank' => $fRank, 'index' => $index);
}
else
{
self::$aRootMenus[] = ['rank' => $fRank, 'index' => $index];
} else {
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$iParentIndex]['node'];
$sParentId = $oNode->GetMenuId();
self::$aMenusIndex[$iParentIndex]['children'][] = array ('rank' => $fRank, 'index' => $index);
self::$aMenusIndex[$iParentIndex]['children'][] = ['rank' => $fRank, 'index' => $index];
}
// Note: At the time when 'parent', 'rank' and 'source_file' have been added for the reflection API,
@@ -182,11 +174,9 @@ class ApplicationMenu
//
$aBacktrace = debug_backtrace();
$sFile = isset($aBacktrace[2]["file"]) ? $aBacktrace[2]["file"] : $aBacktrace[1]["file"];
self::$aMenusIndex[$index] = array('node' => $oMenuNode, 'children' => array(), 'parent' => $sParentId, 'rank' => $fRank, 'source_file' => $sFile);
self::$aMenusIndex[$index] = ['node' => $oMenuNode, 'children' => [], 'parent' => $sParentId, 'rank' => $fRank, 'source_file' => $sFile];
self::$aMenusById[$oMenuNode->GetMenuId()] = $index;
}
else
{
} else {
// the menu already exists, let's combine the conditions that make it visible
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$index]['node'];
@@ -216,7 +206,7 @@ class ApplicationMenu
* @throws \DictExceptionMissingString
* @since 3.0.0
*/
public static function GetMenusCount($aExtraParams = array())
public static function GetMenusCount($aExtraParams = [])
{
$aMenuGroups = static::GetMenuGroups($aExtraParams);
@@ -259,18 +249,16 @@ class ApplicationMenu
* @throws \DictExceptionMissingString
* @since 3.0.0
*/
public static function GetMenuGroups($aExtraParams = array())
public static function GetMenuGroups($aExtraParams = [])
{
self::LoadAdditionalMenus();
// Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
usort(self::$aRootMenus, ['ApplicationMenu', 'CompareOnRank']);
$aMenuGroups = [];
foreach(static::$aRootMenus as $aMenuGroup)
{
if(!static::CanDisplayMenu($aMenuGroup))
{
foreach (static::$aRootMenus as $aMenuGroup) {
if (!static::CanDisplayMenu($aMenuGroup)) {
continue;
}
@@ -321,26 +309,23 @@ class ApplicationMenu
* @throws \Exception
* @since 3.0.0
*/
public static function GetSubMenuNodes($sMenuGroupIdx, $aExtraParams = array())
public static function GetSubMenuNodes($sMenuGroupIdx, $aExtraParams = [])
{
$aSubMenuItems = self::GetChildren($sMenuGroupIdx);
// Sort the children based on the rank
usort($aSubMenuItems, array('ApplicationMenu', 'CompareOnRank'));
usort($aSubMenuItems, ['ApplicationMenu', 'CompareOnRank']);
$aSubMenuNodes = [];
foreach($aSubMenuItems as $aSubMenuItem)
{
if(!static::CanDisplayMenu($aSubMenuItem))
{
foreach ($aSubMenuItems as $aSubMenuItem) {
if (!static::CanDisplayMenu($aSubMenuItem)) {
continue;
}
$sSubMenuItemIdx = $aSubMenuItem['index'];
$oSubMenuNode = static::GetMenuNode($sSubMenuItemIdx);
if(!$oSubMenuNode->IsEnabled())
{
if (!$oSubMenuNode->IsEnabled()) {
continue;
}
@@ -366,21 +351,15 @@ class ApplicationMenu
private static function CanDisplayMenu($aMenu)
{
$oMenuNode = self::GetMenuNode($aMenu['index']);
if ($oMenuNode->IsEnabled())
{
if ($oMenuNode->IsEnabled()) {
$aChildren = self::GetChildren($aMenu['index']);
if (count($aChildren) > 0)
{
foreach($aChildren as $aSubMenu)
{
if (self::CanDisplayMenu($aSubMenu))
{
if (count($aChildren) > 0) {
foreach ($aChildren as $aSubMenu) {
if (self::CanDisplayMenu($aSubMenu)) {
return true;
}
}
}
else
{
} else {
return true;
}
}
@@ -396,12 +375,10 @@ class ApplicationMenu
public static function CompareOnRank($a, $b)
{
$result = 1;
if ($a['rank'] == $b['rank'])
{
if ($a['rank'] == $b['rank']) {
$result = 0;
}
if ($a['rank'] < $b['rank'])
{
if ($a['rank'] < $b['rank']) {
$result = -1;
}
return $result;
@@ -449,8 +426,7 @@ class ApplicationMenu
{
$oAppContext = new ApplicationContext();
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
if ($sMenuId === null)
{
if ($sMenuId === null) {
$sMenuId = self::GetDefaultMenuId();
}
return $sMenuId;
@@ -462,13 +438,12 @@ class ApplicationMenu
public static function GetDefaultMenuId()
{
static $sDefaultMenuId = null;
if (is_null($sDefaultMenuId))
{
if (is_null($sDefaultMenuId)) {
// Make sure the root menu is sorted on 'rank'
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
usort(self::$aRootMenus, ['ApplicationMenu', 'CompareOnRank']);
$oFirstGroup = self::GetMenuNode(self::$aRootMenus[0]['index']);
$aChildren = self::$aMenusIndex[$oFirstGroup->GetIndex()]['children'];
usort($aChildren, array('ApplicationMenu', 'CompareOnRank'));
usort($aChildren, ['ApplicationMenu', 'CompareOnRank']);
$oMenuNode = self::GetMenuNode($aChildren[0]['index']);
$sDefaultMenuId = $oMenuNode->GetMenuId();
}
@@ -482,13 +457,11 @@ class ApplicationMenu
public static function GetRootMenuId($sMenuId)
{
$iMenuIndex = self::GetMenuIndexById($sMenuId);
if ($iMenuIndex == -1)
{
if ($iMenuIndex == -1) {
return '';
}
$oMenu = ApplicationMenu::GetMenuNode($iMenuIndex);
while ($oMenu->GetParentIndex() != -1)
{
while ($oMenu->GetParentIndex() != -1) {
$oMenu = ApplicationMenu::GetMenuNode($oMenu->GetParentIndex());
}
return $oMenu->GetMenuId();
@@ -575,17 +548,17 @@ abstract class MenuNode
{
$this->sMenuId = $sMenuId;
$this->iParentIndex = $iParentIndex;
$this->aReflectionProperties = array();
$this->aReflectionProperties = [];
if (utils::IsNotNullOrEmptyString($sEnableClass)) {
$this->aReflectionProperties['enable_class'] = $sEnableClass;
$this->aReflectionProperties['enable_action'] = $iActionCode;
$this->aReflectionProperties['enable_permission'] = $iAllowedResults;
$this->aReflectionProperties['enable_stimulus'] = $sEnableStimulus;
}
$this->m_aEnableClasses = array($sEnableClass);
$this->m_aEnableActions = array($iActionCode);
$this->m_aEnableActionResults = array($iAllowedResults);
$this->m_aEnableStimuli = array($sEnableStimulus);
$this->m_aEnableClasses = [$sEnableClass];
$this->m_aEnableActions = [$iActionCode];
$this->m_aEnableActionResults = [$iAllowedResults];
$this->m_aEnableStimuli = [$sEnableStimulus];
$this->index = ApplicationMenu::InsertMenu($this, $iParentIndex, $fRank);
}
@@ -639,7 +612,6 @@ abstract class MenuNode
$oSearch->SetShowObsoleteData(utils::ShowObsoleteData());
DBSearchHelper::AddContextFilter($oSearch);
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->CountWithLimit(99);
if ($iCount > 99) {
@@ -690,8 +662,7 @@ abstract class MenuNode
*/
public function PopulateChildMenus()
{
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu)
{
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu) {
$index = $aMenu['index'];
$oMenu = ApplicationMenu::GetMenuNode($index);
$oMenu->PopulateChildMenus();
@@ -726,8 +697,7 @@ abstract class MenuNode
*/
public function AddCondition(MenuNode $oMenuNode)
{
foreach($oMenuNode->m_aEnableClasses as $index => $sClass )
{
foreach ($oMenuNode->m_aEnableClasses as $index => $sClass) {
$this->m_aEnableClasses[] = $sClass;
$this->m_aEnableActions[] = $oMenuNode->m_aEnableActions[$index];
$this->m_aEnableActionResults[] = $oMenuNode->m_aEnableActionResults[$index];
@@ -740,33 +710,24 @@ abstract class MenuNode
*/
public function IsEnabled()
{
foreach($this->m_aEnableClasses as $index => $sClass)
{
if ($sClass != null)
{
if (MetaModel::IsValidClass($sClass))
{
if ($this->m_aEnableStimuli[$index] != null)
{
if (!UserRights::IsStimulusAllowed($sClass, $this->m_aEnableStimuli[$index]))
{
foreach ($this->m_aEnableClasses as $index => $sClass) {
if ($sClass != null) {
if (MetaModel::IsValidClass($sClass)) {
if ($this->m_aEnableStimuli[$index] != null) {
if (!UserRights::IsStimulusAllowed($sClass, $this->m_aEnableStimuli[$index])) {
return false;
}
}
if ($this->m_aEnableActions[$index] != null)
{
if ($this->m_aEnableActions[$index] != null) {
// Menus access rights ignore the archive mode
utils::PushArchiveMode(false);
$iResult = UserRights::IsActionAllowed($sClass, $this->m_aEnableActions[$index]);
utils::PopArchiveMode();
if (!($iResult & $this->m_aEnableActionResults[$index]))
{
if (!($iResult & $this->m_aEnableActionResults[$index])) {
return false;
}
}
}
else
{
} else {
return false;
}
}
@@ -779,7 +740,7 @@ abstract class MenuNode
* @param array $aExtraParams
* @return mixed
*/
public abstract function RenderContent(WebPage $oPage, $aExtraParams = array());
abstract public function RenderContent(WebPage $oPage, $aExtraParams = []);
/**
* @param string $sHyperlink
@@ -788,16 +749,13 @@ abstract class MenuNode
*/
protected function AddParams($sHyperlink, $aExtraParams)
{
if (count($aExtraParams) > 0)
{
$aQuery = array();
if (count($aExtraParams) > 0) {
$aQuery = [];
$sSeparator = '?';
if (strpos($sHyperlink, '?') !== false)
{
if (strpos($sHyperlink, '?') !== false) {
$sSeparator = '&';
}
foreach($aExtraParams as $sName => $sValue)
{
foreach ($aExtraParams as $sName => $sValue) {
$aQuery[] = urlencode($sName).'='.urlencode($sValue);
}
$sHyperlink .= $sSeparator.implode('&', $aQuery);
@@ -813,7 +771,7 @@ abstract class MenuNode
class MenuGroup extends MenuNode
{
/** @var string DEFAULT_DECORATION_CLASSES Set to null by default so it is replaced by initials when none is specified */
const DEFAULT_DECORATION_CLASSES = null;
public const DEFAULT_DECORATION_CLASSES = null;
/** @var string The CSS classes used to display the menu group's icon */
protected $sDecorationClasses = self::DEFAULT_DECORATION_CLASSES;
@@ -833,8 +791,7 @@ class MenuGroup extends MenuNode
{
parent::__construct($sMenuId, -1 /* no parent, groups are at root level */, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
if(!empty($sDecorationClasses))
{
if (!empty($sDecorationClasses)) {
$this->sDecorationClasses = $sDecorationClasses;
}
}
@@ -875,7 +832,7 @@ class MenuGroup extends MenuNode
/**
* @inheritDoc
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
assert(false); // Shall never be called, groups do not display any content
}
@@ -887,7 +844,6 @@ class MenuGroup extends MenuNode
*/
class TemplateMenuNode extends MenuNode
{
/**
* Create a menu item based on a custom template and inserts it into the application's main menu
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
@@ -914,7 +870,7 @@ class TemplateMenuNode extends MenuNode
* @inheritDoc
* @throws \Exception
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
//DO NOTHING this type of menu is only used for title not clickable
}
@@ -948,7 +904,6 @@ class OQLMenuNode extends MenuNode
*/
protected $m_aParams;
/**
* Create a menu item based on an OQL query and inserts it into the application's main menu
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
@@ -969,7 +924,7 @@ class OQLMenuNode extends MenuNode
$this->sOQL = $sOQL;
$this->bSearch = $bSearch;
$this->bSearchFormOpen = $bSearchFormOpen;
$this->m_aParams = array();
$this->m_aParams = [];
$this->aReflectionProperties['oql'] = $sOQL;
$this->aReflectionProperties['do_search'] = $bSearch;
// Enhancement: we could set as the "enable" condition that the user has enough rights to "read" the objects
@@ -983,8 +938,7 @@ class OQLMenuNode extends MenuNode
public function SetParameters($aParams)
{
$this->m_aParams = $aParams;
foreach($aParams as $sKey => $value)
{
foreach ($aParams as $sKey => $value) {
$this->aReflectionProperties[$sKey] = $value;
}
}
@@ -993,12 +947,11 @@ class OQLMenuNode extends MenuNode
* @inheritDoc
* @throws \Exception
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
$oTag = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
OQLMenuNode::RenderOQLSearch
(
OQLMenuNode::RenderOQLSearch(
$this->sOQL,
Dict::S($this->sPageTitle),
'Menu_'.$this->GetMenuId(),
@@ -1023,26 +976,25 @@ class OQLMenuNode extends MenuNode
* @throws DictExceptionMissingString
* @throws OQLException
*/
public static function RenderOQLSearch($sOql, $sTitle, $sUsageId, $bSearchPane, $bSearchOpen, WebPage $oPage, $aExtraParams = array(), $bEnableBreadcrumb = false)
public static function RenderOQLSearch($sOql, $sTitle, $sUsageId, $bSearchPane, $bSearchOpen, WebPage $oPage, $aExtraParams = [], $bEnableBreadcrumb = false)
{
$sUsageId = utils::GetSafeId($sUsageId);
$oSearch = DBObjectSearch::FromOQL($sOql);
$sClass= $oSearch->GetClass();
$sClass = $oSearch->GetClass();
$sIcon = MetaModel::GetClassIcon($sClass, false);
if ($bSearchPane) {
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams);
$oBlock = new DisplayBlock($oSearch, DisplayBlock::ENUM_STYLE_SEARCH, false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0);
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>");
}
else {
} else {
$oPage->add("<div class='sf_results_area' data-target='search_results'>");
}
$aExtraParams['panel_class'] =$sClass;
$aExtraParams['panel_class'] = $sClass;
$aExtraParams['panel_title'] = $sTitle;
$aExtraParams['panel_icon'] = $sIcon;
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
$aParams = array_merge(['table_id' => $sUsageId], $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, $sUsageId);
@@ -1107,14 +1059,14 @@ class SearchMenuNode extends MenuNode
* @throws \DictExceptionMissingString
* @throws \Exception
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oSearch = new DBObjectSearch($this->sClass);
$sUsageId = 'Menu_'.utils::GetSafeId($this->GetMenuId());
$aParams = array_merge(array('table_id' =>$sUsageId), $aExtraParams);
$aParams = array_merge(['table_id' => $sUsageId], $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0);
}
@@ -1151,10 +1103,16 @@ class WebPageMenuNode extends MenuNode
* @param bool $bIsLinkInNewWindow for the {@link WebPageMenuNode::IsHyperLinkInNewWindow} method
*/
public function __construct(
$sMenuId, $sHyperlink, $iParentIndex, $fRank = 0.0, $sEnableClass = null, $iActionCode = null,
$iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null, $bIsLinkInNewWindow = false
)
{
$sMenuId,
$sHyperlink,
$iParentIndex,
$fRank = 0.0,
$sEnableClass = null,
$iActionCode = null,
$iAllowedResults = UR_ALLOWED_YES,
$sEnableStimulus = null,
$bIsLinkInNewWindow = false
) {
parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
$this->sHyperlink = $sHyperlink;
$this->aReflectionProperties['url'] = $sHyperlink;
@@ -1167,7 +1125,7 @@ class WebPageMenuNode extends MenuNode
public function GetHyperlink($aExtraParams)
{
$aExtraParams['c[menu]'] = $this->GetMenuId();
return $this->AddParams( $this->sHyperlink, $aExtraParams);
return $this->AddParams($this->sHyperlink, $aExtraParams);
}
/**
@@ -1181,7 +1139,7 @@ class WebPageMenuNode extends MenuNode
/**
* @inheritDoc
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
assert(false); // Shall never be called, the external web page will handle the display by itself
}
@@ -1242,10 +1200,8 @@ class NewObjectMenuNode extends MenuNode
$aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
$bActionIsAllowed = false;
foreach($aSubClasses as $sCandidateClass)
{
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
{
foreach ($aSubClasses as $sCandidateClass) {
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
$bActionIsAllowed = true;
break; // Enough for now
}
@@ -1256,7 +1212,7 @@ class NewObjectMenuNode extends MenuNode
/**
* @inheritDoc
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
assert(false); // Shall never be called, the external web page will handle the display by itself
}
@@ -1296,7 +1252,9 @@ class DashboardMenuNode extends MenuNode
*/
public function GetHyperlink($aExtraParams)
{
if ($this->sDashboardFile == '') return '';
if ($this->sDashboardFile == '') {
return '';
}
return parent::GetHyperlink($aExtraParams);
}
@@ -1314,12 +1272,11 @@ class DashboardMenuNode extends MenuNode
* @inheritDoc
* @throws \Exception
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$oDashboard = $this->GetDashboard();
if ($oDashboard != null)
{
if ($oDashboard != null) {
WebResourcesHelper::EnableC3JSToWebPage($oPage);
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
@@ -1350,9 +1307,7 @@ class DashboardMenuNode extends MenuNode
}
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
}
}
else
{
} else {
$oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
}
}
@@ -1365,12 +1320,9 @@ class DashboardMenuNode extends MenuNode
public function RenderEditor(WebPage $oPage)
{
$oDashboard = $this->GetDashboard();
if ($oDashboard != null)
{
if ($oDashboard != null) {
$oDashboard->RenderEditor($oPage);
}
else
{
} else {
$oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
}
}
@@ -1382,13 +1334,10 @@ class DashboardMenuNode extends MenuNode
public function AddDashlet($oDashlet)
{
$oDashboard = $this->GetDashboard();
if ($oDashboard != null)
{
if ($oDashboard != null) {
$oDashboard->AddDashlet($oDashlet);
$oDashboard->Save();
}
else
{
} else {
throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
}
}
@@ -1411,7 +1360,7 @@ class ShortcutContainerMenuNode extends MenuNode
/**
* @inheritDoc
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
}
@@ -1426,10 +1375,9 @@ class ShortcutContainerMenuNode extends MenuNode
//
$oBMSearch = new DBObjectSearch('Shortcut');
$oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oBMSet = new DBObjectSet($oBMSearch, array('friendlyname' => true)); // ascending on friendlyname
$oBMSet = new DBObjectSet($oBMSearch, ['friendlyname' => true]); // ascending on friendlyname
$fRank = 1;
while ($oShortcut = $oBMSet->Fetch())
{
while ($oShortcut = $oBMSet->Fetch()) {
$sName = $this->GetMenuId().'_'.$oShortcut->GetKey();
new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++);
}
@@ -1440,7 +1388,6 @@ class ShortcutContainerMenuNode extends MenuNode
}
}
require_once(APPROOT.'application/shortcut.class.inc.php');
/**
* This class defines a menu item which content is a shortcut.
@@ -1477,12 +1424,10 @@ class ShortcutMenuNode extends MenuNode
{
$sContext = $this->oShortcut->Get('context');
$aContext = unserialize($sContext);
if (isset($aContext['menu']))
{
if (isset($aContext['menu'])) {
unset($aContext['menu']);
}
foreach ($aContext as $sArgName => $sArgValue)
{
foreach ($aContext as $sArgName => $sArgValue) {
$aExtraParams[$sArgName] = $sArgValue;
}
return parent::GetHyperlink($aExtraParams);
@@ -1492,7 +1437,7 @@ class ShortcutMenuNode extends MenuNode
* @inheritDoc
* @throws \Exception
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
public function RenderContent(WebPage $oPage, $aExtraParams = [])
{
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$this->oShortcut->RenderContent($oPage, $aExtraParams);
@@ -1529,11 +1474,9 @@ class ShortcutMenuNode extends MenuNode
return true;
}
public function GetEntriesCount()
{
return $this->GetEntriesCountFromOQL($this->oShortcut->Get('oql'));
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* Copyright (C) 2010-2024 Combodo SAS
*
@@ -31,111 +32,117 @@ abstract class Query extends cmdbAbstractObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui,application,grant_by_profile",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_query",
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array(
MetaModel::Init_AddAttribute(new AttributeString("name", [
"allowed_values" => null,
"sql" => "name",
"default_value" => null,
"is_null_allowed" => false,
"depends_on" => array(),
)));
"depends_on" => [],
]));
MetaModel::Init_AddAttribute(new AttributeText("description", array(
MetaModel::Init_AddAttribute(new AttributeText("description", [
"allowed_values" => null,
"sql" => "description",
"default_value" => null,
"is_null_allowed" => false,
"depends_on" => array(),
)));
"depends_on" => [],
]));
MetaModel::Init_AddAttribute(new AttributeEnum("is_template", array(
MetaModel::Init_AddAttribute(new AttributeEnum("is_template", [
'allowed_values' => new ValueSetEnum('yes,no'),
'sql' => 'is_template',
'default_value' => 'no',
'is_null_allowed' => false,
'depends_on' => [],
'display_style' => 'radio_horizontal',
)));
]));
MetaModel::Init_AddAttribute(new AttributeInteger("export_count", array(
MetaModel::Init_AddAttribute(new AttributeInteger("export_count", [
"allowed_values" => null,
"sql" => "export_count",
"default_value" => 0,
"is_null_allowed" => false,
"depends_on" => array(),
"depends_on" => [],
"tracking_level" => ATTRIBUTE_TRACKING_NONE,
)));
]));
MetaModel::Init_AddAttribute(new AttributeDateTime("export_last_date", array(
MetaModel::Init_AddAttribute(new AttributeDateTime("export_last_date", [
"allowed_values" => null,
"sql" => "export_last_date",
"default_value" => null,
"is_null_allowed" => true,
"depends_on" => array(),
"depends_on" => [],
"tracking_level" => ATTRIBUTE_TRACKING_NONE,
)));
]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("export_last_user_id",
array(
"targetclass"=>'User',
"allowed_values"=>null,
"sql"=>'user_id',
"is_null_allowed"=>true,
"depends_on"=>array(),
"display_style"=>'select',
"always_load_in_tables"=>false,
"on_target_delete"=>DEL_SILENT,
MetaModel::Init_AddAttribute(new AttributeExternalKey(
"export_last_user_id",
[
"targetclass" => 'User',
"allowed_values" => null,
"sql" => 'user_id',
"is_null_allowed" => true,
"depends_on" => [],
"display_style" => 'select',
"always_load_in_tables" => false,
"on_target_delete" => DEL_SILENT,
"tracking_level" => ATTRIBUTE_TRACKING_NONE,
)));
]
));
MetaModel::Init_AddAttribute(new AttributeExternalField("export_last_user_contact",
array(
"allowed_values"=>null,
"extkey_attcode"=> "export_last_user_id",
"target_attcode"=>"contactid",
MetaModel::Init_AddAttribute(new AttributeExternalField(
"export_last_user_contact",
[
"allowed_values" => null,
"extkey_attcode" => "export_last_user_id",
"target_attcode" => "contactid",
"tracking_level" => ATTRIBUTE_TRACKING_NONE,
)));
]
));
// Display lists
MetaModel::Init_SetZListItems('details',
array('name', 'is_template', 'description')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems(
'details',
['name', 'is_template', 'description']
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'is_template')); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search',
array('name', 'description', 'is_template')); // Criteria of the default search form
MetaModel::Init_SetZListItems('standard_search', ['name', 'description', 'is_template']); // Criteria of the std search form
MetaModel::Init_SetZListItems(
'default_search',
['name', 'description', 'is_template']
); // Criteria of the default search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
/**
* @inheritdoc
*
* @since 3.1.0
*/
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
public function GetAttributeFlags($sAttCode, &$aReasons = [], $sTargetState = '')
{
// read only attribute
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])){
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])) {
return OPT_ATT_READONLY;
}
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
}
/**
* Return export url.
*
@@ -144,7 +151,7 @@ abstract class Query extends cmdbAbstractObject
* @return string|null
* @since 3.1.0
*/
abstract public function GetExportUrl(array $aValues = null) : ?string;
abstract public function GetExportUrl(array $aValues = null): ?string;
/**
* Update last export information.
@@ -156,7 +163,7 @@ abstract class Query extends cmdbAbstractObject
* @throws \MySQLException
* @since 3.1.0
*/
public function UpdateLastExportInformation() : void
public function UpdateLastExportInformation(): void
{
// last export information
$this->Set('export_last_date', date(AttributeDateTime::GetSQLFormat()));
@@ -173,53 +180,56 @@ class QueryOQL extends Query
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui,application,grant_by_profile",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array('oql', 'is_template'),
"reconc_keys" => ['oql', 'is_template'],
"db_table" => "priv_query_oql",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array(
MetaModel::Init_AddAttribute(new AttributeOQL("oql", [
"allowed_values" => null,
"sql" => "oql",
"default_value" => null,
"is_null_allowed" => false,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeText("fields", array(
"depends_on" => [],
]));
MetaModel::Init_AddAttribute(new AttributeText("fields", [
"allowed_values" => null,
"sql" => "fields",
"default_value" => null,
"is_null_allowed" => true,
"depends_on" => array(),
)));
"depends_on" => [],
]));
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
// Display lists
MetaModel::Init_SetZListItems('details',
array(
'col:col1' => array('fieldset:Query:baseinfo' => array('name', 'is_template', 'description', 'oql', 'fields')),
'col:col2' => array('fieldset:Query:exportInfo' => array('export_count', 'export_last_date', 'export_last_user_id', 'export_last_user_contact'))
)
MetaModel::Init_SetZListItems(
'details',
[
'col:col1' => ['fieldset:Query:baseinfo' => ['name', 'is_template', 'description', 'oql', 'fields']],
'col:col2' => ['fieldset:Query:exportInfo' => ['export_count', 'export_last_date', 'export_last_user_id', 'export_last_user_contact']],
]
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search',
array('name', 'description', 'is_template', 'fields', 'oql')); // Criteria of the std search form
MetaModel::Init_SetZListItems(
'standard_search',
['name', 'description', 'is_template', 'fields', 'oql']
); // Criteria of the std search form
}
/** @inheritdoc */
public function GetExportUrl(array $aValues = null) : ?string
public function GetExportUrl(array $aValues = null): ?string
{
try{
try {
// retrieve attributes
$sOql = $this->Get('oql');
@@ -233,17 +243,16 @@ class QueryOQL extends Query
$aParameters = $oSearch->GetQueryParams();
foreach ($aParameters as $sParam => $val) {
$paramValue = ($aValues === null || $aValues[$sParam] === null) ? $sParam : $aValues[$sParam];
$sUrl .= '&arg_' . $sParam . '=' . $paramValue;
$sUrl .= '&arg_'.$sParam.'='.$paramValue;
}
return $sUrl;
}
catch(Exception $e){
} catch (Exception $e) {
return null;
}
}
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
public function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = [])
{
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
$oPage->add_script("$('[name=\"attr_oql\"]').addClass('ibo-query-oql ibo-is-code'); $('[data-attribute-code=\"oql\"]').addClass('ibo-query-oql ibo-is-code');");
@@ -267,16 +276,14 @@ class QueryOQL extends Query
if (count($aParameters) == 0) {
$oBlock = new DisplayBlock($oSearch, 'list');
$aExtraParams = array(
$aExtraParams = [
//'menu' => $sShowMenu,
'table_id' => 'query_preview_'.$this->getKey(),
);
];
$sBlockId = 'block_query_preview_'.$this->GetKey(); // make a unique id (edition occuring in the same DOM)
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
}
}
catch
(OQLException $e) {
} catch (OQLException $e) {
$oAlert = AlertUIBlockFactory::MakeForFailure(Dict::S('UI:RunQuery:Error'), $e->getHtmlDesc())
->SetIsClosable(false)
->SetIsCollapsible(false);
@@ -287,41 +294,38 @@ class QueryOQL extends Query
return $aFieldsMap;
}
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
//
// public function ComputeValues()
// {
// parent::ComputeValues();
//
// // Remove unwanted attribute codes
// $aChanges = $this->ListChanges();
// if (isset($aChanges['fields']))
// {
// $oAttDef = MetaModel::GetAttributeDef(get_class($this), 'fields');
// $aArgs = array('this' => $this);
// $aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
//
// /** @var \ormSet $oValue */
// $oValue = $this->Get('fields');
// $aValues = $oValue->GetValues();
// $bChanged = false;
// foreach($aValues as $key => $sValue)
// {
// if (!isset($aAllowedValues[$sValue]))
// {
// unset($aValues[$key]);
// $bChanged = true;
// }
// }
// if ($bChanged)
// {
// $oValue->SetValues($aValues);
// $this->Set('fields', $oValue);
// }
// }
// }
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
//
// public function ComputeValues()
// {
// parent::ComputeValues();
//
// // Remove unwanted attribute codes
// $aChanges = $this->ListChanges();
// if (isset($aChanges['fields']))
// {
// $oAttDef = MetaModel::GetAttributeDef(get_class($this), 'fields');
// $aArgs = array('this' => $this);
// $aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
//
// /** @var \ormSet $oValue */
// $oValue = $this->Get('fields');
// $aValues = $oValue->GetValues();
// $bChanged = false;
// foreach($aValues as $key => $sValue)
// {
// if (!isset($aAllowedValues[$sValue]))
// {
// unset($aValues[$key]);
// $bChanged = true;
// }
// }
// if ($bChanged)
// {
// $oValue->SetValues($aValues);
// $this->Set('fields', $oValue);
// }
// }
// }
}
?>

View File

@@ -1,9 +1,10 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -22,7 +23,7 @@ use Combodo\iTop\Application\Helper\Session;
* submitted yet, in order to prevent double submissions. When created a transaction remains valid
* until the user's session expires. This class is actually a wrapper to the underlying implementation
* which choice is configured via the parameter 'transaction_storage'
*
*
* @package iTop
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -37,13 +38,11 @@ class privUITransaction
public static function GetNewTransactionId()
{
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled)
{
if (!$bTransactionsEnabled) {
return 'notransactions'; // Any value will do
}
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage');
if (!class_exists($sClass, false))
{
if (!class_exists($sClass, false)) {
IssueLog::Error("Incorrect value '".MetaModel::GetConfig()->Get('transaction_storage')."' for 'transaction_storage', the class '$sClass' does not exists. Using privUITransactionSession instead for storing sessions.");
$sClass = 'privUITransactionSession';
}
@@ -62,16 +61,14 @@ class privUITransaction
public static function IsTransactionValid($id, $bRemoveTransaction = true)
{
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled)
{
if (!$bTransactionsEnabled) {
return true; // All values are valid
}
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage');
if (!class_exists($sClass, false))
{
if (!class_exists($sClass, false)) {
$sClass = 'privUITransactionSession';
}
return $sClass::IsTransactionValid($id, $bRemoveTransaction);
}
@@ -83,16 +80,14 @@ class privUITransaction
public static function RemoveTransaction($id)
{
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled)
{
if (!$bTransactionsEnabled) {
return; // Nothing to do
}
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage');
if (!class_exists($sClass, false))
{
if (!class_exists($sClass, false)) {
$sClass = 'privUITransactionSession';
}
$sClass::RemoveTransaction($id);
}
}
@@ -114,17 +109,16 @@ class privUITransactionSession
*/
public static function GetNewTransactionId()
{
if (!Session::IsSet('transactions'))
{
if (!Session::IsSet('transactions')) {
Session::Set('transactions', []);
}
// Strictly speaking, the two lines below should be grouped together
// by a critical section
// sem_acquire($rSemIdentified);
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime());
$id = static::GetUserPrefix().str_replace(['.', ' '], '', microtime());
Session::Set(['transactions', $id], true);
// sem_release($rSemIdentified);
return (string)$id;
}
@@ -135,20 +129,17 @@ class privUITransactionSession
* @param int $id Identifier of the transaction, as returned by GetNewTransactionId
* @param bool $bRemoveTransaction True if the transaction must be removed
* @return bool True if the transaction is valid, false otherwise
*/
*/
public static function IsTransactionValid($id, $bRemoveTransaction = true)
{
$bResult = false;
if (Session::IsSet('transactions'))
{
if (Session::IsSet('transactions')) {
// Strictly speaking, the eight lines below should be grouped together
// inside the same critical section as above
// sem_acquire($rSemIdentified);
if (Session::IsSet(['transactions', $id]))
{
if (Session::IsSet(['transactions', $id])) {
$bResult = true;
if ($bRemoveTransaction)
{
if ($bRemoveTransaction) {
Session::Unset(['transactions', $id]);
}
}
@@ -156,7 +147,7 @@ class privUITransactionSession
}
return $bResult;
}
/**
* Removes the transaction specified by its id
* @param int $id The Identifier (as returned by GetNewTranscationId) of the transaction to be removed.
@@ -164,17 +155,15 @@ class privUITransactionSession
*/
public static function RemoveTransaction($id)
{
if (Session::IsSet('transactions'))
{
if (Session::IsSet('transactions')) {
// Strictly speaking, the three lines below should be grouped together
// inside the same critical section as above
// sem_acquire($rSemIdentified);
if (Session::IsSet(['transactions', $id]))
{
if (Session::IsSet(['transactions', $id])) {
Session::Unset(['transactions', $id]);
}
// sem_release($rSemIdentified);
}
}
}
/**
@@ -197,7 +186,7 @@ class privUITransactionSession
class privUITransactionFile
{
/** @var int Value to use when no user logged */
const UNAUTHENTICATED_USER_ID = -666;
public const UNAUTHENTICATED_USER_ID = -666;
/**
* @return int current user id, or {@see self::UNAUTHENTICATED_USER_ID} if no user logged
@@ -228,22 +217,18 @@ class privUITransactionFile
*/
public static function GetNewTransactionId()
{
if (!is_dir(utils::GetDataPath().'transactions'))
{
if (!is_writable(APPROOT.'data'))
{
if (!is_dir(utils::GetDataPath().'transactions')) {
if (!is_writable(APPROOT.'data')) {
throw new Exception('The directory "'.APPROOT.'data" must be writable to the application.');
}
// condition avoids race condition N°2345
// See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition
if (!mkdir($concurrentDirectory = utils::GetDataPath().'transactions') && !is_dir($concurrentDirectory))
{
if (!mkdir($concurrentDirectory = utils::GetDataPath().'transactions') && !is_dir($concurrentDirectory)) {
throw new Exception('Failed to create the directory "'.utils::GetDataPath().'transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
}
}
if (!is_writable(utils::GetDataPath().'transactions'))
{
if (!is_writable(utils::GetDataPath().'transactions')) {
throw new Exception('The directory "'.utils::GetDataPath().'transactions" must be writable to the application.');
}
@@ -277,8 +262,7 @@ class privUITransactionFile
// Constraint the transaction file within utils::GetDataPath().'transactions'
$sTransactionDir = realpath(utils::GetDataPath().'transactions');
$sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir);
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath)))
{
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath))) {
return false;
}
@@ -297,15 +281,11 @@ class privUITransactionFile
return false;
}
if ($bRemoveTransaction)
{
if ($bRemoveTransaction) {
$bResult = @unlink($sFilepath);
if (!$bResult)
{
if (!$bResult) {
self::Error('IsTransactionValid: FAILED to remove transaction '.$id);
}
else
{
} else {
self::Info('IsTransactionValid: OK. Removed transaction: '.$id);
}
}
@@ -347,13 +327,11 @@ class privUITransactionFile
}
clearstatcache();
$iLimit = time() - 24*3600;
$iLimit = time() - 24 * 3600;
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : utils::GetDataPath().'transactions/*';
$aTransactions = glob($sPattern);
foreach($aTransactions as $sFileName)
{
if (filemtime($sFileName) < $iLimit)
{
foreach ($aTransactions as $sFileName) {
if (filemtime($sFileName) < $iLimit) {
@unlink($sFileName);
self::Info('CleanupOldTransactions: Deleted transaction: '.$sFileName);
}
@@ -367,10 +345,9 @@ class privUITransactionFile
protected static function GetPendingTransactions()
{
clearstatcache();
$aResult = array();
$aResult = [];
$aTransactions = glob(utils::GetDataPath().'transactions/'.self::GetUserPrefix().'*');
foreach($aTransactions as $sFileName)
{
foreach ($aTransactions as $sFileName) {
$aResult[] = date('Y-m-d H:i:s', filemtime($sFileName)).' - '.basename($sFileName);
}
sort($aResult);
@@ -398,13 +375,14 @@ class privUITransactionFile
{
self::Write('Warning | '.$sText);
}
protected static function Error($sText)
{
self::Write('Error | '.$sText);
}
protected static function IsLogEnabled() {
protected static function IsLogEnabled()
{
$oConfig = MetaModel::GetConfig();
if (is_null($oConfig)) {
return false;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Class WizardHelper
*
@@ -42,23 +42,17 @@ class WizardHelper
*/
public function GetTargetObject($bReadUploadedFiles = false)
{
if (isset($this->m_aData['m_oCurrentValues']['id']))
{
if (isset($this->m_aData['m_oCurrentValues']['id'])) {
$oObj = MetaModel::GetObject($this->m_aData['m_sClass'], $this->m_aData['m_oCurrentValues']['id']);
}
else
{
} else {
$oObj = MetaModel::NewObject($this->m_aData['m_sClass']);
}
foreach($this->m_aData['m_oCurrentValues'] as $sAttCode => $value)
{
foreach ($this->m_aData['m_oCurrentValues'] as $sAttCode => $value) {
// Because this is stored in a Javascript array, unused indexes
// are filled with null values and unused keys (stored as strings) contain $$NULL$$
if ( ($sAttCode !='id') && ($value !== '$$NULL$$'))
{
if (($sAttCode != 'id') && ($value !== '$$NULL$$')) {
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if (($oAttDef->IsLinkSet()) && ($value != '') )
{
if (($oAttDef->IsLinkSet()) && ($value != '')) {
// special handling for lists
// assumes this is handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
@@ -71,47 +65,35 @@ class WizardHelper
// Check what are the meaningful attributes
$aFields = $this->GetLinkedWizardStructure($oAttDef);
$sLinkedClass = $oAttDef->GetLinkedClass();
$aLinkedObjectsArray = array();
$aLinkedObjectsArray = [];
if (!is_array($aData)) {
echo("aData: '$aData' (value: '$value')\n");
}
foreach ($aData as $aLinkedObject)
{
foreach ($aData as $aLinkedObject) {
$oLinkedObj = MetaModel::NewObject($sLinkedClass);
foreach($aFields as $sLinkedAttCode)
{
if ( isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null) )
{
foreach ($aFields as $sLinkedAttCode) {
if (isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null)) {
$sLinkedAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLinkedAttCode);
if (($sLinkedAttDef->IsExternalKey()) && ($aLinkedObject[$sLinkedAttCode] != '') && ($aLinkedObject[$sLinkedAttCode] > 0) )
{
if (($sLinkedAttDef->IsExternalKey()) && ($aLinkedObject[$sLinkedAttCode] != '') && ($aLinkedObject[$sLinkedAttCode] > 0)) {
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]);
$oLinkedObj->Set($sLinkedAttCode, $oTargetObj);
}
elseif($sLinkedAttDef instanceof AttributeDateTime)
{
$sDateClass = get_class($sLinkedAttDef);
$sDate = $aLinkedObject[$sLinkedAttCode];
if($sDate !== null && $sDate !== '')
{
$oDateTimeFormat = $sDateClass::GetFormat();
$oDate = $oDateTimeFormat->Parse($sDate);
if ($sDateClass == "AttributeDate")
{
$sDate = $oDate->format('Y-m-d');
}
else
{
$sDate = $oDate->format('Y-m-d H:i:s');
}
}
} elseif ($sLinkedAttDef instanceof AttributeDateTime) {
$sDateClass = get_class($sLinkedAttDef);
$sDate = $aLinkedObject[$sLinkedAttCode];
if ($sDate !== null && $sDate !== '') {
$oDateTimeFormat = $sDateClass::GetFormat();
$oDate = $oDateTimeFormat->Parse($sDate);
if ($sDateClass == "AttributeDate") {
$sDate = $oDate->format('Y-m-d');
} else {
$sDate = $oDate->format('Y-m-d H:i:s');
}
}
$oLinkedObj->Set($sLinkedAttCode, $sDate);
}
else
{
$oLinkedObj->Set($sLinkedAttCode, $sDate);
} else {
$oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]);
}
}
@@ -120,98 +102,67 @@ class WizardHelper
}
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
$oObj->Set($sAttCode, $oSet);
}
else if ( $oAttDef->GetEditClass() == 'Document' )
{
if ($bReadUploadedFiles)
{
} elseif ($oAttDef->GetEditClass() == 'Document') {
if ($bReadUploadedFiles) {
$oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents');
$oObj->Set($sAttCode, $oDocument);
}
else
{
} else {
// Create a new empty document, just for displaying the file name
$oDocument = new ormDocument(null, '', $value);
$oObj->Set($sAttCode, $oDocument);
}
}
else if ( $oAttDef->GetEditClass() == 'Image' )
{
if ($bReadUploadedFiles)
{
} elseif ($oAttDef->GetEditClass() == 'Image') {
if ($bReadUploadedFiles) {
$oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents');
$oObj->Set($sAttCode, $oDocument);
}
else
{
} else {
// Create a new empty document, just for displaying the file name
$oDocument = new ormDocument(null, '', $value);
$oObj->Set($sAttCode, $oDocument);
}
}
else if (($oAttDef->IsExternalKey()) && (!empty($value)) && ($value > 0) )
{
} elseif (($oAttDef->IsExternalKey()) && (!empty($value)) && ($value > 0)) {
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value, false);
if ($oTargetObj)
{
if ($oTargetObj) {
$oObj->Set($sAttCode, $oTargetObj);
}
else
{
} else {
// May happen for security reasons (portal, see ticket N°1074)
$oObj->Set($sAttCode, $value);
}
}
else if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
{
if ($value != null)
{
} elseif ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
if ($value != null) {
$oDate = $oAttDef->GetFormat()->Parse($value);
if ($oDate instanceof DateTime)
{
if ($oDate instanceof DateTime) {
$value = $oDate->format($oAttDef->GetInternalFormat());
}
else
{
} else {
$value = null;
}
}
$oObj->Set($sAttCode, $value);
}
else if ($oAttDef instanceof AttributeTagSet) // AttributeDate is derived from AttributeDateTime
{
if (is_null($value))
{
} elseif ($oAttDef instanceof AttributeTagSet) { // AttributeDate is derived from AttributeDateTime
if (is_null($value)) {
// happens if field is hidden (see N°1827)
$value = array();
}
else
{
$value = [];
} else {
$value = json_decode($value, true);
}
$oTagSet = new ormTagSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else if ($oAttDef instanceof AttributeSet) // AttributeDate is derived from AttributeDateTime
{
} elseif ($oAttDef instanceof AttributeSet) { // AttributeDate is derived from AttributeDateTime
$value = json_decode($value, true);
$oTagSet = new ormSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else
{
} else {
$oObj->Set($sAttCode, $value);
}
}
}
if (isset($this->m_aData['m_sState']) && !empty($this->m_aData['m_sState']))
{
if (isset($this->m_aData['m_sState']) && !empty($this->m_aData['m_sState'])) {
$oObj->Set(MetaModel::GetStateAttributeCode($this->m_aData['m_sClass']), $this->m_aData['m_sState']);
}
$oObj->DoComputeValues();
@@ -226,31 +177,25 @@ class WizardHelper
public function SetDefaultValue($sAttCode, $value)
{
// Protect against a request for a non existing field
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
{
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode])) {
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if ($oAttDef->GetEditClass() == 'List')
{
if ($oAttDef->GetEditClass() == 'List') {
// special handling for lists
// this as to be handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
// NOT YET IMPLEMENTED !!
$oSet = $value;
$aData = array();
$aData = [];
$aFields = $this->GetLinkedWizardStructure($oAttDef);
while($oLinkedObj = $oSet->fetch())
{
foreach($aFields as $sLinkedAttCode)
{
while ($oLinkedObj = $oSet->fetch()) {
foreach ($aFields as $sLinkedAttCode) {
$aRow[$sAttCode] = $oLinkedObj->Get($sLinkedAttCode);
}
$aData[] = $aRow;
}
$this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData);
}
else
{
} else {
// Normal handling for all other scalar attributes
$this->m_aData['m_oDefaultValue'][$sAttCode] = $value;
}
@@ -265,8 +210,7 @@ class WizardHelper
public function SetAllowedValuesHtml($sAttCode, $sHtml)
{
// Protect against a request for a non existing field
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
{
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode])) {
$this->m_aData['m_oAllowedValues'][$sAttCode] = $sHtml;
}
}
@@ -276,7 +220,7 @@ class WizardHelper
return json_encode($this->m_aData);
}
static public function FromJSON($sJSON)
public static function FromJSON($sJSON)
{
$oWizHelper = new WizardHelper();
$aData = json_decode($sJSON, true); // true means hash array instead of object
@@ -288,21 +232,17 @@ class WizardHelper
{
$oWizard = new UIWizard(null, $oAttDef->GetLinkedClass());
$aWizardSteps = $oWizard->GetWizardStructure();
$aFields = array();
$aFields = [];
$sExtKeyToMeCode = $oAttDef->GetExtKeyToMe();
// Retrieve as a flat list, all the attributes that are needed to create
// an object of the linked class and put them into a flat array, except
// the attribute 'ext_key_to_me' which is a constant in our case
foreach($aWizardSteps as $sDummy => $aMainSteps)
{
foreach ($aWizardSteps as $sDummy => $aMainSteps) {
// 2 entries: 'mandatory' and 'optional'
foreach($aMainSteps as $aSteps)
{
foreach ($aMainSteps as $aSteps) {
// One entry for each step of the wizard
foreach($aSteps as $sAttCode)
{
if ($sAttCode != $sExtKeyToMeCode)
{
foreach ($aSteps as $sAttCode) {
if ($sAttCode != $sExtKeyToMeCode) {
$aFields[] = $sAttCode;
}
}
@@ -316,20 +256,20 @@ class WizardHelper
return $this->m_aData['m_sClass'];
}
public function GetFormPrefix()
{
return $this->m_aData['m_sFormPrefix'];
}
public function GetFormPrefix()
{
return $this->m_aData['m_sFormPrefix'];
}
public function GetInitialState()
{
return isset($this->m_aData['m_sInitialState']) ? $this->m_aData['m_sInitialState'] : null;
}
public function GetInitialState()
{
return isset($this->m_aData['m_sInitialState']) ? $this->m_aData['m_sInitialState'] : null;
}
public function GetStimulus()
{
return isset($this->m_aData['m_sStimulus']) ? $this->m_aData['m_sStimulus'] : null;
}
public function GetStimulus()
{
return isset($this->m_aData['m_sStimulus']) ? $this->m_aData['m_sStimulus'] : null;
}
public function GetIdForField($sFieldName)
{
@@ -337,8 +277,7 @@ class WizardHelper
// It may happen that the field we'd like to update does not
// exist in the form. For example, if the field should be hidden/read-only
// in the current state of the object
if (isset($this->m_aData['m_oFieldsMap'][$sFieldName]))
{
if (isset($this->m_aData['m_oFieldsMap'][$sFieldName])) {
$sResult = $this->m_aData['m_oFieldsMap'][$sFieldName];
}
@@ -362,12 +301,14 @@ class WizardHelper
$sWizardHelperJsVar = (!is_null($this->m_aData['m_sWizHelperJsVarName'])) ? utils::Sanitize($this->m_aData['m_sWizHelperJsVarName'], '', utils::ENUM_SANITIZATION_FILTER_PARAMETER) : 'oWizardHelper'.$this->GetFormPrefix();
$sWizardHelperJson = $this->ToJSON();
$oPage->add_script(<<<JS
$oPage->add_script(
<<<JS
{$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson};
{$sWizardHelperJsVar}.UpdateFields();
JS
);
$oPage->add_ready_script(<<<JS
$oPage->add_ready_script(
<<<JS
if ({$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve !== null){
{$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve();
}

View File

@@ -556,7 +556,7 @@ class ActionEmail extends ActionNotification
$oLog->Set('trigger_id', $oTrigger->GetKey());
$oLog->Set('action_id', $this->GetKey());
$oLog->Set('object_id', $aContextArgs['this->object()']->GetKey());
$oLog->Set('object_class', get_class($aContextArgs['this->object()']));
$oLog->Set('object_class', get_class($aContextArgs['this->object()']));
// Must be inserted now so that it gets a valid id that will make the link
// between an eventual asynchronous task (queued) and the log
$oLog->DBInsertNoReload();

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -56,28 +57,28 @@ class BulkExportResult extends DBObject
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => 'core/cmdb',
"key_type" => 'autoincrement',
"name_attcode" => array('created'),
"name_attcode" => ['created'],
"state_attcode" => '',
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => 'priv_bulk_export_result',
"db_key_field" => 'id',
"db_finalclass_field" => '',
"display_template" => '',
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("user_id", array("allowed_values"=>null, "sql"=>"user_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("chunk_size", array("allowed_values"=>null, "sql"=>"chunk_size", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("format", array("allowed_values"=>null, "sql"=>"format", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("temp_file_path", array("allowed_values"=>null, "sql"=>"temp_file_path", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("search", array("allowed_values"=>null, "sql"=>"search", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("status_info", array("allowed_values"=>null, "sql"=>"status_info", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("localize_output", array("allowed_values"=>null, "sql"=>"localize_output", "default_value"=>true, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("created", ["allowed_values" => null, "sql" => "created", "default_value" => "NOW()", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("user_id", ["allowed_values" => null, "sql" => "user_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("chunk_size", ["allowed_values" => null, "sql" => "chunk_size", "default_value" => 0, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("format", ["allowed_values" => null, "sql" => "format", "default_value" => '', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("temp_file_path", ["allowed_values" => null, "sql" => "temp_file_path", "default_value" => '', "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLongText("search", ["allowed_values" => null, "sql" => "search", "default_value" => '', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLongText("status_info", ["allowed_values" => null, "sql" => "status_info", "default_value" => '', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeBoolean("localize_output", ["allowed_values" => null, "sql" => "localize_output", "default_value" => true, "is_null_allowed" => true, "depends_on" => []]));
}
@@ -100,23 +101,21 @@ class BulkExportResultGC implements iBackgroundProcess
{
public function GetPeriodicity()
{
return 24*3600; // seconds
return 24 * 3600; // seconds
}
public function Process($iTimeLimit)
{
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time() - 24*3600); // Every BulkExportResult older than one day will be deleted
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time() - 24 * 3600); // Every BulkExportResult older than one day will be deleted
$sOQL = "SELECT BulkExportResult WHERE created < '$sDateLimit'";
$iProcessed = 0;
while (time() < $iTimeLimit)
{
while (time() < $iTimeLimit) {
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array('BulkExportResult' => array('temp_file_path')));
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), ['created' => true] /* order by*/, [], null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(['BulkExportResult' => ['temp_file_path']]);
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
if (is_null($oResult)) {
// Nothing to be done
break;
}
@@ -160,28 +159,24 @@ abstract class BulkExport
$this->bLocalizeOutput = false;
}
/**
* Find the first class capable of exporting the data in the given format
*
* @param string $sFormatCode The lowercase format (e.g. html, csv, spreadsheet, xlsx, xml, json, pdf...)
* @param DBSearch $oSearch The search/filter defining the set of objects to export or null when listing the supported formats
*
* @return BulkExport|null
* @throws ReflectionException
*/
static public function FindExporter($sFormatCode, $oSearch = null)
/**
* Find the first class capable of exporting the data in the given format
*
* @param string $sFormatCode The lowercase format (e.g. html, csv, spreadsheet, xlsx, xml, json, pdf...)
* @param DBSearch $oSearch The search/filter defining the set of objects to export or null when listing the supported formats
*
* @return BulkExport|null
* @throws ReflectionException
*/
public static function FindExporter($sFormatCode, $oSearch = null)
{
foreach(get_declared_classes() as $sPHPClass)
{
foreach (get_declared_classes() as $sPHPClass) {
$oRefClass = new ReflectionClass($sPHPClass);
if ($oRefClass->isSubclassOf('BulkExport') && !$oRefClass->isAbstract())
{
if ($oRefClass->isSubclassOf('BulkExport') && !$oRefClass->isAbstract()) {
/** @var BulkExport $oBulkExporter */
$oBulkExporter = new $sPHPClass();
if ($oBulkExporter->IsFormatSupported($sFormatCode, $oSearch))
{
if ($oSearch)
{
if ($oBulkExporter->IsFormatSupported($sFormatCode, $oSearch)) {
if ($oSearch) {
$oBulkExporter->SetObjectList($oSearch);
}
return $oBulkExporter;
@@ -191,37 +186,34 @@ abstract class BulkExport
return null;
}
/**
* Find the exporter corresponding to the given persistent token
*
* @param int $iPersistentToken The identifier of the BulkExportResult object storing the information
*
* @return BulkExport|null
* @throws ArchivedObjectException
* @throws CoreException
* @throws ReflectionException
*/
static public function FindExporterFromToken($iPersistentToken = null)
/**
* Find the exporter corresponding to the given persistent token
*
* @param int $iPersistentToken The identifier of the BulkExportResult object storing the information
*
* @return BulkExport|null
* @throws ArchivedObjectException
* @throws CoreException
* @throws ReflectionException
*/
public static function FindExporterFromToken($iPersistentToken = null)
{
$oBulkExporter = null;
$oInfo = MetaModel::GetObject('BulkExportResult', $iPersistentToken, false);
if ($oInfo && ($oInfo->Get('user_id') == UserRights::GetUserId()))
{
if ($oInfo && ($oInfo->Get('user_id') == UserRights::GetUserId())) {
$sFormatCode = $oInfo->Get('format');
$aStatusInfo = json_decode($oInfo->Get('status_info'),true);
$aStatusInfo = json_decode($oInfo->Get('status_info'), true);
$oSearch = DBObjectSearch::unserialize($oInfo->Get('search'));
$oSearch->SetShowObsoleteData($aStatusInfo['show_obsolete_data']);
$oBulkExporter = self::FindExporter($sFormatCode, $oSearch);
if ($oBulkExporter)
{
if ($oBulkExporter) {
$oBulkExporter->SetFormat($sFormatCode);
$oBulkExporter->SetObjectList($oSearch);
$oBulkExporter->SetChunkSize($oInfo->Get('chunk_size'));
$oBulkExporter->SetStatusInfo($aStatusInfo);
$oBulkExporter->SetLocalizeOutput($oInfo->Get('localize_output'));
$oBulkExporter->SetLocalizeOutput($oInfo->Get('localize_output'));
$oBulkExporter->sTmpFile = $oInfo->Get('temp_file_path');
$oBulkExporter->oBulkExportResult = $oInfo;
@@ -236,13 +228,11 @@ abstract class BulkExport
*/
public function AppendToTmpFile($data)
{
if ($this->sTmpFile == '')
{
if ($this->sTmpFile == '') {
$this->sTmpFile = $this->MakeTmpFile($this->GetFileExtension());
}
$hFile = fopen($this->sTmpFile, 'ab');
if ($hFile !== false)
{
if ($hFile !== false) {
fwrite($hFile, $data);
fclose($hFile);
}
@@ -257,15 +247,13 @@ abstract class BulkExport
* Lists all possible export formats. The output is a hash array in the form: 'format_code' => 'localized format label'
* @return array :string
*/
static public function FindSupportedFormats()
public static function FindSupportedFormats()
{
$aSupportedFormats = array();
foreach(get_declared_classes() as $sPHPClass)
{
$aSupportedFormats = [];
foreach (get_declared_classes() as $sPHPClass) {
$oRefClass = new ReflectionClass($sPHPClass);
if ($oRefClass->isSubClassOf('BulkExport') && !$oRefClass->isAbstract())
{
$oBulkExporter = new $sPHPClass;
if ($oRefClass->isSubClassOf('BulkExport') && !$oRefClass->isAbstract()) {
$oBulkExporter = new $sPHPClass();
$aFormats = $oBulkExporter->GetSupportedFormats();
$aSupportedFormats = array_merge($aSupportedFormats, $aFormats);
}
@@ -282,13 +270,13 @@ abstract class BulkExport
$this->iChunkSize = $iChunkSize;
}
/**
* @param $bLocalizeOutput
*/
public function SetLocalizeOutput($bLocalizeOutput)
{
$this->bLocalizeOutput = $bLocalizeOutput;
}
/**
* @param $bLocalizeOutput
*/
public function SetLocalizeOutput($bLocalizeOutput)
{
$this->bLocalizeOutput = $bLocalizeOutput;
}
/**
* (non-PHPdoc)
@@ -320,10 +308,9 @@ abstract class BulkExport
*/
public function GetSupportedFormats()
{
return array(); // return array('csv' => Dict::S('UI:ExportFormatCSV'));
return []; // return array('csv' => Dict::S('UI:ExportFormatCSV'));
}
public function SetHttpHeaders(WebPage $oPage)
{
}
@@ -347,14 +334,13 @@ abstract class BulkExport
public function SaveState()
{
if ($this->oBulkExportResult === null)
{
if ($this->oBulkExportResult === null) {
$this->oBulkExportResult = new BulkExportResult();
$this->oBulkExportResult->Set('format', $this->sFormatCode);
$this->oBulkExportResult->Set('search', $this->oSearch->serialize());
$this->oBulkExportResult->Set('chunk_size', $this->iChunkSize);
$this->oBulkExportResult->Set('localize_output', $this->bLocalizeOutput);
}
$this->oBulkExportResult->Set('localize_output', $this->bLocalizeOutput);
}
$this->oBulkExportResult->Set('status_info', json_encode($this->GetStatusInfo()));
$this->oBulkExportResult->Set('temp_file_path', $this->sTmpFile);
utils::PushArchiveMode(false);
@@ -365,11 +351,9 @@ abstract class BulkExport
public function Cleanup()
{
if (($this->oBulkExportResult && (!$this->oBulkExportResult->IsNew())))
{
if (($this->oBulkExportResult && (!$this->oBulkExportResult->IsNew()))) {
$sFilename = $this->oBulkExportResult->Get('temp_file_path');
if ($sFilename != '')
{
if ($sFilename != '') {
@unlink($sFilename);
}
utils::PushArchiveMode(false);
@@ -380,7 +364,7 @@ abstract class BulkExport
public function EnumFormParts()
{
return array();
return [];
}
/**
@@ -464,25 +448,21 @@ abstract class BulkExport
*/
protected function MakeTmpFile($sExtension)
{
if(!is_dir(utils::GetDataPath()."bulk_export"))
{
if (!is_dir(utils::GetDataPath()."bulk_export")) {
@mkdir(utils::GetDataPath()."bulk_export", 0777, true /* recursive */);
clearstatcache();
}
if (!is_writable(utils::GetDataPath()."bulk_export"))
{
if (!is_writable(utils::GetDataPath()."bulk_export")) {
throw new Exception('Data directory "'.utils::GetDataPath().'bulk_export" could not be written.');
}
$iNum = rand();
do
{
do {
$iNum++;
$sToken = sprintf("%08x", $iNum);
$sFileName = utils::GetDataPath()."bulk_export/$sToken.".$sExtension;
$hFile = @fopen($sFileName, 'x');
}
while($hFile === false);
} while ($hFile === false);
fclose($hFile);
return $sFileName;
@@ -492,8 +472,7 @@ abstract class BulkExport
// The built-in exports
require_once(APPROOT.'core/tabularbulkexport.class.inc.php');
require_once(APPROOT.'core/htmlbulkexport.class.inc.php');
if (extension_loaded('gd'))
{
if (extension_loaded('gd')) {
// PDF export - via TCPDF - requires GD
require_once(APPROOT.'core/pdfbulkexport.class.inc.php');
}
@@ -501,4 +480,3 @@ require_once(APPROOT.'core/csvbulkexport.class.inc.php');
require_once(APPROOT.'core/excelbulkexport.class.inc.php');
require_once(APPROOT.'core/spreadsheetbulkexport.class.inc.php');
require_once(APPROOT.'core/xmlbulkexport.class.inc.php');

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Class cmdbObject
*
@@ -24,7 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* cmdbObjectClass
* the file to include, then the core is yours
@@ -148,8 +147,7 @@ abstract class CMDBObject extends DBObject
*/
public static function GetCurrentChange($bAutoCreate = true)
{
if ($bAutoCreate && is_null(self::$m_oCurrChange))
{
if ($bAutoCreate && is_null(self::$m_oCurrChange)) {
self::CreateChange();
}
return self::$m_oCurrChange;
@@ -214,7 +212,7 @@ abstract class CMDBObject extends DBObject
return CMDBChange::GetCurrentUserName();
} else {
//N°5135 - add impersonation information in activity log/current cmdb change
if (UserRights::IsImpersonated()){
if (UserRights::IsImpersonated()) {
return sprintf("%s (%s)", CMDBChange::GetCurrentUserName(), self::$m_sInfo);
} else {
return self::$m_sInfo;
@@ -234,12 +232,9 @@ abstract class CMDBObject extends DBObject
if (is_null(self::$m_sUserId)
//N°5135 - indicate impersonation inside changelogs
&& (false === UserRights::IsImpersonated())
)
{
) {
return CMDBChange::GetCurrentUserId();
}
else
{
} else {
return self::$m_sUserId;
}
}
@@ -249,12 +244,9 @@ abstract class CMDBObject extends DBObject
*/
protected static function GetTrackOrigin()
{
if (is_null(self::$m_sOrigin))
{
if (is_null(self::$m_sOrigin)) {
return 'interactive';
}
else
{
} else {
return self::$m_sOrigin;
}
}
@@ -382,14 +374,10 @@ abstract class CMDBObject extends DBObject
// $aValues is an array of $sAttCode => $value
//
foreach ($aValues as $sAttCode=> $value)
{
if (array_key_exists($sAttCode, $aOrigValues))
{
foreach ($aValues as $sAttCode => $value) {
if (array_key_exists($sAttCode, $aOrigValues)) {
$original = $aOrigValues[$sAttCode];
}
else
{
} else {
$original = null;
}
$this->RecordAttChange($sAttCode, $original, $value);
@@ -431,8 +419,7 @@ abstract class CMDBObject extends DBObject
$bOriginal = $this->Get('archive_flag');
parent::DBArchive();
if (!$bOriginal)
{
if (!$bOriginal) {
utils::PushArchiveMode(false);
$this->RecordAttChange('archive_flag', false, true);
utils::PopArchiveMode();
@@ -445,8 +432,7 @@ abstract class CMDBObject extends DBObject
$bOriginal = $this->Get('archive_flag');
parent::DBUnarchive();
if ($bOriginal)
{
if ($bOriginal) {
utils::PushArchiveMode(false);
$this->RecordAttChange('archive_flag', true, false);
utils::PopArchiveMode();
@@ -454,8 +440,6 @@ abstract class CMDBObject extends DBObject
}
}
/**
* TODO: investigate how to get rid of this class that was made to workaround some language limitation... or a poor design!
*
@@ -471,7 +455,7 @@ class CMDBObjectSet extends DBObjectSet
// just to get the right object class in return.
// I have to think again to those things: maybe it will work fine if a have a constructor define here (?)
static public function FromScratch($sClass)
public static function FromScratch($sClass)
{
$oFilter = new DBObjectSearch($sClass);
$oFilter->AddConditionExpression(new FalseExpression());
@@ -483,14 +467,14 @@ class CMDBObjectSet extends DBObjectSet
// create an object set ex nihilo
// input = array of objects
static public function FromArray($sClass, $aObjects)
public static function FromArray($sClass, $aObjects)
{
$oRetSet = self::FromScratch($sClass);
$oRetSet->AddObjectArray($aObjects, $sClass);
return $oRetSet;
}
static public function FromArrayAssoc($aClasses, $aObjects)
public static function FromArrayAssoc($aClasses, $aObjects)
{
// In a perfect world, we should create a complete tree of DBObjectSearch,
// but as we lack most of the information related to the objects,
@@ -502,8 +486,7 @@ class CMDBObjectSet extends DBObjectSet
$oRetSet = new CMDBObjectSet($oFilter);
$oRetSet->m_bLoaded = true; // no DB load
foreach($aObjects as $rowIndex => $aObjectsByClassAlias)
{
foreach ($aObjects as $rowIndex => $aObjectsByClassAlias) {
$oRetSet->AddObjectExtended($aObjectsByClassAlias);
}
return $oRetSet;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -19,7 +20,6 @@
*
*/
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
@@ -68,7 +68,6 @@ define('DEFAULT_LOG_WEB_SERVICE', true);
define('DEFAULT_QUERY_CACHE_ENABLED', true);
define('DEFAULT_MIN_DISPLAY_LIMIT', 20);
define('DEFAULT_MAX_DISPLAY_LIMIT', 30);
define('DEFAULT_STANDARD_RELOAD_INTERVAL', 5 * 60);
@@ -441,14 +440,14 @@ class Config
'show_in_conf_sample' => true,
],
'export_pdf_font' => [ // @since 2.7.0 PR #49 / N°1947
'type' => 'string',
'description' => 'Font used when generating a PDF file',
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
'type' => 'string',
'description' => 'Font used when generating a PDF file',
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'access_mode' => [
'type' => 'integer',
@@ -891,7 +890,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'forgot_password.url' => [
'forgot_password.url' => [
'type' => 'string',
'description' => 'Set this value to your "forgot password" service URL if it should be handled out of '.ITOP_APPLICATION_SHORT.'. Note that it will apply to all users (iTop users, LDAP users, ...)',
'default' => '',
@@ -1803,7 +1802,7 @@ class Config
'default' => ITOP_APPLICATION.'/'.ITOP_VERSION,
'source_of_value' => '',
'show_in_conf_sample' => false,
]
],
];
public function IsProperty($sPropCode)
@@ -1811,7 +1810,6 @@ class Config
return (array_key_exists($sPropCode, $this->m_aSettings));
}
/**
* @return string identifier that can be used for example to name WebStorage/SessionStorage keys (they
* are related to a whole domain, and a domain can host multiple itop)
@@ -1845,8 +1843,7 @@ class Config
$value = $this->oConfigPlaceholdersResolver->Resolve($value);
switch ($sType)
{
switch ($sType) {
case 'bool':
$value = (bool)$value;
break;
@@ -1854,7 +1851,7 @@ class Config
$value = (string)$value;
break;
case 'integer':
$value = (integer)$value;
$value = (int)$value;
break;
case 'float':
$value = (float)$value;
@@ -1862,11 +1859,10 @@ class Config
case 'array':
break;
default:
throw new CoreException('Unknown type for setting', array('property' => $sPropCode, 'type' => $sType));
throw new CoreException('Unknown type for setting', ['property' => $sPropCode, 'type' => $sType]);
}
if ($this->m_aSettings[$sPropCode]['value'] == $value)
{
if ($this->m_aSettings[$sPropCode]['value'] == $value) {
//when you set the exact same value than the previous one, then, you still can preserve the non evaluated version and so on preserve vars/jokers.
$bCanOverride = true;
}
@@ -2008,15 +2004,13 @@ class Config
$this->oConfigPlaceholdersResolver = new ConfigPlaceholdersResolver();
$this->m_sFile = $sConfigFile;
if (is_null($sConfigFile))
{
if (is_null($sConfigFile)) {
$bLoadConfig = false;
}
$this->m_aAddons = [];
foreach ($this->m_aSettings as $sPropCode => $aSettingInfo)
{
foreach ($this->m_aSettings as $sPropCode => $aSettingInfo) {
$this->m_aSettings[$sPropCode]['value'] = $aSettingInfo['default'];
}
@@ -2032,7 +2026,7 @@ class Config
$this->m_sDefaultLanguage = 'EN US';
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
$this->m_aCharsets = array();
$this->m_aCharsets = [];
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
$this->m_iPasswordHashAlgo = DEFAULT_HASH_ALGO;
$this->m_sAppSecret = bin2hex(random_bytes(16));
@@ -2042,10 +2036,9 @@ class Config
$this->m_sEncryptionLibrary = isset($aEncryptParams['lib']) ? $aEncryptParams['lib'] : DEFAULT_ENCRYPTION_LIB;
$this->m_sEncryptionKey = isset($aEncryptParams['key']) ? $aEncryptParams['key'] : DEFAULT_ENCRYPTION_KEY;
$this->m_aModuleSettings = array();
$this->m_aModuleSettings = [];
if ($bLoadConfig)
{
if ($bLoadConfig) {
$this->Load($sConfigFile);
$this->Verify();
}
@@ -2074,14 +2067,14 @@ class Config
*/
protected function CheckFile($sPurpose, $sFileName)
{
if (!file_exists($sFileName))
{
throw new ConfigException("Could not find $sPurpose file", array('file' => $sFileName));
if (!file_exists($sFileName)) {
throw new ConfigException("Could not find $sPurpose file", ['file' => $sFileName]);
}
if (!is_readable($sFileName))
{
throw new ConfigException("Could not read $sPurpose file (the file exists but cannot be read). Do you have the rights to access this file?",
array('file' => $sFileName));
if (!is_readable($sFileName)) {
throw new ConfigException(
"Could not read $sPurpose file (the file exists but cannot be read). Do you have the rights to access this file?",
['file' => $sFileName]
);
}
}
@@ -2108,64 +2101,58 @@ class Config
// This does not work on several lines
// preg_match('/^<\\?php(.*)\\?'.'>$/', $sConfigCode, $aMatches)...
// So, I've implemented a solution suggested in the PHP doc (search for phpWrapper)
try
{
try {
ob_start();
eval('?'.'>'.trim($sConfigCode));
$sNoise = trim(ob_get_contents());
ob_end_clean();
}
catch (Error $e)
{
} catch (Error $e) {
// PHP 7
throw new ConfigException('Error in configuration file',
array('file' => $sConfigFile, 'error' => $e->getMessage().' at line '.$e->getLine()));
}
catch (Exception $e)
{
throw new ConfigException(
'Error in configuration file',
['file' => $sConfigFile, 'error' => $e->getMessage().' at line '.$e->getLine()]
);
} catch (Exception $e) {
// well, never reach in case of parsing error :-(
// will be improved in PHP 6 ?
throw new ConfigException('Error in configuration file',
array('file' => $sConfigFile, 'error' => $e->getMessage()));
throw new ConfigException(
'Error in configuration file',
['file' => $sConfigFile, 'error' => $e->getMessage()]
);
}
if (strlen($sNoise) > 0)
{
if (strlen($sNoise) > 0) {
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
throw new ConfigException('Syntax error in configuration file',
array('file' => $sConfigFile, 'error' => '<tt>'.utils::EscapeHtml($sNoise, ENT_QUOTES).'</tt>'));
throw new ConfigException(
'Syntax error in configuration file',
['file' => $sConfigFile, 'error' => '<tt>'.utils::EscapeHtml($sNoise, ENT_QUOTES).'</tt>']
);
}
if (!isset($MySettings) || !is_array($MySettings))
{
throw new ConfigException('Missing array in configuration file',
array('file' => $sConfigFile, 'expected' => '$MySettings'));
if (!isset($MySettings) || !is_array($MySettings)) {
throw new ConfigException(
'Missing array in configuration file',
['file' => $sConfigFile, 'expected' => '$MySettings']
);
}
if (!array_key_exists('addons', $MyModules) || !array_key_exists('user rights', $MyModules['addons']))
{
if (!array_key_exists('addons', $MyModules) || !array_key_exists('user rights', $MyModules['addons'])) {
// Add one, by default
$MyModules['addons']['user rights'] = 'addons/userrights/userrightsprofile.class.inc.php';
$this->m_aAddons = $MyModules['addons'];
}
foreach ($MySettings as $sPropCode => $rawvalue)
{
if ($this->IsProperty($sPropCode))
{
if (is_string($rawvalue))
{
foreach ($MySettings as $sPropCode => $rawvalue) {
if ($this->IsProperty($sPropCode)) {
if (is_string($rawvalue)) {
$value = trim($rawvalue);
}
else
{
} else {
$value = $rawvalue;
}
$this->Set($sPropCode, $value, $sConfigFile, true);
}
}
if (file_exists(READONLY_MODE_FILE))
{
if (file_exists(READONLY_MODE_FILE)) {
$this->Set('access_mode', ACCESS_READONLY, READONLY_MODE_FILE);
}
@@ -2181,14 +2168,14 @@ class Config
$this->m_iFastReloadInterval = isset($MySettings['fast_reload_interval']) ? trim($MySettings['fast_reload_interval']) : DEFAULT_FAST_RELOAD_INTERVAL;
$this->m_bSecureConnectionRequired = isset($MySettings['secure_connection_required']) ? (bool)trim($MySettings['secure_connection_required']) : DEFAULT_SECURE_CONNECTION_REQUIRED;
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : array();
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : [];
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
$this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : array();
$this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : [];
$this->m_iPasswordHashAlgo = isset($MySettings['password_hash_algo']) ? $MySettings['password_hash_algo'] : $this->m_iPasswordHashAlgo;
}
@@ -2210,8 +2197,7 @@ class Config
*/
public function GetModuleSetting($sModule, $sProperty, $defaultvalue = null)
{
if (isset($this->m_aModuleSettings[$sModule][$sProperty]))
{
if (isset($this->m_aModuleSettings[$sModule][$sProperty])) {
return $this->m_aModuleSettings[$sModule][$sProperty];
}
@@ -2233,11 +2219,9 @@ class Config
public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null)
{
$ret = $defaultvalue;
if (class_exists('ModulesXMLParameters'))
{
if (class_exists('ModulesXMLParameters')) {
$aAllParams = ModulesXMLParameters::GetData($sModule);
if (array_key_exists($sProperty, $aAllParams))
{
if (array_key_exists($sProperty, $aAllParams)) {
$ret = $aAllParams[$sProperty];
}
}
@@ -2255,10 +2239,10 @@ class Config
*/
public function GetAddons()
{
if (array_key_exists("user rights", $this->m_aAddons)) {
if (array_key_exists("user rights", $this->m_aAddons)) {
return $this->m_aAddons;
} else {
return array_merge($this->m_aAddons,['user rights' => 'addons/userrights/userrightsprofile.class.inc.php']);
return array_merge($this->m_aAddons, ['user rights' => 'addons/userrights/userrightsprofile.class.inc.php']);
}
}
@@ -2438,7 +2422,7 @@ class Config
public function AddAllowedLoginTypes($sLoginMode)
{
$aAllowedLoginTypes = $this->GetAllowedLoginTypes();
if (in_array($sLoginMode, $aAllowedLoginTypes)){
if (in_array($sLoginMode, $aAllowedLoginTypes)) {
return;
}
@@ -2461,7 +2445,6 @@ class Config
$this->m_sAppSecret = $sKey;
}
public function SetCSVImportCharsets($aCharsets)
{
$this->m_aCharsets = $aCharsets;
@@ -2474,12 +2457,9 @@ class Config
public function GetLoadedFile()
{
if (is_null($this->m_sFile))
{
if (is_null($this->m_sFile)) {
return '';
}
else
{
} else {
return $this->m_sFile;
}
}
@@ -2491,9 +2471,8 @@ class Config
*/
public function ToArray()
{
$aSettings = array();
foreach ($this->m_aSettings as $sPropCode => $aSettingInfo)
{
$aSettings = [];
foreach ($this->m_aSettings as $sPropCode => $aSettingInfo) {
$aSettings[$sPropCode] = $aSettingInfo['value'];
}
$aSettings['log_global'] = $this->m_bLogGlobal;
@@ -2514,15 +2493,12 @@ class Config
$aSettings['csv_import_charsets'] = $this->m_aCharsets;
$aSettings['password_hash_algo'] = $this->m_iPasswordHashAlgo;
foreach ($this->m_aModuleSettings as $sModule => $aProperties)
{
foreach ($aProperties as $sProperty => $value)
{
foreach ($this->m_aModuleSettings as $sModule => $aProperties) {
foreach ($aProperties as $sProperty => $value) {
$aSettings['module_settings'][$sModule][$sProperty] = $value;
}
}
foreach ($this->m_aAddons as $sKey => $sFile)
{
foreach ($this->m_aAddons as $sKey => $sFile) {
$aSettings['addon_list'][] = $sFile;
}
@@ -2541,22 +2517,18 @@ class Config
*/
public function WriteToFile($sFileName = '')
{
if (empty($sFileName))
{
if (empty($sFileName)) {
$sFileName = $this->m_sFile;
}
$oHandle = null;
$sConfig = null;
if ($this->m_sFile !== null && is_file($this->m_sFile))
{
if ($this->m_sFile !== null && is_file($this->m_sFile)) {
$oHandle = fopen($this->m_sFile, 'r');
$index = 0;
while (!flock($oHandle, LOCK_SH))
{
if ($index > 50)
{
throw new ConfigException("Could not read to configuration file", array('file' => $this->m_sFile));
while (!flock($oHandle, LOCK_SH)) {
if ($index > 50) {
throw new ConfigException("Could not read to configuration file", ['file' => $this->m_sFile]);
}
usleep(100000);
$index++;
@@ -2564,61 +2536,59 @@ class Config
$sConfig = file_get_contents($this->m_sFile);
}
$this->oItopConfigParser = new iTopConfigParser($sConfig);
if ($oHandle !==null)
{
if ($oHandle !== null) {
flock($oHandle, LOCK_UN);
}
$hFile = @fopen($sFileName, 'w');
if ($hFile !== false)
{
if ($hFile !== false) {
fwrite($hFile, "<?php\n");
fwrite($hFile, "\n/**\n");
fwrite($hFile, " *\n");
fwrite($hFile, " * Configuration file, generated by the ".ITOP_APPLICATION." configuration wizard\n");
fwrite($hFile, " *\n");
fwrite($hFile,
" * The file is used in MetaModel::LoadConfig() which does all the necessary initialization job\n");
fwrite(
$hFile,
" * The file is used in MetaModel::LoadConfig() which does all the necessary initialization job\n"
);
fwrite($hFile, " *\n");
fwrite($hFile, " */\n");
$aConfigSettings = $this->m_aSettings;
// Old fashioned boolean settings
$aBoolValues = array(
$aBoolValues = [
'log_global' => $this->m_bLogGlobal,
'log_notification' => $this->m_bLogNotification,
'log_issue' => $this->m_bLogIssue,
'log_web_service' => $this->m_bLogWebService,
'secure_connection_required' => $this->m_bSecureConnectionRequired,
);
foreach ($aBoolValues as $sKey => $bValue)
{
$aConfigSettings[$sKey] = array(
];
foreach ($aBoolValues as $sKey => $bValue) {
$aConfigSettings[$sKey] = [
'show_in_conf_sample' => true,
'type' => 'bool',
'value' => $bValue,
);
];
}
// Old fashioned integer settings
$aIntValues = array(
$aIntValues = [
'fast_reload_interval' => $this->m_iFastReloadInterval,
'max_display_limit' => $this->m_iMaxDisplayLimit,
'min_display_limit' => $this->m_iMinDisplayLimit,
'standard_reload_interval' => $this->m_iStandardReloadInterval,
);
foreach ($aIntValues as $sKey => $iValue)
{
$aConfigSettings[$sKey] = array(
];
foreach ($aIntValues as $sKey => $iValue) {
$aConfigSettings[$sKey] = [
'show_in_conf_sample' => true,
'type' => 'integer',
'value' => $iValue,
);
];
}
// Old fashioned remaining values
$aOtherValues = array(
$aOtherValues = [
'default_language' => $this->m_sDefaultLanguage,
'allowed_login_types' => $this->m_sAllowedLoginTypes,
'ext_auth_variable' => $this->m_sExtAuthVariable,
@@ -2626,45 +2596,37 @@ class Config
'encryption_library' => $this->m_sEncryptionLibrary,
'csv_import_charsets' => $this->m_aCharsets,
'password_hash_algo' => $this->m_iPasswordHashAlgo,
);
foreach ($aOtherValues as $sKey => $value)
{
$aConfigSettings[$sKey] = array(
];
foreach ($aOtherValues as $sKey => $value) {
$aConfigSettings[$sKey] = [
'show_in_conf_sample' => true,
'type' => is_string($value) ? 'string' : 'mixed',
'value' => $value,
);
];
}
ksort($aConfigSettings);
fwrite($hFile, "\$MySettings = array(\n");
foreach ($aConfigSettings as $sPropCode => $aSettingInfo)
{
foreach ($aConfigSettings as $sPropCode => $aSettingInfo) {
// Write all values that are either always visible or present in the cloned config file
if ($aSettingInfo['show_in_conf_sample'] || (!empty($aSettingInfo['source_of_value']) && ($aSettingInfo['source_of_value'] != 'unknown')))
{
if ($aSettingInfo['show_in_conf_sample'] || (!empty($aSettingInfo['source_of_value']) && ($aSettingInfo['source_of_value'] != 'unknown'))) {
fwrite($hFile, "\n");
if (isset($aSettingInfo['description']))
{
if (isset($aSettingInfo['description'])) {
fwrite($hFile, "\t// $sPropCode: {$aSettingInfo['description']}\n");
}
if (isset($aSettingInfo['default']))
{
$sComment = self::PrettyVarExport(null,$aSettingInfo['default'], "\t//\t\t", true);
fwrite($hFile,"\t//\tdefault: {$sComment}\n");
if (isset($aSettingInfo['default'])) {
$sComment = self::PrettyVarExport(null, $aSettingInfo['default'], "\t//\t\t", true);
fwrite($hFile, "\t//\tdefault: {$sComment}\n");
}
if (isset($this->m_aCanOverrideSettings[$sPropCode]) && $this->m_aCanOverrideSettings[$sPropCode])
{
if (isset($this->m_aCanOverrideSettings[$sPropCode]) && $this->m_aCanOverrideSettings[$sPropCode]) {
$aParserValue = $this->oItopConfigParser->GetVarValue('MySettings', $sPropCode);
}
else
{
} else {
$aParserValue = null;
}
$sSeenAs = self::PrettyVarExport($aParserValue,$aSettingInfo['value'], "\t");
$sSeenAs = self::PrettyVarExport($aParserValue, $aSettingInfo['value'], "\t");
fwrite($hFile, "\t'$sPropCode' => $sSeenAs,\n");
}
}
@@ -2673,11 +2635,9 @@ class Config
fwrite($hFile, "\n");
fwrite($hFile, "/**\n *\n * Modules specific settings\n *\n */\n");
fwrite($hFile, "\$MyModuleSettings = array(\n");
foreach ($this->m_aModuleSettings as $sModule => $aProperties)
{
foreach ($this->m_aModuleSettings as $sModule => $aProperties) {
fwrite($hFile, "\t'$sModule' => array (\n");
foreach ($aProperties as $sProperty => $value)
{
foreach ($aProperties as $sProperty => $value) {
$sNiceExport = self::PrettyVarExport($this->oItopConfigParser->GetVarValue('MyModuleSettings', $sProperty), $value, "\t\t");
fwrite($hFile, "\t\t'$sProperty' => $sNiceExport,\n");
}
@@ -2692,8 +2652,7 @@ class Config
fwrite($hFile, " */\n");
fwrite($hFile, "\$MyModules = array(\n");
$aParserValue = $this->oItopConfigParser->GetVarValue('MyModules', 'addons');
if ($aParserValue['found'])
{
if ($aParserValue['found']) {
fwrite($hFile, "\t'addons' => {$aParserValue['value']},\n");
}
fwrite($hFile, ");\n");
@@ -2704,10 +2663,8 @@ class Config
utils::SetConfig($this);
return $bReturn;
}
else
{
throw new ConfigException("Could not write to configuration file", array('file' => $sFileName));
} else {
throw new ConfigException("Could not write to configuration file", ['file' => $sFileName]);
}
}
@@ -2728,32 +2685,25 @@ class Config
*/
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
{
if (isset($aParamValues['application_path']))
{
if (isset($aParamValues['application_path'])) {
$this->Set('app_root_url', $aParamValues['application_path']);
}
if (isset($aParamValues['graphviz_path']))
{
if (isset($aParamValues['graphviz_path'])) {
$this->Set('graphviz_path', $aParamValues['graphviz_path']);
}
if (isset($aParamValues['mode']) && isset($aParamValues['language']))
{
if (($aParamValues['mode'] == 'install') || $this->GetDefaultLanguage() == '')
{
if (isset($aParamValues['mode']) && isset($aParamValues['language'])) {
if (($aParamValues['mode'] == 'install') || $this->GetDefaultLanguage() == '') {
$this->SetDefaultLanguage($aParamValues['language']);
}
}
if (isset($aParamValues['db_server']))
{
if (isset($aParamValues['db_server'])) {
$this->Set('db_host', $aParamValues['db_server']);
$this->Set('db_user', $aParamValues['db_user']);
$this->Set('db_pwd', $aParamValues['db_pwd']);
$sDBName = $aParamValues['db_name'];
if ($sDBName == '')
{
if ($sDBName == '') {
// Todo - obsolete after the transition to the new setup (2.0) is complete (WARNING: used by the designer)
if (isset($aParamValues['new_db_name']))
{
if (isset($aParamValues['new_db_name'])) {
$sDBName = $aParamValues['new_db_name'];
}
}
@@ -2761,39 +2711,29 @@ class Config
$this->Set('db_subname', $aParamValues['db_prefix']);
$bDbTlsEnabled = (bool)$aParamValues['db_tls_enabled'];
if ($bDbTlsEnabled)
{
if ($bDbTlsEnabled) {
$this->Set('db_tls.enabled', $bDbTlsEnabled, 'UpdateFromParams');
}
else
{
} else {
// disabled : we don't want parameter in the file
$this->Set('db_tls.enabled', $bDbTlsEnabled, null);
}
$sDbTlsCa = $bDbTlsEnabled ? $aParamValues['db_tls_ca'] : null;
if (isset($sDbTlsCa) && !empty($sDbTlsCa))
{
if (isset($sDbTlsCa) && !empty($sDbTlsCa)) {
$this->Set('db_tls.ca', $sDbTlsCa, 'UpdateFromParams');
}
else
{
} else {
// empty parameter : we don't want it in the file
$this->Set('db_tls.ca', null, null);
}
}
if (isset($aParamValues['selected_modules']))
{
if (isset($aParamValues['selected_modules'])) {
$aSelectedModules = explode(',', $aParamValues['selected_modules']);
}
else
{
} else {
$aSelectedModules = null;
}
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
if (isset($aParamValues['source_dir']))
{
if (isset($aParamValues['source_dir'])) {
$this->Set('source_dir', $aParamValues['source_dir']);
}
}
@@ -2811,8 +2751,7 @@ class Config
*/
public function UpdateIncludes($sModulesDir, $aSelectedModules = null)
{
if ($sModulesDir === null)
{
if ($sModulesDir === null) {
return;
}
@@ -2820,23 +2759,16 @@ class Config
$oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values
$aAddOns = $oEmptyConfig->GetAddOns();
$aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT.$sModulesDir));
foreach ($aModules as $sModuleId => $aModuleInfo)
{
list ($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules))
{
if (isset($aModuleInfo['settings']))
{
list ($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
foreach ($aModuleInfo['settings'] as $sProperty => $value)
{
if (isset($this->m_aModuleSettings[$sName][$sProperty]))
{
$aModules = ModuleDiscovery::GetAvailableModules([APPROOT.$sModulesDir]);
foreach ($aModules as $sModuleId => $aModuleInfo) {
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) {
if (isset($aModuleInfo['settings'])) {
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
foreach ($aModuleInfo['settings'] as $sProperty => $value) {
if (isset($this->m_aModuleSettings[$sName][$sProperty])) {
// Do nothing keep the original value
}
else
{
} else {
$this->SetModuleSetting($sName, $sProperty, $value);
}
}
@@ -2857,10 +2789,8 @@ class Config
*/
protected static function ChangePrefix(&$aStrings, $sSearchPrefix, $sNewPrefix)
{
foreach ($aStrings as &$sFile)
{
if (substr($sFile, 0, strlen($sSearchPrefix)) == $sSearchPrefix)
{
foreach ($aStrings as &$sFile) {
if (substr($sFile, 0, strlen($sSearchPrefix)) == $sSearchPrefix) {
$sFile = $sNewPrefix.substr($sFile, strlen($sSearchPrefix));
}
}
@@ -2891,22 +2821,19 @@ class Config
*/
protected static function PrettyVarExport($aParserValue, $value, $sIndentation, $bForceIndentation = false)
{
if (is_array($aParserValue) && $aParserValue['found'])
{
if (is_array($aParserValue) && $aParserValue['found']) {
return $aParserValue['value'];
}
$sExport = var_export($value, true);
$sNiceExport = str_replace(array("\r\n", "\n", "\r"), "\n".$sIndentation, trim($sExport));
if (!$bForceIndentation)
{
$sNiceExport = str_replace(["\r\n", "\n", "\r"], "\n".$sIndentation, trim($sExport));
if (!$bForceIndentation) {
/** @var array $aImported */
$aImported = null;
eval('$aImported='.$sNiceExport.';');
// Check if adding the identations at the beginning of each line
// did not modify the values (in case of a string containing a line break)
if ($aImported != $value)
{
if ($aImported != $value) {
$sNiceExport = $sExport;
}
}
@@ -2935,37 +2862,31 @@ class ConfigPlaceholdersResolver
public function Resolve($rawValue)
{
if (empty($this->aEnv['ITOP_CONFIG_PLACEHOLDERS']) && empty($this->aServer['ITOP_CONFIG_PLACEHOLDERS']))
{
if (empty($this->aEnv['ITOP_CONFIG_PLACEHOLDERS']) && empty($this->aServer['ITOP_CONFIG_PLACEHOLDERS'])) {
return $rawValue;
}
if (is_array($rawValue))
{
$aResolvedRawValue = array();
foreach ($rawValue as $key => $value)
{
if (is_array($rawValue)) {
$aResolvedRawValue = [];
foreach ($rawValue as $key => $value) {
$aResolvedRawValue[$key] = $this->Resolve($value);
}
return $aResolvedRawValue;
}
if (!is_string($rawValue))
{
if (!is_string($rawValue)) {
return $rawValue;
}
$sPattern = '/\%(env|server)\((\w+)\)(?:\?:(\w*))?\%/'; //3 capturing groups, ie `%env(HTTP_PORT)?:8080%` produce: `env` `HTTP_PORT` and `8080`.
if (! preg_match_all($sPattern, $rawValue, $aMatchesCollection, PREG_SET_ORDER))
{
if (! preg_match_all($sPattern, $rawValue, $aMatchesCollection, PREG_SET_ORDER)) {
return $rawValue;
}
$sValue = $rawValue;
foreach ($aMatchesCollection as $aMatches)
{
foreach ($aMatchesCollection as $aMatches) {
$sWholeMask = $aMatches[0];
$sSource = $aMatches[1];
$sKey = $aMatches[2];
@@ -2981,35 +2902,27 @@ class ConfigPlaceholdersResolver
private function Get($sSourceName, $sKey, $sDefault, $sWholeMask)
{
if ('env' == $sSourceName)
{
if ('env' == $sSourceName) {
$aSource = $this->aEnv;
}
else if ('server' == $sSourceName)
{
} elseif ('server' == $sSourceName) {
$aSource = $this->aServer;
}
else
{
} else {
$sErrorMessage = sprintf('unsupported source name "%s" into "%s"', $sSourceName, $sWholeMask);
IssueLog::Error($sErrorMessage, self::class, array($sSourceName, $sKey, $sDefault, $sWholeMask));
IssueLog::Error($sErrorMessage, self::class, [$sSourceName, $sKey, $sDefault, $sWholeMask]);
throw new ConfigException($sErrorMessage);
}
if (array_key_exists($sKey, $aSource))
{
if (array_key_exists($sKey, $aSource)) {
return $aSource[$sKey];
}
if (null !== $sDefault)
{
if (null !== $sDefault) {
return $sDefault;
}
$sErrorMessage = sprintf('key "%s" not found into "%s" while expanding', $sSourceName, $sWholeMask);
IssueLog::Error($sErrorMessage, self::class, array($sSourceName, $sKey, $sDefault, $sWholeMask));
IssueLog::Error($sErrorMessage, self::class, [$sSourceName, $sKey, $sDefault, $sWholeMask]);
throw new ConfigException($sErrorMessage);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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
@@ -26,29 +27,25 @@ class DBUnionSearch extends DBSearch
protected $aSearches; // source queries
protected $aSelectedClasses; // alias => classes (lowest common ancestors) computed at construction
protected $aColumnToAliases;
/**
* DBUnionSearch constructor.
*
* @api
*
* @param $aSearches
*
* @throws CoreException
*/
/**
* DBUnionSearch constructor.
*
* @api
*
* @param $aSearches
*
* @throws CoreException
*/
public function __construct($aSearches)
{
if (count ($aSearches) == 0)
{
if (count($aSearches) == 0) {
throw new CoreException('A DBUnionSearch must be made of at least one search');
}
$this->aSearches = array();
foreach ($aSearches as $oSearch)
{
if ($oSearch instanceof DBUnionSearch)
{
foreach ($oSearch->aSearches as $oSubSearch)
{
$this->aSearches = [];
foreach ($aSearches as $oSearch) {
if ($oSearch instanceof DBUnionSearch) {
foreach ($oSearch->aSearches as $oSubSearch) {
$this->aSearches[] = $oSubSearch->DeepClone();
}
} else {
@@ -69,15 +66,16 @@ class DBUnionSearch extends DBSearch
public function IsAllDataAllowed()
{
foreach ($this->aSearches as $oSearch) {
if ($oSearch->IsAllDataAllowed() === false) return false;
if ($oSearch->IsAllDataAllowed() === false) {
return false;
}
}
return true;
}
public function SetArchiveMode($bEnable)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->SetArchiveMode($bEnable);
}
parent::SetArchiveMode($bEnable);
@@ -85,8 +83,7 @@ class DBUnionSearch extends DBSearch
public function SetShowObsoleteData($bShow)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->SetShowObsoleteData($bShow);
}
parent::SetShowObsoleteData($bShow);
@@ -102,31 +99,25 @@ class DBUnionSearch extends DBSearch
// 1 - Collect all the column/classes
$aColumnToClasses = [];
$this->aColumnToAliases = [];
foreach ($this->aSearches as $iPos => $oSearch)
{
foreach ($this->aSearches as $iPos => $oSearch) {
$aSelected = array_values($oSearch->GetSelectedClasses());
if ($iPos != 0)
{
if (count($aSelected) < count($aColumnToClasses))
{
throw new Exception('Too few selected classes in the subquery #'.($iPos+1));
if ($iPos != 0) {
if (count($aSelected) < count($aColumnToClasses)) {
throw new Exception('Too few selected classes in the subquery #'.($iPos + 1));
}
if (count($aSelected) > count($aColumnToClasses))
{
throw new Exception('Too many selected classes in the subquery #'.($iPos+1));
if (count($aSelected) > count($aColumnToClasses)) {
throw new Exception('Too many selected classes in the subquery #'.($iPos + 1));
}
}
foreach ($aSelected as $iColumn => $sClass)
{
foreach ($aSelected as $iColumn => $sClass) {
$aColumnToClasses[$iColumn][$iPos] = $sClass;
}
// Store the aliases by column to map them later (the first query impose the aliases)
$aAliases = array_keys($oSearch->GetSelectedClasses());
foreach ($aAliases as $iColumn => $sAlias)
{
foreach ($aAliases as $iColumn => $sAlias) {
$this->aColumnToAliases[$iColumn][$iPos] = $sAlias;
}
}
@@ -137,13 +128,11 @@ class DBUnionSearch extends DBSearch
// 3 - Compute alias => lowest common ancestor
$this->aSelectedClasses = [];
foreach ($aColumnToClasses as $iColumn => $aClasses)
{
foreach ($aColumnToClasses as $iColumn => $aClasses) {
$sAlias = $aColumnToAlias[$iColumn];
$sAncestor = MetaModel::GetLowestCommonAncestor($aClasses);
if (is_null($sAncestor))
{
throw new Exception('Could not find a common ancestor for the column '.($iColumn+1).' (Classes: '.implode(', ', $aClasses).')');
if (is_null($sAncestor)) {
throw new Exception('Could not find a common ancestor for the column '.($iColumn + 1).' (Classes: '.implode(', ', $aClasses).')');
}
$this->aSelectedClasses[$sAlias] = $sAncestor;
}
@@ -164,12 +153,9 @@ class DBUnionSearch extends DBSearch
*/
public function GetClassName($sAlias)
{
if (array_key_exists($sAlias, $this->aSelectedClasses))
{
if (array_key_exists($sAlias, $this->aSelectedClasses)) {
return $this->aSelectedClasses[$sAlias];
}
else
{
} else {
throw new CoreException("Invalid class alias '$sAlias'");
}
}
@@ -185,20 +171,16 @@ class DBUnionSearch extends DBSearch
return key($this->aSelectedClasses);
}
/**
* Change the class (only subclasses are supported as of now, because the conditions must fit the new class)
* Defaults to the first selected class
* Only the selected classes can be changed
*/
*/
public function ChangeClass($sNewClass, $sAlias = null)
{
if (is_null($sAlias))
{
if (is_null($sAlias)) {
$sAlias = $this->GetClassAlias();
}
elseif (!array_key_exists($sAlias, $this->aSelectedClasses))
{
} elseif (!array_key_exists($sAlias, $this->aSelectedClasses)) {
// discard silently - necessary when recursing (??? copied from DBObjectSearch)
return;
}
@@ -207,8 +189,7 @@ class DBUnionSearch extends DBSearch
$iColumn = array_search($sAlias, array_keys($this->aSelectedClasses));
// 2 - change for each search
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$aSearchAliases = array_keys($oSearch->GetSelectedClasses());
$sSearchAlias = $aSearchAliases[$iColumn];
$oSearch->ChangeClass($sNewClass, $sSearchAlias);
@@ -279,38 +260,31 @@ class DBUnionSearch extends DBSearch
public function RenameAlias($sOldName, $sNewName)
{
$bRet = false;
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$bRet = $oSearch->RenameAlias($sOldName, $sNewName) || $bRet;
}
return $bRet;
}
public function RenameAliasesInNameSpace($aClassAliases, $aAliasTranslation = array())
public function RenameAliasesInNameSpace($aClassAliases, $aAliasTranslation = [])
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->RenameAliasesInNameSpace($aClassAliases, $aAliasTranslation);
}
}
public function TranslateConditions($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->TranslateConditions($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
public function IsAny()
{
$bIsAny = true;
foreach ($this->aSearches as $oSearch)
{
if (!$oSearch->IsAny())
{
foreach ($this->aSearches as $oSearch) {
if (!$oSearch->IsAny()) {
$bIsAny = false;
break;
}
@@ -320,8 +294,7 @@ class DBUnionSearch extends DBSearch
public function ResetCondition()
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->ResetCondition();
}
}
@@ -329,13 +302,10 @@ class DBUnionSearch extends DBSearch
public function MergeConditionExpression($oExpression)
{
$aAliases = array_keys($this->aSelectedClasses);
foreach ($this->aSearches as $iSearchIndex => $oSearch)
{
foreach ($this->aSearches as $iSearchIndex => $oSearch) {
$oClonedExpression = $oExpression->DeepClone();
if ($iSearchIndex != 0)
{
foreach (array_keys($oSearch->GetSelectedClasses()) as $iColumn => $sSearchAlias)
{
if ($iSearchIndex != 0) {
foreach (array_keys($oSearch->GetSelectedClasses()) as $iColumn => $sSearchAlias) {
$oClonedExpression->RenameAlias($aAliases[$iColumn], $sSearchAlias);
}
}
@@ -346,13 +316,10 @@ class DBUnionSearch extends DBSearch
public function AddConditionExpression($oExpression)
{
$aAliases = array_keys($this->aSelectedClasses);
foreach ($this->aSearches as $iSearchIndex => $oSearch)
{
foreach ($this->aSearches as $iSearchIndex => $oSearch) {
$oClonedExpression = $oExpression->DeepClone();
if ($iSearchIndex != 0)
{
foreach (array_keys($oSearch->GetSelectedClasses()) as $iColumn => $sSearchAlias)
{
if ($iSearchIndex != 0) {
foreach (array_keys($oSearch->GetSelectedClasses()) as $iColumn => $sSearchAlias) {
$oClonedExpression->RenameAlias($aAliases[$iColumn], $sSearchAlias);
}
}
@@ -360,18 +327,16 @@ class DBUnionSearch extends DBSearch
}
}
public function AddNameCondition($sName)
public function AddNameCondition($sName)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->AddNameCondition($sName);
}
}
public function AddCondition($sFilterCode, $value, $sOpCode = null)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->AddCondition($sFilterCode, $value, $sOpCode);
}
}
@@ -379,35 +344,32 @@ class DBUnionSearch extends DBSearch
/**
* Specify a condition on external keys or link sets
* @param String sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
* Example: infra_list->ci_id->location_id->country
* Example: infra_list->ci_id->location_id->country
* @param Object value The value to match (can be an array => IN(val1, val2...)
* @return void
*/
public function AddConditionAdvanced($sAttSpec, $value)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->AddConditionAdvanced($sAttSpec, $value);
}
}
public function AddCondition_FullText($sFullText)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->AddCondition_FullText($sFullText);
}
}
public function AddCondition_FullTextOnAttributes(array $aAttCodes, $sNeedle)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->AddCondition_FullTextOnAttributes($aAttCodes, $sNeedle);
}
}
/**
/**
* @param DBObjectSearch $oFilter
* @param $sExtKeyAttCode
* @param int $iOperatorCode
@@ -415,8 +377,7 @@ class DBUnionSearch extends DBSearch
*/
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oConditionFilter = $oFilter->DeepClone();
$oSearch->AddCondition_PointingTo($oConditionFilter, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
}
@@ -430,8 +391,7 @@ class DBUnionSearch extends DBSearch
*/
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oConditionFilter = $oFilter->DeepClone();
$oSearch->AddCondition_ReferencedBy($oConditionFilter, $sForeignExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
}
@@ -439,9 +399,8 @@ class DBUnionSearch extends DBSearch
public function Filter($sClassAlias, DBSearch $oFilter)
{
$aSearches = array();
foreach ($this->aSearches as $oSearch)
{
$aSearches = [];
foreach ($this->aSearches as $oSearch) {
if (!$oSearch->IsAllDataAllowed()) {
$aSearches[] = $oSearch->Filter($sClassAlias, $oFilter);
} else {
@@ -453,9 +412,8 @@ class DBUnionSearch extends DBSearch
public function Intersect(DBSearch $oFilter)
{
$aSearches = array();
foreach ($this->aSearches as $oSearch)
{
$aSearches = [];
foreach ($this->aSearches as $oSearch) {
$aSearches[] = $oSearch->Intersect($oFilter);
}
return new DBUnionSearch($aSearches);
@@ -463,17 +421,15 @@ class DBUnionSearch extends DBSearch
public function SetInternalParams($aParams)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->SetInternalParams($aParams);
}
}
public function GetInternalParams()
{
$aParams = array();
foreach ($this->aSearches as $oSearch)
{
$aParams = [];
foreach ($this->aSearches as $oSearch) {
$aParams = array_merge($oSearch->GetInternalParams(), $aParams);
}
return $aParams;
@@ -481,9 +437,8 @@ class DBUnionSearch extends DBSearch
public function GetQueryParams()
{
$aParams = array();
foreach ($this->aSearches as $oSearch)
{
$aParams = [];
foreach ($this->aSearches as $oSearch) {
$aParams = array_merge($oSearch->GetQueryParams(), $aParams);
}
return $aParams;
@@ -492,7 +447,7 @@ class DBUnionSearch extends DBSearch
public function ListConstantFields()
{
// Somewhat complex to implement for unions, for a poor benefit
return array();
return [];
}
/**
@@ -501,20 +456,18 @@ class DBUnionSearch extends DBSearch
*/
public function ApplyParameters($aArgs)
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->ApplyParameters($aArgs);
}
}
/**
* Overloads for query building
*/
*/
public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false)
{
$aSubQueries = array();
foreach ($this->aSearches as $oSearch)
{
$aSubQueries = [];
foreach ($this->aSearches as $oSearch) {
$aSubQueries[] = $oSearch->ToOQL($bDevelopParams, $aContextParams, $bWithAllowAllFlag);
}
$sRet = implode(' UNION ', $aSubQueries);
@@ -527,9 +480,8 @@ class DBUnionSearch extends DBSearch
*/
public function ToJSON()
{
$sRet = array('unions' => array());
foreach ($this->aSearches as $oSearch)
{
$sRet = ['unions' => []];
foreach ($this->aSearches as $oSearch) {
$sRet['unions'][] = $oSearch->ToJSON();
}
return $sRet;
@@ -543,21 +495,19 @@ class DBUnionSearch extends DBSearch
*/
public function RemoveDuplicateQueries()
{
$aQueries = array();
$aSearches = array();
$aQueries = [];
$aSearches = [];
foreach ($this->GetSearches() as $oTmpSearch)
{
foreach ($this->GetSearches() as $oTmpSearch) {
$sQuery = $oTmpSearch->ToOQL(true);
if (!in_array($sQuery, $aQueries))
{
if (!in_array($sQuery, $aQueries)) {
$aQueries[] = $sQuery;
$aSearches[] = $oTmpSearch;
}
}
$oNewSearch = new DBUnionSearch($aSearches);
return $oNewSearch;
}
@@ -567,60 +517,49 @@ class DBUnionSearch extends DBSearch
//
////////////////////////////////////////////////////////////////////////////
public function MakeDeleteQuery($aArgs = array())
public function MakeDeleteQuery($aArgs = [])
{
throw new Exception('MakeDeleteQuery is not implemented for the unions!');
}
public function MakeUpdateQuery($aValues, $aArgs = array())
public function MakeUpdateQuery($aValues, $aArgs = [])
{
throw new Exception('MakeUpdateQuery is not implemented for the unions!');
}
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null)
{
if (count($this->aSearches) == 1)
{
if (count($this->aSearches) == 1) {
return $this->aSearches[0]->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr, $aSelectedClasses, $aSelectExpr);
}
$aSQLQueries = array();
$aSQLQueries = [];
$aAliases = array_keys($this->aSelectedClasses);
$aQueryAttToLoad = null;
$aUnionQuerySelectExpr = array();
foreach ($this->aSearches as $iSearch => $oSearch)
{
$aUnionQuerySelectExpr = [];
foreach ($this->aSearches as $iSearch => $oSearch) {
$aSearchAliases = array_keys($oSearch->GetSelectedClasses());
// The selected classes from the query build perspective are the lowest common ancestors amongst the various queries
// (used when it comes to determine which attributes must be selected)
$aSearchSelectedClasses = array();
foreach ($aSearchAliases as $iColumn => $sSearchAlias)
{
$aSearchSelectedClasses = [];
foreach ($aSearchAliases as $iColumn => $sSearchAlias) {
$sAlias = $aAliases[$iColumn];
$aSearchSelectedClasses[$sSearchAlias] = $this->aSelectedClasses[$sAlias];
}
if ($bGetCount)
{
if ($bGetCount) {
// Select only ids for the count to allow optimization of joins
foreach($aSearchAliases as $sSearchAlias)
{
$aQueryAttToLoad[$sSearchAlias] = array();
foreach ($aSearchAliases as $sSearchAlias) {
$aQueryAttToLoad[$sSearchAlias] = [];
}
}
else
{
if (is_null($aAttToLoad))
{
} else {
if (is_null($aAttToLoad)) {
$aQueryAttToLoad = null;
}
else
{
} else {
// (Eventually) Transform the aliases
$aQueryAttToLoad = array();
foreach($aAttToLoad as $sAlias => $aAttributes)
{
$aQueryAttToLoad = [];
foreach ($aAttToLoad as $sAlias => $aAttributes) {
$iColumn = array_search($sAlias, $aAliases);
$sQueryAlias = ($iColumn === false) ? $sAlias : $aSearchAliases[$iColumn];
$aQueryAttToLoad[$sQueryAlias] = $aAttributes;
@@ -628,66 +567,51 @@ class DBUnionSearch extends DBSearch
}
}
if (is_null($aGroupByExpr))
{
if (is_null($aGroupByExpr)) {
$aQueryGroupByExpr = null;
}
else
{
} else {
// Clone (and eventually transform) the group by expressions
$aQueryGroupByExpr = array();
$aTranslationData = array();
$aQueryGroupByExpr = [];
$aTranslationData = [];
$aQueryColumns = array_keys($oSearch->GetSelectedClasses());
foreach ($aAliases as $iColumn => $sAlias)
{
foreach ($aAliases as $iColumn => $sAlias) {
$sQueryAlias = $aQueryColumns[$iColumn];
$aTranslationData[$sAlias]['*'] = $sQueryAlias;
$aQueryGroupByExpr[$sAlias.'id'] = new FieldExpression('id', $sQueryAlias);
}
foreach ($aGroupByExpr as $sExpressionAlias => $oExpression)
{
foreach ($aGroupByExpr as $sExpressionAlias => $oExpression) {
$aQueryGroupByExpr[$sExpressionAlias] = $oExpression->Translate($aTranslationData, false, false);
}
}
if (is_null($aSelectExpr))
{
if (is_null($aSelectExpr)) {
$aQuerySelectExpr = null;
}
else
{
$aQuerySelectExpr = array();
$aTranslationData = array();
} else {
$aQuerySelectExpr = [];
$aTranslationData = [];
$aQueryColumns = array_keys($oSearch->GetSelectedClasses());
foreach($aAliases as $iColumn => $sAlias)
{
foreach ($aAliases as $iColumn => $sAlias) {
$sQueryAlias = $aQueryColumns[$iColumn];
$aTranslationData[$sAlias]['*'] = $sQueryAlias;
}
foreach($aSelectExpr as $sExpressionAlias => $oExpression)
{
$oExpression->Browse(function ($oNode) use (&$aQuerySelectExpr, &$aTranslationData)
{
if ($oNode instanceof FieldExpression)
{
foreach ($aSelectExpr as $sExpressionAlias => $oExpression) {
$oExpression->Browse(function ($oNode) use (&$aQuerySelectExpr, &$aTranslationData) {
if ($oNode instanceof FieldExpression) {
$sAlias = $oNode->GetParent()."__".$oNode->GetName();
if (!key_exists($sAlias, $aQuerySelectExpr))
{
if (!key_exists($sAlias, $aQuerySelectExpr)) {
$aQuerySelectExpr[$sAlias] = $oNode->Translate($aTranslationData, false, false);
}
$aTranslationData[$oNode->GetParent()][$oNode->GetName()] = new FieldExpression($sAlias);
}
});
// Only done for the first select as aliases are named after the first query
if (!array_key_exists($sExpressionAlias, $aUnionQuerySelectExpr))
{
if (!array_key_exists($sExpressionAlias, $aUnionQuerySelectExpr)) {
$aUnionQuerySelectExpr[$sExpressionAlias] = $oExpression->Translate($aTranslationData, false, false);
}
}
}
$oSubQuery = $oSearch->GetSQLQueryStructure($aQueryAttToLoad, false, $aQueryGroupByExpr, $aSearchSelectedClasses, $aQuerySelectExpr);
if (count($aSearchAliases) > 1)
{
if (count($aSearchAliases) > 1) {
// Necessary to make sure that selected columns will match throughout all the queries
// (default order of selected fields depending on the order of JOINS)
$oSubQuery->SortSelectedFields();
@@ -698,17 +622,17 @@ class DBUnionSearch extends DBSearch
$oSQLQuery = new SQLUnionQuery($aSQLQueries, $aGroupByExpr, $aUnionQuerySelectExpr);
//MyHelpers::var_dump_html($oSQLQuery, true);
//MyHelpers::var_dump_html($oSQLQuery->RenderSelect(), true);
if (self::$m_bDebugQuery) $oSQLQuery->DisplayHtml();
if (self::$m_bDebugQuery) {
$oSQLQuery->DisplayHtml();
}
return $oSQLQuery;
}
protected function IsDataFiltered()
{
$bIsAllDataFiltered = true;
foreach ($this->aSearches as $oSearch)
{
if (!$oSearch->IsDataFiltered())
{
foreach ($this->aSearches as $oSearch) {
if (!$oSearch->IsDataFiltered()) {
$bIsAllDataFiltered = false;
break;
}
@@ -718,19 +642,15 @@ class DBUnionSearch extends DBSearch
protected function SetDataFiltered()
{
foreach ($this->aSearches as $oSearch)
{
foreach ($this->aSearches as $oSearch) {
$oSearch->SetDataFiltered();
}
}
public function AddConditionForInOperatorUsingParam($sFilterCode, $aValues, $bPositiveMatch = true)
{
$sInParamName = $this->GenerateUniqueParamName();
foreach ($this->aSearches as $iSearchIndex => $oSearch)
{
foreach ($this->aSearches as $iSearchIndex => $oSearch) {
$oFieldExpression = new FieldExpression($sFilterCode, $oSearch->GetClassAlias());
$sOperator = $bPositiveMatch ? 'IN' : 'NOT IN';
@@ -738,17 +658,16 @@ class DBUnionSearch extends DBSearch
$oParamExpression = new VariableExpression($sInParamName);
$oSearch->GetInternalParamsByRef()[$sInParamName] = $aValues;
$oListExpression = new ListExpression(array($oParamExpression));
$oListExpression = new ListExpression([$oParamExpression]);
$oInCondition = new BinaryExpression($oFieldExpression, $sOperator, $oListExpression);
$oSearch->AddConditionExpression($oInCondition);
}
}
function GetExpectedArguments(): array
public function GetExpectedArguments(): array
{
$aVariableCriteria = array();
foreach ($this->aSearches as $oSearch)
{
$aVariableCriteria = [];
foreach ($this->aSearches as $oSearch) {
$aVariableCriteria = array_merge($aVariableCriteria, $oSearch->GetExpectedArguments());
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,31 +24,31 @@ class Event extends DBObject implements iDisplay
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event",
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("message", ["allowed_values" => null, "sql" => "message", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("date", ["allowed_values" => null, "sql" => "date", "default_value" => "NOW()", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", ["allowed_values" => null, "sql" => "userinfo", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'finalclass', 'message')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'message', 'userinfo']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'finalclass', 'message']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
/**
@@ -58,12 +58,9 @@ class Event extends DBObject implements iDisplay
*/
public static function MapContextParam($sContextParam)
{
if ($sContextParam == 'menu')
{
if ($sContextParam == 'menu') {
return null;
}
else
{
} else {
return $sContextParam;
}
}
@@ -79,7 +76,7 @@ class Event extends DBObject implements iDisplay
public function GetHilightClass()
{
// Possible return values are:
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
return HILIGHT_CLASS_NONE; // Not hilighted by default
}
@@ -88,7 +85,7 @@ class Event extends DBObject implements iDisplay
return 'UI.php';
}
function DisplayDetails(WebPage $oPage, $bEditMode = false)
public function DisplayDetails(WebPage $oPage, $bEditMode = false)
{
// Object's details
//$this->DisplayBareHeader($oPage, $bEditMode);
@@ -97,21 +94,23 @@ class Event extends DBObject implements iDisplay
$oPage->SetCurrentTab('UI:PropertiesTab');
$this->DisplayBareProperties($oPage, $bEditMode);
}
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
if ($bEditMode) return array(); // Not editable
$aDetails = array();
public function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = [])
{
if ($bEditMode) {
return [];
} // Not editable
$aDetails = [];
$sClass = get_class($this);
$aZList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details'));
foreach ($aZList as $sAttCode) {
$sDisplayValue = $this->GetAsHTML($sAttCode);
$aDetails[] = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue);
$aDetails[] = ['label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue];
}
$oPage->Details($aDetails);
return array();
return [];
}
}
@@ -119,35 +118,35 @@ class EventNotification extends Event
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_notification",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false),
'indexes' => array(
array( 'object_class', 'object_id'),
)
);
"order_by_default" => ['date' => false],
'indexes' => [
[ 'object_class', 'object_id'],
],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "jointype"=> "", "allowed_values"=>null, "sql"=>"trigger_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass" => "Action", "jointype" => "", "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values" => null, "sql" => "object_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => array())));
//@since 3.2.0
MetaModel::Init_AddAttribute(new AttributeClass("object_class", array("class_category"=>"", "more_values"=>"", "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>true /*to avoid setting AbstractResource as default in database*/, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", ["targetclass" => "Trigger", "jointype" => "", "allowed_values" => null, "sql" => "trigger_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", ["targetclass" => "Action", "jointype" => "", "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", ["allowed_values" => null, "sql" => "object_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => []]));
//@since 3.2.0
MetaModel::Init_AddAttribute(new AttributeClass("object_class", ["class_category" => "", "more_values" => "", "sql" => "object_class", "default_value" => null, "is_null_allowed" => true /*to avoid setting AbstractResource as default in database*/, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo', 'trigger_id', 'action_id', 'object_class', 'object_id')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'message')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'message', 'userinfo', 'trigger_id', 'action_id', 'object_class', 'object_id']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'message']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -155,35 +154,35 @@ class EventNotificationEmail extends EventNotification
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_email",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("cc", array("allowed_values"=>null, "sql"=>"cc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("bcc", array("allowed_values"=>null, "sql"=>"bcc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("from", array("allowed_values"=>null, "sql"=>"from", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeHTML("body", array("allowed_values"=>null, "sql"=>"body", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeTable("attachments", array("allowed_values"=>null, "sql"=>"attachments", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("to", ["allowed_values" => null, "sql" => "to", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("cc", ["allowed_values" => null, "sql" => "cc", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("bcc", ["allowed_values" => null, "sql" => "bcc", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("from", ["allowed_values" => null, "sql" => "from", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("subject", ["allowed_values" => null, "sql" => "subject", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeHTML("body", ["allowed_values" => null, "sql" => "body", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeTable("attachments", ["allowed_values" => null, "sql" => "attachments", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_class', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'message', 'to', 'subject', 'attachments')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_class', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'message', 'to', 'subject', 'attachments']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -191,34 +190,34 @@ class EventIssue extends Event
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_issue",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("issue", array("allowed_values"=>null, "sql"=>"issue", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("allowed_values"=>null, "sql"=>"impact", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("page", array("allowed_values"=>null, "sql"=>"page", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributePropertySet("arguments_post", array("allowed_values"=>null, "sql"=>"arguments_post", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributePropertySet("arguments_get", array("allowed_values"=>null, "sql"=>"arguments_get", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeTable("callstack", array("allowed_values"=>null, "sql"=>"callstack", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributePropertySet("data", array("allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("issue", ["allowed_values" => null, "sql" => "issue", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("impact", ["allowed_values" => null, "sql" => "impact", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("page", ["allowed_values" => null, "sql" => "page", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributePropertySet("arguments_post", ["allowed_values" => null, "sql" => "arguments_post", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributePropertySet("arguments_get", ["allowed_values" => null, "sql" => "arguments_get", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeTable("callstack", ["allowed_values" => null, "sql" => "callstack", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributePropertySet("data", ["allowed_values" => null, "sql" => "data", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo', 'issue', 'impact', 'page', 'arguments_post', 'arguments_get', 'callstack', 'data')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'issue', 'impact')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'message', 'userinfo', 'issue', 'impact', 'page', 'arguments_post', 'arguments_get', 'callstack', 'data']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'issue', 'impact']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
protected function OnInsert()
@@ -231,20 +230,16 @@ class EventIssue extends Event
$this->Set('userinfo', UserRights::GetUserId());
}
if (array_key_exists('_GET', $GLOBALS) && is_array($GLOBALS['_GET']))
{
if (array_key_exists('_GET', $GLOBALS) && is_array($GLOBALS['_GET'])) {
$this->Set('arguments_get', $this->SanitizeRequestParams($GLOBALS['_GET']));
}
else
{
$this->Set('arguments_get', array());
} else {
$this->Set('arguments_get', []);
}
if (array_key_exists('_POST', $GLOBALS) && is_array($GLOBALS['_POST']))
{
if (array_key_exists('_POST', $GLOBALS) && is_array($GLOBALS['_POST'])) {
$this->Set('arguments_post', $this->SanitizeRequestParams($GLOBALS['_POST']));
} else {
$this->Set('arguments_post', array());
$this->Set('arguments_post', []);
}
$sLength = mb_strlen($this->Get('issue'));
if ($sLength > 255) {
@@ -281,44 +276,42 @@ class EventIssue extends Event
}
}
return $aSanitizedParams;
}
}
class EventWebService extends Event
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_webservice",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("verb", array("allowed_values"=>null, "sql"=>"verb", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("verb", ["allowed_values" => null, "sql" => "verb", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
//MetaModel::Init_AddAttribute(new AttributeStructure("arguments", array("allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("result", array("allowed_values"=>null, "sql"=>"result", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("log_info", array("allowed_values"=>null, "sql"=>"log_info", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("log_warning", array("allowed_values"=>null, "sql"=>"log_warning", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("log_error", array("allowed_values"=>null, "sql"=>"log_error", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("data", array("allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("result", ["allowed_values" => null, "sql" => "result", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("log_info", ["allowed_values" => null, "sql" => "log_info", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("log_warning", ["allowed_values" => null, "sql" => "log_warning", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("log_error", ["allowed_values" => null, "sql" => "log_error", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("data", ["allowed_values" => null, "sql" => "data", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'verb', 'result', 'log_info', 'log_warning', 'log_error', 'data')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'verb', 'result')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'verb', 'result', 'log_info', 'log_warning', 'log_error', 'data']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'verb', 'result']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -326,34 +319,34 @@ class EventRestService extends Event
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_restservice",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("operation", array("allowed_values"=>null, "sql"=>"operation", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("json_input", array("allowed_values"=>null, "sql"=>"json_input", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("operation", ["allowed_values" => null, "sql" => "operation", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("version", ["allowed_values" => null, "sql" => "version", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("json_input", ["allowed_values" => null, "sql" => "json_input", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("code", array("allowed_values"=>null, "sql"=>"code", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("json_output", array("allowed_values"=>null, "sql"=>"json_output", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("provider", array("allowed_values"=>null, "sql"=>"provider", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("code", ["allowed_values" => null, "sql" => "code", "default_value" => 0, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("json_output", ["allowed_values" => null, "sql" => "json_output", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("provider", ["allowed_values" => null, "sql" => "provider", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'operation', 'version', 'json_input', 'message', 'code', 'json_output', 'provider')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'operation', 'message')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'operation', 'version', 'json_input', 'message', 'code', 'json_output', 'provider']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'operation', 'message']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -361,66 +354,64 @@ class EventLoginUsage extends Event
{
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"reconc_keys" => [],
"db_table" => "priv_event_loginusage",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
$aZList = array('date', 'user_id');
if (MetaModel::IsValidAttCode('Contact', 'name'))
{
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_name", array("allowed_values"=>null, "extkey_attcode"=>"user_id", "target_attcode"=>"contactid", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "user_id", "is_null_allowed" => false, "on_target_delete" => DEL_SILENT, "depends_on" => []]));
$aZList = ['date', 'user_id'];
if (MetaModel::IsValidAttCode('Contact', 'name')) {
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_name", ["allowed_values" => null, "extkey_attcode" => "user_id", "target_attcode" => "contactid", "is_null_allowed" => true, "depends_on" => []]));
$aZList[] = 'contact_name';
}
if (MetaModel::IsValidAttCode('Contact', 'email'))
{
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_email", array("allowed_values"=>null, "extkey_attcode"=>"user_id", "target_attcode"=>"email", "is_null_allowed"=>true, "depends_on"=>array())));
if (MetaModel::IsValidAttCode('Contact', 'email')) {
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_email", ["allowed_values" => null, "extkey_attcode" => "user_id", "target_attcode" => "email", "is_null_allowed" => true, "depends_on" => []]));
$aZList[] = 'contact_email';
}
// Display lists
MetaModel::Init_SetZListItems('details', array_merge($aZList, array('userinfo', 'message'))); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array_merge($aZList, array('userinfo'))); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', array_merge($aZList, ['userinfo', 'message'])); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array_merge($aZList, ['userinfo'])); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', $aZList); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
class EventOnObject extends Event
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_event_onobject",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("obj_class", array("allowed_values"=>null, "sql"=>"obj_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("obj_key", array("allowed_values"=>null, "sql"=>"obj_key", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
public static function Init()
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => [],
"db_table" => "priv_event_onobject",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => ['date' => false],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("obj_class", ["allowed_values" => null, "sql" => "obj_class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("obj_key", ["allowed_values" => null, "sql" => "obj_key", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for a list
}
// Display lists
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'obj_class', 'obj_key', 'message']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'obj_class', 'obj_key', 'message']); // Attributes to be displayed for a list
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -25,9 +26,9 @@ define('INLINEIMAGE_DOWNLOAD_URL', 'pages/ajax.document.php?operation=download_i
class InlineImage extends DBObject
{
/** @var string attribute to be added to IMG tags to contain ID */
const DOM_ATTR_ID = 'data-img-id';
public const DOM_ATTR_ID = 'data-img-id';
/** @var string attribute to be added to IMG tags to contain secret */
const DOM_ATTR_SECRET = 'data-img-secret';
public const DOM_ATTR_SECRET = 'data-img-secret';
/**
*
@@ -36,39 +37,37 @@ class InlineImage extends DBObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
'category' => 'addon',
'key_type' => 'autoincrement',
'name_attcode' => array('item_class', 'temp_id'),
'name_attcode' => ['item_class', 'temp_id'],
'state_attcode' => '',
'reconc_keys' => array(''),
'reconc_keys' => [''],
'db_table' => 'inline_image',
'db_key_field' => 'id',
'db_finalclass_field' => '',
'indexes' => array(
array('temp_id'),
array('item_class', 'item_id'),
array('item_org_id'),
),
);
'indexes' => [
['temp_id'],
['item_class', 'item_id'],
['item_org_id'],
],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeDateTime("expire", array("allowed_values" => null, "sql" => 'expire', "default_value" => 'DATE_ADD(NOW(), INTERVAL 1 DAY)', "is_null_allowed" => false, "depends_on" => array(), "always_load_in_tables" => false)));
MetaModel::Init_AddAttribute(new AttributeString("temp_id", array("allowed_values"=>null, "sql"=>'temp_id', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeString("item_class", array("allowed_values"=>null, "sql"=>'item_class', "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeObjectKey("item_id", array("class_attcode"=>'item_class', "allowed_values"=>null, "sql"=>'item_id', "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeInteger("item_org_id", array("allowed_values"=>null, "sql"=>'item_org_id', "default_value"=>'0', "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeBlob("contents", array("is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeString("secret", array("allowed_values"=>null, "sql" => "secret", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeDateTime("expire", ["allowed_values" => null, "sql" => 'expire', "default_value" => 'DATE_ADD(NOW(), INTERVAL 1 DAY)', "is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeString("temp_id", ["allowed_values" => null, "sql" => 'temp_id', "default_value" => '', "is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeString("item_class", ["allowed_values" => null, "sql" => 'item_class', "default_value" => '', "is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeObjectKey("item_id", ["class_attcode" => 'item_class', "allowed_values" => null, "sql" => 'item_id', "is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeInteger("item_org_id", ["allowed_values" => null, "sql" => 'item_org_id', "default_value" => '0', "is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeBlob("contents", ["is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeString("secret", ["allowed_values" => null, "sql" => "secret", "default_value" => '', "is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_SetZListItems('details', array('temp_id', 'item_class', 'item_id', 'item_org_id'));
MetaModel::Init_SetZListItems('standard_search', array('temp_id', 'item_class', 'item_id'));
MetaModel::Init_SetZListItems('list', array('temp_id', 'item_class', 'item_id' ));
MetaModel::Init_SetZListItems('details', ['temp_id', 'item_class', 'item_id', 'item_org_id']);
MetaModel::Init_SetZListItems('standard_search', ['temp_id', 'item_class', 'item_id']);
MetaModel::Init_SetZListItems('list', ['temp_id', 'item_class', 'item_id' ]);
}
/**
* Maps the given context parameter name to the appropriate filter/search code for this class
*
@@ -77,12 +76,9 @@ class InlineImage extends DBObject
*/
public static function MapContextParam($sContextParam)
{
if ($sContextParam == 'org_id')
{
if ($sContextParam == 'org_id') {
return 'item_org_id';
}
else
{
} else {
return null;
}
}
@@ -104,23 +100,18 @@ class InlineImage extends DBObject
$sClass = get_class($oItem);
$iItemId = $oItem->GetKey();
$this->Set('item_class', $sClass);
$this->Set('item_id', $iItemId);
$this->Set('item_class', $sClass);
$this->Set('item_id', $iItemId);
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
$aCallSpec = [$sClass, 'MapContextParam'];
if (is_callable($aCallSpec)) {
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
$iOrgId = $oItem->Get($sAttCode);
if ($iOrgId > 0)
{
if ($iOrgId != $this->Get('item_org_id'))
{
if ($iOrgId > 0) {
if ($iOrgId != $this->Get('item_org_id')) {
$this->Set('item_org_id', $iOrgId);
if ($bUpdateOnChange)
{
if ($bUpdateOnChange) {
$this->DBUpdate();
}
}
@@ -143,29 +134,23 @@ class InlineImage extends DBObject
// First check that the organization CAN be fetched from the target class
//
$sClass = $this->Get('item_class');
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
$aCallSpec = [$sClass, 'MapContextParam'];
if (is_callable($aCallSpec)) {
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
// Second: check that the organization CAN be fetched from the current user
//
if (MetaModel::IsValidClass('Person'))
{
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
if (MetaModel::IsValidClass('Person')) {
$aCallSpec = [$sClass, 'MapContextParam'];
if (is_callable($aCallSpec)) {
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
// OK - try it
//
$oCurrentPerson = MetaModel::GetObject('Person', UserRights::GetContactId(), false);
if ($oCurrentPerson)
{
$this->Set('item_org_id', $oCurrentPerson->Get($sAttCode));
}
if ($oCurrentPerson) {
$this->Set('item_org_id', $oCurrentPerson->Get($sAttCode));
}
}
}
}
@@ -189,39 +174,37 @@ class InlineImage extends DBObject
public static function FinalizeInlineImages(DBObject $oObject)
{
$iTransactionId = utils::ReadParam('transaction_id', null, false, 'transaction_id');
if (!is_null($iTransactionId))
{
if (!is_null($iTransactionId)) {
// Attach new (temporary) inline images
$sTempId = utils::GetUploadTempId($iTransactionId);
// The object is being created from a form, check if there are pending inline images for this object
$sOQL = 'SELECT InlineImage WHERE temp_id = :temp_id';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
$aInlineImagesId = array();
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
$aInlineImagesId = [];
while ($oInlineImage = $oSet->Fetch()) {
$aInlineImagesId[] = $oInlineImage->GetKey();
$oInlineImage->SetItem($oObject);
$oInlineImage->Set('temp_id', '');
$oInlineImage->DBUpdate();
}
IssueLog::Trace('FinalizeInlineImages (see $aInlineImagesId for the id list)', LogChannels::INLINE_IMAGE, array(
IssueLog::Trace('FinalizeInlineImages (see $aInlineImagesId for the id list)', LogChannels::INLINE_IMAGE, [
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
]);
} else {
IssueLog::Trace('FinalizeInlineImages "error" $iTransactionId is null', LogChannels::INLINE_IMAGE, [
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
]);
}
else {
IssueLog::Trace('FinalizeInlineImages "error" $iTransactionId is null', LogChannels::INLINE_IMAGE, array(
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
}
}
/**
@@ -243,11 +226,11 @@ class InlineImage extends DBObject
{
// Protection against unfortunate massive delete of inline images when a null temp ID is passed
if (utils::IsNullOrEmptyString($sTempId)) {
IssueLog::Trace('OnFormCancel "error" $sTempId is null or empty', LogChannels::INLINE_IMAGE, array(
IssueLog::Trace('OnFormCancel "error" $sTempId is null or empty', LogChannels::INLINE_IMAGE, [
'$sTempId' => $sTempId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
]);
return false;
}
@@ -255,19 +238,18 @@ class InlineImage extends DBObject
// Delete all "pending" InlineImages for this form
$sOQL = 'SELECT InlineImage WHERE temp_id = :temp_id';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
$aInlineImagesId = array();
while($oInlineImage = $oSet->Fetch())
{
$aInlineImagesId[] = $oInlineImage->GetKey();
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
$aInlineImagesId = [];
while ($oInlineImage = $oSet->Fetch()) {
$aInlineImagesId[] = $oInlineImage->GetKey();
$oInlineImage->DBDelete();
}
IssueLog::Trace('OnFormCancel', LogChannels::INLINE_IMAGE, array(
IssueLog::Trace('OnFormCancel', LogChannels::INLINE_IMAGE, [
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
]);
return true;
}
@@ -284,15 +266,17 @@ class InlineImage extends DBObject
*/
public static function FixUrls($sHtml)
{
$aNeedles = array();
$aReplacements = array();
$aNeedles = [];
$aReplacements = [];
// Find img tags with an attribute data-img-id
if (preg_match_all('/<img ([^>]*)'.self::DOM_ATTR_ID.'="([0-9]+)"([^>]*)>/i',
$sHtml, $aMatches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
{
if (preg_match_all(
'/<img ([^>]*)'.self::DOM_ATTR_ID.'="([0-9]+)"([^>]*)>/i',
$sHtml,
$aMatches,
PREG_SET_ORDER | PREG_OFFSET_CAPTURE
)) {
$sUrl = utils::GetAbsoluteUrlAppRoot().INLINEIMAGE_DOWNLOAD_URL;
foreach($aMatches as $aImgInfo)
{
foreach ($aMatches as $aImgInfo) {
$sImgTag = $aImgInfo[0][0];
$sSecret = '';
if (preg_match('/data-img-secret="([0-9a-f]+)"/', $sImgTag, $aSecretMatches)) {
@@ -321,11 +305,10 @@ class InlineImage extends DBObject
public static function ProcessImageTag(DOMElement $oElement)
{
$sSrc = $oElement->getAttribute('src');
$sDownloadUrl = str_replace(array('.', '?'), array('\.', '\?'), INLINEIMAGE_DOWNLOAD_URL); // Escape . and ?
$sDownloadUrl = str_replace(['.', '?'], ['\.', '\?'], INLINEIMAGE_DOWNLOAD_URL); // Escape . and ?
$sUrlPattern = '|'.$sDownloadUrl.'([0-9]+)&s=([0-9a-f]+)|';
$bIsInlineImage = preg_match($sUrlPattern, $sSrc, $aMatches);
if (!$bIsInlineImage)
{
if (!$bIsInlineImage) {
return;
}
$iInlineImageId = $aMatches[1];
@@ -334,8 +317,7 @@ class InlineImage extends DBObject
$sAppRoot = utils::GetAbsoluteUrlAppRoot();
$sAppRootPattern = '/^'.preg_quote($sAppRoot, '/').'/';
$bIsSameItop = preg_match($sAppRootPattern, $sSrc);
if (!$bIsSameItop)
{
if (!$bIsSameItop) {
// @see N°1921
// image from another iTop should be treated as external images
$oElement->removeAttribute(self::DOM_ATTR_ID);
@@ -357,8 +339,7 @@ class InlineImage extends DBObject
{
$iMaxWidth = (int)MetaModel::GetConfig()->Get('inline_image_max_display_width', 0);
$sJS = '';
if ($iMaxWidth != 0)
{
if ($iMaxWidth != 0) {
$sJS =
<<<JS
CombodoInlineImage.SetMaxWidth('{$iMaxWidth}');
@@ -381,12 +362,13 @@ JS
*/
public static function IsImage($sMimeType)
{
if (!function_exists('gd_info')) return false; // no image processing capability on this system
if (!function_exists('gd_info')) {
return false;
} // no image processing capability on this system
$bRet = false;
$aInfo = gd_info(); // What are the capabilities
switch($sMimeType)
{
switch ($sMimeType) {
case 'image/gif':
return $aInfo['GIF Read Support'];
break;
@@ -422,24 +404,16 @@ JS
public static function GetMaxUpload()
{
$iMaxUpload = ini_get('upload_max_filesize');
if (!$iMaxUpload)
{
if (!$iMaxUpload) {
$sRet = Dict::S('Attachments:UploadNotAllowedOnThisSystem');
}
else
{
} else {
$iMaxUpload = utils::ConvertToBytes($iMaxUpload);
if ($iMaxUpload > 1024*1024*1024)
{
$sRet = Dict::Format('Attachment:Max_Go', sprintf('%0.2f', $iMaxUpload/(1024*1024*1024)));
}
else if ($iMaxUpload > 1024*1024)
{
$sRet = Dict::Format('Attachment:Max_Mo', sprintf('%0.2f', $iMaxUpload/(1024*1024)));
}
else
{
$sRet = Dict::Format('Attachment:Max_Ko', sprintf('%0.2f', $iMaxUpload/(1024)));
if ($iMaxUpload > 1024 * 1024 * 1024) {
$sRet = Dict::Format('Attachment:Max_Go', sprintf('%0.2f', $iMaxUpload / (1024 * 1024 * 1024)));
} elseif ($iMaxUpload > 1024 * 1024) {
$sRet = Dict::Format('Attachment:Max_Mo', sprintf('%0.2f', $iMaxUpload / (1024 * 1024)));
} else {
$sRet = Dict::Format('Attachment:Max_Ko', sprintf('%0.2f', $iMaxUpload / (1024)));
}
}
return $sRet;
@@ -469,73 +443,71 @@ JS
JS;
}
/**
* @inheritDoc
*/
protected function AfterInsert()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, [
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
]);
parent::AfterInsert();
}
/**
* @inheritDoc
*/
protected function AfterInsert()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
protected function AfterUpdate()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, [
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
]);
parent::AfterInsert();
}
/**
* @inheritDoc
*/
protected function AfterUpdate()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
parent::AfterUpdate();
}
parent::AfterUpdate();
}
/**
* @inheritDoc
*/
protected function AfterDelete()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, [
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
]);
parent::AfterDelete();
}
parent::AfterDelete();
}
}
/**
* Garbage collector for cleaning "old" temporary InlineImages (and Attachments).
*/
@@ -545,9 +517,9 @@ class InlineImageGC implements iBackgroundProcess
* @inheritDoc
*/
public function GetPeriodicity()
{
return 1;
}
{
return 1;
}
/**
* @inheritDoc
@@ -556,13 +528,11 @@ class InlineImageGC implements iBackgroundProcess
{
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time()); // Every temporary InlineImage/Attachment expired will be deleted
$aResults = array();
$aClasses = array('InlineImage', 'Attachment');
foreach($aClasses as $sClass)
{
$aResults = [];
$aClasses = ['InlineImage', 'Attachment'];
foreach ($aClasses as $sClass) {
$iProcessed = 0;
if(class_exists($sClass))
{
if (class_exists($sClass)) {
$iProcessed = $this->DeleteExpiredDocuments($sClass, $iTimeLimit, $sDateLimit);
}
$aResults[] = "$iProcessed old temporary $sClass(s)";
@@ -591,11 +561,15 @@ class InlineImageGC implements iBackgroundProcess
$iProcessed = 0;
$sOQL = "SELECT $sClass WHERE (item_id = 0) AND (expire < '$sDateLimit')";
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null,
1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
while ((time() < $iTimeLimit) && ($oResult = $oSet->Fetch()))
{
$oSet = new CMDBObjectSet(
DBObjectSearch::FromOQL($sOQL),
['expire' => true] /* order by*/,
[],
null,
1 /* limit count */
);
$oSet->OptimizeColumnLoad([]);
while ((time() < $iTimeLimit) && ($oResult = $oSet->Fetch())) {
/** @var \ormDocument $oDocument */
$oDocument = $oResult->Get('contents');
IssueLog::Info($sClass.' GC: Removed temp. file '.$oDocument->GetFileName().' on "'.$oResult->Get('item_class').'" #'.$oResult->Get('item_id').' as it has expired.');
@@ -605,4 +579,4 @@ class InlineImageGC implements iBackgroundProcess
return $iProcessed;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -7,32 +8,31 @@
use Combodo\iTop\Core\Kpi\KpiLogData;
use Combodo\iTop\Service\Module\ModuleService;
/**
* Measures operations duration, memory usage, etc. (and some other KPIs)
*/
class ExecutionKPI
{
static protected $m_bEnabled_Duration = false;
static protected $m_bEnabled_Memory = false;
static protected $m_bBlameCaller = false;
static protected $m_sAllowedUser = '*';
static protected $m_bGenerateLegacyReport = true;
static protected $m_fSlowQueries = 0;
protected static $m_bEnabled_Duration = false;
protected static $m_bEnabled_Memory = false;
protected static $m_bBlameCaller = false;
protected static $m_sAllowedUser = '*';
protected static $m_bGenerateLegacyReport = true;
protected static $m_fSlowQueries = 0;
static protected $m_aStats = []; // Recurrent operations
static protected $m_aExecData = []; // One shot operations
protected static $m_aStats = []; // Recurrent operations
protected static $m_aExecData = []; // One shot operations
/**
* @var array[ExecutionKPI]
*/
static protected $m_aExecutionStack = []; // embedded execution stats
protected static $m_aExecutionStack = []; // embedded execution stats
protected $m_fStarted = null;
protected $m_fChildrenDuration = 0; // Count embedded
protected $m_iInitialMemory = null;
static public function EnableDuration($iLevel)
public static function EnableDuration($iLevel)
{
if ($iLevel > 0) {
self::$m_bEnabled_Duration = true;
@@ -47,7 +47,7 @@ class ExecutionKPI
}
}
static public function EnableMemory($iLevel)
public static function EnableMemory($iLevel)
{
if ($iLevel > 0) {
self::$m_bEnabled_Memory = true;
@@ -57,91 +57,94 @@ class ExecutionKPI
}
/**
* @param string sUser A user login or * for all users
*/
static public function SetAllowedUser($sUser)
* @param string sUser A user login or * for all users
*/
public static function SetAllowedUser($sUser)
{
self::$m_sAllowedUser = $sUser;
}
static public function IsEnabled()
public static function IsEnabled()
{
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory)
{
if ((self::$m_sAllowedUser == '*') || (UserRights::GetUser() == trim(self::$m_sAllowedUser)))
{
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
if ((self::$m_sAllowedUser == '*') || (UserRights::GetUser() == trim(self::$m_sAllowedUser))) {
return true;
}
}
return false;
}
static public function SetGenerateLegacyReport($bReportExtensionsOnly)
{
self::$m_bGenerateLegacyReport = $bReportExtensionsOnly;
}
static public function SetSlowQueries($fSlowQueries)
{
self::$m_fSlowQueries = $fSlowQueries;
}
static public function GetDescription()
public static function SetGenerateLegacyReport($bReportExtensionsOnly)
{
$aFeatures = array();
if (self::$m_bEnabled_Duration) $aFeatures[] = 'Duration';
if (self::$m_bEnabled_Memory) $aFeatures[] = 'Memory usage';
$sFeatures = 'Measures: '.implode(', ', $aFeatures);
$sFor = self::$m_sAllowedUser == '*' ? 'EVERYBODY' : "'".trim(self::$m_sAllowedUser)."'";
$sSlowQueries = '';
if (self::$m_fSlowQueries > 0) {
$sSlowQueries = ". Slow Queries: ".self::$m_fSlowQueries."s";
}
$aExtensions = [];
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$aExtensions[] = ModuleService::GetInstance()->GetModuleNameFromObject($oExtensionInstance);
}
$sExtensions = '';
if (count($aExtensions) > 0) {
$sExtensions = '. KPI Extensions: ['.implode(', ', $aExtensions).']';
}
return "KPI logging is active for $sFor. $sFeatures$sSlowQueries$sExtensions";
self::$m_bGenerateLegacyReport = $bReportExtensionsOnly;
}
static public function ReportStats()
public static function SetSlowQueries($fSlowQueries)
{
if (!self::IsEnabled()) return;
self::$m_fSlowQueries = $fSlowQueries;
}
public static function GetDescription()
{
$aFeatures = [];
if (self::$m_bEnabled_Duration) {
$aFeatures[] = 'Duration';
}
if (self::$m_bEnabled_Memory) {
$aFeatures[] = 'Memory usage';
}
$sFeatures = 'Measures: '.implode(', ', $aFeatures);
$sFor = self::$m_sAllowedUser == '*' ? 'EVERYBODY' : "'".trim(self::$m_sAllowedUser)."'";
$sSlowQueries = '';
if (self::$m_fSlowQueries > 0) {
$sSlowQueries = ". Slow Queries: ".self::$m_fSlowQueries."s";
}
$aExtensions = [];
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$aExtensions[] = ModuleService::GetInstance()->GetModuleNameFromObject($oExtensionInstance);
}
$sExtensions = '';
if (count($aExtensions) > 0) {
$sExtensions = '. KPI Extensions: ['.implode(', ', $aExtensions).']';
}
return "KPI logging is active for $sFor. $sFeatures$sSlowQueries$sExtensions";
}
public static function ReportStats()
{
if (!self::IsEnabled()) {
return;
}
global $fItopStarted;
global $iItopInitialMemory;
global $iItopInitialMemory;
$sExecId = microtime(); // id to differentiate the hrefs!
$sRequest = $_SERVER['REQUEST_URI'].' ('.$_SERVER['REQUEST_METHOD'].')';
if (isset($_POST['operation'])) {
$sRequest .= ' operation: '.$_POST['operation'];
}
$sRequest = $_SERVER['REQUEST_URI'].' ('.$_SERVER['REQUEST_METHOD'].')';
if (isset($_POST['operation'])) {
$sRequest .= ' operation: '.$_POST['operation'];
}
$fStop = MyHelpers::getmicrotime();
if (($fStop - $fItopStarted) > self::$m_fSlowQueries) {
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
$iCurrentMemory = self::memory_get_usage();
$iPeakMemory = self::memory_get_peak_usage();
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$oKPILogData = new KpiLogData(KpiLogData::TYPE_REQUEST, 'Page', $sRequest, $fItopStarted, $fStop, '', $iItopInitialMemory, $iCurrentMemory, $iPeakMemory);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
$fStop = MyHelpers::getmicrotime();
if (($fStop - $fItopStarted) > self::$m_fSlowQueries) {
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
$iCurrentMemory = self::memory_get_usage();
$iPeakMemory = self::memory_get_peak_usage();
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$oKPILogData = new KpiLogData(KpiLogData::TYPE_REQUEST, 'Page', $sRequest, $fItopStarted, $fStop, '', $iItopInitialMemory, $iCurrentMemory, $iPeakMemory);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
if (!self::$m_bGenerateLegacyReport) {
return;
}
if (!self::$m_bGenerateLegacyReport) {
return;
}
$aBeginTimes = array();
foreach (self::$m_aExecData as $aOpStats)
{
$aBeginTimes = [];
foreach (self::$m_aExecData as $aOpStats) {
$aBeginTimes[] = $aOpStats['time_begin'];
}
array_multisort($aBeginTimes, self::$m_aExecData);
@@ -150,7 +153,7 @@ class ExecutionKPI
$sHtml = "<hr/>";
$sHtml .= "<div style=\"background-color: grey; padding: 10px;\">";
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - $sRequest</h3>";
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - $sRequest</h3>";
$oStarted = DateTime::createFromFormat('U.u', $fItopStarted);
$sHtml .= '<p>'.$oStarted->format('Y-m-d H:i:s.u').'</p>';
$sHtml .= "<p>log_kpi_user_id: ".UserRights::GetUserId()."</p>";
@@ -159,8 +162,7 @@ class ExecutionKPI
$sHtml .= "<thead>";
$sHtml .= " <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>";
$sHtml .= "</thead>";
foreach (self::$m_aExecData as $aOpStats)
{
foreach (self::$m_aExecData as $aOpStats) {
$sOperation = $aOpStats['op'];
$sBegin = round($aOpStats['time_begin'], 3);
$sEnd = round($aOpStats['time_end'], 3);
@@ -170,12 +172,10 @@ class ExecutionKPI
$sMemBegin = 'n/a';
$sMemEnd = 'n/a';
$sMemPeak = 'n/a';
if (isset($aOpStats['mem_begin']))
{
if (isset($aOpStats['mem_begin'])) {
$sMemBegin = self::MemStr($aOpStats['mem_begin']);
$sMemEnd = self::MemStr($aOpStats['mem_end']);
if (isset($aOpStats['mem_peak']))
{
if (isset($aOpStats['mem_peak'])) {
$sMemPeak = self::MemStr($aOpStats['mem_peak']);
}
}
@@ -187,38 +187,34 @@ class ExecutionKPI
$sHtml .= "</table>";
$sHtml .= "</div>";
$aConsolidatedStats = array();
foreach (self::$m_aStats as $sOperation => $aOpStats)
{
$aConsolidatedStats = [];
foreach (self::$m_aStats as $sOperation => $aOpStats) {
$fTotalOp = 0;
$iTotalOp = 0;
$fMinOp = null;
$fMaxOp = 0;
$sMaxOpArguments = null;
foreach ($aOpStats as $sArguments => $aEvents)
{
foreach ($aEvents as $aEventData)
{
foreach ($aOpStats as $sArguments => $aEvents) {
foreach ($aEvents as $aEventData) {
$fDuration = $aEventData['time'];
$fTotalOp += $fDuration;
$iTotalOp++;
$fMinOp = is_null($fMinOp) ? $fDuration : min($fMinOp, $fDuration);
if ($fDuration > $fMaxOp)
{
if ($fDuration > $fMaxOp) {
$sMaxOpArguments = $sArguments;
$fMaxOp = $fDuration;
}
}
}
$aConsolidatedStats[$sOperation] = array(
$aConsolidatedStats[$sOperation] = [
'count' => $iTotalOp,
'duration' => $fTotalOp,
'min' => $fMinOp,
'max' => $fMaxOp,
'avg' => $fTotalOp / $iTotalOp,
'max_args' => $sMaxOpArguments
);
'max_args' => $sMaxOpArguments,
];
}
$sHtml .= "<div>";
@@ -226,8 +222,7 @@ class ExecutionKPI
$sHtml .= "<thead>";
$sHtml .= " <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>";
$sHtml .= "</thead>";
foreach ($aConsolidatedStats as $sOperation => $aOpStats)
{
foreach ($aConsolidatedStats as $sOperation => $aOpStats) {
$sOperation = '<a href="#'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
$sCount = $aOpStats['count'];
$sDuration = round($aOpStats['duration'], 3);
@@ -250,25 +245,20 @@ class ExecutionKPI
self::Report($sHtml);
// Report operation details
foreach (self::$m_aStats as $sOperation => $aOpStats)
{
foreach (self::$m_aStats as $sOperation => $aOpStats) {
$sHtml = '';
$bDisplayHeader = true;
foreach ($aOpStats as $sArguments => $aEvents)
{
foreach ($aOpStats as $sArguments => $aEvents) {
$sHtmlArguments = '<a name="'.md5($sExecId.$sArguments).'"><div style="white-space: pre-wrap;">'.$sArguments.'</div></a>';
if ($aConsolidatedStats[$sOperation]['max_args'] == $sArguments)
{
if ($aConsolidatedStats[$sOperation]['max_args'] == $sArguments) {
$sHtmlArguments = '<span style="color: red;">'.$sHtmlArguments.'</span>';
}
if (isset($aEvents[0]['callers']))
{
if (isset($aEvents[0]['callers'])) {
$sHtmlArguments .= '<div style="padding: 10px;">';
$sHtmlArguments .= '<table border="1" bgcolor="#cfc">';
$sHtmlArguments .= '<tr><td colspan="2" bgcolor="#e9b96">Call stack for the <b>FIRST</b> caller</td></tr>';
foreach ($aEvents[0]['callers'] as $aCall)
{
foreach ($aEvents[0]['callers'] as $aCall) {
$sHtmlArguments .= '<tr>';
$sHtmlArguments .= '<td>'.$aCall['Function'].'</td>';
$sHtmlArguments .= '<td>'.$aCall['File'].':'.$aCall['Line'].'</td>';
@@ -281,8 +271,7 @@ class ExecutionKPI
$fTotalInter = 0;
$fMinInter = null;
$fMaxInter = 0;
foreach ($aEvents as $aEventData)
{
foreach ($aEvents as $aEventData) {
$fDuration = $aEventData['time'];
$fTotalInter += $fDuration;
$fMinInter = is_null($fMinInter) ? $fDuration : min($fMinInter, $fDuration);
@@ -293,10 +282,8 @@ class ExecutionKPI
$sTotalInter = round($fTotalInter, 3);
$sMinInter = round($fMinInter, 3);
$sMaxInter = round($fMaxInter, 3);
if (($fTotalInter >= self::$m_fSlowQueries))
{
if ($bDisplayHeader)
{
if (($fTotalInter >= self::$m_fSlowQueries)) {
if ($bDisplayHeader) {
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
$sHtml .= "<h4>$sOperationHtml</h4>";
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
@@ -310,8 +297,7 @@ class ExecutionKPI
$sHtml .= "</tr>";
}
}
if (!$bDisplayHeader)
{
if (!$bDisplayHeader) {
$sHtml .= "</table>";
$sHtml .= "<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>";
}
@@ -321,19 +307,19 @@ class ExecutionKPI
self::Report($sHtml);
}
public static function InitStats()
{
// Invoke extensions to initialize the KPI statistics
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$oExtensionInstance->InitStats();
}
}
public static function InitStats()
{
// Invoke extensions to initialize the KPI statistics
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$oExtensionInstance->InitStats();
}
}
public function __construct()
{
$this->ResetCounters();
}
}
// Get the duration since startup, and reset the counter for the next measure
//
@@ -341,65 +327,62 @@ class ExecutionKPI
{
global $fItopStarted;
if (!self::IsEnabled()) {
return;
}
if (!self::IsEnabled()) {
return;
}
$aNewEntry = null;
$fStarted = $this->m_fStarted;
$fStopped = $this->m_fStarted;
if (self::$m_bEnabled_Duration) {
$fStarted = $this->m_fStarted;
$fStopped = $this->m_fStarted;
if (self::$m_bEnabled_Duration) {
$fStopped = MyHelpers::getmicrotime();
$aNewEntry = array(
$aNewEntry = [
'op' => $sOperationDesc,
'time_begin' => $this->m_fStarted - $fItopStarted,
'time_end' => $fStopped - $fItopStarted,
);
];
// Reset for the next operation (if the object is recycled)
$this->m_fStarted = $fStopped;
}
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
$iCurrentMemory = 0;
$iPeakMemory = 0;
if (self::$m_bEnabled_Memory)
{
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
$iCurrentMemory = 0;
$iPeakMemory = 0;
if (self::$m_bEnabled_Memory) {
$iCurrentMemory = self::memory_get_usage();
if (is_null($aNewEntry))
{
$aNewEntry = array('op' => $sOperationDesc);
if (is_null($aNewEntry)) {
$aNewEntry = ['op' => $sOperationDesc];
}
$aNewEntry['mem_begin'] = $this->m_iInitialMemory;
$aNewEntry['mem_end'] = $iCurrentMemory;
$iPeakMemory = self::memory_get_peak_usage();
$aNewEntry['mem_peak'] = $iPeakMemory;
$iPeakMemory = self::memory_get_peak_usage();
$aNewEntry['mem_peak'] = $iPeakMemory;
// Reset for the next operation (if the object is recycled)
$this->m_iInitialMemory = $iCurrentMemory;
}
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance)
{
$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
$oKPILogData = new KpiLogData(
KpiLogData::TYPE_REPORT,
'Step',
$sOperationDesc,
$fStarted,
$fStopped,
$sExtension,
$iInitialMemory,
$iCurrentMemory,
$iPeakMemory);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
$oKPILogData = new KpiLogData(
KpiLogData::TYPE_REPORT,
'Step',
$sOperationDesc,
$fStarted,
$fStopped,
$sExtension,
$iInitialMemory,
$iCurrentMemory,
$iPeakMemory
);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
if (!is_null($aNewEntry) && self::$m_bGenerateLegacyReport)
{
if (!is_null($aNewEntry) && self::$m_bGenerateLegacyReport) {
self::$m_aExecData[] = $aNewEntry;
}
$this->ResetCounters();
@@ -417,20 +400,20 @@ class ExecutionKPI
* @throws \ReflectionException
*/
public function ComputeStatsForExtension($object, string $sMethod, string $sMessage = ''): bool
{
if (!self::IsEnabled()) {
return true;
}
{
if (!self::IsEnabled()) {
return true;
}
$sSignature = ModuleService::GetInstance()->GetModuleMethodSignature($object, $sMethod);
if (utils::StartsWith($sSignature, '[')) {
$this->ComputeStats('Extension', "$sSignature $sMessage");
$sSignature = ModuleService::GetInstance()->GetModuleMethodSignature($object, $sMethod);
if (utils::StartsWith($sSignature, '[')) {
$this->ComputeStats('Extension', "$sSignature $sMessage");
return true;
}
}
return false;
}
}
public function ComputeStats($sOperation, $sArguments)
{
@@ -442,85 +425,82 @@ class ExecutionKPI
if (self::$m_bEnabled_Duration) {
$fStopped = MyHelpers::getmicrotime();
$fDuration = $fStopped - $this->m_fStarted;
$aCallstack = [];
if (self::$m_bGenerateLegacyReport) {
if (self::$m_bBlameCaller) {
$aCallstack = MyHelpers::get_callstack(1);
self::$m_aStats[$sOperation][$sArguments][] = [
'time' => $fDuration,
'callers' => $aCallstack,
];
} else {
self::$m_aStats[$sOperation][$sArguments][] = [
'time' => $fDuration
];
}
}
$aCallstack = [];
if (self::$m_bGenerateLegacyReport) {
if (self::$m_bBlameCaller) {
$aCallstack = MyHelpers::get_callstack(1);
self::$m_aStats[$sOperation][$sArguments][] = [
'time' => $fDuration,
'callers' => $aCallstack,
];
} else {
self::$m_aStats[$sOperation][$sArguments][] = [
'time' => $fDuration,
];
}
}
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
$iCurrentMemory = 0;
$iPeakMemory = 0;
if (self::$m_bEnabled_Memory)
{
$iCurrentMemory = self::memory_get_usage();
$iPeakMemory = self::memory_get_peak_usage();
}
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
$iCurrentMemory = 0;
$iPeakMemory = 0;
if (self::$m_bEnabled_Memory) {
$iCurrentMemory = self::memory_get_usage();
$iPeakMemory = self::memory_get_peak_usage();
}
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
//$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
$sExtension = '';
$oKPILogData = new KpiLogData(
KpiLogData::TYPE_STATS,
$sOperation,
$sArguments,
$this->m_fStarted,
$fStopped,
$sExtension,
$iInitialMemory,
$iCurrentMemory,
$iPeakMemory,
$aCallstack);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
// Invoke extensions to log the KPI operation
/** @var \iKPILoggerExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
//$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
$sExtension = '';
$oKPILogData = new KpiLogData(
KpiLogData::TYPE_STATS,
$sOperation,
$sArguments,
$this->m_fStarted,
$fStopped,
$sExtension,
$iInitialMemory,
$iCurrentMemory,
$iPeakMemory,
$aCallstack
);
$oExtensionInstance->LogOperation($oKPILogData);
}
}
}
protected function ResetCounters()
{
if (self::$m_bEnabled_Duration)
{
if (self::$m_bEnabled_Duration) {
$this->m_fStarted = microtime(true);
}
if (self::$m_bEnabled_Memory)
{
if (self::$m_bEnabled_Memory) {
$this->m_iInitialMemory = self::memory_get_usage();
}
}
const HTML_REPORT_FILE = 'log/kpi.html';
public const HTML_REPORT_FILE = 'log/kpi.html';
static protected function Report($sText)
protected static function Report($sText)
{
file_put_contents(APPROOT.self::HTML_REPORT_FILE, "$sText\n", FILE_APPEND | LOCK_EX);
}
static protected function MemStr($iMemory)
protected static function MemStr($iMemory)
{
return round($iMemory / 1024).' Kb';
}
static protected function memory_get_usage()
protected static function memory_get_usage()
{
return memory_get_usage(true);
return memory_get_usage(true);
}
static public function memory_get_peak_usage($bRealUsage = false)
public static function memory_get_peak_usage($bRealUsage = false)
{
if (function_exists('memory_get_peak_usage'))
{
if (function_exists('memory_get_peak_usage')) {
return memory_get_peak_usage($bRealUsage);
}
// PHP > 5.2.1 - this verb depends on a compilation option

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class OQLActualClassTreeResolver
{
/** @var OQLClassNode */
@@ -38,67 +38,54 @@ class OQLActualClassTreeResolver
$sClass = $this->oOQLClassNode->GetNodeClass();
$sClassAlias = $this->oOQLClassNode->GetNodeClassAlias();
$aExpectedAttributes = $this->oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias);
if (!is_null($sIncomingKeyAttCode) && !isset($aExpectedAttributes[$sIncomingKeyAttCode]))
{
if (!is_null($sIncomingKeyAttCode) && !isset($aExpectedAttributes[$sIncomingKeyAttCode])) {
// Add entry point as expected attribute
$aExpectedAttributes[$sIncomingKeyAttCode] = new FieldExpression($sIncomingKeyAttCode, $sClassAlias);
}
$aClasses = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, false);
/** @var OQLClassNode[] $aClassAndAncestorsNodes */
$aClassAndAncestorsNodes = array();
foreach ($aClasses as $sFamilyClass)
{
$aClassAndAncestorsNodes = [];
foreach ($aClasses as $sFamilyClass) {
// Remove unnecessary classes
if (MetaModel::HasTable($sFamilyClass))
{
if (MetaModel::HasTable($sFamilyClass)) {
$aClassAndAncestorsNodes[$sFamilyClass] = null;
}
}
if (empty($aClassAndAncestorsNodes))
{
if (empty($aClassAndAncestorsNodes)) {
throw new CoreException("Impossible to query the class $sClass");
}
$oBaseNode = null;
$aTranslateFields = array();
foreach ($aExpectedAttributes as $sAttCode => $oExpression)
{
$aTranslateFields = [];
foreach ($aExpectedAttributes as $sAttCode => $oExpression) {
// 'id' is managed later
if ($sAttCode == 'id')
{
if ($sAttCode == 'id') {
continue;
}
// Attributes can be stored in attributes list or for magic ones into filter codes list.
$sOriginClass = null;
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
} else if ($sAttCode == 'id') {
} elseif ($sAttCode == 'id') {
$sOriginClass = $sClass;
} else {
continue;
}
if (!isset($aClassAndAncestorsNodes[$sOriginClass]) || is_null($aClassAndAncestorsNodes[$sOriginClass]))
{
if ($sOriginClass == $sClass)
{
if (!isset($aClassAndAncestorsNodes[$sOriginClass]) || is_null($aClassAndAncestorsNodes[$sOriginClass])) {
if ($sOriginClass == $sClass) {
$sOriginClassAlias = $sClassAlias;
}
else
{
} else {
$sOriginClassAlias = $this->oBuild->GenerateTableAlias($sClassAlias.'_'.$sOriginClass, $sClass);
}
$oOriginClassNode = new OQLClassNode($this->oBuild, $sOriginClass, $sOriginClassAlias, $sClassAlias);
$aClassAndAncestorsNodes[$sOriginClass] = $oOriginClassNode;
}
else
{
} else {
$oOriginClassNode = $aClassAndAncestorsNodes[$sOriginClass];
}
if ($sOriginClass != $sClass)
{
if ($sOriginClass != $sClass) {
// Alias changed, set a new translation
$sOriginClassAlias = $oOriginClassNode->GetNodeClassAlias();
$aTranslateFields[$sClassAlias][$sAttCode] = new FieldExpression($sAttCode, $sOriginClassAlias);
@@ -107,8 +94,7 @@ class OQLActualClassTreeResolver
// Add Joins corresponding to external keys
$this->ResolveJoins($sAttCode, $oOriginClassNode);
if ($sAttCode === $sIncomingKeyAttCode)
{
if ($sAttCode === $sIncomingKeyAttCode) {
// This is the entry point of the class
$oBaseNode = $oOriginClassNode;
}
@@ -117,47 +103,37 @@ class OQLActualClassTreeResolver
// Create joins for ancestor classes
/** @var \OQLClassNode $oBaseNode */
$sFirstValidAncestor = null;
foreach ($aClassAndAncestorsNodes as $sOriginClass => $oOriginClassNode)
{
if (is_null($sFirstValidAncestor))
{
foreach ($aClassAndAncestorsNodes as $sOriginClass => $oOriginClassNode) {
if (is_null($sFirstValidAncestor)) {
$sFirstValidAncestor = $sOriginClass;
}
if (is_null($oOriginClassNode))
{
if (is_null($oOriginClassNode)) {
continue;
}
if (is_null($oBaseNode))
{
if (is_null($oBaseNode)) {
$oBaseNode = $oOriginClassNode;
continue;
}
if ($oBaseNode === $oOriginClassNode)
{
if ($oBaseNode === $oOriginClassNode) {
// Don't link to itself
continue;
}
$oBaseNode->AddInnerJoin($oOriginClassNode, 'id', 'id');
}
if (is_null($oBaseNode))
{
if (is_null($oBaseNode)) {
// If no class was generated above, keep the first valid ancestor
if (is_null($sFirstValidAncestor) || ($sFirstValidAncestor == $sClass))
{
if (is_null($sFirstValidAncestor) || ($sFirstValidAncestor == $sClass)) {
// take current node
$oBaseNode = $this->oOQLClassNode->CloneNode();
}
else
{
} else {
// Use the first valid class to build a default node
$sDefaultClassAlias = $this->oBuild->GenerateTableAlias($sClassAlias.'_'.$sFirstValidAncestor, $sClass);
$oBaseNode = new OQLClassNode($this->oBuild, $sFirstValidAncestor, $sDefaultClassAlias);
}
}
if (isset($aExpectedAttributes['id']) && !isset($aClassAndAncestorsNodes[$sClass]))
{
if (isset($aExpectedAttributes['id']) && !isset($aClassAndAncestorsNodes[$sClass])) {
$sFirstClassAlias = $oBaseNode->GetNodeClassAlias();
$aTranslateFields[$sClassAlias]['id'] = new FieldExpression('id', $sFirstClassAlias);
}
@@ -167,12 +143,11 @@ class OQLActualClassTreeResolver
$this->ResolveJoins('id', $oBaseNode);
// Add finalclass condition if not the requested class
if ($oBaseNode->GetNodeClass() != $sClass)
{
if ($oBaseNode->GetNodeClass() != $sClass) {
$sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$oInExpression = Expression::FromOQL("`".$oBaseNode->GetNodeClassAlias()."`.finalclass IN ('$sExpectedClasses')");
$oTrueExpression = new TrueExpression();
$aCoalesceAttr = array($oInExpression, $oTrueExpression);
$aCoalesceAttr = [$oInExpression, $oTrueExpression];
$oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr);
$this->oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
@@ -194,10 +169,8 @@ class OQLActualClassTreeResolver
// Joins on the selected class
$aJoins = $this->oOQLClassNode->GetJoins();
if (isset($aJoins[$sAttCode]))
{
foreach ($aJoins[$sAttCode] as $oBaseOQLJoin)
{
if (isset($aJoins[$sAttCode])) {
foreach ($aJoins[$sAttCode] as $oBaseOQLJoin) {
// transfer the join from OQL class tree to actual class tree
$oBaseJoinedClassNode = $oBaseOQLJoin->GetOOQLClassNode();
$oOQLActualClassTreeResolver = new OQLActualClassTreeResolver($oBaseJoinedClassNode, $this->oBuild);

View File

@@ -407,16 +407,16 @@ class ormDocument
* @return ormDocument The resampled image
*
*/
public function ResizeImageToFit(int $iMaxWidth, int $iMaxHeight, array|null &$aFinalDimensions = null) : static
public function ResizeImageToFit(int $iMaxWidth, int $iMaxHeight, array|null &$aFinalDimensions = null): static
{
$aFinalDimensions = null;
// If gd extension is not loaded, we put a warning in the log and return the image as is
if (extension_loaded('gd') === false) {
IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. Its dimensions will remain the same instead of ' . $iMaxWidth . 'x' . $iMaxHeight);
IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. Its dimensions will remain the same instead of '.$iMaxWidth.'x'.$iMaxHeight);
return $this;
}
$oGdImage = false;
switch($this->GetMimeType()) {
switch ($this->GetMimeType()) {
case 'image/gif':
case 'image/jpeg':
case 'image/png':
@@ -428,18 +428,18 @@ class ormDocument
}
if ($oGdImage === false) {
IssueLog::Warning('Image could not be resized as . It will remain as imagecreatefromstring could not read its data.Its dimensions will remain the same instead of ' . $iMaxWidth . 'x' . $iMaxHeight);
IssueLog::Warning('Image could not be resized as . It will remain as imagecreatefromstring could not read its data.Its dimensions will remain the same instead of '.$iMaxWidth.'x'.$iMaxHeight);
return $this;
}
$iWidth = imagesx($oGdImage);
$iHeight = imagesy($oGdImage);
if ( ($iMaxWidth === 0 || $iWidth <= $iMaxWidth) && ($iMaxHeight === 0 || $iHeight <= $iMaxHeight)) {
if (($iMaxWidth === 0 || $iWidth <= $iMaxWidth) && ($iMaxHeight === 0 || $iHeight <= $iMaxHeight)) {
// No need to resize
$aFinalDimensions = [
'width' => $iWidth,
'height' =>$iHeight
'height' => $iHeight,
];
return $this;
}
@@ -456,14 +456,13 @@ class ormDocument
$oNewGdImage = imagecreatetruecolor($iNewWidth, $iNewHeight);
$aFinalDimensions = [
'width' => $iNewWidth,
'height' =>$iNewHeight
'height' => $iNewHeight,
];
// Preserve transparency
if($this->GetMimeType() == "image/gif" || $this->GetMimeType() == "image/png") {
if ($this->GetMimeType() == "image/gif" || $this->GetMimeType() == "image/png") {
imagecolortransparent($oNewGdImage, imagecolorallocatealpha($oNewGdImage, 0, 0, 0, 127));
imagealphablending($oNewGdImage, false);
imagesavealpha($oNewGdImage, true);
@@ -473,16 +472,16 @@ class ormDocument
ob_start();
switch ($this->GetMimeType()) {
case 'image/gif':
imagegif($oNewGdImage); // send image to output buffer
break;
imagegif($oNewGdImage); // send image to output buffer
break;
case 'image/jpeg':
imagejpeg($oNewGdImage, null, 80); // null = send image to output buffer, 80 = good quality
break;
imagejpeg($oNewGdImage, null, 80); // null = send image to output buffer, 80 = good quality
break;
case 'image/png':
imagepng($oNewGdImage, null, 5); // null = send image to output buffer, 5 = medium compression
break;
imagepng($oNewGdImage, null, 5); // null = send image to output buffer, 5 = medium compression
break;
}
$oResampledImage = new ormDocument(ob_get_contents(), $this->GetMimeType(), $this->GetFileName());
@ob_end_clean();
@@ -502,5 +501,4 @@ class ormDocument
return md5($this->GetData() ?? '');
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -19,7 +20,6 @@
require_once('dbobjectiterator.php');
/**
* The value for an attribute representing a set of links between the host object and "remote" objects
*
@@ -56,22 +56,22 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
* Object from the original set, minus the removed objects
* @var DBObject[] array of iObjectId => DBObject
*/
protected $aPreserved = array();
protected $aPreserved = [];
/**
* @var DBObject[] New items
*/
protected $aAdded = array();
protected $aAdded = [];
/**
* @var DBObject[] Modified items (could also be found in aPreserved)
*/
protected $aModified = array();
protected $aModified = [];
/**
* @var int[] Removed items
*/
protected $aRemoved = array();
protected $aRemoved = [];
/**
* @var int Position in the collection
@@ -100,13 +100,11 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->oOriginalSet = $oOriginalSet ? clone $oOriginalSet : null;
$oAttDef = MetaModel::GetAttributeDef($sHostClass, $sAttCode);
if (!$oAttDef instanceof AttributeLinkedSet)
{
if (!$oAttDef instanceof AttributeLinkedSet) {
throw new Exception("ormLinkSet: $sAttCode is not a link set");
}
$this->sClass = $oAttDef->GetLinkedClass();
if ($oOriginalSet && ($oOriginalSet->GetClass() != $this->sClass))
{
if ($oOriginalSet && ($oOriginalSet->GetClass() != $this->sClass)) {
throw new Exception("ormLinkSet: wrong class for the original set, found {$oOriginalSet->GetClass()} while expecting {$oAttDef->GetLinkedClass()}");
}
}
@@ -140,7 +138,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
{
assert($oLink instanceof $this->sClass);
// No impact on the iteration algorithm
$iObjectId = $oLink->GetKey();
$iObjectId = $oLink->GetKey();
$this->aAdded[$iObjectId] = $oLink;
$this->bHasDelta = true;
}
@@ -150,19 +148,15 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
public function RemoveItem($iObjectId)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
if (array_key_exists($iObjectId, $this->aPreserved)) {
unset($this->aPreserved[$iObjectId]);
$this->aRemoved[$iObjectId] = $iObjectId;
$this->bHasDelta = true;
} else {
if (array_key_exists($iObjectId, $this->aAdded)) {
unset($this->aAdded[$iObjectId]);
}
}
else
{
if (array_key_exists($iObjectId, $this->aAdded))
{
unset($this->aAdded[$iObjectId]);
}
}
}
/**
@@ -173,12 +167,11 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
assert($oLink instanceof $this->sClass);
$iObjectId = $oLink->GetKey();
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
$this->aModified[$iObjectId] = $oLink;
$this->bHasDelta = true;
}
if (array_key_exists($iObjectId, $this->aPreserved)) {
unset($this->aPreserved[$iObjectId]);
$this->aModified[$iObjectId] = $oLink;
$this->bHasDelta = true;
}
}
/**
@@ -188,33 +181,25 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
protected function LoadOriginalIds()
{
if ($this->aOriginalObjects === null)
{
if ($this->oOriginalSet)
{
if ($this->aOriginalObjects === null) {
if ($this->oOriginalSet) {
$this->aOriginalObjects = $this->GetArrayOfIndex();
$this->aPreserved = $this->aOriginalObjects; // Copy (not effective until aPreserved gets modified)
foreach ($this->aRemoved as $iObjectId)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
}
}
foreach ($this->aModified as $iObjectId => $oLink)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
}
}
}
else
{
foreach ($this->aRemoved as $iObjectId) {
if (array_key_exists($iObjectId, $this->aPreserved)) {
unset($this->aPreserved[$iObjectId]);
}
}
foreach ($this->aModified as $iObjectId => $oLink) {
if (array_key_exists($iObjectId, $this->aPreserved)) {
unset($this->aPreserved[$iObjectId]);
}
}
} else {
// Nothing to load
$this->aOriginalObjects = array();
$this->aPreserved = array();
$this->aOriginalObjects = [];
$this->aPreserved = [];
}
}
}
@@ -230,39 +215,34 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
protected function GetArrayOfIndex()
{
$aRet = array();
$aRet = [];
$this->oOriginalSet->Rewind();
$iRow = 0;
while ($oObject = $this->oOriginalSet->Fetch())
{
while ($oObject = $this->oOriginalSet->Fetch()) {
$aRet[$oObject->GetKey()] = $iRow++;
}
return $aRet;
}
/**
* @param string $sAttCode
* @param bool $bWithId
* @return array
*/
public function GetColumnAsArray($sAttCode, $bWithId = true)
{
$aRet = array();
foreach($this as $oItem)
{
if ($bWithId)
{
$aRet[$oItem->GetKey()] = $oItem->Get($sAttCode);
}
else
{
$aRet[] = $oItem->Get($sAttCode);
}
}
return $aRet;
}
/**
* @param string $sAttCode
* @param bool $bWithId
* @return array
*/
public function GetColumnAsArray($sAttCode, $bWithId = true)
{
$aRet = [];
foreach ($this as $oItem) {
if ($bWithId) {
$aRet[$oItem->GetKey()] = $oItem->Get($sAttCode);
} else {
$aRet[] = $oItem->Get($sAttCode);
}
}
return $aRet;
}
/**
/**
* The class of the objects of the collection (at least a common ancestor)
*
* @return string
@@ -300,13 +280,11 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->LoadOriginalIds();
$iCount = $this->Count();
if ($iPosition >= $iCount)
{
if ($iPosition >= $iCount) {
throw new Exception("Invalid position $iPosition: the link set is made of $iCount items.");
}
$this->rewind();
for($iPos = 0 ; $iPos < $iPosition ; $iPos++)
{
for ($iPos = 0 ; $iPos < $iPosition ; $iPos++) {
$this->next();
}
}
@@ -324,8 +302,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->LoadOriginalIds();
$ret = $this->current();
if ($ret === false)
{
if ($ret === false) {
$ret = null;
}
$this->next();
@@ -350,22 +327,16 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->LoadOriginalIds();
$iPreservedCount = count($this->aPreserved);
if ($this->iCursor < $iPreservedCount)
{
if ($this->iCursor < $iPreservedCount) {
$sId = key($this->aPreserved);
$oRet = MetaModel::GetObject($this->sClass, $sId);
}
else
{
$iModifiedCount = count($this->aModified);
if($this->iCursor < $iPreservedCount + $iModifiedCount)
{
$oRet = current($this->aModified);
}
else
{
$oRet = current($this->aAdded);
}
} else {
$iModifiedCount = count($this->aModified);
if ($this->iCursor < $iPreservedCount + $iModifiedCount) {
$oRet = current($this->aModified);
} else {
$oRet = current($this->aAdded);
}
}
return $oRet;
}
@@ -384,21 +355,15 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->LoadOriginalIds();
$iPreservedCount = count($this->aPreserved);
if ($this->iCursor < $iPreservedCount)
{
if ($this->iCursor < $iPreservedCount) {
next($this->aPreserved);
}
else
{
$iModifiedCount = count($this->aModified);
if($this->iCursor < $iPreservedCount + $iModifiedCount)
{
next($this->aModified);
}
else
{
next($this->aAdded);
}
} else {
$iModifiedCount = count($this->aModified);
if ($this->iCursor < $iPreservedCount + $iModifiedCount) {
next($this->aModified);
} else {
next($this->aAdded);
}
}
// Increment AFTER moving the internal cursors because when starting aModified / aAdded, we must leave it intact
$this->iCursor++;
@@ -446,12 +411,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
public function rewind(): void
{
$this->LoadOriginalIds();
$this->LoadOriginalIds();
$this->iCursor = 0;
$this->iCursor = 0;
reset($this->aPreserved);
reset($this->aAdded);
reset($this->aModified);
reset($this->aAdded);
reset($this->aModified);
}
/**
@@ -473,19 +438,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
public function Equals(ormLinkSet $oFellow)
{
$bRet = null;
if ($this === $oFellow)
{
if ($this === $oFellow) {
$bRet = true;
}
else
{
if ( ($this->oOriginalSet !== $oFellow->oOriginalSet)
&& ($this->oOriginalSet->GetFilter()->ToOQL() != $oFellow->oOriginalSet->GetFilter()->ToOQL()) )
{
} else {
if (($this->oOriginalSet !== $oFellow->oOriginalSet)
&& ($this->oOriginalSet->GetFilter()->ToOQL() != $oFellow->oOriginalSet->GetFilter()->ToOQL())) {
throw new Exception('ormLinkSet::Equals assumes that compared link sets have the same original scope');
}
if ($this->HasDelta())
{
if ($this->HasDelta()) {
throw new Exception('ormLinkSet::Equals assumes that left link set had no delta');
}
$bRet = !$oFellow->HasDelta();
@@ -501,16 +461,13 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
public function UpdateFromCompleteList(iDBObjectSetIterator $oFellow)
{
if ($oFellow === $this)
{
if ($oFellow === $this) {
throw new Exception('ormLinkSet::UpdateFromCompleteList assumes that the passed link set is at least a clone of the current one');
}
$bUpdateFromDelta = false;
if ($oFellow instanceof ormLinkSet)
{
if ( ($this->oOriginalSet === $oFellow->oOriginalSet)
|| ($this->oOriginalSet->GetFilter()->ToOQL() == $oFellow->oOriginalSet->GetFilter()->ToOQL()) )
{
if ($oFellow instanceof ormLinkSet) {
if (($this->oOriginalSet === $oFellow->oOriginalSet)
|| ($this->oOriginalSet->GetFilter()->ToOQL() == $oFellow->oOriginalSet->GetFilter()->ToOQL())) {
$bUpdateFromDelta = true;
}
} else {
@@ -526,8 +483,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
}
}
if ($bUpdateFromDelta)
{
if ($bUpdateFromDelta) {
// Same original set -> simply update the delta
$this->iCursor = 0;
$this->aAdded = $oFellow->aAdded;
@@ -535,42 +491,36 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->aModified = $oFellow->aModified;
$this->aPreserved = $oFellow->aPreserved;
$this->bHasDelta = $oFellow->bHasDelta;
}
else
{
} else {
// For backward compatibility reasons, let's rebuild a delta...
// Reset the delta
$this->iCursor = 0;
$this->aAdded = array();
$this->aRemoved = array();
$this->aModified = array();
$this->aPreserved = ($this->aOriginalObjects === null) ? array() : $this->aOriginalObjects;
$this->aAdded = [];
$this->aRemoved = [];
$this->aModified = [];
$this->aPreserved = ($this->aOriginalObjects === null) ? [] : $this->aOriginalObjects;
$this->bHasDelta = false;
/** @var \AttributeLinkedSet|\AttributeLinkedSetIndirect $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($this->sHostClass, $this->sAttCode);
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
$sAdditionalKey = null;
if ($oAttDef->IsIndirect() && !$oAttDef->DuplicatesAllowed())
{
if ($oAttDef->IsIndirect() && !$oAttDef->DuplicatesAllowed()) {
$sAdditionalKey = $oAttDef->GetExtKeyToRemote();
}
// Compare both collections by iterating the whole sets, order them, a build a fingerprint based on meaningful data (what make the difference)
/** @var \DBObject $oLink */
$oComparator = new DBObjectSetComparator($this, $oFellow, array($sExtKeyToMe), $sAdditionalKey);
$oComparator = new DBObjectSetComparator($this, $oFellow, [$sExtKeyToMe], $sAdditionalKey);
$aChanges = $oComparator->GetDifferences();
foreach ($aChanges['added'] as $oLink)
{
foreach ($aChanges['added'] as $oLink) {
$this->AddItem($oLink);
}
foreach ($aChanges['modified'] as $oLink)
{
foreach ($aChanges['modified'] as $oLink) {
$this->ModifyItem($oLink);
}
foreach ($aChanges['removed'] as $oLink)
{
foreach ($aChanges['removed'] as $oLink) {
$this->RemoveItem($oLink->GetKey());
}
}
@@ -586,9 +536,8 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
{
$aAdded = $this->aAdded;
$aModified = $this->aModified;
$aRemoved = array();
if (count($this->aRemoved) > 0)
{
$aRemoved = [];
if (count($this->aRemoved) > 0) {
$oSearch = new DBObjectSearch($this->sClass);
$oSearch->AddCondition('id', $this->aRemoved, 'IN');
$oSet = new DBObjectSet($oSearch);
@@ -618,30 +567,23 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
$sExtKeyToRemote = $oAttDef->IsIndirect() ? $oAttDef->GetExtKeyToRemote() : 'n/a';
$aCheckLinks = array();
$aCheckRemote = array();
foreach ($this->aAdded as $oLink)
{
if ($oLink->IsNew())
{
if ($oAttDef->IsIndirect() && !$oAttDef->DuplicatesAllowed())
{
$aCheckLinks = [];
$aCheckRemote = [];
foreach ($this->aAdded as $oLink) {
if ($oLink->IsNew()) {
if ($oAttDef->IsIndirect() && !$oAttDef->DuplicatesAllowed()) {
//todo: faire un test qui passe dans cette branche !
$aCheckRemote[] = $oLink->Get($sExtKeyToRemote);
}
}
else
{
} else {
//todo: faire un test qui passe dans cette branche !
$aCheckLinks[] = $oLink->GetKey();
}
}
foreach ($this->aRemoved as $iLinkId)
{
foreach ($this->aRemoved as $iLinkId) {
$aCheckLinks[] = $iLinkId;
}
foreach ($this->aModified as $iLinkId => $oLink)
{
foreach ($this->aModified as $iLinkId => $oLink) {
$aCheckLinks[] = $oLink->GetKey();
}
@@ -653,11 +595,10 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
// Check for the existing links
//
/** @var DBObject[] $aExistingLinks */
$aExistingLinks = array();
$aExistingLinks = [];
/** @var Int[] $aExistingRemote */
$aExistingRemote = array();
if (count($aCheckLinks) > 0)
{
$aExistingRemote = [];
if (count($aCheckLinks) > 0) {
$oSearch = new DBObjectSearch($this->sClass);
$oSearch->AddCondition('id', $aCheckLinks, 'IN');
$oSet = new DBObjectSet($oSearch);
@@ -666,8 +607,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
// Check for the existing remote objects
//
if (count($aCheckRemote) > 0)
{
if (count($aCheckRemote) > 0) {
$oSearch = new DBObjectSearch($this->sClass);
$oSearch->AddCondition($sExtKeyToMe, $oHostObject->GetKey(), '=');
$oSearch->AddCondition($sExtKeyToRemote, $aCheckRemote, 'IN');
@@ -677,33 +617,27 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
// Write the links according to the existing links
//
foreach ($this->aAdded as $oLink)
{
foreach ($this->aAdded as $oLink) {
// Make sure that the objects in the set point to "this"
$oLink->Set($sExtKeyToMe, $oHostObject->GetKey());
if ($oLink->IsNew())
{
if (count($aCheckRemote) > 0)
{
$bIsDuplicate = false;
foreach($aExistingRemote as $sLinkKey => $sExtKey)
{
if ($sExtKey == $oLink->Get($sExtKeyToRemote))
{
// Do not create a duplicate
// + In the case of a remove action followed by an add action
// of an existing link,
// the final state to consider is add action,
// so suppress the entry in the removed list.
if (array_key_exists($sLinkKey, $this->aRemoved))
{
unset($this->aRemoved[$sLinkKey]);
}
$bIsDuplicate = true;
break;
}
}
if ($oLink->IsNew()) {
if (count($aCheckRemote) > 0) {
$bIsDuplicate = false;
foreach ($aExistingRemote as $sLinkKey => $sExtKey) {
if ($sExtKey == $oLink->Get($sExtKeyToRemote)) {
// Do not create a duplicate
// + In the case of a remove action followed by an add action
// of an existing link,
// the final state to consider is add action,
// so suppress the entry in the removed list.
if (array_key_exists($sLinkKey, $this->aRemoved)) {
unset($this->aRemoved[$sLinkKey]);
}
$bIsDuplicate = true;
break;
}
}
if ($bIsDuplicate) {
continue;
}
@@ -781,8 +715,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
/** @var \AttributeLinkedSet|\AttributeLinkedSetIndirect $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($this->sHostClass, $this->sAttCode);
$oLinkSearch = $this->GetFilter();
if ($oAttDef->IsIndirect())
{
if ($oAttDef->IsIndirect()) {
$oLinkSearch->RenameAlias($oLinkSearch->GetClassAlias(), self::LINK_ALIAS);
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
/** @var \AttributeExternalKey $oLinkingAttDef */
@@ -793,8 +726,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$sTargetClass = $oLinkingAttDef->GetTargetClass();
$oRemoteClassSearch = new DBObjectSearch($sTargetClass, self::REMOTE_ALIAS);
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
{
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass)) {
$oNotObsolete = new BinaryExpression(
new FieldExpression('obsolescence_flag', self::REMOTE_ALIAS),
'=',
@@ -803,8 +735,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$oRemoteClassSearch->AddConditionExpression($oNotObsolete);
}
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass))
{
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass)) {
$oNotArchived = new BinaryExpression(
new FieldExpression('archive_flag', self::REMOTE_ALIAS),
'=',
@@ -845,7 +776,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
public function GetValues()
{
$aValues = array();
$aValues = [];
foreach ($this->aPreserved as $sTagCode => $oTag) {
$aValues[] = $sTagCode;
}

View File

@@ -1,9 +1,10 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -20,16 +21,15 @@ require_once('backgroundprocess.inc.php');
/**
* ormStopWatch
* encapsulate the behavior of a stop watch that will be stored as an attribute of class AttributeStopWatch
* encapsulate the behavior of a stop watch that will be stored as an attribute of class AttributeStopWatch
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* ormStopWatch
* encapsulate the behavior of a stop watch that will be stored as an attribute of class AttributeStopWatch
* encapsulate the behavior of a stop watch that will be stored as an attribute of class AttributeStopWatch
*
* @package itopORM
*/
@@ -40,7 +40,7 @@ class ormStopWatch
protected $iLastStart; // unix time (seconds)
protected $iStopped; // unix time (seconds)
protected $aThresholds;
/**
* Constructor
*/
@@ -51,12 +51,12 @@ class ormStopWatch
$this->iLastStart = $iLastStart;
$this->iStopped = $iStopped;
$this->aThresholds = array();
$this->aThresholds = [];
}
/**
* Necessary for the triggers
*/
*/
public function __toString()
{
return (string) $this->iTimeSpent;
@@ -64,12 +64,12 @@ class ormStopWatch
public function DefineThreshold($iPercent, $tDeadline = null, $bPassed = false, $bTriggered = false, $iOverrun = null, $aHighlightDef = null)
{
$this->aThresholds[$iPercent] = array(
$this->aThresholds[$iPercent] = [
'deadline' => $tDeadline, // unix time (seconds)
'triggered' => $bTriggered,
'overrun' => $iOverrun,
'highlight' => $aHighlightDef, // array('code' => string, 'persistent' => boolean)
);
];
}
public function MarkThresholdAsTriggered($iPercent)
@@ -94,18 +94,14 @@ class ormStopWatch
*/
public function GetElapsedTime($oAttDef, $oObject)
{
if (is_null($this->iLastStart))
{
if (is_null($this->iLastStart)) {
return $this->GetTimeSpent();
}
else
{
} else {
$iElapsed = $this->ComputeDuration($oObject, $oAttDef, $this->iLastStart, time());
return $this->iTimeSpent + $iElapsed;
}
}
public function GetStartDate()
{
return $this->iStarted;
@@ -123,39 +119,30 @@ class ormStopWatch
public function GetThresholdDate($iPercent)
{
if (array_key_exists($iPercent, $this->aThresholds))
{
if (array_key_exists($iPercent, $this->aThresholds)) {
return $this->aThresholds[$iPercent]['deadline'];
}
else
{
} else {
return null;
}
}
public function GetOverrun($iPercent)
{
if (array_key_exists($iPercent, $this->aThresholds))
{
if (array_key_exists($iPercent, $this->aThresholds)) {
return $this->aThresholds[$iPercent]['overrun'];
}
else
{
} else {
return null;
}
}
public function IsThresholdPassed($iPercent)
{
$bRet = false;
if (array_key_exists($iPercent, $this->aThresholds))
{
if (array_key_exists($iPercent, $this->aThresholds)) {
$aThresholdData = $this->aThresholds[$iPercent];
if (!is_null($aThresholdData['deadline']) && ($aThresholdData['deadline'] <= time()))
{
if (!is_null($aThresholdData['deadline']) && ($aThresholdData['deadline'] <= time())) {
$bRet = true;
}
if (isset($aThresholdData['overrun']) && ($aThresholdData['overrun'] > 0))
{
if (isset($aThresholdData['overrun']) && ($aThresholdData['overrun'] > 0)) {
$bRet = true;
}
}
@@ -163,34 +150,27 @@ class ormStopWatch
}
public function IsThresholdTriggered($iPercent)
{
if (array_key_exists($iPercent, $this->aThresholds))
{
if (array_key_exists($iPercent, $this->aThresholds)) {
return $this->aThresholds[$iPercent]['triggered'];
}
else
{
} else {
return false;
}
}
public function GetHighlightCode()
{
$sCode = '';
// Process the thresholds in ascending order
$aPercents = array();
foreach($this->aThresholds as $iPercent => $aDefs)
{
$aPercents = [];
foreach ($this->aThresholds as $iPercent => $aDefs) {
$aPercents[] = $iPercent;
}
sort($aPercents, SORT_NUMERIC);
foreach($aPercents as $iPercent)
{
foreach ($aPercents as $iPercent) {
$aDefs = $this->aThresholds[$iPercent];
if (array_key_exists('highlight', $aDefs) && is_array($aDefs['highlight']) && $this->IsThresholdPassed($iPercent))
{
if (array_key_exists('highlight', $aDefs) && is_array($aDefs['highlight']) && $this->IsThresholdPassed($iPercent)) {
// If persistant or SW running...
if (($aDefs['highlight']['persistent'] == true) || (($aDefs['highlight']['persistent'] == false) && !is_null($this->iLastStart)))
{
if (($aDefs['highlight']['persistent'] == true) || (($aDefs['highlight']['persistent'] == false) && !is_null($this->iLastStart))) {
$sCode = $aDefs['highlight']['code'];
}
}
@@ -200,47 +180,37 @@ class ormStopWatch
public function GetAsHTML($oAttDef, $oHostObject = null)
{
$aProperties = array();
$aProperties = [];
$aProperties['States'] = implode(', ', $oAttDef->GetStates());
if (is_null($this->iLastStart))
{
if (is_null($this->iStarted))
{
if (is_null($this->iLastStart)) {
if (is_null($this->iStarted)) {
$aProperties['Elapsed'] = 'never started';
}
else
{
} else {
$aProperties['Elapsed'] = $this->iTimeSpent.' s';
}
}
else
{
$aProperties['Elapsed'] = 'running <img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/indicator.gif">';
} else {
$aProperties['Elapsed'] = 'running <img src="'.utils::GetAbsoluteUrlAppRoot().'images/indicator.gif">';
}
$aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted);
$aProperties['LastStart'] = $oAttDef->SecondsToDate($this->iLastStart);
$aProperties['Stopped'] = $oAttDef->SecondsToDate($this->iStopped);
foreach ($this->aThresholds as $iPercent => $aThresholdData)
{
foreach ($this->aThresholds as $iPercent => $aThresholdData) {
$sThresholdDesc = $oAttDef->SecondsToDate($aThresholdData['deadline']);
if ($aThresholdData['triggered'])
{
if ($aThresholdData['triggered']) {
$sThresholdDesc .= " <b>TRIGGERED</b>";
}
if ($aThresholdData['overrun'])
{
if ($aThresholdData['overrun']) {
$sThresholdDesc .= " Overrun:".(int) $aThresholdData['overrun']." sec.";
}
$aProperties[$iPercent.'%'] = $sThresholdDesc;
}
$sRes = "<TABLE>";
$sRes .= "<TBODY>";
foreach ($aProperties as $sProperty => $sValue)
{
foreach ($aProperties as $sProperty => $sValue) {
$sRes .= "<TR>";
$sCell = str_replace("\n", "<br>\n", $sValue ?? '');
$sRes .= "<TD class=\"label\">$sProperty</TD><TD>$sCell</TD>";
@@ -265,9 +235,8 @@ class ormStopWatch
/** @var \iMetricComputer $oComputer */
$oComputer = new $sMetricComputer();
$aCallSpec = array($oComputer, 'ComputeMetric');
if (!is_callable($aCallSpec))
{
$aCallSpec = [$oComputer, 'ComputeMetric'];
if (!is_callable($aCallSpec)) {
throw new CoreException("Unknown class/verb '$sMetricComputer/ComputeMetric'");
}
@@ -287,14 +256,12 @@ class ormStopWatch
protected function ComputeDeadline($oObject, $oAttDef, $iPercent, $iStartTime, $iDurationSec)
{
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
if ($sWorkingTimeComputer == '')
{
if ($sWorkingTimeComputer == '') {
$sWorkingTimeComputer = MetaModel::GetWorkingTime(get_class($oObject));
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetDeadline');
if (!is_callable($aCallSpec))
{
$aCallSpec = [$oComputer, 'GetDeadline'];
if (!is_callable($aCallSpec)) {
throw new CoreException("Unknown class/verb '$sWorkingTimeComputer/GetDeadline'");
}
// GetDeadline($oObject, $iDuration, DateTime $oStartDate)
@@ -316,14 +283,12 @@ class ormStopWatch
protected function ComputeDuration($oObject, $oAttDef, $iStartTime, $iEndTime)
{
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
if ($sWorkingTimeComputer == '')
{
if ($sWorkingTimeComputer == '') {
$sWorkingTimeComputer = MetaModel::GetWorkingTime(get_class($oObject));
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetOpenDuration');
if (!is_callable($aCallSpec))
{
$aCallSpec = [$oComputer, 'GetOpenDuration'];
if (!is_callable($aCallSpec)) {
throw new CoreException("Unknown class/verb '$sWorkingTimeComputer/GetOpenDuration'");
}
// GetOpenDuration($oObject, DateTime $oStartDate, DateTime $oEndDate)
@@ -339,14 +304,12 @@ class ormStopWatch
$this->iStopped = null;
$this->iStarted = null;
foreach ($this->aThresholds as $iPercent => &$aThresholdData)
{
foreach ($this->aThresholds as $iPercent => &$aThresholdData) {
$aThresholdData['triggered'] = false;
$aThresholdData['overrun'] = null;
}
if (!is_null($this->iLastStart))
{
if (!is_null($this->iLastStart)) {
// Currently running... starting again from now!
$this->iStarted = time();
$this->iLastStart = time();
@@ -357,23 +320,20 @@ class ormStopWatch
/**
* Start or continue
* It is the responsibility of the caller to compute the deadlines
* (to avoid computing twice for the same result)
*/
* (to avoid computing twice for the same result)
*/
public function Start($oObject, $oAttDef, $iNow = null)
{
if (!is_null($this->iLastStart))
{
if (!is_null($this->iLastStart)) {
// Already started
return false;
}
if (is_null($iNow))
{
if (is_null($iNow)) {
$iNow = time();
}
if (is_null($this->iStarted))
{
if (is_null($this->iStarted)) {
$this->iStarted = $iNow;
}
$this->iLastStart = $iNow;
@@ -384,39 +344,31 @@ class ormStopWatch
/**
* Compute or recompute the goal and threshold deadlines
*/
*/
public function ComputeDeadlines($oObject, $oAttDef)
{
if (is_null($this->iLastStart))
{
if (is_null($this->iLastStart)) {
// Currently stopped - do nothing
return false;
}
$iDurationGoal = $this->ComputeGoal($oObject, $oAttDef);
$iComputationRefTime = time();
foreach ($this->aThresholds as $iPercent => &$aThresholdData)
{
if (is_null($iDurationGoal))
{
foreach ($this->aThresholds as $iPercent => &$aThresholdData) {
if (is_null($iDurationGoal)) {
// No limit: leave null thresholds
$aThresholdData['deadline'] = null;
}
else
{
} else {
$iThresholdDuration = round($iPercent * $iDurationGoal / 100);
if (class_exists('WorkingTimeRecorder'))
{
if (class_exists('WorkingTimeRecorder')) {
$sClass = get_class($oObject);
$sAttCode = $oAttDef->GetCode();
WorkingTimeRecorder::Start($oObject, $iComputationRefTime, "ormStopWatch-Deadline-$iPercent-$sAttCode", 'Core:ExplainWTC:StopWatch-Deadline', array("Class:$sClass/Attribute:$sAttCode", $iPercent));
WorkingTimeRecorder::Start($oObject, $iComputationRefTime, "ormStopWatch-Deadline-$iPercent-$sAttCode", 'Core:ExplainWTC:StopWatch-Deadline', ["Class:$sClass/Attribute:$sAttCode", $iPercent]);
}
$iRemaining = $iThresholdDuration - $this->iTimeSpent;
if ($iRemaining < 0)
{
if (class_exists('WorkingTimeRecorder'))
{
if ($iRemaining < 0) {
if (class_exists('WorkingTimeRecorder')) {
$sClass = get_class($oObject);
$sKey = $oObject->GetKey();
$sAttCode = $oAttDef->GetCode();
@@ -428,13 +380,11 @@ class ormStopWatch
$aThresholdData['deadline'] = $this->ComputeDeadline($oObject, $oAttDef, $iPercent, $this->iLastStart, $iRemaining);
// OR $aThresholdData['deadline'] = $this->ComputeDeadline($oObject, $oAttDef, $iPercent, $this->iStarted, $iThresholdDuration);
if (class_exists('WorkingTimeRecorder'))
{
if (class_exists('WorkingTimeRecorder')) {
WorkingTimeRecorder::End();
}
}
if (is_null($aThresholdData['deadline']) || ($aThresholdData['deadline'] > time()))
{
if (is_null($aThresholdData['deadline']) || ($aThresholdData['deadline'] > time())) {
// The threshold is in the future, reset
$aThresholdData['triggered'] = false;
$aThresholdData['overrun'] = null;
@@ -452,51 +402,41 @@ class ormStopWatch
/**
* Stop counting if not already done
*/
*/
public function Stop($oObject, $oAttDef, $iNow = null)
{
if (is_null($this->iLastStart))
{
if (is_null($this->iLastStart)) {
// Already stopped
return false;
}
if (is_null($iNow))
{
if (is_null($iNow)) {
$iNow = time();
}
if (class_exists('WorkingTimeRecorder'))
{
if (class_exists('WorkingTimeRecorder')) {
$sClass = get_class($oObject);
$sAttCode = $oAttDef->GetCode();
WorkingTimeRecorder::Start($oObject, $iNow, "ormStopWatch-TimeSpent-$sAttCode", 'Core:ExplainWTC:StopWatch-TimeSpent', array("Class:$sClass/Attribute:$sAttCode"), true /*cumulative*/);
WorkingTimeRecorder::Start($oObject, $iNow, "ormStopWatch-TimeSpent-$sAttCode", 'Core:ExplainWTC:StopWatch-TimeSpent', ["Class:$sClass/Attribute:$sAttCode"], true /*cumulative*/);
}
$iElapsed = $this->ComputeDuration($oObject, $oAttDef, $this->iLastStart, $iNow);
$this->iTimeSpent = $this->iTimeSpent + $iElapsed;
if (class_exists('WorkingTimeRecorder'))
{
if (class_exists('WorkingTimeRecorder')) {
WorkingTimeRecorder::End();
}
foreach ($this->aThresholds as $iPercent => &$aThresholdData)
{
if (!is_null($aThresholdData['deadline']) && ($iNow > $aThresholdData['deadline']))
{
if ($aThresholdData['overrun'] > 0)
{
foreach ($this->aThresholds as $iPercent => &$aThresholdData) {
if (!is_null($aThresholdData['deadline']) && ($iNow > $aThresholdData['deadline'])) {
if ($aThresholdData['overrun'] > 0) {
// Accumulate from last start
$aThresholdData['overrun'] += $iElapsed;
}
else
{
} else {
// First stop after the deadline has been passed
$iOverrun = $this->ComputeDuration($oObject, $oAttDef, $aThresholdData['deadline'], $iNow);
$aThresholdData['overrun'] = $iOverrun;
}
}
if ($aThresholdData['overrun'] == 0)
{
if ($aThresholdData['overrun'] == 0) {
$aThresholdData['deadline'] = null;
}
}
@@ -510,76 +450,65 @@ class ormStopWatch
/**
* CheckStopWatchThresholds
* Implements the automatic actions
* Implements the automatic actions
*
* @package itopORM
*/
class CheckStopWatchThresholds implements iBackgroundProcess
{
public function GetPeriodicity()
{
{
return 10; // seconds
}
public function Process($iTimeLimit)
{
$aList = array();
foreach (MetaModel::GetClasses() as $sClass)
{
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if ($oAttDef instanceof AttributeStopWatch)
{
foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData)
{
$aList = [];
foreach (MetaModel::GetClasses() as $sClass) {
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
if ($oAttDef instanceof AttributeStopWatch) {
foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData) {
$iPercent = $aThresholdData['percent']; // could be different than the index !
$sNow = date(AttributeDateTime::GetSQLFormat());
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < :now";
$oFilter = DBObjectSearch::FromOQL($sExpression);
$oSet = new DBObjectSet($oFilter, array(), array('now' => $sNow));
$oSet->OptimizeColumnLoad(array($sClass => array($sAttCode)));
while ((time() < $iTimeLimit) && ($oObj = $oSet->Fetch()))
{
$oSet = new DBObjectSet($oFilter, [], ['now' => $sNow]);
$oSet->OptimizeColumnLoad([$sClass => [$sAttCode]]);
while ((time() < $iTimeLimit) && ($oObj = $oSet->Fetch())) {
$sClass = get_class($oObj);
$aList[] = $sClass.'::'.$oObj->GetKey().' '.$sAttCode.' '.$iThreshold;
// Execute planned actions
//
foreach ($aThresholdData['actions'] as $aActionData)
{
foreach ($aThresholdData['actions'] as $aActionData) {
$sVerb = $aActionData['verb'];
$aParams = $aActionData['params'];
$aValues = array();
foreach($aParams as $def)
{
if (is_string($def))
{
$aValues = [];
foreach ($aParams as $def) {
if (is_string($def)) {
// Old method (pre-2.1.0) non typed parameters
$aValues[] = $def;
}
else // if(is_array($def))
{
} else { // if(is_array($def))
$sParamType = array_key_exists('type', $def) ? $def['type'] : 'string';
switch($sParamType)
{
switch ($sParamType) {
case 'int':
$value = (int)$def['value'];
break;
case 'float':
$value = (float)$def['value'];
break;
case 'bool':
$value = (bool)$def['value'];
break;
case 'reference':
$value = ${$def['value']};
break;
case 'string':
default:
$value = (string)$def['value'];
@@ -587,7 +516,7 @@ class CheckStopWatchThresholds implements iBackgroundProcess
$aValues[] = $value;
}
}
$aCallSpec = array($oObj, $sVerb);
$aCallSpec = [$oObj, $sVerb];
call_user_func_array($aCallSpec, $aValues);
}
@@ -604,22 +533,18 @@ class CheckStopWatchThresholds implements iBackgroundProcess
}
// Activate any existing trigger
//
//
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oTriggerSet = new DBObjectSet(
DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('$sClassList') AND stop_watch_code MATCHES :stop_watch_code AND threshold_index = :threshold_index"),
array(), // order by
array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold)
[], // order by
['stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold]
);
while ($oTrigger = $oTriggerSet->Fetch())
{
try
{
while ($oTrigger = $oTriggerSet->Fetch()) {
try {
$oTrigger->DoActivate($oObj->ToArgs('this'));
}
catch(Exception $e)
{
} catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -412,4 +412,4 @@ class SimpleCryptOpenSSLMcryptCompatibilityEngine implements CryptEngine
return trim($plaintext);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -22,7 +23,6 @@
*/
class SimpleGraphException extends Exception
{
}
/**
@@ -32,7 +32,7 @@ class GraphElement
{
protected $sId;
protected $aProperties;
/**
* Constructor
* @param string $sId The identifier of the object in the graph
@@ -40,9 +40,9 @@ class GraphElement
public function __construct($sId)
{
$this->sId = $sId;
$this->aProperties = array();
$this->aProperties = [];
}
/**
* Get the identifier of the object in the graph
* @return string
@@ -51,7 +51,7 @@ class GraphElement
{
return $this->sId;
}
/**
* Get the value of the given named property for the object
* @param string $sPropName The name of the property to get
@@ -73,7 +73,7 @@ class GraphElement
{
$this->aProperties[$sPropName] = $value;
}
/**
* Get all the known properties of the object
* @return Ambigous <multitype:, mixed>
@@ -91,7 +91,7 @@ class GraphNode extends GraphElement
{
protected $aIncomingEdges;
protected $aOutgoingEdges;
/**
* Create a new node inside a graph
* @param SimpleGraph $oGraph
@@ -100,16 +100,15 @@ class GraphNode extends GraphElement
public function __construct(SimpleGraph $oGraph, $sId)
{
parent::__construct($sId);
$this->aIncomingEdges = array();
$this->aOutgoingEdges = array();
$this->aIncomingEdges = [];
$this->aOutgoingEdges = [];
$oGraph->_AddNode($this);
}
public function GetDotAttributes($bNoLabel = false)
{
$sDot = '';
if (!$bNoLabel)
{
if (!$bNoLabel) {
$sLabel = addslashes($this->GetProperty('label', $this->GetId()));
$sDot = 'label="'.$sLabel.'"';
}
@@ -133,7 +132,7 @@ class GraphNode extends GraphElement
{
$this->aOutgoingEdges[$oEdge->GetId()] = $oEdge;
}
/**
* INTERNAL USE ONLY
* @param GraphEdge $oEdge
@@ -151,7 +150,7 @@ class GraphNode extends GraphElement
{
unset($this->aOutgoingEdges[$oEdge->GetId()]);
}
/**
* Get the list of all incoming edges on the current node
* @return Ambigous <multitype:, GraphEdge>
@@ -160,7 +159,7 @@ class GraphNode extends GraphElement
{
return $this->aIncomingEdges;
}
/**
* Get the list of all outgoing edges from the current node
* @return Ambigous <multitype:, GraphEdge>
@@ -169,7 +168,7 @@ class GraphNode extends GraphElement
{
return $this->aOutgoingEdges;
}
/**
* Flood fill the chart with the given value for the specified property
* @param string $sPropName The name of the property to set
@@ -179,29 +178,24 @@ class GraphNode extends GraphElement
*/
public function FloodProperty($sPropName, $value, $bFloodDown, $bFloodUp)
{
if ($this->GetProperty($sPropName, null) == null)
{
if ($this->GetProperty($sPropName, null) == null) {
// Property not already set, let's do it
$this->SetProperty($sPropName, $value);
if ($bFloodDown)
{
foreach($this->GetOutgoingEdges() as $oEdge)
{
if ($bFloodDown) {
foreach ($this->GetOutgoingEdges() as $oEdge) {
$oEdge->SetProperty($sPropName, $value);
$oEdge->GetSinkNode()->FloodProperty($sPropName, $value, $bFloodDown, $bFloodUp);
}
}
if ($bFloodUp)
{
foreach($this->GetIncomingEdges() as $oEdge)
{
if ($bFloodUp) {
foreach ($this->GetIncomingEdges() as $oEdge) {
$oEdge->SetProperty($sPropName, $value);
$oEdge->GetSourceNode()->FloodProperty($sPropName, $value, $bFloodDown, $bFloodUp);
}
}
}
}
}
/**
@@ -237,7 +231,7 @@ class GraphEdge extends GraphElement
{
return $this->oSourceNode;
}
/**
* Get the "sink" node for this edge
* @return GraphNode
@@ -250,8 +244,7 @@ class GraphEdge extends GraphElement
public function GetDotAttributes($bNoLabel = false)
{
$sDot = '';
if (!$bNoLabel)
{
if (!$bNoLabel) {
$sLabel = addslashes($this->GetProperty('label', ''));
$sDot = 'label="'.$sLabel.'"';
}
@@ -266,16 +259,16 @@ class SimpleGraph
{
protected $aNodes;
protected $aEdges;
/**
* Creates a new empty graph
*/
public function __construct()
{
$this->aNodes = array();
$this->aEdges = array();
$this->aNodes = [];
$this->aEdges = [];
}
/**
* INTERNAL USE ONLY
* @return Ambigous <multitype:, GraphNode>
@@ -284,7 +277,7 @@ class SimpleGraph
{
return $this->aNodes;
}
/**
* INTERNAL USE ONLY
* @return Ambigous <multitype:, GraphNode>
@@ -293,32 +286,34 @@ class SimpleGraph
{
return $this->aEdges;
}
/**
* INTERNAL USE ONLY
* @return Ambigous <multitype:, GraphNode>
*/
public function _AddNode(GraphNode $oNode)
{
if (array_key_exists($oNode->GetId(), $this->aNodes)) throw new SimpleGraphException('Cannot add node (id='.$oNode->GetId().') to the graph. A node with the same id already exists in the graph.');
if (array_key_exists($oNode->GetId(), $this->aNodes)) {
throw new SimpleGraphException('Cannot add node (id='.$oNode->GetId().') to the graph. A node with the same id already exists in the graph.');
}
$this->aNodes[$oNode->GetId()] = $oNode;
}
/**
* INTERNAL USE ONLY
* @return Ambigous <multitype:, GraphNode>
*/
public function _RemoveNode(GraphNode $oNode)
{
if (!array_key_exists($oNode->GetId(), $this->aNodes)) throw new SimpleGraphException('Cannot remove the node (id='.$oNode->GetId().') from the graph. The node was not found in the graph.');
foreach($oNode->GetOutgoingEdges() as $oEdge)
{
if (!array_key_exists($oNode->GetId(), $this->aNodes)) {
throw new SimpleGraphException('Cannot remove the node (id='.$oNode->GetId().') from the graph. The node was not found in the graph.');
}
foreach ($oNode->GetOutgoingEdges() as $oEdge) {
$this->_RemoveEdge($oEdge);
}
foreach($oNode->GetIncomingEdges() as $oEdge)
{
foreach ($oNode->GetIncomingEdges() as $oEdge) {
$this->_RemoveEdge($oEdge);
}
unset($this->aNodes[$oNode->GetId()]);
@@ -333,42 +328,37 @@ class SimpleGraph
*/
public function FilterNode(GraphNode $oNode, $bAllowLoopingEdge = false)
{
if (!array_key_exists($oNode->GetId(), $this->aNodes)) throw new SimpleGraphException('Cannot filter the node (id='.$oNode->GetId().') from the graph. The node was not found in the graph.');
$aSourceNodes = array();
$aSinkNodes = array();
foreach($oNode->GetOutgoingEdges() as $oEdge)
{
if (!array_key_exists($oNode->GetId(), $this->aNodes)) {
throw new SimpleGraphException('Cannot filter the node (id='.$oNode->GetId().') from the graph. The node was not found in the graph.');
}
$aSourceNodes = [];
$aSinkNodes = [];
foreach ($oNode->GetOutgoingEdges() as $oEdge) {
$sSinkId = $oEdge->GetSinkNode()->GetId();
if ($sSinkId != $oNode->GetId())
{
if ($sSinkId != $oNode->GetId()) {
$aSinkNodes[$sSinkId] = $oEdge->GetSinkNode();
}
$this->_RemoveEdge($oEdge);
}
foreach($oNode->GetIncomingEdges() as $oEdge)
{
foreach ($oNode->GetIncomingEdges() as $oEdge) {
$sSourceId = $oEdge->GetSourceNode()->GetId();
if ($sSourceId != $oNode->GetId())
{
if ($sSourceId != $oNode->GetId()) {
$aSourceNodes[$sSourceId] = $oEdge->GetSourceNode();
}
$this->_RemoveEdge($oEdge);
}
unset($this->aNodes[$oNode->GetId()]);
foreach($aSourceNodes as $sSourceId => $oSourceNode)
{
foreach($aSinkNodes as $sSinkId => $oSinkNode)
{
if ($bAllowLoopingEdge || ($oSourceNode->GetId() != $oSinkNode->GetId()))
{
foreach ($aSourceNodes as $sSourceId => $oSourceNode) {
foreach ($aSinkNodes as $sSinkId => $oSinkNode) {
if ($bAllowLoopingEdge || ($oSourceNode->GetId() != $oSinkNode->GetId())) {
$oEdge = new RelationEdge($this, $oSourceNode, $oSinkNode);
}
}
}
}
/**
* Get the node identified by $sId or null if not found
* @param string $sId
@@ -376,7 +366,7 @@ class SimpleGraph
*/
public function GetNode($sId)
{
return array_key_exists($sId, $this->aNodes) ? $this->aNodes[$sId] : null;
return array_key_exists($sId, $this->aNodes) ? $this->aNodes[$sId] : null;
}
/**
@@ -386,7 +376,7 @@ class SimpleGraph
*/
public function HasNode($sId)
{
return array_key_exists($sId, $this->aNodes);
return array_key_exists($sId, $this->aNodes);
}
/**
@@ -397,23 +387,19 @@ class SimpleGraph
*/
public function _AddEdge(GraphEdge $oEdge, $bMustBeUnique = false)
{
if (array_key_exists($oEdge->GetId(), $this->aEdges))
{
if ($bMustBeUnique)
{
throw new SimpleGraphException('Cannot add edge (id=' . $oEdge->GetId() . ') to the graph. An edge with the same id already exists in the graph.');
}
else
{
if (array_key_exists($oEdge->GetId(), $this->aEdges)) {
if ($bMustBeUnique) {
throw new SimpleGraphException('Cannot add edge (id='.$oEdge->GetId().') to the graph. An edge with the same id already exists in the graph.');
} else {
return;
}
}
$this->aEdges[$oEdge->GetId()] = $oEdge;
$oEdge->GetSourceNode()->_AddOutgoingEdge($oEdge);
$oEdge->GetSinkNode()->_AddIncomingEdge($oEdge);
}
/**
* INTERNAL USE ONLY
* @param GraphEdge $oEdge
@@ -421,14 +407,16 @@ class SimpleGraph
*/
public function _RemoveEdge(GraphEdge $oEdge)
{
if (!array_key_exists($oEdge->GetId(), $this->aEdges)) throw new SimpleGraphException('Cannot remove edge (id='.$oEdge->GetId().') from the graph. The edge was not found.');
if (!array_key_exists($oEdge->GetId(), $this->aEdges)) {
throw new SimpleGraphException('Cannot remove edge (id='.$oEdge->GetId().') from the graph. The edge was not found.');
}
$oEdge->GetSourceNode()->_RemoveOutgoingEdge($oEdge);
$oEdge->GetSinkNode()->_RemoveIncomingEdge($oEdge);
unset($this->aEdges[$oEdge->GetId()]);
}
/**
* Get the edge indentified by $sId or null if not found
* @param string $sId
@@ -438,7 +426,7 @@ class SimpleGraph
{
return array_key_exists($sId, $this->aEdges) ? $this->aEdges[$sId] : null;
}
/**
* Determine if the id already exists in amongst the existing edges
* @param string $sId
@@ -446,7 +434,7 @@ class SimpleGraph
*/
public function HasEdge($sId)
{
return array_key_exists($sId, $this->aEdges);
return array_key_exists($sId, $this->aEdges);
}
/**
@@ -470,23 +458,20 @@ EOF
;
$oIterator = new RelationTypeIterator($this, 'Node');
foreach($oIterator as $key => $oNode)
{
foreach ($oIterator as $key => $oNode) {
$sDot .= "\t\"".$oNode->GetId()."\" [ ".$oNode->GetDotAttributes($bNoLabel)." ];\n";
if (count($oNode->GetOutgoingEdges()) > 0)
{
foreach($oNode->GetOutgoingEdges() as $oEdge)
{
if (count($oNode->GetOutgoingEdges()) > 0) {
foreach ($oNode->GetOutgoingEdges() as $oEdge) {
$sDot .= "\t\"".$oNode->GetId()."\" -> \"".$oEdge->GetSinkNode()->GetId()."\" [ ".$oEdge->GetDotAttributes($bNoLabel)." ];\n";
}
}
}
$sDot .= "}\n";
return $sDot;
return $sDot;
}
/**
* Get the description of the graph as an embedded PNG image (using a data: url) as
* generated by graphviz (requires graphviz to be installed on the machine and the path to
@@ -497,51 +482,43 @@ EOF
public function DumpAsHtmlImage()
{
$sDotExecutable = MetaModel::GetConfig()->Get('graphviz_path');
if (file_exists($sDotExecutable))
{
if (file_exists($sDotExecutable)) {
// create the file with Graphviz
if (!is_dir(utils::GetDataPath()))
{
if (!is_dir(utils::GetDataPath())) {
@mkdir(utils::GetDataPath());
}
if (!is_dir(utils::GetDataPath()."tmp"))
{
if (!is_dir(utils::GetDataPath()."tmp")) {
@mkdir(utils::GetDataPath()."tmp");
}
$sImageFilePath = tempnam(utils::GetDataPath()."tmp", 'png-');
$sDotDescription = $this->GetDotDescription();
$sDotFilePath = tempnam(utils::GetDataPath()."tmp", 'dot-');
$rFile = @fopen($sDotFilePath, "w");
@fwrite($rFile, $sDotDescription);
@fclose($rFile);
$aOutput = array();
$aOutput = [];
$CommandLine = "\"$sDotExecutable\" -v -Tpng < \"$sDotFilePath\" -o\"$sImageFilePath\" 2>&1";
exec($CommandLine, $aOutput, $iRetCode);
if ($iRetCode != 0)
{
if ($iRetCode != 0) {
$sHtml = '';
$sHtml .= "<p><b>Error:</b></p>";
$sHtml .= "<p>The command: <pre>$CommandLine</pre> returned $iRetCode</p>";
$sHtml .= "<p>The output of the command is:<pre>\n".implode("\n", $aOutput)."</pre></p>";
$sHtml .= "<hr>";
$sHtml .= "<p>Content of the '".basename($sDotFilePath)."' file:<pre>\n$sDotDescription</pre>";
}
else
{
} else {
$sHtml = '<img src="data:image/png;base64,'.base64_encode(file_get_contents($sImageFilePath)).'">';
@unlink($sImageFilePath);
}
@unlink($sDotFilePath);
}
else
{
throw new Exception('graphviz not found');
} else {
throw new Exception('graphviz not found');
}
return $sHtml;
}
/**
* Get the description of the graph as text string in the XDot format
* including the positions of the nodes and egdes (requires graphviz
@@ -553,51 +530,42 @@ EOF
public function DumpAsXDot()
{
$sDotExecutable = MetaModel::GetConfig()->Get('graphviz_path');
if (file_exists($sDotExecutable))
{
if (file_exists($sDotExecutable)) {
// create the file with Graphviz
if (!is_dir(utils::GetDataPath()))
{
if (!is_dir(utils::GetDataPath())) {
@mkdir(utils::GetDataPath());
}
if (!is_dir(utils::GetDataPath()."tmp"))
{
if (!is_dir(utils::GetDataPath()."tmp")) {
@mkdir(utils::GetDataPath()."tmp");
}
$sXdotFilePath = tempnam(utils::GetDataPath()."tmp", 'xdot-');
$sDotDescription = $this->GetDotDescription(true); // true => don't put (localized) labels in the file, since it makes it harder to parse
$sDotFilePath = tempnam(utils::GetDataPath()."tmp", 'dot-');
$rFile = @fopen($sDotFilePath, "w");
@fwrite($rFile, $sDotDescription);
@fclose($rFile);
$aOutput = array();
$aOutput = [];
$CommandLine = "\"$sDotExecutable\" -v -Tdot < \"$sDotFilePath\" -o\"$sXdotFilePath\" 2>&1";
exec($CommandLine, $aOutput, $iRetCode);
if ($iRetCode != 0)
{
if ($iRetCode != 0) {
$sHtml = '';
$sHtml .= "<p><b>Error:</b></p>";
$sHtml .= "<p>The command: <pre>$CommandLine</pre> returned $iRetCode</p>";
$sHtml .= "<p>The output of the command is:<pre>\n".implode("\n", $aOutput)."</pre></p>";
IssueLog::Error($sHtml);
}
else
{
} else {
$sHtml = '<pre>'.file_get_contents($sXdotFilePath).'</pre>';
@unlink($sXdotFilePath);
}
@unlink($sDotFilePath);
}
else
{
throw new Exception('graphviz not found');
} else {
throw new Exception('graphviz not found');
}
return $sHtml;
}
/**
* Get the description of the graph as some HTML text
* @return string
@@ -606,42 +574,36 @@ EOF
{
$sHtml = '';
$oIterator = new RelationTypeIterator($this);
foreach($oIterator as $key => $oElement)
{
foreach ($oIterator as $key => $oElement) {
$sHtml .= "<p>$key: ".get_class($oElement)."::".$oElement->GetId()."</p>";
switch(get_class($oElement))
{
switch (get_class($oElement)) {
case 'GraphNode':
if (count($oElement->GetIncomingEdges()) > 0)
{
if (count($oElement->GetIncomingEdges()) > 0) {
$sHtml .= "<ul>Incoming edges:\n";
foreach($oElement->GetIncomingEdges() as $oEdge)
{
foreach ($oElement->GetIncomingEdges() as $oEdge) {
$sHtml .= "<li>From: ".$oEdge->GetSourceNode()->GetId()."</li>\n";
}
$sHtml .= "</ul>\n";
}
if (count($oElement->GetOutgoingEdges()) > 0)
{
if (count($oElement->GetOutgoingEdges()) > 0) {
$sHtml .= "<ul>Outgoing edges:\n";
foreach($oElement->GetOutgoingEdges() as $oEdge)
{
foreach ($oElement->GetOutgoingEdges() as $oEdge) {
$sHtml .= "<li>To: ".$oEdge->GetSinkNode()->GetId()."</li>\n";
}
$sHtml .= "</ul>\n";
}
break;
case 'GraphEdge':
$sHtml .= "<p>From: ".$oElement->GetSourceNode()->GetId().", to:".$oElement->GetSinkNode()->GetId()."</p>\n";
break;
}
}
return $sHtml;
return $sHtml;
}
/**
* Split the graph in a array of non connected subgraphs
* @return multitype:SimpleGraph unknown
@@ -649,48 +611,40 @@ EOF
public function GetSubgraphs()
{
$iNbColors = 0;
$aResult = array();
$aResult = [];
$oIterator = new RelationTypeIterator($this, 'Node');
foreach($oIterator as $oNode)
{
foreach ($oIterator as $oNode) {
$iPrevColor = $oNode->GetProperty('color', null);
if ($iPrevColor == null)
{
if ($iPrevColor == null) {
$iNbColors++; // Start a new color
$oNode->FloodProperty('color', $iNbColors, true, true);
}
}
if ($iNbColors == 1)
{
if ($iNbColors == 1) {
// Everything is connected together, only one subgraph
$aResult[] = $this;
}
else
{
} else {
// Let's reconstruct each separate graph
$sClass = get_class($this);
for($i = 1; $i <= $iNbColors; $i++)
{
for ($i = 1; $i <= $iNbColors; $i++) {
$aResult[$i] = new $sClass();
}
foreach($oIterator as $oNode)
{
foreach ($oIterator as $oNode) {
$iNodeColor = $oNode->GetProperty('color');
$aResult[$iNodeColor]->_AddNode($oNode);
}
$oIter2 = new RelationTypeIterator($this, 'Edge');
foreach($oIter2 as $oEdge)
{
foreach ($oIter2 as $oEdge) {
$iEdgeColor = $oEdge->GetProperty('color');
$aResult[$iEdgeColor]->_AddEdge($oEdge);
}
}
return $aResult;
return $aResult;
}
/**
* Merge back two subgraphs into one
* @param SimpleGraph $oGraph
@@ -698,13 +652,11 @@ EOF
public function Merge(SimpleGraph $oGraph)
{
$oIter1 = new RelationTypeIterator($oGraph, 'Node');
foreach($oIter1 as $oNode)
{
foreach ($oIter1 as $oNode) {
$this->_AddNode($oNode);
}
$oIter2 = new RelationTypeIterator($oGraph, 'Edge');
foreach($oIter2 as $oEdge)
{
foreach ($oIter2 as $oEdge) {
$this->_AddEdge($oEdge);
}
}
@@ -718,7 +670,7 @@ class RelationTypeIterator implements Iterator
{
protected $iCurrentIdx;
protected $aList;
/**
* Constructor
* @param SimpleGraph $oGraph The graph to browse
@@ -727,46 +679,53 @@ class RelationTypeIterator implements Iterator
public function __construct(SimpleGraph $oGraph, $sType = null)
{
$this->iCurrentIdx = -1;
$this->aList = array();
switch($sType)
{
$this->aList = [];
switch ($sType) {
case 'Node':
foreach($oGraph->_GetNodes() as $oNode) $this->aList[] = $oNode;
break;
foreach ($oGraph->_GetNodes() as $oNode) {
$this->aList[] = $oNode;
}
break;
case 'Edge':
foreach($oGraph->_GetEdges() as $oEdge) $this->aList[] = $oEdge;
break;
foreach ($oGraph->_GetEdges() as $oEdge) {
$this->aList[] = $oEdge;
}
break;
default:
foreach($oGraph->_GetNodes() as $oNode) $this->aList[] = $oNode;
foreach($oGraph->_GetEdges() as $oEdge) $this->aList[] = $oEdge;
foreach ($oGraph->_GetNodes() as $oNode) {
$this->aList[] = $oNode;
}
foreach ($oGraph->_GetEdges() as $oEdge) {
$this->aList[] = $oEdge;
}
}
}
public function rewind(): void
{
$this->iCurrentIdx = 0;
}
public function valid(): bool
{
return array_key_exists($this->iCurrentIdx, $this->aList);
}
public function next(): void
{
$this->iCurrentIdx++;
}
// Return type mixed is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+
#[\ReturnTypeWillChange]
public function current()
{
return $this->aList[$this->iCurrentIdx];
}
// Return type mixed is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+
#[\ReturnTypeWillChange]
public function key()

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -33,8 +34,8 @@ abstract class Trigger extends cmdbAbstractObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -45,21 +46,23 @@ abstract class Trigger extends cmdbAbstractObject
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-conflict.svg'),
);
];
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("action_list",
array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "trigger_id", "ext_key_to_remote" => "action_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
"action_list",
["linked_class" => "lnkTriggerAction", "ext_key_to_me" => "trigger_id", "ext_key_to_remote" => "action_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => []]
));
$aTags = ContextTag::GetTags();
MetaModel::Init_AddAttribute(new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags, true), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12)));
MetaModel::Init_AddAttribute(new AttributeEnumSet("context", ["allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags, true), "sql" => "context", "depends_on" => [], "is_null_allowed" => true, "max_items" => 12]));
// "complement" is a computed field, fed by Trigger sub-classes, in general in ComputeValues method, for eg. the TriggerOnObject fed it with target_class info
MetaModel::Init_AddAttribute(new AttributeString("complement", array("allowed_values" => null, "sql" => "complement", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", array("allowed_values" => new ValueSetEnum(Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::cases()), "sql" => "subscription_policy", "default_value" => \Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::AllowNoChannel->value, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("complement", ["allowed_values" => null, "sql" => "complement", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", ["allowed_values" => new ValueSetEnum(Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::cases()), "sql" => "subscription_policy", "default_value" => \Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::AllowNoChannel->value, "is_null_allowed" => false, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'subscription_policy', 'action_list', 'complement')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'complement')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['finalclass', 'description', 'context', 'subscription_policy', 'action_list', 'complement']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'complement']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
@@ -78,17 +81,14 @@ abstract class Trigger extends cmdbAbstractObject
$oContext = $this->Get('context');
$bChecked = false;
$bValid = false;
foreach ($oContext->GetValues() as $sValue)
{
foreach ($oContext->GetValues() as $sValue) {
$bChecked = true;
if (ContextTag::Check($sValue))
{
if (ContextTag::Check($sValue)) {
$bValid = true;
break;
}
}
if ($bChecked && !$bValid)
{
if ($bChecked && !$bValid) {
// Trigger does not match the current context
return false;
}
@@ -105,8 +105,7 @@ abstract class Trigger extends cmdbAbstractObject
public function DoActivate($aContextArgs)
{
// Check the context
if (!$this->IsContextValid())
{
if (!$this->IsContextValid()) {
// Trigger does not match the current context
$sClass = get_class($this);
$sName = $this->Get('friendlyname');
@@ -128,7 +127,7 @@ abstract class Trigger extends cmdbAbstractObject
// Execute actions
foreach ($aActionListOrdered as $aActionSubList) {
foreach ($aActionSubList as $oLink) /** @var \DBObject $oLink */ {
foreach ($aActionSubList as $oLink) { /** @var \DBObject $oLink */
/** @var \DBObject $oLink */
$iActionId = $oLink->Get('action_id');
/** @var \Action $oAction */
@@ -170,8 +169,8 @@ abstract class TriggerOnObject extends Trigger
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -181,18 +180,20 @@ abstract class TriggerOnObject extends Trigger
"db_table" => "priv_trigger_onobject",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClass("target_class",
array("class_category" => "bizmodel", "more_values" => "User,UserExternal,UserInternal,UserLDAP,UserLocal", "sql" => "target_class", "default_value" => null, "is_null_allowed" => false, "depends_on" => array(), "class_exclusion_list" => "Attachment")));
MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeClass(
"target_class",
["class_category" => "bizmodel", "more_values" => "User,UserExternal,UserInternal,UserLDAP,UserLocal", "sql" => "target_class", "default_value" => null, "is_null_allowed" => false, "depends_on" => [], "class_exclusion_list" => "Attachment"]
));
MetaModel::Init_AddAttribute(new AttributeOQL("filter", ["allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class', 'description']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('default_search', array('description', 'target_class')); // Default criteria of the search banner
MetaModel::Init_SetZListItems('default_search', ['description', 'target_class']); // Default criteria of the search banner
// MetaModel::Init_SetZListItems('standard_search', array('name', 'target_class', 'description')); // Criteria of the search form
}
@@ -204,18 +205,14 @@ abstract class TriggerOnObject extends Trigger
parent::DoCheckToWrite();
$sFilter = trim($this->Get('filter') ?? '');
if (strlen($sFilter) > 0)
{
try
{
if (strlen($sFilter) > 0) {
try {
$oSearch = DBObjectSearch::FromOQL($sFilter);
if (!MetaModel::IsParentClass($this->Get('target_class'), $oSearch->GetClass()))
{
if (!MetaModel::IsParentClass($this->Get('target_class'), $oSearch->GetClass())) {
$this->m_aCheckIssues[] = Dict::Format('TriggerOnObject:WrongFilterClass', $this->Get('target_class'));
}
} catch (OqlException $e)
{
} catch (OqlException $e) {
$this->m_aCheckIssues[] = Dict::Format('TriggerOnObject:WrongFilterQuery', $e->getMessage());
}
}
@@ -235,7 +232,6 @@ abstract class TriggerOnObject extends Trigger
$this->Set('complement', 'class restriction: '.$this->Get('target_class'));
}
/**
* Check whether the given object is in the scope of this trigger
* and can potentially be the subject of notifications
@@ -261,47 +257,44 @@ abstract class TriggerOnObject extends Trigger
public function DoActivate($aContextArgs)
{
$bGo = true;
if (isset($aContextArgs['this->object()']))
{
if (isset($aContextArgs['this->object()'])) {
/** @var \DBObject $oObject */
$oObject = $aContextArgs['this->object()'];
$bGo = $this->IsTargetObject($oObject->GetKey(), $oObject->ListPreviousValuesForUpdatedAttributes());
}
if ($bGo)
{
if ($bGo) {
parent::DoActivate($aContextArgs);
}
}
/**
* if the target class is Attachment, then the trigger is read-only
* @param $sAttCode
* @param $aReasons
* @param $sTargetState
* @return int
* @throws ArchivedObjectException
* @throws CoreException
*/
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState='')
/**
* if the target class is Attachment, then the trigger is read-only
* @param $sAttCode
* @param $aReasons
* @param $sTargetState
* @return int
* @throws ArchivedObjectException
* @throws CoreException
*/
public function GetAttributeFlags($sAttCode, &$aReasons = [], $sTargetState = '')
{
// Force the computed field to be read-only, preventing it to be written
if ($this->Get('target_class') == 'Attachment' ) {
return OPT_ATT_READONLY;
}
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
// Force the computed field to be read-only, preventing it to be written
if ($this->Get('target_class') == 'Attachment') {
return OPT_ATT_READONLY;
}
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
}
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
{
$aHeaderBlocks = parent::DisplayBareHeader($oPage, $bEditMode);
if ($this->Get('target_class') == 'Attachment') {
$oPage->AddUiBlock(AlertUIBlockFactory::MakeForWarning('', Dict::S('Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage')));
$oPage->add_ready_script("$('#UIMenuModify').hide();");
}
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
{
$aHeaderBlocks = parent::DisplayBareHeader($oPage, $bEditMode);
if ($this->Get('target_class') == 'Attachment' ) {
$oPage->AddUiBlock(AlertUIBlockFactory::MakeForWarning('', Dict::S('Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage')));
$oPage->add_ready_script("$('#UIMenuModify').hide();");
}
return $aHeaderBlocks;
}
return $aHeaderBlocks;
}
/**
* Activate trigger based on attribute list given instead of changed attributes
@@ -319,8 +312,7 @@ abstract class TriggerOnObject extends Trigger
*/
public function DoActivateForSpecificAttributes(array $aContextArgs, ?array $aAttributes)
{
if (isset($aContextArgs['this->object()']))
{
if (isset($aContextArgs['this->object()'])) {
/** @var \DBObject $oObject */
$oObject = $aContextArgs['this->object()'];
if (is_null($aAttributes)) {
@@ -347,7 +339,7 @@ abstract class TriggerOnObject extends Trigger
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function IsTargetObject($iObjectId, $aChanges = array())
public function IsTargetObject($iObjectId, $aChanges = [])
{
$sFilter = trim($this->Get('filter') ?? '');
if (strlen($sFilter) > 0) {
@@ -404,8 +396,8 @@ class TriggerOnPortalUpdate extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -415,13 +407,13 @@ class TriggerOnPortalUpdate extends TriggerOnObject
"db_table" => "priv_trigger_onportalupdate",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class', 'description']); // Attributes to be displayed for a list
// Search criteria
}
}
@@ -437,8 +429,8 @@ abstract class TriggerOnStateChange extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -448,16 +440,16 @@ abstract class TriggerOnStateChange extends TriggerOnObject
"db_table" => "priv_trigger_onstatechange",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('target_class'))));
MetaModel::Init_AddAttribute(new AttributeClassState("state", ["class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => ['target_class']]));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'state')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class', 'state']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class', 'state']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -472,8 +464,8 @@ class TriggerOnStateEnter extends TriggerOnStateChange
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -483,15 +475,15 @@ class TriggerOnStateEnter extends TriggerOnStateChange
"db_table" => "priv_trigger_onstateenter",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['target_class', 'state']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class', 'state']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -506,8 +498,8 @@ class TriggerOnStateLeave extends TriggerOnStateChange
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -517,15 +509,15 @@ class TriggerOnStateLeave extends TriggerOnStateChange
"db_table" => "priv_trigger_onstateleave",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['target_class', 'state']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class', 'state']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('')); // Criteria of the advanced search form
}
}
@@ -540,8 +532,8 @@ class TriggerOnObjectCreate extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -551,15 +543,15 @@ class TriggerOnObjectCreate extends TriggerOnObject
"db_table" => "priv_trigger_onobjcreate",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
@@ -575,8 +567,8 @@ class TriggerOnObjectDelete extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -586,15 +578,15 @@ class TriggerOnObjectDelete extends TriggerOnObject
"db_table" => "priv_trigger_onobjdelete",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
@@ -610,8 +602,8 @@ class TriggerOnObjectUpdate extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -621,37 +613,33 @@ class TriggerOnObjectUpdate extends TriggerOnObject
"db_table" => "priv_trigger_onobjupdate",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', array("allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => array('target_class'))));
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', ["allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => ['target_class']]));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'target_attcodes', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class']); // Criteria of the std search form
}
public function IsTargetObject($iObjectId, $aChanges = array())
public function IsTargetObject($iObjectId, $aChanges = [])
{
if (!parent::IsTargetObject($iObjectId, $aChanges))
{
if (!parent::IsTargetObject($iObjectId, $aChanges)) {
return false;
}
// Check the attribute
$oAttCodeSet = $this->Get('target_attcodes');
$aAttCodes = $oAttCodeSet->GetValues();
if (empty($aAttCodes))
{
if (empty($aAttCodes)) {
return true;
}
foreach($aAttCodes as $sAttCode)
{
if (array_key_exists($sAttCode, $aChanges))
{
foreach ($aAttCodes as $sAttCode) {
if (array_key_exists($sAttCode, $aChanges)) {
return true;
}
}
@@ -664,26 +652,22 @@ class TriggerOnObjectUpdate extends TriggerOnObject
// Remove unwanted attribute codes
$aChanges = $this->ListChanges();
if (isset($aChanges['target_attcodes']))
{
if (isset($aChanges['target_attcodes'])) {
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'target_attcodes');
$aArgs = array('this' => $this);
$aArgs = ['this' => $this];
$aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
/** @var \ormSet $oValue */
$oValue = $this->Get('target_attcodes');
$aValues = $oValue->GetValues();
$bChanged = false;
foreach($aValues as $key => $sValue)
{
if (!isset($aAllowedValues[$sValue]))
{
foreach ($aValues as $key => $sValue) {
if (!isset($aAllowedValues[$sValue])) {
unset($aValues[$key]);
$bChanged = true;
}
}
if ($bChanged)
{
if ($bChanged) {
$oValue->SetValues($aValues);
$this->Set('target_attcodes', $oValue);
}
@@ -706,8 +690,8 @@ class TriggerOnObjectMention extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -718,16 +702,16 @@ class TriggerOnObjectMention extends TriggerOnObject
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("mentioned_filter", array("allowed_values" => null, "sql" => "mentioned_filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeOQL("mentioned_filter", ["allowed_values" => null, "sql" => "mentioned_filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'mentioned_filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'filter', 'mentioned_filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['finalclass', 'target_class']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class']); // Criteria of the std search form
}
/**
@@ -745,8 +729,7 @@ class TriggerOnObjectMention extends TriggerOnObject
public function IsMentionedObjectInScope(DBObject $oObject)
{
$sFilter = trim($this->Get('mentioned_filter'));
if (strlen($sFilter) > 0)
{
if (strlen($sFilter) > 0) {
$oSearch = DBObjectSearch::FromOQL($sFilter);
$sSearchClass = $oSearch->GetClass();
@@ -763,9 +746,7 @@ class TriggerOnObjectMention extends TriggerOnObject
$aParams = $oObject->ToArgs('this');
$oSet = new DBObjectSet($oSearch, [], $aParams);
$bRet = $oSet->CountExceeds(0);
}
else
{
} else {
$bRet = true;
}
@@ -787,8 +768,8 @@ class TriggerOnAttributeBlobDownload extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -799,7 +780,7 @@ class TriggerOnAttributeBlobDownload extends TriggerOnObject
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
}
@@ -816,42 +797,42 @@ class lnkTriggerAction extends cmdbAbstractObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array('action_id', 'trigger_id'),
"reconc_keys" => ['action_id', 'trigger_id'],
"db_table" => "priv_link_action_trigger",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"is_link" => true,
'uniqueness_rules' => array(
'no_duplicate' => array(
'attributes' => array(
'uniqueness_rules' => [
'no_duplicate' => [
'attributes' => [
0 => 'action_id',
1 => 'trigger_id',
),
],
'filter' => '',
'disabled' => false,
'is_blocking' => true,
),
),
);
],
],
];
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass" => "Action", "jointype" => '', "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("action_name", array("allowed_values" => null, "extkey_attcode" => 'action_id', "target_attcode" => "name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass" => "Trigger", "jointype" => '', "allowed_values" => null, "sql" => "trigger_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("trigger_name", array("allowed_values" => null, "extkey_attcode" => 'trigger_id', "target_attcode" => "description")));
MetaModel::Init_AddAttribute(new AttributeInteger("order", array("allowed_values" => null, "sql" => "order", "default_value" => 0, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", ["targetclass" => "Action", "jointype" => '', "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("action_name", ["allowed_values" => null, "extkey_attcode" => 'action_id', "target_attcode" => "name"]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", ["targetclass" => "Trigger", "jointype" => '', "allowed_values" => null, "sql" => "trigger_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("trigger_name", ["allowed_values" => null, "extkey_attcode" => 'trigger_id', "target_attcode" => "description"]));
MetaModel::Init_AddAttribute(new AttributeInteger("order", ["allowed_values" => null, "sql" => "order", "default_value" => 0, "is_null_allowed" => true, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('action_id', 'trigger_id', 'order')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('action_id', 'trigger_id', 'order')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['action_id', 'trigger_id', 'order']); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', ['action_id', 'trigger_id', 'order']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('action_id', 'trigger_id', 'order')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('action_id', 'trigger_id', 'order')); // Criteria of the advanced search form
MetaModel::Init_SetZListItems('standard_search', ['action_id', 'trigger_id', 'order']); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', ['action_id', 'trigger_id', 'order']); // Criteria of the advanced search form
}
}
@@ -866,8 +847,8 @@ class TriggerOnThresholdReached extends TriggerOnObject
*/
public static function Init()
{
$aParams = array
(
$aParams =
[
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
@@ -877,18 +858,18 @@ class TriggerOnThresholdReached extends TriggerOnObject
"db_table" => "priv_trigger_threshold",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
];
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('stop_watch_code', array("allowed_values" => null, "class_field" => "target_class", "sql" => "stop_watch_code", "default_value" => null, "is_null_allowed" => false, "max_items" => 1, "min_items" => 1, "attribute_definition_exclusion_list" => null, "attribute_definition_list" => "AttributeStopWatch", "include_child_classes_attributes" => true, "depends_on" => array('target_class'))));
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('stop_watch_code', ["allowed_values" => null, "class_field" => "target_class", "sql" => "stop_watch_code", "default_value" => null, "is_null_allowed" => false, "max_items" => 1, "min_items" => 1, "attribute_definition_exclusion_list" => null, "attribute_definition_list" => "AttributeStopWatch", "include_child_classes_attributes" => true, "depends_on" => ['target_class']]));
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", ["allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'threshold_index', 'threshold_index')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', ['description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'subscription_policy', 'action_list']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['target_class', 'threshold_index', 'threshold_index']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', ['description', 'target_class']); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Value set definitions (from a fixed list or from a query, etc.)
*
@@ -37,16 +37,14 @@ require_once('MyHelpers.class.inc.php');
abstract class ValueSetDefinition
{
protected $m_bIsLoaded = false;
protected $m_aValues = array();
protected $m_aValues = [];
// Displayable description that could be computed out of the std usage context
public function GetValuesDescription()
{
$aValues = $this->GetValues(array(), '');
$aDisplayedValues = array();
foreach($aValues as $key => $value)
{
$aValues = $this->GetValues([], '');
$aDisplayedValues = [];
foreach ($aValues as $key => $value) {
$aDisplayedValues[] = "$key => $value";
}
$sAllowedValues = implode(', ', $aDisplayedValues);
@@ -62,24 +60,18 @@ abstract class ValueSetDefinition
*/
public function GetValues($aArgs, $sContains = '', $sOperation = 'contains')
{
if (!$this->m_bIsLoaded)
{
if (!$this->m_bIsLoaded) {
$this->LoadValues($aArgs);
$this->m_bIsLoaded = true;
}
if (strlen($sContains) == 0)
{
if (strlen($sContains) == 0) {
// No filtering
$aRet = $this->m_aValues;
}
else
{
} else {
// Filter on results containing the needle <sContain>
$aRet = array();
foreach ($this->m_aValues as $sKey=>$sValue)
{
if (stripos($sValue, $sContains) !== false)
{
$aRet = [];
foreach ($this->m_aValues as $sKey => $sValue) {
if (stripos($sValue, $sContains) !== false) {
$aRet[$sKey] = $sValue;
}
}
@@ -103,7 +95,6 @@ abstract class ValueSetDefinition
abstract protected function LoadValues($aArgs);
}
/**
* Set of existing values for an attribute, given a search filter
*
@@ -122,11 +113,10 @@ class ValueSetObjects extends ValueSetDefinition
private $m_bSort;
private $m_iLimit;
/**
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
*/
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = [], $bAllowAllData = false, $aModifierProperties = [])
{
$this->m_sContains = '';
$this->m_sOperation = '';
@@ -155,54 +145,48 @@ class ValueSetObjects extends ValueSetDefinition
{
$this->m_aOrderBy = $aOrderBy;
}
public function ToObjectSet($aArgs = array(), $sContains = '', $iAdditionalValue = null)
public function ToObjectSet($aArgs = [], $sContains = '', $iAdditionalValue = null)
{
if ($this->m_bAllowAllData)
{
if ($this->m_bAllowAllData) {
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
}
else
{
} else {
$oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
}
if (!is_null($this->m_oExtraCondition))
{
if (!is_null($this->m_oExtraCondition)) {
$oFilter = $oFilter->Intersect($this->m_oExtraCondition);
}
foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
{
foreach ($aProperties as $sProperty => $value)
{
foreach ($this->m_aModifierProperties as $sPluginClass => $aProperties) {
foreach ($aProperties as $sProperty => $value) {
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
}
}
if ($iAdditionalValue > 0)
{
if ($iAdditionalValue > 0) {
$oSearchAdditionalValue = new DBObjectSearch($oFilter->GetClass());
$oSearchAdditionalValue->AddConditionExpression( new BinaryExpression(
new FieldExpression('id', $oSearchAdditionalValue->GetClassAlias()),
'=',
new VariableExpression('current_extkey_id'))
);
$oSearchAdditionalValue->AddConditionExpression(
new BinaryExpression(
new FieldExpression('id', $oSearchAdditionalValue->GetClassAlias()),
'=',
new VariableExpression('current_extkey_id')
)
);
$oSearchAdditionalValue->AllowAllData();
$oSearchAdditionalValue->SetArchiveMode(true);
$oSearchAdditionalValue->SetInternalParams( array('current_extkey_id' => $iAdditionalValue) );
$oSearchAdditionalValue->SetInternalParams(['current_extkey_id' => $iAdditionalValue]);
$oFilter = new DBUnionSearch(array($oFilter, $oSearchAdditionalValue));
$oFilter = new DBUnionSearch([$oFilter, $oSearchAdditionalValue]);
}
return new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
}
/**
* @inheritDoc
* @throws CoreException
* @throws OQLException
*/
public function GetValues($aArgs, $sContains = '', $sOperation = 'contains')
/**
* @inheritDoc
* @throws CoreException
* @throws OQLException
*/
public function GetValues($aArgs, $sContains = '', $sOperation = 'contains')
{
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation))
{
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation)) {
$this->LoadValues($aArgs, $sContains, $sOperation);
$this->m_bIsLoaded = true;
}
@@ -225,15 +209,15 @@ class ValueSetObjects extends ValueSetDefinition
$this->m_sContains = $sContains;
$this->m_sOperation = $sOperation;
$this->m_aValues = array();
$this->m_aValues = [];
$oFilter = $this->GetFilter($sOperation, $sContains);
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
if (empty($this->m_sValueAttCode)) {
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
$aAttToLoad = [$oFilter->GetClassAlias() => ['friendlyname']];
} else {
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
$aAttToLoad = [$oFilter->GetClassAlias() => [$this->m_sValueAttCode]];
}
$oObjects->OptimizeColumnLoad($aAttToLoad);
while ($oObject = $oObjects->Fetch()) {
@@ -247,7 +231,6 @@ class ValueSetObjects extends ValueSetDefinition
return true;
}
/**
* Get filter for functions LoadValues and LoadValuesForAutocomplete
*
@@ -297,7 +280,7 @@ class ValueSetObjects extends ValueSetDefinition
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
if (count($aAttributes) > 0) {
$sClassAlias = $oFilter->GetClassAlias();
$aFilters = array();
$aFilters = [];
$oValueExpr = new ScalarExpression($this->m_sContains);
foreach ($aAttributes as $sAttribute) {
$oNewFilter = $oFilter->DeepClone();
@@ -355,8 +338,7 @@ class ValueSetObjects extends ValueSetDefinition
public function GetValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
{
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation))
{
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation)) {
$this->LoadValuesForAutocomplete($aArgs, $sContains, $sOperation);
$this->m_bIsLoaded = true;
}
@@ -376,7 +358,7 @@ class ValueSetObjects extends ValueSetDefinition
*/
protected function LoadValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
{
$this->m_aValues = array();
$this->m_aValues = [];
$oFilter = $this->GetFilter($sOperation, $sContains);
$sClass = $oFilter->GetClass();
@@ -444,7 +426,6 @@ class ValueSetObjects extends ValueSetDefinition
}
}
/**
* Fixed set values (could be hardcoded in the business model)
*
@@ -514,8 +495,7 @@ class ValueSetEnum extends ValueSetDefinition
protected function LoadValues($aArgs)
{
$aValues = [];
if (is_array($this->m_values))
{
if (is_array($this->m_values)) {
foreach ($this->m_values as $key => $value) {
// Handle backed-enum case
if (is_object($value) && enum_exists(get_class($value))) {
@@ -525,18 +505,13 @@ class ValueSetEnum extends ValueSetDefinition
$aValues[$key] = $value;
}
}
elseif (is_string($this->m_values) && strlen($this->m_values) > 0)
{
foreach (explode(",", $this->m_values) as $sVal)
{
} elseif (is_string($this->m_values) && strlen($this->m_values) > 0) {
foreach (explode(",", $this->m_values) as $sVal) {
$sVal = trim($sVal);
$sKey = $sVal;
$aValues[$sKey] = $sVal;
}
}
else
{
} else {
$aValues = [];
}
$this->m_aValues = $aValues;
@@ -553,17 +528,13 @@ class ValueSetEnumPadded extends ValueSetEnum
public function __construct($Values, bool $bSortByValues = false)
{
parent::__construct($Values, $bSortByValues);
if (is_string($Values))
{
if (is_string($Values)) {
$this->LoadValues(null);
}
else
{
} else {
$this->m_aValues = $Values;
}
$aPaddedValues = array();
foreach ($this->m_aValues as $sKey => $sVal)
{
$aPaddedValues = [];
foreach ($this->m_aValues as $sKey => $sVal) {
// Pad keys to the min. length required by the \AttributeSet
$sKey = str_pad($sKey, 3, '_', STR_PAD_LEFT);
$aPaddedValues[$sKey] = $sVal;
@@ -592,15 +563,13 @@ class ValueSetRange extends ValueSetDefinition
protected function LoadValues($aArgs)
{
$iValue = $this->m_iStart;
for($iValue = $this->m_iStart; $iValue <= $this->m_iEnd; $iValue += $this->m_iStep)
{
for ($iValue = $this->m_iStart; $iValue <= $this->m_iEnd; $iValue += $this->m_iStep) {
$this->m_aValues[$iValue] = $iValue;
}
return true;
}
}
/**
* Data model classes
*
@@ -622,27 +591,19 @@ class ValueSetEnumClasses extends ValueSetEnum
parent::LoadValues($aArgs);
// Translate the labels of the additional values
foreach($this->m_aValues as $sClass => $void)
{
if (MetaModel::IsValidClass($sClass))
{
foreach ($this->m_aValues as $sClass => $void) {
if (MetaModel::IsValidClass($sClass)) {
$this->m_aValues[$sClass] = MetaModel::GetName($sClass);
}
else
{
} else {
unset($this->m_aValues[$sClass]);
}
}
// Then, add the classes from the category definition
foreach (MetaModel::GetClasses($this->m_sCategories) as $sClass)
{
if (MetaModel::IsValidClass($sClass))
{
foreach (MetaModel::GetClasses($this->m_sCategories) as $sClass) {
if (MetaModel::IsValidClass($sClass)) {
$this->m_aValues[$sClass] = MetaModel::GetName($sClass);
}
else
{
} else {
unset($this->m_aValues[$sClass]);
}
}

View File

@@ -1,4 +1,5 @@
<?php
//
// iTop module definition file
//
@@ -6,7 +7,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/3.3.0',
array(
[
// Identification
//
'label' => 'CAS SSO',
@@ -14,36 +15,36 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => true,
// Components
//
'datamodel' => array(
'datamodel' => [
'vendor/autoload.php',
'src/CASLoginExtension.php',
),
'webservice' => array(
),
'data.struct' => array(
],
'webservice' => [
],
'data.struct' => [
// add your 'structure' definition XML files here,
),
'data.sample' => array(
],
'data.sample' => [
// add your sample data XML files here,
),
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(
'settings' => [
// Authentication
'cas_debug' => false,
'cas_host' => '',
@@ -51,6 +52,6 @@ SetupWebPage::AddModule(
'cas_context' => '',
'cas_version' => '',
'service_base_url' => '',
),
)
],
]
);

View File

@@ -1,9 +1,10 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Authent External
* Module definition file for the "External Authentication" module
@@ -28,7 +28,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/3.3.0',
array(
[
// Identification
//
'label' => 'External user authentication',
@@ -36,23 +36,23 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => false,
'visible' => true,
// Components
//
'datamodel' => array(
'datamodel' => [
'model.authent-external.php',
),
'data.struct' => array(
],
'data.struct' => [
//'data.struct.authent-ldap.xml',
),
'data.sample' => array(
],
'data.sample' => [
//'data.sample.authent-ldap.xml',
),
],
// Documentation
//
'doc.manual_setup' => '',
@@ -60,6 +60,6 @@ SetupWebPage::AddModule(
// Default settings
//
'settings' => array(),
)
'settings' => [],
]
);

View File

@@ -1,100 +1,98 @@
<?php
// Until we develop a mean to adress this within the setup, let's check that this instance
// of PHP has the php_ldap extension
//
if (function_exists('ldap_connect'))
{
if (function_exists('ldap_connect')) {
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/3.3.0',
array(
// Identification
//
'label' => 'User authentication based on LDAP',
'category' => 'authentication',
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/3.3.0',
[
// Identification
//
'label' => 'User authentication based on LDAP',
'category' => 'authentication',
// Setup
//
'dependencies' => array(
),
'mandatory' => false,
'visible' => true,
'installer' => 'AuthentLDAPInstaller',
// Setup
//
'dependencies' => [
],
'mandatory' => false,
'visible' => true,
'installer' => 'AuthentLDAPInstaller',
// Components
//
'datamodel' => array(
),
'data.struct' => array(
//'data.struct.authent-ldap.xml',
),
'data.sample' => array(
//'data.sample.authent-ldap.xml',
),
// Documentation
//
'doc.manual_setup' => '',
'doc.more_information' => '',
// Components
//
'datamodel' => [
],
'data.struct' => [
//'data.struct.authent-ldap.xml',
],
'data.sample' => [
//'data.sample.authent-ldap.xml',
],
// Default settings
//
'settings' => array(
'uri' => 'ldap://localhost', // URI with host or IP address of your LDAP server
'default_user' => '', // User and password used for initial "Anonymous" bind to LDAP
'default_pwd' => '', // Leave both blank, if anonymous (read-only) bind is allowed
'base_dn' => 'dc=yourcompany,dc=com', // Base DN for User queries, adjust it to your LDAP schema
'user_query' => '(&(uid=%1$s)(inetuserstatus=ACTIVE))', // Query used to retrieve each user %1$s => iTop login
// For Windows AD use (samaccountname=%1$s) or (userprincipalname=%1$s)
// Some extra LDAP options, refer to: http://www.php.net/manual/en/function.ldap-set-option.php for more info
'options' => array(
LDAP_OPT_PROTOCOL_VERSION => 3,
LDAP_OPT_REFERRALS => 0,
),
'start_tls' => false,
'debug' => false,
'servers' => array(),
),
)
);
// Documentation
//
'doc.manual_setup' => '',
'doc.more_information' => '',
// Module installation handler
//
class AuthentLDAPInstaller extends ModuleInstallerAPI
{
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
// Default settings
//
'settings' => [
'uri' => 'ldap://localhost', // URI with host or IP address of your LDAP server
'default_user' => '', // User and password used for initial "Anonymous" bind to LDAP
'default_pwd' => '', // Leave both blank, if anonymous (read-only) bind is allowed
'base_dn' => 'dc=yourcompany,dc=com', // Base DN for User queries, adjust it to your LDAP schema
'user_query' => '(&(uid=%1$s)(inetuserstatus=ACTIVE))', // Query used to retrieve each user %1$s => iTop login
// For Windows AD use (samaccountname=%1$s) or (userprincipalname=%1$s)
// Some extra LDAP options, refer to: http://www.php.net/manual/en/function.ldap-set-option.php for more info
'options' => [
LDAP_OPT_PROTOCOL_VERSION => 3,
LDAP_OPT_REFERRALS => 0,
],
'start_tls' => false,
'debug' => false,
'servers' => [],
],
]
);
// Module installation handler
//
class AuthentLDAPInstaller extends ModuleInstallerAPI
{
// Create missing table entries
$sUserLDAPTable = MetaModel::DBGetTable('UserLDAP');
$sUserTable = MetaModel::DBGetTable('User');
$sSQL = "insert into $sUserLDAPTable (id) select U.id from $sUserTable as U left join $sUserLDAPTable as L on U.id = L.id where U.finalclass='UserLDAP' and isnull(L.id);";
CMDBSource::Query($sSQL);
}
public static function BeforeWritingConfig(Config $oConfiguration)
{
$sURI = $oConfiguration->GetModuleSetting('authent-ldap', 'uri');
if (empty($sURI)) {
$sLDAPHost = MetaModel::GetModuleSetting('authent-ldap', 'host', 'localhost');
$iLDAPPort = MetaModel::GetModuleSetting('authent-ldap', 'port', 389);
$sURI = preg_match('#^ldaps?://#i', $sLDAPHost) ? $sLDAPHost : 'ldap://'.$sLDAPHost.':'.$iLDAPPort;
$oConfiguration->SetModuleSetting('authent-ldap', 'uri', $sURI);
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
// Create missing table entries
$sUserLDAPTable = MetaModel::DBGetTable('UserLDAP');
$sUserTable = MetaModel::DBGetTable('User');
$sSQL = "insert into $sUserLDAPTable (id) select U.id from $sUserTable as U left join $sUserLDAPTable as L on U.id = L.id where U.finalclass='UserLDAP' and isnull(L.id);";
CMDBSource::Query($sSQL);
}
$aServers = $oConfiguration->GetModuleSetting('authent-ldap', 'servers', []);
foreach ($aServers as &$aServer) {
if (!array_key_exists($aServer, 'uri')) {
$sLDAPHost = $aServerParams['host'] ?? 'localhost';
$iLDAPPort = $aServerParams['port'] ?? 389;
$aServer['uri'] = preg_match('#^ldaps?://#i', $sLDAPHost) ? $sLDAPHost : 'ldap://'.$sLDAPHost.':'.$iLDAPPort;
public static function BeforeWritingConfig(Config $oConfiguration)
{
$sURI = $oConfiguration->GetModuleSetting('authent-ldap', 'uri');
if (empty($sURI)) {
$sLDAPHost = MetaModel::GetModuleSetting('authent-ldap', 'host', 'localhost');
$iLDAPPort = MetaModel::GetModuleSetting('authent-ldap', 'port', 389);
$sURI = preg_match('#^ldaps?://#i', $sLDAPHost) ? $sLDAPHost : 'ldap://'.$sLDAPHost.':'.$iLDAPPort;
$oConfiguration->SetModuleSetting('authent-ldap', 'uri', $sURI);
}
$aServers = $oConfiguration->GetModuleSetting('authent-ldap', 'servers', []);
foreach ($aServers as &$aServer) {
if (!array_key_exists($aServer, 'uri')) {
$sLDAPHost = $aServerParams['host'] ?? 'localhost';
$iLDAPPort = $aServerParams['port'] ?? 389;
$aServer['uri'] = preg_match('#^ldaps?://#i', $sLDAPHost) ? $sLDAPHost : 'ldap://'.$sLDAPHost.':'.$iLDAPPort;
}
}
$oConfiguration->SetModuleSetting('authent-ldap', 'servers', $aServers);
}
$oConfiguration->SetModuleSetting('authent-ldap', 'servers', $aServers);
}
}
} // if (function_exists('ldap_connect'))

View File

@@ -1,10 +1,9 @@
<?php
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/3.3.0',
array(
[
// Identification
//
'label' => 'User authentication based on the local DB',
@@ -12,23 +11,23 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => true,
// Components
//
'datamodel' => array(
'datamodel' => [
'model.authent-local.php',
),
'data.struct' => array(
],
'data.struct' => [
//'data.struct.authent-local.xml',
),
'data.sample' => array(
],
'data.sample' => [
//'data.sample.authent-local.xml',
),
],
// Documentation
//
'doc.manual_setup' => '',
@@ -37,8 +36,8 @@ SetupWebPage::AddModule(
// Default settings
//
'settings' => array(
'settings' => [
// see the './datamodel.authent-local.xml' for the default settings!
),
)
],
]
);

View File

@@ -1,4 +1,5 @@
<?php
//
// iTop module definition file
//
@@ -6,7 +7,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-darkmoon-theme/3.3.0',
array(
[
// Identification
//
'label' => 'Backoffice: Darkmoon theme',
@@ -14,38 +15,35 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
//
'datamodel' => array(
),
'webservice' => array(
),
'data.struct' => array(
'datamodel' => [
],
'webservice' => [
],
'data.struct' => [
// add your 'structure' definition XML files here,
),
'data.sample' => array(
],
'data.sample' => [
// add your sample data XML files here,
),
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(
'settings' => [
// Module specific settings go here, if any
),
)
],
]
);
?>

View File

@@ -1,4 +1,5 @@
<?php
//
// iTop module definition file
//
@@ -6,7 +7,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-fullmoon-high-contrast-theme/3.3.0',
array(
[
// Identification
//
'label' => 'Backoffice: Fullmoon with high contrast accessibility theme',
@@ -14,38 +15,35 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
//
'datamodel' => array(
),
'webservice' => array(
),
'data.struct' => array(
'datamodel' => [
],
'webservice' => [
],
'data.struct' => [
// add your 'structure' definition XML files here,
),
'data.sample' => array(
],
'data.sample' => [
// add your sample data XML files here,
),
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(
'settings' => [
// Module specific settings go here, if any
),
)
],
]
);
?>

View File

@@ -1,4 +1,5 @@
<?php
//
// iTop module definition file
//
@@ -6,7 +7,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.3.0',
array(
[
// Identification
//
'label' => 'Backoffice: Fullmoon with protonopia & deuteranopia accessibility theme',
@@ -14,38 +15,35 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
//
'datamodel' => array(
),
'webservice' => array(
),
'data.struct' => array(
'datamodel' => [
],
'webservice' => [
],
'data.struct' => [
// add your 'structure' definition XML files here,
),
'data.sample' => array(
],
'data.sample' => [
// add your sample data XML files here,
),
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(
'settings' => [
// Module specific settings go here, if any
),
)
],
]
);
?>

View File

@@ -1,4 +1,5 @@
<?php
//
// iTop module definition file
//
@@ -6,7 +7,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-fullmoon-tritanopia-theme/3.3.0',
array(
[
// Identification
//
'label' => 'Backoffice: Fullmoon with tritanopia accessibility theme',
@@ -14,38 +15,35 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
//
'datamodel' => array(
),
'webservice' => array(
),
'data.struct' => array(
'datamodel' => [
],
'webservice' => [
],
'data.struct' => [
// add your 'structure' definition XML files here,
),
'data.sample' => array(
],
'data.sample' => [
// add your sample data XML files here,
),
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(
'settings' => [
// Module specific settings go here, if any
),
)
],
]
);
?>

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -25,7 +26,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-db-tools/3.3.0',
array(
[
// Identification
//
'label' => 'Database maintenance tools',
@@ -33,21 +34,21 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
'dependencies' => [
'itop-structure/3.0.0',
),
],
'mandatory' => false,
'visible' => true,
// Components
//
'datamodel' => array(
'datamodel' => [
'src/Service/DBToolsUtils.php',
'src/Service/DBAnalyzerUtils.php',
),
'webservice' => array(),
'data.struct' => array(),
'data.sample' => array(),
'src/Service/DBAnalyzerUtils.php',
],
'webservice' => [],
'data.struct' => [],
'data.sample' => [],
// Documentation
//
@@ -56,6 +57,6 @@ SetupWebPage::AddModule(
// Default settings
//
'settings' => array(),
)
'settings' => [],
]
);

View File

@@ -1,17 +1,18 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author Lukáš Dvořák <lukas.dvorak@itopportal.cz>
* @author Daniel Rokos <daniel.rokos@itopportal.cz>
*
*/
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Attachments:TabTitle_Count' => 'Přílohy (%1$d)',
'Attachments:EmptyTabTitle' => 'Přílohy',
'Attachments:FieldsetTitle' => 'Přílohy',
@@ -32,13 +33,13 @@ nebe se zeptejte'.ITOP_APPLICATION_SHORT.' správce '.ITOP_APPLICATION_SHORT.' z
'Attachments:Render:Icons' => 'Zobrazit jako ikony',
'Attachments:Render:Table' => 'Zobrazit jako seznam',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
));
]);
//
// Class: Attachment
//
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:Attachment' => 'Příloha',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Exspirace',
@@ -53,10 +54,9 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Obsah',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Attachments:File:Thumbnail' => 'Ikona',
'Attachments:File:Name' => 'Jméno souboru',
'Attachments:File:Date' => 'Datum nahrání',
@@ -64,25 +64,25 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Attachments:File:Size' => 'Velikost',
'Attachments:File:MimeType' => 'Typ',
'Attachments:File:DownloadsCount' => 'Staženo',
));
]);
//
// Class: Attachment
//
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:Attachment/Attribute:creation_date' => 'Datum vytvoření',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'Jméno uživatele',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'Kontakt',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -91,5 +91,5 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,16 +1,17 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author Erik Bøg <erik@boegmoeller.dk>
*
*/
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Attachments:TabTitle_Count' => 'Vedhæftninger (%1$d)',
'Attachments:EmptyTabTitle' => 'Vedhæftninger',
'Attachments:FieldsetTitle' => 'Vedhæftninger',
@@ -31,13 +32,13 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
'Attachments:Render:Icons' => 'Display as icons~~',
'Attachments:Render:Table' => 'Display as list~~',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
));
]);
//
// Class: Attachment
//
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:Attachment' => 'Attachment~~',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Expire~~',
@@ -52,10 +53,9 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Contents~~',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Attachments:File:Thumbnail' => 'Icon~~',
'Attachments:File:Name' => 'File name~~',
'Attachments:File:Date' => 'Upload date~~',
@@ -63,25 +63,25 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Attachments:File:Size' => 'Size~~',
'Attachments:File:MimeType' => 'Type~~',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:Attachment/Attribute:creation_date' => 'Creation date~~',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'User id~~',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'Contact id~~',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -90,5 +90,5 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,16 +1,17 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author ITOMIG GmbH <martin.raenker@itomig.de>
*
*/
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
'Attachments:EmptyTabTitle' => 'Attachments',
'Attachments:FieldsetTitle' => 'Attachments',
@@ -31,13 +32,13 @@ oder melden Sie dem '.ITOP_APPLICATION_SHORT.' Administrator diesen Fehler, weil
'Attachments:Render:Icons' => 'Als Icons anzeigen',
'Attachments:Render:Table' => 'Als Liste anzeigen',
'UI:Attachments:DropYourFileHint' => 'Dateien in diesem Bereich ablegen...',
));
]);
//
// Class: Attachment
//
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:Attachment' => 'Attachment',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Läuft ab',
@@ -52,10 +53,9 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Inhalt',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Attachments:File:Thumbnail' => 'Icon',
'Attachments:File:Name' => 'Dateiname',
'Attachments:File:Date' => 'Upload-Datum',
@@ -63,25 +63,25 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Attachments:File:Size' => 'Größe',
'Attachments:File:MimeType' => 'Typ',
'Attachments:File:DownloadsCount' => 'Downloads',
));
]);
//
// Class: Attachment
//
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:Attachment/Attribute:creation_date' => 'Erstellungsdatum',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Benutzer ID',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Kontakt ID',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (beim Herunterladen eines Attachment eines Objekts)',
'Class:TriggerOnAttachmentDownload+' => 'Trigger für das Herunterladen des Attachments der angegebenen Klasse oder einer Unterklasse',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -90,5 +90,5 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -17,7 +18,7 @@
* You should have received a copy of the GNU Affero General Public License
*/
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
'Attachments:EmptyTabTitle' => 'Attachments',
'Attachments:FieldsetTitle' => 'Attachments',
@@ -38,13 +39,13 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
'Attachments:Render:Icons' => 'Display as icons',
'Attachments:Render:Table' => 'Display as list',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area',
));
]);
//
// Class: Attachment
//
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Class:Attachment' => 'Attachment',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Expire',
@@ -59,10 +60,9 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Contents',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Attachments:File:Thumbnail' => 'Icon',
'Attachments:File:Name' => 'File name',
'Attachments:File:Date' => 'Upload date',
@@ -70,25 +70,25 @@ Dict::Add('EN US', 'English', 'English', array(
'Attachments:File:Size' => 'Size',
'Attachments:File:MimeType' => 'Type',
'Attachments:File:DownloadsCount' => 'Downloads',
));
]);
//
// Class: Attachment
//
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Class:Attachment/Attribute:creation_date' => 'Creation date',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'User id',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Contact id',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)',
@@ -97,5 +97,5 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Add file in email',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger',
]);

View File

@@ -1,13 +1,14 @@
<?php
/**
* Spanish Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Miguel Turrubiates <miguel_tf@yahoo.com>
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
*/
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Attachments:TabTitle_Count' => 'Anexos (%1$d)',
'Attachments:EmptyTabTitle' => 'Anexos',
'Attachments:FieldsetTitle' => 'Anexos',
@@ -28,13 +29,13 @@ o pregunte al administador de iTop si el servidor que ha quedado sin espacio en
'Attachments:Render:Icons' => 'Desplegar como icono',
'Attachments:Render:Table' => 'Desplegar como lista',
'UI:Attachments:DropYourFileHint' => 'Arrastre los archivos en cualquier lugar de esta área',
));
]);
//
// Class: Attachment
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:Attachment' => 'Anexo',
'Class:Attachment+' => 'Anexo',
'Class:Attachment/Attribute:expire' => 'Expira',
@@ -49,10 +50,9 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Contenido',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Attachments:File:Thumbnail' => 'Ícono',
'Attachments:File:Name' => 'Nombre de Archivo',
'Attachments:File:Date' => 'Fecha de Carga',
@@ -60,25 +60,25 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Attachments:File:Size' => 'Tamaño',
'Attachments:File:MimeType' => 'Tipo',
'Attachments:File:DownloadsCount' => 'Descargas',
));
]);
//
// Class: Attachment
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:Attachment/Attribute:creation_date' => 'Fecha de Creación',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Id del Usuario',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Id del Contacto',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:TriggerOnAttachmentDownload' => 'Disparador (al descargar el archivo adjunto del objeto)',
'Class:TriggerOnAttachmentDownload+' => 'Disparador al descargar el archivo adjunto del objeto de [una clase secundaria de] la clase dada',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -87,5 +87,5 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Attachments:TabTitle_Count' => 'Pièces jointes (%1$d)',
'Attachments:EmptyTabTitle' => 'Pièces jointes',
'Attachments:FieldsetTitle' => 'Pièces jointes',
@@ -30,13 +31,13 @@ Soit demandez à votre administrateur système s\'il reste de la place disque di
'Attachments:Render:Icons' => 'Affichage en icônes',
'Attachments:Render:Table' => 'Affichage en liste',
'UI:Attachments:DropYourFileHint' => 'Déposez vos fichiers dans cet espace',
));
]);
//
// Class: Attachment
//
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Class:Attachment' => 'Attachement',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Expire',
@@ -51,10 +52,9 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Contenu',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Attachments:File:Thumbnail' => 'Icône',
'Attachments:File:Name' => 'Nom du fichier',
'Attachments:File:Date' => 'Date de chargement',
@@ -62,25 +62,25 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Attachments:File:Size' => 'Taille',
'Attachments:File:MimeType' => 'Type',
'Attachments:File:DownloadsCount' => 'Téléchargements',
));
]);
//
// Class: Attachment
//
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Class:Attachment/Attribute:creation_date' => 'Date de création',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Utilisateur',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Contact',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Class:TriggerOnAttachmentDownload' => 'Déclencheur sur le téléchargement d\'une pièce jointe d\'un objet',
'Class:TriggerOnAttachmentDownload+' => '',
'Class:TriggerOnAttachmentCreate' => 'Déclencheur sur la création d\'une pièce jointe',
@@ -89,5 +89,5 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'Si coché, le fichier sera automatiquement attaché à l\'email quand l\'action email est lancée',
'Class:TriggerOnAttachmentDelete' => 'Déclencheur sur la suppression d\'une pièce jointe',
'Class:TriggerOnAttachmentDelete+' => '',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Les Triggers sur les objets ne sont pas autorisés sur la classe Attachement. Veuillez utiliser les triggers spécifiques pour cette classe',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Les Triggers sur les objets ne sont pas autorisés sur la classe Attachement. Veuillez utiliser les triggers spécifiques pour cette classe',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Attachments:TabTitle_Count' => 'Mellékletek (%1$d)',
'Attachments:EmptyTabTitle' => 'Mellékletek',
'Attachments:FieldsetTitle' => 'Mellékletek',
@@ -28,13 +29,13 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Attachments:Render:Icons' => 'Mutassa ikonként',
'Attachments:Render:Table' => 'Mutassa listaként',
'UI:Attachments:DropYourFileHint' => 'Húzza a fájlokat erre a területre',
));
]);
//
// Class: Attachment
//
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:Attachment' => 'Mellékletek',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Lejárat',
@@ -49,10 +50,9 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Tartalom',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Attachments:File:Thumbnail' => 'Ikon',
'Attachments:File:Name' => 'Fájlnév',
'Attachments:File:Date' => 'Feltöltés dátuma',
@@ -60,25 +60,25 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Attachments:File:Size' => 'Méret',
'Attachments:File:MimeType' => 'Típus',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:Attachment/Attribute:creation_date' => 'Létrehozás dátuma',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'Felhasználó',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'Kapcsolattartó',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -87,5 +87,5 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Attachments:TabTitle_Count' => 'Allegati (%1$d)',
'Attachments:EmptyTabTitle' => 'Allegati',
'Attachments:FieldsetTitle' => 'Allegati',
@@ -30,13 +31,13 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Attachments:Render:Icons' => 'Visualizza come icone',
'Attachments:Render:Table' => 'Visualizza come lista',
'UI:Attachments:DropYourFileHint' => 'Rilascia i file ovunque in quest\'area',
));
]);
//
// Class: Attachment
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:Attachment' => 'Allegato',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Scadenza',
@@ -51,10 +52,9 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Contenuti',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Attachments:File:Thumbnail' => 'Icona',
'Attachments:File:Name' => 'Nome del file',
'Attachments:File:Date' => 'Data di caricamento',
@@ -62,32 +62,32 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Attachments:File:Size' => 'Dimensione',
'Attachments:File:MimeType' => 'Tipo',
'Attachments:File:DownloadsCount' => 'Download',
));
]);
//
// Class: Attachment
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:Attachment/Attribute:creation_date' => 'Data di creazione',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'ID utente',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'ID contatto',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (al download di un allegato dell\'oggetto)',
'Class:TriggerOnAttachmentDownload+' => 'Trigger al download di un allegato di un oggetto di [una sottoclasse di] la classe data',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment create~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment create~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Add file in email~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Attachments:TabTitle_Count' => '添付 (%1$d)',
'Attachments:EmptyTabTitle' => '添付',
'Attachments:FieldsetTitle' => '添付',
@@ -30,13 +31,13 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
'Attachments:Render:Icons' => 'Display as icons~~',
'Attachments:Render:Table' => 'Display as list~~',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
));
]);
//
// Class: Attachment
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:Attachment' => 'Attachment~~',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Expire~~',
@@ -51,10 +52,9 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Contents~~',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Attachments:File:Thumbnail' => 'Icon~~',
'Attachments:File:Name' => 'File name~~',
'Attachments:File:Date' => 'Upload date~~',
@@ -62,25 +62,25 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Attachments:File:Size' => 'Size~~',
'Attachments:File:MimeType' => 'Type~~',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:Attachment/Attribute:creation_date' => 'Creation date~~',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'User id~~',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'Contact id~~',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -89,5 +89,5 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,17 +1,18 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author LinProfs <info@linprofs.com>
* @author Jeffrey Bostoen <info@jeffreybostoen.be> (2018 - 2022)
* @author Thomas Casteleyn <thomas.casteleyn@super-visions.com>
*/
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Attachments:TabTitle_Count' => 'Bijlagen (%1$d)',
'Attachments:EmptyTabTitle' => 'Bijlagen',
'Attachments:FieldsetTitle' => 'Bijlagen',
@@ -32,13 +33,13 @@ of vraag de iTop administrator om de opslagruimte van de iTop-server na te kijke
'Attachments:Render:Icons' => 'Toon als pictogram',
'Attachments:Render:Table' => 'Toon als lijst',
'UI:Attachments:DropYourFileHint' => 'Sleep bestanden in dit gebied',
));
]);
//
// Class: Attachment
//
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:Attachment' => 'Bijlage',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Vervalt',
@@ -53,10 +54,9 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Inhoud',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Attachments:File:Thumbnail' => 'Pictogram',
'Attachments:File:Name' => 'Bestandsnaam',
'Attachments:File:Date' => 'Geüpload op',
@@ -64,32 +64,32 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Attachments:File:Size' => 'Grootte',
'Attachments:File:MimeType' => 'Type',
'Attachments:File:DownloadsCount' => 'Downloads',
));
]);
//
// Class: Attachment
//
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:Attachment/Attribute:creation_date' => 'Datum creatie',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'ID Gebruiker',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'ID Contact',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (Bij het downloaden van een bijlage)',
'Class:TriggerOnAttachmentDownload+' => 'Trigger bij het downloaden van een bijlage van een object van de opgegeven klasse (of subklasse ervan)',
'Class:TriggerOnAttachmentCreate' => 'Trigger (Bij het toevoegen van een bijlage)',
'Class:TriggerOnAttachmentCreate+' => 'Trigger bij het toevoegen van een bijlage aan een object van de opgegeven klasse (of subklasse ervan)',
'Class:TriggerOnAttachmentCreate' => 'Trigger (Bij het toevoegen van een bijlage)',
'Class:TriggerOnAttachmentCreate+' => 'Trigger bij het toevoegen van een bijlage aan een object van de opgegeven klasse (of subklasse ervan)',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Bestand toevoegen in e-mail',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+'=> 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (Bij het verwijderen van een bijlage)',
'Class:TriggerOnAttachmentDelete+' => 'Trigger bij het verwijderen van een bijlage van een object van de opgegeven klasse (of subklasse ervan)',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Attachments:TabTitle_Count' => 'Załączniki (%1$d)',
'Attachments:EmptyTabTitle' => 'Załączniki',
'Attachments:FieldsetTitle' => 'Załączniki',
@@ -30,13 +31,13 @@ lub zapytaj administratora '.ITOP_APPLICATION_SHORT.', czy dysk serwera '.ITOP_A
'Attachments:Render:Icons' => 'Wyświetlaj jako ikony',
'Attachments:Render:Table' => 'Wyświetl jako listę',
'UI:Attachments:DropYourFileHint' => 'Upuść pliki w dowolnym miejscu w tym obszarze',
));
]);
//
// Class: Attachment
//
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:Attachment' => 'Załącznik',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Wygasa',
@@ -51,10 +52,9 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Zawartość',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Attachments:File:Thumbnail' => 'Ikona',
'Attachments:File:Name' => 'Nazwa pliku',
'Attachments:File:Date' => 'Data przesłania',
@@ -62,32 +62,32 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Attachments:File:Size' => 'Rozmiar',
'Attachments:File:MimeType' => 'Typ',
'Attachments:File:DownloadsCount' => 'Pobrano',
));
]);
//
// Class: Attachment
//
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:Attachment/Attribute:creation_date' => 'Data utworzenia',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Id użytkownika',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Id kontaktu',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:TriggerOnAttachmentDownload' => 'Wyzwalacz (po pobraniu załącznika obiektu)',
'Class:TriggerOnAttachmentDownload+' => 'Wyzwalacz po pobraniu załącznika obiektu [klasy podrzędnej] danej klasy',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment create~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment create~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Add file in email~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Attachments:TabTitle_Count' => 'Anexos (%1$d)',
'Attachments:EmptyTabTitle' => 'Anexos',
'Attachments:FieldsetTitle' => 'Anexos',
@@ -30,13 +31,13 @@ ou entre em contato com o seu administrador do '.ITOP_APPLICATION_SHORT.' pois o
'Attachments:Render:Icons' => 'Exibir como ícones',
'Attachments:Render:Table' => 'Exibir como lista',
'UI:Attachments:DropYourFileHint' => 'Solte arquivos em qualquer lugar nesta área',
));
]);
//
// Class: Attachment
//
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:Attachment' => 'Anexo',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Expira',
@@ -51,10 +52,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Conteúdo',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Attachments:File:Thumbnail' => 'Ícone',
'Attachments:File:Name' => 'Nome do arquivo',
'Attachments:File:Date' => 'Data de envio',
@@ -62,25 +62,25 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Attachments:File:Size' => 'Tamanho',
'Attachments:File:MimeType' => 'Tipo',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:Attachment/Attribute:creation_date' => 'Data de criação',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Identificador do usuário',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Identificador do contato',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -89,5 +89,5 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,16 +1,17 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author Vladimir Kunin <v.b.kunin@gmail.com>
*
*/
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Attachments:TabTitle_Count' => 'Вложения (%1$d)',
'Attachments:EmptyTabTitle' => 'Вложения',
'Attachments:FieldsetTitle' => 'Вложения',
@@ -31,13 +32,13 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
'Attachments:Render:Icons' => 'Display as icons~~',
'Attachments:Render:Table' => 'Display as list~~',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
));
]);
//
// Class: Attachment
//
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:Attachment' => 'Вложение',
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => 'Истекает',
@@ -52,10 +53,9 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Class:Attachment/Attribute:item_org_id+' => '',
'Class:Attachment/Attribute:contents' => 'Содержимое',
'Class:Attachment/Attribute:contents+' => '',
));
]);
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Attachments:File:Thumbnail' => 'Предпросмотр',
'Attachments:File:Name' => 'Имя файла',
'Attachments:File:Date' => 'Дата',
@@ -63,25 +63,25 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Attachments:File:Size' => 'Размер',
'Attachments:File:MimeType' => 'Тип',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:Attachment/Attribute:creation_date' => 'Дата создания',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => 'Пользователь',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Контакт',
'Class:Attachment/Attribute:contact_id+' => '',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -90,5 +90,5 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Attachments:TabTitle_Count' => 'Prílohy (%1$d)',
'Attachments:EmptyTabTitle' => 'Prílohy',
'Attachments:FieldsetTitle' => 'Prílohy',
@@ -30,13 +31,13 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
'Attachments:Render:Icons' => 'Display as icons~~',
'Attachments:Render:Table' => 'Display as list~~',
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
));
]);
//
// Class: Attachment
//
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:Attachment' => 'Attachment~~',
'Class:Attachment+' => '~~',
'Class:Attachment/Attribute:expire' => 'Expire~~',
@@ -51,10 +52,9 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Class:Attachment/Attribute:item_org_id+' => '~~',
'Class:Attachment/Attribute:contents' => 'Contents~~',
'Class:Attachment/Attribute:contents+' => '~~',
));
]);
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Attachments:File:Thumbnail' => 'Icon~~',
'Attachments:File:Name' => 'File name~~',
'Attachments:File:Date' => 'Upload date~~',
@@ -62,25 +62,25 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Attachments:File:Size' => 'Size~~',
'Attachments:File:MimeType' => 'Type~~',
'Attachments:File:DownloadsCount' => 'Downloads~~',
));
]);
//
// Class: Attachment
//
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:Attachment/Attribute:creation_date' => 'Creation date~~',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => 'User id~~',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => 'Contact id~~',
'Class:Attachment/Attribute:contact_id+' => '~~',
));
]);
//
// Class: TriggerOnAttachmentDownload
//
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment create)~~',
@@ -89,5 +89,5 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment delete)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment delete~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
));
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
]);

Some files were not shown because too many files have changed in this diff Show More