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

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

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -23,30 +24,29 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
class UserRightsMatrixClassGrant extends DBObject class UserRightsMatrixClassGrant extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights", "category" => "addon/userrights",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "", "name_attcode" => "",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_ur_matrixclasses", "db_table" => "priv_ur_matrixclasses",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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_MANUAL, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("action", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
} }
} }
@@ -54,25 +54,25 @@ class UserRightsMatrixClassStimulusGrant extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights", "category" => "addon/userrights",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "", "name_attcode" => "",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_ur_matrixclassesstimulus", "db_table" => "priv_ur_matrixclassesstimulus",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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_MANUAL, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("stimulus", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
} }
} }
@@ -80,42 +80,39 @@ class UserRightsMatrixAttributeGrant extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights", "category" => "addon/userrights",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "", "name_attcode" => "",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_ur_matrixattributes", "db_table" => "priv_ur_matrixattributes",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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_MANUAL, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("attcode", ["allowed_values" => null, "sql" => "attcode", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("action", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
} }
} }
class UserRightsMatrix extends UserRightsAddOnAPI class UserRightsMatrix extends UserRightsAddOnAPI
{ {
static public $m_aActionCodes = array( public static $m_aActionCodes = [
UR_ACTION_READ => 'read', UR_ACTION_READ => 'read',
UR_ACTION_MODIFY => 'modify', UR_ACTION_MODIFY => 'modify',
UR_ACTION_DELETE => 'delete', UR_ACTION_DELETE => 'delete',
UR_ACTION_BULK_READ => 'bulk read', UR_ACTION_BULK_READ => 'bulk read',
UR_ACTION_BULK_MODIFY => 'bulk modify', UR_ACTION_BULK_MODIFY => 'bulk modify',
UR_ACTION_BULK_DELETE => 'bulk delete', UR_ACTION_BULK_DELETE => 'bulk delete',
); ];
// Installation: create the very first user // Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US') public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
@@ -149,8 +146,7 @@ class UserRightsMatrix extends UserRightsAddOnAPI
// Users must be added manually // Users must be added manually
// This procedure will then update the matrix when a new user is found or a new class/attribute appears // This procedure will then update the matrix when a new user is found or a new class/attribute appears
$oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT User")); $oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT User"));
while ($oUser = $oUserSet->Fetch()) while ($oUser = $oUserSet->Fetch()) {
{
$this->SetupUser($oUser->GetKey()); $this->SetupUser($oUser->GetKey());
} }
return true; return true;
@@ -158,23 +154,16 @@ class UserRightsMatrix extends UserRightsAddOnAPI
protected function SetupUser($iUserId, $bNewUser = false) protected function SetupUser($iUserId, $bNewUser = false)
{ {
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory) foreach (['bizmodel', 'application', 'gui', 'core/cmdb'] as $sCategory) {
{ foreach (MetaModel::GetClasses($sCategory) as $sClass) {
foreach (MetaModel::GetClasses($sCategory) as $sClass) foreach (self::$m_aActionCodes as $iActionCode => $sAction) {
{ if ($bNewUser) {
foreach (self::$m_aActionCodes as $iActionCode => $sAction)
{
if ($bNewUser)
{
$bAddCell = true; $bAddCell = true;
} } else {
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1); $bAddCell = ($oSet->Count() < 1);
} }
if ($bAddCell) if ($bAddCell) {
{
// Create a new entry // Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant"); $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
$oMyClassGrant->Set("userid", $iUserId); $oMyClassGrant->Set("userid", $iUserId);
@@ -184,19 +173,14 @@ class UserRightsMatrix extends UserRightsAddOnAPI
$iId = $oMyClassGrant->DBInsertNoReload(); $iId = $oMyClassGrant->DBInsertNoReload();
} }
} }
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
{ if ($bNewUser) {
if ($bNewUser)
{
$bAddCell = true; $bAddCell = true;
} } else {
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1); $bAddCell = ($oSet->Count() < 1);
} }
if ($bAddCell) if ($bAddCell) {
{
// Create a new entry // Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant"); $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
$oMyClassGrant->Set("userid", $iUserId); $oMyClassGrant->Set("userid", $iUserId);
@@ -206,21 +190,15 @@ class UserRightsMatrix extends UserRightsAddOnAPI
$iId = $oMyClassGrant->DBInsertNoReload(); $iId = $oMyClassGrant->DBInsertNoReload();
} }
} }
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) {
{ if ($bNewUser) {
if ($bNewUser)
{
$bAddCell = true; $bAddCell = true;
} } else {
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1); $bAddCell = ($oSet->Count() < 1);
} }
if ($bAddCell) if ($bAddCell) {
{ foreach (['read', 'modify'] as $sAction) {
foreach (array('read', 'modify') as $sAction)
{
// Create a new entry // Create a new entry
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant"); $oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
$oMyAttGrant->Set("userid", $iUserId); $oMyAttGrant->Set("userid", $iUserId);
@@ -261,14 +239,13 @@ class UserRightsMatrix extends UserRightsAddOnAPI
*/ */
} }
public function Init() public function Init()
{ {
// Could be loaded in a shared memory (?) // Could be loaded in a shared memory (?)
return true; return true;
} }
public function GetSelectFilter($oUser, $sClass, $aSettings = array()) public function GetSelectFilter($oUser, $sClass, $aSettings = [])
{ {
$oNullFilter = new DBObjectSearch($sClass); $oNullFilter = new DBObjectSearch($sClass);
return $oNullFilter; return $oNullFilter;
@@ -276,21 +253,18 @@ class UserRightsMatrix extends UserRightsAddOnAPI
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null) public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
{ {
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
{
return UR_ALLOWED_NO; return UR_ALLOWED_NO;
} }
$sAction = self::$m_aActionCodes[$iActionCode]; $sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1) if ($oSet->Count() < 1) {
{
return UR_ALLOWED_NO; return UR_ALLOWED_NO;
} }
$oGrantRecord = $oSet->Fetch(); $oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission')) switch ($oGrantRecord->Get('permission')) {
{
case 'yes': case 'yes':
$iRetCode = UR_ALLOWED_YES; $iRetCode = UR_ALLOWED_YES;
break; break;
@@ -304,21 +278,18 @@ class UserRightsMatrix extends UserRightsAddOnAPI
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null) public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
{ {
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
{
return UR_ALLOWED_NO; return UR_ALLOWED_NO;
} }
$sAction = self::$m_aActionCodes[$iActionCode]; $sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1) if ($oSet->Count() < 1) {
{
return UR_ALLOWED_NO; return UR_ALLOWED_NO;
} }
$oGrantRecord = $oSet->Fetch(); $oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission')) switch ($oGrantRecord->Get('permission')) {
{
case 'yes': case 'yes':
$iRetCode = UR_ALLOWED_YES; $iRetCode = UR_ALLOWED_YES;
break; break;
@@ -333,14 +304,12 @@ class UserRightsMatrix extends UserRightsAddOnAPI
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null) public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
{ {
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = '{$oUser->GetKey()}'")); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1) if ($oSet->Count() < 1) {
{
return UR_ALLOWED_NO; return UR_ALLOWED_NO;
} }
$oGrantRecord = $oSet->Fetch(); $oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission')) switch ($oGrantRecord->Get('permission')) {
{
case 'yes': case 'yes':
$iRetCode = UR_ALLOWED_YES; $iRetCode = UR_ALLOWED_YES;
break; break;
@@ -358,5 +327,3 @@ class UserRightsMatrix extends UserRightsAddOnAPI
} }
UserRights::SelectModule('UserRightsMatrix'); UserRights::SelectModule('UserRightsMatrix');
?>

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -47,7 +48,7 @@ class UserRightsNull extends UserRightsAddOnAPI
return true; return true;
} }
public function GetSelectFilter($oUser, $sClass, $aSettings = array()) public function GetSelectFilter($oUser, $sClass, $aSettings = [])
{ {
$oNullFilter = new DBObjectSearch($sClass); $oNullFilter = new DBObjectSearch($sClass);
return $oNullFilter; return $oNullFilter;
@@ -74,5 +75,3 @@ class UserRightsNull extends UserRightsAddOnAPI
} }
UserRights::SelectModule('UserRightsNull'); UserRights::SelectModule('UserRightsNull');
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -29,56 +30,52 @@ class UserRightsBaseClassGUI extends cmdbAbstractObject
} }
} }
class URP_Profiles extends UserRightsBaseClassGUI class URP_Profiles extends UserRightsBaseClassGUI
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights,grant_by_profile,filter", "category" => "addon/userrights,grant_by_profile,filter",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"complementary_name_attcode" => array('description'), "complementary_name_attcode" => ['description'],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_urp_profiles", "db_table" => "priv_urp_profiles",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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("name", ["allowed_values" => null, "sql" => "name", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
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("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 // Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'user_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['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('list', ['description']); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name','description')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['name','description']); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array ('name','description')); MetaModel::Init_SetZListItems('default_search', ['name','description']);
} }
protected static $m_aCacheProfiles = null; protected static $m_aCacheProfiles = null;
public static function DoCreateProfile($sName, $sDescription) public static function DoCreateProfile($sName, $sDescription)
{ {
if (is_null(self::$m_aCacheProfiles)) if (is_null(self::$m_aCacheProfiles)) {
{ self::$m_aCacheProfiles = [];
self::$m_aCacheProfiles = array();
$oFilterAll = new DBObjectSearch('URP_Profiles'); $oFilterAll = new DBObjectSearch('URP_Profiles');
$oSet = new DBObjectSet($oFilterAll); $oSet = new DBObjectSet($oFilterAll);
while ($oProfile = $oSet->Fetch()) while ($oProfile = $oSet->Fetch()) {
{
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey(); self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
} }
} }
$sCacheKey = $sName; $sCacheKey = $sName;
if (isset(self::$m_aCacheProfiles[$sCacheKey])) if (isset(self::$m_aCacheProfiles[$sCacheKey])) {
{
return self::$m_aCacheProfiles[$sCacheKey]; return self::$m_aCacheProfiles[$sCacheKey];
} }
$oNewObj = MetaModel::NewObject("URP_Profiles"); $oNewObj = MetaModel::NewObject("URP_Profiles");
@@ -89,27 +86,21 @@ class URP_Profiles extends UserRightsBaseClassGUI
return $iId; return $iId;
} }
function GetGrantAsHtml($oUserRights, $sClass, $sAction) public function GetGrantAsHtml($oUserRights, $sClass, $sAction)
{ {
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $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>'; 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>'; 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>'; 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 // Looks dirty, but ok that's THE ONE
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+')); $oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
return; return;
@@ -118,21 +109,18 @@ class URP_Profiles extends UserRightsBaseClassGUI
// Note: for sure, we assume that the instance is derived from UserRightsProfile // Note: for sure, we assume that the instance is derived from UserRightsProfile
$oUserRights = UserRights::GetModuleInstance(); $oUserRights = UserRights::GetModuleInstance();
$aDisplayData = array(); $aDisplayData = [];
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
{ $aStimuli = [];
$aStimuli = array(); foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
{
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); $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>'; $aStimuli[] = '<span title="'.$sStimulusCode.': '.utils::EscapeHtml($oStimulus->GetDescription()).'">'.utils::EscapeHtml($oStimulus->GetLabel()).'</span>';
} }
} }
$sStimuli = implode(', ', $aStimuli); $sStimuli = implode(', ', $aStimuli);
$aDisplayData[] = array( $aDisplayData[] = [
'class' => MetaModel::GetName($sClass), 'class' => MetaModel::GetName($sClass),
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'), 'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'), 'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'),
@@ -141,22 +129,22 @@ class URP_Profiles extends UserRightsBaseClassGUI
'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'), 'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'),
'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'), 'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'),
'stimuli' => $sStimuli, 'stimuli' => $sStimuli,
); ];
} }
$aDisplayConfig = array(); $aDisplayConfig = [];
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+')); $aDisplayConfig['class'] = ['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['read'] = ['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['bulkread'] = ['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['write'] = ['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['bulkwrite'] = ['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['delete'] = ['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['bulkdelete'] = ['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['stimuli'] = ['label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+')];
$oPage->table($aDisplayConfig, $aDisplayData); $oPage->table($aDisplayConfig, $aDisplayData);
} }
function DisplayBareRelations(WebPage $oPage, $bEditMode = false) public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{ {
parent::DisplayBareRelations($oPage, $bEditMode); parent::DisplayBareRelations($oPage, $bEditMode);
@@ -166,10 +154,9 @@ class URP_Profiles extends UserRightsBaseClassGUI
public static function GetReadOnlyAttributes() 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") // returns an array of id => array of column => php value(so-called "real value")
public static function GetPredefinedObjects() public static function GetPredefinedObjects()
{ {
@@ -181,15 +168,13 @@ class URP_Profiles extends UserRightsBaseClassGUI
protected function OnDelete() protected function OnDelete()
{ {
// Don't remove admin profile // 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')); 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" ! // Note: this may break the rule that says: "a user must have at least ONE profile" !
$oLnkSet = $this->Get('user_list'); $oLnkSet = $this->Get('user_list');
while($oLnk = $oLnkSet->Fetch()) while ($oLnk = $oLnkSet->Fetch()) {
{
$oLnk->DBDelete(); $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 * @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 * @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); $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!'; $aReasons[] = 'Sorry, profiles are read-only in the demonstration mode!';
$iFlags |= OPT_ATT_READONLY; $iFlags |= OPT_ATT_READONLY;
} }
@@ -214,52 +198,52 @@ class URP_Profiles extends UserRightsBaseClassGUI
} }
} }
class URP_UserProfile extends UserRightsBaseClassGUI class URP_UserProfile extends UserRightsBaseClassGUI
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights,grant_by_profile,filter", "category" => "addon/userrights,grant_by_profile,filter",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => array("userlogin", "profile"), "name_attcode" => ["userlogin", "profile"],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_urp_userprofile", "db_table" => "priv_urp_userprofile",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
"is_link" => true, /** @since 3.1.0 N°6482 */ "is_link" => true, /** @since 3.1.0 N°6482 */
'uniqueness_rules' => array( 'uniqueness_rules' => [
'no_duplicate' => array( 'no_duplicate' => [
'attributes' => array( 'attributes' => [
0 => 'userid', 0 => 'userid',
1 => 'profileid', 1 => 'profileid',
), ],
'filter' => '', 'filter' => '',
'disabled' => false, 'disabled' => false,
'is_blocking' => true, 'is_blocking' => true,
), ],
), ],
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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 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", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"))); MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", MetaModel::Init_AddAttribute(new AttributeExternalKey(
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))); "profileid",
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values" => null, "extkey_attcode" => 'profileid', "target_attcode" => "name"))); ["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 // Display lists
MetaModel::Init_SetZListItems('details', array('userid', 'profileid', 'reason')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['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('list', ['userid', 'profileid', 'reason']); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['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('advanced_search', ['userid', 'profileid']); // Criteria of the advanced search form
} }
public function CheckToDelete(&$oDeletionPlan) public function CheckToDelete(&$oDeletionPlan)
@@ -267,15 +251,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
if (MetaModel::GetConfig()->Get('demo_mode')) { if (MetaModel::GetConfig()->Get('demo_mode')) {
// Users deletion is NOT allowed in demo mode // Users deletion is NOT allowed in demo mode
$oDeletionPlan->AddToDelete($this, null); $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(); $oDeletionPlan->ComputeResults();
return false; return false;
} }
try { try {
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE); $this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
} } catch (SecurityException $e) {
catch (SecurityException $e) {
// Users deletion is NOT allowed // Users deletion is NOT allowed
$oDeletionPlan->AddToDelete($this, null); $oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true); $oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
@@ -292,15 +275,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
if (MetaModel::GetConfig()->Get('demo_mode')) { if (MetaModel::GetConfig()->Get('demo_mode')) {
// Users deletion is NOT allowed in demo mode // Users deletion is NOT allowed in demo mode
$oDeletionPlan->AddToDelete($this, null); $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(); $oDeletionPlan->ComputeResults();
return false; return false;
} }
try { try {
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE); $this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
} } catch (SecurityException $e) {
catch (SecurityException $e) {
// Users deletion is NOT allowed // Users deletion is NOT allowed
$oDeletionPlan->AddToDelete($this, null); $oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true); $oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
@@ -336,29 +318,26 @@ class URP_UserProfile extends UserRightsBaseClassGUI
protected function CheckIfProfileIsAllowed($iActionCode) protected function CheckIfProfileIsAllowed($iActionCode)
{ {
// When initializing or admin, we need to let everything pass trough // 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 // Only administrators can manage administrators
$iOrigUserId = $this->GetOriginal('userid'); $iOrigUserId = $this->GetOriginal('userid');
if (!empty($iOrigUserId)) if (!empty($iOrigUserId)) {
{
$oUser = MetaModel::GetObject('User', $iOrigUserId, true, true); $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')); throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
} }
} }
$oUser = MetaModel::GetObject('User', $this->Get('userid'), true, true); $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')); throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
} }
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, DBObjectSet::FromObject($this))) if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, DBObjectSet::FromObject($this))) {
{
throw new SecurityException(Dict::Format('UI:Error:ObjectCannotBeUpdated')); 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')); throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
} }
} }
@@ -369,33 +348,33 @@ class URP_UserOrg extends UserRightsBaseClassGUI
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "addon/userrights,grant_by_profile", "category" => "addon/userrights,grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => array("userlogin", "allowed_org_name"), "name_attcode" => ["userlogin", "allowed_org_name"],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_urp_userorg", "db_table" => "priv_urp_userorg",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //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 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", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); 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 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", array("allowed_values"=>null, "extkey_attcode"=> 'allowed_org_id', "target_attcode"=>"name"))); 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 // Display lists
MetaModel::Init_SetZListItems('details', array('userid', 'allowed_org_id', 'reason')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['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('list', ['allowed_org_id', 'reason']); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['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('advanced_search', ['userid', 'allowed_org_id']); // Criteria of the advanced search form
} }
protected function OnInsert() protected function OnInsert()
@@ -418,40 +397,37 @@ class URP_UserOrg extends UserRightsBaseClassGUI
*/ */
protected function CheckIfOrgIsAllowed() protected function CheckIfOrgIsAllowed()
{ {
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; } if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
return;
}
$oUser = UserRights::GetUserObject(); $oUser = UserRights::GetUserObject();
$oAddon = UserRights::GetModuleInstance(); $oAddon = UserRights::GetModuleInstance();
$aOrgs = $oAddon->GetUserOrgs($oUser, ''); $aOrgs = $oAddon->GetUserOrgs($oUser, '');
if (count($aOrgs) > 0) if (count($aOrgs) > 0) {
{
$iOrigOrgId = $this->GetOriginal('allowed_org_id'); $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')); throw new SecurityException(Dict::Format('Class:User/Error:OrganizationNotAllowed'));
} }
} }
} }
} }
class UserRightsProfile extends UserRightsAddOnAPI class UserRightsProfile extends UserRightsAddOnAPI
{ {
static public $m_aActionCodes = array( public static $m_aActionCodes = [
UR_ACTION_READ => 'r', UR_ACTION_READ => 'r',
UR_ACTION_MODIFY => 'w', UR_ACTION_MODIFY => 'w',
UR_ACTION_DELETE => 'd', UR_ACTION_DELETE => 'd',
UR_ACTION_BULK_READ => 'br', UR_ACTION_BULK_READ => 'br',
UR_ACTION_BULK_MODIFY => 'bw', UR_ACTION_BULK_MODIFY => 'bw',
UR_ACTION_BULK_DELETE => 'bd', 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, ...] * @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 * @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
*/ */
private $aUsersProfilesList = []; private $aUsersProfilesList = [];
// Installation: create the very first user // Installation: create the very first user
@@ -472,8 +448,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
$oContact = MetaModel::NewObject('Person'); $oContact = MetaModel::NewObject('Person');
$oContact->Set('name', 'My last name'); $oContact->Set('name', 'My last name');
$oContact->Set('first_name', 'My first 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('org_id', $iOrgId);
} }
$oContact->Set('email', 'my.email@foo.org'); $oContact->Set('email', 'my.email@foo.org');
@@ -481,20 +456,17 @@ class UserRightsProfile extends UserRightsAddOnAPI
} }
} }
$oUser = new UserLocal(); $oUser = new UserLocal();
$oUser->Set('login', $sAdminUser); $oUser->Set('login', $sAdminUser);
$oUser->Set('password', $sAdminPwd); $oUser->Set('password', $sAdminPwd);
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0)) if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0)) {
{
$oUser->Set('contactid', $iContactId); $oUser->Set('contactid', $iContactId);
} }
$oUser->Set('language', $sLanguage); // Language was chosen during the installation $oUser->Set('language', $sLanguage); // Language was chosen during the installation
// Add this user to the very specific 'admin' profile // 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*/); $oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => ADMIN_PROFILE_NAME], true /*all data*/);
if (is_object($oAdminProfile)) if (is_object($oAdminProfile)) {
{
$oUserProfile = new URP_UserProfile(); $oUserProfile = new URP_UserProfile();
$oUserProfile->Set('profileid', $oAdminProfile->GetKey()); $oUserProfile->Set('profileid', $oAdminProfile->GetKey());
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile'); $oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
@@ -509,11 +481,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] 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) // 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 * Read and cache organizations allowed to the given user
@@ -528,31 +500,25 @@ class UserRightsProfile extends UserRightsAddOnAPI
public function GetUserOrgs($oUser, $sClass) public function GetUserOrgs($oUser, $sClass)
{ {
$iUser = $oUser->GetKey(); $iUser = $oUser->GetKey();
if (!array_key_exists($iUser, $this->m_aUserOrgs)) if (!array_key_exists($iUser, $this->m_aUserOrgs)) {
{ $this->m_aUserOrgs[$iUser] = [];
$this->m_aUserOrgs[$iUser] = array();
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization'); $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'; $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)); $oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), [], ['userid' => $iUser]);
while ($aRow = $oUserOrgSet->FetchAssoc()) while ($aRow = $oUserOrgSet->FetchAssoc()) {
{
$oOrg = $aRow['Org']; $oOrg = $aRow['Org'];
$this->m_aUserOrgs[$iUser][] = $oOrg->GetKey(); $this->m_aUserOrgs[$iUser][] = $oOrg->GetKey();
} }
} } else {
else
{
$oSearch = new DBObjectSearch('URP_UserOrg'); $oSearch = new DBObjectSearch('URP_UserOrg');
$oSearch->AllowAllData(); $oSearch->AllowAllData();
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid')); $oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
$oSearch->AddConditionExpression($oCondition); $oSearch->AddConditionExpression($oCondition);
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser)); $oUserOrgSet = new DBObjectSet($oSearch, [], ['userid' => $iUser]);
while ($oUserOrg = $oUserOrgSet->Fetch()) while ($oUserOrg = $oUserOrgSet->Fetch()) {
{
$this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id'); $this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id');
} }
} }
@@ -563,21 +529,19 @@ class UserRightsProfile extends UserRightsAddOnAPI
public function ResetCache() public function ResetCache()
{ {
// Loaded by Load cache // Loaded by Load cache
$this->m_aUserOrgs = array(); $this->m_aUserOrgs = [];
// Cache // Cache
$this->m_aObjectActionGrants = array(); $this->m_aObjectActionGrants = [];
$this->m_aAdministrators = null; $this->m_aAdministrators = null;
} }
public function LoadCache() public function LoadCache()
{ {
static $bSharedObjectInitialized = false; static $bSharedObjectInitialized = false;
if (!$bSharedObjectInitialized) if (!$bSharedObjectInitialized) {
{
$bSharedObjectInitialized = true; $bSharedObjectInitialized = true;
if (self::HasSharing()) if (self::HasSharing()) {
{
SharedObject::InitSharedClassProperties(); SharedObject::InitSharedClassProperties();
} }
} }
@@ -615,45 +579,40 @@ class UserRightsProfile extends UserRightsAddOnAPI
*/ */
public function ListProfiles($oUser) public function ListProfiles($oUser)
{ {
$aRet = array(); $aRet = [];
$oSearch = new DBObjectSearch('URP_UserProfile'); $oSearch = new DBObjectSearch('URP_UserProfile');
$oSearch->AllowAllData(); $oSearch->AllowAllData();
$oSearch->NoContextParameters(); $oSearch->NoContextParameters();
$oSearch->Addcondition('userid', $oUser->GetKey(), '='); $oSearch->Addcondition('userid', $oUser->GetKey(), '=');
$oProfiles = new DBObjectSet($oSearch); $oProfiles = new DBObjectSet($oSearch);
while ($oUserProfile = $oProfiles->Fetch()) while ($oUserProfile = $oProfiles->Fetch()) {
{
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname'); $aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
} }
return $aRet; return $aRet;
} }
public function GetSelectFilter($oUser, $sClass, $aSettings = array()) public function GetSelectFilter($oUser, $sClass, $aSettings = [])
{ {
$this->LoadCache(); $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 // 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) // 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) // 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); $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO) if ($aObjectPermissions['permission'] == UR_ALLOWED_NO) {
{
return false; return false;
} }
} }
$oFilter = true; $oFilter = true;
$aConditions = array(); $aConditions = [];
// Determine if this class is part of a silo and build the filter for it // Determine if this class is part of a silo and build the filter for it
$sAttCode = self::GetOwnerOrganizationAttCode($sClass); $sAttCode = self::GetOwnerOrganizationAttCode($sClass);
if (!is_null($sAttCode)) if (!is_null($sAttCode)) {
{
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass); $aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
if (count($aUserOrgs) > 0) if (count($aUserOrgs) > 0) {
{
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode); $oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
} }
// else: No org means 'any org' // else: No org means 'any org'
@@ -662,20 +621,15 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Specific conditions to hide, for non-administrators, the Administrator Users, the Administrator Profile and related links // 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. // Note: when logged as an administrator, GetSelectFilter is completely bypassed.
if ($this->AdministratorsAreHidden()) if ($this->AdministratorsAreHidden()) {
{ if ($sClass == 'URP_Profiles') {
if ($sClass == 'URP_Profiles')
{
$oExpression = new FieldExpression('id', $sClass); $oExpression = new FieldExpression('id', $sClass);
$oScalarExpr = new ScalarExpression(1); $oScalarExpr = new ScalarExpression(1);
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr); $aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
} } elseif (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User'))) {
else if (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User')))
{
$aAdministrators = $this->GetAdministrators(); $aAdministrators = $this->GetAdministrators();
if (count($aAdministrators) > 0) if (count($aAdministrators) > 0) {
{
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id'; $sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
$oExpression = new FieldExpression($sAttCode, $sClass); $oExpression = new FieldExpression($sAttCode, $sClass);
$oListExpr = ListExpression::FromScalars($aAdministrators); $oListExpr = ListExpression::FromScalars($aAdministrators);
@@ -685,17 +639,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
} }
// Handling of the added conditions // Handling of the added conditions
if (count($aConditions) > 0) if (count($aConditions) > 0) {
{ if ($oFilter === true) {
if($oFilter === true)
{
// No 'silo' filter, let's build a clean one // No 'silo' filter, let's build a clean one
$oFilter = new DBObjectSearch($sClass); $oFilter = new DBObjectSearch($sClass);
} }
// Add the conditions to the filter // Add the conditions to the filter
foreach($aConditions as $oCondition) foreach ($aConditions as $oCondition) {
{
$oFilter->AddConditionExpression($oCondition); $oFilter->AddConditionExpression($oCondition);
} }
} }
@@ -710,10 +661,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
*/ */
private function GetAdministrators() private function GetAdministrators()
{ {
if ($this->m_aAdministrators === null) if ($this->m_aAdministrators === null) {
{
// Find all administrators // Find all administrators
$this->m_aAdministrators = array(); $this->m_aAdministrators = [];
$oAdministratorsFilter = new DBObjectSearch('User'); $oAdministratorsFilter = new DBObjectSearch('User');
$oLnkFilter = new DBObjectSearch('URP_UserProfile'); $oLnkFilter = new DBObjectSearch('URP_UserProfile');
$oExpression = new FieldExpression('profileid', 'URP_UserProfile'); $oExpression = new FieldExpression('profileid', 'URP_UserProfile');
@@ -723,9 +673,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid'); $oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !! $oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
$oSet = new DBObjectSet($oAdministratorsFilter); $oSet = new DBObjectSet($oAdministratorsFilter);
$oSet->OptimizeColumnLoad(array('User' => array('login'))); $oSet->OptimizeColumnLoad(['User' => ['login']]);
while($oUser = $oSet->Fetch()) while ($oUser = $oSet->Fetch()) {
{
$this->m_aAdministrators[] = $oUser->GetKey(); $this->m_aAdministrators[] = $oUser->GetKey();
} }
} }
@@ -741,7 +690,6 @@ class UserRightsProfile extends UserRightsAddOnAPI
return ((bool)MetaModel::GetConfig()->Get('security.hide_administrators')); 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 // This verb has been made public to allow the development of an accurate feedback for the current configuration
public function GetProfileActionGrant($iProfile, $sClass, $sAction) public function GetProfileActionGrant($iProfile, $sClass, $sAction)
{ {
@@ -758,33 +706,29 @@ class UserRightsProfile extends UserRightsAddOnAPI
// load and cache permissions for the current user on the given class // load and cache permissions for the current user on the given class
// //
$iUser = $oUser->GetKey(); $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]; $aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
if (is_array($aTest)) return $aTest; if (is_array($aTest)) {
return $aTest;
}
} }
$sAction = self::$m_aActionCodes[$iActionCode]; $sAction = self::$m_aActionCodes[$iActionCode];
$bStatus = null; $bStatus = null;
// Cache user's profiles // Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){ if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser); $this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
} }
// Call the API of UserRights because it caches the list for us // 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); $bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
if (!is_null($bGrant)) if (!is_null($bGrant)) {
{ if ($bGrant) {
if ($bGrant) if (is_null($bStatus)) {
{
if (is_null($bStatus))
{
$bStatus = true; $bStatus = true;
} }
} } else {
else
{
$bStatus = false; $bStatus = false;
} }
} }
@@ -792,9 +736,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
$iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO; $iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO;
$aRes = array( $aRes = [
'permission' => $iPermission, 'permission' => $iPermission,
); ];
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes; $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
return $aRes; return $aRes;
} }
@@ -809,20 +753,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: In most cases the object set is ignored because it was interesting to optimize for huge data sets // 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 // 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! // 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 // 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 // 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 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 // We have to answer NO for objects shared for reading purposes
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) { if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
@@ -886,8 +823,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: this code is VERY close to the code of IsActionAllowed() // Note: this code is VERY close to the code of IsActionAllowed()
$iUser = $oUser->GetKey(); $iUser = $oUser->GetKey();
// Cache user's profiles // Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){ if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser); $this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
} }
@@ -895,20 +832,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
// and acceptable to consider only the root class of the object set // and acceptable to consider only the root class of the object set
$bStatus = null; $bStatus = null;
// Call the API of UserRights because it caches the list for us // 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); $bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
if (!is_null($bGrant)) if (!is_null($bGrant)) {
{ if ($bGrant) {
if ($bGrant) if (is_null($bStatus)) {
{
if (is_null($bStatus))
{
$bStatus = true; $bStatus = true;
} }
} } else {
else
{
$bStatus = false; $bStatus = false;
} }
} }
@@ -932,22 +863,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
{ {
$sAttCode = null; $sAttCode = null;
$aCallSpec = array($sClass, 'MapContextParam'); $aCallSpec = [$sClass, 'MapContextParam'];
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization')) if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization')) {
{
$sAttCode = 'id'; $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 $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... // Skip silently. The data model checker will tell you something about this...
$sAttCode = null; $sAttCode = null;
} }
} } elseif (MetaModel::IsValidAttCode($sClass, 'org_id')) {
elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
{
$sAttCode = 'org_id'; $sAttCode = 'org_id';
} }
@@ -960,14 +885,11 @@ class UserRightsProfile extends UserRightsAddOnAPI
protected static function HasSharing() protected static function HasSharing()
{ {
static $bHasSharing; static $bHasSharing;
if (!isset($bHasSharing)) if (!isset($bHasSharing)) {
{
$bHasSharing = class_exists('SharedObject'); $bHasSharing = class_exists('SharedObject');
} }
return $bHasSharing; return $bHasSharing;
} }
} }
UserRights::SelectModule('UserRightsProfile'); UserRights::SelectModule('UserRightsProfile');

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 <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -25,5 +26,5 @@ require_once('approot.inc.php');
require_once('application/startup.inc.php'); require_once('application/startup.inc.php');
return function (array $context) { return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
}; };

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -48,8 +49,7 @@ class DBSearchHelper
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); $oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode); $oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
} }
} } catch (Exception $e) {
catch (Exception $e) {
// If filtering fails just ignore it // If filtering fails just ignore it
} }
} }
@@ -57,4 +57,4 @@ class DBSearchHelper
} }
} }
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -16,10 +17,9 @@ use Combodo\iTop\Application\WebPage\AjaxPage;
*/ */
class ajax_page extends AjaxPage class ajax_page extends AjaxPage
{ {
function __construct($s_title) public function __construct($s_title)
{ {
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead'); DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead');
parent::__construct($s_title); parent::__construct($s_title);
} }
} }

View File

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

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* Class ApplicationContext * Class ApplicationContext
* *
@@ -47,16 +47,16 @@ interface iDBObjectURLMaker
/** /**
* Direct end-users to the standard iTop application: UI.php * Direct end-users to the standard iTop application: UI.php
*/ */
class iTopStandardURLMaker implements iDBObjectURLMaker class iTopStandardURLMaker implements iDBObjectURLMaker
{ {
/** /**
* @param string $sClass * @param string $sClass
* @param string $iId * @param string $iId
* *
* @return string * @return string
* @throws \Exception * @throws \Exception
*/ */
public static function MakeObjectURL($sClass, $iId) public static function MakeObjectURL($sClass, $iId)
{ {
$sPage = DBObject::ComputeStandardUIPage($sClass); $sPage = DBObject::ComputeStandardUIPage($sClass);
@@ -68,16 +68,16 @@ class iTopStandardURLMaker implements iDBObjectURLMaker
/** /**
* Direct end-users to the standard Portal application * Direct end-users to the standard Portal application
*/ */
class PortalURLMaker implements iDBObjectURLMaker class PortalURLMaker implements iDBObjectURLMaker
{ {
/** /**
* @param string $sClass * @param string $sClass
* @param string $iId * @param string $iId
* *
* @return string * @return string
* @throws \Exception * @throws \Exception
*/ */
public static function MakeObjectURL($sClass, $iId) public static function MakeObjectURL($sClass, $iId)
{ {
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot(); $sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
@@ -86,7 +86,6 @@ class PortalURLMaker implements iDBObjectURLMaker
} }
} }
/** /**
* Helper class to store and manipulate the parameters that make the application's context * Helper class to store and manipulate the parameters that make the application's context
* *
@@ -99,99 +98,90 @@ class PortalURLMaker implements iDBObjectURLMaker
*/ */
class ApplicationContext class ApplicationContext
{ {
public static $m_sUrlMakerClass = null; public static $m_sUrlMakerClass = null;
protected static $m_aPluginProperties = null; protected static $m_aPluginProperties = null;
protected static $aDefaultValues; // Cache shared among all instances protected static $aDefaultValues; // Cache shared among all instances
protected $aNames; protected $aNames;
protected $aValues; protected $aValues;
/** /**
* ApplicationContext constructor. * ApplicationContext constructor.
* *
* @param bool $bReadContext * @param bool $bReadContext
* *
* @throws \Exception * @throws \Exception
*/ */
public function __construct($bReadContext = true) public function __construct($bReadContext = true)
{ {
$this->aNames = array( $this->aNames = [
'org_id', 'menu' 'org_id', 'menu',
); ];
if ($bReadContext) if ($bReadContext) {
{ $this->ReadContext();
$this->ReadContext();
} }
} }
/** /**
* Read the context directly in the PHP parameters (either POST or GET) * Read the context directly in the PHP parameters (either POST or GET)
* return nothing * return nothing
* *
* @throws \Exception * @throws \Exception
*/ */
protected function ReadContext() protected function ReadContext()
{ {
if (!isset(self::$aDefaultValues)) if (!isset(self::$aDefaultValues)) {
{ self::$aDefaultValues = [];
self::$aDefaultValues = array(); $aContext = utils::ReadParam('c', [], false, 'context_param');
$aContext = utils::ReadParam('c', array(), false, 'context_param'); foreach ($this->aNames as $sName) {
foreach($this->aNames as $sName)
{
$sValue = isset($aContext[$sName]) ? $aContext[$sName] : ''; $sValue = isset($aContext[$sName]) ? $aContext[$sName] : '';
// TO DO: check if some of the context parameters are mandatory (or have default values) // TO DO: check if some of the context parameters are mandatory (or have default values)
if (!empty($sValue)) if (!empty($sValue)) {
{
self::$aDefaultValues[$sName] = $sValue; self::$aDefaultValues[$sName] = $sValue;
} }
// Hmm, there must be a better (more generic) way to handle the case below: // Hmm, there must be a better (more generic) way to handle the case below:
// When there is only one possible (allowed) organization, the context must be // When there is only one possible (allowed) organization, the context must be
// fixed to this org unless there is only one organization in the system then // fixed to this org unless there is only one organization in the system then
// no filter is applied // no filter is applied
if ($sName == 'org_id') if ($sName == 'org_id') {
{ if (MetaModel::IsValidClass('Organization')) {
if (MetaModel::IsValidClass('Organization'))
{
$oSearchFilter = new DBObjectSearch('Organization'); $oSearchFilter = new DBObjectSearch('Organization');
$oSet = new CMDBObjectSet($oSearchFilter); $oSet = new CMDBObjectSet($oSearchFilter);
$iCount = $oSet->CountWithLimit(2); $iCount = $oSet->CountWithLimit(2);
if ($iCount > 1) if ($iCount > 1) {
{
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
$oSet = new CMDBObjectSet($oSearchFilter); $oSet = new CMDBObjectSet($oSearchFilter);
$iCount = $oSet->CountWithLimit(2); $iCount = $oSet->CountWithLimit(2);
if ($iCount == 1) if ($iCount == 1) {
{
// Only one possible value for org_id, set it in the context // Only one possible value for org_id, set it in the context
$oOrg = $oSet->Fetch(); $oOrg = $oSet->Fetch();
self::$aDefaultValues[$sName] = $oOrg->GetKey(); self::$aDefaultValues[$sName] = $oOrg->GetKey();
} }
} }
} }
} }
} }
} }
$this->aValues = self::$aDefaultValues; $this->aValues = self::$aDefaultValues;
} }
/** /**
* Returns the current value for the given parameter * Returns the current value for the given parameter
* *
* @param string $sParamName Name of the parameter to read * @param string $sParamName Name of the parameter to read
* @param string $defaultValue * @param string $defaultValue
* *
* @return mixed The value for this parameter * @return mixed The value for this parameter
*/ */
public function GetCurrentValue($sParamName, $defaultValue = '') public function GetCurrentValue($sParamName, $defaultValue = '')
{ {
if (isset($this->aValues[$sParamName])) if (isset($this->aValues[$sParamName])) {
{
return $this->aValues[$sParamName]; return $this->aValues[$sParamName];
} }
return $defaultValue; return $defaultValue;
} }
/** /**
* Returns the context as string with the format name1=value1&name2=value2.... * Returns the context as string with the format name1=value1&name2=value2....
* @return string The context as a string to be appended to an href property * @return string The context as a string to be appended to an href property
@@ -200,21 +190,20 @@ class ApplicationContext
public function GetForLink(bool $bWithLeadingAmpersand = false) public function GetForLink(bool $bWithLeadingAmpersand = false)
{ {
// If there are no parameters, return an empty string // If there are no parameters, return an empty string
if(empty($this->aValues)){ if (empty($this->aValues)) {
return ''; return '';
} }
// Build the query string with ampersand separated parameters // Build the query string with ampersand separated parameters
$aParams = array(); $aParams = [];
foreach($this->aValues as $sName => $sValue) foreach ($this->aValues as $sName => $sValue) {
{
$aParams[] = "c[$sName]".'='.urlencode($sValue); $aParams[] = "c[$sName]".'='.urlencode($sValue);
} }
$sReturnValue = implode('&', $aParams); $sReturnValue = implode('&', $aParams);
// add the leading ampersand if requested // add the leading ampersand if requested
if($bWithLeadingAmpersand){ if ($bWithLeadingAmpersand) {
$sReturnValue = '&' . $sReturnValue; $sReturnValue = '&'.$sReturnValue;
} }
return $sReturnValue; return $sReturnValue;
@@ -278,14 +267,13 @@ class ApplicationContext
*/ */
public function GetAsHash() public function GetAsHash()
{ {
$aReturn = array(); $aReturn = [];
foreach($this->aValues as $sName => $sValue) foreach ($this->aValues as $sName => $sValue) {
{
$aReturn["c[$sName]"] = $sValue; $aReturn["c[$sName]"] = $sValue;
} }
return $aReturn; return $aReturn;
} }
/** /**
* Returns an array of the context parameters NAMEs * Returns an array of the context parameters NAMEs
* @return array The list of context parameters * @return array The list of context parameters
@@ -298,11 +286,10 @@ class ApplicationContext
* Removes the specified parameter from the context, for example when the same parameter * Removes the specified parameter from the context, for example when the same parameter
* is already a search parameter * is already a search parameter
* @param string $sParamName Name of the parameter to remove * @param string $sParamName Name of the parameter to remove
*/ */
public function Reset($sParamName) public function Reset($sParamName)
{ {
if (isset($this->aValues[$sParamName])) if (isset($this->aValues[$sParamName])) {
{
unset($this->aValues[$sParamName]); unset($this->aValues[$sParamName]);
} }
} }
@@ -318,27 +305,22 @@ class ApplicationContext
public function InitObjectFromContext(DBObject &$oObj) public function InitObjectFromContext(DBObject &$oObj)
{ {
$sClass = get_class($oObj); $sClass = get_class($oObj);
foreach($this->GetNames() as $key) foreach ($this->GetNames() as $key) {
{ $aCallSpec = [$sClass, 'MapContextParam'];
$aCallSpec = array($sClass, 'MapContextParam'); if (is_callable($aCallSpec)) {
if (is_callable($aCallSpec)) $sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
{
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->IsWritable()) if ($oAttDef->IsWritable()) {
{
$value = $this->GetCurrentValue($key, null); $value = $this->GetCurrentValue($key, null);
if (!is_null($value)) if (!is_null($value)) {
{
$oObj->Set($sAttCode, $value); $oObj->Set($sAttCode, $value);
} }
} }
} }
} }
} }
} }
/** /**
@@ -362,14 +344,10 @@ class ApplicationContext
*/ */
public static function GetUrlMakerClass() public static function GetUrlMakerClass()
{ {
if (is_null(self::$m_sUrlMakerClass)) if (is_null(self::$m_sUrlMakerClass)) {
{ if (Session::IsSet('UrlMakerClass')) {
if (Session::IsSet('UrlMakerClass'))
{
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass'); self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
} } else {
else
{
self::$m_sUrlMakerClass = 'iTopStandardURLMaker'; self::$m_sUrlMakerClass = 'iTopStandardURLMaker';
} }
} }
@@ -387,23 +365,23 @@ class ApplicationContext
* @return string the name of the class * @return string the name of the class
* @throws \Exception * @throws \Exception
*/ */
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true) public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
{ {
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
if (is_null($sUrlMakerClass)) { if (is_null($sUrlMakerClass)) {
$sUrlMakerClass = self::GetUrlMakerClass(); $sUrlMakerClass = self::GetUrlMakerClass();
} }
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey); $sUrl = call_user_func([$sUrlMakerClass, 'MakeObjectUrl'], $sObjClass, $sObjKey);
if (utils::StrLen($sUrl) > 0) { if (utils::StrLen($sUrl) > 0) {
if ($bWithNavigationContext) { if ($bWithNavigationContext) {
return $sUrl.$oAppContext->GetForLink(true); return $sUrl.$oAppContext->GetForLink(true);
} else { } else {
return $sUrl; return $sUrl;
} }
} else { } else {
return ''; return '';
} }
} }
/** /**
@@ -412,13 +390,10 @@ class ApplicationContext
*/ */
protected static function LoadPluginProperties() protected static function LoadPluginProperties()
{ {
if (Session::IsSet('PluginProperties')) if (Session::IsSet('PluginProperties')) {
{
self::$m_aPluginProperties = Session::Get('PluginProperties'); self::$m_aPluginProperties = Session::Get('PluginProperties');
} } else {
else self::$m_aPluginProperties = [];
{
self::$m_aPluginProperties = array();
} }
} }
@@ -431,7 +406,9 @@ class ApplicationContext
*/ */
public static function SetPluginProperty($sPluginClass, $sProperty, $value) public static function SetPluginProperty($sPluginClass, $sProperty, $value)
{ {
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties(); if (is_null(self::$m_aPluginProperties)) {
self::LoadPluginProperties();
}
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value; self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value); Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
@@ -444,15 +421,14 @@ class ApplicationContext
*/ */
public static function GetPluginProperties($sPluginClass) public static function GetPluginProperties($sPluginClass)
{ {
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties(); if (is_null(self::$m_aPluginProperties)) {
self::LoadPluginProperties();
if (array_key_exists($sPluginClass, self::$m_aPluginProperties))
{
return self::$m_aPluginProperties[$sPluginClass];
} }
else
{ if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) {
return array(); return self::$m_aPluginProperties[$sPluginClass];
} else {
return [];
} }
} }

View File

@@ -524,7 +524,7 @@ abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
*/ */
public function EnumUsedAttributes($oObject) public function EnumUsedAttributes($oObject)
{ {
return array(); return [];
} }
/** /**
@@ -548,7 +548,7 @@ abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
*/ */
public function EnumAllowedActions(DBObjectSet $oSet) public function EnumAllowedActions(DBObjectSet $oSet)
{ {
return array(); return [];
} }
} }
@@ -686,7 +686,7 @@ abstract class AbstractApplicationObjectExtension implements iApplicationObjectE
*/ */
public function OnCheckToWrite($oObject) public function OnCheckToWrite($oObject)
{ {
return array(); return [];
} }
/** /**
@@ -694,7 +694,7 @@ abstract class AbstractApplicationObjectExtension implements iApplicationObjectE
*/ */
public function OnCheckToDelete($oObject) public function OnCheckToDelete($oObject)
{ {
return array(); return [];
} }
/** /**
@@ -739,21 +739,21 @@ interface iPopupMenuExtension
* $param is a DBObjectSet containing the list of objects * $param is a DBObjectSet containing the list of objects
* @api * @api
*/ */
const MENU_OBJLIST_ACTIONS = 1; public const MENU_OBJLIST_ACTIONS = 1;
/** /**
* Insert an item into the Toolkit menu of a list * Insert an item into the Toolkit menu of a list
* *
* $param is a DBObjectSet containing the list of objects * $param is a DBObjectSet containing the list of objects
* @api * @api
*/ */
const MENU_OBJLIST_TOOLKIT = 2; public const MENU_OBJLIST_TOOLKIT = 2;
/** /**
* Insert an item into the Actions menu on an object details page * Insert an item into the Actions menu on an object details page
* *
* $param is a DBObject instance: the object currently displayed * $param is a DBObject instance: the object currently displayed
* @api * @api
*/ */
const MENU_OBJDETAILS_ACTIONS = 3; public const MENU_OBJDETAILS_ACTIONS = 3;
/** /**
* Insert an item into the Dashboard menu * Insert an item into the Dashboard menu
* *
@@ -763,14 +763,14 @@ interface iPopupMenuExtension
* $param is a Dashboard instance: the dashboard currently displayed * $param is a Dashboard instance: the dashboard currently displayed
* @api * @api
*/ */
const MENU_DASHBOARD_ACTIONS = 4; public const MENU_DASHBOARD_ACTIONS = 4;
/** /**
* Insert an item into the User menu (upper right corner) * Insert an item into the User menu (upper right corner)
* *
* $param is null * $param is null
* @api * @api
*/ */
const MENU_USER_ACTIONS = 5; public const MENU_USER_ACTIONS = 5;
/** /**
* Insert an item into the Action menu on an object item in an objects list in the portal * Insert an item into the Action menu on an object item in an objects list in the portal
* *
@@ -778,7 +778,7 @@ interface iPopupMenuExtension
* the current line) * the current line)
* @api * @api
*/ */
const PORTAL_OBJLISTITEM_ACTIONS = 7; public const PORTAL_OBJLISTITEM_ACTIONS = 7;
/** /**
* Insert an item into the Action menu on an object details page in the portal * Insert an item into the Action menu on an object details page in the portal
* *
@@ -786,7 +786,7 @@ interface iPopupMenuExtension
* currently displayed) * currently displayed)
* @api * @api
*/ */
const PORTAL_OBJDETAILS_ACTIONS = 8; public const PORTAL_OBJDETAILS_ACTIONS = 8;
/** /**
* Insert an item into the Actions menu of a list in the portal * Insert an item into the Actions menu of a list in the portal
@@ -796,7 +796,7 @@ interface iPopupMenuExtension
* *
* @todo * @todo
*/ */
const PORTAL_OBJLIST_ACTIONS = 6; public const PORTAL_OBJLIST_ACTIONS = 6;
/** /**
* Insert an item into the user menu of the portal * Insert an item into the user menu of the portal
* Note: This is not implemented yet ! * Note: This is not implemented yet !
@@ -805,7 +805,7 @@ interface iPopupMenuExtension
* *
* @todo * @todo
*/ */
const PORTAL_USER_ACTIONS = 9; public const PORTAL_USER_ACTIONS = 9;
/** /**
* Insert an item into the navigation menu of the portal * Insert an item into the navigation menu of the portal
* Note: This is not implemented yet ! * Note: This is not implemented yet !
@@ -814,7 +814,7 @@ interface iPopupMenuExtension
* *
* @todo * @todo
*/ */
const PORTAL_MENU_ACTIONS = 10; public const PORTAL_MENU_ACTIONS = 10;
/** /**
* Get the list of items to be added to a menu. * Get the list of items to be added to a menu.
@@ -864,7 +864,7 @@ abstract class ApplicationPopupMenuItem
$this->sLabel = $sLabel; $this->sLabel = $sLabel;
$this->sTooltip = ''; $this->sTooltip = '';
$this->sIconClass = ''; $this->sIconClass = '';
$this->aCssClasses = array(); $this->aCssClasses = [];
} }
/** /**
@@ -920,7 +920,6 @@ abstract class ApplicationPopupMenuItem
$this->aCssClasses[] = $sCssClass; $this->aCssClasses[] = $sCssClass;
} }
/** /**
* @param $sTooltip * @param $sTooltip
* *
@@ -976,7 +975,7 @@ abstract class ApplicationPopupMenuItem
/** @ignore */ /** @ignore */
public function GetLinkedScripts() public function GetLinkedScripts()
{ {
return array(); return [];
} }
} }
@@ -1015,13 +1014,13 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
/** @ignore */ /** @ignore */
public function GetMenuItem() public function GetMenuItem()
{ {
return array('label' => $this->GetLabel(), return ['label' => $this->GetLabel(),
'url' => $this->GetUrl(), 'url' => $this->GetUrl(),
'target' => $this-> GetTarget(), 'target' => $this-> GetTarget(),
'css_classes' => $this->aCssClasses, 'css_classes' => $this->aCssClasses,
'icon_class' => $this->sIconClass, 'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip 'tooltip' => $this->sTooltip,
); ];
} }
/** @ignore */ /** @ignore */
@@ -1065,7 +1064,7 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
* ans $sTarget will be ignored * 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. * @param array $aIncludeJSFiles An array of file URLs to be included (once) to provide some JS libraries for the page.
*/ */
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = array()) public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = [])
{ {
parent::__construct($sUID, $sLabel); parent::__construct($sUID, $sLabel);
$this->sJsCode = $sJSCode; $this->sJsCode = $sJSCode;
@@ -1077,14 +1076,14 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
public function GetMenuItem() public function GetMenuItem()
{ {
// Note: the semicolumn is a must here! // Note: the semicolumn is a must here!
return array( return [
'label' => $this->GetLabel(), 'label' => $this->GetLabel(),
'onclick' => $this->GetJsCode().'; return false;', 'onclick' => $this->GetJsCode().'; return false;',
'url' => $this->GetUrl(), 'url' => $this->GetUrl(),
'css_classes' => $this->GetCssClasses(), 'css_classes' => $this->GetCssClasses(),
'icon_class' => $this->sIconClass, 'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip 'tooltip' => $this->sTooltip,
); ];
} }
/** @ignore */ /** @ignore */
@@ -1116,7 +1115,7 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
*/ */
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
{ {
static $idx = 0; public static $idx = 0;
/** /**
* Constructor * Constructor
@@ -1130,7 +1129,7 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
/** @ignore */ /** @ignore */
public function GetMenuItem() public function GetMenuItem()
{ {
return array('label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses); return ['label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses];
} }
} }
@@ -1143,7 +1142,6 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
*/ */
class URLButtonItem extends URLPopupMenuItem class URLButtonItem extends URLPopupMenuItem
{ {
} }
/** /**
@@ -1155,7 +1153,6 @@ class URLButtonItem extends URLPopupMenuItem
*/ */
class JSButtonItem extends JSPopupMenuItem class JSButtonItem extends JSPopupMenuItem
{ {
} }
/** /**
@@ -1504,9 +1501,9 @@ interface iBackofficeDictEntriesPrefixesExtension
*/ */
interface iPortalUIExtension interface iPortalUIExtension
{ {
const ENUM_PORTAL_EXT_UI_BODY = 'Body'; public const ENUM_PORTAL_EXT_UI_BODY = 'Body';
const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu'; public const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu';
const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent'; public const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent';
/** /**
* Returns an array of CSS file urls * Returns an array of CSS file urls
@@ -1593,7 +1590,7 @@ abstract class AbstractPortalUIExtension implements iPortalUIExtension
*/ */
public function GetCSSFiles(Container $oContainer) public function GetCSSFiles(Container $oContainer)
{ {
return array(); return [];
} }
/** /**
@@ -1609,7 +1606,7 @@ abstract class AbstractPortalUIExtension implements iPortalUIExtension
*/ */
public function GetJSFiles(Container $oContainer) public function GetJSFiles(Container $oContainer)
{ {
return array(); return [];
} }
/** /**
@@ -1729,62 +1726,62 @@ class RestResult
* Result: no issue has been encountered * Result: no issue has been encountered
* @api * @api
*/ */
const OK = 0; public const OK = 0;
/** /**
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation * Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
* @api * @api
*/ */
const UNAUTHORIZED = 1; public const UNAUTHORIZED = 1;
/** /**
* Result: the parameter 'version' is missing * Result: the parameter 'version' is missing
* @api * @api
*/ */
const MISSING_VERSION = 2; public const MISSING_VERSION = 2;
/** /**
* Result: the parameter 'json_data' is missing * Result: the parameter 'json_data' is missing
* @api * @api
*/ */
const MISSING_JSON = 3; public const MISSING_JSON = 3;
/** /**
* Result: the input structure is not a valid JSON string * Result: the input structure is not a valid JSON string
* @api * @api
*/ */
const INVALID_JSON = 4; public const INVALID_JSON = 4;
/** /**
* Result: the parameter 'auth_user' is missing, authentication aborted * Result: the parameter 'auth_user' is missing, authentication aborted
* @api * @api
*/ */
const MISSING_AUTH_USER = 5; public const MISSING_AUTH_USER = 5;
/** /**
* Result: the parameter 'auth_pwd' is missing, authentication aborted * Result: the parameter 'auth_pwd' is missing, authentication aborted
* @api * @api
*/ */
const MISSING_AUTH_PWD = 6; public const MISSING_AUTH_PWD = 6;
/** /**
* Result: no operation is available for the specified version * Result: no operation is available for the specified version
* @api * @api
*/ */
const UNSUPPORTED_VERSION = 10; public const UNSUPPORTED_VERSION = 10;
/** /**
* Result: the requested operation is not valid for the specified version * Result: the requested operation is not valid for the specified version
* @api * @api
*/ */
const UNKNOWN_OPERATION = 11; public const UNKNOWN_OPERATION = 11;
/** /**
* Result: the requested operation cannot be performed because it can cause data (integrity) loss * Result: the requested operation cannot be performed because it can cause data (integrity) loss
* @api * @api
*/ */
const UNSAFE = 12; public const UNSAFE = 12;
/** /**
* Result: the request page number is not valid. It must be an integer greater than 0 * Result: the request page number is not valid. It must be an integer greater than 0
* @api * @api
*/ */
const INVALID_PAGE = 13; public const INVALID_PAGE = 13;
/** /**
* Result: the operation could not be performed, see the message for troubleshooting * Result: the operation could not be performed, see the message for troubleshooting
* @api * @api
*/ */
const INTERNAL_ERROR = 100; public const INTERNAL_ERROR = 100;
/** /**
* Default constructor - ok! * Default constructor - ok!
@@ -1807,7 +1804,7 @@ class RestResult
* @api * @api
*/ */
public $message; public $message;
/** /**
* Sanitize the content of this result to hide sensitive information * Sanitize the content of this result to hide sensitive information
*/ */
@@ -1854,17 +1851,13 @@ class RestUtils
*/ */
public static function GetMandatoryParam($oData, $sParamName) public static function GetMandatoryParam($oData, $sParamName)
{ {
if (isset($oData->$sParamName)) if (isset($oData->$sParamName)) {
{
return $oData->$sParamName; return $oData->$sParamName;
} } else {
else
{
throw new Exception("Missing parameter '$sParamName'"); throw new Exception("Missing parameter '$sParamName'");
} }
} }
/** /**
* Read an optional parameter from a Rest/Json structure. * Read an optional parameter from a Rest/Json structure.
* *
@@ -1879,17 +1872,13 @@ class RestUtils
*/ */
public static function GetOptionalParam($oData, $sParamName, $default) public static function GetOptionalParam($oData, $sParamName, $default)
{ {
if (isset($oData->$sParamName)) if (isset($oData->$sParamName)) {
{
return $oData->$sParamName; return $oData->$sParamName;
} } else {
else
{
return $default; return $default;
} }
} }
/** /**
* Read a class from a Rest/Json structure. * Read a class from a Rest/Json structure.
* *
@@ -1903,15 +1892,13 @@ class RestUtils
public static function GetClass($oData, $sParamName) public static function GetClass($oData, $sParamName)
{ {
$sClass = self::GetMandatoryParam($oData, $sParamName); $sClass = self::GetMandatoryParam($oData, $sParamName);
if (!MetaModel::IsValidClass($sClass)) if (!MetaModel::IsValidClass($sClass)) {
{
throw new Exception("$sParamName: '$sClass' is not a valid class'"); throw new Exception("$sParamName: '$sClass' is not a valid class'");
} }
return $sClass; return $sClass;
} }
/** /**
* Read a list of attribute codes from a Rest/Json structure. * Read a list of attribute codes from a Rest/Json structure.
* *
@@ -1927,31 +1914,21 @@ class RestUtils
public static function GetFieldList($sClass, $oData, $sParamName) public static function GetFieldList($sClass, $oData, $sParamName)
{ {
$sFields = self::GetOptionalParam($oData, $sParamName, '*'); $sFields = self::GetOptionalParam($oData, $sParamName, '*');
$aShowFields = array(); $aShowFields = [];
if ($sFields == '*') if ($sFields == '*') {
{ foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$aShowFields[$sClass][] = $sAttCode; $aShowFields[$sClass][] = $sAttCode;
} }
} } elseif ($sFields == '*+') {
elseif ($sFields == '*+') foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
{ foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass)
{
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef)
{
$aShowFields[$sRefClass][] = $sAttCode; $aShowFields[$sRefClass][] = $sAttCode;
} }
} }
} } else {
else foreach (explode(',', $sFields) as $sAttCode) {
{
foreach (explode(',', $sFields) as $sAttCode)
{
$sAttCode = trim($sAttCode); $sAttCode = trim($sAttCode);
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
{
throw new Exception("$sParamName: invalid attribute code '$sAttCode'"); throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
} }
$aShowFields[$sClass][] = $sAttCode; $aShowFields[$sClass][] = $sAttCode;
@@ -1974,38 +1951,30 @@ class RestUtils
*/ */
protected static function FindObjectFromCriteria($sClass, $oCriteria) protected static function FindObjectFromCriteria($sClass, $oCriteria)
{ {
$aCriteriaReport = array(); $aCriteriaReport = [];
if (isset($oCriteria->finalclass)) if (isset($oCriteria->finalclass)) {
{ if (!MetaModel::IsValidClass($oCriteria->finalclass)) {
if (!MetaModel::IsValidClass($oCriteria->finalclass))
{
throw new Exception("finalclass: Unknown class '".$oCriteria->finalclass."'"); throw new Exception("finalclass: Unknown class '".$oCriteria->finalclass."'");
} }
if (!MetaModel::IsParentClass($sClass, $oCriteria->finalclass)) if (!MetaModel::IsParentClass($sClass, $oCriteria->finalclass)) {
{
throw new Exception("finalclass: '".$oCriteria->finalclass."' is not a child class of '$sClass'"); throw new Exception("finalclass: '".$oCriteria->finalclass."' is not a child class of '$sClass'");
} }
$sClass = $oCriteria->finalclass; $sClass = $oCriteria->finalclass;
} }
$oSearch = new DBObjectSearch($sClass); $oSearch = new DBObjectSearch($sClass);
foreach ($oCriteria as $sAttCode => $value) foreach ($oCriteria as $sAttCode => $value) {
{
$realValue = static::MakeValue($sClass, $sAttCode, $value); $realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '='); $oSearch->AddCondition($sAttCode, $realValue, '=');
if (is_object($value) || is_array($value)) if (is_object($value) || is_array($value)) {
{
$value = json_encode($value); $value = json_encode($value);
} }
$aCriteriaReport[] = "$sAttCode: $value ($realValue)"; $aCriteriaReport[] = "$sAttCode: $value ($realValue)";
} }
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count(); $iCount = $oSet->Count();
if ($iCount == 0) if ($iCount == 0) {
{
throw new Exception("No item found with criteria: ".implode(', ', $aCriteriaReport)); throw new Exception("No item found with criteria: ".implode(', ', $aCriteriaReport));
} } elseif ($iCount > 1) {
elseif ($iCount > 1)
{
throw new Exception("Several items found ($iCount) with criteria: ".implode(', ', $aCriteriaReport)); throw new Exception("Several items found ($iCount) with criteria: ".implode(', ', $aCriteriaReport));
} }
$res = $oSet->Fetch(); $res = $oSet->Fetch();
@@ -2013,7 +1982,6 @@ class RestUtils
return $res; return $res;
} }
/** /**
* Find an object from a polymorph search specification (Rest/Json) * Find an object from a polymorph search specification (Rest/Json)
* *
@@ -2029,43 +1997,29 @@ class RestUtils
*/ */
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false) public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
{ {
if (is_object($key)) if (is_object($key)) {
{
$res = static::FindObjectFromCriteria($sClass, $key); $res = static::FindObjectFromCriteria($sClass, $key);
} } elseif (is_numeric($key)) {
elseif (is_numeric($key)) if ($bAllowNullValue && ($key == 0)) {
{
if ($bAllowNullValue && ($key == 0))
{
$res = null; $res = null;
} } else {
else
{
$res = MetaModel::GetObject($sClass, $key, false); $res = MetaModel::GetObject($sClass, $key, false);
if (is_null($res)) if (is_null($res)) {
{
throw new Exception("Invalid object $sClass::$key"); throw new Exception("Invalid object $sClass::$key");
} }
} }
} } elseif (is_string($key)) {
elseif (is_string($key))
{
// OQL // OQL
$oSearch = DBObjectSearch::FromOQL($key); $oSearch = DBObjectSearch::FromOQL($key);
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count(); $iCount = $oSet->Count();
if ($iCount == 0) if ($iCount == 0) {
{
throw new Exception("No item found for query: $key"); throw new Exception("No item found for query: $key");
} } elseif ($iCount > 1) {
elseif ($iCount > 1)
{
throw new Exception("Several items found ($iCount) for query: $key"); throw new Exception("Several items found ($iCount) for query: $key");
} }
$res = $oSet->Fetch(); $res = $oSet->Fetch();
} } else {
else
{
throw new Exception("Wrong format for key"); throw new Exception("Wrong format for key");
} }
@@ -2086,47 +2040,37 @@ class RestUtils
*/ */
public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0) public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0)
{ {
if (is_object($key)) if (is_object($key)) {
{ if (isset($key->finalclass)) {
if (isset($key->finalclass))
{
$sClass = $key->finalclass; $sClass = $key->finalclass;
if (!MetaModel::IsValidClass($sClass)) if (!MetaModel::IsValidClass($sClass)) {
{
throw new Exception("finalclass: Unknown class '$sClass'"); throw new Exception("finalclass: Unknown class '$sClass'");
} }
} }
$oSearch = new DBObjectSearch($sClass); $oSearch = new DBObjectSearch($sClass);
foreach ($key as $sAttCode => $value) foreach ($key as $sAttCode => $value) {
{
$realValue = static::MakeValue($sClass, $sAttCode, $value); $realValue = static::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue, '='); $oSearch->AddCondition($sAttCode, $realValue, '=');
} }
} } elseif (is_numeric($key)) {
elseif (is_numeric($key))
{
$oSearch = new DBObjectSearch($sClass); $oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('id', $key); $oSearch->AddCondition('id', $key);
} } elseif (is_string($key)) {
elseif (is_string($key))
{
// OQL // OQL
try { try {
$oSearch = DBObjectSearch::FromOQL($key); $oSearch = DBObjectSearch::FromOQL($key);
} catch (Exception $e) { } catch (Exception $e) {
throw new CoreOqlException('Query failed to execute', [ throw new CoreOqlException('Query failed to execute', [
'query' => $key, 'query' => $key,
'exception_class' => get_class($e), 'exception_class' => get_class($e),
'exception_message' => $e->getMessage(), 'exception_message' => $e->getMessage(),
]); ]);
} }
} } else {
else
{
throw new Exception("Wrong format for key"); throw new Exception("Wrong format for key");
} }
$oObjectSet = new DBObjectSet($oSearch, array(), array(), null, $iLimit, $iOffset); $oObjectSet = new DBObjectSet($oSearch, [], [], null, $iLimit, $iOffset);
return $oObjectSet; return $oObjectSet;
} }
@@ -2144,53 +2088,38 @@ class RestUtils
*/ */
public static function MakeValue($sClass, $sAttCode, $value) public static function MakeValue($sClass, $sAttCode, $value)
{ {
try try {
{ if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
throw new Exception("Unknown attribute"); throw new Exception("Unknown attribute");
} }
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey) if ($oAttDef instanceof AttributeExternalKey) {
{
$oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */); $oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0; $value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
} } elseif ($oAttDef instanceof AttributeLinkedSet) {
elseif ($oAttDef instanceof AttributeLinkedSet) if (!is_array($value)) {
{
if (!is_array($value))
{
throw new Exception("A link set must be defined by an array of objects"); throw new Exception("A link set must be defined by an array of objects");
} }
$sLnkClass = $oAttDef->GetLinkedClass(); $sLnkClass = $oAttDef->GetLinkedClass();
$aLinks = array(); $aLinks = [];
foreach ($value as $oValues) foreach ($value as $oValues) {
{
$oLnk = static::MakeObjectFromFields($sLnkClass, $oValues); $oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
// Fix for N°1939 // Fix for N°1939
if (($oAttDef instanceof AttributeLinkedSetIndirect) && ($oLnk->Get($oAttDef->GetExtKeyToRemote()) == 0)) if (($oAttDef instanceof AttributeLinkedSetIndirect) && ($oLnk->Get($oAttDef->GetExtKeyToRemote()) == 0)) {
{
continue; continue;
} }
$aLinks[] = $oLnk; $aLinks[] = $oLnk;
} }
$value = DBObjectSet::FromArray($sLnkClass, $aLinks); $value = DBObjectSet::FromArray($sLnkClass, $aLinks);
} } elseif ($oAttDef instanceof AttributeTagSet) {
elseif ($oAttDef instanceof AttributeTagSet) if (!is_array($value)) {
{
if (!is_array($value))
{
throw new Exception("A tag set must be defined by an array of tag codes"); throw new Exception("A tag set must be defined by an array of tag codes");
} }
$value = $oAttDef->FromJSONToValue($value); $value = $oAttDef->FromJSONToValue($value);
} } else {
else
{
$value = $oAttDef->FromJSONToValue($value); $value = $oAttDef->FromJSONToValue($value);
} }
} } catch (Exception $e) {
catch (Exception $e)
{
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode()); throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
} }
@@ -2210,15 +2139,11 @@ class RestUtils
public static function MakeObjectFromFields($sClass, $aFields) public static function MakeObjectFromFields($sClass, $aFields)
{ {
$oObject = MetaModel::NewObject($sClass); $oObject = MetaModel::NewObject($sClass);
foreach ($aFields as $sAttCode => $value) foreach ($aFields as $sAttCode => $value) {
{
$realValue = static::MakeValue($sClass, $sAttCode, $value); $realValue = static::MakeValue($sClass, $sAttCode, $value);
try try {
{
$oObject->Set($sAttCode, $realValue); $oObject->Set($sAttCode, $realValue);
} } catch (Exception $e) {
catch (Exception $e)
{
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode()); throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
} }
} }
@@ -2239,15 +2164,11 @@ class RestUtils
public static function UpdateObjectFromFields($oObject, $aFields) public static function UpdateObjectFromFields($oObject, $aFields)
{ {
$sClass = get_class($oObject); $sClass = get_class($oObject);
foreach ($aFields as $sAttCode => $value) foreach ($aFields as $sAttCode => $value) {
{
$realValue = static::MakeValue($sClass, $sAttCode, $value); $realValue = static::MakeValue($sClass, $sAttCode, $value);
try try {
{
$oObject->Set($sAttCode, $realValue); $oObject->Set($sAttCode, $realValue);
} } catch (Exception $e) {
catch (Exception $e)
{
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode()); throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
} }
} }
@@ -2256,7 +2177,6 @@ class RestUtils
} }
} }
/** /**
* Helpers for modules extensibility, with discover performed by the MetaModel. * Helpers for modules extensibility, with discover performed by the MetaModel.
* *
@@ -2279,21 +2199,21 @@ interface iModuleExtension
*/ */
interface iKPILoggerExtension interface iKPILoggerExtension
{ {
/** /**
* Init the statistics collected * Init the statistics collected
* *
* @return void * @return void
*/ */
public function InitStats(); public function InitStats();
/** /**
* Add a new KPI to the stats * Add a new KPI to the stats
* *
* @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData * @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData
* *
* @return mixed * @return mixed
*/ */
public function LogOperation($oKpiLogData); public function LogOperation($oKpiLogData);
} }
/** /**
@@ -2311,7 +2231,6 @@ interface iBackupExtraFilesExtension
public function GetExtraFilesRelPaths(): array; public function GetExtraFilesRelPaths(): array;
} }
/** /**
* Interface to provide messages to be displayed in the "Welcome Popup" * Interface to provide messages to be displayed in the "Welcome Popup"
* *
@@ -2372,7 +2291,7 @@ abstract class AbstractWelcomePopupExtension implements iWelcomePopupExtension
{ {
return []; return [];
} }
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -2381,4 +2300,4 @@ abstract class AbstractWelcomePopupExtension implements iWelcomePopupExtension
// No need to process the acknowledgment notice by default // No need to process the acknowledgment notice by default
return; return;
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* This class manages the audit "categories". Each category defines a set of objects * This class manages the audit "categories". Each category defines a set of objects
* to check and is linked to a set of rules that determine the valid or invalid objects * to check and is linked to a set of rules that determine the valid or invalid objects
@@ -32,34 +32,36 @@ class AuditCategory extends cmdbAbstractObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "application,grant_by_profile", "category" => "application,grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array('name'), "reconc_keys" => ['name'],
"db_table" => "priv_auditcategory", "db_table" => "priv_auditcategory",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-folder.svg'), 'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-folder.svg'),
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("description"=>"Short name for this category", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
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 AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", array("allowed_values"=>null, "sql"=>"definition_set", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", ["allowed_values" => null, "sql" => "definition_set", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", array("linked_class"=>"AuditRule", "ext_key_to_me"=>"category_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array(), "edit_mode" => LINKSET_EDITMODE_INPLACE, "tracking_level" => LINKSET_TRACKING_ALL))); MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", ["linked_class" => "AuditRule", "ext_key_to_me" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "edit_mode" => LINKSET_EDITMODE_INPLACE, "tracking_level" => LINKSET_TRACKING_ALL]));
MetaModel::Init_AddAttribute(new AttributeInteger("ok_error_tolerance", array("allowed_values"=>null, "sql"=>"ok_error_tolerance", "default_value"=>5, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("ok_error_tolerance", ["allowed_values" => null, "sql" => "ok_error_tolerance", "default_value" => 5, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("warning_error_tolerance", array("allowed_values" => null, "sql" => "warning_error_tolerance", "default_value" => 25, "is_null_allowed" => true, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeInteger("warning_error_tolerance", ["allowed_values" => null, "sql" => "warning_error_tolerance", "default_value" => 25, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("domains_list", MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
array("linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "category_id", "ext_key_to_remote" => "domain_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => array(), "display_style" => 'property'))); "domains_list",
["linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "category_id", "ext_key_to_remote" => "domain_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "display_style" => 'property']
));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'definition_set', 'ok_error_tolerance', 'warning_error_tolerance', 'rules_list', 'domains_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['name', 'description', 'definition_set', 'ok_error_tolerance', 'warning_error_tolerance', 'rules_list', 'domains_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('list', ['description', ]); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'definition_set')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['description', 'definition_set']); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
} }
/** /**
@@ -74,9 +76,9 @@ class AuditCategory extends cmdbAbstractObject
public function GetReportColor($iTotal, $iErrors) public function GetReportColor($iTotal, $iErrors)
{ {
$sResult = 'red'; $sResult = 'red';
if ( ($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100) ) { if (($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100)) {
$sResult = 'green'; $sResult = 'green';
} else if (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) { } elseif (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) {
$sResult = 'orange'; $sResult = 'orange';
} }
@@ -93,4 +95,3 @@ class AuditCategory extends cmdbAbstractObject
return $aShortcutActions; return $aShortcutActions;
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* This class manages the audit "categories". Each category defines a set of objects * This class manages the audit "categories". Each category defines a set of objects
* to check and is linked to a set of rules that determine the valid or invalid objects * to check and is linked to a set of rules that determine the valid or invalid objects
@@ -33,32 +33,34 @@ class AuditDomain extends cmdbAbstractObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "application,grant_by_profile", "category" => "application,grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"complementary_name_attcode" => array('description'), "complementary_name_attcode" => ['description'],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array('name'), "reconc_keys" => ['name'],
"db_table" => "priv_auditdomain", "db_table" => "priv_auditdomain",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-album.svg'), 'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-album.svg'),
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
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 AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeImage("icon", array("is_null_allowed" => true, "depends_on" => array(), "display_max_width" => 96, "display_max_height" => 96, "storage_max_width" => 256, "storage_max_height" => 256, "default_image" => null, "always_load_in_tables" => false))); MetaModel::Init_AddAttribute(new AttributeImage("icon", ["is_null_allowed" => true, "depends_on" => [], "display_max_width" => 96, "display_max_height" => 96, "storage_max_width" => 256, "storage_max_height" => 256, "default_image" => null, "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("categories_list", MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
array("linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "domain_id", "ext_key_to_remote" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => array()))); "categories_list",
["linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "domain_id", "ext_key_to_remote" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => []]
));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'icon', 'categories_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['name', 'description', 'icon', 'categories_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('list', ['description',]); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['description']); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
} }
public static function GetShortcutActions($sFinalClass) public static function GetShortcutActions($sFinalClass)
@@ -84,40 +86,39 @@ class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "application,grant_by_profile", "category" => "application,grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "", "name_attcode" => "",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array('category_id', 'domain_id'), "reconc_keys" => ['category_id', 'domain_id'],
"db_table" => "priv_link_audit_category_domain", "db_table" => "priv_link_audit_category_domain",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
"is_link" => true, "is_link" => true,
'uniqueness_rules' => array( 'uniqueness_rules' => [
'no_duplicate' => array( 'no_duplicate' => [
'attributes' => array( 'attributes' => [
0 => 'category_id', 0 => 'category_id',
1 => 'domain_id', 1 => 'domain_id',
), ],
'filter' => '', 'filter' => '',
'disabled' => false, 'disabled' => false,
'is_blocking' => true, 'is_blocking' => true,
), ],
), ],
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", array("targetclass" => "AuditCategory", "jointype" => '', "allowed_values" => null, "sql" => "category_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["targetclass" => "AuditCategory", "jointype" => '', "allowed_values" => null, "sql" => "category_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", array("allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"))); MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("domain_id", array("targetclass" => "AuditDomain", "jointype" => '', "allowed_values" => null, "sql" => "domain_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("domain_id", ["targetclass" => "AuditDomain", "jointype" => '', "allowed_values" => null, "sql" => "domain_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("domain_name", array("allowed_values" => null, "extkey_attcode" => 'domain_id', "target_attcode" => "name"))); MetaModel::Init_AddAttribute(new AttributeExternalField("domain_name", ["allowed_values" => null, "extkey_attcode" => 'domain_id', "target_attcode" => "name"]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('category_id', 'domain_id')); MetaModel::Init_SetZListItems('details', ['category_id', 'domain_id']);
MetaModel::Init_SetZListItems('list', array('category_id', 'domain_id')); MetaModel::Init_SetZListItems('list', ['category_id', 'domain_id']);
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'domain_id')); MetaModel::Init_SetZListItems('standard_search', ['category_id', 'domain_id']);
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* This class manages the audit "rule" linked to a given audit category. * This class manages the audit "rule" linked to a given audit category.
* Each rule is based on an OQL expression that returns either the "good" objects * Each rule is based on an OQL expression that returns either the "good" objects
@@ -33,35 +33,34 @@ class AuditRule extends cmdbAbstractObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "application,grant_by_profile", "category" => "application,grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array('name'), "reconc_keys" => ['name'],
"db_table" => "priv_auditrule", "db_table" => "priv_auditrule",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit.svg'), 'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit.svg'),
); ];
MetaModel::Init_Params($aParams); 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("name", ["allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
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 AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeOQL("query", array("allowed_values" => null, "sql" => "query", "default_value" => "", "is_null_allowed" => false, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeOQL("query", ["allowed_values" => null, "sql" => "query", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", array("allowed_values" => new ValueSetEnum('true,false'), "sql" => "valid_flag", "default_value" => "true", "is_null_allowed" => false, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", ["allowed_values" => new ValueSetEnum('true,false'), "sql" => "valid_flag", "default_value" => "true", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", array("allowed_values" => null, "sql" => "category_id", "targetclass" => "AuditCategory", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["allowed_values" => null, "sql" => "category_id", "targetclass" => "AuditCategory", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", array("allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"))); MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('category_id', 'name', 'description', 'query', 'valid_flag')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('category_id', 'description', 'valid_flag')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'valid_flag']); // Attributes to be displayed for a list
// Search criteria // Search criteria
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'name', 'description', 'valid_flag', 'query')); // Criteria of the std search form MetaModel::Init_SetZListItems('standard_search', ['category_id', 'name', 'description', 'valid_flag', 'query']); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'category_id')); // Criteria of the advanced search form MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'category_id']); // Criteria of the advanced search form
} }
public static function GetShortcutActions($sFinalClass) public static function GetShortcutActions($sFinalClass)
{ {
$aShortcutActions = parent::GetShortcutActions($sFinalClass); $aShortcutActions = parent::GetShortcutActions($sFinalClass);
@@ -72,4 +71,3 @@ class AuditRule extends cmdbAbstractObject
return $aShortcutActions; return $aShortcutActions;
} }
} }
?>

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader');

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -32,7 +33,8 @@ class CompileCSSService
{ {
} }
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){ public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = [])
{
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables); return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
} }
} }

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader');

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -53,7 +54,7 @@ abstract class Dashboard
$this->sLayoutClass = 'DashboardLayoutOneCol'; $this->sLayoutClass = 'DashboardLayoutOneCol';
$this->bAutoReload = false; $this->bAutoReload = false;
$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval(); $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
$this->aCells = array(); $this->aCells = [];
$this->oDOMNode = null; $this->oDOMNode = null;
$this->sId = $sId; $this->sId = $sId;
} }
@@ -65,8 +66,8 @@ abstract class Dashboard
*/ */
public function FromXml($sXml) public function FromXml($sXml)
{ {
$this->aCells = array(); // reset the content of the dashboard $this->aCells = []; // reset the content of the dashboard
set_error_handler(array('Dashboard', 'ErrorHandler')); set_error_handler(['Dashboard', 'ErrorHandler']);
$oDoc = new DOMDocument(); $oDoc = new DOMDocument();
$oDoc->loadXML($sXml); $oDoc->loadXML($sXml);
restore_error_handler(); restore_error_handler();
@@ -79,87 +80,69 @@ abstract class Dashboard
public function FromDOMDocument(DOMDocument $oDoc) public function FromDOMDocument(DOMDocument $oDoc)
{ {
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0); $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; $this->sLayoutClass = $oLayoutNode->textContent;
} } else {
else
{
$this->sLayoutClass = 'DashboardLayoutOneCol'; $this->sLayoutClass = 'DashboardLayoutOneCol';
} }
if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0)) if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0)) {
{
$this->sTitle = $oTitleNode->textContent; $this->sTitle = $oTitleNode->textContent;
} } else {
else
{
$this->sTitle = ''; $this->sTitle = '';
} }
$this->bAutoReload = false; $this->bAutoReload = false;
$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval(); $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0)) if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0)) {
{ if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0)) {
if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0))
{
$this->bAutoReload = ($oAutoReloadEnabled->textContent == 'true'); $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); $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'); $oCellsList = $oCellsNode->getElementsByTagName('cell');
$aCellOrder = array(); $aCellOrder = [];
$iCellRank = 0; $iCellRank = 0;
/** @var \DOMElement $oCellNode */ /** @var \DOMElement $oCellNode */
foreach($oCellsList as $oCellNode) foreach ($oCellsList as $oCellNode) {
{
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0); $oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
if ($oCellRank) if ($oCellRank) {
{
$iCellRank = (float)$oCellRank->textContent; $iCellRank = (float)$oCellRank->textContent;
} }
$oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0); $oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0);
{ {
$oDashletList = $oDashletsNode->getElementsByTagName('dashlet'); $oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
$iRank = 0; $iRank = 0;
$aDashletOrder = array(); $aDashletOrder = [];
/** @var \DOMElement $oDomNode */ /** @var \DOMElement $oDomNode */
foreach($oDashletList as $oDomNode) foreach ($oDashletList as $oDomNode) {
{
$oRank = $oDomNode->getElementsByTagName('rank')->item(0); $oRank = $oDomNode->getElementsByTagName('rank')->item(0);
if ($oRank) if ($oRank) {
{
$iRank = (float)$oRank->textContent; $iRank = (float)$oRank->textContent;
} }
$oNewDashlet = $this->InitDashletFromDOMNode($oDomNode); $oNewDashlet = $this->InitDashletFromDOMNode($oDomNode);
$aDashletOrder[] = array('rank' => $iRank, 'dashlet' => $oNewDashlet); $aDashletOrder[] = ['rank' => $iRank, 'dashlet' => $oNewDashlet];
} }
usort($aDashletOrder, array(get_class($this), 'SortOnRank')); usort($aDashletOrder, [get_class($this), 'SortOnRank']);
$aDashletList = array(); $aDashletList = [];
foreach($aDashletOrder as $aItem) foreach ($aDashletOrder as $aItem) {
{
$aDashletList[] = $aItem['dashlet']; $aDashletList[] = $aItem['dashlet'];
} }
$aCellOrder[] = array('rank' => $iCellRank, 'dashlets' => $aDashletList); $aCellOrder[] = ['rank' => $iCellRank, 'dashlets' => $aDashletList];
} }
} }
usort($aCellOrder, array(get_class($this), 'SortOnRank')); usort($aCellOrder, [get_class($this), 'SortOnRank']);
foreach($aCellOrder as $aItem) foreach ($aCellOrder as $aItem) {
{
$this->aCells[] = $aItem['dashlets']; $this->aCells[] = $aItem['dashlets'];
} }
} } else {
else $this->aCells = [];
{
$this->aCells = array();
} }
} }
@@ -169,20 +152,20 @@ abstract class Dashboard
* @return mixed * @return mixed
*/ */
protected function InitDashletFromDOMNode($oDomNode) 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 // Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
$sClass = static::GetDashletClassFromType($sDashletType); $sClass = static::GetDashletClassFromType($sDashletType);
/** @var \Dashlet $oNewDashlet */ /** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sClass($this->oMetaModel, $sId); $oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet->SetDashletType($sDashletType); $oNewDashlet->SetDashletType($sDashletType);
$oNewDashlet->FromDOMNode($oDomNode); $oNewDashlet->FromDOMNode($oDomNode);
return $oNewDashlet; return $oNewDashlet;
} }
/** /**
* @param array $aItem1 * @param array $aItem1
@@ -208,12 +191,9 @@ abstract class Dashboard
*/ */
public static function ErrorHandler($errno, $errstr, $errfile, $errline) 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); throw new DOMException($errstr);
} } else {
else
{
return false; return false;
} }
} }
@@ -231,7 +211,7 @@ abstract class Dashboard
$oMainNode = $oDoc->createElement('dashboard'); $oMainNode = $oDoc->createElement('dashboard');
$oMainNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance"); $oMainNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
$oDoc->appendChild($oMainNode); $oDoc->appendChild($oMainNode);
$this->ToDOMNode($oMainNode); $this->ToDOMNode($oMainNode);
$sXml = $oDoc->saveXML(); $sXml = $oDoc->saveXML();
@@ -261,23 +241,21 @@ abstract class Dashboard
$oCellsNode = $oDoc->createElement('cells'); $oCellsNode = $oDoc->createElement('cells');
$oDefinition->appendChild($oCellsNode); $oDefinition->appendChild($oCellsNode);
$iCellRank = 0; $iCellRank = 0;
foreach ($this->aCells as $aCell) foreach ($this->aCells as $aCell) {
{
$oCellNode = $oDoc->createElement('cell'); $oCellNode = $oDoc->createElement('cell');
$oCellNode->setAttribute('id', $iCellRank); $oCellNode->setAttribute('id', $iCellRank);
$oCellsNode->appendChild($oCellNode); $oCellsNode->appendChild($oCellNode);
$oCellRank = $oDoc->createElement('rank', $iCellRank); $oCellRank = $oDoc->createElement('rank', $iCellRank);
$oCellNode->appendChild($oCellRank); $oCellNode->appendChild($oCellRank);
$iCellRank++; $iCellRank++;
$iDashletRank = 0; $iDashletRank = 0;
$oDashletsNode = $oDoc->createElement('dashlets'); $oDashletsNode = $oDoc->createElement('dashlets');
$oCellNode->appendChild($oDashletsNode); $oCellNode->appendChild($oDashletsNode);
/** @var \Dashlet $oDashlet */ /** @var \Dashlet $oDashlet */
foreach ($aCell as $oDashlet) foreach ($aCell as $oDashlet) {
{
$oNode = $oDoc->createElement('dashlet'); $oNode = $oDoc->createElement('dashlet');
$oDashletsNode->appendChild($oNode); $oDashletsNode->appendChild($oNode);
$oNode->setAttribute('id', $oDashlet->GetID()); $oNode->setAttribute('id', $oDashlet->GetID());
@@ -299,18 +277,15 @@ abstract class Dashboard
$this->sTitle = $aParams['title']; $this->sTitle = $aParams['title'];
$this->bAutoReload = $aParams['auto_reload'] == 'true'; $this->bAutoReload = $aParams['auto_reload'] == 'true';
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']); $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']);
foreach($aParams['cells'] as $aCell) foreach ($aParams['cells'] as $aCell) {
{ $aCellDashlets = [];
$aCellDashlets = array(); foreach ($aCell as $aDashletParams) {
foreach($aCell as $aDashletParams)
{
$sDashletClass = $aDashletParams['dashlet_class']; $sDashletClass = $aDashletParams['dashlet_class'];
$sId = $aDashletParams['dashlet_id']; $sId = $aDashletParams['dashlet_id'];
/** @var \Dashlet $oNewDashlet */ /** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sDashletClass($this->oMetaModel, $sId); $oNewDashlet = new $sDashletClass($this->oMetaModel, $sId);
if (isset($aDashletParams['dashlet_type'])) if (isset($aDashletParams['dashlet_type'])) {
{
$oNewDashlet->SetDashletType($aDashletParams['dashlet_type']); $oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
} }
$oForm = $oNewDashlet->GetForm(); $oForm = $oNewDashlet->GetForm();
@@ -322,12 +297,12 @@ abstract class Dashboard
} }
$this->aCells[] = $aCellDashlets; $this->aCells[] = $aCellDashlets;
} }
} }
public function Save() public function Save()
{ {
} }
/** /**
@@ -420,7 +395,7 @@ abstract class Dashboard
{ {
$sId = $this->GetNewDashletId(); $sId = $this->GetNewDashletId();
$oDashlet->SetId($sId); $oDashlet->SetId($sId);
$this->aCells[] = array($oDashlet); $this->aCells[] = [$oDashlet];
} }
/** /**
@@ -430,7 +405,7 @@ abstract class Dashboard
* @throws \ReflectionException * @throws \ReflectionException
* @throws \Exception * @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 // 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>'); $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 +417,7 @@ abstract class Dashboard
if (is_subclass_of($sLayoutClass, 'DashboardLayout')) { if (is_subclass_of($sLayoutClass, 'DashboardLayout')) {
$oReflection = new ReflectionClass($sLayoutClass); $oReflection = new ReflectionClass($sLayoutClass);
if (!$oReflection->isAbstract()) { if (!$oReflection->isAbstract()) {
$aCallSpec = array($sLayoutClass, 'GetInfo'); $aCallSpec = [$sLayoutClass, 'GetInfo'];
$aInfo = call_user_func($aCallSpec); $aInfo = call_user_func($aCallSpec);
$sChecked = ($this->sLayoutClass == $sLayoutClass) ? 'checked' : ''; $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 ! $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 +441,6 @@ abstract class Dashboard
$oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit $oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit
$oForm->AddField($oField); $oForm->AddField($oField);
$this->SetFormParams($oForm, $aExtraParams); $this->SetFormParams($oForm, $aExtraParams);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard'); $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
@@ -474,7 +448,7 @@ abstract class Dashboard
$sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval'))); $sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval')));
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
// Note: the title gets deleted by the validation mechanism // Note: the title gets deleted by the validation mechanism
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle'); $("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec")); CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
@@ -522,7 +496,7 @@ EOF
* *
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout * @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); $aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
@@ -551,7 +525,8 @@ EOF
$oToolbar->AddHtml($sHtml); $oToolbar->AddHtml($sHtml);
} else { } else {
$oPage->add_script(<<<JS $oPage->add_script(
<<<JS
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML").attr("title", $('<div>').html("$sTitleForHTML").text()); $(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML").attr("title", $('<div>').html("$sTitleForHTML").text());
JS JS
); );
@@ -595,7 +570,7 @@ JS
* @param WebPage $oPage * @param WebPage $oPage
* @param array $aExtraParams * @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 // 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>'); $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 +579,10 @@ JS
$oLayout = new $this->sLayoutClass(); $oLayout = new $this->sLayoutClass();
$oPage->add('<div id="dashlet_properties">'); $oPage->add('<div id="dashlet_properties">');
foreach($this->aCells as $iCellIdx => $aCell) foreach ($this->aCells as $iCellIdx => $aCell) {
{
/** @var \Dashlet $oDashlet */ /** @var \Dashlet $oDashlet */
foreach($aCell as $oDashlet) foreach ($aCell as $oDashlet) {
{ if ($oDashlet->IsVisible()) {
if ($oDashlet->IsVisible())
{
$oPage->add('<div class="dashlet_properties" id="dashlet_properties_'.$oDashlet->GetID().'" style="display:none">'); $oPage->add('<div class="dashlet_properties" id="dashlet_properties_'.$oDashlet->GetID().'" style="display:none">');
$oForm = $oDashlet->GetForm(); $oForm = $oDashlet->GetForm();
$this->SetFormParams($oForm, $aExtraParams); $this->SetFormParams($oForm, $aExtraParams);
@@ -632,18 +604,17 @@ JS
*/ */
protected function GetAvailableDashlets() 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. // 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); $oReflection = new ReflectionClass($sDashletClass);
if (!$oReflection->isAbstract()) { if (!$oReflection->isAbstract()) {
$aCallSpec = array($sDashletClass, 'IsVisible'); $aCallSpec = [$sDashletClass, 'IsVisible'];
$bVisible = call_user_func($aCallSpec); $bVisible = call_user_func($aCallSpec);
if ($bVisible) { if ($bVisible) {
$aCallSpec = array($sDashletClass, 'GetInfo'); $aCallSpec = [$sDashletClass, 'GetInfo'];
$aInfo = call_user_func($aCallSpec); $aInfo = call_user_func($aCallSpec);
$aDashlets[$sDashletClass] = $aInfo; $aDashlets[$sDashletClass] = $aInfo;
} }
@@ -660,11 +631,9 @@ JS
protected function GetNewDashletId() protected function GetNewDashletId()
{ {
$iNewId = 0; $iNewId = 0;
foreach($this->aCells as $aDashlets) foreach ($this->aCells as $aDashlets) {
{
/** @var \Dashlet $oDashlet */ /** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet) foreach ($aDashlets as $oDashlet) {
{
$iNewId = max($iNewId, (int)$oDashlet->GetID()); $iNewId = max($iNewId, (int)$oDashlet->GetID());
} }
} }
@@ -681,15 +650,15 @@ JS
* *
* @return void * @return void
*/ */
abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = array()); abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = []);
/** /**
* @param \DesignerForm $oForm * @param \DesignerForm $oForm
* @param array $aExtraParams * @param array $aExtraParams
* *
* @return mixed * @return mixed
*/ */
abstract protected function SetFormParams($oForm, $aExtraParams = array()); abstract protected function SetFormParams($oForm, $aExtraParams = []);
/** /**
* @param string $sType * @param string $sType
@@ -699,8 +668,7 @@ JS
*/ */
public static function GetDashletClassFromType($sType, $oFactory = null) public static function GetDashletClassFromType($sType, $oFactory = null)
{ {
if (is_subclass_of($sType, 'Dashlet')) if (is_subclass_of($sType, 'Dashlet')) {
{
return $sType; return $sType;
} }
return 'DashletUnknown'; return 'DashletUnknown';
@@ -723,14 +691,12 @@ JS
*/ */
public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletOrigId) public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletOrigId)
{ {
if(strpos($sDashletOrigId, '_ID_row') !== false) if (strpos($sDashletOrigId, '_ID_row') !== false) {
{
return $sDashletOrigId; return $sDashletOrigId;
} }
$sDashletId = $sDashboardDivId."_ID_row".$iRow."_col".$iCol."_".$sDashletOrigId; $sDashletId = $sDashboardDivId."_ID_row".$iRow."_col".$iCol."_".$sDashletOrigId;
if ($bIsCustomized) if ($bIsCustomized) {
{
$sDashletId = 'CUSTOM_'.$sDashletId; $sDashletId = 'CUSTOM_'.$sDashletId;
} }
@@ -782,9 +748,9 @@ class RuntimeDashboard extends Dashboard
* @inheritDoc * @inheritDoc
* @throws \Exception * @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 +766,11 @@ class RuntimeDashboard extends Dashboard
$oUDSearch->AddCondition('menu_code', $this->sId, '='); $oUDSearch->AddCondition('menu_code', $this->sId, '=');
$oUDSet = new DBObjectSet($oUDSearch); $oUDSet = new DBObjectSet($oUDSearch);
$bIsNew = false; $bIsNew = false;
if ($oUDSet->Count() > 0) if ($oUDSet->Count() > 0) {
{
// Assuming there is at most one couple {user, menu}! // Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch(); $oUserDashboard = $oUDSet->Fetch();
$oUserDashboard->Set('contents', $sXml); $oUserDashboard->Set('contents', $sXml);
} } else {
else
{
// No such customized dashboard for the current user, let's create a new record // No such customized dashboard for the current user, let's create a new record
$oUserDashboard = new UserDashboard(); $oUserDashboard = new UserDashboard();
$oUserDashboard->Set('user_id', UserRights::GetUserId()); $oUserDashboard->Set('user_id', UserRights::GetUserId());
@@ -838,8 +801,7 @@ class RuntimeDashboard extends Dashboard
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->sId, '='); $oUDSearch->AddCondition('menu_code', $this->sId, '=');
$oUDSet = new DBObjectSet($oUDSearch); $oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0) if ($oUDSet->Count() > 0) {
{
// Assuming there is at most one couple {user, menu}! // Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch(); $oUserDashboard = $oUDSet->Fetch();
utils::PushArchiveMode(false); utils::PushArchiveMode(false);
@@ -883,14 +845,11 @@ class RuntimeDashboard extends Dashboard
} else { } else {
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized); $sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
} }
} } else {
else
{
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized); $sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
} }
if ($sDashboardDefinition !== false) if ($sDashboardDefinition !== false) {
{
$oDashboard = new RuntimeDashboard($sDashBoardId); $oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition); $oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized); $oDashboard->SetCustomFlag($bCustomized);
@@ -937,7 +896,6 @@ class RuntimeDashboard extends Dashboard
$sDashboardDefinition = @file_get_contents($sDashboardFileSanitized); $sDashboardDefinition = @file_get_contents($sDashboardFileSanitized);
} }
if ($sDashboardDefinition !== false) { if ($sDashboardDefinition !== false) {
$oDashboard = new RuntimeDashboard($sDashBoardId); $oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition); $oDashboard->FromXml($sDashboardDefinition);
@@ -954,11 +912,11 @@ class RuntimeDashboard extends Dashboard
* @inheritDoc * @inheritDoc
* @throws \Exception * @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'])) { if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class'])) {
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']); $oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery()); $aRenderParams = ['query_params' => $oObj->ToArgsForQuery()];
} else { } else {
$aRenderParams = $aExtraParams; $aRenderParams = $aExtraParams;
} }
@@ -968,7 +926,7 @@ class RuntimeDashboard extends Dashboard
if (isset($aExtraParams['query_params']['this->object()'])) { if (isset($aExtraParams['query_params']['this->object()'])) {
/** @var \DBObject $oObj */ /** @var \DBObject $oObj */
$oObj = $aExtraParams['query_params']['this->object()']; $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'])) { if (isset($aExtraParams['from_dashboard_page'])) {
$aAjaxParams['from_dashboard_page'] = $aExtraParams['from_dashboard_page']; $aAjaxParams['from_dashboard_page'] = $aExtraParams['from_dashboard_page'];
} }
@@ -1001,9 +959,7 @@ class RuntimeDashboard extends Dashboard
} }
JS JS
); );
} } else {
else
{
$oPage->add_script( $oPage->add_script(
<<<EOF <<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined') if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
@@ -1032,7 +988,7 @@ EOF
* @throws \CoreUnexpectedValue * @throws \CoreUnexpectedValue
* @throws \MySQLException * @throws \MySQLException
*/ */
protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = array()) protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = [])
{ {
if (!$this->HasCustomDashboard()) { if (!$this->HasCustomDashboard()) {
return; return;
@@ -1092,8 +1048,7 @@ JS
*/ */
protected function HasCustomDashboard() protected function HasCustomDashboard()
{ {
try try {
{
// Search for an eventual user defined dashboard // Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard'); $oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
@@ -1101,9 +1056,7 @@ JS
$oUDSet = new DBObjectSet($oUDSearch); $oUDSet = new DBObjectSet($oUDSearch);
return ($oUDSet->Count() > 0); return ($oUDSet->Count() > 0);
} } catch (Exception $e) {
catch (Exception $e)
{
return false; return false;
} }
} }
@@ -1139,21 +1092,23 @@ JS
->AddCSSClass('ibo-action-button'); ->AddCSSClass('ibo-action-button');
$oToolbar->AddSubBlock($oActionButton); $oToolbar->AddSubBlock($oActionButton);
$aActions = array(); $aActions = [];
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile)); $sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
$sJSExtraParams = json_encode($aExtraParams); $sJSExtraParams = json_encode($aExtraParams);
if ($this->HasCustomDashboard()) { if ($this->HasCustomDashboard()) {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)"); $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem(); $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:DeleteCustom'), $oRevert = new JSPopupMenuItem(
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false"); '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(); $aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
} else { } else {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)"); $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem(); $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
} }
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions); utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
$oActionsMenu = $oPage->GetPopoverMenu($sPopoverMenuId, $aActions) $oActionsMenu = $oPage->GetPopoverMenu($sPopoverMenuId, $aActions)
@@ -1193,12 +1148,12 @@ EOF
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function RenderProperties($oPage, $aExtraParams = array()) public function RenderProperties($oPage, $aExtraParams = [])
{ {
parent::RenderProperties($oPage, $aExtraParams); parent::RenderProperties($oPage, $aExtraParams);
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
$('#select_layout input').on('click', function() { $('#select_layout input').on('click', function() {
var sLayoutClass = $(this).val(); var sLayoutClass = $(this).val();
$('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass}); $('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass});
@@ -1225,7 +1180,6 @@ EOF
); );
} }
/** /**
* @param WebPage $oPage * @param WebPage $oPage
* *
@@ -1236,11 +1190,11 @@ EOF
* @throws \ReflectionException * @throws \ReflectionException
* @throws \Exception * @throws \Exception
*/ */
public function RenderEditor($oPage, $aExtraParams = array()) public function RenderEditor($oPage, $aExtraParams = [])
{ {
if (isset($aExtraParams['this->class'])) { if (isset($aExtraParams['this->class'])) {
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']); $oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery()); $aRenderParams = ['query_params' => $oObj->ToArgsForQuery()];
} else { } else {
$aRenderParams = $aExtraParams; $aRenderParams = $aExtraParams;
} }
@@ -1262,7 +1216,7 @@ EOF
$sDialogTitle = Dict::S('UI:DashboardEdit:Title'); $sDialogTitle = Dict::S('UI:DashboardEdit:Title');
$sOkButtonLabel = Dict::S('UI:Button:Save'); $sOkButtonLabel = Dict::S('UI:Button:Save');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$sId = json_encode($this->sId); $sId = json_encode($this->sId);
$sLayoutClass = json_encode($this->sLayoutClass); $sLayoutClass = json_encode($this->sLayoutClass);
$sAutoReload = $this->bAutoReload ? 'true' : 'false'; $sAutoReload = $this->bAutoReload ? 'true' : 'false';
@@ -1275,9 +1229,9 @@ EOF
$sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage')); $sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage'));
$sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage')); $sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage'));
$sAutoApplyConfirmationMessage = addslashes(Dict::S('UI:AutoApplyConfirmationMessage')); $sAutoApplyConfirmationMessage = addslashes(Dict::S('UI:AutoApplyConfirmationMessage'));
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
window.bLeavingOnUserAction = false; window.bLeavingOnUserAction = false;
$('#dashboard_editor').dialog({ $('#dashboard_editor').dialog({
@@ -1385,104 +1339,89 @@ JS
$sContextMenuId = $oAppContext->GetCurrentValue('menu', null); $sContextMenuId = $oAppContext->GetCurrentValue('menu', null);
$oForm = new DesignerForm(); $oForm = new DesignerForm();
// Get the list of all 'dashboard' menus in which we can insert a dashlet // Get the list of all 'dashboard' menus in which we can insert a dashlet
$aAllMenus = ApplicationMenu::ReflectionMenuNodes(); $aAllMenus = ApplicationMenu::ReflectionMenuNodes();
$sRootMenuId = ApplicationMenu::GetRootMenuId($sContextMenuId); $sRootMenuId = ApplicationMenu::GetRootMenuId($sContextMenuId);
$aAllowedDashboards = array(); $aAllowedDashboards = [];
$sDefaultDashboard = null; $sDefaultDashboard = null;
// Store the parent menus for acces check // Store the parent menus for acces check
$aParentMenus = array(); $aParentMenus = [];
foreach($aAllMenus as $idx => $aMenu) foreach ($aAllMenus as $idx => $aMenu) {
{ /** @var MenuNode $oMenu */
/** @var MenuNode $oMenu */
$oMenu = $aMenu['node'];
if (count(ApplicationMenu::GetChildren($oMenu->GetIndex())) > 0)
{
$aParentMenus[$oMenu->GetMenuId()] = $aMenu;
}
}
foreach($aAllMenus as $idx => $aMenu)
{
$oMenu = $aMenu['node']; $oMenu = $aMenu['node'];
if ($oMenu instanceof DashboardMenuNode) if (count(ApplicationMenu::GetChildren($oMenu->GetIndex())) > 0) {
{ $aParentMenus[$oMenu->GetMenuId()] = $aMenu;
// 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);
foreach ($aAllMenus as $idx => $aMenu) {
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard); $oMenu = $aMenu['node'];
$oField->SetAllowedValues($aAllowedDashboards); if ($oMenu instanceof DashboardMenuNode) {
$oField->SetMandatory(true); // Get the root parent for access check
$oForm->AddField($oField); $sParentId = $aMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
// Get the list of possible dashlets that support a creation from while (isset($aParentMenus[$aParentMenu['parent']])) {
// an OQL // grand parent exists
$aDashlets = array(); $sParentId = $aParentMenu['parent'];
foreach(get_declared_classes() as $sDashletClass) $aParentMenu = $aParentMenus[$sParentId];
{ }
if (is_subclass_of($sDashletClass, 'Dashlet')) /** @var \MenuNode $oParentMenu */
{ $oParentMenu = $aParentMenu['node'];
$oReflection = new ReflectionClass($sDashletClass); if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled()) {
if (!$oReflection->isAbstract()) $sMenuLabel = $oMenu->GetTitle();
{ $sParentLabel = Dict::S('Menu:'.$sParentId);
$aCallSpec = array($sDashletClass, 'CanCreateFromOQL'); if ($sParentLabel != $sMenuLabel) {
$bShorcutMode = call_user_func($aCallSpec); $aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
if ($bShorcutMode) } else {
{ $aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
$aCallSpec = array($sDashletClass, 'GetInfo'); }
$aInfo = call_user_func($aCallSpec); if (empty($sDefaultDashboard) && ($sRootMenuId == ApplicationMenu::GetRootMenuId($oMenu->GetMenuId()))) {
$aDashlets[$sDashletClass] = array('label' => $aInfo['label'], 'class' => $sDashletClass, 'icon' => $aInfo['icon']); $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'), ''); $oSelectorField = new DesignerFormSelectorField('dashlet_class', Dict::S('UI:DashletCreation:DashletType'), '');
$oForm->AddField($oSelectorField); $oForm->AddField($oSelectorField);
foreach($aDashlets as $sDashletClass => $aDashletInfo) foreach ($aDashlets as $sDashletClass => $aDashletInfo) {
{
$oSubForm = new DesignerForm(); $oSubForm = new DesignerForm();
$oMetaModel = new ModelReflectionRuntime(); $oMetaModel = new ModelReflectionRuntime();
/** @var \Dashlet $oDashlet */ /** @var \Dashlet $oDashlet */
$oDashlet = new $sDashletClass($oMetaModel, 0); $oDashlet = new $sDashletClass($oMetaModel, 0);
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL); $oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
$oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']); $oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']);
} }
$oField = new DesignerBooleanField('open_editor', Dict::S('UI:DashletCreation:EditNow'), true); $oField = new DesignerBooleanField('open_editor', Dict::S('UI:DashletCreation:EditNow'), true);
$oForm->AddField($oField); $oForm->AddField($oField);
return $oForm; return $oForm;
} }
@@ -1501,11 +1440,11 @@ JS
$oForm->Render($oPage); $oForm->Render($oPage);
$oPage->add('</div>'); $oPage->add('</div>');
$sDialogTitle = Dict::S('UI:DashletCreation:Title'); $sDialogTitle = Dict::S('UI:DashletCreation:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok'); $sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
$('#dashlet_creation_dlg').dialog({ $('#dashlet_creation_dlg').dialog({
@@ -1603,7 +1542,7 @@ JS
/** /**
* @inheritDoc * @inheritDoc
*/ */
protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = array()) protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = [])
{ {
$sDashletIdOrig = $oDashlet->GetID(); $sDashletIdOrig = $oDashlet->GetID();
$sDashboardSanitizedId = $this->GetSanitizedId(); $sDashboardSanitizedId = $this->GetSanitizedId();
@@ -1630,31 +1569,27 @@ JS
private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams) private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams)
{ {
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList); $bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
if (!$bIsDashletWithListPref) if (!$bIsDashletWithListPref) {
{
return; return;
} }
/** @var \DashletObjectList $oDashlet */ /** @var \DashletObjectList $oDashlet */
$bDashletIdInNewFormat = ($sDashletIdOrig === $oDashlet->GetID()); $bDashletIdInNewFormat = ($sDashletIdOrig === $oDashlet->GetID());
if ($bDashletIdInNewFormat) if ($bDashletIdInNewFormat) {
{
return; return;
} }
$sNewPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $oDashlet->GetID()); $sNewPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $oDashlet->GetID());
$sPrefValueForNewKey = appUserPreferences::GetPref($sNewPrefKey, null); $sPrefValueForNewKey = appUserPreferences::GetPref($sNewPrefKey, null);
$bHasPrefInNewFormat = ($sPrefValueForNewKey !== null); $bHasPrefInNewFormat = ($sPrefValueForNewKey !== null);
if ($bHasPrefInNewFormat) if ($bHasPrefInNewFormat) {
{
return; return;
} }
$sOldPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $sDashletIdOrig); $sOldPrefKey = $this->GetDashletObjectListAppUserPreferencesPrefix($oDashlet, $aExtraParams, $sDashletIdOrig);
$sPrefValueForOldKey = appUserPreferences::GetPref($sOldPrefKey, null); $sPrefValueForOldKey = appUserPreferences::GetPref($sOldPrefKey, null);
$bHasPrefInOldFormat = ($sPrefValueForOldKey !== null); $bHasPrefInOldFormat = ($sPrefValueForOldKey !== null);
if (!$bHasPrefInOldFormat) if (!$bHasPrefInOldFormat) {
{
return; return;
} }
@@ -1673,7 +1608,7 @@ JS
private function GetDashletObjectListAppUserPreferencesPrefix(DashletObjectList $oDashlet, $aExtraParams, $sDashletId) private function GetDashletObjectListAppUserPreferencesPrefix(DashletObjectList $oDashlet, $aExtraParams, $sDashletId)
{ {
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId; $sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
$aClassAliases = array(); $aClassAliases = [];
try { try {
$oFilter = $oDashlet->GetDBSearch($aExtraParams); $oFilter = $oDashlet->GetDBSearch($aExtraParams);
$aClassAliases = $oFilter->GetSelectedClasses(); $aClassAliases = $oFilter->GetSelectedClasses();

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -38,21 +39,21 @@ abstract class DashboardLayout
* @since 2.7.0 * @since 2.7.0
*/ */
abstract public function GetDashletCoordinates($iCellIdx); abstract public function GetDashletCoordinates($iCellIdx);
public static function GetInfo() public static function GetInfo()
{ {
return array( return [
'label' => '', 'label' => '',
'icon' => '', 'icon' => '',
'description' => '', 'description' => '',
); ];
} }
} }
abstract class DashboardLayoutMultiCol extends DashboardLayout abstract class DashboardLayoutMultiCol extends DashboardLayout
{ {
protected $iNbCols; protected $iNbCols;
public function __construct() public function __construct()
{ {
$this->iNbCols = 1; $this->iNbCols = 1;
@@ -63,47 +64,38 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$aKeys = array_reverse(array_keys($aDashlets)); $aKeys = array_reverse(array_keys($aDashlets));
$idx = 0; $idx = 0;
$bNoVisibleFound = true; $bNoVisibleFound = true;
while($idx < count($aKeys) && $bNoVisibleFound) while ($idx < count($aKeys) && $bNoVisibleFound) {
{
/** @var \Dashlet $oDashlet */ /** @var \Dashlet $oDashlet */
$oDashlet = $aDashlets[$aKeys[$idx]]; $oDashlet = $aDashlets[$aKeys[$idx]];
if ($oDashlet::IsVisible()) if ($oDashlet::IsVisible()) {
{
$bNoVisibleFound = false; $bNoVisibleFound = false;
} } else {
else
{
unset($aDashlets[$aKeys[$idx]]); unset($aDashlets[$aKeys[$idx]]);
} }
$idx++; $idx++;
} }
return $aDashlets; return $aDashlets;
} }
protected function TrimCellsArray($aCells) protected function TrimCellsArray($aCells)
{ {
foreach($aCells as $key => $aDashlets) foreach ($aCells as $key => $aDashlets) {
{
$aCells[$key] = $this->TrimCell($aDashlets); $aCells[$key] = $this->TrimCell($aDashlets);
} }
$aKeys = array_reverse(array_keys($aCells)); $aKeys = array_reverse(array_keys($aCells));
$idx = 0; $idx = 0;
$bNoVisibleFound = true; $bNoVisibleFound = true;
while($idx < count($aKeys) && $bNoVisibleFound) while ($idx < count($aKeys) && $bNoVisibleFound) {
{
$aDashlets = $aCells[$aKeys[$idx]]; $aDashlets = $aCells[$aKeys[$idx]];
if (count($aDashlets) > 0) if (count($aDashlets) > 0) {
{
$bNoVisibleFound = false; $bNoVisibleFound = false;
} } else {
else
{
unset($aCells[$aKeys[$idx]]); unset($aCells[$aKeys[$idx]]);
} }
$idx++; $idx++;
} }
return $aCells; return $aCells;
} }
/** /**
@@ -112,7 +104,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
* @param bool $bEditMode * @param bool $bEditMode
* @param array $aExtraParams * @param array $aExtraParams
*/ */
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = array()) public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = [])
{ {
// Trim the list of cells to remove the invisible/empty ones at the end of the array // Trim the list of cells to remove the invisible/empty ones at the end of the array
$aCells = $this->TrimCellsArray($aCells); $aCells = $this->TrimCellsArray($aCells);
@@ -157,8 +149,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}"); $oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
if ($bEditMode) // Add one row for extensibility if ($bEditMode) { // Add one row for extensibility
{
$oDashboardRow = new DashboardRow(); $oDashboardRow = new DashboardRow();
$oDashboardLayout->AddDashboardRow($oDashboardRow); $oDashboardLayout->AddDashboardRow($oDashboardRow);
@@ -180,7 +171,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$iColNumber = (int) $iCellIdx % $this->iNbCols; $iColNumber = (int) $iCellIdx % $this->iNbCols;
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols); $iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
return array($iColNumber, $iRowNumber); return [$iColNumber, $iRowNumber];
} }
} }
@@ -191,13 +182,13 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
parent::__construct(); parent::__construct();
$this->iNbCols = 1; $this->iNbCols = 1;
} }
static public function GetInfo() public static function GetInfo()
{ {
return array( return [
'label' => 'One Column', 'label' => 'One Column',
'icon' => 'images/layout_1col.png', 'icon' => 'images/layout_1col.png',
'description' => '', 'description' => '',
); ];
} }
} }
@@ -208,13 +199,13 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
parent::__construct(); parent::__construct();
$this->iNbCols = 2; $this->iNbCols = 2;
} }
static public function GetInfo() public static function GetInfo()
{ {
return array( return [
'label' => 'Two Columns', 'label' => 'Two Columns',
'icon' => 'images/layout_2col.png', 'icon' => 'images/layout_2col.png',
'description' => '', 'description' => '',
); ];
} }
} }
@@ -225,12 +216,12 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
parent::__construct(); parent::__construct();
$this->iNbCols = 3; $this->iNbCols = 3;
} }
static public function GetInfo() public static function GetInfo()
{ {
return array( return [
'label' => 'Two Columns', 'label' => 'Two Columns',
'icon' => 'images/layout_3col.png', 'icon' => 'images/layout_3col.png',
'description' => '', 'description' => '',
); ];
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -80,42 +80,31 @@ class DataTable
// Identified tables can have their own specific settings // Identified tables can have their own specific settings
$oCustomSettings = DataTableSettings::GetTableSettings($this->aClassAliases, $this->sTableId); $oCustomSettings = DataTableSettings::GetTableSettings($this->aClassAliases, $this->sTableId);
if ($oCustomSettings != null) if ($oCustomSettings != null) {
{
// Custom settings overload the default ones // Custom settings overload the default ones
$this->bUseCustomSettings = true; $this->bUseCustomSettings = true;
if ($this->oDefaultSettings->iDefaultPageSize == 0) if ($this->oDefaultSettings->iDefaultPageSize == 0) {
{
$oCustomSettings->iDefaultPageSize = 0; $oCustomSettings->iDefaultPageSize = 0;
} }
} } else {
else
{
$oCustomSettings = $oSettings; $oCustomSettings = $oSettings;
} }
if ($oCustomSettings->iDefaultPageSize > 0) if ($oCustomSettings->iDefaultPageSize > 0) {
{
$this->oSet->SetLimit($oCustomSettings->iDefaultPageSize); $this->oSet->SetLimit($oCustomSettings->iDefaultPageSize);
} }
$this->oSet->SetOrderBy($oCustomSettings->GetSortOrder()); $this->oSet->SetOrderBy($oCustomSettings->GetSortOrder());
// Load only the requested columns // Load only the requested columns
$aColumnsToLoad = array(); $aColumnsToLoad = [];
foreach($oCustomSettings->aColumns as $sAlias => $aColumnsInfo) foreach ($oCustomSettings->aColumns as $sAlias => $aColumnsInfo) {
{ foreach ($aColumnsInfo as $sAttCode => $aData) {
foreach($aColumnsInfo as $sAttCode => $aData) if ($sAttCode != '_key_') {
{ if ($aData['checked']) {
if ($sAttCode != '_key_')
{
if ($aData['checked'])
{
$aColumnsToLoad[$sAlias][] = $sAttCode; $aColumnsToLoad[$sAlias][] = $sAttCode;
} } else {
else // See if this column is a must to load
{
// See if this column is a must to load
$sClass = $this->aClassAliases[$sAlias]; $sClass = $this->aClassAliases[$sAlias];
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->AlwaysLoadInTables()) { if ($oAttDef->AlwaysLoadInTables()) {
@@ -127,18 +116,15 @@ class DataTable
} }
$this->oSet->OptimizeColumnLoad($aColumnsToLoad); $this->oSet->OptimizeColumnLoad($aColumnsToLoad);
$bToolkitMenu = true; $bToolkitMenu = true;
if (isset($aExtraParams['toolkit_menu'])) if (isset($aExtraParams['toolkit_menu'])) {
{
$bToolkitMenu = (bool) $aExtraParams['toolkit_menu']; $bToolkitMenu = (bool) $aExtraParams['toolkit_menu'];
} }
if (UserRights::IsPortalUser()) if (UserRights::IsPortalUser()) {
{
// Portal users have a limited access to data, for now they can only see what's configured for them // Portal users have a limited access to data, for now they can only see what's configured for them
$bToolkitMenu = false; $bToolkitMenu = false;
} }
return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams); return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams);
} }
@@ -167,10 +153,10 @@ class DataTable
if ($bActionsMenu) { if ($bActionsMenu) {
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams); $sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
} }
// if ($bToolkitMenu) // if ($bToolkitMenu)
// { // {
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams); // $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
// } // }
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams); $sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize); $sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
@@ -188,7 +174,7 @@ class DataTable
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData; $aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
$aOptions = array( $aOptions = [
'sPersistentId' => '', 'sPersistentId' => '',
'sFilter' => $this->oSet->GetFilter()->serialize(), 'sFilter' => $this->oSet->GetFilter()->serialize(),
'oColumns' => $aColumns, 'oColumns' => $aColumns,
@@ -202,12 +188,11 @@ class DataTable
'sTableId' => $this->sTableId, 'sTableId' => $this->sTableId,
'oExtraParams' => $aExtraParams, 'oExtraParams' => $aExtraParams,
'sRenderUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', 'sRenderUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
'oRenderParameters' => array('str' => ''), // Forces JSON to encode this as a object... 'oRenderParameters' => ['str' => ''], // Forces JSON to encode this as a object...
'oDefaultSettings' => array('str' => ''), // Forces JSON to encode this as a object... 'oDefaultSettings' => ['str' => ''], // Forces JSON to encode this as a object...
'oLabels' => array('moveup' => Dict::S('UI:Button:MoveUp'), 'movedown' => Dict::S('UI:Button:MoveDown')), 'oLabels' => ['moveup' => Dict::S('UI:Button:MoveUp'), 'movedown' => Dict::S('UI:Button:MoveDown')],
); ];
if($this->oDefaultSettings != null) if ($this->oDefaultSettings != null) {
{
$aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings); $aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings);
} }
$sJSOptions = json_encode($aOptions); $sJSOptions = json_encode($aOptions);
@@ -222,16 +207,14 @@ class DataTable
*/ */
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams) public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
{ {
if ($iPageSize < 1) if ($iPageSize < 1) {
{
$iPageSize = -1; // convention: no pagination $iPageSize = -1; // convention: no pagination
} }
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink); $aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams); $aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sHtml = ''; $sHtml = '';
foreach($aValues as $aRow) foreach ($aValues as $aRow) {
{
$sHtml .= $oPage->GetTableRow($aRow, $aAttribs); $sHtml .= $oPage->GetTableRow($aRow, $aAttribs);
} }
return $sHtml; return $sHtml;
@@ -245,15 +228,12 @@ class DataTable
*/ */
protected function GetObjectCount(WebPage $oPage, $sSelectMode) protected function GetObjectCount(WebPage $oPage, $sSelectMode)
{ {
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
{
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderSelection', '<span id="total">'.$this->iNbObjects.'</span>', '<span class="selectedCount">0</span>').'</div>'; $sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderSelection', '<span id="total">'.$this->iNbObjects.'</span>', '<span class="selectedCount">0</span>').'</div>';
} } else {
else
{
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderNoSelection', '<span id="total">'.$this->iNbObjects.'</span>').'</div>'; $sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderNoSelection', '<span id="total">'.$this->iNbObjects.'</span>').'</div>';
} }
return $sHtml; return $sHtml;
} }
/** /**
@@ -267,26 +247,19 @@ class DataTable
protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex) protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex)
{ {
$sHtml = ''; $sHtml = '';
if ($iPageSize < 1) // Display all if ($iPageSize < 1) { // Display all
{
$sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI $sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI
// WARNING: mPDF does not take the "display" style into account // WARNING: mPDF does not take the "display" style into account
// when applied to a <td> or a <table> tag, so make sure you apply this to a div // when applied to a <td> or a <table> tag, so make sure you apply this to a div
} } else {
else
{
$sPagerStyle = ''; $sPagerStyle = '';
} }
$sCombo = '<select class="pagesize">'; $sCombo = '<select class="pagesize">';
if($iPageSize < 1) if ($iPageSize < 1) {
{
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>"; $sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
} } else {
else for ($iPage = 1; $iPage < 5; $iPage++) {
{
for($iPage = 1; $iPage < 5; $iPage++)
{
$iNbItems = $iPage * $iDefaultPageSize; $iNbItems = $iPage * $iDefaultPageSize;
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : ''; $sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>"; $sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
@@ -295,31 +268,25 @@ class DataTable
} }
$sCombo .= '</select>'; $sCombo .= '</select>';
$sPages = Dict::S('UI:Pagination:PagesLabel'); $sPages = Dict::S('UI:Pagination:PagesLabel');
$sPageSizeCombo = Dict::Format('UI:Pagination:PageSize', $sCombo); $sPageSizeCombo = Dict::Format('UI:Pagination:PageSize', $sCombo);
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize); $iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iNbPages == 1) if ($iNbPages == 1) {
{
// No need to display the pager // No need to display the pager
$sPagerStyle = 'style="display:none"'; $sPagerStyle = 'style="display:none"';
} }
$aPagesToDisplay = array(); $aPagesToDisplay = [];
for($idx = 0; $idx <= min(4, $iNbPages-1); $idx++) for ($idx = 0; $idx <= min(4, $iNbPages - 1); $idx++) {
{ if ($idx == 0) {
if ($idx == 0)
{
$aPagesToDisplay[$idx] = '<span page="0" class="curr_page">1</span>'; $aPagesToDisplay[$idx] = '<span page="0" class="curr_page">1</span>';
} } else {
else $aPagesToDisplay[$idx] = "<span id=\"gotopage_$idx\" class=\"gotopage\" page=\"$idx\">".(1 + $idx)."</span>";
{
$aPagesToDisplay[$idx] = "<span id=\"gotopage_$idx\" class=\"gotopage\" page=\"$idx\">".(1+$idx)."</span>";
} }
} }
$iLastPageIdx = $iNbPages - 1; $iLastPageIdx = $iNbPages - 1;
if (!isset($aPagesToDisplay[$iLastPageIdx])) if (!isset($aPagesToDisplay[$iLastPageIdx])) {
{
unset($aPagesToDisplay[$idx - 1]); // remove the last page added to make room for the very last page unset($aPagesToDisplay[$idx - 1]); // remove the last page added to make room for the very last page
$aPagesToDisplay[$iLastPageIdx] = "<span id=\"gotopage_$iLastPageIdx\" class=\"gotopage\" page=\"$iLastPageIdx\">... $iNbPages</span>"; $aPagesToDisplay[$iLastPageIdx] = "<span id=\"gotopage_$iLastPageIdx\" class=\"gotopage\" page=\"$iLastPageIdx\">... $iNbPages</span>";
} }
@@ -386,22 +353,19 @@ EOF;
*/ */
protected function GetToolkitMenu(WebPage $oPage, $aExtraParams) protected function GetToolkitMenu(WebPage $oPage, $aExtraParams)
{ {
if (!$oPage->IsPrintableVersion()) if (!$oPage->IsPrintableVersion()) {
{
$sMenuTitle = Dict::S('UI:ConfigureThisList'); $sMenuTitle = Dict::S('UI:ConfigureThisList');
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>'; $sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');"); $oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
$aActions = array( $aActions = [
$oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(), $oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(),
); ];
$this->oSet->Rewind(); $this->oSet->Rewind();
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions, $this->sTableId, $this->iListId); utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions, $this->sTableId, $this->iListId);
$this->oSet->Rewind(); $this->oSet->Rewind();
$sHtml .= $oPage->RenderPopupMenuItems($aActions); $sHtml .= $oPage->RenderPopupMenuItems($aActions);
} } else {
else
{
$sHtml = ''; $sHtml = '';
} }
return $sHtml; return $sHtml;
@@ -422,10 +386,10 @@ EOF;
$sChecked = ($this->bUseCustomSettings) ? '' : 'checked'; $sChecked = ($this->bUseCustomSettings) ? '' : 'checked';
$sHtml .= "<p><input id=\"dtbl_dlg_settings_{$this->iListId}\" type=\"radio\" name=\"settings\" $sChecked value=\"defaults\"><label for=\"dtbl_dlg_settings_{$this->iListId}\">&nbsp;".Dict::S('UI:UseDefaultSettings').'</label></p>'; $sHtml .= "<p><input id=\"dtbl_dlg_settings_{$this->iListId}\" type=\"radio\" name=\"settings\" $sChecked value=\"defaults\"><label for=\"dtbl_dlg_settings_{$this->iListId}\">&nbsp;".Dict::S('UI:UseDefaultSettings').'</label></p>';
$sHtml .= "<fieldset>"; $sHtml .= "<fieldset>";
$sChecked = ($this->bUseCustomSettings) ? 'checked': ''; $sChecked = ($this->bUseCustomSettings) ? 'checked' : '';
$sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_specific_{$this->iListId}\" type=\"radio\" class=\"specific_settings\" name=\"settings\" $sChecked value=\"specific\"><label for=\"dtbl_dlg_specific_{$this->iListId}\">&nbsp;".Dict::S('UI:UseSpecificSettings')."</label></legend>"; $sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_specific_{$this->iListId}\" type=\"radio\" class=\"specific_settings\" name=\"settings\" $sChecked value=\"specific\"><label for=\"dtbl_dlg_specific_{$this->iListId}\">&nbsp;".Dict::S('UI:UseSpecificSettings')."</label></legend>";
$sHtml .= Dict::S('UI:ColumnsAndSortOrder').'<br/><ul class="sortable_field_list" id="sfl_'.$this->iListId.'"></ul>'; $sHtml .= Dict::S('UI:ColumnsAndSortOrder').'<br/><ul class="sortable_field_list" id="sfl_'.$this->iListId.'"></ul>';
$sHtml .= '<p>'.Dict::Format('UI:Display_X_ItemsPerPage', '<input type="text" size="4" name="page_size" value="'.$iDefaultPageSize.'">').'</p>'; $sHtml .= '<p>'.Dict::Format('UI:Display_X_ItemsPerPage', '<input type="text" size="4" name="page_size" value="'.$iDefaultPageSize.'">').'</p>';
$sHtml .= "</fieldset>"; $sHtml .= "</fieldset>";
$sHtml .= "<fieldset>"; $sHtml .= "<fieldset>";
@@ -444,7 +408,7 @@ EOF;
$sHtml .= '</td></tr></table>'; $sHtml .= '</td></tr></table>';
$sHtml .= "</form>"; $sHtml .= "</form>";
$sHtml .= "</div>"; $sHtml .= "</div>";
$sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle')); $sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle'));
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });"); $oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });");
@@ -458,7 +422,7 @@ EOF;
*/ */
public function GetAsHash($oSetting) public function GetAsHash($oSetting)
{ {
$aSettings = array('iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns); $aSettings = ['iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns];
return $aSettings; return $aSettings;
} }
@@ -474,55 +438,46 @@ EOF;
*/ */
protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink) protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
{ {
$aAttribs = array(); $aAttribs = [];
if ($sSelectMode == 'multiple') if ($sSelectMode == 'multiple') {
{ $aAttribs['form::select'] = [
$aAttribs['form::select'] = array(
'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>", 'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>",
'description' => Dict::S('UI:SelectAllToggle+'), 'description' => Dict::S('UI:SelectAllToggle+'),
'metadata' => array(), 'metadata' => [],
); ];
} } elseif ($sSelectMode == 'single') {
else if ($sSelectMode == 'single') $aAttribs['form::select'] = ['label' => '', 'description' => '', 'metadata' => []];
{
$aAttribs['form::select'] = array('label' => '', 'description' => '', 'metadata' => array());
} }
foreach($this->aClassAliases as $sAlias => $sClassName) foreach ($this->aClassAliases as $sAlias => $sClassName) {
{ foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
foreach($aColumns[$sAlias] as $sAttCode => $aData) if ($aData['checked']) {
{ if ($sAttCode == '_key_') {
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$sAttLabel = MetaModel::GetName($sClassName); $sAttLabel = MetaModel::GetName($sClassName);
$aAttribs['key_'.$sAlias] = array( $aAttribs['key_'.$sAlias] = [
'label' => $sAttLabel, 'label' => $sAttLabel,
'description' => '', 'description' => '',
'metadata' => array( 'metadata' => [
'object_class' => $sClassName, 'object_class' => $sClassName,
'attribute_label' => $sAttLabel, 'attribute_label' => $sAttLabel,
), ],
); ];
} } else {
else
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
$sAttDefClass = get_class($oAttDef); $sAttDefClass = get_class($oAttDef);
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode); $sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
$aAttribs[$sAttCode.'_'.$sAlias] = array( $aAttribs[$sAttCode.'_'.$sAlias] = [
'label' => $sAttLabel, 'label' => $sAttLabel,
'description' => $oAttDef->GetOrderByHint(), 'description' => $oAttDef->GetOrderByHint(),
'metadata' => array( 'metadata' => [
'object_class' => $sClassName, 'object_class' => $sClassName,
'attribute_code' => $sAttCode, 'attribute_code' => $sAttCode,
'attribute_type' => $sAttDefClass, 'attribute_type' => $sAttDefClass,
'attribute_label' => $sAttLabel, 'attribute_label' => $sAttLabel,
), ],
); ];
} }
} }
} }
@@ -530,7 +485,6 @@ EOF;
return $aAttribs; return $aAttribs;
} }
/** /**
* @param $aColumns * @param $aColumns
* @param $sSelectMode * @param $sSelectMode
@@ -549,104 +503,74 @@ EOF;
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams) protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{ {
$bLocalize = true; $bLocalize = true;
if (isset($aExtraParams['localize_values'])) if (isset($aExtraParams['localize_values'])) {
{
$bLocalize = (bool) $aExtraParams['localize_values']; $bLocalize = (bool) $aExtraParams['localize_values'];
} }
$aValues = array(); $aValues = [];
$aAttDefsCache = array(); $aAttDefsCache = [];
$this->oSet->Seek(0); $this->oSet->Seek(0);
$iMaxObjects = $iPageSize; $iMaxObjects = $iPageSize;
while (($aObjects = $this->oSet->FetchAssoc()) && ($iMaxObjects != 0)) while (($aObjects = $this->oSet->FetchAssoc()) && ($iMaxObjects != 0)) {
{
$bFirstObject = true; $bFirstObject = true;
$aRow = array(); $aRow = [];
foreach($this->aClassAliases as $sAlias => $sClassName) foreach ($this->aClassAliases as $sAlias => $sClassName) {
{ if (is_object($aObjects[$sAlias])) {
if (is_object($aObjects[$sAlias]))
{
$sHilightClass = MetaModel::GetHilightClass($sClassName, $aObjects[$sAlias]); $sHilightClass = MetaModel::GetHilightClass($sClassName, $aObjects[$sAlias]);
if ($sHilightClass != '') if ($sHilightClass != '') {
{ $aRow['@class'] = $sHilightClass;
$aRow['@class'] = $sHilightClass;
} }
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject) if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject) {
{ if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()])) {
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]))
{
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"'; $sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
} } else {
else
{
$sDisabled = ''; $sDisabled = '';
} }
if ($sSelectMode == 'single') if ($sSelectMode == 'single') {
{
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>"; $aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
} } else {
else
{
$aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>"; $aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
} }
} }
foreach($aColumns[$sAlias] as $sAttCode => $aData) foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
{ if ($aData['checked']) {
if ($aData['checked']) if ($sAttCode == '_key_') {
{ $aRow['key_'.$sAlias] = [
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = array(
'value_raw' => $aObjects[$sAlias]->GetKey(), 'value_raw' => $aObjects[$sAlias]->GetKey(),
'value_html' => $aObjects[$sAlias]->GetHyperLink(), 'value_html' => $aObjects[$sAlias]->GetHyperLink(),
); ];
} } else {
else
{
// Prepare att. def. classes cache to avoid retrieving AttDef for each row // Prepare att. def. classes cache to avoid retrieving AttDef for each row
if(!isset($aAttDefsCache[$sClassName][$sAttCode])) if (!isset($aAttDefsCache[$sClassName][$sAttCode])) {
{
$aAttDefClassesCache[$sClassName][$sAttCode] = get_class(MetaModel::GetAttributeDef($sClassName, $sAttCode)); $aAttDefClassesCache[$sClassName][$sAttCode] = get_class(MetaModel::GetAttributeDef($sClassName, $sAttCode));
} }
// Only retrieve raw (stored) value for simple fields // Only retrieve raw (stored) value for simple fields
$bExcludeRawValue = false; $bExcludeRawValue = false;
foreach (cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) foreach (cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
{ if (is_a($aAttDefClassesCache[$sClassName][$sAttCode], $sAttDefClassToExclude, true)) {
if (is_a($aAttDefClassesCache[$sClassName][$sAttCode], $sAttDefClassToExclude, true))
{
$bExcludeRawValue = true; $bExcludeRawValue = true;
break; break;
} }
} }
if($bExcludeRawValue) if ($bExcludeRawValue) {
{
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize); $aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize);
} } else {
else $aRow[$sAttCode.'_'.$sAlias] = [
{
$aRow[$sAttCode.'_'.$sAlias] = array(
'value_raw' => $aObjects[$sAlias]->Get($sAttCode), 'value_raw' => $aObjects[$sAlias]->Get($sAttCode),
'value_html' => $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize), 'value_html' => $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize),
); ];
} }
} }
} }
} }
} } else {
else foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
{ if ($aData['checked']) {
foreach($aColumns[$sAlias] as $sAttCode => $aData) if ($sAttCode == '_key_') {
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = ''; $aRow['key_'.$sAlias] = '';
} } else {
else
{
$aRow[$sAttCode.'_'.$sAlias] = ''; $aRow[$sAttCode.'_'.$sAlias] = '';
} }
} }
@@ -681,8 +605,7 @@ EOF;
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams) public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{ {
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize); $iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iPageSize < 1) if ($iPageSize < 1) {
{
$iPageSize = -1; // convention: no pagination $iPageSize = -1; // convention: no pagination
} }
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink); $aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
@@ -691,8 +614,7 @@ EOF;
$sHtml = '<table class="listContainer object-list">'; $sHtml = '<table class="listContainer object-list">';
foreach($this->oSet->GetFilter()->GetInternalParams() as $sName => $sValue) foreach ($this->oSet->GetFilter()->GetInternalParams() as $sName => $sValue) {
{
$aExtraParams['query_params'][$sName] = $sValue; $aExtraParams['query_params'][$sName] = $sValue;
} }
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData; $aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
@@ -707,20 +629,16 @@ EOF;
$sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them $sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them
$sSelectModeJS = ''; $sSelectModeJS = '';
$sHeaders = ''; $sHeaders = '';
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
{
$sSelectModeJS = $sSelectMode; $sSelectModeJS = $sSelectMode;
$sHeaders = 'headers: { 0: {sorter: false}},'; $sHeaders = 'headers: { 0: {sorter: false}},';
} }
$sDisplayKey = ($bViewLink) ? 'true' : 'false'; $sDisplayKey = ($bViewLink) ? 'true' : 'false';
// Protect against duplicate elements in the Zlist // Protect against duplicate elements in the Zlist
$aUniqueOrderedList = array(); $aUniqueOrderedList = [];
foreach($this->aClassAliases as $sAlias => $sClassName) foreach ($this->aClassAliases as $sAlias => $sClassName) {
{ foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
foreach($aColumns[$sAlias] as $sAttCode => $aData) if ($aData['checked']) {
{
if ($aData['checked'])
{
$aUniqueOrderedList[$sAttCode] = true; $aUniqueOrderedList[$sAttCode] = true;
} }
} }
@@ -732,41 +650,32 @@ EOF;
$this->oSet->ApplyParameters(); $this->oSet->ApplyParameters();
// Display the actual sort order of the table // Display the actual sort order of the table
$aRealSortOrder = $this->oSet->GetRealSortOrder(); $aRealSortOrder = $this->oSet->GetRealSortOrder();
$aDefaultSort = array(); $aDefaultSort = [];
$iColOffset = 0; $iColOffset = 0;
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
{
$iColOffset += 1; $iColOffset += 1;
} }
if ($bViewLink) if ($bViewLink) {
{ // $iColOffset += 1;
// $iColOffset += 1;
} }
foreach($aRealSortOrder as $sColCode => $bAscending) foreach ($aRealSortOrder as $sColCode => $bAscending) {
{
$iPos = array_search($sColCode, $aUniqueOrderedList); $iPos = array_search($sColCode, $aUniqueOrderedList);
if ($iPos !== false) if ($iPos !== false) {
{ $aDefaultSort[] = "[".($iColOffset + $iPos).",".($bAscending ? '0' : '1')."]";
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]"; } elseif (($iPos = array_search(preg_replace('/_friendlyname$/', '', $sColCode), $aUniqueOrderedList)) !== false) {
}
else if (($iPos = array_search(preg_replace('/_friendlyname$/', '', $sColCode), $aUniqueOrderedList)) !== false)
{
// if sorted on the friendly name of an external key, then consider it sorted on the column that shows the links // if sorted on the friendly name of an external key, then consider it sorted on the column that shows the links
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]"; $aDefaultSort[] = "[".($iColOffset + $iPos).",".($bAscending ? '0' : '1')."]";
} } elseif ($sColCode == 'friendlyname' && $bViewLink) {
else if($sColCode == 'friendlyname' && $bViewLink)
{
$aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]"; $aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]";
} }
} }
$sFakeSortList = ''; $sFakeSortList = '';
if (count($aDefaultSort) > 0) if (count($aDefaultSort) > 0) {
{
$sFakeSortList = '['.implode(',', $aDefaultSort).']'; $sFakeSortList = '['.implode(',', $aDefaultSort).']';
} }
$sOQL = addslashes($this->oSet->GetFilter()->serialize()); $sOQL = addslashes($this->oSet->GetFilter()->serialize());
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
var oTable = $('#{$this->sDatatableContainerId} table.listResults'); var oTable = $('#{$this->sDatatableContainerId} table.listResults');
oTable.tableHover(); oTable.tableHover();
oTable oTable
@@ -784,9 +693,8 @@ oTable
class_aliases: $sJSClassAliases $sCssCount class_aliases: $sJSClassAliases $sCssCount
}); });
JS JS
); );
if ($sFakeSortList != '') if ($sFakeSortList != '') {
{
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);"); $oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
} }
return $sHtml; return $sHtml;
@@ -803,12 +711,9 @@ JS
$iPageIndex = 0; $iPageIndex = 0;
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex); $sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');"); $oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
if ($iDefaultPageSize < 1) if ($iDefaultPageSize < 1) {
{
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().hide()"); $oPage->add_ready_script("$('#pager{$this->iListId}').parent().hide()");
} } else {
else
{
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().show()"); $oPage->add_ready_script("$('#pager{$this->iListId}').parent().show()");
} }
} }
@@ -865,16 +770,15 @@ class PrintableDataTable extends DataTable
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams) public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{ {
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize); $iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iPageSize < 1) if ($iPageSize < 1) {
{
$iPageSize = -1; // convention: no pagination $iPageSize = -1; // convention: no pagination
} }
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink); $aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams); $aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sHtml = $oPage->GetTable($aAttribs, $aValues); $sHtml = $oPage->GetTable($aAttribs, $aValues);
return $sHtml; return $sHtml;
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -104,7 +105,7 @@ class DisplayBlock
*/ */
public const ENUM_STYLE_CHART_AJAX = 'chart_ajax'; public const ENUM_STYLE_CHART_AJAX = 'chart_ajax';
const TAG_BLOCK = 'itopblock'; public const TAG_BLOCK = 'itopblock';
/** @var \DBSearch */ /** @var \DBSearch */
protected $m_oFilter; protected $m_oFilter;
protected $m_aConditions; // Conditions added to the filter -> avoid duplicate conditions protected $m_aConditions; // Conditions added to the filter -> avoid duplicate conditions
@@ -137,20 +138,18 @@ class DisplayBlock
* *
* @throws \ApplicationException * @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_oFilter = $oFilter->DeepClone();
$this->m_aConditions = array(); $this->m_aConditions = [];
$this->m_sStyle = $sStyle; $this->m_sStyle = $sStyle;
$this->m_bAsynchronous = $bAsynchronous; $this->m_bAsynchronous = $bAsynchronous;
$this->m_aParams = $aParams; $this->m_aParams = $aParams;
$this->m_oSet = $oSet; $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']; $this->m_bShowObsoleteData = $aParams['show_obsolete_data'];
} }
if ($this->m_bShowObsoleteData === null) if ($this->m_bShowObsoleteData === null) {
{
// User defined // User defined
$this->m_bShowObsoleteData = utils::ShowObsoleteData(); $this->m_bShowObsoleteData = utils::ShowObsoleteData();
} }
@@ -410,22 +409,18 @@ class DisplayBlock
* @throws \CoreException * @throws \CoreException
* @throws \Exception * @throws \Exception
*/ */
public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = array()) public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = [])
{ {
$oDummyFilter = new DBObjectSearch($oSet->GetClass()); $oDummyFilter = new DBObjectSearch($oSet->GetClass());
$aKeys = array(); $aKeys = [];
$oSet->OptimizeColumnLoad(array($oSet->GetClassAlias() => array())); // No need to load all the columns just to get the id $oSet->OptimizeColumnLoad([$oSet->GetClassAlias() => []]); // No need to load all the columns just to get the id
while($oObject = $oSet->Fetch()) while ($oObject = $oSet->Fetch()) {
{ $aKeys[] = $oObject->GetKey();
$aKeys[] = $oObject->GetKey();
} }
$oSet->Rewind(); $oSet->Rewind();
if (count($aKeys) > 0) if (count($aKeys) > 0) {
{
$oDummyFilter->AddCondition('id', $aKeys, 'IN'); $oDummyFilter->AddCondition('id', $aKeys, 'IN');
} } else {
else
{
$oDummyFilter->AddCondition('id', 0, '='); $oDummyFilter->AddCondition('id', 0, '=');
} }
$oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams); // DisplayBlocks built this way are synchronous $oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams); // DisplayBlocks built this way are synchronous
@@ -446,7 +441,7 @@ class DisplayBlock
$iStartPos = stripos($sTemplate, '<'.self::TAG_BLOCK.' ', 0); $iStartPos = stripos($sTemplate, '<'.self::TAG_BLOCK.' ', 0);
$iEndPos = stripos($sTemplate, '</'.self::TAG_BLOCK.'>', $iStartPos); $iEndPos = stripos($sTemplate, '</'.self::TAG_BLOCK.'>', $iStartPos);
$iEndTag = stripos($sTemplate, '>', $iStartPos); $iEndTag = stripos($sTemplate, '>', $iStartPos);
$aParams = array(); $aParams = [];
if (($iStartPos === false) || ($iEndPos === false)) { if (($iStartPos === false) || ($iEndPos === false)) {
return null; return null;
@@ -454,7 +449,7 @@ class DisplayBlock
$sITopData = substr($sTemplate, 1 + $iEndTag, $iEndPos - $iEndTag - 1); $sITopData = substr($sTemplate, 1 + $iEndTag, $iEndPos - $iEndTag - 1);
$sITopTag = substr($sTemplate, $iStartPos + strlen('<'.self::TAG_BLOCK), $iEndTag - $iStartPos - strlen('<'.self::TAG_BLOCK)); $sITopTag = substr($sTemplate, $iStartPos + strlen('<'.self::TAG_BLOCK), $iEndTag - $iStartPos - strlen('<'.self::TAG_BLOCK));
$aMatches = array(); $aMatches = [];
$sBlockClass = "DisplayBlock"; $sBlockClass = "DisplayBlock";
$bAsynchronous = false; $bAsynchronous = false;
$sBlockType = 'list'; $sBlockType = 'list';
@@ -520,25 +515,28 @@ class DisplayBlock
return new $sBlockClass($oFilter, $sBlockType, $bAsynchronous, $aParams); 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)); $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)); $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 = new UIContentBlock($sId);
$oHtml->AddCSSClass("display_block"); $oHtml->AddCSSClass("display_block");
$aExtraParams = array_merge($aExtraParams, $this->m_aParams); $aExtraParams = array_merge($aExtraParams, $this->m_aParams);
$aExtraParams['currentId'] = $sId; $aExtraParams['currentId'] = $sId;
$sExtraParams = addslashes(str_replace('"', "'", $sExtraParams = addslashes(str_replace(
json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them '"',
"'",
json_encode($aExtraParams)
)); // JSON encode, change the style of the quotes and escape them
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params']; $aQueryParams = $aExtraParams['query_params'];
@@ -547,9 +545,9 @@ class DisplayBlock
$sClass = $aExtraParams['this->class']; $sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id']; $iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey); $oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj); $aQueryParams = ['this->object()' => $oObj];
} else { } else {
$aQueryParams = array(); $aQueryParams = [];
} }
} }
@@ -585,8 +583,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)); $listJsonExtraParams = json_encode(json_encode($aExtraParams));
$oPage->add_ready_script(" $oPage->add_ready_script("
$('#$sId').data('sExtraParams', ".$listJsonExtraParams."); $('#$sId').data('sExtraParams', ".$listJsonExtraParams.");
@@ -606,7 +603,7 @@ class DisplayBlock
* @throws \DictExceptionMissingString * @throws \DictExceptionMissingString
* @throws \MySQLException * @throws \MySQLException
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
if (!isset($aExtraParams['currentId'])) { if (!isset($aExtraParams['currentId'])) {
$sId = utils::GetUniqueId(); // Works only if the page is not an Ajax one ! $sId = utils::GetUniqueId(); // Works only if the page is not an Ajax one !
@@ -638,7 +635,7 @@ class DisplayBlock
$this->CheckParams($this->m_sStyle, $aExtraParams); $this->CheckParams($this->m_sStyle, $aExtraParams);
// Add the extra params into the filter if they make sense for such a filter // Add the extra params into the filter if they make sense for such a filter
$bDoSearch = utils::ReadParam('dosearch', false); $bDoSearch = utils::ReadParam('dosearch', false);
$aQueryParams = array(); $aQueryParams = [];
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params']; $aQueryParams = $aExtraParams['query_params'];
} else { } else {
@@ -646,7 +643,7 @@ class DisplayBlock
$sClass = $aExtraParams['this->class']; $sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id']; $iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey); $oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj); $aQueryParams = ['this->object()' => $oObj];
} }
} }
if ($this->m_oSet == null) { if ($this->m_oSet == null) {
@@ -656,7 +653,7 @@ class DisplayBlock
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sClass = $this->m_oFilter->GetClass(); $sClass = $this->m_oFilter->GetClass();
$aFilterCodes = MetaModel::GetFiltersList($sClass); $aFilterCodes = MetaModel::GetFiltersList($sClass);
$aCallSpec = array($sClass, 'MapContextParam'); $aCallSpec = [$sClass, 'MapContextParam'];
if (is_callable($aCallSpec)) { if (is_callable($aCallSpec)) {
foreach ($oAppContext->GetNames() as $sContextParam) { foreach ($oAppContext->GetNames() as $sContextParam) {
$sParamCode = call_user_func($aCallSpec, $sContextParam); //Map context parameter to the value/filter code depending on the class $sParamCode = call_user_func($aCallSpec, $sContextParam); //Map context parameter to the value/filter code depending on the class
@@ -691,11 +688,9 @@ class DisplayBlock
} }
} }
if (!is_null($condition)) if (!is_null($condition)) {
{
$sOpCode = null; // default operator $sOpCode = null; // default operator
if (is_array($condition)) if (is_array($condition)) {
{
// Multiple values, add them as AND X IN (v1, v2, v3...) // Multiple values, add them as AND X IN (v1, v2, v3...)
$sOpCode = 'IN'; $sOpCode = 'IN';
} }
@@ -703,26 +698,22 @@ class DisplayBlock
$this->AddCondition($sFilterCode, $condition, $sOpCode, $bParseSearchString); $this->AddCondition($sFilterCode, $condition, $sOpCode, $bParseSearchString);
} }
} }
if ($bDoSearch) if ($bDoSearch) {
{
// Keep the table_id identifying this table if we're performing a search // 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); $sTableId = utils::ReadParam('_table_id_', null, false, utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
if ($sTableId != null) if ($sTableId != null) {
{
$aExtraParams['table_id'] = $sTableId; $aExtraParams['table_id'] = $sTableId;
} }
} }
} }
$aOrderBy = array(); $aOrderBy = [];
if (isset($aExtraParams['order_by'])) if (isset($aExtraParams['order_by'])) {
{
// Convert the string describing the order_by parameter into an array // Convert the string describing the order_by parameter into an array
// The syntax is +attCode1,-attCode2 // The syntax is +attCode1,-attCode2
// attCode1 => ascending, attCode2 => descending // attCode1 => ascending, attCode2 => descending
$aTemp = explode(',', $aExtraParams['order_by']); $aTemp = explode(',', $aExtraParams['order_by']);
foreach($aTemp as $sTemp) foreach ($aTemp as $sTemp) {
{ $aMatches = [];
$aMatches = array();
if (preg_match('/^([+-])?(.+)$/', $sTemp, $aMatches)) { if (preg_match('/^([+-])?(.+)$/', $sTemp, $aMatches)) {
$bAscending = true; $bAscending = true;
if ($aMatches[1] == '-') { if ($aMatches[1] == '-') {
@@ -738,7 +729,7 @@ class DisplayBlock
} }
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData); $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_SEARCH:
case static::ENUM_STYLE_LIST: case static::ENUM_STYLE_LIST:
break; break;
@@ -768,7 +759,7 @@ class DisplayBlock
case static::ENUM_STYLE_LIST: case static::ENUM_STYLE_LIST:
case static::ENUM_STYLE_LIST_IN_OBJECT: case static::ENUM_STYLE_LIST_IN_OBJECT:
$oBlock = $this->RenderList($aExtraParams, $oPage); $oBlock = $this->RenderList($aExtraParams, $oPage);
break; break;
case 'links': case 'links':
$oBlock = $this->RenderLinks($oPage, $aExtraParams); $oBlock = $this->RenderLinks($oPage, $aExtraParams);
@@ -793,53 +784,45 @@ class DisplayBlock
case static::ENUM_STYLE_CHART: case static::ENUM_STYLE_CHART:
$oBlock = $this->RenderChart($sId, $aQueryParams, $aExtraParams); $oBlock = $this->RenderChart($sId, $aQueryParams, $aExtraParams);
break; break;
case static::ENUM_STYLE_CHART_AJAX: case static::ENUM_STYLE_CHART_AJAX:
$oBlock = $this->RenderChartAjax($aExtraParams); $oBlock = $this->RenderChartAjax($aExtraParams);
break; break;
default: default:
// Unsupported style, do nothing. // Unsupported style, do nothing.
$sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle); $sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
} }
$bAutoReload = false; $bAutoReload = false;
if (isset($aExtraParams['auto_reload'])) if (isset($aExtraParams['auto_reload'])) {
{ if ($aExtraParams['auto_reload'] === true) {
if ($aExtraParams['auto_reload'] === true)
{
// Note: does not work in the switch (case true) because a positive number evaluates to true!!! // Note: does not work in the switch (case true) because a positive number evaluates to true!!!
$aExtraParams['auto_reload'] = 'standard'; $aExtraParams['auto_reload'] = 'standard';
} }
switch($aExtraParams['auto_reload']) switch ($aExtraParams['auto_reload']) {
{
case 'fast': case 'fast':
$bAutoReload = true; $bAutoReload = true;
$iReloadInterval = MetaModel::GetConfig()->GetFastReloadInterval()*1000; $iReloadInterval = MetaModel::GetConfig()->GetFastReloadInterval() * 1000;
break; break;
case 'standard': case 'standard':
case 'true': case 'true':
$bAutoReload = true; $bAutoReload = true;
$iReloadInterval = MetaModel::GetConfig()->GetStandardReloadInterval()*1000; $iReloadInterval = MetaModel::GetConfig()->GetStandardReloadInterval() * 1000;
break; break;
default: default:
if (is_numeric($aExtraParams['auto_reload']) && ($aExtraParams['auto_reload'] > 0)) if (is_numeric($aExtraParams['auto_reload']) && ($aExtraParams['auto_reload'] > 0)) {
{
$bAutoReload = true; $bAutoReload = true;
$iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload'])*1000; $iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload']) * 1000;
} } else {
else
{
// incorrect config, ignore it // incorrect config, ignore it
$bAutoReload = false; $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 // Used either for asynchronous or auto_reload
// does a json_encode twice to get a string usable as function parameter // does a json_encode twice to get a string usable as function parameter
$sFilterBefore = $this->m_oFilter->serialize(); $sFilterBefore = $this->m_oFilter->serialize();
@@ -886,8 +869,7 @@ JS
{ {
// Workaround to an issue revealed whenever a condition on org_id is applied twice (with a hierarchy of organizations) // 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 // 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 // Skip
return; return;
} }
@@ -895,59 +877,48 @@ JS
$sClass = $this->m_oFilter->GetClass(); $sClass = $this->m_oFilter->GetClass();
$bConditionAdded = false; $bConditionAdded = false;
// If the condition is an external key with a class having a hierarchy, use a "below" criteria // 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); $oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
if ($oAttDef->IsExternalKey()) if ($oAttDef->IsExternalKey()) {
{
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass()); $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
if ($sHierarchicalKeyCode !== false) if ($sHierarchicalKeyCode !== false) {
{
$oFilter = new DBObjectSearch($oAttDef->GetTargetClass()); $oFilter = new DBObjectSearch($oAttDef->GetTargetClass());
if (($sOpCode == 'IN') && is_array($condition)) if (($sOpCode == 'IN') && is_array($condition)) {
{ $oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
$oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition)); } else {
}
else
{
$oFilter->AddCondition('id', $condition); $oFilter->AddCondition('id', $condition);
} }
$oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass()); $oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default $oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
$this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode); $this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode);
$bConditionAdded = true; $bConditionAdded = true;
} } elseif (($sOpCode == 'IN') && is_array($condition)) {
else if (($sOpCode == 'IN') && is_array($condition))
{
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition)); $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true; $bConditionAdded = true;
} }
} } elseif (($sOpCode == 'IN') && is_array($condition)) {
else if (($sOpCode == 'IN') && is_array($condition))
{
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition)); $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true; $bConditionAdded = true;
} }
} }
// In all other cases, just add the condition directly // 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 $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)).')'; $sListExpr = '('.implode(', ', CMDBSource::Quote($condition)).')';
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr"; $sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition); $oNewCondition = Expression::FromOQL($sOQLCondition);
return $oNewCondition; return $oNewCondition;
} }
/** /**
@@ -974,13 +945,10 @@ JS
protected function MakeGroupByQuery(&$aExtraParams, &$oGroupByExp, &$sGroupByLabel, &$aGroupBy, &$sAggregationFunction, &$sFctVar, &$sAggregationAttr, &$sSql) protected function MakeGroupByQuery(&$aExtraParams, &$oGroupByExp, &$sGroupByLabel, &$aGroupBy, &$sAggregationFunction, &$sFctVar, &$sAggregationAttr, &$sSql)
{ {
$sAlias = $this->m_oFilter->GetClassAlias(); $sAlias = $this->m_oFilter->GetClassAlias();
if (isset($aExtraParams['group_by_label'])) if (isset($aExtraParams['group_by_label'])) {
{
$oGroupByExp = Expression::FromOQL($aExtraParams['group_by']); $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
$sGroupByLabel = $aExtraParams['group_by_label']; $sGroupByLabel = $aExtraParams['group_by_label'];
} } else {
else
{
// Backward compatibility: group_by is simply a field id // Backward compatibility: group_by is simply a field id
$oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias); $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
$sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']); $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
@@ -988,61 +956,52 @@ JS
// Security filtering // Security filtering
$aFields = $oGroupByExp->ListRequiredFields(); $aFields = $oGroupByExp->ListRequiredFields();
foreach($aFields as $sFieldAlias) foreach ($aFields as $sFieldAlias) {
{ $aMatches = [];
$aMatches = array(); if (preg_match('/^([^.]+)\\.([^.]+)$/', $sFieldAlias, $aMatches)) {
if (preg_match('/^([^.]+)\\.([^.]+)$/', $sFieldAlias, $aMatches))
{
$sFieldClass = $this->m_oFilter->GetClassName($aMatches[1]); $sFieldClass = $this->m_oFilter->GetClassName($aMatches[1]);
$oAttDef = MetaModel::GetAttributeDef($sFieldClass, $aMatches[2]); $oAttDef = MetaModel::GetAttributeDef($sFieldClass, $aMatches[2]);
if ($oAttDef instanceof AttributeOneWayPassword) if ($oAttDef instanceof AttributeOneWayPassword) {
{
throw new Exception('Grouping on password fields is not supported.'); throw new Exception('Grouping on password fields is not supported.');
} }
} }
} }
$aGroupBy = array(); $aGroupBy = [];
$aGroupBy['grouped_by_1'] = $oGroupByExp; $aGroupBy['grouped_by_1'] = $oGroupByExp;
$aQueryParams = array(); $aQueryParams = [];
if (isset($aExtraParams['query_params'])) if (isset($aExtraParams['query_params'])) {
{
$aQueryParams = $aExtraParams['query_params']; $aQueryParams = $aExtraParams['query_params'];
} }
$aFunctions = array(); $aFunctions = [];
$sAggregationFunction = 'count'; $sAggregationFunction = 'count';
$sFctVar = '_itop_count_'; $sFctVar = '_itop_count_';
$sAggregationAttr = ''; $sAggregationAttr = '';
if (isset($aExtraParams['aggregation_function']) && !empty($aExtraParams['aggregation_attribute'])) if (isset($aExtraParams['aggregation_function']) && !empty($aExtraParams['aggregation_attribute'])) {
{
$sAggregationFunction = $aExtraParams['aggregation_function']; $sAggregationFunction = $aExtraParams['aggregation_function'];
$sAggregationAttr = $aExtraParams['aggregation_attribute']; $sAggregationAttr = $aExtraParams['aggregation_attribute'];
$oAttrExpr = Expression::FromOQL('`'.$sAlias.'`.`'.$sAggregationAttr.'`'); $oAttrExpr = Expression::FromOQL('`'.$sAlias.'`.`'.$sAggregationAttr.'`');
$oFctExpr = new FunctionExpression(strtoupper($sAggregationFunction), array($oAttrExpr)); $oFctExpr = new FunctionExpression(strtoupper($sAggregationFunction), [$oAttrExpr]);
$sFctVar = '_itop_'.$sAggregationFunction.'_'; $sFctVar = '_itop_'.$sAggregationFunction.'_';
$aFunctions = array($sFctVar => $oFctExpr); $aFunctions = [$sFctVar => $oFctExpr];
} }
if (!empty($sAggregationAttr)) if (!empty($sAggregationAttr)) {
{
$sClass = $this->m_oFilter->GetClass(); $sClass = $this->m_oFilter->GetClass();
$sAggregationAttr = MetaModel::GetLabel($sClass, $sAggregationAttr); $sAggregationAttr = MetaModel::GetLabel($sClass, $sAggregationAttr);
} }
$iLimit = 0; $iLimit = 0;
if (isset($aExtraParams['limit'])) if (isset($aExtraParams['limit'])) {
{
$iLimit = intval($aExtraParams['limit']); $iLimit = intval($aExtraParams['limit']);
} }
$aOrderBy = array(); $aOrderBy = [];
if (isset($aExtraParams['order_direction']) && isset($aExtraParams['order_by'])) if (isset($aExtraParams['order_direction']) && isset($aExtraParams['order_by'])) {
{ switch ($aExtraParams['order_by']) {
switch ($aExtraParams['order_by'])
{
case 'attribute': case 'attribute':
$aOrderBy = array('grouped_by_1' => ($aExtraParams['order_direction'] === 'asc')); $aOrderBy = ['grouped_by_1' => ($aExtraParams['order_direction'] === 'asc')];
break; break;
case 'function': case 'function':
$aOrderBy = array($sFctVar => ($aExtraParams['order_direction'] === 'asc')); $aOrderBy = [$sFctVar => ($aExtraParams['order_direction'] === 'asc')];
break; break;
} }
} }
@@ -1078,31 +1037,31 @@ JS
$this->AddCondition($sFilterCode, $sContextParamValue); $this->AddCondition($sFilterCode, $sContextParamValue);
} }
} }
$aQueryParams = array(); $aQueryParams = [];
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $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); $this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
} }
// Summary details // Summary details
$aCounts = array(); $aCounts = [];
$aStateLabels = array(); $aStateLabels = [];
if (!empty($sStateAttrCode) && !empty($sStatesList)) { if (!empty($sStateAttrCode) && !empty($sStatesList)) {
$aStates = explode(',', $sStatesList); $aStates = explode(',', $sStatesList);
// Generate one count + group by query [#1330] // Generate one count + group by query [#1330]
$sClassAlias = $this->m_oFilter->GetClassAlias(); $sClassAlias = $this->m_oFilter->GetClassAlias();
$oGroupByExpr = Expression::FromOQL($sClassAlias.'.'.$sStateAttrCode); $oGroupByExpr = Expression::FromOQL($sClassAlias.'.'.$sStateAttrCode);
$aGroupBy = array('group1' => $oGroupByExpr); $aGroupBy = ['group1' => $oGroupByExpr];
$oGroupBySearch = $this->m_oFilter->DeepClone(); $oGroupBySearch = $this->m_oFilter->DeepClone();
if (isset($this->m_bShowObsoleteData)) { if (isset($this->m_bShowObsoleteData)) {
$oGroupBySearch->SetShowObsoleteData($this->m_bShowObsoleteData); $oGroupBySearch->SetShowObsoleteData($this->m_bShowObsoleteData);
} }
$sCountGroupByQuery = $oGroupBySearch->MakeGroupByQuery($aQueryParams, $aGroupBy, false); $sCountGroupByQuery = $oGroupBySearch->MakeGroupByQuery($aQueryParams, $aGroupBy, false);
$aCountGroupByResults = CMDBSource::QueryToArray($sCountGroupByQuery); $aCountGroupByResults = CMDBSource::QueryToArray($sCountGroupByQuery);
$aCountsQueryResults = array(); $aCountsQueryResults = [];
foreach ($aCountGroupByResults as $aCountGroupBySingleResult) { foreach ($aCountGroupByResults as $aCountGroupBySingleResult) {
$aCountsQueryResults[$aCountGroupBySingleResult[0]] = $aCountGroupBySingleResult[1]; $aCountsQueryResults[$aCountGroupBySingleResult[0]] = $aCountGroupBySingleResult[1];
} }
@@ -1116,7 +1075,8 @@ JS
: 0; : 0;
if ($aCounts[$sStateValue] == 0) { if ($aCounts[$sStateValue] == 0) {
$aCounts[$sStateValue] = ['link' => '-', 'label' => $aCounts[$sStateValue]];; $aCounts[$sStateValue] = ['link' => '-', 'label' => $aCounts[$sStateValue]];
;
} else { } else {
$oSingleGroupByValueFilter = $this->m_oFilter->DeepClone(); $oSingleGroupByValueFilter = $this->m_oFilter->DeepClone();
$oSingleGroupByValueFilter->AddCondition($sStateAttrCode, $sStateValue, '='); $oSingleGroupByValueFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
@@ -1166,7 +1126,7 @@ JS
$oBlock->AddSubBlock($oPill); $oBlock->AddSubBlock($oPill);
} }
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams(); $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->class'] = get_class($aExtraParams['query_params']['this->object()']);
$aExtraParams['query_params']['this->id'] = $aExtraParams['query_params']['this->object()']->GetKey(); $aExtraParams['query_params']['this->id'] = $aExtraParams['query_params']['this->object()']->GetKey();
unset($aExtraParams['query_params']['this->object()']); unset($aExtraParams['query_params']['this->object()']);
@@ -1180,7 +1140,8 @@ JS
$('#".$oBlock->GetId()."').html(data); $('#".$oBlock->GetId()."').html(data);
$('#".$oBlock->GetId()."').unblock(); $('#".$oBlock->GetId()."').unblock();
}); });
$('#".$oBlock->GetId()."').unblock();"); $('#".$oBlock->GetId()."').unblock();"
);
return $oBlock; return $oBlock;
} }
@@ -1190,7 +1151,7 @@ JS
* *
* @return string[] * @return string[]
*/ */
protected function GetAllowedActionsParams(array $aExtraParams) protected function GetAllowedActionsParams(array $aExtraParams)
{ {
return [ return [
'context_filter', /** int if != 0 filter with user context */ 'context_filter', /** int if != 0 filter with user context */
@@ -1222,11 +1183,11 @@ JS
$this->AddCondition($sFilterCode, $sContextParamValue); $this->AddCondition($sFilterCode, $sContextParamValue);
} }
} }
$aQueryParams = array(); $aQueryParams = [];
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $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); $this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
} }
$iCount = $this->m_oSet->Count(); $iCount = $this->m_oSet->Count();
@@ -1243,8 +1204,15 @@ JS
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) { if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
$sCreateActionUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class='.$sClass.$oAppContext->GetForLink(true); $sCreateActionUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class='.$sClass.$oAppContext->GetForLink(true);
$sCreateActionLabel = Dict::Format('UI:Button:Create'); $sCreateActionLabel = Dict::Format('UI:Button:Create');
$oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, $sCreateActionUrl, $oBlock = DashletFactory::MakeForDashletBadge(
$sCreateActionLabel, $aRefreshParams); $sClassIconUrl,
$sHyperlink,
$iCount,
$sClassLabel,
$sCreateActionUrl,
$sCreateActionLabel,
$aRefreshParams
);
} else { } else {
$oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, null, null, $aRefreshParams); $oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, null, null, $aRefreshParams);
} }
@@ -1274,9 +1242,9 @@ JS
$aRes = CMDBSource::QueryToArray($sSql); $aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array(); $aGroupBy = [];
$aLabels = array(); $aLabels = [];
$aValues = array(); $aValues = [];
$iTotalCount = 0; $iTotalCount = 0;
foreach ($aRes as $iRow => $aRow) { foreach ($aRes as $iRow => $aRow) {
$sValue = $aRow['grouped_by_1']; $sValue = $aRow['grouped_by_1'];
@@ -1287,7 +1255,7 @@ JS
$iTotalCount += $aRow['_itop_count_']; $iTotalCount += $aRow['_itop_count_'];
} }
$aData = array(); $aData = [];
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink(true); $sParams = $oAppContext->GetForLink(true);
foreach ($aGroupBy as $iRow => $iCount) { foreach ($aGroupBy as $iRow => $iCount) {
@@ -1298,22 +1266,22 @@ JS
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params']; $aQueryParams = $aExtraParams['query_params'];
} else { } else {
$aQueryParams = array(); $aQueryParams = [];
} }
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams)); $sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
$aData[] = array( $aData[] = [
'group' => $aLabels[$iRow], 'group' => $aLabels[$iRow],
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1$sParams&filter=$sFilter\">$iCount</a>" 'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1$sParams&filter=$sFilter\">$iCount</a>",
); // TO DO: add the context information ]; // TO DO: add the context information
} }
$aAttribs = array( $aAttribs = [
'group' => array('label' => $sGroupByLabel, 'description' => ''), 'group' => ['label' => $sGroupByLabel, 'description' => ''],
'value' => array( 'value' => [
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction), 'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr), 'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
), ],
); ];
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection'; $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams(); $aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
@@ -1324,7 +1292,7 @@ JS
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]); $oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
$oBlock->AddSubTitleBlock(new Html($sTitle)); $oBlock->AddSubTitleBlock(new Html($sTitle));
$oBlock->AddCSSClass('ibo-datatable-panel'); $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"]); $oBlock->SetIcon($aExtraParams["panel_icon"]);
} }
$oDataTable = DataTableUIBlockFactory::MakeForStaticData("", $aAttribs, $aData, null, $aExtraParams, $this->m_oFilter->ToOQL(), $aOption); $oDataTable = DataTableUIBlockFactory::MakeForStaticData("", $aAttribs, $aData, null, $aExtraParams, $this->m_oFilter->ToOQL(), $aOption);
@@ -1343,7 +1311,7 @@ JS
} }
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) { if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]); $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->SetIcon($aExtraParams["panel_icon"]);
} }
$oBlock->AddSubBlock(new Html('<p>'.Dict::Format($sFormat, $iCount).'</p>')); $oBlock->AddSubBlock(new Html('<p>'.Dict::Format($sFormat, $iCount).'</p>'));
@@ -1353,7 +1321,7 @@ JS
} }
return $oBlock; return $oBlock;
} }
/** /**
* @param WebPage $oPage * @param WebPage $oPage
@@ -1411,7 +1379,6 @@ JS
$oBlock->aExtraParams = $aExtraParams; $oBlock->aExtraParams = $aExtraParams;
$oBlock->sFilter = $this->m_oFilter->ToOQL(); $oBlock->sFilter = $this->m_oFilter->ToOQL();
// Check the classes that can be read (i.e authorized) by this user... // Check the classes that can be read (i.e authorized) by this user...
foreach ($aClasses as $sAlias => $sClassName) { foreach ($aClasses as $sAlias => $sClassName) {
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) { if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) {
@@ -1433,7 +1400,7 @@ JS
$sSearchFilter = $this->m_oSet->GetFilter()->serialize(); $sSearchFilter = $this->m_oSet->GetFilter()->serialize();
// Limit the size of the URL (N°1585 - request uri too long) // Limit the size of the URL (N°1585 - request uri too long)
if (strlen($sSearchFilter) < SERVER_MAX_URL_LENGTH) { if (strlen($sSearchFilter) < SERVER_MAX_URL_LENGTH) {
$oBlock->sEventAttachedData = json_encode(array( $oBlock->sEventAttachedData = json_encode([
'filter' => $sSearchFilter, 'filter' => $sSearchFilter,
'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(), 'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(),
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()), 'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
@@ -1441,7 +1408,7 @@ JS
'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(), 'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(),
'breadcrumb_icon' => 'fas fa-search', 'breadcrumb_icon' => 'fas fa-search',
'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES, 'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES,
)); ]);
} }
} }
@@ -1474,25 +1441,25 @@ JS
$oContentBlock = new UIContentBlock(); $oContentBlock = new UIContentBlock();
$oHtml = new Html(); $oHtml = new Html();
$oContentBlock->AddSubBlock($oHtml); $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'])) { if (!isset($aExtraParams['group_by'])) {
$oHtml->AddHtml('<p>'.Dict::S('UI:Error:MandatoryTemplateParameter_group_by').'</p>'); $oHtml->AddHtml('<p>'.Dict::S('UI:Error:MandatoryTemplateParameter_group_by').'</p>');
} else { } else {
$aGroupByFields = array(); $aGroupByFields = [];
$aGroupBy = explode(',', $aExtraParams['group_by']); $aGroupBy = explode(',', $aExtraParams['group_by']);
foreach ($aGroupBy as $sGroupBy) { foreach ($aGroupBy as $sGroupBy) {
$aMatches = array(); $aMatches = [];
if (preg_match('/^(.+)\.(.+)$/', $sGroupBy, $aMatches) > 0) { 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) { if (count($aGroupByFields) == 0) {
$oHtml->AddHtml('<p>'.Dict::Format('UI:Error:InvalidGroupByFields', $aExtraParams['group_by']).'</p>'); $oHtml->AddHtml('<p>'.Dict::Format('UI:Error:InvalidGroupByFields', $aExtraParams['group_by']).'</p>');
} else { } else {
$aResults = array(); $aResults = [];
$aCriteria = array(); $aCriteria = [];
while ($aObjects = $this->m_oSet->FetchAssoc()) { while ($aObjects = $this->m_oSet->FetchAssoc()) {
$aKeys = array(); $aKeys = [];
foreach ($aGroupByFields as $aField) { foreach ($aGroupByFields as $aField) {
$sAlias = $aField['alias']; $sAlias = $aField['alias'];
if (is_null($aObjects[$sAlias])) { if (is_null($aObjects[$sAlias])) {
@@ -1509,7 +1476,7 @@ JS
$oHtml->AddHtml("<table>\n"); $oHtml->AddHtml("<table>\n");
// Construct a new (parametric) query that will return the content of this block // Construct a new (parametric) query that will return the content of this block
$oBlockFilter = $this->m_oFilter->DeepClone(); $oBlockFilter = $this->m_oFilter->DeepClone();
$aExpressions = array(); $aExpressions = [];
$index = 0; $index = 0;
foreach ($aGroupByFields as $aField) { foreach ($aGroupByFields as $aField) {
$aExpressions[] = '`'.$aField['alias'].'`.`'.$aField['att_code'].'` = :param'.$index++; $aExpressions[] = '`'.$aField['alias'].'`.`'.$aField['att_code'].'` = :param'.$index++;
@@ -1521,7 +1488,7 @@ JS
foreach ($aResults as $sCategory => $aObjects) { foreach ($aResults as $sCategory => $aObjects) {
$oHtml->AddHtml("<tr><td><h1>$sCategory</h1></td></tr>\n"); $oHtml->AddHtml("<tr><td><h1>$sCategory</h1></td></tr>\n");
if (count($aDisplayAliases) == 1) { if (count($aDisplayAliases) == 1) {
$aSimpleArray = array(); $aSimpleArray = [];
foreach ($aObjects as $aRow) { foreach ($aObjects as $aRow) {
$oObj = $aRow[$aDisplayAliases[0]]; $oObj = $aRow[$aDisplayAliases[0]];
if (!is_null($oObj)) { if (!is_null($oObj)) {
@@ -1537,12 +1504,12 @@ JS
$oHtml->AddHtml("</td></tr>\n"); $oHtml->AddHtml("</td></tr>\n");
} else { } else {
$index = 0; $index = 0;
$aArgs = array(); $aArgs = [];
foreach ($aGroupByFields as $aField) { foreach ($aGroupByFields as $aField) {
$aArgs['param'.$index] = $aCriteria[$sCategory][$aField['alias'].'.'.$aField['att_code']]; $aArgs['param'.$index] = $aCriteria[$sCategory][$aField['alias'].'.'.$aField['att_code']];
$index++; $index++;
} }
$oSet = new CMDBObjectSet($oBlockFilter, array(), $aArgs); $oSet = new CMDBObjectSet($oBlockFilter, [], $aArgs);
if (empty($aExtraParams['currentId'])) { if (empty($aExtraParams['currentId'])) {
$iListId = utils::GetUniqueId(); // Works only if not in an Ajax page !! $iListId = utils::GetUniqueId(); // Works only if not in an Ajax page !!
} else { } else {
@@ -1603,8 +1570,10 @@ JS
$sDefaults .= '&'.urlencode($sName).'='.urlencode($sValue); $sDefaults .= '&'.urlencode($sName).'='.urlencode($sValue);
} }
} }
$oBlock->AddHtml("<p><a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=modify_links&class=$sClass&sParams&link_attr=".$aExtraParams['link_attr']."&id=".$aExtraParams['object_id']."&target_class=$sTargetClass&addObjects=true$sDefaults\">".Dict::Format('UI:ClickToCreateNew', $oBlock->AddHtml("<p><a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=modify_links&class=$sClass&sParams&link_attr=".$aExtraParams['link_attr']."&id=".$aExtraParams['object_id']."&target_class=$sTargetClass&addObjects=true$sDefaults\">".Dict::Format(
Metamodel::GetName($sClass))."</a></p>\n"); 'UI:ClickToCreateNew',
Metamodel::GetName($sClass)
)."</a></p>\n");
} }
} }
} }
@@ -1653,7 +1622,7 @@ JS
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) { if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]); $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->SetIcon($aExtraParams["panel_icon"]);
} }
$oPanel->AddSubBlock($oBlock); $oPanel->AddSubBlock($oBlock);
@@ -1677,7 +1646,7 @@ JS
{ {
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie'; $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$sId = utils::ReadParam('id', ''); $sId = utils::ReadParam('id', '');
$aValues = array(); $aValues = [];
$oBlock = null; $oBlock = null;
$sJSURLs = ''; $sJSURLs = '';
@@ -1688,21 +1657,18 @@ JS
$this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql); $this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql);
$aRes = CMDBSource::QueryToArray($sSql); $aRes = CMDBSource::QueryToArray($sSql);
$iTotalCount = 0; $iTotalCount = 0;
$aURLs = array(); $aURLs = [];
foreach ($aRes as $iRow => $aRow) { foreach ($aRes as $iRow => $aRow) {
$sValue = $aRow['grouped_by_1']; $sValue = $aRow['grouped_by_1'];
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue); $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
$iTotalCount += $aRow['_itop_count_']; $iTotalCount += $aRow['_itop_count_'];
$aValues[] = array( $aValues[] = [
'label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'), 'label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'),
'label_html' => $sHtmlValue, 'label_html' => $sHtmlValue,
'value' => (float)$aRow[$sFctVar], 'value' => (float)$aRow[$sFctVar],
); ];
// Build the search for this subset // Build the search for this subset
$oSubsetSearch = $this->m_oFilter->DeepClone(); $oSubsetSearch = $this->m_oFilter->DeepClone();
@@ -1741,7 +1707,7 @@ JS
$aColumns = []; $aColumns = [];
$aNames = []; $aNames = [];
foreach ($aValues as $idx => $aValue) { foreach ($aValues as $idx => $aValue) {
$aColumns[] = array('series_'.$idx, (float)$aValue['value']); $aColumns[] = ['series_'.$idx, (float)$aValue['value']];
$aNames['series_'.$idx] = $aValue['label']; $aNames['series_'.$idx] = $aValue['label'];
} }
@@ -1763,7 +1729,7 @@ JS
} }
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) { if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]); $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->SetIcon($aExtraParams["panel_icon"]);
} }
$oPanel->AddSubBlock($oBlock); $oPanel->AddSubBlock($oBlock);
@@ -1790,12 +1756,12 @@ JS
$oBlock->sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($oBlock->sCsvFile); $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'; $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 // Pass the parameters via POST, since expression may be very long
$aParamsToPost = array( $aParamsToPost = [
'expression' => $this->m_oFilter->ToOQL(true), 'expression' => $this->m_oFilter->ToOQL(true),
'format' => 'csv', 'format' => 'csv',
'filename' => $oBlock->sCsvFile, 'filename' => $oBlock->sCsvFile,
'charset' => 'UTF-8', 'charset' => 'UTF-8',
); ];
if ($oBlock->bAdvancedMode) { if ($oBlock->bAdvancedMode) {
$oBlock->sDownloadLink .= '&fields_advanced=1'; $oBlock->sDownloadLink .= '&fields_advanced=1';
$aParamsToPost['fields_advanced'] = 1; $aParamsToPost['fields_advanced'] = 1;
@@ -1854,8 +1820,7 @@ class MenuBlock extends DisplayBlock
$oRouter = Router::GetInstance(); $oRouter = Router::GetInstance();
$oRenderBlock = new UIContentBlock(); $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; $this->m_sStyle = static::ENUM_STYLE_LIST;
} }
@@ -1890,7 +1855,6 @@ class MenuBlock extends DisplayBlock
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true); $sContext = $oAppContext->GetForLink(true);
$sFilter = $this->GetFilter()->serialize(); $sFilter = $this->GetFilter()->serialize();
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass); $sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass);
$sRootUrl = utils::GetAbsoluteUrlAppRoot(); $sRootUrl = utils::GetAbsoluteUrlAppRoot();
@@ -1948,7 +1912,7 @@ class MenuBlock extends DisplayBlock
$iLimit = MetaModel::GetConfig()->Get('complex_actions_limit'); $iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
if ( if (
($iSetCount > 0) && (false === $bLocked) && MetaModel::HasLifecycle($sClass) && ($iSetCount > 0) && (false === $bLocked) && MetaModel::HasLifecycle($sClass) &&
( ($iLimit == 0) || ($iSetCount < $iLimit) ) (($iLimit == 0) || ($iSetCount < $iLimit))
) { ) {
$aTransitions = []; $aTransitions = [];
// Processing (optimizations) and endpoints are not exactly the same depending on if there is only 1 object or a set // Processing (optimizations) and endpoints are not exactly the same depending on if there is only 1 object or a set
@@ -1968,8 +1932,8 @@ class MenuBlock extends DisplayBlock
// Life cycle actions may be available... if all objects are in the same state // Life cycle actions may be available... if all objects are in the same state
// Group by <state> // Group by <state>
$oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias()); $oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias());
$aGroupBy = array('__state__' => $oGroupByExp); $aGroupBy = ['__state__' => $oGroupByExp];
$aQueryParams = array(); $aQueryParams = [];
if (isset($aExtraParams['query_params'])) { if (isset($aExtraParams['query_params'])) {
$aQueryParams = $aExtraParams['query_params']; $aQueryParams = $aExtraParams['query_params'];
} }
@@ -2001,10 +1965,10 @@ class MenuBlock extends DisplayBlock
switch ($iActionAllowed) { switch ($iActionAllowed) {
case UR_ALLOWED_YES: case UR_ALLOWED_YES:
case UR_ALLOWED_DEPENDS: case UR_ALLOWED_DEPENDS:
$aTransitionActions[$sStimulusCode] = array( $aTransitionActions[$sStimulusCode] = [
'label' => $aStimuli[$sStimulusCode]->GetLabel(), 'label' => $aStimuli[$sStimulusCode]->GetLabel(),
'url' => "{$sRootUrl}pages/UI.php?stimulus=$sStimulusCode&class=$sLifecycleClass&{$sUrlQueryString}", 'url' => "{$sRootUrl}pages/UI.php?stimulus=$sStimulusCode&class=$sLifecycleClass&{$sUrlQueryString}",
) + $aActionParams; ] + $aActionParams;
break; break;
default: default:
@@ -2066,16 +2030,16 @@ class MenuBlock extends DisplayBlock
// Just one object in the set, possible actions are "new / clone / modify and delete" // Just one object in the set, possible actions are "new / clone / modify and delete"
if (!isset($aExtraParams['link_attr'])) { if (!isset($aExtraParams['link_attr'])) {
if ($bIsModifyAllowed) { if ($bIsModifyAllowed) {
$aRegularActions['UI:Menu:Modify'] = array( $aRegularActions['UI:Menu:Modify'] = [
'label' => Dict::S('UI:Menu:Modify'), 'label' => Dict::S('UI:Menu:Modify'),
'url' => $oRouter->GenerateUrl('object.modify', ['class' => $sClass, 'id' => $id]) . "{$sContext}#", 'url' => $oRouter->GenerateUrl('object.modify', ['class' => $sClass, 'id' => $id])."{$sContext}#",
) + $aActionParams; ] + $aActionParams;
} }
if ($bIsDeleteAllowed) { if ($bIsDeleteAllowed) {
$aRegularActions['UI:Menu:Delete'] = array( $aRegularActions['UI:Menu:Delete'] = [
'label' => Dict::S('UI:Menu:Delete'), 'label' => Dict::S('UI:Menu:Delete'),
'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$id{$sContext}", 'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$id{$sContext}",
) + $aActionParams; ] + $aActionParams;
} }
// Relations... // Relations...
@@ -2084,16 +2048,16 @@ class MenuBlock extends DisplayBlock
$this->AddMenuSeparator($aRegularActions); $this->AddMenuSeparator($aRegularActions);
foreach ($aRelations as $sRelationCode => $aRelationInfo) { foreach ($aRelations as $sRelationCode => $aRelationInfo) {
if (array_key_exists('down', $aRelationInfo)) { if (array_key_exists('down', $aRelationInfo)) {
$aRegularActions[$sRelationCode.'_down'] = array( $aRegularActions[$sRelationCode.'_down'] = [
'label' => $aRelationInfo['down'], 'label' => $aRelationInfo['down'],
'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}", 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}",
) + $aActionParams; ] + $aActionParams;
} }
if (array_key_exists('up', $aRelationInfo)) { if (array_key_exists('up', $aRelationInfo)) {
$aRegularActions[$sRelationCode.'_up'] = array( $aRegularActions[$sRelationCode.'_up'] = [
'label' => $aRelationInfo['up'], 'label' => $aRelationInfo['up'],
'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}", 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}",
) + $aActionParams; ] + $aActionParams;
} }
} }
} }
@@ -2105,7 +2069,7 @@ class MenuBlock extends DisplayBlock
$bCanKill = false; $bCanKill = false;
$oUser = UserRights::GetUserObject(); $oUser = UserRights::GetUserObject();
$aUserProfiles = array(); $aUserProfiles = [];
if (!is_null($oUser)) { if (!is_null($oUser)) {
$oProfileSet = $oUser->Get('profile_list'); $oProfileSet = $oUser->Get('profile_list');
while ($oProfile = $oProfileSet->Fetch()) { while ($oProfile = $oProfileSet->Fetch()) {
@@ -2127,10 +2091,10 @@ class MenuBlock extends DisplayBlock
if ($bCanKill) { if ($bCanKill) {
$this->AddMenuSeparator($aRegularActions); $this->AddMenuSeparator($aRegularActions);
$aRegularActions['concurrent_lock_unlock'] = array( $aRegularActions['concurrent_lock_unlock'] = [
'label' => Dict::S('UI:Menu:KillConcurrentLock'), 'label' => Dict::S('UI:Menu:KillConcurrentLock'),
'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}", 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}",
); ];
} }
} }
} }
@@ -2138,7 +2102,7 @@ class MenuBlock extends DisplayBlock
$this->AddMenuSeparator($aRegularActions); $this->AddMenuSeparator($aRegularActions);
$this->GetEnumAllowedActions($oSet, function ($sLabel, $data) use (&$aRegularActions, $aActionParams) { $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; break;
@@ -2474,13 +2438,11 @@ class MenuBlock extends DisplayBlock
protected function AddMenuSeparator(&$aActions) protected function AddMenuSeparator(&$aActions)
{ {
$sSeparator = '<hr class="menu-separator"/>'; $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); $aKeys = array_keys($aActions);
$sLastKey = array_pop($aKeys); $sLastKey = array_pop($aKeys);
if ($aActions[$sLastKey]['label'] != $sSeparator) // Make sure there are no 2 consecutive separators if ($aActions[$sLastKey]['label'] != $sSeparator) { // Make sure there are no 2 consecutive separators
{ $aActions['sep_'.(count($aActions) - 1)] = ['label' => $sSeparator, 'url' => ''];
$aActions['sep_'.(count($aActions)-1)] = array('label' => $sSeparator, 'url' => '');
} }
} }
} }
@@ -2540,10 +2502,10 @@ class MenuBlock extends DisplayBlock
*/ */
protected function AddBulkDeleteObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:BulkDelete', $sActionLabel = 'UI:Menu:BulkDelete') 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), 'label' => Dict::S($sActionLabel),
'url' => $this->PrepareUrlForStandardMenuAction($sClass, "operation=select_for_deletion&filter=".urlencode($sFilter)), 'url' => $this->PrepareUrlForStandardMenuAction($sClass, "operation=select_for_deletion&filter=".urlencode($sFilter)),
) + $this->GetDefaultParamsForMenuAction(); ] + $this->GetDefaultParamsForMenuAction();
} }
/** /**
@@ -2580,6 +2542,6 @@ class MenuBlock extends DisplayBlock
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true); $sContext = $oAppContext->GetForLink(true);
return $sUrl . $sContext; return $sUrl.$sContext;
} }
} }

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader');

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class BulkChangeException extends CoreException class BulkChangeException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class CSVParserException extends CoreException class CSVParserException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class ConfigException extends CoreException class ConfigException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -63,21 +64,20 @@ class CoreCannotSaveObjectException extends CoreException
public function getTextMessage() public function getTextMessage()
{ {
$sTitle = Dict::S('UI:Error:SaveFailed'); $sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = $sTitle; $sContent = $sTitle;
if (count($this->aIssues) == 1) { if (count($this->aIssues) == 1) {
$sIssue = reset($this->aIssues); $sIssue = reset($this->aIssues);
$sContent .= $sIssue; $sContent .= $sIssue;
} else { } else {
foreach ($this->aIssues as $sError) { foreach ($this->aIssues as $sError) {
$sContent .= " " . $sError . ", "; $sContent .= " ".$sError.", ";
} }
} }
return $sContent; return $sContent;
} }
public function getIssues() public function getIssues()
{ {
return $this->aIssues; return $this->aIssues;

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -35,10 +36,10 @@ class CoreException extends Exception
} }
if (count($this->m_aContextData) > 0) { if (count($this->m_aContextData) > 0) {
$sMessage .= ": "; $sMessage .= ": ";
$aContextItems = array(); $aContextItems = [];
foreach ($this->m_aContextData as $sKey => $value) { foreach ($this->m_aContextData as $sKey => $value) {
if (is_array($value)) { if (is_array($value)) {
$aPairs = array(); $aPairs = [];
foreach ($value as $key => $val) { foreach ($value as $key => $val) {
if (is_array($val)) { if (is_array($val)) {
$aPairs[] = $key.'=>('.implode(', ', $val).')'; $aPairs[] = $key.'=>('.implode(', ', $val).')';
@@ -109,4 +110,4 @@ class CoreException extends Exception
{ {
return $this->m_aContextData; return $this->m_aContextData;
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -9,5 +10,4 @@
*/ */
class CorePortalInvalidActionRuleException extends CoreException class CorePortalInvalidActionRuleException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -14,4 +15,4 @@ class CoreTemplateException extends CoreException
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage(); $sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
parent::__construct($sMessage, null, '', $oTwigException); parent::__construct($sMessage, null, '', $oTwigException);
} }
} }

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class DeleteException extends CoreException class DeleteException extends CoreException
{ {
} }

View File

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

View File

@@ -12,13 +12,13 @@ class InvalidExternalKeyValueException extends CoreUnexpectedValue
public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null) public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null)
{ {
$aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject) . '::' . $oObject->GetKey(); $aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject).'::'.$oObject->GetKey();
$aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode; $aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode;
$aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode); $aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode);
$oCurrentUser = UserRights::GetUserObject(); $oCurrentUser = UserRights::GetUserObject();
if (false === is_null($oCurrentUser)) { if (false === is_null($oCurrentUser)) {
$aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser) . '::' . $oCurrentUser->GetKey(); $aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser).'::'.$oCurrentUser->GetKey();
} }
parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious); parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious);

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -11,4 +12,4 @@
*/ */
class InvalidPasswordAttributeOneWayPassword extends CoreException class InvalidPasswordAttributeOneWayPassword extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -10,4 +11,4 @@ use Exception;
class PageNotFoundException extends Exception class PageNotFoundException extends Exception
{ {
} }

View File

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

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class SynchroExceptionNotStarted extends CoreException class SynchroExceptionNotStarted extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class UserRightException extends CoreException class UserRightException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
class DictException extends CoreException class DictException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -8,9 +9,9 @@ class DictExceptionMissingString extends DictException
{ {
public function __construct($sLanguageCode, $sStringCode) public function __construct($sLanguageCode, $sStringCode)
{ {
$aContext = array(); $aContext = [];
$aContext['language_code'] = $sLanguageCode; $aContext['language_code'] = $sLanguageCode;
$aContext['string_code'] = $sStringCode; $aContext['string_code'] = $sStringCode;
parent::__construct('Missing localized string', $aContext); parent::__construct('Missing localized string', $aContext);
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -8,8 +9,8 @@ class DictExceptionUnknownLanguage extends DictException
{ {
public function __construct($sLanguageCode) public function __construct($sLanguageCode)
{ {
$aContext = array(); $aContext = [];
$aContext['language_code'] = $sLanguageCode; $aContext['language_code'] = $sLanguageCode;
parent::__construct('Unknown localization language', $aContext); parent::__construct('Unknown localization language', $aContext);
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,5 +7,4 @@
class iTopXmlException extends CoreException class iTopXmlException extends CoreException
{ {
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -20,7 +21,7 @@ class MySQLException extends CoreException
$aContext['mysql_errno'] = $oException->getCode(); $aContext['mysql_errno'] = $oException->getCode();
$this->code = $oException->getCode(); $this->code = $oException->getCode();
$aContext['mysql_error'] = $oException->getMessage(); $aContext['mysql_error'] = $oException->getMessage();
} else if ($oMysqli != null) { } elseif ($oMysqli != null) {
$aContext['mysql_errno'] = $oMysqli->errno; $aContext['mysql_errno'] = $oMysqli->errno;
$this->code = $oMysqli->errno; $this->code = $oMysqli->errno;
$aContext['mysql_error'] = $oMysqli->error; $aContext['mysql_error'] = $oMysqli->error;
@@ -36,4 +37,4 @@ class MySQLException extends CoreException
error_reporting(0); error_reporting(0);
} }
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -19,14 +20,14 @@ class MySQLHasGoneAwayException extends MySQLException
*/ */
public static function getErrorCodes() public static function getErrorCodes()
{ {
return array( return [
2006, 2006,
2013, 2013,
); ];
} }
public function __construct($sIssue, $aContext) public function __construct($sIssue, $aContext)
{ {
parent::__construct($sIssue, $aContext, null); parent::__construct($sIssue, $aContext, null);
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -9,5 +10,4 @@
*/ */
class MySQLNoTransactionException extends MySQLException class MySQLNoTransactionException extends MySQLException
{ {
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -11,5 +12,4 @@
*/ */
class MySQLQueryHasNoResultException extends MySQLException class MySQLQueryHasNoResultException extends MySQLException
{ {
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -9,5 +10,4 @@
*/ */
class MySQLTransactionNotClosedException extends MySQLException class MySQLTransactionNotClosedException extends MySQLException
{ {
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -12,4 +13,4 @@
*/ */
class ProcessException extends CoreException class ProcessException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -13,4 +14,4 @@
*/ */
class ProcessFatalException extends CoreException class ProcessFatalException extends CoreException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -9,4 +10,4 @@
*/ */
class ProcessInvalidConfigException extends ProcessException class ProcessInvalidConfigException extends ProcessException
{ {
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -22,8 +23,8 @@
* @author Olivier DAIN <olivier.dain@combodo.com> * @author Olivier DAIN <olivier.dain@combodo.com>
* @since 3.0.0 N°3588 * @since 3.0.0 N°3588
*/ */
class FindStylesheetObject{ class FindStylesheetObject
{
//file URIs //file URIs
private $aStylesheetFileURIs; private $aStylesheetFileURIs;
@@ -64,7 +65,7 @@ class FindStylesheetObject{
return $this->aStylesheetFileURIs; return $this->aStylesheetFileURIs;
} }
public function GetLastModified() : int public function GetLastModified(): int
{ {
return $this->iLastModified; return $this->iLastModified;
} }
@@ -92,7 +93,8 @@ class FindStylesheetObject{
$this->sLastStyleSheetPath = $sStylesheetFilePath; $this->sLastStyleSheetPath = $sStylesheetFilePath;
} }
public function AlreadyFetched(string $sStylesheetFilePath) : bool { public function AlreadyFetched(string $sStylesheetFilePath): bool
{
return in_array($sStylesheetFilePath, $this->aAllStylesheetFilePaths); return in_array($sStylesheetFilePath, $this->aAllStylesheetFilePaths);
} }
@@ -111,4 +113,4 @@ class FindStylesheetObject{
{ {
$this->sLastStyleSheetPath = ""; $this->sLastStyleSheetPath = "";
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* Persistent class InputOutputTask * Persistent class InputOutputTask
* *
@@ -28,41 +28,40 @@ require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
/** /**
* This class manages the input/output tasks * 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 class InputOutputTask extends cmdbAbstractObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "application", "category" => "application",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_iotask", "db_table" => "priv_iotask",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); 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("name", ["allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
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 AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
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("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", 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_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", 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 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", array("allowed_values"=>null, "sql"=>"source_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); 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", array("class_category"=>"", "more_values"=>"", "sql"=>"objects_class", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeClass("objects_class", ["class_category" => "", "more_values" => "", "sql" => "objects_class", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
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("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", 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("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", 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 AttributeEnum("options", ["allowed_values" => new ValueSetEnum('Full, Update Only, Creation Only'), "sql" => "options", "default_value" => 'Full', "is_null_allowed" => true, "depends_on" => []]));
// Display lists // 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('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', array('description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options']); // Attributes to be displayed for a list
// Search criteria // 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('standard_search', ['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('advanced_search', ['name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype']); // Criteria of the advanced search form
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -6,4 +7,4 @@
*/ */
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core ! // cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');

View File

@@ -18,23 +18,17 @@ class LoginBasic extends AbstractLoginFSMExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('basic'); return ['basic'];
} }
protected function OnModeDetection(&$iErrorCode) protected function OnModeDetection(&$iErrorCode)
{ {
if (!Session::IsSet('login_mode')) if (!Session::IsSet('login_mode')) {
{ if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
{
Session::Set('login_mode', 'basic'); Session::Set('login_mode', 'basic');
} } elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
{
Session::Set('login_mode', 'basic'); Session::Set('login_mode', 'basic');
} } elseif (isset($_SERVER['PHP_AUTH_USER'])) {
elseif (isset($_SERVER['PHP_AUTH_USER']))
{
Session::Set('login_mode', 'basic'); Session::Set('login_mode', 'basic');
} }
} }
@@ -43,22 +37,18 @@ class LoginBasic extends AbstractLoginFSMExtension
protected function OnReadCredentials(&$iErrorCode) protected function OnReadCredentials(&$iErrorCode)
{ {
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'basic') if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'basic') {
{
list($sAuthUser) = $this->GetAuthUserAndPassword(); list($sAuthUser) = $this->GetAuthUserAndPassword();
Session::Set('login_temp_auth_user', $sAuthUser); Session::Set('login_temp_auth_user', $sAuthUser);
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
} }
protected function OnCheckCredentials(&$iErrorCode) protected function OnCheckCredentials(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'basic') if (Session::Get('login_mode') == 'basic') {
{
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword(); list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) {
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR; return LoginWebPage::LOGIN_FSM_ERROR;
} }
@@ -69,8 +59,7 @@ class LoginBasic extends AbstractLoginFSMExtension
protected function OnCredentialsOK(&$iErrorCode) protected function OnCredentialsOK(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'basic') if (Session::Get('login_mode') == 'basic') {
{
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode')); LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -78,13 +67,11 @@ class LoginBasic extends AbstractLoginFSMExtension
protected function OnError(&$iErrorCode) protected function OnError(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'basic') if (Session::Get('login_mode') == 'basic') {
{ $iOnExit = LoginWebPage::getIOnExit();
$iOnExit = LoginWebPage::getIOnExit(); if ($iOnExit === LoginWebPage::EXIT_RETURN) {
if ($iOnExit === LoginWebPage::EXIT_RETURN) return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
{ }
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
}
LoginWebPage::HTTP401Error(); LoginWebPage::HTTP401Error();
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -92,8 +79,7 @@ class LoginBasic extends AbstractLoginFSMExtension
protected function OnConnected(&$iErrorCode) protected function OnConnected(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'basic') if (Session::Get('login_mode') == 'basic') {
{
Session::Set('can_logoff', true); Session::Set('can_logoff', true);
return LoginWebPage::CheckLoggedUser($iErrorCode); return LoginWebPage::CheckLoggedUser($iErrorCode);
} }
@@ -105,42 +91,33 @@ class LoginBasic extends AbstractLoginFSMExtension
$sAuthUser = ''; $sAuthUser = '';
$sAuthPwd = null; $sAuthPwd = null;
$sAuthorization = ''; $sAuthorization = '';
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
{
$sAuthorization = $_SERVER['HTTP_AUTHORIZATION']; $sAuthorization = $_SERVER['HTTP_AUTHORIZATION'];
} } elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
{
$sAuthorization = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; $sAuthorization = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
} }
if (!empty($sAuthorization)) if (!empty($sAuthorization)) {
{
list($sAuthUser, $sAuthPwd) = explode(':', base64_decode(substr($sAuthorization, 6))); list($sAuthUser, $sAuthPwd) = explode(':', base64_decode(substr($sAuthorization, 6)));
} } else {
else if (isset($_SERVER['PHP_AUTH_USER'])) {
{
if (isset($_SERVER['PHP_AUTH_USER']))
{
$sAuthUser = $_SERVER['PHP_AUTH_USER']; $sAuthUser = $_SERVER['PHP_AUTH_USER'];
// Unfortunately, the RFC is not clear about the encoding... // Unfortunately, the RFC is not clear about the encoding...
// IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8 // IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8
// So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base // So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base
if (!LoginWebPage::LooksLikeUTF8($sAuthUser)) if (!LoginWebPage::LooksLikeUTF8($sAuthUser)) {
{
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8 // Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
// Supposed to be harmless in case of a plain ASCII string... // Supposed to be harmless in case of a plain ASCII string...
$sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser); $sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser);
} }
$sAuthPwd = $_SERVER['PHP_AUTH_PW']; $sAuthPwd = $_SERVER['PHP_AUTH_PW'];
if (!LoginWebPage::LooksLikeUTF8($sAuthPwd)) if (!LoginWebPage::LooksLikeUTF8($sAuthPwd)) {
{
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8 // Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
// Supposed to be harmless in case of a plain ASCII string... // Supposed to be harmless in case of a plain ASCII string...
$sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd); $sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd);
} }
} }
} }
return array($sAuthUser, $sAuthPwd); return [$sAuthUser, $sAuthPwd];
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -18,7 +19,7 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('before'); return ['before'];
} }
protected function OnStart(&$iErrorCode) protected function OnStart(&$iErrorCode)
@@ -31,13 +32,10 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes(); $aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
$sProposedLoginMode = utils::ReadParam('login_mode', ''); $sProposedLoginMode = utils::ReadParam('login_mode', '');
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes); $index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
if ($index !== false) if ($index !== false) {
{
// Force login mode // Force login mode
Session::Set('login_mode', $sProposedLoginMode); Session::Set('login_mode', $sProposedLoginMode);
} } else {
else
{
Session::Unset('login_mode'); Session::Unset('login_mode');
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -49,8 +47,7 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes(); $aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
$sProposedLoginMode = utils::ReadParam('login_mode', ''); $sProposedLoginMode = utils::ReadParam('login_mode', '');
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes); $index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
if ($index !== false) if ($index !== false) {
{
// Force login mode // Force login mode
LoginWebPage::SetLoginModeAndReload($sProposedLoginMode); LoginWebPage::SetLoginModeAndReload($sProposedLoginMode);
} else { } else {
@@ -69,8 +66,6 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
*/ */
class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExtension class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExtension
{ {
/** /**
* Must be executed after the other login plugins * Must be executed after the other login plugins
* *
@@ -78,19 +73,16 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('after'); return ['after'];
} }
protected function OnError(&$iErrorCode) protected function OnError(&$iErrorCode)
{ {
self::ResetLoginSession(); self::ResetLoginSession();
$iOnExit = LoginWebPage::getIOnExit(); $iOnExit = LoginWebPage::getIOnExit();
if ($iOnExit === LoginWebPage::EXIT_RETURN) if ($iOnExit === LoginWebPage::EXIT_RETURN) {
{
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
} } elseif ($iOnExit == LoginWebPage::EXIT_HTTP_401) {
elseif ($iOnExit == LoginWebPage::EXIT_HTTP_401)
{
LoginWebPage::HTTP401Error(); // Error, exit LoginWebPage::HTTP401Error(); // Error, exit
} }
// LoginWebPage::EXIT_PROMPT // LoginWebPage::EXIT_PROMPT
@@ -99,13 +91,12 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
protected function OnCredentialsOk(&$iErrorCode) protected function OnCredentialsOk(&$iErrorCode)
{ {
if (!Session::IsSet('login_mode')) if (!Session::IsSet('login_mode')) {
{ // N°6358 - if EXIT_RETURN was asked, send an error
// N°6358 - if EXIT_RETURN was asked, send an error if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) {
if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) { $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; return LoginWebPage::LOGIN_FSM_ERROR;
return LoginWebPage::LOGIN_FSM_ERROR; }
}
// If no plugin validated the user, exit // If no plugin validated the user, exit
self::ResetLoginSession(); self::ResetLoginSession();
@@ -125,7 +116,7 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
protected function OnConnected(&$iErrorCode) protected function OnConnected(&$iErrorCode)
{ {
Session::Unset('login_temp_auth_user'); Session::Unset('login_temp_auth_user');
if (is_null(UserRights::GetUserObject())){ if (is_null(UserRights::GetUserObject())) {
//N°7085 avoid infinite loop //N°7085 avoid infinite loop
IssueLog::Error("No user logged in. exit"); IssueLog::Error("No user logged in. exit");
exit(-1); exit(-1);
@@ -137,10 +128,8 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
private static function ResetLoginSession() private static function ResetLoginSession()
{ {
LoginWebPage::ResetSession(); LoginWebPage::ResetSession();
foreach (Session::ListVariables() as $sKey) foreach (Session::ListVariables() as $sKey) {
{ if (utils::StartsWith($sKey, 'login_')) {
if (utils::StartsWith($sKey, 'login_'))
{
Session::Unset($sKey); Session::Unset($sKey);
} }
} }

View File

@@ -11,7 +11,6 @@ use Combodo\iTop\Application\Helper\Session;
class LoginExternal extends AbstractLoginFSMExtension class LoginExternal extends AbstractLoginFSMExtension
{ {
/** /**
* Return the list of supported login modes for this plugin * Return the list of supported login modes for this plugin
* *
@@ -19,16 +18,14 @@ class LoginExternal extends AbstractLoginFSMExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('external'); return ['external'];
} }
protected function OnModeDetection(&$iErrorCode) protected function OnModeDetection(&$iErrorCode)
{ {
if (!Session::IsSet('login_mode')) if (!Session::IsSet('login_mode')) {
{
$sAuthUser = $this->GetAuthUser(); $sAuthUser = $this->GetAuthUser();
if ($sAuthUser && (strlen($sAuthUser) > 0)) if ($sAuthUser && (strlen($sAuthUser) > 0)) {
{
Session::Set('login_mode', 'external'); Session::Set('login_mode', 'external');
} }
} }
@@ -37,11 +34,9 @@ class LoginExternal extends AbstractLoginFSMExtension
protected function OnCheckCredentials(&$iErrorCode) protected function OnCheckCredentials(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'external') if (Session::Get('login_mode') == 'external') {
{
$sAuthUser = $this->GetAuthUser(); $sAuthUser = $this->GetAuthUser();
if (!UserRights::CheckCredentials($sAuthUser, '', Session::Get('login_mode'), 'external')) if (!UserRights::CheckCredentials($sAuthUser, '', Session::Get('login_mode'), 'external')) {
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR; return LoginWebPage::LOGIN_FSM_ERROR;
} }
@@ -52,8 +47,7 @@ class LoginExternal extends AbstractLoginFSMExtension
protected function OnCredentialsOK(&$iErrorCode) protected function OnCredentialsOK(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'external') if (Session::Get('login_mode') == 'external') {
{
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'external', Session::Get('login_mode')); LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'external', Session::Get('login_mode'));
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -61,8 +55,7 @@ class LoginExternal extends AbstractLoginFSMExtension
protected function OnConnected(&$iErrorCode) protected function OnConnected(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'external') if (Session::Get('login_mode') == 'external') {
{
Session::Set('can_logoff', false); Session::Set('can_logoff', false);
return LoginWebPage::CheckLoggedUser($iErrorCode); return LoginWebPage::CheckLoggedUser($iErrorCode);
} }
@@ -71,13 +64,11 @@ class LoginExternal extends AbstractLoginFSMExtension
protected function OnError(&$iErrorCode) protected function OnError(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'external') if (Session::Get('login_mode') == 'external') {
{ $iOnExit = LoginWebPage::getIOnExit();
$iOnExit = LoginWebPage::getIOnExit(); if ($iOnExit === LoginWebPage::EXIT_RETURN) {
if ($iOnExit === LoginWebPage::EXIT_RETURN) return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
{ }
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
}
LoginWebPage::HTTP401Error(); LoginWebPage::HTTP401Error();
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;

View File

@@ -23,7 +23,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('form'); return ['form'];
} }
/** /**
@@ -34,19 +34,17 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'form') { if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'form') {
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd)) if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd)) {
{ if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER)) {
if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER))
{
// X-Combodo-Ajax is a special header automatically added to all ajax requests // X-Combodo-Ajax is a special header automatically added to all ajax requests
// Let's reply that we're currently logged-out // Let's reply that we're currently logged-out
header('HTTP/1.0 401 Unauthorized'); header('HTTP/1.0 401 Unauthorized');
exit; exit;
} }
if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) { if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) {
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
} }
// No credentials yet, display the form // No credentials yet, display the form
$oPage = LoginWebPage::NewLoginWebPage(); $oPage = LoginWebPage::NewLoginWebPage();
@@ -66,12 +64,10 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
protected function OnCheckCredentials(&$iErrorCode) protected function OnCheckCredentials(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'form') if (Session::Get('login_mode') == 'form') {
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) {
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR; return LoginWebPage::LOGIN_FSM_ERROR;
} }
@@ -85,8 +81,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
protected function OnCredentialsOK(&$iErrorCode) protected function OnCredentialsOK(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'form') if (Session::Get('login_mode') == 'form') {
{
// Store 'auth_user' in session for further use // Store 'auth_user' in session for further use
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode')); LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
} }
@@ -98,8 +93,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
protected function OnError(&$iErrorCode) protected function OnError(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'form') if (Session::Get('login_mode') == 'form') {
{
$this->bForceFormOnError = true; $this->bForceFormOnError = true;
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -110,8 +104,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
protected function OnConnected(&$iErrorCode) protected function OnConnected(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'form') if (Session::Get('login_mode') == 'form') {
{
Session::Set('can_logoff', true); Session::Set('can_logoff', true);
return LoginWebPage::CheckLoggedUser($iErrorCode); return LoginWebPage::CheckLoggedUser($iErrorCode);
} }
@@ -131,24 +124,23 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
$sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
$sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data'); $sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data');
$aData = array( $aData = [
'sAuthUser' => $sAuthUser, 'sAuthUser' => $sAuthUser,
'sAuthPwd' => $sAuthPwd, 'sAuthPwd' => $sAuthPwd,
); ];
$oLoginContext->AddBlockExtension('login_input', new LoginBlockExtension('extensionblock/loginforminput.html.twig', $aData)); $oLoginContext->AddBlockExtension('login_input', new LoginBlockExtension('extensionblock/loginforminput.html.twig', $aData));
$oLoginContext->AddBlockExtension('login_submit', new LoginBlockExtension('extensionblock/loginformsubmit.html.twig')); $oLoginContext->AddBlockExtension('login_submit', new LoginBlockExtension('extensionblock/loginformsubmit.html.twig'));
$oLoginContext->AddBlockExtension('login_form_footer', new LoginBlockExtension('extensionblock/loginformfooter.html.twig')); $oLoginContext->AddBlockExtension('login_form_footer', new LoginBlockExtension('extensionblock/loginformfooter.html.twig'));
$bEnableResetPassword = MetaModel::GetConfig()->Get('forgot_password'); $bEnableResetPassword = MetaModel::GetConfig()->Get('forgot_password');
$sResetPasswordUrl = MetaModel::GetConfig()->Get('forgot_password.url'); $sResetPasswordUrl = MetaModel::GetConfig()->Get('forgot_password.url');
if ($sResetPasswordUrl == '') if ($sResetPasswordUrl == '') {
{ $sResetPasswordUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=forgot_pwd';
$sResetPasswordUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?loginop=forgot_pwd';
} }
$aData = array( $aData = [
'bEnableResetPassword' => $bEnableResetPassword, 'bEnableResetPassword' => $bEnableResetPassword,
'sResetPasswordUrl' => $sResetPasswordUrl, 'sResetPasswordUrl' => $sResetPasswordUrl,
); ];
$oLoginContext->AddBlockExtension('login_links', new LoginBlockExtension('extensionblock/loginformlinks.html.twig', $aData)); $oLoginContext->AddBlockExtension('login_links', new LoginBlockExtension('extensionblock/loginformlinks.html.twig', $aData));
return $oLoginContext; return $oLoginContext;

View File

@@ -6,7 +6,6 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
use Combodo\iTop\Application\Branding; use Combodo\iTop\Application\Branding;
use Combodo\iTop\Application\TwigBase\Twig\Extension; use Combodo\iTop\Application\TwigBase\Twig\Extension;
use Combodo\iTop\Application\WebPage\NiceWebPage; use Combodo\iTop\Application\WebPage\NiceWebPage;
@@ -41,11 +40,11 @@ class LoginTwigContext
*/ */
public function __construct() public function __construct()
{ {
$this->aBlockExtension = array(); $this->aBlockExtension = [];
$this->aPostedVars = array(); $this->aPostedVars = [];
$this->sTwigLoaderPath = null; $this->sTwigLoaderPath = null;
$this->aCSSFiles = array(); $this->aCSSFiles = [];
$this->aJsFiles = array(); $this->aJsFiles = [];
$this->sTwigNameSpace = null; $this->sTwigNameSpace = null;
} }
@@ -179,7 +178,7 @@ class LoginBlockExtension
* @param array $aData Data given to the twig template (into the variable {{ aData }}) * @param array $aData Data given to the twig template (into the variable {{ aData }})
* @api * @api
*/ */
public function __construct($sTwig, $aData = array()) public function __construct($sTwig, $aData = [])
{ {
$this->sTwig = $sTwig; $this->sTwig = $sTwig;
$this->aData = $aData; $this->aData = $aData;
@@ -210,21 +209,18 @@ class LoginTwigRenderer
public function __construct() public function __construct()
{ {
$this->aLoginPluginList = LoginWebPage::GetLoginPluginList('iLoginUIExtension', false); $this->aLoginPluginList = LoginWebPage::GetLoginPluginList('iLoginUIExtension', false);
$this->aPluginFormData = array(); $this->aPluginFormData = [];
$aTwigLoaders = array(); $aTwigLoaders = [];
$this->aPostedVars = array(); $this->aPostedVars = [];
foreach ($this->aLoginPluginList as $oLoginPlugin) foreach ($this->aLoginPluginList as $oLoginPlugin) {
{
/** @var \iLoginUIExtension $oLoginPlugin */ /** @var \iLoginUIExtension $oLoginPlugin */
$oLoginContext = $oLoginPlugin->GetTwigContext(); $oLoginContext = $oLoginPlugin->GetTwigContext();
if (is_null($oLoginContext)) if (is_null($oLoginContext)) {
{
continue; continue;
} }
$this->aPluginFormData[] = $oLoginContext; $this->aPluginFormData[] = $oLoginContext;
$sTwigLoaderPath = $oLoginContext->GetTwigLoaderPath(); $sTwigLoaderPath = $oLoginContext->GetTwigLoaderPath();
if ($sTwigLoaderPath != null) if ($sTwigLoaderPath != null) {
{
$oExtensionLoader = new FilesystemLoader(); $oExtensionLoader = new FilesystemLoader();
$oExtensionLoader->setPaths($sTwigLoaderPath); $oExtensionLoader->setPaths($sTwigLoaderPath);
$aTwigLoaders[] = $oExtensionLoader; $aTwigLoaders[] = $oExtensionLoader;
@@ -232,8 +228,8 @@ class LoginTwigRenderer
$this->aPostedVars = array_merge($this->aPostedVars, $oLoginContext->GetPostedVars()); $this->aPostedVars = array_merge($this->aPostedVars, $oLoginContext->GetPostedVars());
} }
$oCoreLoader = new FilesystemLoader(array(), APPROOT.'templates'); $oCoreLoader = new FilesystemLoader([], APPROOT.'templates');
$aCoreTemplatesPaths = array('pages/login', 'pages/login/password'); $aCoreTemplatesPaths = ['pages/login', 'pages/login/password'];
// Having this path declared after the plugins let the plugins replace the core templates // Having this path declared after the plugins let the plugins replace the core templates
$oCoreLoader->setPaths($aCoreTemplatesPaths); $oCoreLoader->setPaths($aCoreTemplatesPaths);
// Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them // Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them
@@ -251,19 +247,19 @@ class LoginTwigRenderer
$sIconUrl = Utils::GetConfig()->Get('app_icon_url'); $sIconUrl = Utils::GetConfig()->Get('app_icon_url');
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl(); $sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
$aVars = array( $aVars = [
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(), 'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
'aPluginFormData' => $this->GetPluginFormData(), 'aPluginFormData' => $this->GetPluginFormData(),
'sItopVersion' => ITOP_VERSION, 'sItopVersion' => ITOP_VERSION,
'sVersionShort' => $sVersionShort, 'sVersionShort' => $sVersionShort,
'sIconUrl' => $sIconUrl, 'sIconUrl' => $sIconUrl,
'sDisplayIcon' => $sDisplayIcon, 'sDisplayIcon' => $sDisplayIcon,
); ];
return $aVars; return $aVars;
} }
public function Render(NiceWebPage $oPage, $sTwigFile, $aVars = array()) public function Render(NiceWebPage $oPage, $sTwigFile, $aVars = [])
{ {
$oTemplate = $this->GetTwig()->load($sTwigFile); $oTemplate = $this->GetTwig()->load($sTwigFile);
$oPage->add($oTemplate->renderBlock('body', $aVars)); $oPage->add($oTemplate->renderBlock('body', $aVars));
@@ -272,17 +268,14 @@ class LoginTwigRenderer
$oPage->add_style($oTemplate->renderBlock('css', $aVars)); $oPage->add_style($oTemplate->renderBlock('css', $aVars));
// Render CSS links // Render CSS links
foreach ($this->aPluginFormData as $oFormData) foreach ($this->aPluginFormData as $oFormData) {
{
/** @var \LoginTwigContext $oFormData */ /** @var \LoginTwigContext $oFormData */
$aCSSFiles = $oFormData->GetCSSFiles(); $aCSSFiles = $oFormData->GetCSSFiles();
foreach ($aCSSFiles as $sCSSFile) foreach ($aCSSFiles as $sCSSFile) {
{
$oPage->LinkStylesheetFromURI($sCSSFile); $oPage->LinkStylesheetFromURI($sCSSFile);
} }
$aJsFiles = $oFormData->GetJsFiles(); $aJsFiles = $oFormData->GetJsFiles();
foreach ($aJsFiles as $sJsFile) foreach ($aJsFiles as $sJsFile) {
{
$oPage->LinkScriptFromURI($sJsFile); $oPage->LinkScriptFromURI($sJsFile);
} }

View File

@@ -23,17 +23,15 @@ class LoginURL extends AbstractLoginFSMExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('url'); return ['url'];
} }
protected function OnModeDetection(&$iErrorCode) protected function OnModeDetection(&$iErrorCode)
{ {
if (!Session::IsSet('login_mode') && !$this->bErrorOccurred) if (!Session::IsSet('login_mode') && !$this->bErrorOccurred) {
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd)) if (!empty($sAuthUser) && !empty($sAuthPwd)) {
{
Session::Set('login_mode', 'url'); Session::Set('login_mode', 'url');
} }
} }
@@ -42,8 +40,7 @@ class LoginURL extends AbstractLoginFSMExtension
protected function OnReadCredentials(&$iErrorCode) protected function OnReadCredentials(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'url') if (Session::Get('login_mode') == 'url') {
{
Session::Set('login_temp_auth_user', utils::ReadParam('auth_user', '', false, 'raw_data')); Session::Set('login_temp_auth_user', utils::ReadParam('auth_user', '', false, 'raw_data'));
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -51,12 +48,10 @@ class LoginURL extends AbstractLoginFSMExtension
protected function OnCheckCredentials(&$iErrorCode) protected function OnCheckCredentials(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'url') if (Session::Get('login_mode') == 'url') {
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal')) {
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR; return LoginWebPage::LOGIN_FSM_ERROR;
} }
@@ -67,8 +62,7 @@ class LoginURL extends AbstractLoginFSMExtension
protected function OnCredentialsOK(&$iErrorCode) protected function OnCredentialsOK(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'url') if (Session::Get('login_mode') == 'url') {
{
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode')); LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -76,8 +70,7 @@ class LoginURL extends AbstractLoginFSMExtension
protected function OnError(&$iErrorCode) protected function OnError(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'url') if (Session::Get('login_mode') == 'url') {
{
$this->bErrorOccurred = true; $this->bErrorOccurred = true;
} }
return LoginWebPage::LOGIN_FSM_CONTINUE; return LoginWebPage::LOGIN_FSM_CONTINUE;
@@ -85,8 +78,7 @@ class LoginURL extends AbstractLoginFSMExtension
protected function OnConnected(&$iErrorCode) protected function OnConnected(&$iErrorCode)
{ {
if (Session::Get('login_mode') == 'url') if (Session::Get('login_mode') == 'url') {
{
Session::Set('can_logoff', true); Session::Set('can_logoff', true);
return LoginWebPage::CheckLoggedUser($iErrorCode); return LoginWebPage::CheckLoggedUser($iErrorCode);
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* Class LoginWebPage * Class LoginWebPage
* *
@@ -37,33 +37,33 @@ use Combodo\iTop\Service\Events\EventService;
class LoginWebPage extends NiceWebPage class LoginWebPage extends NiceWebPage
{ {
const EXIT_PROMPT = 0; public const EXIT_PROMPT = 0;
const EXIT_HTTP_401 = 1; public const EXIT_HTTP_401 = 1;
const EXIT_RETURN = 2; public const EXIT_RETURN = 2;
const EXIT_CODE_OK = 0; public const EXIT_CODE_OK = 0;
const EXIT_CODE_MISSINGLOGIN = 1; public const EXIT_CODE_MISSINGLOGIN = 1;
const EXIT_CODE_MISSINGPASSWORD = 2; public const EXIT_CODE_MISSINGPASSWORD = 2;
const EXIT_CODE_WRONGCREDENTIALS = 3; public const EXIT_CODE_WRONGCREDENTIALS = 3;
const EXIT_CODE_MUSTBEADMIN = 4; public const EXIT_CODE_MUSTBEADMIN = 4;
const EXIT_CODE_PORTALUSERNOTAUTHORIZED = 5; public const EXIT_CODE_PORTALUSERNOTAUTHORIZED = 5;
const EXIT_CODE_NOTAUTHORIZED = 6; public const EXIT_CODE_NOTAUTHORIZED = 6;
// Login FSM States // Login FSM States
const LOGIN_STATE_START = 'start'; // Entry state public const LOGIN_STATE_START = 'start'; // Entry state
const LOGIN_STATE_MODE_DETECTION = 'login mode detection'; // Detect which login plugin to use public const LOGIN_STATE_MODE_DETECTION = 'login mode detection'; // Detect which login plugin to use
const LOGIN_STATE_READ_CREDENTIALS = 'read credentials'; // Read the credentials public const LOGIN_STATE_READ_CREDENTIALS = 'read credentials'; // Read the credentials
const LOGIN_STATE_CHECK_CREDENTIALS = 'check credentials'; // Check if the credentials are valid public const LOGIN_STATE_CHECK_CREDENTIALS = 'check credentials'; // Check if the credentials are valid
const LOGIN_STATE_CREDENTIALS_OK = 'credentials ok'; // User provisioning public const LOGIN_STATE_CREDENTIALS_OK = 'credentials ok'; // User provisioning
const LOGIN_STATE_USER_OK = 'user ok'; // Additional check (2FA) public const LOGIN_STATE_USER_OK = 'user ok'; // Additional check (2FA)
const LOGIN_STATE_CONNECTED = 'connected'; // User connected public const LOGIN_STATE_CONNECTED = 'connected'; // User connected
const LOGIN_STATE_SET_ERROR = 'prepare for error'; // Internal state to trigger ERROR state public const LOGIN_STATE_SET_ERROR = 'prepare for error'; // Internal state to trigger ERROR state
const LOGIN_STATE_ERROR = 'error'; // An error occurred, next state will be NONE public const LOGIN_STATE_ERROR = 'error'; // An error occurred, next state will be NONE
// Login FSM Returns // Login FSM Returns
const LOGIN_FSM_RETURN = 0; // End the FSM OK (connected) public const LOGIN_FSM_RETURN = 0; // End the FSM OK (connected)
const LOGIN_FSM_ERROR = 1; // Error signaled public const LOGIN_FSM_ERROR = 1; // Error signaled
const LOGIN_FSM_CONTINUE = 2; // Continue FSM public const LOGIN_FSM_CONTINUE = 2; // Continue FSM
protected static $sHandlerClass = __class__; protected static $sHandlerClass = __class__;
private static $iOnExit; private static $iOnExit;
@@ -78,7 +78,7 @@ class LoginWebPage extends NiceWebPage
*/ */
public static function NewLoginWebPage() public static function NewLoginWebPage()
{ {
return new self::$sHandlerClass; return new self::$sHandlerClass();
} }
protected static $m_sLoginFailedMessage = ''; protected static $m_sLoginFailedMessage = '';
@@ -94,7 +94,7 @@ class LoginWebPage extends NiceWebPage
$this->no_cache(); $this->no_cache();
$this->add_http_headers(); $this->add_http_headers();
} }
public function SetStyleSheet() public function SetStyleSheet()
{ {
$this->LinkStylesheetFromAppRoot('css/login.css'); $this->LinkStylesheetFromAppRoot('css/login.css');
@@ -128,23 +128,18 @@ class LoginWebPage extends NiceWebPage
$oProfilesSet = $oUser->Get('profile_list'); $oProfilesSet = $oUser->Get('profile_list');
//delete old profiles //delete old profiles
$aExistingProfiles = []; $aExistingProfiles = [];
while ($oProfile = $oProfilesSet->Fetch()) while ($oProfile = $oProfilesSet->Fetch()) {
{
array_push($aExistingProfiles, $oProfile->Get('profileid')); array_push($aExistingProfiles, $oProfile->Get('profileid'));
$iArrayKey = array_search($oProfile->Get('profileid'), $aProfiles); $iArrayKey = array_search($oProfile->Get('profileid'), $aProfiles);
if (!$iArrayKey) if (!$iArrayKey) {
{
$oProfilesSet->RemoveItem($oProfile->Get('profileid')); $oProfilesSet->RemoveItem($oProfile->Get('profileid'));
} } else {
else
{
unset($aProfiles[$iArrayKey]); unset($aProfiles[$iArrayKey]);
} }
} }
//add profiles not already linked with user //add profiles not already linked with user
foreach ($aProfiles as $iProfileId) foreach ($aProfiles as $iProfileId) {
{ $oProfilesSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $iProfileId, 'reason' => $sOrigin]));
$oProfilesSet->AddItem(MetaModel::NewObject('URP_UserProfile', array('profileid' => $iProfileId, 'reason' => $sOrigin)));
} }
$oUser->Set('profile_list', $oProfilesSet); $oUser->Set('profile_list', $oProfilesSet);
} }
@@ -154,56 +149,49 @@ class LoginWebPage extends NiceWebPage
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION); $sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
$sIconUrl = Utils::GetConfig()->Get('app_icon_url'); $sIconUrl = Utils::GetConfig()->Get('app_icon_url');
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl(); $sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
$this->add("<div id=\"login-logo\"><a href=\"".htmlentities($sIconUrl, ENT_QUOTES, $this->add("<div id=\"login-logo\"><a href=\"".htmlentities(
self::PAGES_CHARSET)."\"><img title=\"$sVersionShort\" src=\"$sDisplayIcon\"></a></div>\n"); $sIconUrl,
ENT_QUOTES,
self::PAGES_CHARSET
)."\"><img title=\"$sVersionShort\" src=\"$sDisplayIcon\"></a></div>\n");
} }
public function DisplayLoginForm($bFailedLogin = false) public function DisplayLoginForm($bFailedLogin = false)
{ {
$oTwigContext = new LoginTwigRenderer(); $oTwigContext = new LoginTwigRenderer();
$aPostedVars = array_merge(array('login_mode', 'loginop'), $oTwigContext->GetPostedVars()); $aPostedVars = array_merge(['login_mode', 'loginop'], $oTwigContext->GetPostedVars());
$sMessage = Dict::S('UI:Login:IdentifyYourself'); $sMessage = Dict::S('UI:Login:IdentifyYourself');
// Error message // Error message
if ($bFailedLogin) if ($bFailedLogin) {
{ if (self::$m_sLoginFailedMessage != '') {
if (self::$m_sLoginFailedMessage != '')
{
$sMessage = self::$m_sLoginFailedMessage; $sMessage = self::$m_sLoginFailedMessage;
} } else {
else
{
$sMessage = Dict::S('UI:Login:IncorrectLoginPassword'); $sMessage = Dict::S('UI:Login:IncorrectLoginPassword');
} }
} }
// Keep the OTHER parameters posted // Keep the OTHER parameters posted
$aPreviousPostedVars = array(); $aPreviousPostedVars = [];
foreach($_POST as $sPostedKey => $postedValue) foreach ($_POST as $sPostedKey => $postedValue) {
{ if (!in_array($sPostedKey, $aPostedVars)) {
if (!in_array($sPostedKey, $aPostedVars)) if (is_array($postedValue)) {
{ foreach ($postedValue as $sKey => $sValue) {
if (is_array($postedValue))
{
foreach($postedValue as $sKey => $sValue)
{
$sName = "{$sPostedKey}[{$sKey}]"; $sName = "{$sPostedKey}[{$sKey}]";
$aPreviousPostedVars[$sName] = $sValue; $aPreviousPostedVars[$sName] = $sValue;
} }
} } else {
else
{
$aPreviousPostedVars[$sPostedKey] = $postedValue; $aPreviousPostedVars[$sPostedKey] = $postedValue;
} }
} }
} }
$aVars = array( $aVars = [
'bFailedLogin' => $bFailedLogin, 'bFailedLogin' => $bFailedLogin,
'sMessage' => $sMessage, 'sMessage' => $sMessage,
'aPreviousPostedVars' => $aPreviousPostedVars, 'aPreviousPostedVars' => $aPreviousPostedVars,
); ];
$aVars = array_merge($aVars, $oTwigContext->GetDefaultVars()); $aVars = array_merge($aVars, $oTwigContext->GetDefaultVars());
$oTwigContext->Render($this, 'login.html.twig', $aVars); $oTwigContext->Render($this, 'login.html.twig', $aVars);
@@ -226,26 +214,21 @@ class LoginWebPage extends NiceWebPage
{ {
$sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
try try {
{
UserRights::Login($sAuthUser); // Set the user's language (if possible!) UserRights::Login($sAuthUser); // Set the user's language (if possible!)
/** @var UserInternal $oUser */ /** @var UserInternal $oUser */
$oUser = UserRights::GetUserObject(); $oUser = UserRights::GetUserObject();
if ($oUser != null) if ($oUser != null) {
{ if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) {
if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token'))
{
throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible')); throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible'));
} }
if (!$oUser->CanChangePassword()) if (!$oUser->CanChangePassword()) {
{
throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd')); throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd'));
} }
$sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed $sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed
if ($sTo == '') if ($sTo == '') {
{
throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail')); throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail'));
} }
@@ -265,8 +248,7 @@ class LoginWebPage extends NiceWebPage
$sResetUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=reset_pwd&auth_user='.urlencode($oUser->Get('login')).'&token='.urlencode($sToken); $sResetUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=reset_pwd&auth_user='.urlencode($oUser->Get('login')).'&token='.urlencode($sToken);
$oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl, $oUser->Get('login'))); $oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl, $oUser->Get('login')));
$iRes = $oEmail->Send($aIssues, true /* force synchronous exec */); $iRes = $oEmail->Send($aIssues, true /* force synchronous exec */);
switch ($iRes) switch ($iRes) {
{
//case EMAIL_SEND_PENDING: //case EMAIL_SEND_PENDING:
case EMAIL_SEND_OK: case EMAIL_SEND_OK:
break; break;
@@ -278,13 +260,10 @@ class LoginWebPage extends NiceWebPage
} }
} }
$oTwigContext = new LoginTwigRenderer(); $oTwigContext = new LoginTwigRenderer();
$aVars = $oTwigContext->GetDefaultVars(); $aVars = $oTwigContext->GetDefaultVars();
$oTwigContext->Render($this, 'forgotpwdsent.html.twig', $aVars); $oTwigContext->Render($this, 'forgotpwdsent.html.twig', $aVars);
} } catch (Exception $e) {
catch(Exception $e)
{
$this->DisplayForgotPwdForm(true, $e->getMessage()); $this->DisplayForgotPwdForm(true, $e->getMessage());
} }
} }
@@ -304,22 +283,16 @@ class LoginWebPage extends NiceWebPage
$aVars['sToken'] = $sToken; $aVars['sToken'] = $sToken;
$aVars['sErrorMessage'] = $sErrorMessage; $aVars['sErrorMessage'] = $sErrorMessage;
if (($oUser == null)) if (($oUser == null)) {
{
$aVars['bNoUser'] = true; $aVars['bNoUser'] = true;
} } else {
else
{
$aVars['bNoUser'] = false; $aVars['bNoUser'] = false;
$aVars['sUserName'] = $oUser->GetFriendlyName(); $aVars['sUserName'] = $oUser->GetFriendlyName();
$oEncryptedToken = $oUser->Get('reset_pwd_token'); $oEncryptedToken = $oUser->Get('reset_pwd_token');
if (!$oEncryptedToken->CheckPassword($sToken)) if (!$oEncryptedToken->CheckPassword($sToken)) {
{
$aVars['bBadToken'] = true; $aVars['bBadToken'] = true;
} } else {
else
{
$aVars['bBadToken'] = false; $aVars['bBadToken'] = false;
} }
} }
@@ -342,21 +315,15 @@ class LoginWebPage extends NiceWebPage
$aVars['sAuthUser'] = $sAuthUser; $aVars['sAuthUser'] = $sAuthUser;
$aVars['sToken'] = $sToken; $aVars['sToken'] = $sToken;
if (($oUser == null)) if (($oUser == null)) {
{
$aVars['bNoUser'] = true; $aVars['bNoUser'] = true;
} } else {
else
{
$aVars['bNoUser'] = false; $aVars['bNoUser'] = false;
$oEncryptedToken = $oUser->Get('reset_pwd_token'); $oEncryptedToken = $oUser->Get('reset_pwd_token');
if (!$oEncryptedToken->CheckPassword($sToken)) if (!$oEncryptedToken->CheckPassword($sToken)) {
{
$aVars['bBadToken'] = true; $aVars['bBadToken'] = true;
} } else {
else
{
$aVars['bBadToken'] = false; $aVars['bBadToken'] = false;
// Trash the token and change the password // Trash the token and change the password
$oUser->Set('reset_pwd_token', new ormPassword()); $oUser->Set('reset_pwd_token', new ormPassword());
@@ -413,7 +380,7 @@ class LoginWebPage extends NiceWebPage
// Note: This will destroy the session, and not just the session data! // Note: This will destroy the session, and not just the session data!
} }
static function SecureConnectionRequired() public static function SecureConnectionRequired()
{ {
return MetaModel::GetConfig()->GetSecureConnectionRequired(); return MetaModel::GetConfig()->GetSecureConnectionRequired();
} }
@@ -423,7 +390,7 @@ class LoginWebPage extends NiceWebPage
* @param string $sString * @param string $sString
* @return bool True if the string contains some typical UTF-8 multi-byte sequences * @return bool True if the string contains some typical UTF-8 multi-byte sequences
*/ */
static function LooksLikeUTF8($sString) public static function LooksLikeUTF8($sString)
{ {
return preg_match('%(?: return preg_match('%(?:
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
@@ -446,22 +413,19 @@ class LoginWebPage extends NiceWebPage
protected static function Login($iOnExit) protected static function Login($iOnExit)
{ {
self::$iOnExit = $iOnExit; self::$iOnExit = $iOnExit;
if (self::SecureConnectionRequired() && !utils::IsConnectionSecure()) if (self::SecureConnectionRequired() && !utils::IsConnectionSecure()) {
{
// Non secured URL... request for a secure connection // Non secured URL... request for a secure connection
throw new Exception('Secure connection required!'); throw new Exception('Secure connection required!');
} }
$bLoginDebug = MetaModel::GetConfig()->Get('login_debug'); $bLoginDebug = MetaModel::GetConfig()->Get('login_debug');
if (Session::Get('login_state') == self::LOGIN_STATE_ERROR) if (Session::Get('login_state') == self::LOGIN_STATE_ERROR) {
{
Session::Set('login_state', self::LOGIN_STATE_START); Session::Set('login_state', self::LOGIN_STATE_START);
} }
$sLoginState = Session::Get('login_state'); $sLoginState = Session::Get('login_state');
$sSessionLog = ''; $sSessionLog = '';
if ($bLoginDebug) if ($bLoginDebug) {
{
IssueLog::Info("---------------------------------"); IssueLog::Info("---------------------------------");
IssueLog::Info($_SERVER['REQUEST_URI']); IssueLog::Info($_SERVER['REQUEST_URI']);
IssueLog::Info("--> Entering Login FSM with state: [$sLoginState]"); IssueLog::Info("--> Entering Login FSM with state: [$sLoginState]");
@@ -472,38 +436,30 @@ class LoginWebPage extends NiceWebPage
$iErrorCode = self::EXIT_CODE_OK; $iErrorCode = self::EXIT_CODE_OK;
// Finite state machine loop // Finite state machine loop
while (true) while (true) {
{ try {
try
{
$aLoginPlugins = self::GetLoginPluginList(); $aLoginPlugins = self::GetLoginPluginList();
if (empty($aLoginPlugins)) if (empty($aLoginPlugins)) {
{
throw new Exception("Missing login classes"); throw new Exception("Missing login classes");
} }
/** @var iLoginFSMExtension $oLoginFSMExtensionInstance */ /** @var iLoginFSMExtension $oLoginFSMExtensionInstance */
foreach ($aLoginPlugins as $oLoginFSMExtensionInstance) foreach ($aLoginPlugins as $oLoginFSMExtensionInstance) {
{ if ($bLoginDebug) {
if ($bLoginDebug)
{
$sCurrSessionLog = session_id().' '.utils::GetSessionLog(); $sCurrSessionLog = session_id().' '.utils::GetSessionLog();
if ($sCurrSessionLog != $sSessionLog) if ($sCurrSessionLog != $sSessionLog) {
{
$sSessionLog = $sCurrSessionLog; $sSessionLog = $sCurrSessionLog;
IssueLog::Info("SESSION: $sSessionLog"); IssueLog::Info("SESSION: $sSessionLog");
} }
IssueLog::Info("Login: state: [$sLoginState] call: ".get_class($oLoginFSMExtensionInstance)); IssueLog::Info("Login: state: [$sLoginState] call: ".get_class($oLoginFSMExtensionInstance));
} }
$iResponse = $oLoginFSMExtensionInstance->LoginAction($sLoginState, $iErrorCode); $iResponse = $oLoginFSMExtensionInstance->LoginAction($sLoginState, $iErrorCode);
if ($iResponse == self::LOGIN_FSM_RETURN) if ($iResponse == self::LOGIN_FSM_RETURN) {
{
EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['code' => $iErrorCode, 'state' => $sLoginState])); EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['code' => $iErrorCode, 'state' => $sLoginState]));
Session::WriteClose(); Session::WriteClose();
return $iErrorCode; // Asked to exit FSM, generally login OK return $iErrorCode; // Asked to exit FSM, generally login OK
} }
if ($iResponse == self::LOGIN_FSM_ERROR) if ($iResponse == self::LOGIN_FSM_ERROR) {
{
EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['code' => $iErrorCode, 'state' => $sLoginState])); EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['code' => $iErrorCode, 'state' => $sLoginState]));
$sLoginState = self::LOGIN_STATE_SET_ERROR; // Next state will be error $sLoginState = self::LOGIN_STATE_SET_ERROR; // Next state will be error
// An error was detected, skip the other plugins turn // An error was detected, skip the other plugins turn
@@ -515,9 +471,7 @@ class LoginWebPage extends NiceWebPage
// Every plugin has nothing else to do in this state, go forward // Every plugin has nothing else to do in this state, go forward
$sLoginState = self::AdvanceLoginFSMState($sLoginState); $sLoginState = self::AdvanceLoginFSMState($sLoginState);
Session::Set('login_state', $sLoginState); Session::Set('login_state', $sLoginState);
} } catch (Exception $e) {
catch (Exception $e)
{
EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['state' => $_SESSION['login_state']])); EventService::FireEvent(new EventData(EVENT_LOGIN, null, ['state' => $_SESSION['login_state']]));
IssueLog::Error($e->getTraceAsString()); IssueLog::Error($e->getTraceAsString());
static::ResetSession(); static::ResetSession();
@@ -537,30 +491,23 @@ class LoginWebPage extends NiceWebPage
*/ */
public static function GetLoginPluginList($sInterface = 'iLoginFSMExtension', $bFilterWithMode = true) public static function GetLoginPluginList($sInterface = 'iLoginFSMExtension', $bFilterWithMode = true)
{ {
$aAllPlugins = array(); $aAllPlugins = [];
if ($bFilterWithMode) if ($bFilterWithMode) {
{
$sCurrentLoginMode = Session::Get('login_mode', ''); $sCurrentLoginMode = Session::Get('login_mode', '');
} } else {
else
{
$sCurrentLoginMode = ''; $sCurrentLoginMode = '';
} }
/** @var iLoginExtension $oLoginExtensionInstance */ /** @var iLoginExtension $oLoginExtensionInstance */
foreach (MetaModel::EnumPlugins($sInterface) as $oLoginExtensionInstance) foreach (MetaModel::EnumPlugins($sInterface) as $oLoginExtensionInstance) {
{
$aLoginModes = $oLoginExtensionInstance->ListSupportedLoginModes(); $aLoginModes = $oLoginExtensionInstance->ListSupportedLoginModes();
$aLoginModes = (is_array($aLoginModes) ? $aLoginModes : array()); $aLoginModes = (is_array($aLoginModes) ? $aLoginModes : []);
foreach ($aLoginModes as $sLoginMode) foreach ($aLoginModes as $sLoginMode) {
{
// Keep only the plugins for the current login mode + before + after // Keep only the plugins for the current login mode + before + after
if (empty($sCurrentLoginMode) || ($sLoginMode == $sCurrentLoginMode) || ($sLoginMode == 'before') || ($sLoginMode == 'after')) if (empty($sCurrentLoginMode) || ($sLoginMode == $sCurrentLoginMode) || ($sLoginMode == 'before') || ($sLoginMode == 'after')) {
{ if (!isset($aAllPlugins[$sLoginMode])) {
if (!isset($aAllPlugins[$sLoginMode])) $aAllPlugins[$sLoginMode] = [];
{
$aAllPlugins[$sLoginMode] = array();
} }
$aAllPlugins[$sLoginMode][] = $oLoginExtensionInstance; $aAllPlugins[$sLoginMode][] = $oLoginExtensionInstance;
break; // Stop here to avoid registering a plugin twice break; // Stop here to avoid registering a plugin twice
@@ -569,12 +516,10 @@ class LoginWebPage extends NiceWebPage
} }
// Order and filter by the config list of allowed types (allowed_login_types) // Order and filter by the config list of allowed types (allowed_login_types)
$aAllowedLoginModes = array_merge(array('before'), MetaModel::GetConfig()->GetAllowedLoginTypes(), array('after')); $aAllowedLoginModes = array_merge(['before'], MetaModel::GetConfig()->GetAllowedLoginTypes(), ['after']);
$aPlugins = array(); $aPlugins = [];
foreach ($aAllowedLoginModes as $sAllowedMode) foreach ($aAllowedLoginModes as $sAllowedMode) {
{ if (isset($aAllPlugins[$sAllowedMode])) {
if (isset($aAllPlugins[$sAllowedMode]))
{
$aPlugins = array_merge($aPlugins, $aAllPlugins[$sAllowedMode]); $aPlugins = array_merge($aPlugins, $aAllPlugins[$sAllowedMode]);
} }
} }
@@ -590,8 +535,7 @@ class LoginWebPage extends NiceWebPage
*/ */
private static function AdvanceLoginFSMState($sLoginState) private static function AdvanceLoginFSMState($sLoginState)
{ {
switch ($sLoginState) switch ($sLoginState) {
{
case self::LOGIN_STATE_START: case self::LOGIN_STATE_START:
return self::LOGIN_STATE_MODE_DETECTION; return self::LOGIN_STATE_MODE_DETECTION;
@@ -638,8 +582,7 @@ class LoginWebPage extends NiceWebPage
public static function CheckUser($sAuthUser, $sAuthPassword = '', $sAuthentication = 'external') public static function CheckUser($sAuthUser, $sAuthPassword = '', $sAuthentication = 'external')
{ {
$oUser = self::FindUser($sAuthUser, true, ucfirst(strtolower($sAuthentication))); $oUser = self::FindUser($sAuthUser, true, ucfirst(strtolower($sAuthentication)));
if (is_null($oUser)) if (is_null($oUser)) {
{
return false; return false;
} }
@@ -668,8 +611,7 @@ class LoginWebPage extends NiceWebPage
{ {
// User is Ok, let's save it in the session and proceed with normal login // User is Ok, let's save it in the session and proceed with normal login
$bLoginSuccess = UserRights::Login($sAuthUser, $sAuthentication); // Login & set the user's language $bLoginSuccess = UserRights::Login($sAuthUser, $sAuthentication); // Login & set the user's language
if (!$bLoginSuccess) if (!$bLoginSuccess) {
{
throw new Exception("Bad user"); throw new Exception("Bad user");
} }
if (MetaModel::GetConfig()->Get('log_usage')) { if (MetaModel::GetConfig()->Get('log_usage')) {
@@ -696,12 +638,10 @@ class LoginWebPage extends NiceWebPage
*/ */
public static function CheckLoggedUser(&$iErrorCode) public static function CheckLoggedUser(&$iErrorCode)
{ {
if (Session::IsSet('auth_user')) if (Session::IsSet('auth_user')) {
{
// Already authenticated // Already authenticated
$bRet = UserRights::Login(Session::Get('auth_user')); // Login & set the user's language $bRet = UserRights::Login(Session::Get('auth_user')); // Login & set the user's language
if ($bRet) if ($bRet) {
{
$iErrorCode = self::EXIT_CODE_OK; $iErrorCode = self::EXIT_CODE_OK;
return self::LOGIN_FSM_RETURN; return self::LOGIN_FSM_RETURN;
} }
@@ -727,8 +667,7 @@ class LoginWebPage extends NiceWebPage
public static function SetLoginModeAndReload($sNewLoginMode) public static function SetLoginModeAndReload($sNewLoginMode)
{ {
if (Session::Get('login_mode') == $sNewLoginMode) if (Session::Get('login_mode') == $sNewLoginMode) {
{
return; return;
} }
Session::Set('login_mode', $sNewLoginMode); Session::Set('login_mode', $sNewLoginMode);
@@ -738,8 +677,7 @@ class LoginWebPage extends NiceWebPage
public static function HTTPReload() public static function HTTPReload()
{ {
$sOriginURL = utils::GetCurrentAbsoluteUrl(); $sOriginURL = utils::GetCurrentAbsoluteUrl();
if (!utils::StartsWith($sOriginURL, utils::GetAbsoluteUrlAppRoot())) if (!utils::StartsWith($sOriginURL, utils::GetAbsoluteUrlAppRoot())) {
{
// If the found URL does not start with the configured AppRoot URL // If the found URL does not start with the configured AppRoot URL
$sOriginURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php'; $sOriginURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php';
} }
@@ -753,7 +691,6 @@ class LoginWebPage extends NiceWebPage
exit; exit;
} }
/** /**
* Provisioning API: Find a User * Provisioning API: Find a User
* *
@@ -767,33 +704,28 @@ class LoginWebPage extends NiceWebPage
*/ */
public static function FindUser($sAuthUser, $bMustBeValid = true, $sType = 'External') public static function FindUser($sAuthUser, $bMustBeValid = true, $sType = 'External')
{ {
try try {
{ $aArgs = ['login' => $sAuthUser];
$aArgs = array('login' => $sAuthUser);
$sUserClass = "User$sType"; $sUserClass = "User$sType";
$oSearch = DBObjectSearch::FromOQL("SELECT $sUserClass WHERE login = :login"); $oSearch = DBObjectSearch::FromOQL("SELECT $sUserClass WHERE login = :login");
if ($bMustBeValid) if ($bMustBeValid) {
{
$oSearch->AddCondition('status', 'enabled'); $oSearch->AddCondition('status', 'enabled');
} }
$oSet = new DBObjectSet($oSearch, array(), $aArgs); $oSet = new DBObjectSet($oSearch, [], $aArgs);
if ($oSet->CountExceeds(0)) if ($oSet->CountExceeds(0)) {
{
/** @var User $oUser */ /** @var User $oUser */
$oUser = $oSet->Fetch(); $oUser = $oSet->Fetch();
return $oUser; return $oUser;
} }
} } catch (Exception $e) {
catch (Exception $e)
{
IssueLog::Error($e->getMessage()); IssueLog::Error($e->getMessage());
} }
return null; return null;
} }
/** /**
* Provisioning API: Find a Person by email * Provisioning API: Find a Person by email
* *
* @api * @api
* *
@@ -805,19 +737,15 @@ class LoginWebPage extends NiceWebPage
{ {
/** @var \Person $oPerson */ /** @var \Person $oPerson */
$oPerson = null; $oPerson = null;
try try {
{
$oSearch = new DBObjectSearch('Person'); $oSearch = new DBObjectSearch('Person');
$oSearch->AddCondition('email', $sEmail); $oSearch->AddCondition('email', $sEmail);
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
if ($oSet->CountExceeds(1)) if ($oSet->CountExceeds(1)) {
{
throw new Exception(Dict::S('UI:Login:Error:MultipleContactsHaveSameEmail')); throw new Exception(Dict::S('UI:Login:Error:MultipleContactsHaveSameEmail'));
} }
$oPerson = $oSet->Fetch(); $oPerson = $oSet->Fetch();
} } catch (Exception $e) {
catch (Exception $e)
{
IssueLog::Error($e->getMessage()); IssueLog::Error($e->getMessage());
} }
return $oPerson; return $oPerson;
@@ -836,16 +764,14 @@ class LoginWebPage extends NiceWebPage
* *
* @return \Person * @return \Person
*/ */
public static function ProvisionPerson($sFirstName, $sLastName, $sEmail, $sOrganization, $aAdditionalParams = array()) public static function ProvisionPerson($sFirstName, $sLastName, $sEmail, $sOrganization, $aAdditionalParams = [])
{ {
/** @var Person $oPerson */ /** @var Person $oPerson */
$oPerson = null; $oPerson = null;
try try {
{
CMDBObject::SetTrackOrigin('custom-extension'); CMDBObject::SetTrackOrigin('custom-extension');
$sInfo = 'External User provisioning'; $sInfo = 'External User provisioning';
if (Session::IsSet('login_mode')) if (Session::IsSet('login_mode')) {
{
$sInfo .= " (".Session::Get('login_mode').")"; $sInfo .= " (".Session::Get('login_mode').")";
} }
CMDBObject::SetTrackInfo($sInfo); CMDBObject::SetTrackInfo($sInfo);
@@ -855,19 +781,15 @@ class LoginWebPage extends NiceWebPage
$oPerson->Set('name', $sLastName); $oPerson->Set('name', $sLastName);
$oPerson->Set('email', $sEmail); $oPerson->Set('email', $sEmail);
$oOrg = MetaModel::GetObjectByName('Organization', $sOrganization, false); $oOrg = MetaModel::GetObjectByName('Organization', $sOrganization, false);
if (is_null($oOrg)) if (is_null($oOrg)) {
{
throw new Exception(Dict::S('UI:Login:Error:WrongOrganizationName')); throw new Exception(Dict::S('UI:Login:Error:WrongOrganizationName'));
} }
$oPerson->Set('org_id', $oOrg->GetKey()); $oPerson->Set('org_id', $oOrg->GetKey());
foreach ($aAdditionalParams as $sAttCode => $sValue) foreach ($aAdditionalParams as $sAttCode => $sValue) {
{
$oPerson->Set($sAttCode, $sValue); $oPerson->Set($sAttCode, $sValue);
} }
$oPerson->DBInsert(); $oPerson->DBInsert();
} } catch (Exception $e) {
catch (Exception $e)
{
IssueLog::Error($e->getMessage()); IssueLog::Error($e->getMessage());
} }
return $oPerson; return $oPerson;
@@ -886,27 +808,23 @@ class LoginWebPage extends NiceWebPage
*/ */
public static function ProvisionUser($sAuthUser, $oPerson, $aRequestedProfiles) public static function ProvisionUser($sAuthUser, $oPerson, $aRequestedProfiles)
{ {
if (!MetaModel::IsValidClass('URP_Profiles')) if (!MetaModel::IsValidClass('URP_Profiles')) {
{
IssueLog::Error("URP_Profiles is not a valid class. Automatic creation of Users is not supported in this context, sorry."); IssueLog::Error("URP_Profiles is not a valid class. Automatic creation of Users is not supported in this context, sorry.");
return null; return null;
} }
/** @var UserExternal $oUser */ /** @var UserExternal $oUser */
$oUser = null; $oUser = null;
try try {
{
CMDBObject::SetTrackOrigin('custom-extension'); CMDBObject::SetTrackOrigin('custom-extension');
$sInfo = 'External User provisioning'; $sInfo = 'External User provisioning';
if (Session::IsSet('login_mode')) if (Session::IsSet('login_mode')) {
{
$sInfo .= " (".Session::Get('login_mode').")"; $sInfo .= " (".Session::Get('login_mode').")";
} }
CMDBObject::SetTrackInfo($sInfo); CMDBObject::SetTrackInfo($sInfo);
$oUser = MetaModel::GetObjectByName('UserExternal', $sAuthUser, false); $oUser = MetaModel::GetObjectByName('UserExternal', $sAuthUser, false);
if (is_null($oUser)) if (is_null($oUser)) {
{
$oUser = MetaModel::NewObject('UserExternal'); $oUser = MetaModel::NewObject('UserExternal');
$oUser->Set('login', $sAuthUser); $oUser->Set('login', $sAuthUser);
$oUser->Set('contactid', $oPerson->GetKey()); $oUser->Set('contactid', $oPerson->GetKey());
@@ -916,41 +834,33 @@ class LoginWebPage extends NiceWebPage
// read all the existing profiles // read all the existing profiles
$oProfilesSearch = new DBObjectSearch('URP_Profiles'); $oProfilesSearch = new DBObjectSearch('URP_Profiles');
$oProfilesSet = new DBObjectSet($oProfilesSearch); $oProfilesSet = new DBObjectSet($oProfilesSearch);
$aAllProfiles = array(); $aAllProfiles = [];
while ($oProfile = $oProfilesSet->Fetch()) while ($oProfile = $oProfilesSet->Fetch()) {
{
$aAllProfiles[mb_strtolower($oProfile->GetName())] = $oProfile->GetKey(); $aAllProfiles[mb_strtolower($oProfile->GetName())] = $oProfile->GetKey();
} }
$aProfiles = array(); $aProfiles = [];
foreach ($aRequestedProfiles as $sRequestedProfile) foreach ($aRequestedProfiles as $sRequestedProfile) {
{
$sRequestedProfile = mb_strtolower($sRequestedProfile); $sRequestedProfile = mb_strtolower($sRequestedProfile);
if (isset($aAllProfiles[$sRequestedProfile])) if (isset($aAllProfiles[$sRequestedProfile])) {
{
$aProfiles[] = $aAllProfiles[$sRequestedProfile]; $aProfiles[] = $aAllProfiles[$sRequestedProfile];
} }
} }
if (empty($aProfiles)) if (empty($aProfiles)) {
{
throw new Exception(Dict::S('UI:Login:Error:NoValidProfiles')); throw new Exception(Dict::S('UI:Login:Error:NoValidProfiles'));
} }
// Now synchronize the profiles // Now synchronize the profiles
$sOrigin = 'External User provisioning'; $sOrigin = 'External User provisioning';
if (Session::IsSet('login_mode')) if (Session::IsSet('login_mode')) {
{
$sOrigin .= " (".Session::Get('login_mode').")"; $sOrigin .= " (".Session::Get('login_mode').")";
} }
$aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin); $aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin);
if ($oUser->IsModified()) if ($oUser->IsModified()) {
{
$oUser->DBWrite(); $oUser->DBWrite();
} }
} } catch (Exception $e) {
catch (Exception $e)
{
IssueLog::Error($e->getMessage()); IssueLog::Error($e->getMessage());
} }
@@ -961,26 +871,18 @@ class LoginWebPage extends NiceWebPage
* Overridable: depending on the user, head toward a dedicated portal * Overridable: depending on the user, head toward a dedicated portal
* @param string|null $sRequestedPortalId * @param string|null $sRequestedPortalId
* @param int $iOnExit How to complete the call: redirect or return a code * @param int $iOnExit How to complete the call: redirect or return a code
*/ */
protected static function ChangeLocation($sRequestedPortalId = null, $iOnExit = self::EXIT_PROMPT) protected static function ChangeLocation($sRequestedPortalId = null, $iOnExit = self::EXIT_PROMPT)
{ {
$ret = call_user_func(array(self::$sHandlerClass, 'Dispatch'), $sRequestedPortalId); $ret = call_user_func([self::$sHandlerClass, 'Dispatch'], $sRequestedPortalId);
if ($ret === true) if ($ret === true) {
{
return self::EXIT_CODE_OK; return self::EXIT_CODE_OK;
} } elseif ($ret === false) {
else if($ret === false)
{
throw new Exception('Nowhere to go: Your combination of user Profiles denies you access to any '.ITOP_APPLICATION_SHORT.' portal. Please contact your administrator'); throw new Exception('Nowhere to go: Your combination of user Profiles denies you access to any '.ITOP_APPLICATION_SHORT.' portal. Please contact your administrator');
} } else {
else if ($iOnExit == self::EXIT_RETURN) {
{
if ($iOnExit == self::EXIT_RETURN)
{
return self::EXIT_CODE_PORTALUSERNOTAUTHORIZED; return self::EXIT_CODE_PORTALUSERNOTAUTHORIZED;
} } else {
else
{
// No rights to be here, redirect to the portal // No rights to be here, redirect to the portal
header('Location: '.$ret); header('Location: '.$ret);
die(); die();
@@ -1002,7 +904,7 @@ class LoginWebPage extends NiceWebPage
* @return int|mixed|string * @return int|mixed|string
* @throws \Exception * @throws \Exception
*/ */
static function DoLogin($bMustBeAdmin = false, $bIsAllowedToPortalUsers = false, $iOnExit = self::EXIT_PROMPT) public static function DoLogin($bMustBeAdmin = false, $bIsAllowedToPortalUsers = false, $iOnExit = self::EXIT_PROMPT)
{ {
$sRequestedPortalId = $bIsAllowedToPortalUsers ? 'legacy_portal' : 'backoffice'; $sRequestedPortalId = $bIsAllowedToPortalUsers ? 'legacy_portal' : 'backoffice';
return self::DoLoginEx($sRequestedPortalId, $bMustBeAdmin, $iOnExit); return self::DoLoginEx($sRequestedPortalId, $bMustBeAdmin, $iOnExit);
@@ -1019,23 +921,18 @@ class LoginWebPage extends NiceWebPage
* @return int|mixed|string * @return int|mixed|string
* @throws \Exception * @throws \Exception
*/ */
static function DoLoginEx($sRequestedPortalId = null, $bMustBeAdmin = false, $iOnExit = self::EXIT_PROMPT) public static function DoLoginEx($sRequestedPortalId = null, $bMustBeAdmin = false, $iOnExit = self::EXIT_PROMPT)
{ {
$operation = utils::ReadParam('loginop', ''); $operation = utils::ReadParam('loginop', '');
$sMessage = self::HandleOperations($operation); // May exit directly $sMessage = self::HandleOperations($operation); // May exit directly
$iRet = self::Login($iOnExit); $iRet = self::Login($iOnExit);
if ($iRet == self::EXIT_CODE_OK) if ($iRet == self::EXIT_CODE_OK) {
{ if ($bMustBeAdmin && !UserRights::IsAdministrator()) {
if ($bMustBeAdmin && !UserRights::IsAdministrator()) if ($iOnExit == self::EXIT_RETURN) {
{
if ($iOnExit == self::EXIT_RETURN)
{
return self::EXIT_CODE_MUSTBEADMIN; return self::EXIT_CODE_MUSTBEADMIN;
} } else {
else
{
require_once(APPROOT.'/setup/setuppage.class.inc.php'); require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError')); $oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:Login:Error:AccessAdmin')."</h1>\n"); $oP->add("<h1>".Dict::S('UI:Login:Error:AccessAdmin')."</h1>\n");
@@ -1044,69 +941,52 @@ class LoginWebPage extends NiceWebPage
exit; exit;
} }
} }
$iRet = call_user_func(array(self::$sHandlerClass, 'ChangeLocation'), $sRequestedPortalId, $iOnExit); $iRet = call_user_func([self::$sHandlerClass, 'ChangeLocation'], $sRequestedPortalId, $iOnExit);
} }
if ($iOnExit == self::EXIT_RETURN) if ($iOnExit == self::EXIT_RETURN) {
{
return $iRet; return $iRet;
} } else {
else
{
return $sMessage; return $sMessage;
} }
} }
protected static function HandleOperations($operation) protected static function HandleOperations($operation)
{ {
$sMessage = ''; // most of the operations never return, but some can return a message to be displayed $sMessage = ''; // most of the operations never return, but some can return a message to be displayed
if ($operation == 'logoff') if ($operation == 'logoff') {
{
self::ResetSession(); self::ResetSession();
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayLoginForm(false /* not a failed attempt */); $oPage->DisplayLoginForm(false /* not a failed attempt */);
$oPage->output(); $oPage->output();
exit; exit;
} } elseif ($operation == 'forgot_pwd') {
else if ($operation == 'forgot_pwd')
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayForgotPwdForm(); $oPage->DisplayForgotPwdForm();
$oPage->output(); $oPage->output();
exit; exit;
} } elseif ($operation == 'forgot_pwd_go') {
else if ($operation == 'forgot_pwd_go')
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->ForgotPwdGo(); $oPage->ForgotPwdGo();
$oPage->output(); $oPage->output();
exit; exit;
} } elseif ($operation == 'reset_pwd') {
else if ($operation == 'reset_pwd')
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayResetPwdForm(); $oPage->DisplayResetPwdForm();
$oPage->output(); $oPage->output();
exit; exit;
} } elseif ($operation == 'do_reset_pwd') {
else if ($operation == 'do_reset_pwd')
{
try { try {
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DoResetPassword(); $oPage->DoResetPassword();
} } catch (CoreCannotSaveObjectException $e) {
catch (CoreCannotSaveObjectException $e)
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayResetPwdForm($e->getIssue()); $oPage->DisplayResetPwdForm($e->getIssue());
} }
$oPage->output(); $oPage->output();
exit; exit;
} } elseif ($operation == 'change_pwd') {
else if ($operation == 'change_pwd') if (Session::IsSet('auth_user')) {
{
if (Session::IsSet('auth_user'))
{
$sAuthUser = Session::Get('auth_user'); $sAuthUser = Session::Get('auth_user');
$sIssue = Session::Get('pwd_issue'); $sIssue = Session::Get('pwd_issue');
Session::Unset('pwd_issue'); Session::Unset('pwd_issue');
@@ -1118,16 +998,13 @@ class LoginWebPage extends NiceWebPage
$oPage->output(); $oPage->output();
exit; exit;
} }
} } elseif ($operation == 'check_pwd_policy') {
else if ($operation == 'check_pwd_policy')
{
$sAuthUser = Session::Get('auth_user'); $sAuthUser = Session::Get('auth_user');
UserRights::Login($sAuthUser); // Set the user's language UserRights::Login($sAuthUser); // Set the user's language
$aPwdMap = array(); $aPwdMap = [];
foreach (array('new_pwd', 'retype_new_pwd') as $postedPwd) foreach (['new_pwd', 'retype_new_pwd'] as $postedPwd) {
{
$oUser = new UserLocal(); $oUser = new UserLocal();
$oUser->ValidatePassword($_POST[$postedPwd]); $oUser->ValidatePassword($_POST[$postedPwd]);
@@ -1137,27 +1014,21 @@ class LoginWebPage extends NiceWebPage
echo json_encode($aPwdMap); echo json_encode($aPwdMap);
die(); die();
} }
if ($operation == 'do_change_pwd') if ($operation == 'do_change_pwd') {
{ if (Session::IsSet('auth_user')) {
if (Session::IsSet('auth_user'))
{
$sAuthUser = Session::Get('auth_user'); $sAuthUser = Session::Get('auth_user');
UserRights::Login($sAuthUser); // Set the user's language UserRights::Login($sAuthUser); // Set the user's language
$sOldPwd = utils::ReadPostedParam('old_pwd', '', 'raw_data'); $sOldPwd = utils::ReadPostedParam('old_pwd', '', 'raw_data');
$sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data'); $sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data');
try try {
{ if (UserRights::CanChangePassword() && ((!UserRights::CheckCredentials($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd)))) {
if (UserRights::CanChangePassword() && ((!UserRights::CheckCredentials($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd))))
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayChangePwdForm(true); // old pwd was wrong $oPage->DisplayChangePwdForm(true); // old pwd was wrong
$oPage->output(); $oPage->output();
exit; exit;
} }
} } catch (CoreCannotSaveObjectException $e) {
catch (CoreCannotSaveObjectException $e)
{
$oPage = self::NewLoginWebPage(); $oPage = self::NewLoginWebPage();
$oPage->DisplayChangePwdForm(true, $e->getIssue()); // password policy was not met. $oPage->DisplayChangePwdForm(true, $e->getIssue()); // password policy was not met.
$oPage->output(); $oPage->output();
@@ -1168,26 +1039,27 @@ class LoginWebPage extends NiceWebPage
} }
return $sMessage; return $sMessage;
} }
protected static function Dispatch($sRequestedPortalId) protected static function Dispatch($sRequestedPortalId)
{ {
if ($sRequestedPortalId === null) return true; // allowed to any portal => return true if ($sRequestedPortalId === null) {
return true;
} // allowed to any portal => return true
$aPortalsConf = PortalDispatcherData::GetData(); $aPortalsConf = PortalDispatcherData::GetData();
$aDispatchers = array(); $aDispatchers = [];
foreach($aPortalsConf as $sPortalId => $aConf) foreach ($aPortalsConf as $sPortalId => $aConf) {
{
$sHandlerClass = $aConf['handler']; $sHandlerClass = $aConf['handler'];
$aDispatchers[$sPortalId] = new $sHandlerClass($sPortalId); $aDispatchers[$sPortalId] = new $sHandlerClass($sPortalId);
} }
if (array_key_exists($sRequestedPortalId, $aDispatchers) && $aDispatchers[$sRequestedPortalId]->IsUserAllowed()) if (array_key_exists($sRequestedPortalId, $aDispatchers) && $aDispatchers[$sRequestedPortalId]->IsUserAllowed()) {
{
return true; return true;
} }
foreach($aDispatchers as $sPortalId => $oDispatcher) foreach ($aDispatchers as $sPortalId => $oDispatcher) {
{ if ($oDispatcher->IsUserAllowed()) {
if ($oDispatcher->IsUserAllowed()) return $oDispatcher->GetUrl(); return $oDispatcher->GetUrl();
}
} }
return false; // nothing matched !! return false; // nothing matched !!
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -17,7 +18,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
*/ */
// //
// Maintenance message display functions // Maintenance message display functions
// Only included by approot.inc.php // Only included by approot.inc.php
@@ -33,21 +33,17 @@ function _MaintenanceSetupPageMessage($sTitle, $sMessage)
{ {
// Web Page // Web Page
@include_once(APPROOT.'setup/setuppage.class.inc.php'); @include_once(APPROOT.'setup/setuppage.class.inc.php');
if (class_exists('SetupPage')) if (class_exists('SetupPage')) {
{
$oP = new ErrorPage($sTitle); $oP = new ErrorPage($sTitle);
$oP->p("<h2 class=\"center\">$sMessage</h2>"); $oP->p("<h2 class=\"center\">$sMessage</h2>");
$oP->add_ready_script( $oP->add_ready_script(
<<<JS <<<JS
// Reload in 30s to check if maintenance is over // Reload in 30s to check if maintenance is over
setTimeout(function(){ window.location.reload(); }, 30000); setTimeout(function(){ window.location.reload(); }, 30000);
JS JS
); );
$oP->output(); $oP->output();
} } else {
else
{
_MaintenanceTextMessage($sMessage); _MaintenanceTextMessage($sMessage);
} }
} }
@@ -78,14 +74,13 @@ function _MaintenanceHtmlMessage($sMessage)
*/ */
function _MaintenanceJsonMessage($sTitle, $sMessage) function _MaintenanceJsonMessage($sTitle, $sMessage)
{ {
if (class_exists('JsonPage')) if (class_exists('JsonPage')) {
{
$oP = new JsonPage($sTitle); $oP = new JsonPage($sTitle);
$oP->add_header('Access-Control-Allow-Origin: *'); $oP->add_header('Access-Control-Allow-Origin: *');
$aMessage = [ $aMessage = [
'code' => 100, 'code' => 100,
'message' =>$sMessage 'message' => $sMessage,
]; ];
$oP->AddData($aMessage); $oP->AddData($aMessage);

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -13,7 +14,6 @@ require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/application/template.class.inc.php'); require_once(APPROOT.'/application/template.class.inc.php');
require_once(APPROOT."/application/user.dashboard.class.inc.php"); require_once(APPROOT."/application/user.dashboard.class.inc.php");
/** /**
* This class manipulates, stores and displays the navigation menu used in the application * 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 * In order to improve the modularity of the data model and to ease the update/migration
@@ -52,43 +52,40 @@ class ApplicationMenu
/** /**
* @var bool * @var bool
*/ */
static $bAdditionalMenusLoaded = false; public static $bAdditionalMenusLoaded = false;
/** /**
* @var array * @var array
*/ */
static $aRootMenus = array(); public static $aRootMenus = [];
/** /**
* @var array * @var array
*/ */
static $aMenusIndex = array(); public static $aMenusIndex = [];
/** /**
* @var array * @var array
*/ */
static $aMenusById = []; public static $aMenusById = [];
/** /**
* @var string * @var string
*/ */
static $sFavoriteSiloQuery = 'SELECT Organization'; public static $sFavoriteSiloQuery = 'SELECT Organization';
/** /**
* @return void * @return void
*/ */
public static function LoadAdditionalMenus() public static function LoadAdditionalMenus()
{ {
if (!self::$bAdditionalMenusLoaded) if (!self::$bAdditionalMenusLoaded) {
{
// Build menus from module handlers // Build menus from module handlers
// //
/** @var \ModuleHandlerApiInterface $oPHPClass */ /** @var \ModuleHandlerApiInterface $oPHPClass */
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
{ $oPHPClass::OnMenuCreation();
$oPHPClass::OnMenuCreation(); }
}
// Build menus from the menus themselves (e.g. the ShortcutContainerMenuNode will do that) // 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 = self::GetMenuNode($aMenu['index']);
$oMenuNode->PopulateChildMenus(); $oMenuNode->PopulateChildMenus();
} }
@@ -125,8 +122,7 @@ class ApplicationMenu
*/ */
public static function CheckMenuIdEnabled($sMenuId) public static function CheckMenuIdEnabled($sMenuId)
{ {
if (self::IsMenuIdEnabled($sMenuId) === false) if (self::IsMenuIdEnabled($sMenuId) === false) {
{
require_once(APPROOT.'/setup/setuppage.class.inc.php'); require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError')); $oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
$oP->add("<h1>".Dict::S('UI:Login:Error:AccessRestricted')."</h1>\n"); $oP->add("<h1>".Dict::S('UI:Login:Error:AccessRestricted')."</h1>\n");
@@ -142,7 +138,7 @@ class ApplicationMenu
* @return bool true if the menu exists and current user is allowed to see the menu * @return bool true if the menu exists and current user is allowed to see the menu
* @since 3.2.0 * @since 3.2.0
*/ */
public static function IsMenuIdEnabled($sMenuId):bool public static function IsMenuIdEnabled($sMenuId): bool
{ {
self::LoadAdditionalMenus(); self::LoadAdditionalMenus();
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId)); $oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
@@ -160,22 +156,18 @@ class ApplicationMenu
public static function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank) public static function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
{ {
$index = self::GetMenuIndexById($oMenuNode->GetMenuId()); $index = self::GetMenuIndexById($oMenuNode->GetMenuId());
if ($index == -1) if ($index == -1) {
{
// The menu does not already exist, insert it // The menu does not already exist, insert it
$index = count(self::$aMenusIndex); $index = count(self::$aMenusIndex);
if ($iParentIndex == -1) if ($iParentIndex == -1) {
{
$sParentId = ''; $sParentId = '';
self::$aRootMenus[] = array ('rank' => $fRank, 'index' => $index); self::$aRootMenus[] = ['rank' => $fRank, 'index' => $index];
} } else {
else
{
/** @var \MenuNode $oNode */ /** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$iParentIndex]['node']; $oNode = self::$aMenusIndex[$iParentIndex]['node'];
$sParentId = $oNode->GetMenuId(); $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, // Note: At the time when 'parent', 'rank' and 'source_file' have been added for the reflection API,
@@ -183,11 +175,9 @@ class ApplicationMenu
// //
$aBacktrace = debug_backtrace(); $aBacktrace = debug_backtrace();
$sFile = isset($aBacktrace[2]["file"]) ? $aBacktrace[2]["file"] : $aBacktrace[1]["file"]; $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; self::$aMenusById[$oMenuNode->GetMenuId()] = $index;
} } else {
else
{
// the menu already exists, let's combine the conditions that make it visible // the menu already exists, let's combine the conditions that make it visible
/** @var \MenuNode $oNode */ /** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$index]['node']; $oNode = self::$aMenusIndex[$index]['node'];
@@ -217,7 +207,7 @@ class ApplicationMenu
* @throws \DictExceptionMissingString * @throws \DictExceptionMissingString
* @since 3.0.0 * @since 3.0.0
*/ */
public static function GetMenusCount($aExtraParams = array()) public static function GetMenusCount($aExtraParams = [])
{ {
$aMenuGroups = static::GetMenuGroups($aExtraParams); $aMenuGroups = static::GetMenuGroups($aExtraParams);
@@ -260,18 +250,16 @@ class ApplicationMenu
* @throws \DictExceptionMissingString * @throws \DictExceptionMissingString
* @since 3.0.0 * @since 3.0.0
*/ */
public static function GetMenuGroups($aExtraParams = array()) public static function GetMenuGroups($aExtraParams = [])
{ {
self::LoadAdditionalMenus(); self::LoadAdditionalMenus();
// Sort the root menu based on the rank // Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank')); usort(self::$aRootMenus, ['ApplicationMenu', 'CompareOnRank']);
$aMenuGroups = []; $aMenuGroups = [];
foreach(static::$aRootMenus as $aMenuGroup) foreach (static::$aRootMenus as $aMenuGroup) {
{ if (!static::CanDisplayMenu($aMenuGroup)) {
if(!static::CanDisplayMenu($aMenuGroup))
{
continue; continue;
} }
@@ -322,26 +310,23 @@ class ApplicationMenu
* @throws \Exception * @throws \Exception
* @since 3.0.0 * @since 3.0.0
*/ */
public static function GetSubMenuNodes($sMenuGroupIdx, $aExtraParams = array()) public static function GetSubMenuNodes($sMenuGroupIdx, $aExtraParams = [])
{ {
$aSubMenuItems = self::GetChildren($sMenuGroupIdx); $aSubMenuItems = self::GetChildren($sMenuGroupIdx);
// Sort the children based on the rank // Sort the children based on the rank
usort($aSubMenuItems, array('ApplicationMenu', 'CompareOnRank')); usort($aSubMenuItems, ['ApplicationMenu', 'CompareOnRank']);
$aSubMenuNodes = []; $aSubMenuNodes = [];
foreach($aSubMenuItems as $aSubMenuItem) foreach ($aSubMenuItems as $aSubMenuItem) {
{ if (!static::CanDisplayMenu($aSubMenuItem)) {
if(!static::CanDisplayMenu($aSubMenuItem))
{
continue; continue;
} }
$sSubMenuItemIdx = $aSubMenuItem['index']; $sSubMenuItemIdx = $aSubMenuItem['index'];
$oSubMenuNode = static::GetMenuNode($sSubMenuItemIdx); $oSubMenuNode = static::GetMenuNode($sSubMenuItemIdx);
if(!$oSubMenuNode->IsEnabled()) if (!$oSubMenuNode->IsEnabled()) {
{
continue; continue;
} }
@@ -372,7 +357,7 @@ class ApplicationMenu
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetMenuGroups() instead'); DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetMenuGroups() instead');
self::LoadAdditionalMenus(); self::LoadAdditionalMenus();
// Sort the root menu based on the rank // Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank')); usort(self::$aRootMenus, ['ApplicationMenu', 'CompareOnRank']);
$iAccordion = 0; $iAccordion = 0;
$iActiveAccordion = $iAccordion; $iActiveAccordion = $iAccordion;
$iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId()); $iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
@@ -387,8 +372,7 @@ class ApplicationMenu
$aChildren = self::GetChildren($aMenu['index']); $aChildren = self::GetChildren($aMenu['index']);
$bActive = self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu); $bActive = self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
$oPage->AddToMenu('</ul>'); $oPage->AddToMenu('</ul>');
if ($bActive) if ($bActive) {
{
$iActiveAccordion = $iAccordion; $iActiveAccordion = $iAccordion;
} }
$oPage->AddToMenu('</div>'); $oPage->AddToMenu('</div>');
@@ -396,7 +380,7 @@ class ApplicationMenu
} }
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
// Accordion Menu // Accordion Menu
$("#accordion").css({display:'block'}).accordion({ header: "h3", heightStyle: "content", collapsible: true, active: $iActiveAccordion, icons: false, animate: true }); // collapsible will be enabled once the item will be selected $("#accordion").css({display:'block'}).accordion({ header: "h3", heightStyle: "content", collapsible: true, active: $iActiveAccordion, icons: false, animate: true }); // collapsible will be enabled once the item will be selected
EOF EOF
@@ -411,21 +395,15 @@ EOF
private static function CanDisplayMenu($aMenu) private static function CanDisplayMenu($aMenu)
{ {
$oMenuNode = self::GetMenuNode($aMenu['index']); $oMenuNode = self::GetMenuNode($aMenu['index']);
if ($oMenuNode->IsEnabled()) if ($oMenuNode->IsEnabled()) {
{
$aChildren = self::GetChildren($aMenu['index']); $aChildren = self::GetChildren($aMenu['index']);
if (count($aChildren) > 0) if (count($aChildren) > 0) {
{ foreach ($aChildren as $aSubMenu) {
foreach($aChildren as $aSubMenu) if (self::CanDisplayMenu($aSubMenu)) {
{
if (self::CanDisplayMenu($aSubMenu))
{
return true; return true;
} }
} }
} } else {
else
{
return true; return true;
} }
} }
@@ -450,46 +428,38 @@ EOF
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetSubMenuNodes() instead'); DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetSubMenuNodes() instead');
// Sort the menu based on the rank // Sort the menu based on the rank
$bActive = false; $bActive = false;
usort($aMenus, array('ApplicationMenu', 'CompareOnRank')); usort($aMenus, ['ApplicationMenu', 'CompareOnRank']);
foreach ($aMenus as $aMenu) { foreach ($aMenus as $aMenu) {
if (!self::CanDisplayMenu($aMenu)) { if (!self::CanDisplayMenu($aMenu)) {
continue; continue;
} }
$index = $aMenu['index']; $index = $aMenu['index'];
$oMenu = self::GetMenuNode($index); $oMenu = self::GetMenuNode($index);
if ($oMenu->IsEnabled()) if ($oMenu->IsEnabled()) {
{
$aChildren = self::GetChildren($index); $aChildren = self::GetChildren($index);
$aCSSClasses = array('navigation-menu-item'); $aCSSClasses = ['navigation-menu-item'];
if (count($aChildren) > 0) if (count($aChildren) > 0) {
{
$aCSSClasses[] = 'submenu'; $aCSSClasses[] = 'submenu';
} }
$sHyperlink = $oMenu->GetHyperlink($aExtraParams); $sHyperlink = $oMenu->GetHyperlink($aExtraParams);
$sItemHtml = '<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" class="'.implode(' ', $aCSSClasses).'" data-menu-id="'.$oMenu->GetMenuID().'">'; $sItemHtml = '<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" class="'.implode(' ', $aCSSClasses).'" data-menu-id="'.$oMenu->GetMenuID().'">';
if ($sHyperlink != '') if ($sHyperlink != '') {
{
$sLinkTarget = ''; $sLinkTarget = '';
if ($oMenu->IsHyperLinkInNewWindow()) if ($oMenu->IsHyperLinkInNewWindow()) {
{
$sLinkTarget .= ' target="_blank"'; $sLinkTarget .= ' target="_blank"';
} }
$sURL = '"'.$oMenu->GetHyperlink($aExtraParams).'"'.$sLinkTarget; $sURL = '"'.$oMenu->GetHyperlink($aExtraParams).'"'.$sLinkTarget;
$sTitle = utils::HtmlEntities($oMenu->GetTitle()); $sTitle = utils::HtmlEntities($oMenu->GetTitle());
$sItemHtml .= "<a href={$sURL}>{$sTitle}</a>"; $sItemHtml .= "<a href={$sURL}>{$sTitle}</a>";
} } else {
else
{
$sItemHtml .= $oMenu->GetTitle(); $sItemHtml .= $oMenu->GetTitle();
} }
$sItemHtml .= '</li>'; $sItemHtml .= '</li>';
$oPage->AddToMenu($sItemHtml); $oPage->AddToMenu($sItemHtml);
if ($iActiveMenu == $index) if ($iActiveMenu == $index) {
{
$bActive = true; $bActive = true;
} }
if (count($aChildren) > 0) if (count($aChildren) > 0) {
{
$oPage->AddToMenu('<ul>'); $oPage->AddToMenu('<ul>');
$bActive |= self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu); $bActive |= self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
$oPage->AddToMenu('</ul>'); $oPage->AddToMenu('</ul>');
@@ -508,12 +478,10 @@ EOF
public static function CompareOnRank($a, $b) public static function CompareOnRank($a, $b)
{ {
$result = 1; $result = 1;
if ($a['rank'] == $b['rank']) if ($a['rank'] == $b['rank']) {
{
$result = 0; $result = 0;
} }
if ($a['rank'] < $b['rank']) if ($a['rank'] < $b['rank']) {
{
$result = -1; $result = -1;
} }
return $result; return $result;
@@ -561,8 +529,7 @@ EOF
{ {
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sMenuId = $oAppContext->GetCurrentValue('menu', null); $sMenuId = $oAppContext->GetCurrentValue('menu', null);
if ($sMenuId === null) if ($sMenuId === null) {
{
$sMenuId = self::GetDefaultMenuId(); $sMenuId = self::GetDefaultMenuId();
} }
return $sMenuId; return $sMenuId;
@@ -574,13 +541,12 @@ EOF
public static function GetDefaultMenuId() public static function GetDefaultMenuId()
{ {
static $sDefaultMenuId = null; static $sDefaultMenuId = null;
if (is_null($sDefaultMenuId)) if (is_null($sDefaultMenuId)) {
{
// Make sure the root menu is sorted on 'rank' // 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']); $oFirstGroup = self::GetMenuNode(self::$aRootMenus[0]['index']);
$aChildren = self::$aMenusIndex[$oFirstGroup->GetIndex()]['children']; $aChildren = self::$aMenusIndex[$oFirstGroup->GetIndex()]['children'];
usort($aChildren, array('ApplicationMenu', 'CompareOnRank')); usort($aChildren, ['ApplicationMenu', 'CompareOnRank']);
$oMenuNode = self::GetMenuNode($aChildren[0]['index']); $oMenuNode = self::GetMenuNode($aChildren[0]['index']);
$sDefaultMenuId = $oMenuNode->GetMenuId(); $sDefaultMenuId = $oMenuNode->GetMenuId();
} }
@@ -594,13 +560,11 @@ EOF
public static function GetRootMenuId($sMenuId) public static function GetRootMenuId($sMenuId)
{ {
$iMenuIndex = self::GetMenuIndexById($sMenuId); $iMenuIndex = self::GetMenuIndexById($sMenuId);
if ($iMenuIndex == -1) if ($iMenuIndex == -1) {
{
return ''; return '';
} }
$oMenu = ApplicationMenu::GetMenuNode($iMenuIndex); $oMenu = ApplicationMenu::GetMenuNode($iMenuIndex);
while ($oMenu->GetParentIndex() != -1) while ($oMenu->GetParentIndex() != -1) {
{
$oMenu = ApplicationMenu::GetMenuNode($oMenu->GetParentIndex()); $oMenu = ApplicationMenu::GetMenuNode($oMenu->GetParentIndex());
} }
return $oMenu->GetMenuId(); return $oMenu->GetMenuId();
@@ -687,17 +651,17 @@ abstract class MenuNode
{ {
$this->sMenuId = $sMenuId; $this->sMenuId = $sMenuId;
$this->iParentIndex = $iParentIndex; $this->iParentIndex = $iParentIndex;
$this->aReflectionProperties = array(); $this->aReflectionProperties = [];
if (utils::IsNotNullOrEmptyString($sEnableClass)) { if (utils::IsNotNullOrEmptyString($sEnableClass)) {
$this->aReflectionProperties['enable_class'] = $sEnableClass; $this->aReflectionProperties['enable_class'] = $sEnableClass;
$this->aReflectionProperties['enable_action'] = $iActionCode; $this->aReflectionProperties['enable_action'] = $iActionCode;
$this->aReflectionProperties['enable_permission'] = $iAllowedResults; $this->aReflectionProperties['enable_permission'] = $iAllowedResults;
$this->aReflectionProperties['enable_stimulus'] = $sEnableStimulus; $this->aReflectionProperties['enable_stimulus'] = $sEnableStimulus;
} }
$this->m_aEnableClasses = array($sEnableClass); $this->m_aEnableClasses = [$sEnableClass];
$this->m_aEnableActions = array($iActionCode); $this->m_aEnableActions = [$iActionCode];
$this->m_aEnableActionResults = array($iAllowedResults); $this->m_aEnableActionResults = [$iAllowedResults];
$this->m_aEnableStimuli = array($sEnableStimulus); $this->m_aEnableStimuli = [$sEnableStimulus];
$this->index = ApplicationMenu::InsertMenu($this, $iParentIndex, $fRank); $this->index = ApplicationMenu::InsertMenu($this, $iParentIndex, $fRank);
} }
@@ -751,7 +715,6 @@ abstract class MenuNode
$oSearch->SetShowObsoleteData(utils::ShowObsoleteData()); $oSearch->SetShowObsoleteData(utils::ShowObsoleteData());
DBSearchHelper::AddContextFilter($oSearch); DBSearchHelper::AddContextFilter($oSearch);
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
$iCount = $oSet->CountWithLimit(99); $iCount = $oSet->CountWithLimit(99);
if ($iCount > 99) { if ($iCount > 99) {
@@ -802,8 +765,7 @@ abstract class MenuNode
*/ */
public function PopulateChildMenus() public function PopulateChildMenus()
{ {
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu) foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu) {
{
$index = $aMenu['index']; $index = $aMenu['index'];
$oMenu = ApplicationMenu::GetMenuNode($index); $oMenu = ApplicationMenu::GetMenuNode($index);
$oMenu->PopulateChildMenus(); $oMenu->PopulateChildMenus();
@@ -838,8 +800,7 @@ abstract class MenuNode
*/ */
public function AddCondition(MenuNode $oMenuNode) 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_aEnableClasses[] = $sClass;
$this->m_aEnableActions[] = $oMenuNode->m_aEnableActions[$index]; $this->m_aEnableActions[] = $oMenuNode->m_aEnableActions[$index];
$this->m_aEnableActionResults[] = $oMenuNode->m_aEnableActionResults[$index]; $this->m_aEnableActionResults[] = $oMenuNode->m_aEnableActionResults[$index];
@@ -852,33 +813,24 @@ abstract class MenuNode
*/ */
public function IsEnabled() public function IsEnabled()
{ {
foreach($this->m_aEnableClasses as $index => $sClass) foreach ($this->m_aEnableClasses as $index => $sClass) {
{ if ($sClass != null) {
if ($sClass != null) if (MetaModel::IsValidClass($sClass)) {
{ if ($this->m_aEnableStimuli[$index] != null) {
if (MetaModel::IsValidClass($sClass)) if (!UserRights::IsStimulusAllowed($sClass, $this->m_aEnableStimuli[$index])) {
{
if ($this->m_aEnableStimuli[$index] != null)
{
if (!UserRights::IsStimulusAllowed($sClass, $this->m_aEnableStimuli[$index]))
{
return false; return false;
} }
} }
if ($this->m_aEnableActions[$index] != null) if ($this->m_aEnableActions[$index] != null) {
{
// Menus access rights ignore the archive mode // Menus access rights ignore the archive mode
utils::PushArchiveMode(false); utils::PushArchiveMode(false);
$iResult = UserRights::IsActionAllowed($sClass, $this->m_aEnableActions[$index]); $iResult = UserRights::IsActionAllowed($sClass, $this->m_aEnableActions[$index]);
utils::PopArchiveMode(); utils::PopArchiveMode();
if (!($iResult & $this->m_aEnableActionResults[$index])) if (!($iResult & $this->m_aEnableActionResults[$index])) {
{
return false; return false;
} }
} }
} } else {
else
{
return false; return false;
} }
} }
@@ -891,7 +843,7 @@ abstract class MenuNode
* @param array $aExtraParams * @param array $aExtraParams
* @return mixed * @return mixed
*/ */
public abstract function RenderContent(WebPage $oPage, $aExtraParams = array()); abstract public function RenderContent(WebPage $oPage, $aExtraParams = []);
/** /**
* @param string $sHyperlink * @param string $sHyperlink
@@ -900,16 +852,13 @@ abstract class MenuNode
*/ */
protected function AddParams($sHyperlink, $aExtraParams) protected function AddParams($sHyperlink, $aExtraParams)
{ {
if (count($aExtraParams) > 0) if (count($aExtraParams) > 0) {
{ $aQuery = [];
$aQuery = array();
$sSeparator = '?'; $sSeparator = '?';
if (strpos($sHyperlink, '?') !== false) if (strpos($sHyperlink, '?') !== false) {
{
$sSeparator = '&'; $sSeparator = '&';
} }
foreach($aExtraParams as $sName => $sValue) foreach ($aExtraParams as $sName => $sValue) {
{
$aQuery[] = urlencode($sName).'='.urlencode($sValue); $aQuery[] = urlencode($sName).'='.urlencode($sValue);
} }
$sHyperlink .= $sSeparator.implode('&', $aQuery); $sHyperlink .= $sSeparator.implode('&', $aQuery);
@@ -925,7 +874,7 @@ abstract class MenuNode
class MenuGroup extends 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 */ /** @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 */ /** @var string The CSS classes used to display the menu group's icon */
protected $sDecorationClasses = self::DEFAULT_DECORATION_CLASSES; protected $sDecorationClasses = self::DEFAULT_DECORATION_CLASSES;
@@ -945,8 +894,7 @@ class MenuGroup extends MenuNode
{ {
parent::__construct($sMenuId, -1 /* no parent, groups are at root level */, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus); 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; $this->sDecorationClasses = $sDecorationClasses;
} }
} }
@@ -987,7 +935,7 @@ class MenuGroup extends MenuNode
/** /**
* @inheritDoc * @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 assert(false); // Shall never be called, groups do not display any content
} }
@@ -1027,7 +975,9 @@ class TemplateMenuNode extends MenuNode
*/ */
public function GetHyperlink($aExtraParams) public function GetHyperlink($aExtraParams)
{ {
if ($this->sTemplateFile == '') return ''; if ($this->sTemplateFile == '') {
return '';
}
return parent::GetHyperlink($aExtraParams); return parent::GetHyperlink($aExtraParams);
} }
@@ -1035,18 +985,15 @@ class TemplateMenuNode extends MenuNode
* @inheritDoc * @inheritDoc
* @throws \Exception * @throws \Exception
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$sTemplate = @file_get_contents($this->sTemplateFile); $sTemplate = @file_get_contents($this->sTemplateFile);
if ($sTemplate !== false) if ($sTemplate !== false) {
{
$aExtraParams['table_id'] = 'Menu_'.$this->GetMenuId(); $aExtraParams['table_id'] = 'Menu_'.$this->GetMenuId();
$oTemplate = new DisplayTemplate($sTemplate); $oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, $aExtraParams); $oTemplate->Render($oPage, $aExtraParams);
} } else {
else
{
$oPage->p("Error: failed to load template file: '{$this->sTemplateFile}'"); // No need to translate ? $oPage->p("Error: failed to load template file: '{$this->sTemplateFile}'"); // No need to translate ?
} }
} }
@@ -1080,7 +1027,6 @@ class OQLMenuNode extends MenuNode
*/ */
protected $m_aParams; protected $m_aParams;
/** /**
* Create a menu item based on an OQL query and inserts it into the application's main menu * 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) * @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
@@ -1101,7 +1047,7 @@ class OQLMenuNode extends MenuNode
$this->sOQL = $sOQL; $this->sOQL = $sOQL;
$this->bSearch = $bSearch; $this->bSearch = $bSearch;
$this->bSearchFormOpen = $bSearchFormOpen; $this->bSearchFormOpen = $bSearchFormOpen;
$this->m_aParams = array(); $this->m_aParams = [];
$this->aReflectionProperties['oql'] = $sOQL; $this->aReflectionProperties['oql'] = $sOQL;
$this->aReflectionProperties['do_search'] = $bSearch; $this->aReflectionProperties['do_search'] = $bSearch;
// Enhancement: we could set as the "enable" condition that the user has enough rights to "read" the objects // Enhancement: we could set as the "enable" condition that the user has enough rights to "read" the objects
@@ -1115,8 +1061,7 @@ class OQLMenuNode extends MenuNode
public function SetParameters($aParams) public function SetParameters($aParams)
{ {
$this->m_aParams = $aParams; $this->m_aParams = $aParams;
foreach($aParams as $sKey => $value) foreach ($aParams as $sKey => $value) {
{
$this->aReflectionProperties[$sKey] = $value; $this->aReflectionProperties[$sKey] = $value;
} }
} }
@@ -1125,12 +1070,11 @@ class OQLMenuNode extends MenuNode
* @inheritDoc * @inheritDoc
* @throws \Exception * @throws \Exception
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
$oTag = new ContextTag(ContextTag::TAG_OBJECT_SEARCH); $oTag = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
OQLMenuNode::RenderOQLSearch OQLMenuNode::RenderOQLSearch(
(
$this->sOQL, $this->sOQL,
Dict::S($this->sPageTitle), Dict::S($this->sPageTitle),
'Menu_'.$this->GetMenuId(), 'Menu_'.$this->GetMenuId(),
@@ -1155,26 +1099,25 @@ class OQLMenuNode extends MenuNode
* @throws DictExceptionMissingString * @throws DictExceptionMissingString
* @throws OQLException * @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); $sUsageId = utils::GetSafeId($sUsageId);
$oSearch = DBObjectSearch::FromOQL($sOql); $oSearch = DBObjectSearch::FromOQL($sOql);
$sClass= $oSearch->GetClass(); $sClass = $oSearch->GetClass();
$sIcon = MetaModel::GetClassIcon($sClass, false); $sIcon = MetaModel::GetClassIcon($sClass, false);
if ($bSearchPane) { if ($bSearchPane) {
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams); $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 = new DisplayBlock($oSearch, DisplayBlock::ENUM_STYLE_SEARCH, false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0); $oBlock->Display($oPage, 0);
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>"); $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'>"); $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_title'] = $sTitle;
$aExtraParams['panel_icon'] = $sIcon; $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 = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, $sUsageId); $oBlock->Display($oPage, $sUsageId);
@@ -1239,14 +1182,14 @@ class SearchMenuNode extends MenuNode
* @throws \DictExceptionMissingString * @throws \DictExceptionMissingString
* @throws \Exception * @throws \Exception
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES); $oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oSearch = new DBObjectSearch($this->sClass); $oSearch = new DBObjectSearch($this->sClass);
$sUsageId = 'Menu_'.utils::GetSafeId($this->GetMenuId()); $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 = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0); $oBlock->Display($oPage, 0);
} }
@@ -1283,10 +1226,16 @@ class WebPageMenuNode extends MenuNode
* @param bool $bIsLinkInNewWindow for the {@link WebPageMenuNode::IsHyperLinkInNewWindow} method * @param bool $bIsLinkInNewWindow for the {@link WebPageMenuNode::IsHyperLinkInNewWindow} method
*/ */
public function __construct( public function __construct(
$sMenuId, $sHyperlink, $iParentIndex, $fRank = 0.0, $sEnableClass = null, $iActionCode = null, $sMenuId,
$iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null, $bIsLinkInNewWindow = false $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); parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
$this->sHyperlink = $sHyperlink; $this->sHyperlink = $sHyperlink;
$this->aReflectionProperties['url'] = $sHyperlink; $this->aReflectionProperties['url'] = $sHyperlink;
@@ -1299,7 +1248,7 @@ class WebPageMenuNode extends MenuNode
public function GetHyperlink($aExtraParams) public function GetHyperlink($aExtraParams)
{ {
$aExtraParams['c[menu]'] = $this->GetMenuId(); $aExtraParams['c[menu]'] = $this->GetMenuId();
return $this->AddParams( $this->sHyperlink, $aExtraParams); return $this->AddParams($this->sHyperlink, $aExtraParams);
} }
/** /**
@@ -1313,7 +1262,7 @@ class WebPageMenuNode extends MenuNode
/** /**
* @inheritDoc * @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 assert(false); // Shall never be called, the external web page will handle the display by itself
} }
@@ -1374,10 +1323,8 @@ class NewObjectMenuNode extends MenuNode
$aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself $aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
$bActionIsAllowed = false; $bActionIsAllowed = false;
foreach($aSubClasses as $sCandidateClass) foreach ($aSubClasses as $sCandidateClass) {
{ if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
{
$bActionIsAllowed = true; $bActionIsAllowed = true;
break; // Enough for now break; // Enough for now
} }
@@ -1388,7 +1335,7 @@ class NewObjectMenuNode extends MenuNode
/** /**
* @inheritDoc * @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 assert(false); // Shall never be called, the external web page will handle the display by itself
} }
@@ -1428,7 +1375,9 @@ class DashboardMenuNode extends MenuNode
*/ */
public function GetHyperlink($aExtraParams) public function GetHyperlink($aExtraParams)
{ {
if ($this->sDashboardFile == '') return ''; if ($this->sDashboardFile == '') {
return '';
}
return parent::GetHyperlink($aExtraParams); return parent::GetHyperlink($aExtraParams);
} }
@@ -1446,12 +1395,11 @@ class DashboardMenuNode extends MenuNode
* @inheritDoc * @inheritDoc
* @throws \Exception * @throws \Exception
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$oDashboard = $this->GetDashboard(); $oDashboard = $this->GetDashboard();
if ($oDashboard != null) if ($oDashboard != null) {
{
WebResourcesHelper::EnableC3JSToWebPage($oPage); WebResourcesHelper::EnableC3JSToWebPage($oPage);
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier'); $sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
@@ -1482,9 +1430,7 @@ class DashboardMenuNode extends MenuNode
} }
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES); $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}'"); $oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
} }
} }
@@ -1497,12 +1443,9 @@ class DashboardMenuNode extends MenuNode
public function RenderEditor(WebPage $oPage) public function RenderEditor(WebPage $oPage)
{ {
$oDashboard = $this->GetDashboard(); $oDashboard = $this->GetDashboard();
if ($oDashboard != null) if ($oDashboard != null) {
{
$oDashboard->RenderEditor($oPage); $oDashboard->RenderEditor($oPage);
} } else {
else
{
$oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'"); $oPage->p("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
} }
} }
@@ -1514,13 +1457,10 @@ class DashboardMenuNode extends MenuNode
public function AddDashlet($oDashlet) public function AddDashlet($oDashlet)
{ {
$oDashboard = $this->GetDashboard(); $oDashboard = $this->GetDashboard();
if ($oDashboard != null) if ($oDashboard != null) {
{
$oDashboard->AddDashlet($oDashlet); $oDashboard->AddDashlet($oDashlet);
$oDashboard->Save(); $oDashboard->Save();
} } else {
else
{
throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'"); throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
} }
} }
@@ -1543,7 +1483,7 @@ class ShortcutContainerMenuNode extends MenuNode
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
} }
@@ -1558,10 +1498,9 @@ class ShortcutContainerMenuNode extends MenuNode
// //
$oBMSearch = new DBObjectSearch('Shortcut'); $oBMSearch = new DBObjectSearch('Shortcut');
$oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $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; $fRank = 1;
while ($oShortcut = $oBMSet->Fetch()) while ($oShortcut = $oBMSet->Fetch()) {
{
$sName = $this->GetMenuId().'_'.$oShortcut->GetKey(); $sName = $this->GetMenuId().'_'.$oShortcut->GetKey();
new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++); new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++);
} }
@@ -1572,7 +1511,6 @@ class ShortcutContainerMenuNode extends MenuNode
} }
} }
require_once(APPROOT.'application/shortcut.class.inc.php'); require_once(APPROOT.'application/shortcut.class.inc.php');
/** /**
* This class defines a menu item which content is a shortcut. * This class defines a menu item which content is a shortcut.
@@ -1609,12 +1547,10 @@ class ShortcutMenuNode extends MenuNode
{ {
$sContext = $this->oShortcut->Get('context'); $sContext = $this->oShortcut->Get('context');
$aContext = unserialize($sContext); $aContext = unserialize($sContext);
if (isset($aContext['menu'])) if (isset($aContext['menu'])) {
{
unset($aContext['menu']); unset($aContext['menu']);
} }
foreach ($aContext as $sArgName => $sArgValue) foreach ($aContext as $sArgName => $sArgValue) {
{
$aExtraParams[$sArgName] = $sArgValue; $aExtraParams[$sArgName] = $sArgValue;
} }
return parent::GetHyperlink($aExtraParams); return parent::GetHyperlink($aExtraParams);
@@ -1624,7 +1560,7 @@ class ShortcutMenuNode extends MenuNode
* @inheritDoc * @inheritDoc
* @throws \Exception * @throws \Exception
*/ */
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$this->oShortcut->RenderContent($oPage, $aExtraParams); $this->oShortcut->RenderContent($oPage, $aExtraParams);
@@ -1661,11 +1597,9 @@ class ShortcutMenuNode extends MenuNode
return true; return true;
} }
public function GetEntriesCount() public function GetEntriesCount()
{ {
return $this->GetEntriesCountFromOQL($this->oShortcut->Get('oql')); return $this->GetEntriesCountFromOQL($this->oShortcut->Get('oql'));
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -34,44 +35,44 @@ interface iNewsroomProvider
* return bool * return bool
*/ */
public function IsApplicable(User $oUser = null); public function IsApplicable(User $oUser = null);
/** /**
* The human readable (localized) label for this provider * The human readable (localized) label for this provider
* @return string * @return string
*/ */
public function GetLabel(); public function GetLabel();
/** /**
* The URL to query (from the browser, using jsonp) to fetch all unread messages * The URL to query (from the browser, using jsonp) to fetch all unread messages
* @return string * @return string
*/ */
public function GetFetchURL(); public function GetFetchURL();
/** /**
* The URL to navigate to in order to display all messages * The URL to navigate to in order to display all messages
* @return string * @return string
*/ */
public function GetViewAllURL(); public function GetViewAllURL();
/** /**
* The URL to query(from the browser, using jsonp) to mark all unread messages as read * The URL to query(from the browser, using jsonp) to mark all unread messages as read
* @return string * @return string
*/ */
public function GetMarkAllAsReadURL(); public function GetMarkAllAsReadURL();
/** /**
* Return the URL to configure the preferences for this provider or null is there is nothing to configure * Return the URL to configure the preferences for this provider or null is there is nothing to configure
* @return string|null * @return string|null
*/ */
public function GetPreferencesUrl(); public function GetPreferencesUrl();
/** /**
* Return an array key => value to be replaced in URL of the messages * Return an array key => value to be replaced in URL of the messages
* Example: '%itop_root%' => utils::GetAbsoluteUrlAppRoot(); * Example: '%itop_root%' => utils::GetAbsoluteUrlAppRoot();
* @return string[] * @return string[]
*/ */
public function GetPlaceholders(); public function GetPlaceholders();
/** /**
* The duration between to refreshes of the cache (in seconds) * The duration between to refreshes of the cache (in seconds)
* @return int * @return int
@@ -90,19 +91,19 @@ abstract class NewsroomProviderBase implements iNewsroomProvider
* @var Config * @var Config
*/ */
protected $oConfig; protected $oConfig;
public function __construct() public function __construct()
{ {
$this->oConfig = null; $this->oConfig = null;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::SetConfig() * @see iNewsroomProvider::SetConfig()
*/ */
public function SetConfig(Config $oConfig) public function SetConfig(Config $oConfig)
{ {
$this->oConfig = $oConfig; $this->oConfig = $oConfig;
} }
/** /**
@@ -118,42 +119,42 @@ abstract class NewsroomProviderBase implements iNewsroomProvider
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::GetLabel() * @see iNewsroomProvider::GetLabel()
*/ */
public abstract function GetLabel(); abstract public function GetLabel();
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::GetFetchURL() * @see iNewsroomProvider::GetFetchURL()
*/ */
public abstract function GetFetchURL(); abstract public function GetFetchURL();
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::GetMarkAllURL() * @see iNewsroomProvider::GetMarkAllURL()
*/ */
public abstract function GetMarkAllAsReadURL(); abstract public function GetMarkAllAsReadURL();
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::GetViewAllURL() * @see iNewsroomProvider::GetViewAllURL()
*/ */
public abstract function GetViewAllURL(); abstract public function GetViewAllURL();
public function IsApplicable(User $oUser = null) public function IsApplicable(User $oUser = null)
{ {
return false; return false;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see iNewsroomProvider::GetPlaceholders() * @see iNewsroomProvider::GetPlaceholders()
*/ */
public function GetPlaceholders() public function GetPlaceholders()
{ {
return array(); // By default, empty set of placeholders return []; // By default, empty set of placeholders
} }
public function GetTTL() public function GetTTL()
{ {
return 10*60; // Refresh every 10 minutes return 10 * 60; // Refresh every 10 minutes
} }
} }

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader');

View File

@@ -1,9 +1,10 @@
<?php <?php
class PortalDispatcher class PortalDispatcher
{ {
protected $sPortalid; protected $sPortalid;
protected $aData; protected $aData;
public function __construct($sPortalId) public function __construct($sPortalId)
{ {
$this->sPortalid = $sPortalId; $this->sPortalid = $sPortalId;
@@ -20,53 +21,45 @@ class PortalDispatcher
{ {
$bRet = true; $bRet = true;
$aProfiles = UserRights::ListProfiles($oUser); $aProfiles = UserRights::ListProfiles($oUser);
foreach($this->aData['deny'] as $sDeniedProfile) foreach ($this->aData['deny'] as $sDeniedProfile) {
{
// If one denied profile is present, it's enough => return false // If one denied profile is present, it's enough => return false
if (in_array($sDeniedProfile, $aProfiles)) if (in_array($sDeniedProfile, $aProfiles)) {
{
return false; return false;
} }
} }
// If there are some "allow" profiles, then by default the result is false // If there are some "allow" profiles, then by default the result is false
// since the user must have at least one of the profiles to be allowed // since the user must have at least one of the profiles to be allowed
if (count($this->aData['allow']) > 0) if (count($this->aData['allow']) > 0) {
{
$bRet = false; $bRet = false;
} }
foreach($this->aData['allow'] as $sAllowProfile) foreach ($this->aData['allow'] as $sAllowProfile) {
{
// If one "allow" profile is present, it's enough => return true // If one "allow" profile is present, it's enough => return true
if (in_array($sAllowProfile, $aProfiles)) if (in_array($sAllowProfile, $aProfiles)) {
{
return true; return true;
} }
} }
return $bRet; return $bRet;
} }
public function GetURL() public function GetURL()
{ {
$aOverloads = MetaModel::GetConfig()->Get('portal_dispatch_urls'); $aOverloads = MetaModel::GetConfig()->Get('portal_dispatch_urls');
if (array_key_exists($this->sPortalid, $aOverloads)) if (array_key_exists($this->sPortalid, $aOverloads)) {
{
$sRet = $aOverloads[$this->sPortalid]; $sRet = $aOverloads[$this->sPortalid];
} } else {
else
{
$sRet = utils::GetAbsoluteUrlAppRoot().$this->aData['url']; $sRet = utils::GetAbsoluteUrlAppRoot().$this->aData['url'];
} }
return $sRet; return $sRet;
} }
public function GetLabel() public function GetLabel()
{ {
return Dict::S('portal:'.$this->sPortalid); return Dict::S('portal:'.$this->sPortalid);
} }
public function GetRank() public function GetRank()
{ {
return $this->aData['rank']; return $this->aData['rank'];
} }
} }

View File

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

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -18,7 +19,6 @@
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings; use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
use Combodo\iTop\Application\WebPage\WebPage; use Combodo\iTop\Application\WebPage\WebPage;
/** /**
* Persistent class Shortcut and derived * Persistent class Shortcut and derived
* Shortcuts of any kind * Shortcuts of any kind
@@ -31,32 +31,32 @@ abstract class Shortcut extends DBObject implements iDisplay
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "gui,view_in_gui", "category" => "gui,view_in_gui",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_shortcut", "db_table" => "priv_shortcut",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "realclass", "db_finalclass_field" => "realclass",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", ["targetclass" => "User", "allowed_values" => null, "sql" => "user_id", "is_null_allowed" => true, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
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("name", ["allowed_values" => null, "sql" => "name", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("context", array("allowed_values"=>null, "sql"=>"context", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("context", ["allowed_values" => null, "sql" => "context", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('name', 'context')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['name', 'context']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['name']); // Attributes to be displayed for a list
// Search criteria // Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std 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 // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
} }
abstract public function RenderContent(WebPage $oPage, $aExtraParams = array()); abstract public function RenderContent(WebPage $oPage, $aExtraParams = []);
protected function OnInsert() protected function OnInsert()
{ {
@@ -74,14 +74,14 @@ abstract class Shortcut extends DBObject implements iDisplay
$oForm->AddField($oField); $oForm->AddField($oField);
$oForm->Render($oPage); $oForm->Render($oPage);
$oPage->add('</div>'); $oPage->add('</div>');
$sDialogTitle = Dict::S('UI:ShortcutRenameDlg:Title'); $sDialogTitle = Dict::S('UI:ShortcutRenameDlg:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok'); $sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$iShortcut = $this->GetKey(); $iShortcut = $this->GetKey();
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
function ShortcutRenameOK() function ShortcutRenameOK()
{ {
var oForm = $(this).find('form'); var oForm = $(this).find('form');
@@ -137,13 +137,13 @@ EOF
return ''; return '';
} }
function DisplayDetails(WebPage $oPage, $bEditMode = false) public function DisplayDetails(WebPage $oPage, $bEditMode = false)
{ {
} }
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array()) public function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = [])
{ {
return array(); return [];
} }
// End of the minimal implementation of iDisplay // End of the minimal implementation of iDisplay
} }
@@ -152,61 +152,56 @@ class ShortcutOQL extends Shortcut
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "gui,view_in_gui", "category" => "gui,view_in_gui",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_shortcut_oql", "db_table" => "priv_shortcut_oql",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes(); MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeOQL("oql", ["allowed_values" => null, "sql" => "oql", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("auto_reload", array("allowed_values"=>new ValueSetEnum('none,custom'), "sql"=>"auto_reload", "default_value"=>"none", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("auto_reload", ["allowed_values" => new ValueSetEnum('none,custom'), "sql" => "auto_reload", "default_value" => "none", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("auto_reload_sec", array("allowed_values"=>null, "sql"=>"auto_reload_sec", "default_value"=>60, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("auto_reload_sec", ["allowed_values" => null, "sql" => "auto_reload_sec", "default_value" => 60, "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('name', 'context', 'oql')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['name', 'context', 'oql']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['name']); // Attributes to be displayed for a list
// Search criteria // Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std 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 // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
} }
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = [])
{ {
$oPage->set_title($this->Get('name')); $oPage->set_title($this->Get('name'));
switch($this->Get('auto_reload')) switch ($this->Get('auto_reload')) {
{ case 'custom':
case 'custom': $iRate = (int)$this->Get('auto_reload_sec');
$iRate = (int)$this->Get('auto_reload_sec'); if ($iRate > 0) {
if ($iRate > 0) // Must a string otherwise it can be evaluated to 'true' and defaults to "standard" refresh rate!
{ $aExtraParams['auto_reload'] = (string)$iRate;
// Must a string otherwise it can be evaluated to 'true' and defaults to "standard" refresh rate! }
$aExtraParams['auto_reload'] = (string)$iRate; break;
}
break;
default: default:
case 'none': case 'none':
} }
$bSearchPane = true; $bSearchPane = true;
$bSearchOpen = true; $bSearchOpen = true;
try try {
{
OQLMenuNode::RenderOQLSearch($this->Get('oql'), $this->Get('name'), 'shortcut_'.$this->GetKey(), $bSearchPane, $bSearchOpen, $oPage, $aExtraParams, true); OQLMenuNode::RenderOQLSearch($this->Get('oql'), $this->Get('name'), 'shortcut_'.$this->GetKey(), $bSearchPane, $bSearchOpen, $oPage, $aExtraParams, true);
} } catch (Exception $e) {
catch (Exception $e)
{
throw new Exception("The OQL shortcut '".$this->Get('name')."' (id: ".$this->GetKey().") could not be displayed: ".$e->getMessage()); throw new Exception("The OQL shortcut '".$this->Get('name')."' (id: ".$this->GetKey().") could not be displayed: ".$e->getMessage());
} }
} }
public function CloneTableSettings($sTableSettings) public function CloneTableSettings($sTableSettings)
@@ -226,17 +221,14 @@ class ShortcutOQL extends Shortcut
// Find a unique default name // Find a unique default name
// -> The class of the query + an index if necessary // -> The class of the query + an index if necessary
if ($sOQL == null) if ($sOQL == null) {
{
$sDefault = ''; $sDefault = '';
} } else {
else
{
$oBMSearch = new DBObjectSearch('Shortcut'); $oBMSearch = new DBObjectSearch('Shortcut');
$oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oBMSet = new DBObjectSet($oBMSearch); $oBMSet = new DBObjectSet($oBMSearch);
$aNames = $oBMSet->GetColumnAsArray('name'); $aNames = $oBMSet->GetColumnAsArray('name');
$oSearch = DBObjectSearch::FromOQL($sOQL); $oSearch = DBObjectSearch::FromOQL($sOQL);
$sDefault = utils::MakeUniqueName($oSearch->GetClass(), $aNames); $sDefault = utils::MakeUniqueName($oSearch->GetClass(), $aNames);
} }
@@ -276,18 +268,18 @@ class ShortcutOQL extends Shortcut
$oForm->Render($oPage); $oForm->Render($oPage);
$oPage->add('</div>'); $oPage->add('</div>');
$sDialogTitle = Dict::S('UI:ShortcutListDlg:Title'); $sDialogTitle = Dict::S('UI:ShortcutListDlg:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok'); $sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(); $sContext = $oAppContext->GetForLink();
$sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval'))); $sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval')));
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
// Note: the title gets deleted by the validation mechanism // Note: the title gets deleted by the validation mechanism
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle'); $("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec")); CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -23,7 +24,6 @@ require_once(APPROOT.'core/contexttag.class.inc.php');
require_once(APPROOT.'core/kpi.class.inc.php'); require_once(APPROOT.'core/kpi.class.inc.php');
require_once(APPROOT.'setup/setuputils.class.inc.php'); require_once(APPROOT.'setup/setuputils.class.inc.php');
/** /**
* File to include to initialize the datamodel in memory * File to include to initialize the datamodel in memory
* *
@@ -36,12 +36,10 @@ ExecutionKPI::EnableMemory(1);
// This storage is freed on error (case of allowed memory exhausted) // This storage is freed on error (case of allowed memory exhausted)
$sReservedMemory = str_repeat('*', 1024 * 1024); $sReservedMemory = str_repeat('*', 1024 * 1024);
register_shutdown_function(function() register_shutdown_function(function () {
{
global $sReservedMemory; global $sReservedMemory;
$sReservedMemory = null; $sReservedMemory = null;
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR)) if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR)) {
{
// Remove stack trace from MySQLException (since 2.7.2 see N°3174) // Remove stack trace from MySQLException (since 2.7.2 see N°3174)
$sMessage = $err['message']; $sMessage = $err['message'];
if (strpos($sMessage, 'MySQLException') !== false) { if (strpos($sMessage, 'MySQLException') !== false) {
@@ -71,38 +69,30 @@ $oKPI->ComputeAndReport("Session Start");
$sSwitchEnv = utils::ReadParam('switch_env', null); $sSwitchEnv = utils::ReadParam('switch_env', null);
$bAllowCache = true; $bAllowCache = true;
if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE) &&( Session::Get('itop_env') !== $sSwitchEnv)) if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE) && (Session::Get('itop_env') !== $sSwitchEnv)) {
{
Session::Set('itop_env', $sSwitchEnv); Session::Set('itop_env', $sSwitchEnv);
$sEnv = $sSwitchEnv; $sEnv = $sSwitchEnv;
$bAllowCache = false; $bAllowCache = false;
// Reset the opcache since otherwise the PHP "model" files may still be cached !! // Reset the opcache since otherwise the PHP "model" files may still be cached !!
if (function_exists('opcache_reset')) if (function_exists('opcache_reset')) {
{ // Zend opcode cache
// Zend opcode cache opcache_reset();
opcache_reset(); }
} if (function_exists('apc_clear_cache')) {
if (function_exists('apc_clear_cache')) // APC(u) cache
{ apc_clear_cache();
// APC(u) cache }
apc_clear_cache();
}
// TODO: reset the credentials as well ?? // TODO: reset the credentials as well ??
} } elseif (Session::IsSet('itop_env')) {
else if (Session::IsSet('itop_env'))
{
$sEnv = Session::Get('itop_env'); $sEnv = Session::Get('itop_env');
} } else {
else
{
$sEnv = ITOP_DEFAULT_ENV; $sEnv = ITOP_DEFAULT_ENV;
Session::Set('itop_env', ITOP_DEFAULT_ENV); Session::Set('itop_env', ITOP_DEFAULT_ENV);
} }
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE; $sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
try { try {
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv); MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
} catch (MySQLException $e) {
IssueLog::Debug($e->getMessage());
throw new MySQLException('Could not connect to the DB server', []);
} }
catch (MySQLException $e) {
IssueLog::Debug($e->getMessage());
throw new MySQLException('Could not connect to the DB server', []);
}

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -30,12 +31,12 @@ class DisplayTemplate
{ {
protected $m_sTemplate; protected $m_sTemplate;
protected $m_aTags; protected $m_aTags;
static protected $iBlockCount = 0; protected static $iBlockCount = 0;
public function __construct($sTemplate) public function __construct($sTemplate)
{ {
DeprecatedCallsLog::NotifyDeprecatedPhpMethod(); DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
$this->m_aTags = array( $this->m_aTags = [
'itopblock', 'itopblock',
'itopcheck', 'itopcheck',
'itoptabs', 'itoptabs',
@@ -43,11 +44,11 @@ class DisplayTemplate
'itoptoggle', 'itoptoggle',
'itopstring', 'itopstring',
'sqlblock', 'sqlblock',
); ];
$this->m_sTemplate = $sTemplate; $this->m_sTemplate = $sTemplate;
} }
public function Render(WebPage $oPage, $aParams = array()) public function Render(WebPage $oPage, $aParams = [])
{ {
$this->m_sTemplate = MetaModel::ApplyParams($this->m_sTemplate, $aParams); $this->m_sTemplate = MetaModel::ApplyParams($this->m_sTemplate, $aParams);
$iStart = 0; $iStart = 0;
@@ -55,70 +56,55 @@ class DisplayTemplate
$iCount = 0; $iCount = 0;
$iBeforeTagPos = $iStart; $iBeforeTagPos = $iStart;
$iAfterTagPos = $iStart; $iAfterTagPos = $iStart;
while($sTag = $this->GetNextTag($iStart, $iEnd)) while ($sTag = $this->GetNextTag($iStart, $iEnd)) {
{
$sContent = $this->GetTagContent($sTag, $iStart, $iEnd); $sContent = $this->GetTagContent($sTag, $iStart, $iEnd);
$iAfterTagPos = $iEnd + strlen('</'.$sTag.'>'); $iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
$sOuterTag = substr($this->m_sTemplate, $iStart, $iAfterTagPos - $iStart); $sOuterTag = substr($this->m_sTemplate, $iStart, $iAfterTagPos - $iStart);
$oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos)); $oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos));
if ($sTag == DisplayBlock::TAG_BLOCK) if ($sTag == DisplayBlock::TAG_BLOCK) {
{ try {
try
{
$oBlock = DisplayBlock::FromTemplate($sOuterTag); $oBlock = DisplayBlock::FromTemplate($sOuterTag);
if (is_object($oBlock)) if (is_object($oBlock)) {
{
$oBlock->Display($oPage, 'block_'.self::$iBlockCount, $aParams); $oBlock->Display($oPage, 'block_'.self::$iBlockCount, $aParams);
} }
} } catch (OQLException $e) {
catch(OQLException $e)
{
$oPage->p('Error in template (please contact your administrator) - Invalid query<!--'.$sOuterTag.'-->'); $oPage->p('Error in template (please contact your administrator) - Invalid query<!--'.$sOuterTag.'-->');
} } catch (Exception $e) {
catch(Exception $e)
{
$oPage->p('Error in template (please contact your administrator)<!--'.$e->getMessage().'--><!--'.$sOuterTag.'-->'); $oPage->p('Error in template (please contact your administrator)<!--'.$e->getMessage().'--><!--'.$sOuterTag.'-->');
} }
self::$iBlockCount++; self::$iBlockCount++;
} } else {
else
{
$aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd); $aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd);
//$oPage->p("Tag: $sTag - ($iStart, $iEnd)"); //$oPage->p("Tag: $sTag - ($iStart, $iEnd)");
$this->RenderTag($oPage, $sTag, $aAttributes, $sContent); $this->RenderTag($oPage, $sTag, $aAttributes, $sContent);
} }
$iAfterTagPos = $iEnd + strlen('</'.$sTag.'>'); $iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
$iBeforeTagPos = $iAfterTagPos; $iBeforeTagPos = $iAfterTagPos;
$iStart = $iEnd; $iStart = $iEnd;
$iEnd = strlen($this->m_sTemplate); $iEnd = strlen($this->m_sTemplate);
$iCount++; $iCount++;
} }
$oPage->add(substr($this->m_sTemplate, $iAfterTagPos)); $oPage->add(substr($this->m_sTemplate, $iAfterTagPos));
} }
public function GetNextTag(&$iStartPos, &$iEndPos) public function GetNextTag(&$iStartPos, &$iEndPos)
{ {
$iChunkStartPos = $iStartPos; $iChunkStartPos = $iStartPos;
$sNextTag = null; $sNextTag = null;
$iStartPos = $iEndPos; $iStartPos = $iEndPos;
foreach($this->m_aTags as $sTag) foreach ($this->m_aTags as $sTag) {
{
// Search for the opening tag // Search for the opening tag
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos); $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos);
if ($iOpeningPos === false) if ($iOpeningPos === false) {
{
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos); $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos);
} }
if ($iOpeningPos !== false) if ($iOpeningPos !== false) {
{
$iClosingPos = stripos($this->m_sTemplate, '</'.$sTag.'>', $iOpeningPos); $iClosingPos = stripos($this->m_sTemplate, '</'.$sTag.'>', $iOpeningPos);
} }
if ( ($iOpeningPos !== false) && ($iClosingPos !== false)) if (($iOpeningPos !== false) && ($iClosingPos !== false)) {
{ if ($iOpeningPos < $iStartPos) {
if ($iOpeningPos < $iStartPos)
{
// This is the next tag // This is the next tag
$iStartPos = $iOpeningPos; $iStartPos = $iOpeningPos;
$iEndPos = $iClosingPos; $iEndPos = $iClosingPos;
@@ -128,108 +114,100 @@ class DisplayTemplate
} }
return $sNextTag; return $sNextTag;
} }
public function GetTagContent($sTag, $iStartPos, $iEndPos) public function GetTagContent($sTag, $iStartPos, $iEndPos)
{ {
$sContent = ""; $sContent = "";
$iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket $iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket
if ($iContentStart !== false) if ($iContentStart !== false) {
{ $sContent = substr($this->m_sTemplate, 1 + $iContentStart, $iEndPos - $iContentStart - 1);
$sContent = substr($this->m_sTemplate, 1+$iContentStart, $iEndPos - $iContentStart - 1);
} }
return $sContent; return $sContent;
} }
public function GetTagAttributes($sTag, $iStartPos, $iEndPos) public function GetTagAttributes($sTag, $iStartPos, $iEndPos)
{ {
$aAttr = array(); $aAttr = [];
$iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space $iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space
$iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket $iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket
if ( ($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart)) if (($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart)) {
{ $sAttributes = substr($this->m_sTemplate, 1 + $iAttrStart, $iAttrEnd - $iAttrStart - 1);
$sAttributes = substr($this->m_sTemplate, 1+$iAttrStart, $iAttrEnd - $iAttrStart - 1);
$aAttributes = explode(' ', $sAttributes); $aAttributes = explode(' ', $sAttributes);
foreach($aAttributes as $sAttr) foreach ($aAttributes as $sAttr) {
{ if (preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches)) {
if ( preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches) )
{
$aAttr[strtolower($aMatches[1])] = $aMatches[2]; $aAttr[strtolower($aMatches[1])] = $aMatches[2];
} }
} }
} }
return $aAttr; return $aAttr;
} }
protected function RenderTag($oPage, $sTag, $aAttributes, $sContent) protected function RenderTag($oPage, $sTag, $aAttributes, $sContent)
{ {
static $iTabContainerCount = 0; static $iTabContainerCount = 0;
switch($sTag) switch ($sTag) {
{
case 'itoptabs': case 'itoptabs':
$oPage->AddTabContainer('Tabs_'.$iTabContainerCount); $oPage->AddTabContainer('Tabs_'.$iTabContainerCount);
$oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount); $oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount);
$iTabContainerCount++; $iTabContainerCount++;
//$oPage->p('Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>'); //$oPage->p('Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oTemplate = new DisplayTemplate($sContent); $oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied $oTemplate->Render($oPage, []); // no params to apply, they have already been applied
$oPage->SetCurrentTabContainer(''); $oPage->SetCurrentTabContainer('');
break; break;
case 'itopcheck': case 'itopcheck':
$sClassName = $aAttributes['class']; $sClassName = $aAttributes['class'];
if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ)) if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ)) {
{
$oTemplate = new DisplayTemplate($sContent); $oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied $oTemplate->Render($oPage, []); // no params to apply, they have already been applied
} } else {
else
{
// Leave a trace for those who'd like to understand why nothing is displayed // Leave a trace for those who'd like to understand why nothing is displayed
$oPage->add("<!-- class $sClassName does not exist, skipping some part of the template -->\n"); $oPage->add("<!-- class $sClassName does not exist, skipping some part of the template -->\n");
} }
break; break;
case 'itoptab': case 'itoptab':
$oPage->SetCurrentTab($aAttributes['name'], str_replace('_', ' ', $aAttributes['name'])); $oPage->SetCurrentTab($aAttributes['name'], str_replace('_', ' ', $aAttributes['name']));
$oTemplate = new DisplayTemplate($sContent); $oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied $oTemplate->Render($oPage, []); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>'); //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oPage->SetCurrentTab(''); $oPage->SetCurrentTab('');
break; break;
case 'itoptoggle': case 'itoptoggle':
$sName = isset($aAttributes['name']) ? $aAttributes['name'] : 'Tagada'; $sName = isset($aAttributes['name']) ? $aAttributes['name'] : 'Tagada';
$bOpen = isset($aAttributes['open']) ? $aAttributes['open'] : true; $bOpen = isset($aAttributes['open']) ? $aAttributes['open'] : true;
$oPage->StartCollapsibleSection(Dict::S($sName), $bOpen); $oPage->StartCollapsibleSection(Dict::S($sName), $bOpen);
$oTemplate = new DisplayTemplate($sContent); $oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied $oTemplate->Render($oPage, []); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>'); //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oPage->EndCollapsibleSection(); $oPage->EndCollapsibleSection();
break; break;
case 'itopstring': case 'itopstring':
$oPage->add(Dict::S($sContent)); $oPage->add(Dict::S($sContent));
break; break;
case 'sqlblock': case 'sqlblock':
$oBlock = SqlBlock::FromTemplate($sContent); $oBlock = SqlBlock::FromTemplate($sContent);
$oBlock->RenderContent($oPage); $oBlock->RenderContent($oPage);
break; break;
case 'itopblock': // No longer used, handled by DisplayBlock::FromTemplate see above case 'itopblock': // No longer used, handled by DisplayBlock::FromTemplate see above
$oPage->add("<!-- Application Error: should be handled by DisplayBlock::FromTemplate -->"); $oPage->add("<!-- Application Error: should be handled by DisplayBlock::FromTemplate -->");
break; break;
default: default:
// Unknown tag, just ignore it or now -- output an HTML comment // Unknown tag, just ignore it or now -- output an HTML comment
$oPage->add("<!-- unsupported tag: $sTag -->"); $oPage->add("<!-- unsupported tag: $sTag -->");
} }
} }
/** /**
* Unit test * Unit test
*/ */
static public function UnitTest() public static function UnitTest()
{ {
require_once(APPROOT.'/application/startup.inc.php'); require_once(APPROOT.'/application/startup.inc.php');
@@ -250,11 +228,11 @@ class DisplayTemplate
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Document AS d JOIN lnkDocumentToCI as l ON l.document_id = d.id WHERE l.ci_id = $id$)</itopblock> <itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Document AS d JOIN lnkDocumentToCI as l ON l.document_id = d.id WHERE l.ci_id = $id$)</itopblock>
</itoptab> </itoptab>
</itoptabs>'; </itoptabs>';
$oPage = new iTopWebPage('Unit Test'); $oPage = new iTopWebPage('Unit Test');
//$oPage->add("Template content: <pre>".htmlentities($sTemplate, ENT_QUOTES, 'UTF-8')."</pre>\n"); //$oPage->add("Template content: <pre>".htmlentities($sTemplate, ENT_QUOTES, 'UTF-8')."</pre>\n");
$oTemplate = new DisplayTemplate($sTemplate); $oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, array('class'=>'Network device','pkey'=> 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3)); $oTemplate->Render($oPage, ['class' => 'Network device','pkey' => 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3]);
$oPage->output(); $oPage->output();
} }
} }
@@ -275,89 +253,68 @@ class ObjectDetailsTemplate extends DisplayTemplate
$this->m_oObj = $oObj; $this->m_oObj = $oObj;
$this->m_sPrefix = $sFormPrefix; $this->m_sPrefix = $sFormPrefix;
} }
public function Render(WebPage $oPage, $aParams = array(), $bEditMode = false) public function Render(WebPage $oPage, $aParams = [], $bEditMode = false)
{ {
$sStateAttCode = MetaModel :: GetStateAttributeCode(get_class($this->m_oObj)); $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this->m_oObj));
$aTemplateFields = array(); $aTemplateFields = [];
preg_match_all('/\\$this->([a-z0-9_]+)\\$/', $this->m_sTemplate, $aMatches); preg_match_all('/\\$this->([a-z0-9_]+)\\$/', $this->m_sTemplate, $aMatches);
foreach ($aMatches[1] as $sAttCode) foreach ($aMatches[1] as $sAttCode) {
{ if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode)) {
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode; $aTemplateFields[] = $sAttCode;
} } else {
else $aParams['this->'.$sAttCode] = "<!--Unknown attribute: $sAttCode-->";
{
$aParams['this->'.$sAttCode] = "<!--Unknown attribute: $sAttCode-->";
} }
} }
preg_match_all('/\\$this->field\\(([a-z0-9_]+)\\)\\$/', $this->m_sTemplate, $aMatches); preg_match_all('/\\$this->field\\(([a-z0-9_]+)\\)\\$/', $this->m_sTemplate, $aMatches);
foreach ($aMatches[1] as $sAttCode) foreach ($aMatches[1] as $sAttCode) {
{ if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode)) {
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode; $aTemplateFields[] = $sAttCode;
} } else {
else
{
$aParams['this->field('.$sAttCode.')'] = "<!--Unknown attribute: $sAttCode-->"; $aParams['this->field('.$sAttCode.')'] = "<!--Unknown attribute: $sAttCode-->";
} }
} }
$aFieldsComments = (isset($aParams['fieldsComments'])) ? $aParams['fieldsComments'] : array(); $aFieldsComments = (isset($aParams['fieldsComments'])) ? $aParams['fieldsComments'] : [];
$aFieldsMap = array(); $aFieldsMap = [];
$sClass = get_class($this->m_oObj); $sClass = get_class($this->m_oObj);
// Renders the fields used in the template // Renders the fields used in the template
foreach(MetaModel::ListAttributeDefs(get_class($this->m_oObj)) as $sAttCode => $oAttDef) foreach (MetaModel::ListAttributeDefs(get_class($this->m_oObj)) as $sAttCode => $oAttDef) {
{
$aParams['this->label('.$sAttCode.')'] = $oAttDef->GetLabel(); $aParams['this->label('.$sAttCode.')'] = $oAttDef->GetLabel();
$aParams['this->comments('.$sAttCode.')'] = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : ''; $aParams['this->comments('.$sAttCode.')'] = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '';
$iInputId = '2_'.$sAttCode; // TODO: generate a real/unique prefix... $iInputId = '2_'.$sAttCode; // TODO: generate a real/unique prefix...
if (in_array($sAttCode, $aTemplateFields)) if (in_array($sAttCode, $aTemplateFields)) {
{ if ($this->m_oObj->IsNew()) {
if ($this->m_oObj->IsNew())
{
$iFlags = $this->m_oObj->GetInitialStateAttributeFlags($sAttCode); $iFlags = $this->m_oObj->GetInitialStateAttributeFlags($sAttCode);
} else {
$iFlags = $this->m_oObj->GetAttributeFlags($sAttCode);
} }
else if (($iFlags & OPT_ATT_MANDATORY) && $this->m_oObj->IsNew()) {
{
$iFlags = $this->m_oObj->GetAttributeFlags($sAttCode);
}
if (($iFlags & OPT_ATT_MANDATORY) && $this->m_oObj->IsNew())
{
$iFlags = $iFlags & ~OPT_ATT_READONLY; // Mandatory fields cannot be read-only when creating an object $iFlags = $iFlags & ~OPT_ATT_READONLY; // Mandatory fields cannot be read-only when creating an object
} }
if ((!$oAttDef->IsWritable()) || ($sStateAttCode == $sAttCode)) if ((!$oAttDef->IsWritable()) || ($sStateAttCode == $sAttCode)) {
{
$iFlags = $iFlags | OPT_ATT_READONLY; $iFlags = $iFlags | OPT_ATT_READONLY;
} }
if ($iFlags & OPT_ATT_HIDDEN) if ($iFlags & OPT_ATT_HIDDEN) {
{
$aParams['this->label('.$sAttCode.')'] = ''; $aParams['this->label('.$sAttCode.')'] = '';
$aParams['this->field('.$sAttCode.')'] = ''; $aParams['this->field('.$sAttCode.')'] = '';
$aParams['this->comments('.$sAttCode.')'] = ''; $aParams['this->comments('.$sAttCode.')'] = '';
$aParams['this->'.$sAttCode] = ''; $aParams['this->'.$sAttCode] = '';
} } else {
else if ($bEditMode && ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE))) {
{
if ($bEditMode && ($iFlags & (OPT_ATT_READONLY|OPT_ATT_SLAVE)))
{
// Check if the attribute is not read-only because of a synchro... // Check if the attribute is not read-only because of a synchro...
$aReasons = array(); $aReasons = [];
$sSynchroIcon = ''; $sSynchroIcon = '';
if ($iFlags & OPT_ATT_SLAVE) if ($iFlags & OPT_ATT_SLAVE) {
{
$iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons); $iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sAppRooturl = utils::GetAbsoluteUrlAppRoot(); $sAppRooturl = utils::GetAbsoluteUrlAppRoot();
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>"; $sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = ''; $sTip = '';
foreach($aReasons as $aRow) foreach ($aReasons as $aRow) {
{
$sDescription = utils::EscapeHtml($aRow['description']); $sDescription = utils::EscapeHtml($aRow['description']);
$sDescription = str_replace(array("\r\n", "\n"), "<br/>", $sDescription); $sDescription = str_replace(["\r\n", "\n"], "<br/>", $sDescription);
$sTip .= "<div class='synchro-source'>"; $sTip .= "<div class='synchro-source'>";
$sTip .= "<div class='synchro-source-title'>Synchronized with {$aRow['name']}</div>"; $sTip .= "<div class='synchro-source-title'>Synchronized with {$aRow['name']}</div>";
$sTip .= "<div class='synchro-source-description'>$sDescription</div>"; $sTip .= "<div class='synchro-source-description'>$sDescription</div>";
@@ -371,46 +328,43 @@ class ObjectDetailsTemplate extends DisplayTemplate
$aFieldsMap[$sAttCode] = $iInputId; $aFieldsMap[$sAttCode] = $iInputId;
$aParams['this->comments('.$sAttCode.')'] = $sSynchroIcon; $aParams['this->comments('.$sAttCode.')'] = $sSynchroIcon;
} }
if ($bEditMode && !($iFlags & OPT_ATT_READONLY)) //TODO: check the data synchro status... if ($bEditMode && !($iFlags & OPT_ATT_READONLY)) { //TODO: check the data synchro status...
{ $aParams['this->field('.$sAttCode.')'] = "<span id=\"field_{$iInputId}\">".$this->m_oObj->GetFormElementForField(
$aParams['this->field('.$sAttCode.')'] = "<span id=\"field_{$iInputId}\">".$this->m_oObj->GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $oPage,
$this->m_oObj->Get($sAttCode), $sClass,
$this->m_oObj->GetEditValue($sAttCode), $sAttCode,
$iInputId, // InputID $oAttDef,
'', $this->m_oObj->Get($sAttCode),
$iFlags, $this->m_oObj->GetEditValue($sAttCode),
array('this' => $this->m_oObj) // aArgs $iInputId, // InputID
).'</span>'; '',
$aFieldsMap[$sAttCode] = $iInputId; $iFlags,
} ['this' => $this->m_oObj] // aArgs
else ).'</span>';
{ $aFieldsMap[$sAttCode] = $iInputId;
} else {
$aParams['this->field('.$sAttCode.')'] = $this->m_oObj->GetAsHTML($sAttCode); $aParams['this->field('.$sAttCode.')'] = $this->m_oObj->GetAsHTML($sAttCode);
} }
$aParams['this->'.$sAttCode] = "<table class=\"field\"><tr><td class=\"label\">".$aParams['this->label('.$sAttCode.')'].":</td><td>".$aParams['this->field('.$sAttCode.')']."</td><td>".$aParams['this->comments('.$sAttCode.')']."</td></tr></table>"; $aParams['this->'.$sAttCode] = "<table class=\"field\"><tr><td class=\"label\">".$aParams['this->label('.$sAttCode.')'].":</td><td>".$aParams['this->field('.$sAttCode.')']."</td><td>".$aParams['this->comments('.$sAttCode.')']."</td></tr></table>";
} }
} }
} }
// Renders the PlugIns used in the template // Renders the PlugIns used in the template
preg_match_all('/\\$PlugIn:([A-Za-z0-9_]+)->properties\\(\\)\\$/', $this->m_sTemplate, $aMatches); preg_match_all('/\\$PlugIn:([A-Za-z0-9_]+)->properties\\(\\)\\$/', $this->m_sTemplate, $aMatches);
$aPlugInProperties = $aMatches[1]; $aPlugInProperties = $aMatches[1];
foreach($aPlugInProperties as $sPlugInClass) foreach ($aPlugInProperties as $sPlugInClass) {
{
/** @var \iApplicationUIExtension $oInstance */ /** @var \iApplicationUIExtension $oInstance */
$oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass); $oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass);
if ($oInstance != null) // Safety check... if ($oInstance != null) { // Safety check...
{
$offset = $oPage->start_capture(); $offset = $oPage->start_capture();
$oInstance->OnDisplayProperties($this->m_oObj, $oPage, $bEditMode); $oInstance->OnDisplayProperties($this->m_oObj, $oPage, $bEditMode);
$sContent = $oPage->end_capture($offset); $sContent = $oPage->end_capture($offset);
$aParams["PlugIn:{$sPlugInClass}->properties()"]= $sContent; $aParams["PlugIn:{$sPlugInClass}->properties()"] = $sContent;
} else {
$aParams["PlugIn:{$sPlugInClass}->properties()"] = "Missing PlugIn: $sPlugInClass";
} }
else
{
$aParams["PlugIn:{$sPlugInClass}->properties()"]= "Missing PlugIn: $sPlugInClass";
}
} }
$offset = $oPage->start_capture(); $offset = $oPage->start_capture();
@@ -424,4 +378,3 @@ class ObjectDetailsTemplate extends DisplayTemplate
} }
//DisplayTemplate::UnitTest(); //DisplayTemplate::UnitTest();
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -25,7 +26,7 @@
*/ */
class ThemeHandler class ThemeHandler
{ {
const IMAGE_EXTENSIONS = ['png', 'gif', 'jpg', 'jpeg']; public const IMAGE_EXTENSIONS = ['png', 'gif', 'jpg', 'jpeg'];
/** @var \CompileCSSService */ /** @var \CompileCSSService */
private static $oCompileCSSService; private static $oCompileCSSService;
@@ -50,7 +51,7 @@ class ThemeHandler
'imports' => [], 'imports' => [],
'stylesheets' => [ 'stylesheets' => [
'main' => '../css/backoffice/main.scss', 'main' => '../css/backoffice/main.scss',
] ],
], ],
]; ];
} }
@@ -75,8 +76,7 @@ class ThemeHandler
{ {
try { try {
$sThemeId = utils::GetConfig()->Get('backoffice_default_theme'); $sThemeId = utils::GetConfig()->Get('backoffice_default_theme');
} } catch (CoreException $oCompileException) {
catch (CoreException $oCompileException) {
// Fallback on our default theme in case the config. is not available yet // Fallback on our default theme in case the config. is not available yet
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation(); $aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
$sThemeId = $aDefaultTheme['name']; $sThemeId = $aDefaultTheme['name'];
@@ -97,8 +97,7 @@ class ThemeHandler
if (true === utils::GetConfig()->Get('user_preferences.allow_backoffice_theme_override')) { if (true === utils::GetConfig()->Get('user_preferences.allow_backoffice_theme_override')) {
$sThemeId = appUserPreferences::GetPref('backoffice_theme', null); $sThemeId = appUserPreferences::GetPref('backoffice_theme', null);
} }
} } catch (Exception $oException) {
catch (Exception $oException) {
// Do nothing, already handled by $sThemeId null by default // Do nothing, already handled by $sThemeId null by default
} }
@@ -213,8 +212,7 @@ class ThemeHandler
if (static::ShouldThemeSignatureCheckBeForced($sThemeId)) { if (static::ShouldThemeSignatureCheckBeForced($sThemeId)) {
static::CompileTheme($sThemeId); static::CompileTheme($sThemeId);
} }
} } catch (CoreException $oCompileException) {
catch (CoreException $oCompileException) {
// Fallback on our default theme (should always be compilable) in case the previous theme doesn't exists // Fallback on our default theme (should always be compilable) in case the previous theme doesn't exists
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation(); $aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
$sThemeId = $aDefaultTheme['name']; $sThemeId = $aDefaultTheme['name'];
@@ -270,13 +268,16 @@ class ThemeHandler
* @throws \CoreException * @throws \CoreException
* @return boolean: indicate whether theme compilation occured * @return boolean: indicate whether theme compilation occured
*/ */
public static function CompileTheme($sThemeId, $bSetup=false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null) { public static function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp = "", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
{
if ($sSetupCompilationTimestamp === "") { if ($sSetupCompilationTimestamp === "") {
$sSetupCompilationTimestamp = microtime(true); $sSetupCompilationTimestamp = microtime(true);
} }
$sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !== false) ? explode('.', $sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !== false) ? explode(
$sSetupCompilationTimestamp)[0] : $sSetupCompilationTimestamp; '.',
$sSetupCompilationTimestamp
)[0] : $sSetupCompilationTimestamp;
$sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/'; $sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
@@ -329,7 +330,7 @@ class ThemeHandler
} }
} }
foreach ($oFindStylesheetObject->GetStylesheetFileURIs() as $sStylesheet){ foreach ($oFindStylesheetObject->GetStylesheetFileURIs() as $sStylesheet) {
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n"; $sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
} }
@@ -341,11 +342,9 @@ class ThemeHandler
$iStyleLastModified = $oFindStylesheetObject->GetLastModified(); $iStyleLastModified = $oFindStylesheetObject->GetLastModified();
$aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $oFindStylesheetObject->GetAllStylesheetPaths(), $sThemeId); $aIncludedImages = static::GetIncludedImages($aThemeParametersWithVersion, $oFindStylesheetObject->GetAllStylesheetPaths(), $sThemeId);
foreach ($aIncludedImages as $sImage) foreach ($aIncludedImages as $sImage) {
{ if (is_file($sImage)) {
if (is_file($sImage))
{
$iStylesheetLastModified = @filemtime($sImage); $iStylesheetLastModified = @filemtime($sImage);
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified; $iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
} }
@@ -354,34 +353,28 @@ class ThemeHandler
// Checking if our compiled css is outdated // Checking if our compiled css is outdated
$iFilemetime = @filemtime($sThemeCssPath); $iFilemetime = @filemtime($sThemeCssPath);
$bFileExists = file_exists($sThemeCssPath); $bFileExists = file_exists($sThemeCssPath);
$bVarSignatureChanged=false; $bVarSignatureChanged = false;
if ($bFileExists && $bSetup) if ($bFileExists && $bSetup) {
{
$sPrecompiledSignature = static::GetSignature($sThemeCssPath); $sPrecompiledSignature = static::GetSignature($sThemeCssPath);
//check variable signature has changed which is independant from any file modification //check variable signature has changed which is independant from any file modification
if (!empty($sPrecompiledSignature)){ if (!empty($sPrecompiledSignature)) {
$sPreviousVariableSignature = static::GetVarSignature($sPrecompiledSignature); $sPreviousVariableSignature = static::GetVarSignature($sPrecompiledSignature);
$sCurrentVariableSignature = md5(json_encode($aThemeParameters['variables'])); $sCurrentVariableSignature = md5(json_encode($aThemeParameters['variables']));
$bVarSignatureChanged= ($sPreviousVariableSignature!==$sCurrentVariableSignature); $bVarSignatureChanged = ($sPreviousVariableSignature !== $sCurrentVariableSignature);
} }
} }
if (!$bFileExists || $bVarSignatureChanged || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified))) if (!$bFileExists || $bVarSignatureChanged || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified))) {
{
// Dates don't match. Second chance: check if the already compiled stylesheet exists and is consistent based on its signature // Dates don't match. Second chance: check if the already compiled stylesheet exists and is consistent based on its signature
$sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages); $sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages);
if ($bFileExists && !$bSetup) if ($bFileExists && !$bSetup) {
{
$sPrecompiledSignature = static::GetSignature($sThemeCssPath); $sPrecompiledSignature = static::GetSignature($sThemeCssPath);
} }
if (!empty($sPrecompiledSignature) && $sActualSignature == $sPrecompiledSignature) if (!empty($sPrecompiledSignature) && $sActualSignature == $sPrecompiledSignature) {
{
touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time
} } else {
else
{
// Alas, we really need to recompile // Alas, we really need to recompile
// Add the signature to the generated CSS file so that the file can be used as a precompiled stylesheet if needed // Add the signature to the generated CSS file so that the file can be used as a precompiled stylesheet if needed
$sSignatureComment = $sSignatureComment =
@@ -393,14 +386,16 @@ $sActualSignature
*/ */
CSS; CSS;
if (!static::$oCompileCSSService) if (!static::$oCompileCSSService) {
{
static::$oCompileCSSService = new CompileCSSService(); static::$oCompileCSSService = new CompileCSSService();
} }
//store it again to change $version with latest compiled time //store it again to change $version with latest compiled time
SetupLog::Info("Compiling theme $sThemeId..."); SetupLog::Info("Compiling theme $sThemeId...");
$sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, $sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS(
$aThemeParametersWithVersion); $sTmpThemeScssContent,
$aImportsPaths,
$aThemeParametersWithVersion
);
SetupLog::Info("$sThemeId theme compilation done."); SetupLog::Info("$sThemeId theme compilation done.");
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters)); file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent); file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
@@ -425,13 +420,14 @@ CSS;
* @return string * @return string
* @throws \Exception * @throws \Exception
*/ */
public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages) { public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages)
{
$aSignature = [ $aSignature = [
'variables' => md5(json_encode($aThemeParameters['variables'])), 'variables' => md5(json_encode($aThemeParameters['variables'])),
'stylesheets' => [], 'stylesheets' => [],
'variable_imports' => [], 'variable_imports' => [],
'images' => [], 'images' => [],
'utility_imports' => [] 'utility_imports' => [],
]; ];
$oFindStylesheetObject = new FindStylesheetObject(); $oFindStylesheetObject = new FindStylesheetObject();
@@ -473,8 +469,7 @@ CSS;
} }
} }
foreach ($aIncludedImages as $sImage) foreach ($aIncludedImages as $sImage) {
{
if (is_file($sImage)) { if (is_file($sImage)) {
$sUri = str_replace(self::GetAppRootWithSlashes(), '', $sImage); $sUri = str_replace(self::GetAppRootWithSlashes(), '', $sImage);
$aSignature['images'][$sUri] = md5_file($sImage); $aSignature['images'][$sUri] = md5_file($sImage);
@@ -501,7 +496,7 @@ CSS;
$aCompleteUrls = []; $aCompleteUrls = [];
$aToCompleteUrls = []; $aToCompleteUrls = [];
$aMissingVariables = []; $aMissingVariables = [];
$aFoundVariables = ['version'=>'']; $aFoundVariables = ['version' => ''];
$aMap = [ $aMap = [
'aCompleteUrls' => $aCompleteUrls, 'aCompleteUrls' => $aCompleteUrls,
'aToCompleteUrls' => $aToCompleteUrls, 'aToCompleteUrls' => $aToCompleteUrls,
@@ -509,14 +504,11 @@ CSS;
'aFoundVariables' => $aFoundVariables, 'aFoundVariables' => $aFoundVariables,
]; ];
foreach ($aStylesheetFiles as $sStylesheetFile) foreach ($aStylesheetFiles as $sStylesheetFile) {
{
$aRes = static::GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile); $aRes = static::GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile);
/** @var array $aVal */ /** @var array $aVal */
foreach($aMap as $key => $aVal) foreach ($aMap as $key => $aVal) {
{ if (array_key_exists($key, $aMap)) {
if (array_key_exists($key, $aMap))
{
$aMap[$key] = array_merge($aVal, $aRes[$key]); $aMap[$key] = array_merge($aVal, $aRes[$key]);
} }
} }
@@ -525,17 +517,14 @@ CSS;
$aMap = static::ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFiles); $aMap = static::ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFiles);
$aImages = []; $aImages = [];
foreach ($aMap ['aCompleteUrls'] as $sUri => $sUrl) foreach ($aMap ['aCompleteUrls'] as $sUri => $sUrl) {
{
$sImg = $sUrl; $sImg = $sUrl;
if (preg_match("/(.*)\?/", $sUrl, $aMatches)) if (preg_match("/(.*)\?/", $sUrl, $aMatches)) {
{ $sImg = $aMatches[1];
$sImg=$aMatches[1];
} }
if (static::HasImageExtension($sImg) if (static::HasImageExtension($sImg)
&& ! array_key_exists($sImg, $aImages)) && ! array_key_exists($sImg, $aImages)) {
{
$sFilePath = utils::RealPath($sImg, APPROOT); $sFilePath = utils::RealPath($sImg, APPROOT);
if ($sFilePath !== false) { if ($sFilePath !== false) {
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath); $sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
@@ -566,8 +555,8 @@ CSS;
*/ */
public static function CanonicalizePath($path) public static function CanonicalizePath($path)
{ {
$path = explode('/', str_replace('//','/', $path)); $path = explode('/', str_replace('//', '/', $path));
$stack = array(); $stack = [];
foreach ($path as $seg) { foreach ($path as $seg) {
if ($seg == '..') { if ($seg == '..') {
// Ignore this segment, remove last segment from stack // Ignore this segment, remove last segment from stack
@@ -597,25 +586,23 @@ CSS;
*/ */
public static function ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFile) public static function ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFile)
{ {
$sContent=""; $sContent = "";
foreach ($aStylesheetFile as $sStylesheetFile) foreach ($aStylesheetFile as $sStylesheetFile) {
{ if (is_file($sStylesheetFile)) {
if (is_file($sStylesheetFile)) $sContent .= '\n'.file_get_contents($sStylesheetFile);
{
$sContent .= '\n' . file_get_contents($sStylesheetFile);
} }
} }
$aMissingVariables=$aMap['aMissingVariables']; $aMissingVariables = $aMap['aMissingVariables'];
$aFoundVariables=$aMap['aFoundVariables']; $aFoundVariables = $aMap['aFoundVariables'];
$aToCompleteUrls=$aMap['aToCompleteUrls']; $aToCompleteUrls = $aMap['aToCompleteUrls'];
$aCompleteUrls=$aMap['aCompleteUrls']; $aCompleteUrls = $aMap['aCompleteUrls'];
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, true); list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, true);
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls); list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
$aMap['aMissingVariables']=$aMissingVariables; $aMap['aMissingVariables'] = $aMissingVariables;
$aMap['aFoundVariables']=$aFoundVariables; $aMap['aFoundVariables'] = $aFoundVariables;
$aMap['aToCompleteUrls']=$aToCompleteUrls; $aMap['aToCompleteUrls'] = $aToCompleteUrls;
$aMap['aCompleteUrls']=$aCompleteUrls; $aMap['aCompleteUrls'] = $aCompleteUrls;
return $aMap; return $aMap;
} }
@@ -631,43 +618,29 @@ CSS;
* *
* @return array * @return array
*/ */
public static function FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, $bForceEmptyValueWhenNotFound=false) public static function FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, $bForceEmptyValueWhenNotFound = false)
{ {
$aNewMissingVars = []; $aNewMissingVars = [];
if (!empty($aMissingVariables)) if (!empty($aMissingVariables)) {
{ foreach ($aMissingVariables as $var) {
foreach ($aMissingVariables as $var) if (array_key_exists($var, $aThemeParametersVariables)) {
{
if (array_key_exists($var, $aThemeParametersVariables))
{
$aFoundVariables[$var] = $aThemeParametersVariables[$var]; $aFoundVariables[$var] = $aThemeParametersVariables[$var];
} } else {
else if (preg_match_all("/\\\$$var\s*:\s*[\"']{0,1}(.*)[\"']{0,1};/", $sContent, $aValues)) {
{
if (preg_match_all("/\\\$$var\s*:\s*[\"']{0,1}(.*)[\"']{0,1};/", $sContent, $aValues))
{
$sValue = $aValues[1][0]; $sValue = $aValues[1][0];
if (preg_match_all("/([^!]+)!/", $sValue, $aSubValues)) if (preg_match_all("/([^!]+)!/", $sValue, $aSubValues)) {
{
$sValue = trim($aSubValues[1][0], ' "\''); $sValue = trim($aSubValues[1][0], ' "\'');
} }
if (strpos($sValue, '$') === false) if (strpos($sValue, '$') === false) {
{
$aFoundVariables[$var] = $sValue; $aFoundVariables[$var] = $sValue;
} } else {
else{
$aNewMissingVars[] = $var; $aNewMissingVars[] = $var;
} }
} } else {
else if ($bForceEmptyValueWhenNotFound) {
{
if ($bForceEmptyValueWhenNotFound)
{
$aFoundVariables[$var] = ''; $aFoundVariables[$var] = '';
} } else {
else
{
$aNewMissingVars[] = $var; $aNewMissingVars[] = $var;
} }
} }
@@ -688,32 +661,23 @@ CSS;
*/ */
public static function ResolveUrls($aFoundVariables, array $aToCompleteUrls, array $aCompleteUrls) public static function ResolveUrls($aFoundVariables, array $aToCompleteUrls, array $aCompleteUrls)
{ {
if (!empty($aFoundVariables)) if (!empty($aFoundVariables)) {
{
$aFoundVariablesWithEmptyValue = []; $aFoundVariablesWithEmptyValue = [];
foreach ($aFoundVariables as $aFoundVariable => $sValue) foreach ($aFoundVariables as $aFoundVariable => $sValue) {
{
$aFoundVariablesWithEmptyValue[$aFoundVariable] = ''; $aFoundVariablesWithEmptyValue[$aFoundVariable] = '';
} }
foreach ($aToCompleteUrls as $sUrlTemplate) foreach ($aToCompleteUrls as $sUrlTemplate) {
{
unset($aToCompleteUrls[$sUrlTemplate]); unset($aToCompleteUrls[$sUrlTemplate]);
$sResolvedUrl = static::ResolveUrl($sUrlTemplate, $aFoundVariables); $sResolvedUrl = static::ResolveUrl($sUrlTemplate, $aFoundVariables);
if ($sResolvedUrl == false) if ($sResolvedUrl == false) {
{
$aToCompleteUrls[$sUrlTemplate] = $sUrlTemplate; $aToCompleteUrls[$sUrlTemplate] = $sUrlTemplate;
} } else {
else
{
$sUri = static::ResolveUrl($sUrlTemplate, $aFoundVariablesWithEmptyValue); $sUri = static::ResolveUrl($sUrlTemplate, $aFoundVariablesWithEmptyValue);
$aExplodedUri = explode('?', $sUri); $aExplodedUri = explode('?', $sUri);
if (empty($aExplodedUri)) if (empty($aExplodedUri)) {
{
$aCompleteUrls[$sUri] = $sResolvedUrl; $aCompleteUrls[$sUri] = $sResolvedUrl;
} } else {
else
{
$aCompleteUrls[$aExplodedUri[0]] = $sResolvedUrl; $aCompleteUrls[$aExplodedUri[0]] = $sResolvedUrl;
} }
} }
@@ -738,41 +702,31 @@ CSS;
$aMissingVariables = []; $aMissingVariables = [];
$aFoundVariables = []; $aFoundVariables = [];
if (is_file($sStylesheetFile)) if (is_file($sStylesheetFile)) {
{
$sContent = file_get_contents($sStylesheetFile); $sContent = file_get_contents($sStylesheetFile);
if (preg_match_all("/url\s*\((.*)\)/", $sContent, $aMatches)) if (preg_match_all("/url\s*\((.*)\)/", $sContent, $aMatches)) {
{ foreach ($aMatches[1] as $path) {
foreach ($aMatches[1] as $path)
{
$iRemainingClosingParenthesisPos = strpos($path, ')'); $iRemainingClosingParenthesisPos = strpos($path, ')');
if ($iRemainingClosingParenthesisPos !== false){ if ($iRemainingClosingParenthesisPos !== false) {
$path = substr($path, 0, $iRemainingClosingParenthesisPos); $path = substr($path, 0, $iRemainingClosingParenthesisPos);
} }
if (!array_key_exists($path, $aCompleteUrls) if (!array_key_exists($path, $aCompleteUrls)
&& !array_key_exists($path, $aToCompleteUrls)) && !array_key_exists($path, $aToCompleteUrls)) {
{ if (preg_match_all("/\\$([\w\-_]+)/", $path, $aCurrentVars)) {
if (preg_match_all("/\\$([\w\-_]+)/", $path, $aCurrentVars))
{
/** @var string $aCurrentVars */ /** @var string $aCurrentVars */
foreach ($aCurrentVars[1] as $var) foreach ($aCurrentVars[1] as $var) {
{ if (!array_key_exists($var, $aMissingVariables)) {
if (!array_key_exists($var, $aMissingVariables))
{
$aMissingVariables[$var] = $var; $aMissingVariables[$var] = $var;
} }
} }
$aToCompleteUrls[$path] = $path; $aToCompleteUrls[$path] = $path;
} } else {
else
{
$aCompleteUrls[$path] = trim($path, "\"'"); $aCompleteUrls[$path] = trim($path, "\"'");
} }
} }
} }
} }
if (!empty($aMissingVariables)) if (!empty($aMissingVariables)) {
{
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent); list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent);
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls); list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
} }
@@ -782,7 +736,7 @@ CSS;
'aCompleteUrls' => $aCompleteUrls, 'aCompleteUrls' => $aCompleteUrls,
'aToCompleteUrls' => $aToCompleteUrls, 'aToCompleteUrls' => $aToCompleteUrls,
'aMissingVariables' => $aMissingVariables, 'aMissingVariables' => $aMissingVariables,
'aFoundVariables' => $aFoundVariables 'aFoundVariables' => $aFoundVariables,
]; ];
} }
@@ -796,23 +750,21 @@ CSS;
*/ */
public static function ResolveUrl($sUrlTemplate, $aFoundVariables) public static function ResolveUrl($sUrlTemplate, $aFoundVariables)
{ {
$aPattern= []; $aPattern = [];
$aReplacement= []; $aReplacement = [];
foreach ($aFoundVariables as $aFoundVariable => $aFoundVariableValue) foreach ($aFoundVariables as $aFoundVariable => $aFoundVariableValue) {
{
//XX + $key + YY //XX + $key + YY
$aPattern[]="/['\"]\s*\+\s*\\\$" . $aFoundVariable . "[\s\+]+\s*['\"]/"; $aPattern[] = "/['\"]\s*\+\s*\\\$".$aFoundVariable."[\s\+]+\s*['\"]/";
$aReplacement[]=$aFoundVariableValue; $aReplacement[] = $aFoundVariableValue;
//$key + YY //$key + YY
$aPattern[]="/\\\$" . $aFoundVariable. "[\s\+]+\s*['\"]/"; $aPattern[] = "/\\\$".$aFoundVariable."[\s\+]+\s*['\"]/";
$aReplacement[]=$aFoundVariableValue; $aReplacement[] = $aFoundVariableValue;
//XX + $key //XX + $key
$aPattern[]="/['\"]\s*[\+\s]+\\\$" . $aFoundVariable . "$/"; $aPattern[] = "/['\"]\s*[\+\s]+\\\$".$aFoundVariable."$/";
$aReplacement[]=$aFoundVariableValue; $aReplacement[] = $aFoundVariableValue;
} }
$sResolvedUrl=preg_replace($aPattern, $aReplacement, $sUrlTemplate); $sResolvedUrl = preg_replace($aPattern, $aReplacement, $sUrlTemplate);
if (strpos($sResolvedUrl, "+")!==false) if (strpos($sResolvedUrl, "+") !== false) {
{
return false; return false;
} }
return trim($sResolvedUrl, "\"'"); return trim($sResolvedUrl, "\"'");
@@ -826,17 +778,14 @@ CSS;
*/ */
private static function HasImageExtension($path) private static function HasImageExtension($path)
{ {
foreach (static::IMAGE_EXTENSIONS as $sExt) foreach (static::IMAGE_EXTENSIONS as $sExt) {
{ if (endsWith($path, $sExt)) {
if (endsWith($path, $sExt))
{
return true; return true;
} }
} }
return false; return false;
} }
/** /**
* @since 3.0.0 N°2982 * @since 3.0.0 N°2982
* Extract the signature for a generated CSS file. * Extract the signature for a generated CSS file.
@@ -855,16 +804,13 @@ CSS;
$iCount = 0; $iCount = 0;
$sPreviousLine = ''; $sPreviousLine = '';
$hFile = @fopen($sFilepath, "r"); $hFile = @fopen($sFilepath, "r");
if ($hFile !== false) if ($hFile !== false) {
{
$sLine = ''; $sLine = '';
do do {
{
$iCount++; $iCount++;
$sPreviousLine = $sLine; $sPreviousLine = $sLine;
$sLine = rtrim(fgets($hFile)); // Remove the trailing \n $sLine = rtrim(fgets($hFile)); // Remove the trailing \n
} } while (($sLine !== false) && ($sLine != '=== SIGNATURE END ===') && ($iCount <= 100));
while (($sLine !== false) && ($sLine != '=== SIGNATURE END ===') && ($iCount <= 100));
fclose($hFile); fclose($hFile);
} }
return $sPreviousLine; return $sPreviousLine;
@@ -879,8 +825,7 @@ CSS;
public static function GetVarSignature($JsonSignature) public static function GetVarSignature($JsonSignature)
{ {
$aJsonArray = json_decode($JsonSignature, true); $aJsonArray = json_decode($JsonSignature, true);
if (array_key_exists('variables', $aJsonArray)) if (array_key_exists('variables', $aJsonArray)) {
{
return $aJsonArray['variables']; return $aJsonArray['variables'];
} }
return false; return false;
@@ -904,23 +849,22 @@ CSS;
$oFindStylesheetObject->ResetLastStyleSheet(); $oFindStylesheetObject->ResetLastStyleSheet();
} }
foreach($aImportsPaths as $sPath) foreach ($aImportsPaths as $sPath) {
{
$sAlterableFileURI = $sFileURI; $sAlterableFileURI = $sFileURI;
$sFilePath = $sPath.'/'.$sAlterableFileURI; $sFilePath = $sPath.'/'.$sAlterableFileURI;
$sImportedFile = realpath($sFilePath); $sImportedFile = realpath($sFilePath);
if ($sImportedFile === false){ if ($sImportedFile === false) {
// Handle shortcut syntax : @import "typo" ; // Handle shortcut syntax : @import "typo" ;
// file matched: typo.scss // file matched: typo.scss
$sFilePath2 = "$sFilePath.scss"; $sFilePath2 = "$sFilePath.scss";
$sImportedFile = realpath($sFilePath2); $sImportedFile = realpath($sFilePath2);
if ($sImportedFile){ if ($sImportedFile) {
self::FindStylesheetFile("$sAlterableFileURI.scss", [ $sPath ], $oFindStylesheetObject, $bImports); self::FindStylesheetFile("$sAlterableFileURI.scss", [ $sPath ], $oFindStylesheetObject, $bImports);
$sImportedFile = false; $sImportedFile = false;
} }
} }
if ($sImportedFile === false){ if ($sImportedFile === false) {
// Handle shortcut syntax : @import "typo" ; // Handle shortcut syntax : @import "typo" ;
// file matched: _typo.scss // file matched: _typo.scss
$sShortCut = substr($sFilePath, strrpos($sFilePath, '/') + 1); $sShortCut = substr($sFilePath, strrpos($sFilePath, '/') + 1);
@@ -930,11 +874,10 @@ CSS;
} }
if ((file_exists($sImportedFile)) if ((file_exists($sImportedFile))
&& (!$oFindStylesheetObject->AlreadyFetched($sImportedFile))) && (!$oFindStylesheetObject->AlreadyFetched($sImportedFile))) {
{ if ($bImports) {
if ($bImports){
$oFindStylesheetObject->AddImport($sAlterableFileURI, $sImportedFile); $oFindStylesheetObject->AddImport($sAlterableFileURI, $sImportedFile);
}else{ } else {
$oFindStylesheetObject->AddStylesheet($sAlterableFileURI, $sImportedFile); $oFindStylesheetObject->AddStylesheet($sAlterableFileURI, $sImportedFile);
} }
$oFindStylesheetObject->UpdateLastModified($sImportedFile); $oFindStylesheetObject->UpdateLastModified($sImportedFile);
@@ -942,8 +885,8 @@ CSS;
//Regexp matching on all included scss files : @import 'XXX.scss'; //Regexp matching on all included scss files : @import 'XXX.scss';
$sDirUri = dirname($sAlterableFileURI); $sDirUri = dirname($sAlterableFileURI);
preg_match_all('/@import \s*[\"\']([^\"\']*)\s*[\"\']\s*;/', file_get_contents($sImportedFile), $aMatches); preg_match_all('/@import \s*[\"\']([^\"\']*)\s*[\"\']\s*;/', file_get_contents($sImportedFile), $aMatches);
if ( (is_array($aMatches)) && (count($aMatches)!==0) ){ if ((is_array($aMatches)) && (count($aMatches) !== 0)) {
foreach ($aMatches[1] as $sImportedFile){ foreach ($aMatches[1] as $sImportedFile) {
self::FindStylesheetFile("$sDirUri/$sImportedFile", [ $sPath ], $oFindStylesheetObject, true); self::FindStylesheetFile("$sDirUri/$sImportedFile", [ $sPath ], $oFindStylesheetObject, true);
} }
} }
@@ -964,8 +907,7 @@ CSS;
{ {
$iPos = strrpos($sSubject, $sSearch); $iPos = strrpos($sSubject, $sSearch);
if($iPos !== false) if ($iPos !== false) {
{
$sSubject = substr_replace($sSubject, $sReplace, $iPos, strlen($sSearch)); $sSubject = substr_replace($sSubject, $sReplace, $iPos, strlen($sSearch));
} }
@@ -994,18 +936,14 @@ CSS;
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp, $aImportsPaths) public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp, $aImportsPaths)
{ {
$aThemeParametersVariable = []; $aThemeParametersVariable = [];
if (array_key_exists('variables', $aThemeParameters)) if (array_key_exists('variables', $aThemeParameters)) {
{ if (is_array($aThemeParameters['variables'])) {
if (is_array($aThemeParameters['variables']))
{
$aThemeParametersVariable = array_merge([], $aThemeParameters['variables']); $aThemeParametersVariable = array_merge([], $aThemeParameters['variables']);
} }
} }
if (array_key_exists('variable_imports', $aThemeParameters)) if (array_key_exists('variable_imports', $aThemeParameters)) {
{ if (is_array($aThemeParameters['variable_imports'])) {
if (is_array($aThemeParameters['variable_imports']))
{
$aThemeParametersVariable = array_merge($aThemeParametersVariable, static::GetVariablesFromFile($aThemeParameters['variable_imports'], $aImportsPaths)); $aThemeParametersVariable = array_merge($aThemeParametersVariable, static::GetVariablesFromFile($aThemeParameters['variable_imports'], $aImportsPaths));
} }
} }
@@ -1021,11 +959,11 @@ CSS;
* @return array * @return array
* @since 3.0.0 N°3593 * @since 3.0.0 N°3593
*/ */
public static function GetVariablesFromFile($aVariableFiles, $aImportsPaths){ public static function GetVariablesFromFile($aVariableFiles, $aImportsPaths)
{
$aVariablesResults = []; $aVariablesResults = [];
foreach ($aVariableFiles as $sVariableFile) foreach ($aVariableFiles as $sVariableFile) {
{ foreach ($aImportsPaths as $sPath) {
foreach($aImportsPaths as $sPath) {
$sFilePath = $sPath.'/'.$sVariableFile; $sFilePath = $sPath.'/'.$sVariableFile;
$sImportedFile = realpath($sFilePath); $sImportedFile = realpath($sFilePath);
if ($sImportedFile !== false) { if ($sImportedFile !== false) {
@@ -1041,9 +979,8 @@ CSS;
} }
} }
} }
array_map( function($sVariableValue) { return ltrim($sVariableValue); }, $aVariablesResults ); array_map(function ($sVariableValue) { return ltrim($sVariableValue); }, $aVariablesResults);
return $aVariablesResults; return $aVariablesResults;
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -29,7 +30,8 @@ class ThemeHandlerService
{ {
} }
public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp = "", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null){ public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp = "", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
{
return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp, $aThemeParameters, $aImportsPaths, $sWorkingPath); return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp, $aThemeParameters, $aImportsPaths, $sWorkingPath);
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (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 * 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 * 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' * which choice is configured via the parameter 'transaction_storage'
* *
* @package iTop * @package iTop
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -37,13 +38,11 @@ class privUITransaction
public static function GetNewTransactionId() public static function GetNewTransactionId()
{ {
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled'); $bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled) if (!$bTransactionsEnabled) {
{
return 'notransactions'; // Any value will do return 'notransactions'; // Any value will do
} }
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage'); $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."); 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'; $sClass = 'privUITransactionSession';
} }
@@ -62,16 +61,14 @@ class privUITransaction
public static function IsTransactionValid($id, $bRemoveTransaction = true) public static function IsTransactionValid($id, $bRemoveTransaction = true)
{ {
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled'); $bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled) if (!$bTransactionsEnabled) {
{
return true; // All values are valid return true; // All values are valid
} }
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage'); $sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage');
if (!class_exists($sClass, false)) if (!class_exists($sClass, false)) {
{
$sClass = 'privUITransactionSession'; $sClass = 'privUITransactionSession';
} }
return $sClass::IsTransactionValid($id, $bRemoveTransaction); return $sClass::IsTransactionValid($id, $bRemoveTransaction);
} }
@@ -83,16 +80,14 @@ class privUITransaction
public static function RemoveTransaction($id) public static function RemoveTransaction($id)
{ {
$bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled'); $bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled');
if (!$bTransactionsEnabled) if (!$bTransactionsEnabled) {
{
return; // Nothing to do return; // Nothing to do
} }
$sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage'); $sClass = 'privUITransaction'.MetaModel::GetConfig()->Get('transaction_storage');
if (!class_exists($sClass, false)) if (!class_exists($sClass, false)) {
{
$sClass = 'privUITransactionSession'; $sClass = 'privUITransactionSession';
} }
$sClass::RemoveTransaction($id); $sClass::RemoveTransaction($id);
} }
} }
@@ -114,17 +109,16 @@ class privUITransactionSession
*/ */
public static function GetNewTransactionId() public static function GetNewTransactionId()
{ {
if (!Session::IsSet('transactions')) if (!Session::IsSet('transactions')) {
{
Session::Set('transactions', []); Session::Set('transactions', []);
} }
// Strictly speaking, the two lines below should be grouped together // Strictly speaking, the two lines below should be grouped together
// by a critical section // by a critical section
// sem_acquire($rSemIdentified); // sem_acquire($rSemIdentified);
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime()); $id = static::GetUserPrefix().str_replace(['.', ' '], '', microtime());
Session::Set(['transactions', $id], true); Session::Set(['transactions', $id], true);
// sem_release($rSemIdentified); // sem_release($rSemIdentified);
return (string)$id; return (string)$id;
} }
@@ -135,20 +129,17 @@ class privUITransactionSession
* @param int $id Identifier of the transaction, as returned by GetNewTransactionId * @param int $id Identifier of the transaction, as returned by GetNewTransactionId
* @param bool $bRemoveTransaction True if the transaction must be removed * @param bool $bRemoveTransaction True if the transaction must be removed
* @return bool True if the transaction is valid, false otherwise * @return bool True if the transaction is valid, false otherwise
*/ */
public static function IsTransactionValid($id, $bRemoveTransaction = true) public static function IsTransactionValid($id, $bRemoveTransaction = true)
{ {
$bResult = false; $bResult = false;
if (Session::IsSet('transactions')) if (Session::IsSet('transactions')) {
{
// Strictly speaking, the eight lines below should be grouped together // Strictly speaking, the eight lines below should be grouped together
// inside the same critical section as above // inside the same critical section as above
// sem_acquire($rSemIdentified); // sem_acquire($rSemIdentified);
if (Session::IsSet(['transactions', $id])) if (Session::IsSet(['transactions', $id])) {
{
$bResult = true; $bResult = true;
if ($bRemoveTransaction) if ($bRemoveTransaction) {
{
Session::Unset(['transactions', $id]); Session::Unset(['transactions', $id]);
} }
} }
@@ -156,7 +147,7 @@ class privUITransactionSession
} }
return $bResult; return $bResult;
} }
/** /**
* Removes the transaction specified by its id * Removes the transaction specified by its id
* @param int $id The Identifier (as returned by GetNewTranscationId) of the transaction to be removed. * @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) public static function RemoveTransaction($id)
{ {
if (Session::IsSet('transactions')) if (Session::IsSet('transactions')) {
{
// Strictly speaking, the three lines below should be grouped together // Strictly speaking, the three lines below should be grouped together
// inside the same critical section as above // inside the same critical section as above
// sem_acquire($rSemIdentified); // sem_acquire($rSemIdentified);
if (Session::IsSet(['transactions', $id])) if (Session::IsSet(['transactions', $id])) {
{
Session::Unset(['transactions', $id]); Session::Unset(['transactions', $id]);
} }
// sem_release($rSemIdentified); // sem_release($rSemIdentified);
} }
} }
/** /**
@@ -197,7 +186,7 @@ class privUITransactionSession
class privUITransactionFile class privUITransactionFile
{ {
/** @var int Value to use when no user logged */ /** @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 * @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() public static function GetNewTransactionId()
{ {
if (!is_dir(APPROOT.'data/transactions')) if (!is_dir(APPROOT.'data/transactions')) {
{ if (!is_writable(APPROOT.'data')) {
if (!is_writable(APPROOT.'data'))
{
throw new Exception('The directory "'.APPROOT.'data" must be writable to the application.'); throw new Exception('The directory "'.APPROOT.'data" must be writable to the application.');
} }
// condition avoids race condition N°2345 // condition avoids race condition N°2345
// See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition // See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition
if (!mkdir($concurrentDirectory = APPROOT.'data/transactions') && !is_dir($concurrentDirectory)) if (!mkdir($concurrentDirectory = APPROOT.'data/transactions') && !is_dir($concurrentDirectory)) {
{
throw new Exception('Failed to create the directory "'.APPROOT.'data/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.'); throw new Exception('Failed to create the directory "'.APPROOT.'data/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(APPROOT.'data/transactions')) if (!is_writable(APPROOT.'data/transactions')) {
{
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.'); throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
} }
@@ -277,8 +262,7 @@ class privUITransactionFile
// Constraint the transaction file within APPROOT.'data/transactions' // Constraint the transaction file within APPROOT.'data/transactions'
$sTransactionDir = realpath(APPROOT.'data/transactions'); $sTransactionDir = realpath(APPROOT.'data/transactions');
$sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir); $sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir);
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath))) if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath))) {
{
return false; return false;
} }
@@ -297,15 +281,11 @@ class privUITransactionFile
return false; return false;
} }
if ($bRemoveTransaction) if ($bRemoveTransaction) {
{
$bResult = @unlink($sFilepath); $bResult = @unlink($sFilepath);
if (!$bResult) if (!$bResult) {
{
self::Error('IsTransactionValid: FAILED to remove transaction '.$id); self::Error('IsTransactionValid: FAILED to remove transaction '.$id);
} } else {
else
{
self::Info('IsTransactionValid: OK. Removed transaction: '.$id); self::Info('IsTransactionValid: OK. Removed transaction: '.$id);
} }
} }
@@ -347,13 +327,11 @@ class privUITransactionFile
} }
clearstatcache(); clearstatcache();
$iLimit = time() - 24*3600; $iLimit = time() - 24 * 3600;
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : APPROOT.'data/transactions/*'; $sPattern = $sTransactionDir ? "$sTransactionDir/*" : APPROOT.'data/transactions/*';
$aTransactions = glob($sPattern); $aTransactions = glob($sPattern);
foreach($aTransactions as $sFileName) foreach ($aTransactions as $sFileName) {
{ if (filemtime($sFileName) < $iLimit) {
if (filemtime($sFileName) < $iLimit)
{
@unlink($sFileName); @unlink($sFileName);
self::Info('CleanupOldTransactions: Deleted transaction: '.$sFileName); self::Info('CleanupOldTransactions: Deleted transaction: '.$sFileName);
} }
@@ -367,10 +345,9 @@ class privUITransactionFile
protected static function GetPendingTransactions() protected static function GetPendingTransactions()
{ {
clearstatcache(); clearstatcache();
$aResult = array(); $aResult = [];
$aTransactions = glob(APPROOT.'data/transactions/'.self::GetUserPrefix().'*'); $aTransactions = glob(APPROOT.'data/transactions/'.self::GetUserPrefix().'*');
foreach($aTransactions as $sFileName) foreach ($aTransactions as $sFileName) {
{
$aResult[] = date('Y-m-d H:i:s', filemtime($sFileName)).' - '.basename($sFileName); $aResult[] = date('Y-m-d H:i:s', filemtime($sFileName)).' - '.basename($sFileName);
} }
sort($aResult); sort($aResult);
@@ -398,13 +375,14 @@ class privUITransactionFile
{ {
self::Write('Warning | '.$sText); self::Write('Warning | '.$sText);
} }
protected static function Error($sText) protected static function Error($sText)
{ {
self::Write('Error | '.$sText); self::Write('Error | '.$sText);
} }
protected static function IsLogEnabled() { protected static function IsLogEnabled()
{
$oConfig = MetaModel::GetConfig(); $oConfig = MetaModel::GetConfig();
if (is_null($oConfig)) { if (is_null($oConfig)) {
return false; return false;

View File

@@ -34,24 +34,32 @@ class TwigExtension
{ {
// Filter to translate a string via the Dict::S function // Filter to translate a string via the Dict::S function
// Usage in twig: {{ 'String:ToTranslate'|dict_s }} // Usage in twig: {{ 'String:ToTranslate'|dict_s }}
$oTwigEnv->addFilter(new TwigFilter('dict_s', $oTwigEnv->addFilter(
new TwigFilter(
'dict_s',
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) { function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly); return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
}) }
)
); );
// Filter to format a string via the Dict::Format function // Filter to format a string via the Dict::Format function
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }} // Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
$oTwigEnv->addFilter(new TwigFilter('dict_format', $oTwigEnv->addFilter(
new TwigFilter(
'dict_format',
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) { function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04); return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
}) }
)
); );
// Filter to format output // Filter to format output
// example a DateTime is converted to user format // example a DateTime is converted to user format
// Usage in twig: {{ 'String:ToFormat'|output_format }} // Usage in twig: {{ 'String:ToFormat'|output_format }}
$oTwigEnv->addFilter(new TwigFilter('date_format', $oTwigEnv->addFilter(
new TwigFilter(
'date_format',
function ($sDate) { function ($sDate) {
try { try {
if (preg_match('@^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$@', trim($sDate))) { if (preg_match('@^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$@', trim($sDate))) {
@@ -60,22 +68,23 @@ class TwigExtension
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate))) { if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate))) {
return AttributeDate::GetFormat()->Format($sDate); return AttributeDate::GetFormat()->Format($sDate);
} }
} } catch (Exception $e) {
catch (Exception $e)
{
} }
return $sDate; return $sDate;
}) }
)
); );
// Filter to format output // Filter to format output
// example a DateTime is converted to user format // example a DateTime is converted to user format
// Usage in twig: {{ 'String:ToFormat'|output_format }} // Usage in twig: {{ 'String:ToFormat'|output_format }}
$oTwigEnv->addFilter(new TwigFilter('size_format', $oTwigEnv->addFilter(
new TwigFilter(
'size_format',
function ($sSize) { function ($sSize) {
return utils::BytesToFriendlyFormat($sSize); return utils::BytesToFriendlyFormat($sSize);
}) }
)
); );
// Filter to enable base64 encode/decode // Filter to enable base64 encode/decode
@@ -85,7 +94,8 @@ class TwigExtension
// Filter to enable json decode (encode already exists) // Filter to enable json decode (encode already exists)
// Usage in twig: {{ aSomeArray|json_decode }} // Usage in twig: {{ aSomeArray|json_decode }}
$oTwigEnv->addFilter(new TwigFilter('json_decode', function ($sJsonString, $bAssoc = false) { $oTwigEnv->addFilter(
new TwigFilter('json_decode', function ($sJsonString, $bAssoc = false) {
return json_decode($sJsonString, $bAssoc); return json_decode($sJsonString, $bAssoc);
}) })
); );

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -54,8 +55,8 @@ require_once(APPROOT.'/application/displayblock.class.inc.php');
*/ */
class UIExtKeyWidget class UIExtKeyWidget
{ {
const ENUM_OUTPUT_FORMAT_CSV = 'csv'; public const ENUM_OUTPUT_FORMAT_CSV = 'csv';
const ENUM_OUTPUT_FORMAT_JSON = 'json'; public const ENUM_OUTPUT_FORMAT_JSON = 'json';
protected $iId; protected $iId;
protected $sTargetClass; protected $sTargetClass;
@@ -87,10 +88,20 @@ class UIExtKeyWidget
* @since 2.7.7 3.0.1 3.1.0 N°3129 Add default value for $aArgs for PHP 8.0 compat * @since 2.7.7 3.0.1 3.1.0 N°3129 Add default value for $aArgs for PHP 8.0 compat
*/ */
public static function DisplayFromAttCode( public static function DisplayFromAttCode(
$oPage, $sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName = '', $sFormPrefix = '', $oPage,
$aArgs = [], $bSearchMode = false, &$sInputType = '' $sAttCode,
) $sClass,
{ $sTitle,
$oAllowedValues,
$value,
$iInputId,
$bMandatory,
$sFieldName = '',
$sFormPrefix = '',
$aArgs = [],
$bSearchMode = false,
&$sInputType = ''
) {
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sTargetClass = $oAttDef->GetTargetClass(); $sTargetClass = $oAttDef->GetTargetClass();
$iMaxComboLength = $oAttDef->GetMaximumComboLength(); $iMaxComboLength = $oAttDef->GetMaximumComboLength();
@@ -102,8 +113,7 @@ class UIExtKeyWidget
} }
$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode); $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode);
if (!$bSearchMode) { if (!$bSearchMode) {
switch ($sDisplayStyle) switch ($sDisplayStyle) {
{
case 'radio': case 'radio':
case 'radio_horizontal': case 'radio_horizontal':
case 'radio_vertical': case 'radio_vertical':
@@ -114,12 +124,38 @@ class UIExtKeyWidget
case 'select': case 'select':
case 'list': case 'list':
default: default:
return $oWidget->DisplaySelect($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, return $oWidget->DisplaySelect(
$bMandatory, $sFieldName, $sFormPrefix, $aArgs, $sInputType); $oPage,
$iMaxComboLength,
$bAllowTargetCreation,
$sTitle,
$oAllowedValues,
$value,
$bMandatory,
$sFieldName,
$sFormPrefix,
$aArgs,
$sInputType
);
} }
} else { } else {
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, return $oWidget->Display(
$bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle, true, $sInputType); $oPage,
$iMaxComboLength,
$bAllowTargetCreation,
$sTitle,
$oAllowedValues,
$value,
$iInputId,
$bMandatory,
$sFieldName,
$sFormPrefix,
$aArgs,
null,
$sDisplayStyle,
true,
$sInputType
);
} }
} }
@@ -158,7 +194,7 @@ class UIExtKeyWidget
* @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete * @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete
* @since 3.0.0 N°3750 new $sInputType parameter * @since 3.0.0 N°3750 new $sInputType parameter
*/ */
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '') public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = [], &$sInputType = '')
{ {
$sTitle = addslashes($sTitle); $sTitle = addslashes($sTitle);
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js'); $oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
@@ -194,7 +230,7 @@ class UIExtKeyWidget
$bIsAutocomplete = $oAllowedValues->CountExceeds($iMaxComboLength); $bIsAutocomplete = $oAllowedValues->CountExceeds($iMaxComboLength);
$sWrapperCssClass = $bIsAutocomplete ? 'ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper'; $sWrapperCssClass = $bIsAutocomplete ? 'ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper';
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey ibo-input-wrapper ibo-input-select-wrapper--with-buttons $sWrapperCssClass\" data-attcode=\"".$this->sAttCode."\" data-validation=\"untouched\" data-accessibility-selectize-label=\"$sTitle\">"; $sHTMLValue = "<div class=\"field_input_zone field_input_extkey ibo-input-wrapper ibo-input-select-wrapper--with-buttons $sWrapperCssClass\" data-attcode=\"".$this->sAttCode."\" data-validation=\"untouched\" data-accessibility-selectize-label=\"$sTitle\">";
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count. // We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
if (!$bIsAutocomplete) { if (!$bIsAutocomplete) {
// Discrete list of values, use a SELECT or RADIO buttons depending on the config // Discrete list of values, use a SELECT or RADIO buttons depending on the config
@@ -281,21 +317,17 @@ EOF
$oPage->add_ready_script("$('#$this->iId').one('validate', function() { $(this).trigger('change'); } );"); $oPage->add_ready_script("$('#$this->iId').one('validate', function() { $(this).trigger('change'); } );");
} }
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">"; $sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
} } else {
else
{
// Too many choices, use an autocomplete // Too many choices, use an autocomplete
// Check that the given value is allowed // Check that the given value is allowed
$oSearch = $oAllowedValues->GetFilter(); $oSearch = $oAllowedValues->GetFilter();
$oSearch->AddCondition('id', $value); $oSearch->AddCondition('id', $value);
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
if ($oSet->Count() == 0) if ($oSet->Count() == 0) {
{
$value = null; $value = null;
} }
if (is_null($value) || ($value == 0)) // Null values are displayed as '' if (is_null($value) || ($value == 0)) { // Null values are displayed as ''
{
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : ''; $sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
} else { } else {
$sDisplayValue = $this->GetObjectName($value); $sDisplayValue = $this->GetObjectName($value);
@@ -376,36 +408,30 @@ JS
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">"; $sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
if (is_null($oAllowedValues)) if (is_null($oAllowedValues)) {
{
throw new Exception('Implementation: null value for allowed values definition'); throw new Exception('Implementation: null value for allowed values definition');
} }
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData()); $oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count. // We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
if (!$oAllowedValues->CountExceeds($iMaxComboLength)) if (!$oAllowedValues->CountExceeds($iMaxComboLength)) {
{
// Discrete list of values, use a SELECT or RADIO buttons depending on the config // Discrete list of values, use a SELECT or RADIO buttons depending on the config
$sValidationField = null; $sValidationField = null;
$bVertical = ($sDisplayStyle != 'radio_horizontal'); $bVertical = ($sDisplayStyle != 'radio_horizontal');
$bExtensions = false; $bExtensions = false;
$oAllowedValues->Rewind(); $oAllowedValues->Rewind();
$aAllowedValues = array(); $aAllowedValues = [];
while($oObj = $oAllowedValues->Fetch()) while ($oObj = $oAllowedValues->Fetch()) {
{
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName(); $aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
} }
$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField); $sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField);
$aEventsList[] ='change'; $aEventsList[] = 'change';
} } else {
else
{
$sHTMLValue .= "unable to display. Too much values"; $sHTMLValue .= "unable to display. Too much values";
} }
$sHTMLValue .= '<div class="ibo-input-select--action-buttons">'; $sHTMLValue .= '<div class="ibo-input-select--action-buttons">';
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
{
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>"; $sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
@@ -416,8 +442,7 @@ JS
JS JS
); );
} }
if ($bCreate && $bExtensions) if ($bCreate && $bExtensions) {
{
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject'; $sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>"; $sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
@@ -471,7 +496,7 @@ JS
* *
* @since 3.0.0 N°3750 new $sInputType parameter * @since 3.0.0 N°3750 new $sInputType parameter
*/ */
public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true, &$sInputType = '') public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = [], $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true, &$sInputType = '')
{ {
if (!is_null($bSearchMode)) { if (!is_null($bSearchMode)) {
$this->bSearchMode = $bSearchMode; $this->bSearchMode = $bSearchMode;
@@ -521,7 +546,7 @@ JS
$bVertical = ($sDisplayStyle != 'radio_horizontal'); $bVertical = ($sDisplayStyle != 'radio_horizontal');
$bExtensions = false; $bExtensions = false;
$oAllowedValues->Rewind(); $oAllowedValues->Rewind();
$aAllowedValues = array(); $aAllowedValues = [];
while ($oObj = $oAllowedValues->Fetch()) { while ($oObj = $oAllowedValues->Fetch()) {
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName(); $aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
} }
@@ -568,22 +593,22 @@ EOF
} }
$sHTMLValue .= "<option value=\"$key\" $sSelected>$display_value</option>\n"; $sHTMLValue .= "<option value=\"$key\" $sSelected>$display_value</option>\n";
} }
$sHTMLValue .= "</select>\n"; $sHTMLValue .= "</select>\n";
$sHTMLValue .= "</div>\n"; $sHTMLValue .= "</div>\n";
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_RAW; $sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_RAW;
if (($this->bSearchMode) && $bSearchMultiple) { if (($this->bSearchMode) && $bSearchMultiple) {
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_MULTIPLE_CHOICES; $sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_MULTIPLE_CHOICES;
$aOptions = array( $aOptions = [
'header' => true, 'header' => true,
'checkAllText' => Dict::S('UI:SearchValue:CheckAll'), 'checkAllText' => Dict::S('UI:SearchValue:CheckAll'),
'uncheckAllText' => Dict::S('UI:SearchValue:UncheckAll'), 'uncheckAllText' => Dict::S('UI:SearchValue:UncheckAll'),
'noneSelectedText' => Dict::S('UI:SearchValue:Any'), 'noneSelectedText' => Dict::S('UI:SearchValue:Any'),
'selectedText' => Dict::S('UI:SearchValue:NbSelected'), 'selectedText' => Dict::S('UI:SearchValue:NbSelected'),
'selectedList' => 1, 'selectedList' => 1,
); ];
$sJSOptions = json_encode($aOptions); $sJSOptions = json_encode($aOptions);
$oPage->add_ready_script("$('.multiselect').multiselect($sJSOptions);"); $oPage->add_ready_script("$('.multiselect').multiselect($sJSOptions);");
} }
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
@@ -606,8 +631,7 @@ EOF
$value = null; $value = null;
} }
if (is_null($value) || ($value == 0)) // Null values are displayed as '' if (is_null($value) || ($value == 0)) { // Null values are displayed as ''
{
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : ''; $sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
} else { } else {
$sDisplayValue = $this->GetObjectName($value); $sDisplayValue = $this->GetObjectName($value);
@@ -673,20 +697,22 @@ JS
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
/** @var \DBObject $oCurrObject */ /** @var \DBObject $oCurrObject */
$aArgs = $oCurrObject->ToArgsForQuery(); $aArgs = $oCurrObject->ToArgsForQuery();
$aParams = array('query_params' => $aArgs); $aParams = ['query_params' => $aArgs];
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs); $oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs);
$oFilter = $oSet->GetFilter(); $oFilter = $oSet->GetFilter();
} else if (!empty($this->sFilter)) { } elseif (!empty($this->sFilter)) {
$aParams = array(); $aParams = [];
$oFilter = DBObjectSearch::FromOQL($this->sFilter); $oFilter = DBObjectSearch::FromOQL($this->sFilter);
} else { } else {
$aParams = array(); $aParams = [];
$oFilter = new DBObjectSearch($this->sTargetClass); $oFilter = new DBObjectSearch($this->sTargetClass);
} }
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode); $oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams); $oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, 'dtc_'.$this->iId, $oPage->AddUiBlock($oBlock->GetDisplay(
array( $oPage,
'dtc_'.$this->iId,
[
'menu' => false, 'menu' => false,
'currentId' => $this->iId, 'currentId' => $this->iId,
'table_id' => "dr_{$this->iId}", 'table_id' => "dr_{$this->iId}",
@@ -694,12 +720,13 @@ JS
'selection_mode' => true, 'selection_mode' => true,
'selection_type' => 'single', 'selection_type' => 'single',
'cssCount' => '#count_'.$this->iId.'_results', 'cssCount' => '#count_'.$this->iId.'_results',
) ]
)); ));
$sCancel = Dict::S('UI:Button:Cancel'); $sCancel = Dict::S('UI:Button:Cancel');
$sOK = Dict::S('UI:Button:Ok'); $sOK = Dict::S('UI:Button:Ok');
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm'); $sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
$oPage->add(<<<HTML $oPage->add(
<<<HTML
<form id="fr_{$this->iId}" OnSubmit="return oACWidget_{$this->iId}.DoOk();"> <form id="fr_{$this->iId}" OnSubmit="return oACWidget_{$this->iId}.DoOk();">
<div id="dr_{$this->iId}"> <div id="dr_{$this->iId}">
<div><p>{$sEmptyList}</p></div> <div><p>{$sEmptyList}</p></div>
@@ -711,7 +738,8 @@ HTML
); );
$sDialogTitleSanitized = addslashes(utils::HtmlToText($sTitle)); $sDialogTitleSanitized = addslashes(utils::HtmlToText($sTitle));
$oPage->add_ready_script(<<<JS $oPage->add_ready_script(
<<<JS
$('#ac_dlg_{$this->iId}').dialog({ $('#ac_dlg_{$this->iId}').dialog({
width: $(window).width()*0.8, width: $(window).width()*0.8,
height: $(window).height()*0.8, height: $(window).height()*0.8,
@@ -751,14 +779,12 @@ JS
*/ */
public function SearchObjectsToSelect(WebPage $oP, $sFilter, $sRemoteClass = '', $oObj = null) public function SearchObjectsToSelect(WebPage $oP, $sFilter, $sRemoteClass = '', $oObj = null)
{ {
if (is_null($sFilter)) if (is_null($sFilter)) {
{
throw new Exception('Implementation: null value for allowed values definition'); throw new Exception('Implementation: null value for allowed values definition');
} }
$oFilter = DBObjectSearch::FromOQL($sFilter); $oFilter = DBObjectSearch::FromOQL($sFilter);
if (strlen($sRemoteClass) > 0) if (strlen($sRemoteClass) > 0) {
{
$oFilter->ChangeClass($sRemoteClass); $oFilter->ChangeClass($sRemoteClass);
} }
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode); $oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
@@ -766,26 +792,26 @@ JS
// Current extkey value, so we can display event if it is not available anymore (eg. archived). // Current extkey value, so we can display event if it is not available anymore (eg. archived).
$iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode); $iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode);
$oBlock = new DisplayBlock($oFilter, 'list_search', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId))); $oBlock = new DisplayBlock($oFilter, 'list_search', false, ['query_params' => ['this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId]]);
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId.'_results', 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results $oBlock->Display($oP, $this->iId.'_results', ['this' => $oObj, 'cssCount' => '#count_'.$this->iId.'_results', 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode]); // Don't display the 'Actions' menu on the results
} }
/** /**
* Search for objects to be selected * Search for objects to be selected
* *
* @param WebPage $oP The page used for the output (usually an AjaxWebPage) * @param WebPage $oP The page used for the output (usually an AjaxWebPage)
* @param string $sFilter The OQL expression used to define/limit limit the scope of possible values * @param string $sFilter The OQL expression used to define/limit limit the scope of possible values
* @param DBObject $oObj The current object for the OQL context * @param DBObject $oObj The current object for the OQL context
* @param string $sContains The text of the autocomplete to filter the results * @param string $sContains The text of the autocomplete to filter the results
* @param string $sOutputFormat * @param string $sOutputFormat
* @param null $sOperation for the values @see ValueSetObjects->LoadValues() not used since 3.0.0 * @param null $sOperation for the values @see ValueSetObjects->LoadValues() not used since 3.0.0
* *
* @throws CoreException * @throws CoreException
* @throws OQLException * @throws OQLException
* *
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $oObj for PHP 8.0 compatibility * @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $oObj for PHP 8.0 compatibility
*/ */
public function AutoComplete(WebPage $oP, $sFilter, $oObj, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null ) public function AutoComplete(WebPage $oP, $sFilter, $oObj, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null)
{ {
if (is_null($sFilter)) { if (is_null($sFilter)) {
throw new Exception('Implementation: null value for allowed values definition'); throw new Exception('Implementation: null value for allowed values definition');
@@ -799,38 +825,32 @@ JS
$oValuesSet->SetSort(false); $oValuesSet->SetSort(false);
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode); $oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oValuesSet->SetLimit($iMax); $oValuesSet->SetLimit($iMax);
$aValuesStartWith = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with'); $aValuesStartWith = $oValuesSet->GetValuesForAutocomplete(['this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId], $sContains, 'start_with');
asort($aValuesStartWith); asort($aValuesStartWith);
$aValues = $aValuesStartWith; $aValues = $aValuesStartWith;
if (sizeof($aValues) < $iMax) { if (sizeof($aValues) < $iMax) {
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains'); $aValuesContains = $oValuesSet->GetValuesForAutocomplete(['this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId], $sContains, 'contains');
asort($aValuesContains); asort($aValuesContains);
$iSize = sizeof($aValues); $iSize = sizeof($aValues);
foreach ($aValuesContains as $sKey => $sFriendlyName) foreach ($aValuesContains as $sKey => $sFriendlyName) {
{ if (!isset($aValues[$sKey])) {
if (!isset($aValues[$sKey]))
{
$aValues[$sKey] = $sFriendlyName; $aValues[$sKey] = $sFriendlyName;
if (++$iSize >= $iMax) if (++$iSize >= $iMax) {
{
break; break;
} }
} }
} }
} } elseif (!in_array($sContains, $aValues)) {
elseif (!in_array($sContains, $aValues)) $aValuesEquals = $oValuesSet->GetValuesForAutocomplete(['this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId], $sContains, 'equals');
{
$aValuesEquals = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals');
// Note: Here we cannot use array_merge as it would reindex the numeric keys starting from 0 when keys are actually the objects ID. // Note: Here we cannot use array_merge as it would reindex the numeric keys starting from 0 when keys are actually the objects ID.
// As a workaround we use array_replace as it does preserve numeric keys. It's ok if some values from $aValuesEquals are replaced with values from $aValues as they contain the same data. // As a workaround we use array_replace as it does preserve numeric keys. It's ok if some values from $aValuesEquals are replaced with values from $aValues as they contain the same data.
$aValues = array_replace($aValuesEquals, $aValues); $aValues = array_replace($aValuesEquals, $aValues);
} }
switch($sOutputFormat) switch ($sOutputFormat) {
{
case static::ENUM_OUTPUT_FORMAT_JSON: case static::ENUM_OUTPUT_FORMAT_JSON:
$aJsonMap = array(); $aJsonMap = [];
foreach ($aValues as $sKey => $aValue) { foreach ($aValues as $sKey => $aValue) {
$aElt = ['value' => $sKey, 'label' => utils::EscapeHtml($aValue['label']), 'obsolescence_flag' => $aValue['obsolescence_flag']]; $aElt = ['value' => $sKey, 'label' => utils::EscapeHtml($aValue['label']), 'obsolescence_flag' => $aValue['obsolescence_flag']];
if ($aValue['additional_field'] != '') { if ($aValue['additional_field'] != '') {
@@ -851,8 +871,7 @@ JS
break; break;
case static::ENUM_OUTPUT_FORMAT_CSV: case static::ENUM_OUTPUT_FORMAT_CSV:
foreach($aValues as $sKey => $aValue) foreach ($aValues as $sKey => $aValue) {
{
$oP->add(trim($aValue['label'])."\t".$sKey."\n"); $oP->add(trim($aValue['label'])."\t".$sKey."\n");
} }
break; break;
@@ -874,7 +893,7 @@ JS
*/ */
public function GetObjectName($iObjId, $sFormAttCode = null) public function GetObjectName($iObjId, $sFormAttCode = null)
{ {
$aModifierProps = array(); $aModifierProps = [];
$aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode; $aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode;
$oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps); $oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps);
@@ -884,9 +903,7 @@ JS
} else { } else {
return $oObj->Get($sFormAttCode); return $oObj->Get($sFormAttCode);
} }
} } else {
else
{
return ''; return '';
} }
} }
@@ -902,30 +919,29 @@ JS
*/ */
public function GetClassSelectionForm(WebPage $oPage) public function GetClassSelectionForm(WebPage $oPage)
{ {
// For security reasons: check that the "proposed" class is actually a subclass of the linked class // For security reasons: check that the "proposed" class is actually a subclass of the linked class
// and that the current user is allowed to create objects of this class // and that the current user is allowed to create objects of this class
$aSubClasses = MetaModel::EnumChildClasses($this->sTargetClass, ENUM_CHILD_CLASSES_ALL); $aSubClasses = MetaModel::EnumChildClasses($this->sTargetClass, ENUM_CHILD_CLASSES_ALL);
$aPossibleClasses = array(); $aPossibleClasses = [];
foreach($aSubClasses as $sCandidateClass) foreach ($aSubClasses as $sCandidateClass) {
{ if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) $aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass);
{ }
$aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass); }
}
}
$sClassLabel = MetaModel::GetName($this->sTargetClass); $sClassLabel = MetaModel::GetName($this->sTargetClass);
$sDialogTitle = Dict::Format('UI:CreationTitle_Class', $sClassLabel);; $sDialogTitle = Dict::Format('UI:CreationTitle_Class', $sClassLabel);
$oBlock = UIContentBlockUIBlockFactory::MakeStandard('ac_create_'.$this->iId,['ibo-is-visible']); ;
$oBlock = UIContentBlockUIBlockFactory::MakeStandard('ac_create_'.$this->iId, ['ibo-is-visible']);
$oPage->AddSubBlock($oBlock); $oPage->AddSubBlock($oBlock);
$oClassForm = FormUIBlockFactory::MakeStandard(); $oClassForm = FormUIBlockFactory::MakeStandard();
$oBlock->AddSubBlock($oClassForm); $oBlock->AddSubBlock($oClassForm);
$oClassForm->AddSubBlock(cmdbAbstractObject::DisplayBlockSelectClassToCreate( $sClassLabel, $this->sTargetClass, $aPossibleClasses)); $oClassForm->AddSubBlock(cmdbAbstractObject::DisplayBlockSelectClassToCreate($sClassLabel, $this->sTargetClass, $aPossibleClasses));
$sDialogTitleEscaped = addslashes($sDialogTitle); $sDialogTitleEscaped = addslashes($sDialogTitle);
$oPage->add_ready_script("$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitleEscaped'});\n"); $oPage->add_ready_script("$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitleEscaped'});\n");
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').removeAttr('onsubmit');"); $oPage->add_ready_script("$('#ac_create_{$this->iId} form').removeAttr('onsubmit');");
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').find('select').attr('id', 'ac_create_{$this->iId}_select');"); $oPage->add_ready_script("$('#ac_create_{$this->iId} form').find('select').attr('id', 'ac_create_{$this->iId}_select');");
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);"); $oPage->add_ready_script("$('#ac_create_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
} }
/** /**
@@ -941,16 +957,14 @@ JS
$oAppContext->InitObjectFromContext($oNewObj); $oAppContext->InitObjectFromContext($oNewObj);
$oNewObj->PrefillForm('creation_from_extkey', $aPrefillFormParam); $oNewObj->PrefillForm('creation_from_extkey', $aPrefillFormParam);
// 2nd set the default values from the constraint on the external key... if any // 2nd set the default values from the constraint on the external key... if any
if ( ($oCurrObject != null) && ($this->sAttCode != '')) if (($oCurrObject != null) && ($this->sAttCode != '')) {
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
$aParams = array('this' => $oCurrObject); $aParams = ['this' => $oCurrObject];
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aParams); $oSet = $oAttDef->GetAllowedValuesAsObjectSet($aParams);
$aConsts = $oSet->ListConstantFields(); $aConsts = $oSet->ListConstantFields();
$sClassAlias = $oSet->GetFilter()->GetClassAlias(); $sClassAlias = $oSet->GetFilter()->GetClassAlias();
if (isset($aConsts[$sClassAlias])) if (isset($aConsts[$sClassAlias])) {
{ foreach ($aConsts[$sClassAlias] as $sAttCode => $value) {
foreach($aConsts[$sClassAlias] as $sAttCode => $value) {
$oNewObj->Set($sAttCode, $value); $oNewObj->Set($sAttCode, $value);
} }
} }
@@ -962,32 +976,35 @@ JS
$sClassLabel = MetaModel::GetName($this->sTargetClass); $sClassLabel = MetaModel::GetName($this->sTargetClass);
$sHeaderTitleEscaped = utils::EscapeHtml(Dict::Format('UI:CreationTitle_Class', $sClassLabel)); $sHeaderTitleEscaped = utils::EscapeHtml(Dict::Format('UI:CreationTitle_Class', $sClassLabel));
$oPage->add(<<<HTML $oPage->add(
<<<HTML
<div id="ac_create_{$this->iId}" title="{$sHeaderTitleEscaped}"> <div id="ac_create_{$this->iId}" title="{$sHeaderTitleEscaped}">
<div id="dcr_{$this->iId}"> <div id="dcr_{$this->iId}">
HTML HTML
); );
$aFormExtraParams = array( $aFormExtraParams = [
'formPrefix' => $this->iId, 'formPrefix' => $this->iId,
'noRelations' => true, 'noRelations' => true,
); ];
// Remove blob edition from creation form @see N°5863 to allow blob edition in modal context // Remove blob edition from creation form @see N°5863 to allow blob edition in modal context
FormHelper::DisableAttributeBlobInputs($this->sTargetClass, $aFormExtraParams); FormHelper::DisableAttributeBlobInputs($this->sTargetClass, $aFormExtraParams);
if(FormHelper::HasMandatoryAttributeBlobInputs($oNewObj)){ if (FormHelper::HasMandatoryAttributeBlobInputs($oNewObj)) {
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE)); $oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE));
} }
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), $aFormExtraParams); cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, [], $aFormExtraParams);
$oPage->add(<<<HTML $oPage->add(
<<<HTML
</div> </div>
</div> </div>
HTML HTML
); );
$oPage->add_ready_script(<<<JS $oPage->add_ready_script(
<<<JS
$('#ac_create_{$this->iId}').dialog({ width: $(window).width() * 0.6, height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true}); $('#ac_create_{$this->iId}').dialog({ width: $(window).width() * 0.6, height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
$('#dcr_{$this->iId} form').removeAttr('onsubmit'); $('#dcr_{$this->iId} form').removeAttr('onsubmit');
$('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject); $('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject);
@@ -1003,14 +1020,13 @@ JS
$sDialogTitle = addslashes(Dict::Format('UI:HierarchyOf_Class', MetaModel::GetName($this->sTargetClass))); $sDialogTitle = addslashes(Dict::Format('UI:HierarchyOf_Class', MetaModel::GetName($this->sTargetClass)));
$oPage->add('<div id="dlg_tree_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div style="margin-bottom:5px;" id="tree_'.$this->iId.'">'); $oPage->add('<div id="dlg_tree_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div style="margin-bottom:5px;" id="tree_'.$this->iId.'">');
$oPage->add('<table style="width:100%"><tr><td>'); $oPage->add('<table style="width:100%"><tr><td>');
if (is_null($sFilter)) if (is_null($sFilter)) {
{
throw new Exception('Implementation: null value for allowed values definition'); throw new Exception('Implementation: null value for allowed values definition');
} }
$oFilter = DBObjectSearch::FromOQL($sFilter); $oFilter = DBObjectSearch::FromOQL($sFilter);
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode); $oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oSet = new DBObjectSet($oFilter, array(), array('this' => $oObj, 'current_extkey_id' => $currValue)); $oSet = new DBObjectSet($oFilter, [], ['this' => $oObj, 'current_extkey_id' => $currValue]);
$oSet->SetShowObsoleteData(utils::ShowObsoleteData()); $oSet->SetShowObsoleteData(utils::ShowObsoleteData());
@@ -1020,17 +1036,17 @@ JS
$oPage->add('</td></tr></table>'); $oPage->add('</td></tr></table>');
$oPage->add('</div>'); $oPage->add('</div>');
if ($bHasChildLeafs) if ($bHasChildLeafs) {
{
$oPage->add('<span class="treecontrol ibo-button-group" id="treecontrolid"><a class="ibo-button ibo-is-regular ibo-is-neutral" href="?#">'.Dict::S("UI:Treeview:CollapseAll").'</a><a class="ibo-button ibo-is-regular ibo-is-neutral" href="?#">'.Dict::S("UI:Treeview:ExpandAll").'</a></span>'); $oPage->add('<span class="treecontrol ibo-button-group" id="treecontrolid"><a class="ibo-button ibo-is-regular ibo-is-neutral" href="?#">'.Dict::S("UI:Treeview:CollapseAll").'</a><a class="ibo-button ibo-is-regular ibo-is-neutral" href="?#">'.Dict::S("UI:Treeview:ExpandAll").'</a></span>');
} }
$oPage->add('</div></div>'); $oPage->add('</div></div>');
$sOkButtonLabel = Dict::S('UI:Button:Ok'); $sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oPage->add_ready_script("\$('#tree_$this->iId ul').treeview({ control: '#treecontrolid', persist: 'false'});\n"); $oPage->add_ready_script("\$('#tree_$this->iId ul').treeview({ control: '#treecontrolid', persist: 'false'});\n");
$oPage->add_ready_script(<<<JS $oPage->add_ready_script(
<<<JS
$('#dlg_tree_$this->iId').dialog({ $('#dlg_tree_$this->iId').dialog({
width: 'auto', width: 'auto',
height: 'auto', height: 'auto',
@@ -1069,8 +1085,7 @@ JS
*/ */
public function DoCreateObject($oPage) public function DoCreateObject($oPage)
{ {
try try {
{
$oObj = MetaModel::NewObject($this->sTargetClass); $oObj = MetaModel::NewObject($this->sTargetClass);
$aErrors = $oObj->UpdateObjectFromPostedForm($this->iId); $aErrors = $oObj->UpdateObjectFromPostedForm($this->iId);
if (count($aErrors) == 0) { if (count($aErrors) == 0) {
@@ -1088,13 +1103,12 @@ JS
]); ]);
$oObj->DBInsertNoReload(); $oObj->DBInsertNoReload();
return array('name' => $oObj->GetName(), 'id' => $oObj->GetKey()); return ['name' => $oObj->GetName(), 'id' => $oObj->GetKey()];
} else { } else {
return array('error' => implode(' ', $aErrors), 'id' => 0); return ['error' => implode(' ', $aErrors), 'id' => 0];
} }
} } catch (Exception $e) {
catch (Exception $e) { return ['error' => $e->getMessage(), 'id' => 0];
return array('error' => $e->getMessage(), 'id' => 0);
} }
} }
@@ -1110,32 +1124,27 @@ JS
* @throws \CoreUnexpectedValue * @throws \CoreUnexpectedValue
* @throws \MySQLException * @throws \MySQLException
*/ */
function DumpTree($oP, $oSet, $sParentAttCode, $currValue) public function DumpTree($oP, $oSet, $sParentAttCode, $currValue)
{ {
$aTree = array(); $aTree = [];
$aNodes = array(); $aNodes = [];
while($oObj = $oSet->Fetch()) while ($oObj = $oSet->Fetch()) {
{
$iParentId = $oObj->Get($sParentAttCode); $iParentId = $oObj->Get($sParentAttCode);
if (!isset($aTree[$iParentId])) if (!isset($aTree[$iParentId])) {
{ $aTree[$iParentId] = [];
$aTree[$iParentId] = array();
} }
$aTree[$iParentId][$oObj->GetKey()] = $oObj->GetName(); $aTree[$iParentId][$oObj->GetKey()] = $oObj->GetName();
$aNodes[$oObj->GetKey()] = $oObj; $aNodes[$oObj->GetKey()] = $oObj;
} }
$aParents = array_keys($aTree); $aParents = array_keys($aTree);
$aRoots = array(); $aRoots = [];
foreach($aParents as $id) foreach ($aParents as $id) {
{ if (!array_key_exists($id, $aNodes)) {
if (!array_key_exists($id, $aNodes))
{
$aRoots[] = $id; $aRoots[] = $id;
} }
} }
foreach($aRoots as $iRootId) foreach ($aRoots as $iRootId) {
{
$this->DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue); $this->DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue);
} }
@@ -1143,28 +1152,22 @@ JS
return !$bHasOnlyRootNodes; return !$bHasOnlyRootNodes;
} }
function DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue) public function DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue)
{ {
$bSelect = true; $bSelect = true;
$bMultiple = false; $bMultiple = false;
$sSelect = ''; $sSelect = '';
if (array_key_exists($iRootId, $aTree)) if (array_key_exists($iRootId, $aTree)) {
{
$aSortedRoots = $aTree[$iRootId]; $aSortedRoots = $aTree[$iRootId];
asort($aSortedRoots); asort($aSortedRoots);
$oP->add("<ul>\n"); $oP->add("<ul>\n");
$fUniqueId = microtime(true); $fUniqueId = microtime(true);
foreach($aSortedRoots as $id => $sName) foreach ($aSortedRoots as $id => $sName) {
{ if ($bSelect) {
if ($bSelect)
{
$sChecked = ($aNodes[$id]->GetKey() == $currValue) ? 'checked' : ''; $sChecked = ($aNodes[$id]->GetKey() == $currValue) ? 'checked' : '';
if ($bMultiple) if ($bMultiple) {
{
$sSelect = '<input id="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'" type="checkbox" value="'.$aNodes[$id]->GetKey().'" name="selectObject[]" '.$sChecked.'>&nbsp;'; $sSelect = '<input id="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'" type="checkbox" value="'.$aNodes[$id]->GetKey().'" name="selectObject[]" '.$sChecked.'>&nbsp;';
} } else {
else
{
$sSelect = '<input id="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'" type="radio" value="'.$aNodes[$id]->GetKey().'" name="selectObject" '.$sChecked.'>&nbsp;'; $sSelect = '<input id="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'" type="radio" value="'.$aNodes[$id]->GetKey().'" name="selectObject" '.$sChecked.'>&nbsp;';
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -30,7 +31,7 @@ use Combodo\iTop\Renderer\BlockRenderer;
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
class UIHTMLEditorWidget class UIHTMLEditorWidget
{ {
protected $m_iId; protected $m_iId;
protected $m_oAttDef; protected $m_oAttDef;
@@ -41,7 +42,7 @@ class UIHTMLEditorWidget
protected $m_sValidationField; protected $m_sValidationField;
protected $m_sValue; protected $m_sValue;
protected $m_sMandatory; protected $m_sMandatory;
public function __construct($iInputId, $oAttDef, $sNameSuffix, $sFieldPrefix, $sHelpText, $sValidationField, $sValue, $sMandatory) public function __construct($iInputId, $oAttDef, $sNameSuffix, $sFieldPrefix, $sHelpText, $sValidationField, $sValue, $sMandatory)
{ {
$this->m_iId = $iInputId; $this->m_iId = $iInputId;
@@ -54,7 +55,7 @@ class UIHTMLEditorWidget
$this->m_sMandatory = $sMandatory; $this->m_sMandatory = $sMandatory;
$this->m_sFieldPrefix = $sFieldPrefix; $this->m_sFieldPrefix = $sFieldPrefix;
} }
/** /**
* Get the HTML fragment corresponding to the HTML editor widget * Get the HTML fragment corresponding to the HTML editor widget
* *
@@ -63,7 +64,7 @@ class UIHTMLEditorWidget
* *
* @return string The HTML fragment to be inserted into the page * @return string The HTML fragment to be inserted into the page
*/ */
public function Display(WebPage $oPage, array $aArgs = array()) : string public function Display(WebPage $oPage, array $aArgs = []): string
{ {
$iId = $this->m_iId; $iId = $this->m_iId;
$sCode = $this->m_sAttCode.$this->m_sNameSuffix; $sCode = $this->m_sAttCode.$this->m_sNameSuffix;

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -38,39 +39,35 @@ class UILinksWidgetDirect
$this->sAttCode = $sAttCode; $this->sAttCode = $sAttCode;
$this->sInputid = $sInputId; $this->sInputid = $sInputId;
$this->sNameSuffix = $sNameSuffix; $this->sNameSuffix = $sNameSuffix;
$this->aZlist = array(); $this->aZlist = [];
$this->sLinkedClass = ''; $this->sLinkedClass = '';
// Compute the list of attributes visible from the given objet: // Compute the list of attributes visible from the given objet:
// All the attributes from the "list" Zlist of the Link class except // All the attributes from the "list" Zlist of the Link class except
// the ExternalKey that points to the current object and its related external fields // the ExternalKey that points to the current object and its related external fields
$oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$this->sLinkedClass = $oLinksetDef->GetLinkedClass(); $this->sLinkedClass = $oLinksetDef->GetLinkedClass();
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe(); $sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
switch($oLinksetDef->GetEditMode()) switch ($oLinksetDef->GetEditMode()) {
{
case LINKSET_EDITMODE_INPLACE: // The whole linkset can be edited 'in-place' case LINKSET_EDITMODE_INPLACE: // The whole linkset can be edited 'in-place'
$aZList = MetaModel::FlattenZList(MetaModel::GetZListItems($this->sLinkedClass, 'details')); $aZList = MetaModel::FlattenZList(MetaModel::GetZListItems($this->sLinkedClass, 'details'));
break; break;
default: default:
$aZList = MetaModel::FlattenZList(MetaModel::GetZListItems($this->sLinkedClass, 'list')); $aZList = MetaModel::FlattenZList(MetaModel::GetZListItems($this->sLinkedClass, 'list'));
array_unshift($aZList, 'friendlyname'); array_unshift($aZList, 'friendlyname');
} }
foreach($aZList as $sLinkedAttCode) foreach ($aZList as $sLinkedAttCode) {
{ if ($sLinkedAttCode != $sExtKeyToMe) {
if ($sLinkedAttCode != $sExtKeyToMe)
{
$oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode); $oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode);
if ((!$oAttDef->IsExternalField() || ($oAttDef->GetKeyAttCode() != $sExtKeyToMe)) && if ((!$oAttDef->IsExternalField() || ($oAttDef->GetKeyAttCode() != $sExtKeyToMe)) &&
(!$oAttDef->IsLinkSet()) ) (!$oAttDef->IsLinkSet())) {
{
$this->aZlist[] = $sLinkedAttCode; $this->aZlist[] = $sLinkedAttCode;
} }
} }
} }
} }
/** /**
@@ -101,21 +98,17 @@ class UILinksWidgetDirect
$sRealClass = ''; $sRealClass = '';
//$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>'); //$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
$aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself $aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
$aPossibleClasses = array(); $aPossibleClasses = [];
foreach($aSubClasses as $sCandidateClass) foreach ($aSubClasses as $sCandidateClass) {
{ if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) if ($sCandidateClass == $sProposedRealClass) {
{
if ($sCandidateClass == $sProposedRealClass)
{
$sRealClass = $sProposedRealClass; $sRealClass = $sProposedRealClass;
} }
$aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass); $aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass);
} }
} }
// Only one of the subclasses can be instantiated... // Only one of the subclasses can be instantiated...
if (count($aPossibleClasses) == 1) if (count($aPossibleClasses) == 1) {
{
$aKeys = array_keys($aPossibleClasses); $aKeys = array_keys($aPossibleClasses);
$sRealClass = $aKeys[0]; $sRealClass = $aKeys[0];
} }
@@ -123,11 +116,11 @@ class UILinksWidgetDirect
if ($sRealClass != '') { if ($sRealClass != '') {
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode); $oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe(); $sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
$aFieldsFlags = array($sExtKeyToMe => OPT_ATT_HIDDEN); $aFieldsFlags = [$sExtKeyToMe => OPT_ATT_HIDDEN];
$oObj = DBObject::MakeDefaultInstance($sRealClass); $oObj = DBObject::MakeDefaultInstance($sRealClass);
$aPrefillParam = array('source_obj' => $oSourceObj); $aPrefillParam = ['source_obj' => $oSourceObj];
$oObj->PrefillForm('creation_from_editinplace', $aPrefillParam); $oObj->PrefillForm('creation_from_editinplace', $aPrefillParam);
$aFormExtraParams = array( $aFormExtraParams = [
'formPrefix' => $this->sInputid, 'formPrefix' => $this->sInputid,
'noRelations' => true, 'noRelations' => true,
'fieldsFlags' => $aFieldsFlags, 'fieldsFlags' => $aFieldsFlags,
@@ -140,25 +133,22 @@ class UILinksWidgetDirect
JS JS
, ,
], ],
); ];
// Remove blob edition from creation form @see N°5863 to allow blob edition in modal context // Remove blob edition from creation form @see N°5863 to allow blob edition in modal context
FormHelper::DisableAttributeBlobInputs($sRealClass, $aFormExtraParams); FormHelper::DisableAttributeBlobInputs($sRealClass, $aFormExtraParams);
if(FormHelper::HasMandatoryAttributeBlobInputs($oObj)){ if (FormHelper::HasMandatoryAttributeBlobInputs($oObj)) {
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE)); $oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE));
} }
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, array(), $aFormExtraParams); cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, [], $aFormExtraParams);
} } else {
else
{
$sClassLabel = MetaModel::GetName($this->sLinkedClass); $sClassLabel = MetaModel::GetName($this->sLinkedClass);
$oPage->add('<p>'.Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel)); $oPage->add('<p>'.Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel));
$oPage->add('<nobr><select name="class">'); $oPage->add('<nobr><select name="class">');
asort($aPossibleClasses); asort($aPossibleClasses);
foreach($aPossibleClasses as $sClassName => $sClassLabel) foreach ($aPossibleClasses as $sClassName => $sClassLabel) {
{
$oPage->add("<option value=\"$sClassName\">$sClassLabel</option>"); $oPage->add("<option value=\"$sClassName\">$sClassLabel</option>");
} }
$oPage->add('</select>'); $oPage->add('</select>');
@@ -178,7 +168,7 @@ JS
* @throws \MissingQueryArgument * @throws \MissingQueryArgument
* @throws \OQLException * @throws \OQLException
*/ */
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array()) public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = [])
{ {
//$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n"); //$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
@@ -199,8 +189,7 @@ JS
$oLinkSetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode); $oLinkSetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$valuesDef = $oLinkSetDef->GetValuesDef(); $valuesDef = $oLinkSetDef->GetValuesDef();
if ($valuesDef === null) if ($valuesDef === null) {
{
$oFilter = new DBObjectSearch($this->sLinkedClass); $oFilter = new DBObjectSearch($this->sLinkedClass);
} else { } else {
if (!$valuesDef instanceof ValueSetObjects) { if (!$valuesDef instanceof ValueSetObjects) {
@@ -218,8 +207,10 @@ JS
$oCurrentObj->PrefillForm('search', $aPrefillFormParam); $oCurrentObj->PrefillForm('search', $aPrefillFormParam);
} }
$oBlock = new DisplayBlock($oFilter, 'search', false); $oBlock = new DisplayBlock($oFilter, 'search', false);
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}", $oPage->AddUiBlock($oBlock->GetDisplay(
array( $oPage,
"SearchFormToAdd_{$this->sInputid}",
[
'result_list_outer_selector' => "SearchResultsToAdd_{$this->sInputid}", 'result_list_outer_selector' => "SearchResultsToAdd_{$this->sInputid}",
'table_id' => "add_{$this->sInputid}", 'table_id' => "add_{$this->sInputid}",
'table_inner_id' => "ResultsToAdd_{$this->sInputid}", 'table_inner_id' => "ResultsToAdd_{$this->sInputid}",
@@ -227,13 +218,14 @@ JS
'cssCount' => "#count_{$this->sInputid}", 'cssCount' => "#count_{$this->sInputid}",
'query_params' => $oFilter->GetInternalParams(), 'query_params' => $oFilter->GetInternalParams(),
'hidden_criteria' => $sHiddenCriteria, 'hidden_criteria' => $sHiddenCriteria,
) ]
)); ));
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm'); $sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
$sCancel = Dict::S('UI:Button:Cancel'); $sCancel = Dict::S('UI:Button:Cancel');
$sAdd = Dict::S('UI:Button:Add'); $sAdd = Dict::S('UI:Button:Add');
$oPage->add(<<<HTML $oPage->add(
<<<HTML
<form id="ObjectsAddForm_{$this->sInputid}"> <form id="ObjectsAddForm_{$this->sInputid}">
<div id="SearchResultsToAdd_{$this->sInputid}"> <div id="SearchResultsToAdd_{$this->sInputid}">
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div> <div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
@@ -256,52 +248,43 @@ HTML
* @throws \CoreException * @throws \CoreException
* @throws \OQLException * @throws \OQLException
*/ */
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null, $aPrefillFormParam = array()) public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = [], $oCurrentObj = null, $aPrefillFormParam = [])
{ {
if ($sRemoteClass == '') if ($sRemoteClass == '') {
{
$sRemoteClass = $this->sLinkedClass; $sRemoteClass = $this->sLinkedClass;
} }
$oLinkSetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode); $oLinkSetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$valuesDef = $oLinkSetDef->GetValuesDef(); $valuesDef = $oLinkSetDef->GetValuesDef();
if ($valuesDef === null) if ($valuesDef === null) {
{
$oFilter = new DBObjectSearch($sRemoteClass); $oFilter = new DBObjectSearch($sRemoteClass);
} } else {
else if (!$valuesDef instanceof ValueSetObjects) {
{
if (!$valuesDef instanceof ValueSetObjects)
{
throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').'); throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').');
} }
$oFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression()); $oFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression());
} }
if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($sRemoteClass, $this->sClass)) if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($sRemoteClass, $this->sClass)) {
{
// Prevent linking to self if the linked object is of the same family // Prevent linking to self if the linked object is of the same family
// and already present in the database // and already present in the database
if (!$oCurrentObj->IsNew()) if (!$oCurrentObj->IsNew()) {
{
$oFilter->AddCondition('id', $oCurrentObj->GetKey(), '!='); $oFilter->AddCondition('id', $oCurrentObj->GetKey(), '!=');
} }
} }
if ($oCurrentObj != null) if ($oCurrentObj != null) {
{
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter); $this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams()); $aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
$oFilter->SetInternalParams($aArgs); $oFilter->SetInternalParams($aArgs);
$aPrefillFormParam['filter'] = $oFilter; $aPrefillFormParam['filter'] = $oFilter;
$oCurrentObj->PrefillForm('search', $aPrefillFormParam); $oCurrentObj->PrefillForm('search', $aPrefillFormParam);
} }
if (count($aAlreadyLinked) > 0) if (count($aAlreadyLinked) > 0) {
{
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN'); $oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
} }
$oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results $oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", ['menu' => false, 'cssCount' => '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid]); // Don't display the 'Actions' menu on the results
} }
/** /**
@@ -311,29 +294,28 @@ HTML
public function DoAddObjects(WebPage $oP, $oFullSetFilter) public function DoAddObjects(WebPage $oP, $oFullSetFilter)
{ {
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter); $aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
foreach($aLinkedObjectIds as $iObjectId) foreach ($aLinkedObjectIds as $iObjectId) {
{
$oLinkObj = MetaModel::GetObject($this->sLinkedClass, $iObjectId); $oLinkObj = MetaModel::GetObject($this->sLinkedClass, $iObjectId);
$oP->add($this->GetObjectRow($oP, $oLinkObj, $oLinkObj->GetKey())); $oP->add($this->GetObjectRow($oP, $oLinkObj, $oLinkObj->GetKey()));
} }
} }
public function GetObjectModificationDlg() public function GetObjectModificationDlg()
{ {
} }
public function GetTableConfig() public function GetTableConfig()
{ {
$aAttribs = array(); $aAttribs = [];
$aAttribs['form::select'] = array( $aAttribs['form::select'] = [
'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->sInputid}:not(:disabled)', this.checked);oWidget".$this->sInputid.".directlinks('instance')._onSelectChange();\" class=\"checkAll\"></input>", 'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->sInputid}:not(:disabled)', this.checked);oWidget".$this->sInputid.".directlinks('instance')._onSelectChange();\" class=\"checkAll\"></input>",
'description' => Dict::S('UI:SelectAllToggle+'), 'description' => Dict::S('UI:SelectAllToggle+'),
); ];
foreach ($this->aZlist as $sLinkedAttCode) { foreach ($this->aZlist as $sLinkedAttCode) {
$oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode); $oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode);
$aAttribs[$sLinkedAttCode] = array('label' => MetaModel::GetLabel($this->sLinkedClass, $sLinkedAttCode), 'description' => $oAttDef->GetOrderByHint()); $aAttribs[$sLinkedAttCode] = ['label' => MetaModel::GetLabel($this->sLinkedClass, $sLinkedAttCode), 'description' => $oAttDef->GetOrderByHint()];
} }
return $aAttribs; return $aAttribs;
@@ -348,13 +330,12 @@ HTML
*/ */
public function GetRow($oPage, $sRealClass, $aValues, $iTempId) public function GetRow($oPage, $sRealClass, $aValues, $iTempId)
{ {
if ($sRealClass == '') if ($sRealClass == '') {
{
$sRealClass = $this->sLinkedClass; $sRealClass = $this->sLinkedClass;
} }
$oLinkObj = new $sRealClass(); $oLinkObj = new $sRealClass();
$oLinkObj->UpdateObjectFromPostedForm($this->sInputid); $oLinkObj->UpdateObjectFromPostedForm($this->sInputid);
return $this->GetObjectRow($oPage, $oLinkObj, $iTempId); return $this->GetObjectRow($oPage, $oLinkObj, $iTempId);
} }
@@ -367,13 +348,12 @@ HTML
protected function GetObjectRow($oPage, $oLinkObj, $iTempId) protected function GetObjectRow($oPage, $oLinkObj, $iTempId)
{ {
$aAttribs = $this->GetTableConfig(); $aAttribs = $this->GetTableConfig();
$aRow = array(); $aRow = [];
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.($iTempId).'"/>'; $aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.($iTempId).'"/>';
foreach($this->aZlist as $sLinkedAttCode) foreach ($this->aZlist as $sLinkedAttCode) {
{
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode); $aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
} }
return $oPage->GetTableRow($aRow, $aAttribs); return $oPage->GetTableRow($aRow, $aAttribs);
} }
/** /**
@@ -386,23 +366,21 @@ HTML
*/ */
public function GetFormRow($oPage, $sRealClass, $aValues, $iTempId) public function GetFormRow($oPage, $sRealClass, $aValues, $iTempId)
{ {
if ($sRealClass == '') if ($sRealClass == '') {
{
$sRealClass = $this->sLinkedClass; $sRealClass = $this->sLinkedClass;
} }
$oLinkObj = new $sRealClass(); $oLinkObj = new $sRealClass();
$oLinkObj->UpdateObjectFromPostedForm($this->sInputid); $oLinkObj->UpdateObjectFromPostedForm($this->sInputid);
$aAttribs = $this->GetTableConfig(); $aAttribs = $this->GetTableConfig();
$aRow = array(); $aRow = [];
$aRow[] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.($iTempId).'"/>'; $aRow[] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.($iTempId).'"/>';
foreach($this->aZlist as $sLinkedAttCode) foreach ($this->aZlist as $sLinkedAttCode) {
{
$aRow[] = $oLinkObj->GetAsHTML($sLinkedAttCode); $aRow[] = $oLinkObj->GetAsHTML($sLinkedAttCode);
} }
return $aRow; return $aRow;
} }
/** /**
* Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context * Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
* @param DBObject $oSourceObj * @param DBObject $oSourceObj
@@ -413,27 +391,23 @@ HTML
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sSrcClass = get_class($oSourceObj); $sSrcClass = get_class($oSourceObj);
$sDestClass = $oSearch->GetClass(); $sDestClass = $oSearch->GetClass();
foreach($oAppContext->GetNames() as $key) foreach ($oAppContext->GetNames() as $key) {
{
// Find the value of the object corresponding to each 'context' parameter // Find the value of the object corresponding to each 'context' parameter
$aCallSpec = array($sSrcClass, 'MapContextParam'); $aCallSpec = [$sSrcClass, 'MapContextParam'];
$sAttCode = ''; $sAttCode = '';
if (is_callable($aCallSpec)) if (is_callable($aCallSpec)) {
{ $sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
} }
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode)) if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode)) {
{
$defaultValue = $oSourceObj->Get($sAttCode); $defaultValue = $oSourceObj->Get($sAttCode);
// Find the attcode for the same 'context' parameter in the destination class // Find the attcode for the same 'context' parameter in the destination class
// and sets its value as the default value for the search condition // and sets its value as the default value for the search condition
$aCallSpec = array($sDestClass, 'MapContextParam'); $aCallSpec = [$sDestClass, 'MapContextParam'];
$sAttCode = ''; $sAttCode = '';
if (is_callable($aCallSpec)) if (is_callable($aCallSpec)) {
{ $sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
} }
if (MetaModel::IsValidAttCode($sDestClass, $sAttCode) && !empty($defaultValue)) { if (MetaModel::IsValidAttCode($sDestClass, $sAttCode) && !empty($defaultValue)) {
@@ -443,7 +417,6 @@ HTML
} }
} }
public function GetClass(): string public function GetClass(): string
{ {
return $this->sClass; return $this->sClass;

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -54,7 +55,7 @@ class UILinksWidget
$this->m_sNameSuffix = $sNameSuffix; $this->m_sNameSuffix = $sNameSuffix;
$this->m_bDuplicatesAllowed = $bDuplicatesAllowed; $this->m_bDuplicatesAllowed = $bDuplicatesAllowed;
$this->m_aEditableFields = array(); $this->m_aEditableFields = [];
/** @var AttributeLinkedSetIndirect $oAttDef */ /** @var AttributeLinkedSetIndirect $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode); $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
@@ -67,34 +68,33 @@ class UILinksWidget
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote); $oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass(); $this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
$this->m_aEditableFields = array(); $this->m_aEditableFields = [];
$this->m_aTableConfig = array(); $this->m_aTableConfig = [];
$this->m_aTableConfig['form::checkbox'] = array( $this->m_aTableConfig['form::checkbox'] = [
'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_sInputId.".OnSelectChange();\">", 'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_sInputId.".OnSelectChange();\">",
'description' => Dict::S('UI:SelectAllToggle+'), 'description' => Dict::S('UI:SelectAllToggle+'),
); ];
$aLnkAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode); $aLnkAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode);
foreach ($aLnkAttDefsToDisplay as $oLnkAttDef) foreach ($aLnkAttDefsToDisplay as $oLnkAttDef) {
{
$sLnkAttCode = $oLnkAttDef->GetCode(); $sLnkAttCode = $oLnkAttDef->GetCode();
$this->m_aEditableFields[] = $sLnkAttCode; $this->m_aEditableFields[] = $sLnkAttCode;
$this->m_aTableConfig[$sLnkAttCode] = array('label' => $oLnkAttDef->GetLabel(), 'description' => $oLnkAttDef->GetDescription()); $this->m_aTableConfig[$sLnkAttCode] = ['label' => $oLnkAttDef->GetLabel(), 'description' => $oLnkAttDef->GetDescription()];
} }
$this->m_aTableConfig['static::key'] = array( $this->m_aTableConfig['static::key'] = [
'label' => MetaModel::GetName($this->m_sRemoteClass), 'label' => MetaModel::GetName($this->m_sRemoteClass),
'description' => MetaModel::GetClassDescription($this->m_sRemoteClass), 'description' => MetaModel::GetClassDescription($this->m_sRemoteClass),
); ];
$this->m_aEditableFields[] = $this->m_sExtKeyToRemote; $this->m_aEditableFields[] = $this->m_sExtKeyToRemote;
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass); $aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef) { foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef) {
$sRemoteAttCode = $oRemoteAttDef->GetCode(); $sRemoteAttCode = $oRemoteAttDef->GetCode();
$this->m_aTableConfig['static::'.$sRemoteAttCode] = array( $this->m_aTableConfig['static::'.$sRemoteAttCode] = [
'label' => $oRemoteAttDef->GetLabel(), 'label' => $oRemoteAttDef->GetLabel(),
'description' => $oRemoteAttDef->GetDescription(), 'description' => $oRemoteAttDef->GetDescription(),
); ];
} }
} }
@@ -105,7 +105,6 @@ class UILinksWidget
return ($bSafe) ? utils::GetSafeId($sFieldId) : $sFieldId; return ($bSafe) ? utils::GetSafeId($sFieldId) : $sFieldId;
} }
/** /**
* Display the table with the form for editing all the links at once * Display the table with the form for editing all the links at once
* *
@@ -119,7 +118,6 @@ class UILinksWidget
return DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aData); return DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aData);
} }
/** /**
* Get the HTML fragment corresponding to the linkset editing widget * Get the HTML fragment corresponding to the linkset editing widget
* *
@@ -157,7 +155,7 @@ class UILinksWidget
* @throws DictExceptionMissingString * @throws DictExceptionMissingString
* @throws Exception * @throws Exception
*/ */
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array()) public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = [], $aPrefillFormParam = [])
{ {
$oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass); $oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass);
if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) { if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) {
@@ -183,7 +181,9 @@ class UILinksWidget
$sLinkedSetId = $oBlock->oUILinksWidget->GetLinkedSetId(); $sLinkedSetId = $oBlock->oUILinksWidget->GetLinkedSetId();
$oDisplayBlock = new DisplayBlock($oFilter, 'search', false); $oDisplayBlock = new DisplayBlock($oFilter, 'search', false);
$oBlock->AddSubBlock($oDisplayBlock->GetDisplay($oPage, "SearchFormToAdd_{$sLinkedSetId}", $oBlock->AddSubBlock($oDisplayBlock->GetDisplay(
$oPage,
"SearchFormToAdd_{$sLinkedSetId}",
[ [
'menu' => false, 'menu' => false,
'result_list_outer_selector' => "SearchResultsToAdd_{$sLinkedSetId}", 'result_list_outer_selector' => "SearchResultsToAdd_{$sLinkedSetId}",
@@ -195,7 +195,8 @@ class UILinksWidget
'query_params' => $oFilter->GetInternalParams(), 'query_params' => $oFilter->GetInternalParams(),
'hidden_criteria' => $sAlreadyLinkedExpression, 'hidden_criteria' => $sAlreadyLinkedExpression,
'submit_on_load' => false, 'submit_on_load' => false,
])); ]
));
$oBlock->AddForm(); $oBlock->AddForm();
} }
@@ -212,25 +213,21 @@ class UILinksWidget
* @throws \CoreException * @throws \CoreException
* @throws \Exception * @throws \Exception
*/ */
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinkedIds = array(), $oCurrentObj = null) public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinkedIds = [], $oCurrentObj = null)
{ {
if ($sRemoteClass != '') if ($sRemoteClass != '') {
{
// assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass)); // assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass));
$oFilter = new DBObjectSearch($sRemoteClass); $oFilter = new DBObjectSearch($sRemoteClass);
} } else {
else
{
// No remote class specified use the one defined in the linkedset // No remote class specified use the one defined in the linkedset
$oFilter = new DBObjectSearch($this->m_sRemoteClass); $oFilter = new DBObjectSearch($this->m_sRemoteClass);
} }
if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) {
{
$oFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN'); $oFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN');
} }
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter); $this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
$oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode)); // Don't display the 'Actions' menu on the results $oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", ['menu' => false, 'cssCount' => '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode]); // Don't display the 'Actions' menu on the results
} }
/** /**
@@ -251,7 +248,7 @@ class UILinksWidget
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false); $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
if (is_object($oLinkedObj)) { if (is_object($oLinkedObj)) {
$oBlock = new BlockIndirectLinkSetEditTable($this); $oBlock = new BlockIndirectLinkSetEditTable($this);
$aRow = $oBlock->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids $aRow = $oBlock->GetFormRow($oP, $oLinkedObj, $iObjectId, [], $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId); $oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId);
$oP->AddUiBlock($oRow); $oP->AddUiBlock($oRow);
$iAdditionId++; $iAdditionId++;
@@ -280,7 +277,7 @@ class UILinksWidget
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false); $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
if (is_object($oLinkedObj)) { if (is_object($oLinkedObj)) {
$oBlock = new BlockIndirectLinkSetEditTable($this); $oBlock = new BlockIndirectLinkSetEditTable($this);
$aRow = $oBlock->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId, false /* Default value */, $bAllowRemoteExtKeyEdit); // Not yet created link get negative Ids $aRow = $oBlock->GetFormRow($oP, $oLinkedObj, $iObjectId, [], $oCurrentObj, $iAdditionId, false /* Default value */, $bAllowRemoteExtKeyEdit); // Not yet created link get negative Ids
$aData = []; $aData = [];
foreach ($aRow as $item) { foreach ($aRow as $item) {
$aData[] = $item; $aData[] = $item;
@@ -307,37 +304,30 @@ class UILinksWidget
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$sSrcClass = get_class($oSourceObj); $sSrcClass = get_class($oSourceObj);
$sDestClass = $oSearch->GetClass(); $sDestClass = $oSearch->GetClass();
foreach($oAppContext->GetNames() as $key) foreach ($oAppContext->GetNames() as $key) {
{
// Find the value of the object corresponding to each 'context' parameter // Find the value of the object corresponding to each 'context' parameter
$aCallSpec = array($sSrcClass, 'MapContextParam'); $aCallSpec = [$sSrcClass, 'MapContextParam'];
$sAttCode = ''; $sAttCode = '';
if (is_callable($aCallSpec)) if (is_callable($aCallSpec)) {
{ $sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
} }
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode)) if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode)) {
{
$defaultValue = $oSourceObj->Get($sAttCode); $defaultValue = $oSourceObj->Get($sAttCode);
// Find the attcode for the same 'context' parameter in the destination class // Find the attcode for the same 'context' parameter in the destination class
// and sets its value as the default value for the search condition // and sets its value as the default value for the search condition
$aCallSpec = array($sDestClass, 'MapContextParam'); $aCallSpec = [$sDestClass, 'MapContextParam'];
$sAttCode = ''; $sAttCode = '';
if (is_callable($aCallSpec)) if (is_callable($aCallSpec)) {
{ $sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
} }
if (MetaModel::IsValidAttCode($sDestClass, $sAttCode) && !empty($defaultValue)) if (MetaModel::IsValidAttCode($sDestClass, $sAttCode) && !empty($defaultValue)) {
{
// Add Hierarchical condition if hierarchical key // Add Hierarchical condition if hierarchical key
$oAttDef = MetaModel::GetAttributeDef($sDestClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sDestClass, $sAttCode);
if (isset($oAttDef) && ($oAttDef->IsExternalKey())) if (isset($oAttDef) && ($oAttDef->IsExternalKey())) {
{ try {
try
{
/** @var AttributeExternalKey $oAttDef */ /** @var AttributeExternalKey $oAttDef */
$sTargetClass = $oAttDef->GetTargetClass(); $sTargetClass = $oAttDef->GetTargetClass();
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass); $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass);
@@ -348,8 +338,7 @@ class UILinksWidget
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); $oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode); $oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
} }
} } catch (Exception $e) {
catch (Exception $e) {
} }
} else { } else {
$oSearch->AddCondition($sAttCode, $defaultValue); $oSearch->AddCondition($sAttCode, $defaultValue);

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -28,13 +29,13 @@ use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'/application/displayblock.class.inc.php'); require_once(APPROOT.'/application/displayblock.class.inc.php');
class UIPasswordWidget class UIPasswordWidget
{ {
protected static $iWidgetIndex = 0; protected static $iWidgetIndex = 0;
protected $sAttCode; protected $sAttCode;
protected $sNameSuffix; protected $sNameSuffix;
protected $iId; protected $iId;
public function __construct($sAttCode, $iInputId, $sNameSuffix = '') public function __construct($sAttCode, $iInputId, $sNameSuffix = '')
{ {
self::$iWidgetIndex++; self::$iWidgetIndex++;
@@ -42,14 +43,14 @@ class UIPasswordWidget
$this->sNameSuffix = $sNameSuffix; $this->sNameSuffix = $sNameSuffix;
$this->iId = $iInputId; $this->iId = $iInputId;
} }
/** /**
* Get the HTML fragment corresponding to the linkset editing widget * Get the HTML fragment corresponding to the linkset editing widget
* @param WebPage $oP The web page used for all the output * @param WebPage $oP The web page used for all the output
* @param Hash $aArgs Extra context arguments * @param Hash $aArgs Extra context arguments
* @return string The HTML fragment to be inserted into the page * @return string The HTML fragment to be inserted into the page
*/ */
public function Display(WebPage $oPage, $aArgs = array()) public function Display(WebPage $oPage, $aArgs = [])
{ {
$oPage->add_dict_entry('UI:Component:Input:Password:DoesNotMatch'); $oPage->add_dict_entry('UI:Component:Input:Password:DoesNotMatch');
@@ -94,4 +95,3 @@ class UIPasswordWidget
return $sHtmlValue; return $sHtmlValue;
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* *
* Copyright (C) 2010-2024 Combodo SAS * Copyright (C) 2010-2024 Combodo SAS
@@ -20,7 +21,6 @@
* *
*/ */
use Combodo\iTop\Application\WebPage\WebPage; use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'/application/displayblock.class.inc.php'); require_once(APPROOT.'/application/displayblock.class.inc.php');
@@ -46,8 +46,10 @@ class UISearchFormForeignKeys
$oFilter = new DBObjectSearch($this->m_sRemoteClass); $oFilter = new DBObjectSearch($this->m_sRemoteClass);
$oBlock = new DisplayBlock($oFilter, 'search', false); $oBlock = new DisplayBlock($oFilter, 'search', false);
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_iInputId}", $oPage->AddUiBlock($oBlock->GetDisplay(
array( $oPage,
"SearchFormToAdd_{$this->m_iInputId}",
[
'menu' => false, 'menu' => false,
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_iInputId}", 'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_iInputId}",
'table_id' => "add_{$this->m_iInputId}", 'table_id' => "add_{$this->m_iInputId}",
@@ -55,12 +57,14 @@ class UISearchFormForeignKeys
'selection_mode' => true, 'selection_mode' => true,
'cssCount' => "#count_{$this->m_iInputId}", 'cssCount' => "#count_{$this->m_iInputId}",
'query_params' => $oFilter->GetInternalParams(), 'query_params' => $oFilter->GetInternalParams(),
))); ]
));
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm'); $sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
$sCancel = Dict::S('UI:Button:Cancel'); $sCancel = Dict::S('UI:Button:Cancel');
$sAdd = Dict::S('UI:Button:Add'); $sAdd = Dict::S('UI:Button:Add');
$oPage->add(<<<HTML $oPage->add(
<<<HTML
<form id="ObjectsAddForm_{$this->m_iInputId}"> <form id="ObjectsAddForm_{$this->m_iInputId}">
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;"> <div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;">
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div> <div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
@@ -101,20 +105,17 @@ $('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd); $('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
$('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes); $('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
JS JS
); );
} }
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter) public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
{ {
try try {
{
$aLinkedObjects = utils::ReadMultipleSelectionWithFriendlyname($oFullSetFilter); $aLinkedObjects = utils::ReadMultipleSelectionWithFriendlyname($oFullSetFilter);
$oPage->add(json_encode($aLinkedObjects)); $oPage->add(json_encode($aLinkedObjects));
} } catch (CoreException $e) {
catch (CoreException $e)
{
http_response_code(500); http_response_code(500);
$oPage->add(json_encode(array('error' => $e->GetMessage()))); $oPage->add(json_encode(['error' => $e->GetMessage()]));
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString()); IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
} }
} }
@@ -129,20 +130,20 @@ JS
*/ */
public function ListResultsSearchForeignKeys(WebPage $oP, $sRemoteClass = '') public function ListResultsSearchForeignKeys(WebPage $oP, $sRemoteClass = '')
{ {
if ($sRemoteClass != '') if ($sRemoteClass != '') {
{
// assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass)); // assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass));
$oFilter = new DBObjectSearch($sRemoteClass); $oFilter = new DBObjectSearch($sRemoteClass);
} } else {
else
{
// No remote class specified use the one defined in the linkedset // No remote class specified use the one defined in the linkedset
$oFilter = new DBObjectSearch($this->m_sRemoteClass); $oFilter = new DBObjectSearch($this->m_sRemoteClass);
} }
$oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oP, "ResultsToAdd_{$this->m_iInputId}", $oBlock->Display(
array('menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}")); $oP,
"ResultsToAdd_{$this->m_iInputId}",
['menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}"]
);
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -17,7 +18,6 @@
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\WebPage\iTopWebPage; use Combodo\iTop\Application\WebPage\iTopWebPage;
/** /**
* Class UIWizard * Class UIWizard
* *
@@ -31,74 +31,73 @@ class UIWizard
protected $m_sClass; protected $m_sClass;
protected $m_sTargetState; protected $m_sTargetState;
protected $m_aWizardSteps; protected $m_aWizardSteps;
public function __construct($oPage, $sClass, $sTargetState = '') public function __construct($oPage, $sClass, $sTargetState = '')
{ {
$this->m_oPage = $oPage; $this->m_oPage = $oPage;
$this->m_sClass = $sClass; $this->m_sClass = $sClass;
if (empty($sTargetState)) if (empty($sTargetState)) {
{
$sTargetState = MetaModel::GetDefaultState($sClass); $sTargetState = MetaModel::GetDefaultState($sClass);
} }
$this->m_sTargetState = $sTargetState; $this->m_sTargetState = $sTargetState;
$this->m_aWizardSteps = $this->ComputeWizardStructure(); $this->m_aWizardSteps = $this->ComputeWizardStructure();
} }
public function GetObjectClass() { return $this->m_sClass; } public function GetObjectClass()
public function GetTargetState() { return $this->m_sTargetState; } {
public function GetWizardStructure() { return $this->m_aWizardSteps; } return $this->m_sClass;
}
public function GetTargetState()
{
return $this->m_sTargetState;
}
public function GetWizardStructure()
{
return $this->m_aWizardSteps;
}
/** /**
* Displays one step of the wizard * Displays one step of the wizard
*/ */
public function DisplayWizardStep($aStep, $iStepIndex, &$iMaxInputId, &$aFieldsMap, $bFinishEnabled = false, $aArgs = array()) public function DisplayWizardStep($aStep, $iStepIndex, &$iMaxInputId, &$aFieldsMap, $bFinishEnabled = false, $aArgs = [])
{ {
if ($iStepIndex == 1) // one big form that contains everything, to make sure that the uploaded files are posted too if ($iStepIndex == 1) { // one big form that contains everything, to make sure that the uploaded files are posted too
{
$this->m_oPage->add("<form method=\"post\" enctype=\"multipart/form-data\" action=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php\">\n"); $this->m_oPage->add("<form method=\"post\" enctype=\"multipart/form-data\" action=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php\">\n");
} }
$this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n"); $this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n");
$this->m_oPage->add("<a name=\"step$iStepIndex\" />\n"); $this->m_oPage->add("<a name=\"step$iStepIndex\" />\n");
$aStates = MetaModel::EnumStates($this->m_sClass); $aStates = MetaModel::EnumStates($this->m_sClass);
$aDetails = array(); $aDetails = [];
$sJSHandlerCode = ''; // Javascript code to be executed each time this step of the wizard is entered $sJSHandlerCode = ''; // Javascript code to be executed each time this step of the wizard is entered
foreach($aStep as $sAttCode) foreach ($aStep as $sAttCode) {
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oAttDef->IsWritable()) if ($oAttDef->IsWritable()) {
{
$sAttLabel = $oAttDef->GetLabel(); $sAttLabel = $oAttDef->GetLabel();
$iOptions = isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode]) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0; $iOptions = isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode]) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes(); $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) {
{ $aFields[$sAttCode] = [];
$aFields[$sAttCode] = array(); foreach ($aPrerequisites as $sCode) {
foreach($aPrerequisites as $sCode)
{
$aFields[$sAttCode][$sCode] = ''; $aFields[$sAttCode][$sCode] = '';
} }
} }
if (count($aPrerequisites) > 0) if (count($aPrerequisites) > 0) {
{
$aOptions[] = 'Prerequisites: '.implode(', ', $aPrerequisites); $aOptions[] = 'Prerequisites: '.implode(', ', $aPrerequisites);
} }
$sFieldFlag = (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) || (!$oAttDef->IsNullAllowed()) )? ' <span class="hilite">*</span>' : ''; $sFieldFlag = (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) || (!$oAttDef->IsNullAllowed())) ? ' <span class="hilite">*</span>' : '';
$oDefaultValuesSet = $oAttDef->GetDefaultValue(/* $oObject->ToArgs() */); // @@@ TO DO: get the object's current value if the object exists $oDefaultValuesSet = $oAttDef->GetDefaultValue(/* $oObject->ToArgs() */); // @@@ TO DO: get the object's current value if the object exists
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId", '', $iOptions, $aArgs); $sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId", '', $iOptions, $aArgs);
$aFieldsMap["att_$iMaxInputId"] = $sAttCode; $aFieldsMap["att_$iMaxInputId"] = $sAttCode;
$aDetails[] = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().$sFieldFlag.'</span>', 'value' => "<span id=\"field_att_$iMaxInputId\">$sHTMLValue</span>"); $aDetails[] = ['label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().$sFieldFlag.'</span>', 'value' => "<span id=\"field_att_$iMaxInputId\">$sHTMLValue</span>"];
if ($oAttDef->GetValuesDef() != null) if ($oAttDef->GetValuesDef() != null) {
{
$sJSHandlerCode .= "\toWizardHelper.RequestAllowedValues('$sAttCode');\n"; $sJSHandlerCode .= "\toWizardHelper.RequestAllowedValues('$sAttCode');\n";
} }
if ($oAttDef->GetDefaultValue() != null) if ($oAttDef->GetDefaultValue() != null) {
{
$sJSHandlerCode .= "\toWizardHelper.RequestDefaultValue('$sAttCode');\n"; $sJSHandlerCode .= "\toWizardHelper.RequestDefaultValue('$sAttCode');\n";
} }
if ($oAttDef->IsLinkSet()) if ($oAttDef->IsLinkSet()) {
{
$sJSHandlerCode .= "\toLinkWidgetatt_$iMaxInputId.Init();"; $sJSHandlerCode .= "\toLinkWidgetatt_$iMaxInputId.Init();";
} }
$iMaxInputId++; $iMaxInputId++;
@@ -126,11 +125,11 @@ $sJSHandlerCode
} }
"); ");
$this->m_oPage->add("</div>\n\n"); $this->m_oPage->add("</div>\n\n");
} }
/** /**
* Display the final step of the wizard: a confirmation screen * Display the final step of the wizard: a confirmation screen
*/ */
public function DisplayFinalStep($iStepIndex, $aFieldsMap) public function DisplayFinalStep($iStepIndex, $aFieldsMap)
{ {
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
@@ -141,136 +140,116 @@ $sJSHandlerCode
$this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\" />\n"); $this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\" />\n");
$this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\" />\n"); $this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\" />\n");
$sScript = "function OnEnterStep$iStepIndex() {\n"; $sScript = "function OnEnterStep$iStepIndex() {\n";
foreach($aFieldsMap as $iInputId => $sAttCode) foreach ($aFieldsMap as $iInputId => $sAttCode) {
{ $sScript .= "\toWizardHelper.UpdateCurrentValue('$sAttCode');\n";
$sScript .= "\toWizardHelper.UpdateCurrentValue('$sAttCode');\n";
} }
$sScript .= "\toWizardHelper.Preview('object_preview');\n"; $sScript .= "\toWizardHelper.Preview('object_preview');\n";
$sScript .= "\t$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n"; $sScript .= "\t$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n";
$sScript .= "}\n"; $sScript .= "}\n";
$this->m_oPage->add_script($sScript); $this->m_oPage->add_script($sScript);
$this->m_oPage->add("<div id=\"object_preview\">\n"); $this->m_oPage->add("<div id=\"object_preview\">\n");
$this->m_oPage->add("</div>\n"); $this->m_oPage->add("</div>\n");
$this->m_oPage->add($oAppContext->GetForForm()); $this->m_oPage->add($oAppContext->GetForForm());
$this->m_oPage->add("<input type=\"button\" value=\"".Dict::S('UI:Button:Back')."\" onClick=\"GoToStep($iStepIndex, $iStepIndex - 1)\" />"); $this->m_oPage->add("<input type=\"button\" value=\"".Dict::S('UI:Button:Back')."\" onClick=\"GoToStep($iStepIndex, $iStepIndex - 1)\" />");
$this->m_oPage->add("<input type=\"submit\" value=\"Create ".MetaModel::GetName($this->m_sClass)."\" />\n"); $this->m_oPage->add("<input type=\"submit\" value=\"Create ".MetaModel::GetName($this->m_sClass)."\" />\n");
$this->m_oPage->add("</div>\n"); $this->m_oPage->add("</div>\n");
$this->m_oPage->add("</form>\n"); $this->m_oPage->add("</form>\n");
} }
/** /**
* Compute the order of the fields & pages in the wizard * Compute the order of the fields & pages in the wizard
* @param $oPage iTopWebPage The current page (used to display error messages) * @param $oPage iTopWebPage The current page (used to display error messages)
* @param $sClass string Name of the class * @param $sClass string Name of the class
* @param $sStateCode string Code of the target state of the object * @param $sStateCode string Code of the target state of the object
* @return hash Two dimensional array: each element represents the list of fields for a given page * @return hash Two dimensional array: each element represents the list of fields for a given page
*/ */
protected function ComputeWizardStructure() protected function ComputeWizardStructure()
{ {
$aWizardSteps = array( 'mandatory' => array(), 'optional' => array()); $aWizardSteps = [ 'mandatory' => [], 'optional' => []];
$aFieldsDone = array(); // Store all the fields that are already covered by a previous step of the wizard $aFieldsDone = []; // Store all the fields that are already covered by a previous step of the wizard
$aStates = MetaModel::EnumStates($this->m_sClass); $aStates = MetaModel::EnumStates($this->m_sClass);
$sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass); $sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
$aMandatoryAttributes = array();
// Some attributes are always mandatory independently of the state machine (if any)
foreach(MetaModel::GetAttributesList($this->m_sClass) as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() &&
$oAttDef->IsWritable() && ($sAttCode != $sStateAttCode) )
{
$aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY;
}
}
// Now check the attributes that are mandatory in the specified state $aMandatoryAttributes = [];
if ( (!empty($this->m_sTargetState)) && (count($aStates[$this->m_sTargetState]['attribute_list']) > 0) ) // Some attributes are always mandatory independently of the state machine (if any)
{ foreach (MetaModel::GetAttributesList($this->m_sClass) as $sAttCode) {
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() &&
$oAttDef->IsWritable() && ($sAttCode != $sStateAttCode)) {
$aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY;
}
}
// Now check the attributes that are mandatory in the specified state
if ((!empty($this->m_sTargetState)) && (count($aStates[$this->m_sTargetState]['attribute_list']) > 0)) {
// Check all the fields that *must* be included in the wizard for this // Check all the fields that *must* be included in the wizard for this
// particular target state // particular target state
$aFields = array(); $aFields = [];
foreach($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions) foreach ($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions) {
{ if ((isset($aMandatoryAttributes[$sAttCode])) &&
if ( (isset($aMandatoryAttributes[$sAttCode])) && ($aMandatoryAttributes[$sAttCode] & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT))) {
($aMandatoryAttributes[$sAttCode] & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) )
{
$aMandatoryAttributes[$sAttCode] |= $iOptions; $aMandatoryAttributes[$sAttCode] |= $iOptions;
} } else {
else
{
$aMandatoryAttributes[$sAttCode] = $iOptions; $aMandatoryAttributes[$sAttCode] = $iOptions;
} }
} }
} }
// Check all the fields that *must* be included in the wizard // Check all the fields that *must* be included in the wizard
// i.e. all mandatory, must-change or must-prompt fields that are // i.e. all mandatory, must-change or must-prompt fields that are
// not also read-only or hidden. // not also read-only or hidden.
// Some fields may be required (null not allowed) from the database // Some fields may be required (null not allowed) from the database
// perspective, but hidden or read-only from the user interface perspective // perspective, but hidden or read-only from the user interface perspective
$aFields = array(); $aFields = [];
foreach($aMandatoryAttributes as $sAttCode => $iOptions) foreach ($aMandatoryAttributes as $sAttCode => $iOptions) {
{ if (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) &&
if ( ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) && !($iOptions & (OPT_ATT_READONLY | OPT_ATT_HIDDEN))) {
!($iOptions & (OPT_ATT_READONLY | OPT_ATT_HIDDEN)) )
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes(); $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
$aFields[$sAttCode] = array(); $aFields[$sAttCode] = [];
foreach($aPrerequisites as $sCode) foreach ($aPrerequisites as $sCode) {
{
$aFields[$sAttCode][$sCode] = ''; $aFields[$sAttCode][$sCode] = '';
} }
} }
} }
// Now use the dependencies between the fields to order them // Now use the dependencies between the fields to order them
// Start from the order of the 'details' // Start from the order of the 'details'
$aList = MetaModel::FlattenZlist(MetaModel::GetZListItems($this->m_sClass, 'details')); $aList = MetaModel::FlattenZlist(MetaModel::GetZListItems($this->m_sClass, 'details'));
$index = 0; $index = 0;
$aOrder = array(); $aOrder = [];
foreach($aFields as $sAttCode => $void) foreach ($aFields as $sAttCode => $void) {
{ $aOrder[$sAttCode] = 999; // At the end of the list...
$aOrder[$sAttCode] = 999; // At the end of the list...
} }
foreach($aList as $sAttCode) foreach ($aList as $sAttCode) {
{ if (array_key_exists($sAttCode, $aFields)) {
if (array_key_exists($sAttCode, $aFields))
{
$aOrder[$sAttCode] = $index; $aOrder[$sAttCode] = $index;
} }
$index++; $index++;
} }
foreach($aFields as $sAttCode => $aDependencies) foreach ($aFields as $sAttCode => $aDependencies) {
{
// All fields with no remaining dependencies can be entered at this // All fields with no remaining dependencies can be entered at this
// step of the wizard // step of the wizard
if (count($aDependencies) > 0) if (count($aDependencies) > 0) {
{
$iMaxPos = 0; $iMaxPos = 0;
// Remove this field from the dependencies of the other fields // Remove this field from the dependencies of the other fields
foreach($aDependencies as $sDependentAttCode => $void) foreach ($aDependencies as $sDependentAttCode => $void) {
{
// position the current field after the ones it depends on // position the current field after the ones it depends on
$iMaxPos = max($iMaxPos, 1+$aOrder[$sDependentAttCode]); $iMaxPos = max($iMaxPos, 1 + $aOrder[$sDependentAttCode]);
} }
} }
} }
asort($aOrder); asort($aOrder);
$aCurrentStep = array(); $aCurrentStep = [];
foreach($aOrder as $sAttCode => $rank) foreach ($aOrder as $sAttCode => $rank) {
{
$aCurrentStep[] = $sAttCode; $aCurrentStep[] = $sAttCode;
$aFieldsDone[$sAttCode] = ''; $aFieldsDone[$sAttCode] = '';
} }
$aWizardSteps['mandatory'][] = $aCurrentStep; $aWizardSteps['mandatory'][] = $aCurrentStep;
// Now computes the steps to fill the optional fields // Now computes the steps to fill the optional fields
$aFields = array(); // reset $aFields = []; // reset
foreach(MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode=>$oAttDef) foreach (MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode => $oAttDef) {
{
$iOptions = (isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode])) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0; $iOptions = (isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode])) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
if (($sStateAttCode != $sAttCode) && if (($sStateAttCode != $sAttCode) &&
(!$oAttDef->IsExternalField()) && (!$oAttDef->IsExternalField()) &&
@@ -282,7 +261,7 @@ $sJSHandlerCode
// are removed from the 'optional' part of the wizard // are removed from the 'optional' part of the wizard
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes(); $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
$aFields[$sAttCode] = array(); $aFields[$sAttCode] = [];
foreach ($aPrerequisites as $sCode) { foreach ($aPrerequisites as $sCode) {
if (!isset($aFieldsDone[$sCode])) { if (!isset($aFieldsDone[$sCode])) {
// retain only the dependencies that were not covered // retain only the dependencies that were not covered
@@ -293,28 +272,23 @@ $sJSHandlerCode
} }
} }
// Now use the dependencies between the fields to order them // Now use the dependencies between the fields to order them
while(count($aFields) > 0) while (count($aFields) > 0) {
{ $aCurrentStep = [];
$aCurrentStep = array(); foreach ($aFields as $sAttCode => $aDependencies) {
foreach($aFields as $sAttCode => $aDependencies)
{
// All fields with no remaining dependencies can be entered at this // All fields with no remaining dependencies can be entered at this
// step of the wizard // step of the wizard
if (count($aDependencies) == 0) if (count($aDependencies) == 0) {
{
$aCurrentStep[] = $sAttCode; $aCurrentStep[] = $sAttCode;
$aFieldsDone[$sAttCode] = ''; $aFieldsDone[$sAttCode] = '';
unset($aFields[$sAttCode]); unset($aFields[$sAttCode]);
// Remove this field from the dependencies of the other fields // Remove this field from the dependencies of the other fields
foreach($aFields as $sUpdatedCode => $aDummy) foreach ($aFields as $sUpdatedCode => $aDummy) {
{
// remove the dependency // remove the dependency
unset($aFields[$sUpdatedCode][$sAttCode]); unset($aFields[$sUpdatedCode][$sAttCode]);
} }
} }
} }
if (count($aCurrentStep) == 0) if (count($aCurrentStep) == 0) {
{
// This step of the wizard would contain NO field ! // This step of the wizard would contain NO field !
$this->m_oPage->add(Dict::S('UI:Error:WizardCircularReferenceInDependencies')); $this->m_oPage->add(Dict::S('UI:Error:WizardCircularReferenceInDependencies'));
print_r($aFields); print_r($aFields);
@@ -323,7 +297,6 @@ $sJSHandlerCode
$aWizardSteps['optional'][] = $aCurrentStep; $aWizardSteps['optional'][] = $aCurrentStep;
} }
return $aWizardSteps; return $aWizardSteps;
} }
} }
?>

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -31,40 +32,39 @@ class UserDashboard extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "gui", "category" => "gui",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => array('user_id', 'menu_code'), "name_attcode" => ['user_id', 'menu_code'],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_app_dashboards", "db_table" => "priv_app_dashboards",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("menu_code", array("allowed_values"=>null, "sql"=>"menu_code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("contents", array("allowed_values"=>null, "sql"=>"contents", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_SetZListItems('default_search', array ( MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", ["targetclass" => "User", "allowed_values" => null, "sql" => "user_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("menu_code", ["allowed_values" => null, "sql" => "menu_code", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("contents", ["allowed_values" => null, "sql" => "contents", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_SetZListItems('default_search', [
0 => 'user_id', 0 => 'user_id',
1 => 'menu_code', 1 => 'menu_code',
)); ]);
MetaModel::Init_SetZListItems('list', array ( MetaModel::Init_SetZListItems('list', [
0 => 'user_id', 0 => 'user_id',
1 => 'menu_code', 1 => 'menu_code',
)); ]);
} }
/** /**
* Overloading this function here to secure a fix done right before the release * Overloading this function here to secure a fix done right before the release
* The real fix should be to implement this verb in DBObject * The real fix should be to implement this verb in DBObject
*/ */
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null) public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
{ {
$this->DBDelete($oDeletionPlan); $this->DBDelete($oDeletionPlan);
} }
} }
?>

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -227,13 +228,12 @@ class appUserPreferences extends DBObject
// No prefs (yet) for this user, create the object // No prefs (yet) for this user, create the object
$oObj = new appUserPreferences(); $oObj = new appUserPreferences();
$oObj->Set('userid', $sUserId); $oObj->Set('userid', $sUserId);
$oObj->Set('preferences', array()); // Default preferences: an empty array $oObj->Set('preferences', []); // Default preferences: an empty array
try { try {
utils::PushArchiveMode(false); utils::PushArchiveMode(false);
$oObj->DBInsert(); $oObj->DBInsert();
utils::PopArchiveMode(); utils::PopArchiveMode();
} } catch (Exception $e) {
catch (Exception $e) {
// Ignore errors // Ignore errors
} }
} }
@@ -245,25 +245,25 @@ class appUserPreferences extends DBObject
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "gui", "category" => "gui",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "login", "name_attcode" => "login",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array("userid","login"), "reconc_keys" => ["userid","login"],
"db_table" => "priv_app_preferences", "db_table" => "priv_app_preferences",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributePropertySet("preferences", array("allowed_values"=>null, "sql"=>"preferences", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributePropertySet("preferences", ["allowed_values" => null, "sql" => "preferences", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("org_id", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "org_id"))); MetaModel::Init_AddAttribute(new AttributeExternalField("org_id", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "org_id"]));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"))); MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
MetaModel::Init_SetZListItems('list', array('org_id','preferences')); MetaModel::Init_SetZListItems('list', ['org_id','preferences']);
MetaModel::Init_SetZListItems('default_search', array('userid','login','org_id')); MetaModel::Init_SetZListItems('default_search', ['userid','login','org_id']);
} }
/** /**

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader');

View File

@@ -1,9 +1,10 @@
<?php <?php
// Copyright (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
@@ -16,7 +17,6 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/> // along with iTop. If not, see <http://www.gnu.org/licenses/>
/** /**
* Class WizardHelper * Class WizardHelper
* *
@@ -31,7 +31,7 @@ require_once(APPROOT.'/application/uiwizard.class.inc.php');
class WizardHelper class WizardHelper
{ {
protected $m_aData; protected $m_aData;
public function __construct() public function __construct()
{ {
} }
@@ -39,26 +39,20 @@ class WizardHelper
* Constructs the PHP target object from the parameters sent to the web page by the wizard * Constructs the PHP target object from the parameters sent to the web page by the wizard
* @param boolean $bReadUploadedFiles True to also read any uploaded file (for blob/document fields) * @param boolean $bReadUploadedFiles True to also read any uploaded file (for blob/document fields)
* @return object * @return object
*/ */
public function GetTargetObject($bReadUploadedFiles = false) 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']); $oObj = MetaModel::GetObject($this->m_aData['m_sClass'], $this->m_aData['m_oCurrentValues']['id']);
} } else {
else
{
$oObj = MetaModel::NewObject($this->m_aData['m_sClass']); $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 // Because this is stored in a Javascript array, unused indexes
// are filled with null values and unused keys (stored as strings) contain $$NULL$$ // 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); $oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if (($oAttDef->IsLinkSet()) && ($value != '') ) if (($oAttDef->IsLinkSet()) && ($value != '')) {
{
// special handling for lists // special handling for lists
// assumes this is handled as an array of objects // assumes this is handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...] // 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 // Check what are the meaningful attributes
$aFields = $this->GetLinkedWizardStructure($oAttDef); $aFields = $this->GetLinkedWizardStructure($oAttDef);
$sLinkedClass = $oAttDef->GetLinkedClass(); $sLinkedClass = $oAttDef->GetLinkedClass();
$aLinkedObjectsArray = array(); $aLinkedObjectsArray = [];
if (!is_array($aData)) { if (!is_array($aData)) {
echo("aData: '$aData' (value: '$value')\n"); echo("aData: '$aData' (value: '$value')\n");
} }
foreach ($aData as $aLinkedObject) foreach ($aData as $aLinkedObject) {
{
$oLinkedObj = MetaModel::NewObject($sLinkedClass); $oLinkedObj = MetaModel::NewObject($sLinkedClass);
foreach($aFields as $sLinkedAttCode) foreach ($aFields as $sLinkedAttCode) {
{ if (isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null)) {
if ( isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null) )
{
$sLinkedAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLinkedAttCode); $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 // For external keys: load the target object so that external fields
// get filled too // get filled too
$oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]); $oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]);
$oLinkedObj->Set($sLinkedAttCode, $oTargetObj); $oLinkedObj->Set($sLinkedAttCode, $oTargetObj);
} } elseif ($sLinkedAttDef instanceof AttributeDateTime) {
elseif($sLinkedAttDef instanceof AttributeDateTime) $sDateClass = get_class($sLinkedAttDef);
{ $sDate = $aLinkedObject[$sLinkedAttCode];
$sDateClass = get_class($sLinkedAttDef); if ($sDate !== null && $sDate !== '') {
$sDate = $aLinkedObject[$sLinkedAttCode]; $oDateTimeFormat = $sDateClass::GetFormat();
if($sDate !== null && $sDate !== '') $oDate = $oDateTimeFormat->Parse($sDate);
{ if ($sDateClass == "AttributeDate") {
$oDateTimeFormat = $sDateClass::GetFormat(); $sDate = $oDate->format('Y-m-d');
$oDate = $oDateTimeFormat->Parse($sDate); } else {
if ($sDateClass == "AttributeDate") $sDate = $oDate->format('Y-m-d H:i:s');
{ }
$sDate = $oDate->format('Y-m-d'); }
}
else
{
$sDate = $oDate->format('Y-m-d H:i:s');
}
}
$oLinkedObj->Set($sLinkedAttCode, $sDate); $oLinkedObj->Set($sLinkedAttCode, $sDate);
} } else {
else
{
$oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]); $oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]);
} }
} }
@@ -120,189 +102,147 @@ class WizardHelper
} }
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray); $oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
$oObj->Set($sAttCode, $oSet); $oObj->Set($sAttCode, $oSet);
} } elseif ($oAttDef->GetEditClass() == 'Document') {
else if ( $oAttDef->GetEditClass() == 'Document' ) if ($bReadUploadedFiles) {
{
if ($bReadUploadedFiles)
{
$oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents'); $oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents');
$oObj->Set($sAttCode, $oDocument); $oObj->Set($sAttCode, $oDocument);
} } else {
else
{
// Create a new empty document, just for displaying the file name // Create a new empty document, just for displaying the file name
$oDocument = new ormDocument(null, '', $value); $oDocument = new ormDocument(null, '', $value);
$oObj->Set($sAttCode, $oDocument); $oObj->Set($sAttCode, $oDocument);
} }
} } elseif ($oAttDef->GetEditClass() == 'Image') {
else if ( $oAttDef->GetEditClass() == 'Image' ) if ($bReadUploadedFiles) {
{
if ($bReadUploadedFiles)
{
$oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents'); $oDocument = utils::ReadPostedDocument('attr_'.$sAttCode, 'fcontents');
$oObj->Set($sAttCode, $oDocument); $oObj->Set($sAttCode, $oDocument);
} } else {
else
{
// Create a new empty document, just for displaying the file name // Create a new empty document, just for displaying the file name
$oDocument = new ormDocument(null, '', $value); $oDocument = new ormDocument(null, '', $value);
$oObj->Set($sAttCode, $oDocument); $oObj->Set($sAttCode, $oDocument);
} }
} } elseif (($oAttDef->IsExternalKey()) && (!empty($value)) && ($value > 0)) {
else if (($oAttDef->IsExternalKey()) && (!empty($value)) && ($value > 0) )
{
// For external keys: load the target object so that external fields // For external keys: load the target object so that external fields
// get filled too // get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value, false); $oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value, false);
if ($oTargetObj) if ($oTargetObj) {
{
$oObj->Set($sAttCode, $oTargetObj); $oObj->Set($sAttCode, $oTargetObj);
} } else {
else
{
// May happen for security reasons (portal, see ticket N°1074) // May happen for security reasons (portal, see ticket N°1074)
$oObj->Set($sAttCode, $value); $oObj->Set($sAttCode, $value);
} }
} } elseif ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
else if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime if ($value != null) {
{
if ($value != null)
{
$oDate = $oAttDef->GetFormat()->Parse($value); $oDate = $oAttDef->GetFormat()->Parse($value);
if ($oDate instanceof DateTime) if ($oDate instanceof DateTime) {
{
$value = $oDate->format($oAttDef->GetInternalFormat()); $value = $oDate->format($oAttDef->GetInternalFormat());
} } else {
else
{
$value = null; $value = null;
} }
} }
$oObj->Set($sAttCode, $value); $oObj->Set($sAttCode, $value);
} } elseif ($oAttDef instanceof AttributeTagSet) { // AttributeDate is derived from AttributeDateTime
else if ($oAttDef instanceof AttributeTagSet) // AttributeDate is derived from AttributeDateTime if (is_null($value)) {
{
if (is_null($value))
{
// happens if field is hidden (see N°1827) // happens if field is hidden (see N°1827)
$value = array(); $value = [];
} } else {
else
{
$value = json_decode($value, true); $value = json_decode($value, true);
} }
$oTagSet = new ormTagSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems()); $oTagSet = new ormTagSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']); $oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value); $oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet); $oObj->Set($sAttCode, $oTagSet);
} } elseif ($oAttDef instanceof AttributeSet) { // AttributeDate is derived from AttributeDateTime
else if ($oAttDef instanceof AttributeSet) // AttributeDate is derived from AttributeDateTime
{
$value = json_decode($value, true); $value = json_decode($value, true);
$oTagSet = new ormSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems()); $oTagSet = new ormSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']); $oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value); $oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet); $oObj->Set($sAttCode, $oTagSet);
} } else {
else
{
$oObj->Set($sAttCode, $value); $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->Set(MetaModel::GetStateAttributeCode($this->m_aData['m_sClass']), $this->m_aData['m_sState']);
} }
$oObj->DoComputeValues(); $oObj->DoComputeValues();
return $oObj; return $oObj;
} }
public function GetFieldsForDefaultValue() public function GetFieldsForDefaultValue()
{ {
return $this->m_aData['m_aDefaultValueRequested']; return $this->m_aData['m_aDefaultValueRequested'];
} }
public function SetDefaultValue($sAttCode, $value) public function SetDefaultValue($sAttCode, $value)
{ {
// Protect against a request for a non existing field // 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); $oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if ($oAttDef->GetEditClass() == 'List') if ($oAttDef->GetEditClass() == 'List') {
{
// special handling for lists // special handling for lists
// this as to be handled as an array of objects // this as to be handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...] // thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
// NOT YET IMPLEMENTED !! // NOT YET IMPLEMENTED !!
$oSet = $value; $oSet = $value;
$aData = array(); $aData = [];
$aFields = $this->GetLinkedWizardStructure($oAttDef); $aFields = $this->GetLinkedWizardStructure($oAttDef);
while($oLinkedObj = $oSet->fetch()) while ($oLinkedObj = $oSet->fetch()) {
{ foreach ($aFields as $sLinkedAttCode) {
foreach($aFields as $sLinkedAttCode)
{
$aRow[$sAttCode] = $oLinkedObj->Get($sLinkedAttCode); $aRow[$sAttCode] = $oLinkedObj->Get($sLinkedAttCode);
} }
$aData[] = $aRow; $aData[] = $aRow;
} }
$this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData); $this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData);
} } else {
else
{
// Normal handling for all other scalar attributes // Normal handling for all other scalar attributes
$this->m_aData['m_oDefaultValue'][$sAttCode] = $value; $this->m_aData['m_oDefaultValue'][$sAttCode] = $value;
} }
} }
} }
public function GetFieldsForAllowedValues() public function GetFieldsForAllowedValues()
{ {
return $this->m_aData['m_aAllowedValuesRequested']; return $this->m_aData['m_aAllowedValuesRequested'];
} }
public function SetAllowedValuesHtml($sAttCode, $sHtml) public function SetAllowedValuesHtml($sAttCode, $sHtml)
{ {
// Protect against a request for a non existing field // 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; $this->m_aData['m_oAllowedValues'][$sAttCode] = $sHtml;
} }
} }
public function ToJSON() public function ToJSON()
{ {
return json_encode($this->m_aData); return json_encode($this->m_aData);
} }
static public function FromJSON($sJSON) public static function FromJSON($sJSON)
{ {
$oWizHelper = new WizardHelper(); $oWizHelper = new WizardHelper();
$aData = json_decode($sJSON, true); // true means hash array instead of object $aData = json_decode($sJSON, true); // true means hash array instead of object
$oWizHelper->m_aData = $aData; $oWizHelper->m_aData = $aData;
return $oWizHelper; return $oWizHelper;
} }
protected function GetLinkedWizardStructure($oAttDef) protected function GetLinkedWizardStructure($oAttDef)
{ {
$oWizard = new UIWizard(null, $oAttDef->GetLinkedClass()); $oWizard = new UIWizard(null, $oAttDef->GetLinkedClass());
$aWizardSteps = $oWizard->GetWizardStructure(); $aWizardSteps = $oWizard->GetWizardStructure();
$aFields = array(); $aFields = [];
$sExtKeyToMeCode = $oAttDef->GetExtKeyToMe(); $sExtKeyToMeCode = $oAttDef->GetExtKeyToMe();
// Retrieve as a flat list, all the attributes that are needed to create // 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 // 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 // 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' // 2 entries: 'mandatory' and 'optional'
foreach($aMainSteps as $aSteps) foreach ($aMainSteps as $aSteps) {
{
// One entry for each step of the wizard // One entry for each step of the wizard
foreach($aSteps as $sAttCode) foreach ($aSteps as $sAttCode) {
{ if ($sAttCode != $sExtKeyToMeCode) {
if ($sAttCode != $sExtKeyToMeCode)
{
$aFields[] = $sAttCode; $aFields[] = $sAttCode;
} }
} }
@@ -310,35 +250,34 @@ class WizardHelper
} }
return $aFields; return $aFields;
} }
public function GetTargetClass() public function GetTargetClass()
{ {
return $this->m_aData['m_sClass']; return $this->m_aData['m_sClass'];
} }
public function GetFormPrefix() public function GetFormPrefix()
{ {
return $this->m_aData['m_sFormPrefix']; return $this->m_aData['m_sFormPrefix'];
} }
public function GetInitialState() public function GetInitialState()
{ {
return isset($this->m_aData['m_sInitialState']) ? $this->m_aData['m_sInitialState'] : null; 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) public function GetIdForField($sFieldName)
{ {
$sResult = ''; $sResult = '';
// It may happen that the field we'd like to update does not // 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 // exist in the form. For example, if the field should be hidden/read-only
// in the current state of the object // 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]; $sResult = $this->m_aData['m_oFieldsMap'][$sFieldName];
} }
@@ -378,12 +317,14 @@ JS;
$sWizardHelperJsVar = (!is_null($this->m_aData['m_sWizHelperJsVarName'])) ? utils::Sanitize($this->m_aData['m_sWizHelperJsVarName'], '', utils::ENUM_SANITIZATION_FILTER_PARAMETER) : 'oWizardHelper'.$this->GetFormPrefix(); $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(); $sWizardHelperJson = $this->ToJSON();
$oPage->add_script(<<<JS $oPage->add_script(
<<<JS
{$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson}; {$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson};
{$sWizardHelperJsVar}.UpdateFields(); {$sWizardHelperJsVar}.UpdateFields();
JS JS
); );
$oPage->add_ready_script(<<<JS $oPage->add_ready_script(
<<<JS
if ({$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve !== null){ if ({$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve !== null){
{$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve(); {$sWizardHelperJsVar}.m_oDependenciesUpdatedPromiseResolve();
} }
@@ -396,7 +337,7 @@ JS
* Function with an old pattern of code * Function with an old pattern of code
* @deprecated 3.1.0 * @deprecated 3.1.0
*/ */
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet) public static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
{ {
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object $aSet = json_decode($sJsonSet, true); // true means hash array instead of object
$oSet = CMDBObjectSet::FromScratch($sLinkClass); $oSet = CMDBObjectSet::FromScratch($sLinkClass);
@@ -404,8 +345,7 @@ JS
$oLink = MetaModel::NewObject($sLinkClass); $oLink = MetaModel::NewObject($sLinkClass);
foreach ($aLinkObj as $sAttCode => $value) { foreach ($aLinkObj as $sAttCode => $value) {
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0)) if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0)) {
{
// For external keys: load the target object so that external fields // For external keys: load the target object so that external fields
// get filled too // get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value); $oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value);

View File

@@ -1,43 +1,51 @@
<?php <?php
/* @author Mark Jones /* @author Mark Jones
* @license MIT License * @license MIT License
* */ * */
if (!class_exists('ZipArchive')) { throw new Exception('ZipArchive not found'); } if (!class_exists('ZipArchive')) {
throw new Exception('ZipArchive not found');
}
Class XLSXWriter class XLSXWriter
{ {
//------------------------------------------------------------------ //------------------------------------------------------------------
protected $author ='Doc Author'; protected $author = 'Doc Author';
protected $sheets_meta = array(); protected $sheets_meta = [];
protected $shared_strings = array();//unique set protected $shared_strings = [];//unique set
protected $shared_string_count = 0;//count of non-unique references to the unique set protected $shared_string_count = 0;//count of non-unique references to the unique set
protected $temp_files = array(); protected $temp_files = [];
protected $date_format = 'YYYY-MM-DD'; protected $date_format = 'YYYY-MM-DD';
protected $date_time_format = 'YYYY-MM-DD\ HH:MM:SS'; protected $date_time_format = 'YYYY-MM-DD\ HH:MM:SS';
public function __construct(){} public function __construct()
public function setAuthor($author='') { $this->author=$author; } {
}
public function setAuthor($author = '')
{
$this->author = $author;
}
public function __destruct() public function __destruct()
{ {
if (!empty($this->temp_files)) { if (!empty($this->temp_files)) {
foreach($this->temp_files as $temp_file) { foreach ($this->temp_files as $temp_file) {
@unlink($temp_file); @unlink($temp_file);
} }
} }
} }
public function setDateFormat($date_format) public function setDateFormat($date_format)
{ {
$this->date_format = $date_format; $this->date_format = $date_format;
} }
public function setDateTimeFormat($date_time_format) public function setDateTimeFormat($date_time_format)
{ {
$this->date_time_format = $date_time_format; $this->date_time_format = $date_time_format;
} }
protected function tempFilename() protected function tempFilename()
{ {
$filename = tempnam(SetupUtils::GettmpDir(), 'xlsx_writer_'); $filename = tempnam(SetupUtils::GettmpDir(), 'xlsx_writer_');
@@ -64,120 +72,123 @@ Class XLSXWriter
{ {
@unlink($filename);//if the zip already exists, overwrite it @unlink($filename);//if the zip already exists, overwrite it
$zip = new ZipArchive(); $zip = new ZipArchive();
if (empty($this->sheets_meta)) { self::log("Error in ".__CLASS__."::".__FUNCTION__.", no worksheets defined."); return; } if (empty($this->sheets_meta)) {
if (!$zip->open($filename, ZipArchive::CREATE)) { self::log("Error in ".__CLASS__."::".__FUNCTION__.", unable to create zip."); return; } self::log("Error in ".__CLASS__."::".__FUNCTION__.", no worksheets defined.");
return;
}
if (!$zip->open($filename, ZipArchive::CREATE)) {
self::log("Error in ".__CLASS__."::".__FUNCTION__.", unable to create zip.");
return;
}
$zip->addEmptyDir("docProps/"); $zip->addEmptyDir("docProps/");
$zip->addFromString("docProps/app.xml" , self::buildAppXML() ); $zip->addFromString("docProps/app.xml", self::buildAppXML());
$zip->addFromString("docProps/core.xml", self::buildCoreXML()); $zip->addFromString("docProps/core.xml", self::buildCoreXML());
$zip->addEmptyDir("_rels/"); $zip->addEmptyDir("_rels/");
$zip->addFromString("_rels/.rels", self::buildRelationshipsXML()); $zip->addFromString("_rels/.rels", self::buildRelationshipsXML());
$zip->addEmptyDir("xl/worksheets/"); $zip->addEmptyDir("xl/worksheets/");
foreach($this->sheets_meta as $sheet_meta) { foreach ($this->sheets_meta as $sheet_meta) {
$zip->addFile($sheet_meta['filename'], "xl/worksheets/".$sheet_meta['xmlname'] ); $zip->addFile($sheet_meta['filename'], "xl/worksheets/".$sheet_meta['xmlname']);
} }
if (!empty($this->shared_strings)) { if (!empty($this->shared_strings)) {
$zip->addFile($this->writeSharedStringsXML(), "xl/sharedStrings.xml" ); //$zip->addFromString("xl/sharedStrings.xml", self::buildSharedStringsXML() ); $zip->addFile($this->writeSharedStringsXML(), "xl/sharedStrings.xml"); //$zip->addFromString("xl/sharedStrings.xml", self::buildSharedStringsXML() );
} }
$zip->addFromString("xl/workbook.xml" , self::buildWorkbookXML() ); $zip->addFromString("xl/workbook.xml", self::buildWorkbookXML());
$zip->addFile($this->writeStylesXML(), "xl/styles.xml" ); //$zip->addFromString("xl/styles.xml" , self::buildStylesXML() ); $zip->addFile($this->writeStylesXML(), "xl/styles.xml"); //$zip->addFromString("xl/styles.xml" , self::buildStylesXML() );
$zip->addFromString("[Content_Types].xml" , self::buildContentTypesXML() ); $zip->addFromString("[Content_Types].xml", self::buildContentTypesXML());
$zip->addEmptyDir("xl/_rels/"); $zip->addEmptyDir("xl/_rels/");
$zip->addFromString("xl/_rels/workbook.xml.rels", self::buildWorkbookRelsXML() ); $zip->addFromString("xl/_rels/workbook.xml.rels", self::buildWorkbookRelsXML());
$zip->close(); $zip->close();
} }
public function writeSheet(array $data, $sheet_name = '', array $header_types = [], array $header_row = [])
public function writeSheet(array $data, $sheet_name='', array $header_types=array(), array $header_row=array() )
{ {
$data = empty($data) ? array( array('') ) : $data; $data = empty($data) ? [ [''] ] : $data;
$sheet_filename = $this->tempFilename(); $sheet_filename = $this->tempFilename();
$sheet_default = 'Sheet'.(count($this->sheets_meta)+1); $sheet_default = 'Sheet'.(count($this->sheets_meta) + 1);
$sheet_name = !empty($sheet_name) ? $sheet_name : $sheet_default; $sheet_name = !empty($sheet_name) ? $sheet_name : $sheet_default;
$this->sheets_meta[] = array('filename'=>$sheet_filename, 'sheetname'=>$sheet_name ,'xmlname'=>strtolower($sheet_default).".xml" ); $this->sheets_meta[] = ['filename' => $sheet_filename, 'sheetname' => $sheet_name ,'xmlname' => strtolower($sheet_default).".xml" ];
$header_offset = empty($header_types) ? 0 : 1; $header_offset = empty($header_types) ? 0 : 1;
$row_count = count($data) + $header_offset; $row_count = count($data) + $header_offset;
$column_count = count($data[self::array_first_key($data)]); $column_count = count($data[self::array_first_key($data)]);
$max_cell = self::xlsCell( $row_count-1, $column_count-1 ); $max_cell = self::xlsCell($row_count - 1, $column_count - 1);
$tabselected = count($this->sheets_meta)==1 ? 'true' : 'false';//only first sheet is selected $tabselected = count($this->sheets_meta) == 1 ? 'true' : 'false';//only first sheet is selected
$cell_formats_arr = empty($header_types) ? array_fill(0, $column_count, 'string') : array_values($header_types); $cell_formats_arr = empty($header_types) ? array_fill(0, $column_count, 'string') : array_values($header_types);
if (empty($header_row) && !empty($header_types)) if (empty($header_row) && !empty($header_types)) {
{ $header_row = empty($header_types) ? [] : array_keys($header_types);
$header_row = empty($header_types) ? array() : array_keys($header_types);
} }
$fd = fopen($sheet_filename, "w+"); $fd = fopen($sheet_filename, "w+");
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; } if ($fd === false) {
self::log("write failed in ".__CLASS__."::".__FUNCTION__.".");
fwrite($fd,'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"); return;
fwrite($fd,'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'); }
fwrite($fd, '<sheetPr filterMode="false">');
fwrite($fd, '<pageSetUpPr fitToPage="false"/>'); fwrite($fd, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
fwrite($fd, '</sheetPr>'); fwrite($fd, '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">');
fwrite($fd, '<dimension ref="A1:'.$max_cell.'"/>'); fwrite($fd, '<sheetPr filterMode="false">');
fwrite($fd, '<sheetViews>'); fwrite($fd, '<pageSetUpPr fitToPage="false"/>');
fwrite($fd, '<sheetView colorId="64" defaultGridColor="true" rightToLeft="false" showFormulas="false" showGridLines="true" showOutlineSymbols="true" showRowColHeaders="true" showZeros="true" tabSelected="'.$tabselected.'" topLeftCell="A1" view="normal" windowProtection="false" workbookViewId="0" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100">'); fwrite($fd, '</sheetPr>');
fwrite($fd, '<selection activeCell="A1" activeCellId="0" pane="topLeft" sqref="A1"/>'); fwrite($fd, '<dimension ref="A1:'.$max_cell.'"/>');
fwrite($fd, '</sheetView>'); fwrite($fd, '<sheetViews>');
fwrite($fd, '</sheetViews>'); fwrite($fd, '<sheetView colorId="64" defaultGridColor="true" rightToLeft="false" showFormulas="false" showGridLines="true" showOutlineSymbols="true" showRowColHeaders="true" showZeros="true" tabSelected="'.$tabselected.'" topLeftCell="A1" view="normal" windowProtection="false" workbookViewId="0" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100">');
fwrite($fd, '<cols>'); fwrite($fd, '<selection activeCell="A1" activeCellId="0" pane="topLeft" sqref="A1"/>');
fwrite($fd, '<col collapsed="false" hidden="false" max="1025" min="1" style="0" width="19"/>'); fwrite($fd, '</sheetView>');
fwrite($fd, '</cols>'); fwrite($fd, '</sheetViews>');
fwrite($fd, '<sheetData>'); fwrite($fd, '<cols>');
if (!empty($header_row)) fwrite($fd, '<col collapsed="false" hidden="false" max="1025" min="1" style="0" width="19"/>');
{ fwrite($fd, '</cols>');
fwrite($fd, '<sheetData>');
if (!empty($header_row)) {
fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.(1).'">'); fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.(1).'">');
foreach($header_row as $k=>$v) foreach ($header_row as $k => $v) {
{ $this->writeCell($fd, 0, $k, $v, $cell_format = 'string');
$this->writeCell($fd, 0, $k, $v, $cell_format='string');
} }
fwrite($fd, '</row>'); fwrite($fd, '</row>');
} }
foreach($data as $i=>$row) foreach ($data as $i => $row) {
{ fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.($i + $header_offset + 1).'">');
fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.($i+$header_offset+1).'">'); foreach ($row as $k => $v) {
foreach($row as $k=>$v) $this->writeCell($fd, $i + $header_offset, $k, $v, $cell_formats_arr[$k]);
{
$this->writeCell($fd, $i+$header_offset, $k, $v, $cell_formats_arr[$k]);
} }
fwrite($fd, '</row>'); fwrite($fd, '</row>');
} }
fwrite($fd, '</sheetData>'); fwrite($fd, '</sheetData>');
fwrite($fd, '<printOptions headings="false" gridLines="false" gridLinesSet="true" horizontalCentered="false" verticalCentered="false"/>'); fwrite($fd, '<printOptions headings="false" gridLines="false" gridLinesSet="true" horizontalCentered="false" verticalCentered="false"/>');
fwrite($fd, '<pageMargins left="0.5" right="0.5" top="1.0" bottom="1.0" header="0.5" footer="0.5"/>'); fwrite($fd, '<pageMargins left="0.5" right="0.5" top="1.0" bottom="1.0" header="0.5" footer="0.5"/>');
fwrite($fd, '<pageSetup blackAndWhite="false" cellComments="none" copies="1" draft="false" firstPageNumber="1" fitToHeight="1" fitToWidth="1" horizontalDpi="300" orientation="portrait" pageOrder="downThenOver" paperSize="1" scale="100" useFirstPageNumber="true" usePrinterDefaults="false" verticalDpi="300"/>'); fwrite($fd, '<pageSetup blackAndWhite="false" cellComments="none" copies="1" draft="false" firstPageNumber="1" fitToHeight="1" fitToWidth="1" horizontalDpi="300" orientation="portrait" pageOrder="downThenOver" paperSize="1" scale="100" useFirstPageNumber="true" usePrinterDefaults="false" verticalDpi="300"/>');
fwrite($fd, '<headerFooter differentFirst="false" differentOddEven="false">'); fwrite($fd, '<headerFooter differentFirst="false" differentOddEven="false">');
fwrite($fd, '<oddHeader>&amp;C&amp;&quot;Times New Roman,Regular&quot;&amp;12&amp;A</oddHeader>'); fwrite($fd, '<oddHeader>&amp;C&amp;&quot;Times New Roman,Regular&quot;&amp;12&amp;A</oddHeader>');
fwrite($fd, '<oddFooter>&amp;C&amp;&quot;Times New Roman,Regular&quot;&amp;12Page &amp;P</oddFooter>'); fwrite($fd, '<oddFooter>&amp;C&amp;&quot;Times New Roman,Regular&quot;&amp;12Page &amp;P</oddFooter>');
fwrite($fd, '</headerFooter>'); fwrite($fd, '</headerFooter>');
fwrite($fd,'</worksheet>'); fwrite($fd, '</worksheet>');
fclose($fd); fclose($fd);
} }
protected function writeCell($fd, $row_number, $column_number, $value, $cell_format) protected function writeCell($fd, $row_number, $column_number, $value, $cell_format)
{ {
static $styles = array('money'=>1,'dollar'=>1,'datetime'=>2,'date'=>3,'string'=>0); static $styles = ['money' => 1,'dollar' => 1,'datetime' => 2,'date' => 3,'string' => 0];
$cell = self::xlsCell($row_number, $column_number); $cell = self::xlsCell($row_number, $column_number);
$s = isset($styles[$cell_format]) && ($value !== '') ? $styles[$cell_format] : '0'; $s = isset($styles[$cell_format]) && ($value !== '') ? $styles[$cell_format] : '0';
if (is_int($value) || is_float($value)) { if (is_int($value) || is_float($value)) {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.($value*1).'</v></c>');//int,float, etc fwrite($fd, '<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.($value * 1).'</v></c>');//int,float, etc
} else if (($cell_format=='date') && ($value != '')) { } elseif (($cell_format == 'date') && ($value != '')) {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.intval(self::convert_date_time($value)).'</v></c>'); fwrite($fd, '<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.intval(self::convert_date_time($value)).'</v></c>');
} else if (($cell_format=='datetime') && ($value != '')) { } elseif (($cell_format == 'datetime') && ($value != '')) {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.self::convert_date_time($value).'</v></c>'); fwrite($fd, '<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.self::convert_date_time($value).'</v></c>');
} else if ($value==''){ } elseif ($value == '') {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'"/>'); fwrite($fd, '<c r="'.$cell.'" s="'.$s.'"/>');
} else if ($value[0]=='='){ } elseif ($value[0] == '=') {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="s"><f>'.self::xmlspecialchars($value).'</f></c>'); fwrite($fd, '<c r="'.$cell.'" s="'.$s.'" t="s"><f>'.self::xmlspecialchars($value).'</f></c>');
} else if ($value!==''){ } elseif ($value !== '') {
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="s"><v>'.self::xmlspecialchars($this->setSharedString($value)).'</v></c>'); fwrite($fd, '<c r="'.$cell.'" s="'.$s.'" t="s"><v>'.self::xmlspecialchars($this->setSharedString($value)).'</v></c>');
} }
} }
@@ -185,62 +196,65 @@ Class XLSXWriter
{ {
$tempfile = $this->tempFilename(); $tempfile = $this->tempFilename();
$fd = fopen($tempfile, "w+"); $fd = fopen($tempfile, "w+");
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; } if ($fd === false) {
self::log("write failed in ".__CLASS__."::".__FUNCTION__.".");
return;
}
fwrite($fd, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"); fwrite($fd, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
fwrite($fd, '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'); fwrite($fd, '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">');
fwrite($fd, '<numFmts count="4">'); fwrite($fd, '<numFmts count="4">');
fwrite($fd, '<numFmt formatCode="GENERAL" numFmtId="164"/>'); fwrite($fd, '<numFmt formatCode="GENERAL" numFmtId="164"/>');
fwrite($fd, '<numFmt formatCode="[$$-1009]#,##0.00;[RED]\-[$$-1009]#,##0.00" numFmtId="165"/>'); fwrite($fd, '<numFmt formatCode="[$$-1009]#,##0.00;[RED]\-[$$-1009]#,##0.00" numFmtId="165"/>');
fwrite($fd, '<numFmt formatCode="'.$this->date_time_format.'" numFmtId="166"/>'); fwrite($fd, '<numFmt formatCode="'.$this->date_time_format.'" numFmtId="166"/>');
fwrite($fd, '<numFmt formatCode="'.$this->date_format.'" numFmtId="167"/>'); fwrite($fd, '<numFmt formatCode="'.$this->date_format.'" numFmtId="167"/>');
fwrite($fd, '</numFmts>'); fwrite($fd, '</numFmts>');
fwrite($fd, '<fonts count="4">'); fwrite($fd, '<fonts count="4">');
fwrite($fd, '<font><name val="Arial"/><charset val="1"/><family val="2"/><sz val="10"/></font>'); fwrite($fd, '<font><name val="Arial"/><charset val="1"/><family val="2"/><sz val="10"/></font>');
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>'); fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>'); fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>'); fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
fwrite($fd, '</fonts>'); fwrite($fd, '</fonts>');
fwrite($fd, '<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>'); fwrite($fd, '<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
fwrite($fd, '<borders count="1"><border diagonalDown="false" diagonalUp="false"><left/><right/><top/><bottom/><diagonal/></border></borders>'); fwrite($fd, '<borders count="1"><border diagonalDown="false" diagonalUp="false"><left/><right/><top/><bottom/><diagonal/></border></borders>');
fwrite($fd, '<cellStyleXfs count="15">'); fwrite($fd, '<cellStyleXfs count="15">');
fwrite($fd, '<xf applyAlignment="true" applyBorder="true" applyFont="true" applyProtection="true" borderId="0" fillId="0" fontId="0" numFmtId="164">'); fwrite($fd, '<xf applyAlignment="true" applyBorder="true" applyFont="true" applyProtection="true" borderId="0" fillId="0" fontId="0" numFmtId="164">');
fwrite($fd, '<alignment horizontal="general" indent="0" shrinkToFit="false" textRotation="0" vertical="bottom" wrapText="false"/>'); fwrite($fd, '<alignment horizontal="general" indent="0" shrinkToFit="false" textRotation="0" vertical="bottom" wrapText="false"/>');
fwrite($fd, '<protection hidden="false" locked="true"/>'); fwrite($fd, '<protection hidden="false" locked="true"/>');
fwrite($fd, '</xf>'); fwrite($fd, '</xf>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="43"/>'); //fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="43"/>');
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="41"/>'); //fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="41"/>');
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="44"/>'); //fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="44"/>');
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="42"/>'); //fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="42"/>');
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="9"/>'); //fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="9"/>');
fwrite($fd, '</cellStyleXfs>'); fwrite($fd, '</cellStyleXfs>');
fwrite($fd, '<cellXfs count="4">'); fwrite($fd, '<cellXfs count="4">');
fwrite($fd, '<xf applyAlignment="1" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="164" xfId="0"><alignment wrapText="1"/></xf>'); fwrite($fd, '<xf applyAlignment="1" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="164" xfId="0"><alignment wrapText="1"/></xf>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="165" xfId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="165" xfId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="166" xfId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="166" xfId="0"/>');
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="167" xfId="0"/>'); fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="167" xfId="0"/>');
fwrite($fd, '</cellXfs>'); fwrite($fd, '</cellXfs>');
fwrite($fd, '<cellStyles count="1">'); fwrite($fd, '<cellStyles count="1">');
fwrite($fd, '<cellStyle builtinId="0" customBuiltin="false" name="Normal" xfId="0"/>'); fwrite($fd, '<cellStyle builtinId="0" customBuiltin="false" name="Normal" xfId="0"/>');
//fwrite($fd, '<cellStyle builtinId="3" customBuiltin="false" name="Comma" xfId="15"/>'); //fwrite($fd, '<cellStyle builtinId="3" customBuiltin="false" name="Comma" xfId="15"/>');
//fwrite($fd, '<cellStyle builtinId="6" customBuiltin="false" name="Comma [0]" xfId="16"/>'); //fwrite($fd, '<cellStyle builtinId="6" customBuiltin="false" name="Comma [0]" xfId="16"/>');
//fwrite($fd, '<cellStyle builtinId="4" customBuiltin="false" name="Currency" xfId="17"/>'); //fwrite($fd, '<cellStyle builtinId="4" customBuiltin="false" name="Currency" xfId="17"/>');
//fwrite($fd, '<cellStyle builtinId="7" customBuiltin="false" name="Currency [0]" xfId="18"/>'); //fwrite($fd, '<cellStyle builtinId="7" customBuiltin="false" name="Currency [0]" xfId="18"/>');
//fwrite($fd, '<cellStyle builtinId="5" customBuiltin="false" name="Percent" xfId="19"/>'); //fwrite($fd, '<cellStyle builtinId="5" customBuiltin="false" name="Percent" xfId="19"/>');
fwrite($fd, '</cellStyles>'); fwrite($fd, '</cellStyles>');
fwrite($fd, '</styleSheet>'); fwrite($fd, '</styleSheet>');
fclose($fd); fclose($fd);
return $tempfile; return $tempfile;
@@ -250,12 +264,9 @@ Class XLSXWriter
{ {
// Strip control characters which Excel does not seem to like... // Strip control characters which Excel does not seem to like...
$v = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F]/u', '', $v); $v = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F]/u', '', $v);
if (isset($this->shared_strings[$v])) if (isset($this->shared_strings[$v])) {
{
$string_value = $this->shared_strings[$v]; $string_value = $this->shared_strings[$v];
} } else {
else
{
$string_value = count($this->shared_strings); $string_value = count($this->shared_strings);
$this->shared_strings[$v] = $string_value; $this->shared_strings[$v] = $string_value;
} }
@@ -267,13 +278,15 @@ Class XLSXWriter
{ {
$tempfile = $this->tempFilename(); $tempfile = $this->tempFilename();
$fd = fopen($tempfile, "w+"); $fd = fopen($tempfile, "w+");
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; } if ($fd === false) {
self::log("write failed in ".__CLASS__."::".__FUNCTION__.".");
fwrite($fd,'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"); return;
fwrite($fd,'<sst count="'.($this->shared_string_count).'" uniqueCount="'.count($this->shared_strings).'" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'); }
foreach($this->shared_strings as $s=>$c)
{ fwrite($fd, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
fwrite($fd,'<si><t>'.self::xmlspecialchars($s).'</t></si>'); fwrite($fd, '<sst count="'.($this->shared_string_count).'" uniqueCount="'.count($this->shared_strings).'" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">');
foreach ($this->shared_strings as $s => $c) {
fwrite($fd, '<si><t>'.self::xmlspecialchars($s).'</t></si>');
} }
fwrite($fd, '</sst>'); fwrite($fd, '</sst>');
fclose($fd); fclose($fd);
@@ -282,89 +295,89 @@ Class XLSXWriter
protected function buildAppXML() protected function buildAppXML()
{ {
$app_xml=""; $app_xml = "";
$app_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"; $app_xml .= '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
$app_xml.='<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime></Properties>'; $app_xml .= '<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime></Properties>';
return $app_xml; return $app_xml;
} }
protected function buildCoreXML() protected function buildCoreXML()
{ {
$core_xml=""; $core_xml = "";
$core_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"; $core_xml .= '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
$core_xml.='<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'; $core_xml .= '<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
$core_xml.='<dcterms:created xsi:type="dcterms:W3CDTF">'.date("Y-m-d\TH:i:s.00\Z").'</dcterms:created>';//$date_time = '2013-07-25T15:54:37.00Z'; $core_xml .= '<dcterms:created xsi:type="dcterms:W3CDTF">'.date("Y-m-d\TH:i:s.00\Z").'</dcterms:created>';//$date_time = '2013-07-25T15:54:37.00Z';
$core_xml.='<dc:creator>'.self::xmlspecialchars($this->author).'</dc:creator>'; $core_xml .= '<dc:creator>'.self::xmlspecialchars($this->author).'</dc:creator>';
$core_xml.='<cp:revision>0</cp:revision>'; $core_xml .= '<cp:revision>0</cp:revision>';
$core_xml.='</cp:coreProperties>'; $core_xml .= '</cp:coreProperties>';
return $core_xml; return $core_xml;
} }
protected function buildRelationshipsXML() protected function buildRelationshipsXML()
{ {
$rels_xml=""; $rels_xml = "";
$rels_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n"; $rels_xml .= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$rels_xml.='<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'; $rels_xml .= '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">';
$rels_xml.='<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'; $rels_xml .= '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>';
$rels_xml.='<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>'; $rels_xml .= '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>';
$rels_xml.='<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>'; $rels_xml .= '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>';
$rels_xml.="\n"; $rels_xml .= "\n";
$rels_xml.='</Relationships>'; $rels_xml .= '</Relationships>';
return $rels_xml; return $rels_xml;
} }
protected function buildWorkbookXML() protected function buildWorkbookXML()
{ {
$workbook_xml=""; $workbook_xml = "";
$workbook_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n"; $workbook_xml .= '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
$workbook_xml.='<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'; $workbook_xml .= '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">';
$workbook_xml.='<fileVersion appName="Calc"/><workbookPr backupFile="false" showObjects="all" date1904="false"/><workbookProtection/>'; $workbook_xml .= '<fileVersion appName="Calc"/><workbookPr backupFile="false" showObjects="all" date1904="false"/><workbookProtection/>';
$workbook_xml.='<bookViews><workbookView activeTab="0" firstSheet="0" showHorizontalScroll="true" showSheetTabs="true" showVerticalScroll="true" tabRatio="212" windowHeight="8192" windowWidth="16384" xWindow="0" yWindow="0"/></bookViews>'; $workbook_xml .= '<bookViews><workbookView activeTab="0" firstSheet="0" showHorizontalScroll="true" showSheetTabs="true" showVerticalScroll="true" tabRatio="212" windowHeight="8192" windowWidth="16384" xWindow="0" yWindow="0"/></bookViews>';
$workbook_xml.='<sheets>'; $workbook_xml .= '<sheets>';
foreach($this->sheets_meta as $i=>$sheet_meta) { foreach ($this->sheets_meta as $i => $sheet_meta) {
$workbook_xml.='<sheet name="'.self::xmlspecialchars($sheet_meta['sheetname']).'" sheetId="'.($i+1).'" state="visible" r:id="rId'.($i+2).'"/>'; $workbook_xml .= '<sheet name="'.self::xmlspecialchars($sheet_meta['sheetname']).'" sheetId="'.($i + 1).'" state="visible" r:id="rId'.($i + 2).'"/>';
} }
$workbook_xml.='</sheets>'; $workbook_xml .= '</sheets>';
$workbook_xml.='<calcPr iterateCount="100" refMode="A1" iterate="false" iterateDelta="0.001"/></workbook>'; $workbook_xml .= '<calcPr iterateCount="100" refMode="A1" iterate="false" iterateDelta="0.001"/></workbook>';
return $workbook_xml; return $workbook_xml;
} }
protected function buildWorkbookRelsXML() protected function buildWorkbookRelsXML()
{ {
$wkbkrels_xml=""; $wkbkrels_xml = "";
$wkbkrels_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n"; $wkbkrels_xml .= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$wkbkrels_xml.='<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'; $wkbkrels_xml .= '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">';
$wkbkrels_xml.='<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'; $wkbkrels_xml .= '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>';
foreach($this->sheets_meta as $i=>$sheet_meta) { foreach ($this->sheets_meta as $i => $sheet_meta) {
$wkbkrels_xml.='<Relationship Id="rId'.($i+2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/'.($sheet_meta['xmlname']).'"/>'; $wkbkrels_xml .= '<Relationship Id="rId'.($i + 2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/'.($sheet_meta['xmlname']).'"/>';
} }
if (!empty($this->shared_strings)) { if (!empty($this->shared_strings)) {
$wkbkrels_xml.='<Relationship Id="rId'.(count($this->sheets_meta)+2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>'; $wkbkrels_xml .= '<Relationship Id="rId'.(count($this->sheets_meta) + 2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>';
} }
$wkbkrels_xml.="\n"; $wkbkrels_xml .= "\n";
$wkbkrels_xml.='</Relationships>'; $wkbkrels_xml .= '</Relationships>';
return $wkbkrels_xml; return $wkbkrels_xml;
} }
protected function buildContentTypesXML() protected function buildContentTypesXML()
{ {
$content_types_xml=""; $content_types_xml = "";
$content_types_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n"; $content_types_xml .= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$content_types_xml.='<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'; $content_types_xml .= '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">';
$content_types_xml.='<Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'; $content_types_xml .= '<Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>';
$content_types_xml.='<Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'; $content_types_xml .= '<Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>';
foreach($this->sheets_meta as $i=>$sheet_meta) { foreach ($this->sheets_meta as $i => $sheet_meta) {
$content_types_xml.='<Override PartName="/xl/worksheets/'.($sheet_meta['xmlname']).'" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>'; $content_types_xml .= '<Override PartName="/xl/worksheets/'.($sheet_meta['xmlname']).'" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>';
} }
if (!empty($this->shared_strings)) { if (!empty($this->shared_strings)) {
$content_types_xml.='<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>'; $content_types_xml .= '<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>';
} }
$content_types_xml.='<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'; $content_types_xml .= '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>';
$content_types_xml.='<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>'; $content_types_xml .= '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>';
$content_types_xml.='<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>'; $content_types_xml .= '<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>';
$content_types_xml.='<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>'; $content_types_xml .= '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>';
$content_types_xml.="\n"; $content_types_xml .= "\n";
$content_types_xml.='</Types>'; $content_types_xml .= '</Types>';
return $content_types_xml; return $content_types_xml;
} }
@@ -377,10 +390,10 @@ Class XLSXWriter
public static function xlsCell($row_number, $column_number) public static function xlsCell($row_number, $column_number)
{ {
$n = $column_number; $n = $column_number;
for($r = ""; $n >= 0; $n = intval($n / 26) - 1) { for ($r = ""; $n >= 0; $n = intval($n / 26) - 1) {
$r = chr($n%26 + 0x41) . $r; $r = chr($n % 26 + 0x41).$r;
} }
return $r . ($row_number+1); return $r.($row_number + 1);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
public static function log($string) public static function log($string)
@@ -404,26 +417,30 @@ Class XLSXWriter
{ {
$days = 0; # Number of days since epoch $days = 0; # Number of days since epoch
$seconds = 0; # Time expressed as fraction of 24h hours in seconds $seconds = 0; # Time expressed as fraction of 24h hours in seconds
$year=$month=$day=0; $year = $month = $day = 0;
$hour=$min =$sec=0; $hour = $min = $sec = 0;
$date_time = $date_input; $date_time = $date_input;
if (preg_match("/(\d{4})\-(\d{2})\-(\d{2})/", $date_time, $matches)) if (preg_match("/(\d{4})\-(\d{2})\-(\d{2})/", $date_time, $matches)) {
{ list($junk, $year, $month, $day) = $matches;
list($junk,$year,$month,$day) = $matches;
} }
if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $date_time, $matches)) if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $date_time, $matches)) {
{ list($junk, $hour, $min, $sec) = $matches;
list($junk,$hour,$min,$sec) = $matches; $seconds = ($hour * 60 * 60 + $min * 60 + $sec) / (24 * 60 * 60);
$seconds = ( $hour * 60 * 60 + $min * 60 + $sec ) / ( 24 * 60 * 60 );
} }
//using 1900 as epoch, not 1904, ignoring 1904 special case //using 1900 as epoch, not 1904, ignoring 1904 special case
# Special cases for Excel. # Special cases for Excel.
if ("$year-$month-$day"=='1899-12-31') return $seconds ; # Excel 1900 epoch if ("$year-$month-$day" == '1899-12-31') {
if ("$year-$month-$day"=='1900-01-00') return $seconds ; # Excel 1900 epoch return $seconds ;
if ("$year-$month-$day"=='1900-02-29') return 60 + $seconds ; # Excel false leapday } # Excel 1900 epoch
if ("$year-$month-$day" == '1900-01-00') {
return $seconds ;
} # Excel 1900 epoch
if ("$year-$month-$day" == '1900-02-29') {
return 60 + $seconds ;
} # Excel false leapday
# We calculate the date by calculating the number of days since the epoch # We calculate the date by calculating the number of days since the epoch
# and adjust for the number of leap days. We calculate the number of leap # and adjust for the number of leap days. We calculate the number of leap
@@ -435,33 +452,35 @@ Class XLSXWriter
$range = $year - $epoch; $range = $year - $epoch;
# Set month days and check for leap year. # Set month days and check for leap year.
$leap = (($year % 400 == 0) || (($year % 4 == 0) && ($year % 100)) ) ? 1 : 0; $leap = (($year % 400 == 0) || (($year % 4 == 0) && ($year % 100))) ? 1 : 0;
$mdays = array( 31, ($leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); $mdays = [ 31, ($leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
# Some boundary checks # Some boundary checks
if($year < $epoch || $year > 9999) return 0; if ($year < $epoch || $year > 9999) {
if($month < 1 || $month > 12) return 0; return 0;
if($day < 1 || $day > $mdays[ $month - 1 ]) return 0; }
if ($month < 1 || $month > 12) {
return 0;
}
if ($day < 1 || $day > $mdays[ $month - 1 ]) {
return 0;
}
# Accumulate the number of days since the epoch. # Accumulate the number of days since the epoch.
$days = $day; # Add days for current month $days = $day; # Add days for current month
$days += array_sum( array_slice($mdays, 0, $month-1 ) ); # Add days for past months $days += array_sum(array_slice($mdays, 0, $month - 1)); # Add days for past months
$days += $range * 365; # Add days for past years $days += $range * 365; # Add days for past years
$days += intval( ( $range ) / 4 ); # Add leapdays $days += intval(($range) / 4); # Add leapdays
$days -= intval( ( $range + $offset ) / 100 ); # Subtract 100 year leapdays $days -= intval(($range + $offset) / 100); # Subtract 100 year leapdays
$days += intval( ( $range + $offset + $norm ) / 400 ); # Add 400 year leapdays $days += intval(($range + $offset + $norm) / 400); # Add 400 year leapdays
$days -= $leap; # Already counted above $days -= $leap; # Already counted above
# Adjust for Excel erroneously treating 1900 as a leap year. # Adjust for Excel erroneously treating 1900 as a leap year.
if ($days > 59) { $days++;} if ($days > 59) {
$days++;
}
return $days + $seconds; return $days + $seconds;
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
} }

View File

@@ -1,8 +1,9 @@
<?php <?php
/** /**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader * @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
*/ */
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader'); DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader');

View File

@@ -18,7 +18,6 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
*/ */
/** /**
* Checks PHP version * Checks PHP version
* *
@@ -39,7 +38,6 @@ if (PHP_MAJOR_VERSION >= 7) {
exit(-1); exit(-1);
} }
define('ITOP_DEFAULT_ENV', 'production'); define('ITOP_DEFAULT_ENV', 'production');
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance'); define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
define('READONLY_MODE_FILE', APPROOT.'data/.readonly'); define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
@@ -60,8 +58,7 @@ if (!isset($bBypassMaintenance)) {
$bBypassMaintenance = isset($_REQUEST['maintenance']) ? boolval($_REQUEST['maintenance']) : false; $bBypassMaintenance = isset($_REQUEST['maintenance']) ? boolval($_REQUEST['maintenance']) : false;
} }
if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance) if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance) {
{
$sTitle = 'Maintenance'; $sTitle = 'Maintenance';
$sMessage = 'This application is currently under maintenance.'; $sMessage = 'This application is currently under maintenance.';
@@ -70,8 +67,7 @@ if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
include(APPROOT.'application/maintenancemsg.php'); include(APPROOT.'application/maintenancemsg.php');
$sSAPIName = strtoupper(trim(PHP_SAPI)); $sSAPIName = strtoupper(trim(PHP_SAPI));
switch (true) switch (true) {
{
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/pages/ajax.searchform.php'): case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/pages/ajax.searchform.php'):
_MaintenanceHtmlMessage($sMessage); _MaintenanceHtmlMessage($sMessage);
break; break;
@@ -102,6 +98,7 @@ if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
* *
* @return bool * @return bool
*/ */
function EndsWith($haystack, $needle) { function EndsWith($haystack, $needle)
{
return substr_compare($haystack, $needle, -strlen($needle)) === 0; return substr_compare($haystack, $needle, -strlen($needle)) === 0;
} }

View File

@@ -1,2 +1,3 @@
<?php <?php
echo 'Access denied'; echo 'Access denied';

View File

@@ -1,4 +1,5 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2024 Combodo SAS * @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
@@ -67,9 +68,8 @@ class DbConnectionWrapper
if (is_null($oMysqli)) { if (is_null($oMysqli)) {
// Reset to standard connection // Reset to standard connection
static::$oDbCnxMockableForQuery = static::$oDbCnxStandard; static::$oDbCnxMockableForQuery = static::$oDbCnxStandard;
} } else {
else {
static::$oDbCnxMockableForQuery = $oMysqli; static::$oDbCnxMockableForQuery = $oMysqli;
} }
} }
} }

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