Merge branch 'support/3.2' into develop

This commit is contained in:
odain
2025-11-07 20:33:14 +01:00
1837 changed files with 33034 additions and 34549 deletions

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
} }
} }

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 (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/>
/** /**
* Class ApplicationContext * Class ApplicationContext
* *
@@ -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
* *
@@ -115,11 +114,10 @@ class ApplicationContext
*/ */
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();
} }
@@ -133,36 +131,29 @@ class ApplicationContext
*/ */
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();
@@ -185,8 +176,7 @@ class ApplicationContext
*/ */
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;
@@ -205,9 +195,8 @@ class ApplicationContext
} }
// 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);
@@ -278,9 +267,8 @@ 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;
@@ -301,8 +289,7 @@ class ApplicationContext
*/ */
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,21 +305,16 @@ 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';
} }
} }
@@ -394,7 +372,7 @@ class 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);
@@ -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)) if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) {
{
return self::$m_aPluginProperties[$sPluginClass]; return self::$m_aPluginProperties[$sPluginClass];
} } else {
else return [];
{
return array();
} }
} }

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
@@ -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
} }
/** /**
@@ -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,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 "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,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,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.
@@ -41,11 +42,11 @@ abstract class DashboardLayout
public static function GetInfo() public static function GetInfo()
{ {
return array( return [
'label' => '', 'label' => '',
'icon' => '', 'icon' => '',
'description' => '', 'description' => '',
); ];
} }
} }
@@ -63,16 +64,12 @@ 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++;
@@ -82,22 +79,17 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
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++;
@@ -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

@@ -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

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
@@ -77,7 +78,6 @@ class CoreCannotSaveObjectException extends CoreException
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).')';

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

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

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

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

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
@@ -8,7 +9,7 @@ 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,7 +9,7 @@ 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

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,10 +20,10 @@ 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)

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

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 (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;
@@ -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);
} }

File diff suppressed because it is too large Load Diff

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,11 +67,9 @@ 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();
@@ -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,8 +91,7 @@ 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;
@@ -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,11 +64,9 @@ 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();

View File

@@ -23,7 +23,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
*/ */
public function ListSupportedLoginModes() public function ListSupportedLoginModes()
{ {
return array('form'); return ['form'];
} }
/** /**
@@ -34,10 +34,8 @@ 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');
@@ -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,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/>
/** /**
* 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 = '';
@@ -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,26 +704,21 @@ 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;
@@ -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());
} }
@@ -964,23 +874,15 @@ class LoginWebPage extends NiceWebPage
*/ */
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();
@@ -1171,23 +1042,24 @@ class LoginWebPage extends NiceWebPage
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,8 +33,7 @@ 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(
@@ -42,12 +41,9 @@ function _MaintenanceSetupPageMessage($sTitle, $sMessage)
// 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 (C) 2010-2024 Combodo SAS // Copyright (C) 2010-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -118,25 +119,25 @@ 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)
{ {
@@ -149,7 +150,7 @@ abstract class NewsroomProviderBase implements iNewsroomProvider
*/ */
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()

View File

@@ -1,4 +1,5 @@
<?php <?php
class PortalDispatcher class PortalDispatcher
{ {
protected $sPortalid; protected $sPortalid;
@@ -21,25 +22,20 @@ 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;
} }
} }
@@ -49,12 +45,9 @@ class PortalDispatcher
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;

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.
@@ -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()
{ {
@@ -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,41 +152,39 @@ 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! // Must a string otherwise it can be evaluated to 'true' and defaults to "standard" refresh rate!
$aExtraParams['auto_reload'] = (string)$iRate; $aExtraParams['auto_reload'] = (string)$iRate;
} }
@@ -198,12 +196,9 @@ class ShortcutOQL extends Shortcut
$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());
} }
@@ -226,12 +221,9 @@ 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);

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(u) cache
apc_clear_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) {
catch (MySQLException $e) {
IssueLog::Debug($e->getMessage()); IssueLog::Debug($e->getMessage());
throw new MySQLException('Could not connect to the DB server', []); 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
* *
@@ -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',
] ],
], ],
]; ];
} }
@@ -63,8 +64,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'];
@@ -85,8 +85,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
} }
@@ -201,8 +200,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'];
@@ -258,13 +256,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().'/';
@@ -330,10 +331,8 @@ 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;
} }
@@ -343,8 +342,7 @@ class ThemeHandler
$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)) {
@@ -354,22 +352,17 @@ class ThemeHandler
} }
} }
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 =
@@ -381,14 +374,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);
@@ -413,13 +408,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();
@@ -461,8 +457,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);
@@ -497,14 +492,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]);
} }
} }
@@ -513,17 +505,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);
@@ -555,7 +544,7 @@ 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
@@ -586,10 +575,8 @@ 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);
} }
} }
@@ -622,40 +609,26 @@ CSS;
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;
} }
} }
@@ -676,32 +649,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;
} }
} }
@@ -726,41 +690,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);
} }
@@ -770,7 +724,7 @@ CSS;
'aCompleteUrls' => $aCompleteUrls, 'aCompleteUrls' => $aCompleteUrls,
'aToCompleteUrls' => $aToCompleteUrls, 'aToCompleteUrls' => $aToCompleteUrls,
'aMissingVariables' => $aMissingVariables, 'aMissingVariables' => $aMissingVariables,
'aFoundVariables' => $aFoundVariables 'aFoundVariables' => $aFoundVariables,
]; ];
} }
@@ -786,8 +740,7 @@ CSS;
{ {
$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;
@@ -799,8 +752,7 @@ CSS;
$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, "\"'");
@@ -814,17 +766,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.
@@ -843,16 +792,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;
@@ -867,8 +813,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;
@@ -892,8 +837,7 @@ 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);
@@ -918,8 +862,7 @@ 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 {
@@ -952,8 +895,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));
} }
@@ -982,18 +924,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));
} }
} }
@@ -1009,10 +947,10 @@ 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 = [];
foreach ($aVariableFiles as $sVariableFile)
{ {
$aVariablesResults = [];
foreach ($aVariableFiles as $sVariableFile) {
foreach ($aImportsPaths as $sPath) { foreach ($aImportsPaths as $sPath) {
$sFilePath = $sPath.'/'.$sVariableFile; $sFilePath = $sPath.'/'.$sVariableFile;
$sImportedFile = realpath($sFilePath); $sImportedFile = realpath($sFilePath);
@@ -1034,4 +972,3 @@ CSS;
} }
} }

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,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');
@@ -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();
} }
@@ -574,14 +599,14 @@ EOF
$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);");
} }
@@ -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();
} elseif (!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,8 +792,8 @@ 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
} }
/** /**
@@ -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 '';
} }
} }
@@ -905,17 +922,16 @@ JS
// 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();
@@ -941,15 +957,13 @@ 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,16 +976,17 @@ 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);
@@ -980,14 +995,16 @@ HTML
$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,8 +1036,7 @@ 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>');
} }
@@ -1030,7 +1045,8 @@ JS
$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();
$aNodes = array();
while($oObj = $oSet->Fetch())
{ {
$aTree = [];
$aNodes = [];
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,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.
@@ -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,7 +39,7 @@ 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:
@@ -47,8 +48,7 @@ class UILinksWidgetDirect
$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;
@@ -57,15 +57,12 @@ class UILinksWidgetDirect
$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,7 +133,7 @@ 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);
@@ -149,16 +142,13 @@ JS
$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,38 +248,30 @@ 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());
@@ -296,12 +280,11 @@ HTML
$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,8 +294,7 @@ 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()));
} }
@@ -325,15 +307,15 @@ HTML
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,8 +330,7 @@ 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();
@@ -367,10 +348,9 @@ 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,18 +366,16 @@ 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;
@@ -413,26 +391,22 @@ 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
} }
@@ -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,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.
@@ -49,7 +50,7 @@ class UIPasswordWidget
* @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>
@@ -106,15 +110,12 @@ 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,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.
@@ -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
* *
@@ -36,51 +36,53 @@ class UIWizard
{ {
$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);
} }
@@ -88,17 +90,14 @@ class UIWizard
$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++;
@@ -141,8 +140,7 @@ $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";
@@ -166,39 +164,32 @@ $sJSHandlerCode
*/ */
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(); $aMandatoryAttributes = [];
// Some attributes are always mandatory independently of the state machine (if any) // Some attributes are always mandatory independently of the state machine (if any)
foreach(MetaModel::GetAttributesList($this->m_sClass) as $sAttCode) foreach (MetaModel::GetAttributesList($this->m_sClass) as $sAttCode) {
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() && if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() &&
$oAttDef->IsWritable() && ($sAttCode != $sStateAttCode) ) $oAttDef->IsWritable() && ($sAttCode != $sStateAttCode)) {
{
$aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY; $aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY;
} }
} }
// Now check the attributes that are mandatory in the specified state // Now check the attributes that are mandatory in the specified state
if ( (!empty($this->m_sTargetState)) && (count($aStates[$this->m_sTargetState]['attribute_list']) > 0) ) 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;
} }
} }
@@ -209,17 +200,14 @@ $sJSHandlerCode
// 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] = '';
} }
} }
@@ -229,48 +217,39 @@ $sJSHandlerCode
// 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);
@@ -326,4 +300,3 @@ $sJSHandlerCode
} }
} }
?>

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.
@@ -31,31 +32,31 @@ 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_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 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", array("allowed_values"=>null, "sql"=>"menu_code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); 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", array("allowed_values"=>null, "sql"=>"contents", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); 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', array ( 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',
)); ]);
} }
/** /**
@@ -67,4 +68,3 @@ class UserDashboard extends DBObject
$this->DBDelete($oDeletionPlan); $this->DBDelete($oDeletionPlan);
} }
} }
?>

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.
@@ -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']);
} }
/** /**

View File

@@ -1,23 +1,31 @@
<?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()
{ {
@@ -64,8 +72,14 @@ 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());
@@ -90,15 +104,14 @@ Class XLSXWriter
$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;
@@ -107,13 +120,15 @@ Class XLSXWriter
$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__.".");
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, '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'); fwrite($fd, '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">');
@@ -130,20 +145,16 @@ Class XLSXWriter
fwrite($fd, '<col collapsed="false" hidden="false" max="1025" min="1" style="0" width="19"/>'); fwrite($fd, '<col collapsed="false" hidden="false" max="1025" min="1" style="0" width="19"/>');
fwrite($fd, '</cols>'); fwrite($fd, '</cols>');
fwrite($fd, '<sheetData>'); fwrite($fd, '<sheetData>');
if (!empty($header_row)) 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>');
@@ -162,7 +173,7 @@ Class XLSXWriter
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';
@@ -185,7 +196,10 @@ 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">');
@@ -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,12 +278,14 @@ 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, '<sst count="'.($this->shared_string_count).'" uniqueCount="'.count($this->shared_strings).'" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'); 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) foreach ($this->shared_strings as $s => $c) {
{
fwrite($fd, '<si><t>'.self::xmlspecialchars($s).'</t></si>'); fwrite($fd, '<si><t>'.self::xmlspecialchars($s).'</t></si>');
} }
fwrite($fd, '</sst>'); fwrite($fd, '</sst>');
@@ -408,12 +421,10 @@ Class XLSXWriter
$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);
} }
@@ -421,9 +432,15 @@ Class XLSXWriter
//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
@@ -436,12 +453,18 @@ Class XLSXWriter
# 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
@@ -453,15 +476,11 @@ Class XLSXWriter
$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

@@ -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,8 +68,7 @@ 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;
} }
} }

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/>
/** /**
* Various dev/debug helpers * Various dev/debug helpers
* TODO: cleanup or at least re-organize * TODO: cleanup or at least re-organize
@@ -25,7 +25,6 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
/** /**
* MyHelpers * MyHelpers
* *
@@ -35,28 +34,23 @@ class MyHelpers
{ {
public static function CheckValueInArray($sDescription, $value, $aData) public static function CheckValueInArray($sDescription, $value, $aData)
{ {
if (!in_array($value, $aData)) if (!in_array($value, $aData)) {
{
self::HandleWrongValue($sDescription, $value, $aData); self::HandleWrongValue($sDescription, $value, $aData);
} }
} }
public static function CheckKeyInArray($sDescription, $key, $aData) public static function CheckKeyInArray($sDescription, $key, $aData)
{ {
if (!array_key_exists($key, $aData)) if (!array_key_exists($key, $aData)) {
{
self::HandleWrongValue($sDescription, $key, array_keys($aData)); self::HandleWrongValue($sDescription, $key, array_keys($aData));
} }
} }
public static function HandleWrongValue($sDescription, $value, $aData) public static function HandleWrongValue($sDescription, $value, $aData)
{ {
if (count($aData) == 0) if (count($aData) == 0) {
{
$sArrayDesc = "{}"; $sArrayDesc = "{}";
} } else {
else
{
$sArrayDesc = "{".implode(", ", $aData)."}"; $sArrayDesc = "{".implode(", ", $aData)."}";
} }
// exit! // exit!
@@ -76,11 +70,12 @@ class MyHelpers
*/ */
public static function MakeSQLComment($aHash) public static function MakeSQLComment($aHash)
{ {
if (empty($aHash)) return ""; if (empty($aHash)) {
return "";
}
$sComment = ""; $sComment = "";
{ {
foreach($aHash as $sKey=>$sValue) foreach ($aHash as $sKey => $sValue) {
{
$sComment .= "\n-- ".$sKey."=>".$sValue; $sComment .= "\n-- ".$sKey."=>".$sValue;
} }
} }
@@ -90,12 +85,9 @@ class MyHelpers
public static function var_dump_html($aWords, $bFullDisplay = false) public static function var_dump_html($aWords, $bFullDisplay = false)
{ {
echo "<pre>\n"; echo "<pre>\n";
if ($bFullDisplay) if ($bFullDisplay) {
{
print_r($aWords); // full dump! print_r($aWords); // full dump!
} } else {
else
{
var_dump($aWords); // truncate things when they are too big var_dump($aWords); // truncate things when they are too big
} }
echo "\n</pre>\n"; echo "\n</pre>\n";
@@ -123,9 +115,10 @@ class MyHelpers
{ {
$aLines1 = explode("\n", $s1); $aLines1 = explode("\n", $s1);
$aLines2 = explode("\n", $s2); $aLines2 = explode("\n", $s2);
for ($i = 0 ; $i < min(count($aLines1), count($aLines2)) ; $i++) for ($i = 0 ; $i < min(count($aLines1), count($aLines2)) ; $i++) {
{ if ($aLines1[$i] != $aLines2[$i]) {
if ($aLines1[$i] != $aLines2[$i]) return $i; return $i;
}
} }
return false; return false;
} }
@@ -142,9 +135,10 @@ class MyHelpers
// do not work fine with multiline strings // do not work fine with multiline strings
$iLen1 = strlen($s1); $iLen1 = strlen($s1);
$iLen2 = strlen($s2); $iLen2 = strlen($s2);
for ($i = 0 ; $i < min($iLen1, $iLen2) ; $i++) for ($i = 0 ; $i < min($iLen1, $iLen2) ; $i++) {
{ if ($s1[$i] !== $s2[$i]) {
if ($s1[$i] !== $s2[$i]) return $i; return $i;
}
} }
return false; return false;
} }
@@ -154,9 +148,10 @@ class MyHelpers
// do not work fine with multiline strings // do not work fine with multiline strings
$iLen1 = strlen($s1); $iLen1 = strlen($s1);
$iLen2 = strlen($s2); $iLen2 = strlen($s2);
for ($i = 0 ; $i < min(strlen($s1), strlen($s2)) ; $i++) for ($i = 0 ; $i < min(strlen($s1), strlen($s2)) ; $i++) {
{ if ($s1[$iLen1 - $i - 1] !== $s2[$iLen2 - $i - 1]) {
if ($s1[$iLen1 - $i - 1] !== $s2[$iLen2 - $i - 1]) return array($iLen1 - $i, $iLen2 - $i); return [$iLen1 - $i, $iLen2 - $i];
}
} }
return false; return false;
} }
@@ -177,8 +172,7 @@ class MyHelpers
protected static function string_cmp_html($s1, $s2, $sHighlight) protected static function string_cmp_html($s1, $s2, $sHighlight)
{ {
$iDiffPos = self::first_diff($s1, $s2); $iDiffPos = self::first_diff($s1, $s2);
if ($iDiffPos === false) if ($iDiffPos === false) {
{
echo "strings are identical"; echo "strings are identical";
return; return;
} }
@@ -203,40 +197,34 @@ class MyHelpers
public static function var_cmp_html($var1, $var2, $sHighlight = 'color:red; font-weight:bold;') public static function var_cmp_html($var1, $var2, $sHighlight = 'color:red; font-weight:bold;')
{ {
if (is_object($var1)) if (is_object($var1)) {
{
return self::object_cmp_html($var1, $var2, $sHighlight); return self::object_cmp_html($var1, $var2, $sHighlight);
} } elseif (count(explode("\n", $var1)) > 1) {
else if (count(explode("\n", $var1)) > 1)
{
// multiline string // multiline string
return self::text_cmp_html($var1, $var2, $sHighlight); return self::text_cmp_html($var1, $var2, $sHighlight);
} } else {
else
{
return self::string_cmp_html($var1, $var2, $sHighlight); return self::string_cmp_html($var1, $var2, $sHighlight);
} }
} }
public static function get_callstack($iLevelsToIgnore = 0, $aCallStack = null) public static function get_callstack($iLevelsToIgnore = 0, $aCallStack = null)
{ {
if ($aCallStack == null) $aCallStack = debug_backtrace(); if ($aCallStack == null) {
$aCallStack = debug_backtrace();
}
$aCallStack = array_slice($aCallStack, $iLevelsToIgnore); $aCallStack = array_slice($aCallStack, $iLevelsToIgnore);
$aDigestCallStack = array(); $aDigestCallStack = [];
$bFirstLine = true; $bFirstLine = true;
foreach ($aCallStack as $aCallInfo) foreach ($aCallStack as $aCallInfo) {
{
$sLine = empty($aCallInfo['line']) ? "" : $aCallInfo['line']; $sLine = empty($aCallInfo['line']) ? "" : $aCallInfo['line'];
$sFile = empty($aCallInfo['file']) ? "" : $aCallInfo['file']; $sFile = empty($aCallInfo['file']) ? "" : $aCallInfo['file'];
if ($sFile != '') if ($sFile != '') {
{
$sFile = str_replace('\\', '/', $sFile); $sFile = str_replace('\\', '/', $sFile);
$sAppRoot = str_replace('\\', '/', APPROOT); $sAppRoot = str_replace('\\', '/', APPROOT);
$iPos = strpos($sFile, $sAppRoot); $iPos = strpos($sFile, $sAppRoot);
if ($iPos !== false) if ($iPos !== false) {
{
$sFile = substr($sFile, strlen($sAppRoot)); $sFile = substr($sFile, strlen($sAppRoot));
} }
} }
@@ -244,25 +232,21 @@ class MyHelpers
$sType = empty($aCallInfo['type']) ? "" : $aCallInfo['type']; $sType = empty($aCallInfo['type']) ? "" : $aCallInfo['type'];
$sFunction = empty($aCallInfo['function']) ? "" : $aCallInfo['function']; $sFunction = empty($aCallInfo['function']) ? "" : $aCallInfo['function'];
if ($bFirstLine) if ($bFirstLine) {
{
$bFirstLine = false; $bFirstLine = false;
// For this line do not display the "function name" because // For this line do not display the "function name" because
// that will be the name of our error handler for sure ! // that will be the name of our error handler for sure !
$sFunctionInfo = "N/A"; $sFunctionInfo = "N/A";
} } else {
else
{
$args = ''; $args = '';
if (empty($aCallInfo['args'])) $aCallInfo['args'] = array(); if (empty($aCallInfo['args'])) {
foreach ($aCallInfo['args'] as $a) $aCallInfo['args'] = [];
{ }
if (!empty($args)) foreach ($aCallInfo['args'] as $a) {
{ if (!empty($args)) {
$args .= ', '; $args .= ', ';
} }
switch (gettype($a)) switch (gettype($a)) {
{
case 'integer': case 'integer':
case 'double': case 'double':
$args .= $a; $args .= $a;
@@ -292,7 +276,7 @@ class MyHelpers
} }
$sFunctionInfo = "$sClass$sType$sFunction($args)"; $sFunctionInfo = "$sClass$sType$sFunction($args)";
} }
$aDigestCallStack[] = array('File'=>$sFile, 'Line'=>$sLine, 'Function'=>$sFunctionInfo); $aDigestCallStack[] = ['File' => $sFile, 'Line' => $sLine, 'Function' => $sFunctionInfo];
} }
return $aDigestCallStack; return $aDigestCallStack;
} }
@@ -311,9 +295,8 @@ class MyHelpers
public static function get_callstack_text($iLevelsToIgnore = 0, $aCallStack = null) public static function get_callstack_text($iLevelsToIgnore = 0, $aCallStack = null)
{ {
$aDigestCallStack = self::get_callstack($iLevelsToIgnore, $aCallStack); $aDigestCallStack = self::get_callstack($iLevelsToIgnore, $aCallStack);
$aRes = array(); $aRes = [];
foreach ($aDigestCallStack as $aCall) foreach ($aDigestCallStack as $aCall) {
{
$aRes[] = $aCall['File'].' at '.$aCall['Line'].', '.$aCall['Function']; $aRes[] = $aCall['File'].' at '.$aCall['Line'].', '.$aCall['Function'];
} }
return implode("\n", $aRes); return implode("\n", $aRes);
@@ -325,10 +308,16 @@ class MyHelpers
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
public static function make_table_from_assoc_array(&$aData) public static function make_table_from_assoc_array(&$aData)
{ {
if (!is_array($aData)) throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not an array"); if (!is_array($aData)) {
throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not an array");
}
$aFirstRow = reset($aData); $aFirstRow = reset($aData);
if (count($aData) == 0) return ''; if (count($aData) == 0) {
if (!is_array($aFirstRow)) throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not a bi-dimensional array"); return '';
}
if (!is_array($aFirstRow)) {
throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not a bi-dimensional array");
}
$sOutput = ""; $sOutput = "";
$sOutput .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\">\n"; $sOutput .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\">\n";
@@ -368,7 +357,9 @@ class MyHelpers
} }
public static function debug_breakpoint_notempty($arg) public static function debug_breakpoint_notempty($arg)
{ {
if (empty($arg)) return; if (empty($arg)) {
return;
}
echo "<H1> Debug breakpoint (triggered on non-empty value) </H1>\n"; echo "<H1> Debug breakpoint (triggered on non-empty value) </H1>\n";
MyHelpers::var_dump_html($arg); MyHelpers::var_dump_html($arg);
MyHelpers::dump_callstack(); MyHelpers::dump_callstack();
@@ -381,7 +372,7 @@ class MyHelpers
*/ */
public static function xmlentities($string) public static function xmlentities($string)
{ {
return str_replace( array( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string ); return str_replace([ '&', '"', "'", '<', '>' ], [ '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ], $string);
} }
/** /**
@@ -399,10 +390,14 @@ class MyHelpers
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
public static function beautifulstr($sLongString, $iMaxLen, $bShowLen = false, $bShowTooltip = true) public static function beautifulstr($sLongString, $iMaxLen, $bShowLen = false, $bShowTooltip = true)
{ {
if (!is_string($sLongString)) throw new CoreException("beautifulstr: expect a string as 1st argument"); if (!is_string($sLongString)) {
throw new CoreException("beautifulstr: expect a string as 1st argument");
}
// Nothing to do if the string is short // Nothing to do if the string is short
if (strlen($sLongString) <= $iMaxLen) return $sLongString; if (strlen($sLongString) <= $iMaxLen) {
return $sLongString;
}
// Truncate the string // Truncate the string
$sSuffix = "..."; $sSuffix = "...";
@@ -456,8 +451,11 @@ class Str
} }
public static function gpc2pure($gpc) public static function gpc2pure($gpc)
{ {
if (ini_get('magic_quotes_sybase')) $pure = str_replace("''", "'", $gpc); if (ini_get('magic_quotes_sybase')) {
else $pure = $gpc; $pure = str_replace("''", "'", $gpc);
} else {
$pure = $gpc;
}
return $pure; return $pure;
} }
public static function html2pure($html) public static function html2pure($html)
@@ -477,7 +475,9 @@ class Str
} }
public static function pure2sql($pure, $maxLength = false) public static function pure2sql($pure, $maxLength = false)
{ {
if ($maxLength) $pure = substr($pure, 0, $maxLength); if ($maxLength) {
$pure = substr($pure, 0, $maxLength);
}
return (STR_SYBASE) return (STR_SYBASE)
? str_replace("'", "''", $pure) ? str_replace("'", "''", $pure)
: addslashes($pure); : addslashes($pure);
@@ -485,7 +485,9 @@ class Str
public static function sql2html($sql, $maxLength = false) public static function sql2html($sql, $maxLength = false)
{ {
$pure = self::sql2pure($sql); $pure = self::sql2pure($sql);
if ($maxLength) $pure = substr($pure, 0, $maxLength); if ($maxLength) {
$pure = substr($pure, 0, $maxLength);
}
return self::pure2html($pure); return self::pure2html($pure);
} }
public static function sql2pure($sql) public static function sql2pure($sql)
@@ -507,7 +509,7 @@ class Str
protected static function xmlentities($string) protected static function xmlentities($string)
{ {
return str_replace( array( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string ); return str_replace([ '&', '"', "'", '<', '>' ], [ '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ], $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
@@ -17,64 +18,64 @@ class TemporaryObjectDescriptor extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array( $aParams = [
'category' => 'core', 'category' => 'core',
'key_type' => 'autoincrement', 'key_type' => 'autoincrement',
'name_attcode' => array('item_class', 'temp_id'), 'name_attcode' => ['item_class', 'temp_id'],
'image_attcode' => '', 'image_attcode' => '',
'state_attcode' => '', 'state_attcode' => '',
'reconc_keys' => array(''), 'reconc_keys' => [''],
'db_table' => 'priv_temporary_object_descriptor', 'db_table' => 'priv_temporary_object_descriptor',
'db_key_field' => 'id', 'db_key_field' => 'id',
'db_finalclass_field' => '', 'db_finalclass_field' => '',
'style' => new ormStyle(null, null, null, null, null, null), 'style' => new ormStyle(null, null, null, null, null, null),
'indexes' => array( 'indexes' => [
1 => 1 =>
array( [
0 => 'temp_id', 0 => 'temp_id',
), ],
2 => 2 =>
array( [
0 => 'item_class', 0 => 'item_class',
1 => 'item_id', 1 => 'item_id',
), ],
), ],
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes(); MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeDateTime('expiration_date', array('sql' => 'expiration_date', 'is_null_allowed' => false, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeDateTime('expiration_date', ['sql' => 'expiration_date', 'is_null_allowed' => false, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeString('temp_id', array('sql' => 'temp_id', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeString('temp_id', ['sql' => 'temp_id', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeString('item_class', array('sql' => 'item_class', 'is_null_allowed' => false, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeString('item_class', ['sql' => 'item_class', 'is_null_allowed' => false, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeObjectKey('item_id', array('class_attcode' => 'item_class', 'sql' => 'item_id', 'is_null_allowed' => true, 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeObjectKey('item_id', ['class_attcode' => 'item_class', 'sql' => 'item_id', 'is_null_allowed' => true, 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeDateTime('creation_date', array('sql' => 'creation_date', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeDateTime('creation_date', ['sql' => 'creation_date', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeString('host_class', array('sql' => 'host_class', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeString('host_class', ['sql' => 'host_class', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeObjectKey('host_id', array('class_attcode' => 'host_class', 'sql' => 'host_id', 'is_null_allowed' => true, 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeObjectKey('host_id', ['class_attcode' => 'host_class', 'sql' => 'host_id', 'is_null_allowed' => true, 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeString('host_att_code', array('sql' => 'host_att_code', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => array(), 'always_load_in_tables' => false))); MetaModel::Init_AddAttribute(new AttributeString('host_att_code', ['sql' => 'host_att_code', 'is_null_allowed' => true, 'default_value' => '', 'allowed_values' => null, 'depends_on' => [], 'always_load_in_tables' => false]));
MetaModel::Init_AddAttribute(new AttributeEnum("operation", array("allowed_values" => new ValueSetEnum('create,delete'), "sql" => "operation", "default_value" => "create", "is_null_allowed" => true, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeEnum("operation", ["allowed_values" => new ValueSetEnum('create,delete'), "sql" => "operation", "default_value" => "create", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_SetZListItems('details', array( MetaModel::Init_SetZListItems('details', [
0 => 'temp_id', 0 => 'temp_id',
1 => 'item_class', 1 => 'item_class',
2 => 'item_id', 2 => 'item_id',
3 => 'creation_date', 3 => 'creation_date',
4 => 'expiration_date', 4 => 'expiration_date',
5 => 'meta', 5 => 'meta',
)); ]);
MetaModel::Init_SetZListItems('standard_search', array( MetaModel::Init_SetZListItems('standard_search', [
0 => 'temp_id', 0 => 'temp_id',
1 => 'item_class', 1 => 'item_class',
2 => 'item_id', 2 => 'item_id',
)); ]);
MetaModel::Init_SetZListItems('list', array( MetaModel::Init_SetZListItems('list', [
0 => 'temp_id', 0 => 'temp_id',
1 => 'item_class', 1 => 'item_class',
2 => 'item_id', 2 => 'item_id',
3 => 'creation_date', 3 => 'creation_date',
4 => 'expiration_date', 4 => 'expiration_date',
));; ]);
;
} }
public function DBInsertNoReload() public function DBInsertNoReload()
{ {
$this->SetCurrentDateIfNull('creation_date'); $this->SetCurrentDateIfNull('creation_date');
@@ -82,7 +83,6 @@ class TemporaryObjectDescriptor extends DBObject
return parent::DBInsertNoReload(); return parent::DBInsertNoReload();
} }
/** /**
* Set/Update all of the '_item' fields * Set/Update all of the '_item' fields
* *

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.
@@ -30,7 +31,6 @@ use Combodo\iTop\Service\Router\Router;
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
require_once(APPROOT.'/core/asynctask.class.inc.php'); require_once(APPROOT.'/core/asynctask.class.inc.php');
require_once(APPROOT.'/core/email.class.inc.php'); require_once(APPROOT.'/core/email.class.inc.php');
@@ -47,8 +47,8 @@ abstract class Action extends cmdbAbstractObject
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "grant_by_profile,core/cmdb", "category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
@@ -59,14 +59,14 @@ abstract class Action extends cmdbAbstractObject
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "realclass", "db_finalclass_field" => "realclass",
"style" => new ormStyle("ibo-dm-class--Action", "ibo-dm-class-alt--Action", "var(--ibo-dm-class--Action--main-color)", "var(--ibo-dm-class--Action--complementary-color)", null, '../images/icons/icons8-in-transit.svg'), "style" => new ormStyle("ibo-dm-class--Action", "ibo-dm-class-alt--Action", "var(--ibo-dm-class--Action--main-color)", "var(--ibo-dm-class--Action--complementary-color)", null, '../images/icons/icons8-in-transit.svg'),
); ];
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" => true, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array( MetaModel::Init_AddAttribute(new AttributeEnum("status", [
"allowed_values" => new ValueSetEnum(array('test' => 'Being tested', 'enabled' => 'In production', 'disabled' => 'Inactive')), "allowed_values" => new ValueSetEnum(['test' => 'Being tested', 'enabled' => 'In production', 'disabled' => 'Inactive']),
"styled_values" => [ "styled_values" => [
'test' => new ormStyle('ibo-dm-enum--Action-status-test', 'ibo-dm-enum-alt--Action-status-test', 'var(--ibo-dm-enum--Action-status-test--main-color)', 'var(--ibo-dm-enum--Action-status-test--complementary-color)', null, null), 'test' => new ormStyle('ibo-dm-enum--Action-status-test', 'ibo-dm-enum-alt--Action-status-test', 'var(--ibo-dm-enum--Action-status-test--main-color)', 'var(--ibo-dm-enum--Action-status-test--complementary-color)', null, null),
'enabled' => new ormStyle('ibo-dm-enum--Action-status-enabled', 'ibo-dm-enum-alt--Action-status-enabled', 'var(--ibo-dm-enum--Action-status-enabled--main-color)', 'var(--ibo-dm-enum--Action-status-enabled--complementary-color)', 'fas fa-check', null), 'enabled' => new ormStyle('ibo-dm-enum--Action-status-enabled', 'ibo-dm-enum-alt--Action-status-enabled', 'var(--ibo-dm-enum--Action-status-enabled--main-color)', 'var(--ibo-dm-enum--Action-status-enabled--complementary-color)', 'fas fa-check', null),
@@ -76,21 +76,23 @@ abstract class Action extends cmdbAbstractObject
"sql" => "status", "sql" => "status",
"default_value" => "test", "default_value" => "test",
"is_null_allowed" => false, "is_null_allowed" => false,
"depends_on" => array(), "depends_on" => [],
))); ]));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list", MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "action_id", "ext_key_to_remote" => "trigger_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => array(), "display_style" => 'property'))); "trigger_list",
MetaModel::Init_AddAttribute(new AttributeEnum("asynchronous", array("allowed_values" => new ValueSetEnum(['use_global_setting' => 'Use global settings','yes' => 'Yes' ,'no' => 'No']), "sql" => "asynchronous", "default_value" => 'use_global_setting', "is_null_allowed" => false, "depends_on" => array()))); ["linked_class" => "lnkTriggerAction", "ext_key_to_me" => "action_id", "ext_key_to_remote" => "trigger_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "display_style" => 'property']
));
MetaModel::Init_AddAttribute(new AttributeEnum("asynchronous", ["allowed_values" => new ValueSetEnum(['use_global_setting' => 'Use global settings','yes' => 'Yes' ,'no' => 'No']), "sql" => "asynchronous", "default_value" => 'use_global_setting', "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
// - Attributes to be displayed for the complete details // - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); MetaModel::Init_SetZListItems('details', ['name', 'description', 'status', 'trigger_list']);
// - Attributes to be displayed for a list // - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); MetaModel::Init_SetZListItems('list', ['finalclass', 'name', 'description', 'status']);
// Search criteria // Search criteria
// - Default criteria of the search form // - Default criteria of the search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status')); MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'status']);
} }
@@ -111,8 +113,7 @@ abstract class Action extends cmdbAbstractObject
*/ */
public function IsActive() public function IsActive()
{ {
switch($this->Get('status')) switch ($this->Get('status')) {
{
case 'enabled': case 'enabled':
case 'test': case 'test':
return true; return true;
@@ -131,8 +132,7 @@ abstract class Action extends cmdbAbstractObject
*/ */
public function IsBeingTested() public function IsBeingTested()
{ {
switch($this->Get('status')) switch ($this->Get('status')) {
{
case 'test': case 'test':
return true; return true;
@@ -282,8 +282,8 @@ abstract class ActionNotification extends Action
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "grant_by_profile,core/cmdb", "category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
@@ -293,16 +293,16 @@ abstract class ActionNotification extends Action
"db_table" => "priv_action_notification", "db_table" => "priv_action_notification",
"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();
// Display lists // Display lists
// - Attributes to be displayed for the complete details // - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); MetaModel::Init_SetZListItems('details', ['name', 'description', 'status', 'trigger_list']);
// - Attributes to be displayed for a list // - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'description', 'status')); MetaModel::Init_SetZListItems('list', ['finalclass', 'description', 'status']);
MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql"=>"language", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", ["sql" => "language", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Search criteria // Search criteria
// - Criteria of the std search form // - Criteria of the std search form
@@ -321,7 +321,8 @@ abstract class ActionNotification extends Action
* @throws \DictExceptionUnknownLanguage * @throws \DictExceptionUnknownLanguage
* @since 3.2.0 * @since 3.2.0
*/ */
public function SetNotificationLanguage($sLanguage = null, $sLanguageCode = null){ public function SetNotificationLanguage($sLanguage = null, $sLanguageCode = null)
{
$sPreviousLanguage = Dict::GetUserLanguage(); $sPreviousLanguage = Dict::GetUserLanguage();
$aPreviousPluginProperties = ApplicationContext::GetPluginProperties('QueryLocalizerPlugin'); $aPreviousPluginProperties = ApplicationContext::GetPluginProperties('QueryLocalizerPlugin');
$sLanguage = $sLanguage ?? $this->Get('language'); $sLanguage = $sLanguage ?? $this->Get('language');
@@ -348,69 +349,68 @@ class ActionEmail extends ActionNotification
* @var string * @var string
* @since 3.0.1 * @since 3.0.1
*/ */
const ENUM_HEADER_NAME_MESSAGE_ID = 'Message-ID'; public const ENUM_HEADER_NAME_MESSAGE_ID = 'Message-ID';
/** /**
* @var string * @var string
* @since 3.0.1 * @since 3.0.1
*/ */
const ENUM_HEADER_NAME_REFERENCES = 'References'; public const ENUM_HEADER_NAME_REFERENCES = 'References';
/** /**
* @var string * @var string
* @since 3.1.0 * @since 3.1.0
*/ */
const TEMPLATE_BODY_CONTENT = '$content$'; public const TEMPLATE_BODY_CONTENT = '$content$';
/** /**
* Wraps the 'body' of the message for previewing inside an IFRAME -- i.e. without any of the iTop stylesheets being applied * Wraps the 'body' of the message for previewing inside an IFRAME -- i.e. without any of the iTop stylesheets being applied
* @var string * @var string
* @since 3.1.0 * @since 3.1.0
*/ */
const CONTENT_HIGHLIGHT = '<div style="border:2px dashed #6800ff;position:relative;padding:2px;margin-top:14px;"><div style="background-color:#6800ff;color:#fff;font-family:Courier New, sans-serif;font-size:14px;line-height:16px;padding:3px;display:block;position:absolute;top:-22px;right:0;">$content$</div>%s</div>'; public const CONTENT_HIGHLIGHT = '<div style="border:2px dashed #6800ff;position:relative;padding:2px;margin-top:14px;"><div style="background-color:#6800ff;color:#fff;font-family:Courier New, sans-serif;font-size:14px;line-height:16px;padding:3px;display:block;position:absolute;top:-22px;right:0;">$content$</div>%s</div>';
/** /**
* Wraps a placeholder of the email's body for previewing inside an IFRAME -- i.e. without any of the iTop stylesheets being applied * Wraps a placeholder of the email's body for previewing inside an IFRAME -- i.e. without any of the iTop stylesheets being applied
* @var string * @var string
*/ */
const FIELD_HIGHLIGHT = '<span style="background-color:#6800ff;color:#fff;font-size:smaller;font-family:Courier New, sans-serif;padding:2px;">\\$$1\\$</span>'; public const FIELD_HIGHLIGHT = '<span style="background-color:#6800ff;color:#fff;font-size:smaller;font-family:Courier New, sans-serif;padding:2px;">\\$$1\\$</span>';
/** /**
* @inheritDoc * @inheritDoc
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "grant_by_profile,core/cmdb,application", "category" => "grant_by_profile,core/cmdb,application",
"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_action_email", "db_table" => "priv_action_email",
"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-mailing.svg'), 'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-mailing.svg'),
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes(); MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeEmailAddress("test_recipient", array("allowed_values" => null, "sql" => "test_recipient", "default_value" => "", "is_null_allowed" => true, "depends_on" => array()))); MetaModel::Init_AddAttribute(new AttributeEmailAddress("test_recipient", ["allowed_values" => null, "sql" => "test_recipient", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("from", array("allowed_values" => null, "sql" => "from", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("from_label", array("allowed_values" => null, "sql" => "from_label", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("reply_to", array("allowed_values" => null, "sql" => "reply_to", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("reply_to_label", array("allowed_values" => null, "sql" => "reply_to_label", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeOQL("to", array("allowed_values" => null, "sql" => "to", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeOQL("cc", array("allowed_values" => null, "sql" => "cc", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeOQL("bcc", array("allowed_values" => null, "sql" => "bcc", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeTemplateString("subject", array("allowed_values" => null, "sql" => "subject", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeTemplateHTML("body", array("allowed_values" => null, "sql" => "body", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("importance", array("allowed_values" => new ValueSetEnum('low,normal,high'), "sql" => "importance", "default_value" => 'normal', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeBlob("html_template", array("is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_AddAttribute(new AttributeEnum("ignore_notify", array("allowed_values" => new ValueSetEnum('yes,no'), "sql" => "ignore_notify", "default_value" => 'yes', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("from", ["allowed_values" => null, "sql" => "from", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("from_label", ["allowed_values" => null, "sql" => "from_label", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("reply_to", ["allowed_values" => null, "sql" => "reply_to", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("reply_to_label", ["allowed_values" => null, "sql" => "reply_to_label", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeOQL("to", ["allowed_values" => null, "sql" => "to", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeOQL("cc", ["allowed_values" => null, "sql" => "cc", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeOQL("bcc", ["allowed_values" => null, "sql" => "bcc", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeTemplateString("subject", ["allowed_values" => null, "sql" => "subject", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeTemplateHTML("body", ["allowed_values" => null, "sql" => "body", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("importance", ["allowed_values" => new ValueSetEnum('low,normal,high'), "sql" => "importance", "default_value" => 'normal', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeBlob("html_template", ["is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeEnum("ignore_notify", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "ignore_notify", "default_value" => 'yes', "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
// - Attributes to be displayed for the complete details // - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array( MetaModel::Init_SetZListItems('details', [
'col:col1' => array( 'col:col1' => [
'fieldset:ActionEmail:main' => array( 'fieldset:ActionEmail:main' => [
0 => 'name', 0 => 'name',
1 => 'description', 1 => 'description',
2 => 'status', 2 => 'status',
@@ -419,14 +419,14 @@ class ActionEmail extends ActionNotification
5 => 'subject', 5 => 'subject',
6 => 'body', 6 => 'body',
// 5 => 'importance', not handled when sending the mail, better hide it then // 5 => 'importance', not handled when sending the mail, better hide it then
), ],
'fieldset:ActionEmail:trigger' => array( 'fieldset:ActionEmail:trigger' => [
0 => 'trigger_list', 0 => 'trigger_list',
1 => 'asynchronous' 1 => 'asynchronous',
), ],
), ],
'col:col2' => array( 'col:col2' => [
'fieldset:ActionEmail:recipients' => array( 'fieldset:ActionEmail:recipients' => [
0 => 'from', 0 => 'from',
1 => 'from_label', 1 => 'from_label',
2 => 'reply_to', 2 => 'reply_to',
@@ -436,17 +436,17 @@ class ActionEmail extends ActionNotification
6 => 'to', 6 => 'to',
7 => 'cc', 7 => 'cc',
8 => 'bcc', 8 => 'bcc',
), ],
), ],
)); ]);
// - Attributes to be displayed for a list // - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('status', 'to', 'subject', 'language')); MetaModel::Init_SetZListItems('list', ['status', 'to', 'subject', 'language']);
// Search criteria // Search criteria
// - Standard criteria of the search // - Standard criteria of the search
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'status', 'subject', 'language')); MetaModel::Init_SetZListItems('standard_search', ['name', 'description', 'status', 'subject', 'language']);
// - Default criteria for the search // - Default criteria for the search
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status', 'subject', 'language')); MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'status', 'subject', 'language']);
} }
// count the recipients found // count the recipients found
@@ -477,10 +477,11 @@ class ActionEmail extends ActionNotification
{ {
$oTrigger = $aArgs['trigger->object()'] ?? null; $oTrigger = $aArgs['trigger->object()'] ?? null;
$sOQL = $this->Get($sRecipAttCode); $sOQL = $this->Get($sRecipAttCode);
if (utils::IsNullOrEmptyString($sOQL)) return ''; if (utils::IsNullOrEmptyString($sOQL)) {
return '';
}
try try {
{
$oSearch = DBObjectSearch::FromOQL($sOQL); $oSearch = DBObjectSearch::FromOQL($sOQL);
if ($this->Get('ignore_notify') === 'no') { if ($this->Get('ignore_notify') === 'no') {
// In theory, it is possible to notify *any* kind of object, // In theory, it is possible to notify *any* kind of object,
@@ -492,26 +493,21 @@ class ActionEmail extends ActionNotification
} }
} }
$oSearch->AllowAllData(); $oSearch->AllowAllData();
} } catch (OQLException $e) {
catch (OQLException $e)
{
$this->m_aMailErrors[] = "query syntax error for recipient '$sRecipAttCode'"; $this->m_aMailErrors[] = "query syntax error for recipient '$sRecipAttCode'";
return $e->getMessage(); return $e->getMessage();
} }
$sClass = $oSearch->GetClass(); $sClass = $oSearch->GetClass();
// Determine the email attribute (the first one will be our choice) // Determine the email attribute (the first one will be our choice)
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
{ if ($oAttDef instanceof AttributeEmailAddress) {
if ($oAttDef instanceof AttributeEmailAddress)
{
$sEmailAttCode = $sAttCode; $sEmailAttCode = $sAttCode;
// we've got one, exit the loop // we've got one, exit the loop
break; break;
} }
} }
if (!isset($sEmailAttCode)) if (!isset($sEmailAttCode)) {
{
$this->m_aMailErrors[] = "wrong target for recipient '$sRecipAttCode'"; $this->m_aMailErrors[] = "wrong target for recipient '$sRecipAttCode'";
return "The objects of the class '$sClass' do not have any email attribute"; return "The objects of the class '$sClass' do not have any email attribute";
} }
@@ -526,13 +522,11 @@ class ActionEmail extends ActionNotification
$oSearch->AddConditionExpression(Expression::FromOQL("`$sAlias`.id NOT IN ($sSubscribedContactsOQL)")); $oSearch->AddConditionExpression(Expression::FromOQL("`$sAlias`.id NOT IN ($sSubscribedContactsOQL)"));
} }
$oSet = new DBObjectSet($oSearch, array() /* order */, $aArgs); $oSet = new DBObjectSet($oSearch, [] /* order */, $aArgs);
$aRecipients = array(); $aRecipients = [];
while ($oObj = $oSet->Fetch()) while ($oObj = $oSet->Fetch()) {
{
$sAddress = trim($oObj->Get($sEmailAttCode)); $sAddress = trim($oObj->Get($sEmailAttCode));
if (utils::IsNotNullOrEmptyString($sAddress)) if (utils::IsNotNullOrEmptyString($sAddress)) {
{
$aRecipients[] = $sAddress; $aRecipients[] = $sAddress;
$this->m_iRecipients++; $this->m_iRecipients++;
} }
@@ -551,15 +545,11 @@ class ActionEmail extends ActionNotification
*/ */
public function DoExecute($oTrigger, $aContextArgs) public function DoExecute($oTrigger, $aContextArgs)
{ {
if (MetaModel::IsLogEnabledNotification()) if (MetaModel::IsLogEnabledNotification()) {
{
$oLog = new EventNotificationEmail(); $oLog = new EventNotificationEmail();
if ($this->IsBeingTested()) if ($this->IsBeingTested()) {
{
$oLog->Set('message', 'TEST - Notification sent ('.$this->Get('test_recipient').')'); $oLog->Set('message', 'TEST - Notification sent ('.$this->Get('test_recipient').')');
} } else {
else
{
$oLog->Set('message', 'Notification pending'); $oLog->Set('message', 'Notification pending');
} }
$oLog->Set('userinfo', UserRights::GetUser()); $oLog->Set('userinfo', UserRights::GetUser());
@@ -570,44 +560,31 @@ class ActionEmail extends ActionNotification
// Must be inserted now so that it gets a valid id that will make the link // Must be inserted now so that it gets a valid id that will make the link
// between an eventual asynchronous task (queued) and the log // between an eventual asynchronous task (queued) and the log
$oLog->DBInsertNoReload(); $oLog->DBInsertNoReload();
} } else {
else
{
$oLog = null; $oLog = null;
} }
try try {
{
$sRes = $this->_DoExecute($oTrigger, $aContextArgs, $oLog); $sRes = $this->_DoExecute($oTrigger, $aContextArgs, $oLog);
if ($this->IsBeingTested()) if ($this->IsBeingTested()) {
{
$sPrefix = 'TEST ('.$this->Get('test_recipient').') - '; $sPrefix = 'TEST ('.$this->Get('test_recipient').') - ';
} } else {
else
{
$sPrefix = ''; $sPrefix = '';
} }
if ($oLog) if ($oLog) {
{
$oLog->Set('message', $sPrefix.$sRes); $oLog->Set('message', $sPrefix.$sRes);
$oLog->DBUpdate(); $oLog->DBUpdate();
} }
} } catch (Exception $e) {
catch (Exception $e) if ($oLog) {
{
if ($oLog)
{
$oLog->Set('message', 'Error: '.$e->getMessage()); $oLog->Set('message', 'Error: '.$e->getMessage());
try try {
{
$oLog->DBUpdate(); $oLog->DBUpdate();
} } catch (Exception $eSecondTryUpdate) {
catch (Exception $eSecondTryUpdate)
{
IssueLog::Error("Failed to process email ".$oLog->GetKey()." - reason: ".$e->getMessage()."\nTrace:\n".$e->getTraceAsString()); IssueLog::Error("Failed to process email ".$oLog->GetKey()." - reason: ".$e->getMessage()."\nTrace:\n".$e->getTraceAsString());
$oLog->Set('message', 'Error: more details in the log for email "'.$oLog->GetKey().'"'); $oLog->Set('message', 'Error: more details in the log for email "'.$oLog->GetKey().'"');
@@ -650,18 +627,13 @@ class ActionEmail extends ActionNotification
$oEmail->AddAttachment($aAttachment['data'], $aAttachment['filename'], $aAttachment['mime_type']); $oEmail->AddAttachment($aAttachment['data'], $aAttachment['filename'], $aAttachment['mime_type']);
} }
if (empty($this->m_aMailErrors)) if (empty($this->m_aMailErrors)) {
{ if ($this->m_iRecipients == 0) {
if ($this->m_iRecipients == 0)
{
return 'No recipient'; return 'No recipient';
} } else {
else
{
$aErrors = []; $aErrors = [];
$iRes = $oEmail->Send($aErrors, $this->IsAsynchronous() ? Email::ENUM_SEND_FORCE_ASYNCHRONOUS : Email::ENUM_SEND_FORCE_SYNCHRONOUS, $oLog); $iRes = $oEmail->Send($aErrors, $this->IsAsynchronous() ? Email::ENUM_SEND_FORCE_ASYNCHRONOUS : Email::ENUM_SEND_FORCE_SYNCHRONOUS, $oLog);
switch ($iRes) switch ($iRes) {
{
case EMAIL_SEND_OK: case EMAIL_SEND_OK:
return "Sent"; return "Sent";
@@ -721,10 +693,9 @@ class ActionEmail extends ActionNotification
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass(); $sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();
[$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage(); [$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage();
try try {
{
$this->m_iRecipients = 0; $this->m_iRecipients = 0;
$this->m_aMailErrors = array(); $this->m_aMailErrors = [];
// Determine recipients // Determine recipients
// //
@@ -744,12 +715,10 @@ class ActionEmail extends ActionNotification
$oObj = $aContextArgs['this->object()']; $oObj = $aContextArgs['this->object()'];
$aMessageContent['message_id'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_MESSAGE_ID); $aMessageContent['message_id'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_MESSAGE_ID);
$aMessageContent['references'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_REFERENCES); $aMessageContent['references'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_REFERENCES);
} } catch (Exception $e) {
catch (Exception $e) {
/** @noinspection PhpUnhandledExceptionInspection */ /** @noinspection PhpUnhandledExceptionInspection */
throw $e; throw $e;
} } finally {
finally {
ApplicationContext::SetUrlMakerClass($sPreviousUrlMaker); ApplicationContext::SetUrlMakerClass($sPreviousUrlMaker);
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null); $this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
} }
@@ -803,14 +772,12 @@ class ActionEmail extends ActionNotification
// Note: N°4849 We pass the "References" identifier instead of the "Message-ID" on purpose as we want notifications emails to group around the triggering iTop object, not just the users' replies to the notification // Note: N°4849 We pass the "References" identifier instead of the "Message-ID" on purpose as we want notifications emails to group around the triggering iTop object, not just the users' replies to the notification
$aMessageContent['in_reply_to'] = $aMessageContent['references']; $aMessageContent['in_reply_to'] = $aMessageContent['references'];
if (isset($aContextArgs['attachments'])) if (isset($aContextArgs['attachments'])) {
{ $aAttachmentReport = [];
$aAttachmentReport = array();
/** @var \ormDocument $oDocument */ /** @var \ormDocument $oDocument */
foreach($aContextArgs['attachments'] as $oDocument) foreach ($aContextArgs['attachments'] as $oDocument) {
{
$aMessageContent['attachments'][] = ['data' => $oDocument->GetData(), 'filename' => $oDocument->GetFileName(), 'mime_type' => $oDocument->GetMimeType()]; $aMessageContent['attachments'][] = ['data' => $oDocument->GetData(), 'filename' => $oDocument->GetFileName(), 'mime_type' => $oDocument->GetMimeType()];
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData() ?? '')); $aAttachmentReport[] = [$oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData() ?? '')];
} }
$oLog->Set('attachments', $aAttachmentReport); $oLog->Set('attachments', $aAttachmentReport);
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2016-2024 Combodo SAS // Copyright (C) 2016-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -20,8 +21,7 @@
// Note: for PHP < 7, this compatibility used to be provided by APCU itself (if compiled with some options) // Note: for PHP < 7, this compatibility used to be provided by APCU itself (if compiled with some options)
// for PHP 7+, it can be provided by the mean of apcu_bc, which is not so simple to install // for PHP 7+, it can be provided by the mean of apcu_bc, which is not so simple to install
// The current emulation aims at skipping this complexity // The current emulation aims at skipping this complexity
if (!function_exists('apc_store') && function_exists('apcu_store')) if (!function_exists('apc_store') && function_exists('apcu_store')) {
{
function apc_add($key, $var, $ttl = 0) function apc_add($key, $var, $ttl = 0)
{ {
return apcu_add($key, $var, $ttl); return apcu_add($key, $var, $ttl);
@@ -74,25 +74,23 @@ if (!function_exists('apc_store') && function_exists('apcu_store'))
*/ */
function apc_cache_info_compat() function apc_cache_info_compat()
{ {
if (!function_exists('apc_cache_info')) return array(); if (!function_exists('apc_cache_info')) {
return [];
}
$oFunction = new ReflectionFunction('apc_cache_info'); $oFunction = new ReflectionFunction('apc_cache_info');
if ($oFunction->getNumberOfParameters() != 2) if ($oFunction->getNumberOfParameters() != 2) {
{
// Beware: APCu behaves slightly differently from APC !! // Beware: APCu behaves slightly differently from APC !!
// Worse: the compatibility layer integrated into APC differs from apcu-bc (testing the number of parameters is a must) // Worse: the compatibility layer integrated into APC differs from apcu-bc (testing the number of parameters is a must)
// In CLI mode (PHP > 7) apc_cache_info returns null and outputs an error message. // In CLI mode (PHP > 7) apc_cache_info returns null and outputs an error message.
$aCacheUserData = @apc_cache_info(); $aCacheUserData = @apc_cache_info();
} } else {
else
{
$aCacheUserData = @apc_cache_info('user'); $aCacheUserData = @apc_cache_info('user');
} }
return $aCacheUserData; return $aCacheUserData;
} }
// Cache emulation // Cache emulation
if (!function_exists('apc_store')) if (!function_exists('apc_store')) {
{
require_once(APPROOT.'core/apc-emulation.php'); require_once(APPROOT.'core/apc-emulation.php');
} }

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.
@@ -28,7 +29,7 @@
*/ */
function apc_cache_info($cache_type = '', $limited = false) function apc_cache_info($cache_type = '', $limited = false)
{ {
$aInfo = array(); $aInfo = [];
$sRootCacheDir = apcFile::GetCacheFileName(); $sRootCacheDir = apcFile::GetCacheFileName();
$aInfo['cache_list'] = apcFile::GetCacheEntries($sRootCacheDir); $aInfo['cache_list'] = apcFile::GetCacheEntries($sRootCacheDir);
return $aInfo; return $aInfo;
@@ -40,13 +41,11 @@ function apc_cache_info($cache_type = '', $limited = false)
* @param int $ttl * @param int $ttl
* @return array|bool * @return array|bool
*/ */
function apc_store($key, $var = NULL, $ttl = 0) function apc_store($key, $var = null, $ttl = 0)
{
if (is_array($key))
{
$aResult = array();
foreach($key as $sKey => $value)
{ {
if (is_array($key)) {
$aResult = [];
foreach ($key as $sKey => $value) {
$aResult[] = apcFile::StoreOneFile($sKey, $value, $ttl); $aResult[] = apcFile::StoreOneFile($sKey, $value, $ttl);
} }
return $aResult; return $aResult;
@@ -89,8 +88,7 @@ function apc_clear_cache($cache_type = '')
*/ */
function apc_delete($key) function apc_delete($key)
{ {
if (empty($key)) if (empty($key)) {
{
return false; return false;
} }
$bRet1 = apcFile::DeleteEntry(apcFile::GetCacheFileName($key)); $bRet1 = apcFile::DeleteEntry(apcFile::GetCacheFileName($key));
@@ -126,17 +124,17 @@ function apc_exists($keys)
class apcFile class apcFile
{ {
// Check only once per request // Check only once per request
static public $aFilesByTime = null; public static $aFilesByTime = null;
static public $iFileCount = 0; public static $iFileCount = 0;
/** Get the file name corresponding to the cache entry. /** Get the file name corresponding to the cache entry.
* If an empty key is provided, the root of the cache is returned. * If an empty key is provided, the root of the cache is returned.
* @param $sKey * @param $sKey
* @return string * @return string
*/ */
static public function GetCacheFileName($sKey = '') public static function GetCacheFileName($sKey = '')
{ {
$sPath = str_replace(array(' ', '/', '\\', '.'), '-', $sKey ?? ''); $sPath = str_replace([' ', '/', '\\', '.'], '-', $sKey ?? '');
return utils::GetCachePath().'apc-emul/'.$sPath; return utils::GetCachePath().'apc-emul/'.$sPath;
} }
@@ -144,26 +142,21 @@ class apcFile
* @param $sEntry string starting folder. * @param $sEntry string starting folder.
* @return array list of entries stored into array of key 'info' * @return array list of entries stored into array of key 'info'
*/ */
static public function GetCacheEntries($sEntry) public static function GetCacheEntries($sEntry)
{
$aResult = array();
if (is_dir($sEntry))
{
$aFiles = array_diff(scandir($sEntry), array('.', '..'));
foreach($aFiles as $sFile)
{ {
$aResult = [];
if (is_dir($sEntry)) {
$aFiles = array_diff(scandir($sEntry), ['.', '..']);
foreach ($aFiles as $sFile) {
$sSubFile = $sEntry.'/'.$sFile; $sSubFile = $sEntry.'/'.$sFile;
$aResult = array_merge($aResult, self::GetCacheEntries($sSubFile)); $aResult = array_merge($aResult, self::GetCacheEntries($sSubFile));
} }
} } else {
else
{
$sKey = basename($sEntry); $sKey = basename($sEntry);
if (strpos($sKey, '-') === 0) if (strpos($sKey, '-') === 0) {
{
$sKey = substr($sKey, 1); $sKey = substr($sKey, 1);
} }
$aResult[] = array('info' => $sKey); $aResult[] = ['info' => $sKey];
} }
return $aResult; return $aResult;
} }
@@ -172,35 +165,25 @@ class apcFile
* @param $sCache * @param $sCache
* @return bool true if the entry was deleted false if error occurs (like entry did not exist). * @return bool true if the entry was deleted false if error occurs (like entry did not exist).
*/ */
static public function DeleteEntry($sCache) public static function DeleteEntry($sCache)
{
if (is_dir($sCache))
{
$aFiles = array_diff(scandir($sCache), array('.', '..'));
foreach($aFiles as $sFile)
{ {
if (is_dir($sCache)) {
$aFiles = array_diff(scandir($sCache), ['.', '..']);
foreach ($aFiles as $sFile) {
$sSubFile = $sCache.'/'.$sFile; $sSubFile = $sCache.'/'.$sFile;
if (!self::DeleteEntry($sSubFile)) if (!self::DeleteEntry($sSubFile)) {
{
return false; return false;
} }
} }
if (!@rmdir($sCache)) if (!@rmdir($sCache)) {
{
return false; return false;
} }
} } else {
else if (is_file($sCache)) {
{ if (!@unlink($sCache)) {
if (is_file($sCache))
{
if (!@unlink($sCache))
{
return false; return false;
} }
} } else {
else
{
return false; return false;
} }
} }
@@ -215,7 +198,8 @@ class apcFile
* @return bool * @return bool
* @since 3.2.0 N°7068 * @since 3.2.0 N°7068
*/ */
static public function ExistsOneFile($sKey) { public static function ExistsOneFile($sKey)
{
return is_file(self::GetCacheFileName('-'.$sKey)) || is_file(self::GetCacheFileName($sKey)); return is_file(self::GetCacheFileName('-'.$sKey)) || is_file(self::GetCacheFileName($sKey));
} }
@@ -223,15 +207,13 @@ class apcFile
* @param $sKey * @param $sKey
* @return bool|mixed * @return bool|mixed
*/ */
static public function FetchOneFile($sKey) public static function FetchOneFile($sKey)
{ {
// Try the 'TTLed' version // Try the 'TTLed' version
$sValue = self::ReadCacheLocked(self::GetCacheFileName('-'.$sKey)); $sValue = self::ReadCacheLocked(self::GetCacheFileName('-'.$sKey));
if ($sValue === false) if ($sValue === false) {
{
$sValue = self::ReadCacheLocked(self::GetCacheFileName($sKey)); $sValue = self::ReadCacheLocked(self::GetCacheFileName($sKey));
if ($sValue === false) if ($sValue === false) {
{
return false; return false;
} }
} }
@@ -245,7 +227,7 @@ class apcFile
* @param int $iTTL time to live * @param int $iTTL time to live
* @return bool * @return bool
*/ */
static public function StoreOneFile($sKey, $value, $iTTL) public static function StoreOneFile($sKey, $value, $iTTL)
{ {
if (empty($sKey)) { if (empty($sKey)) {
return false; return false;
@@ -279,40 +261,31 @@ class apcFile
* remove older files if the mamximum is reached. * remove older files if the mamximum is reached.
* @param $sNewFilename * @param $sNewFilename
*/ */
static protected function AddFile($sNewFilename) protected static function AddFile($sNewFilename)
{
if (strpos(basename($sNewFilename), '-') !== 0)
{ {
if (strpos(basename($sNewFilename), '-') !== 0) {
return; return;
} }
$iMaxFiles = MetaModel::GetConfig()->Get('apc_cache_emulation.max_entries'); $iMaxFiles = MetaModel::GetConfig()->Get('apc_cache_emulation.max_entries');
if ($iMaxFiles == 0) if ($iMaxFiles == 0) {
{
return; return;
} }
if (!self::$aFilesByTime) if (!self::$aFilesByTime) {
{
self::ListFilesByTime(); self::ListFilesByTime();
self::$iFileCount = count(self::$aFilesByTime); self::$iFileCount = count(self::$aFilesByTime);
if ($iMaxFiles !== 0) if ($iMaxFiles !== 0) {
{
asort(self::$aFilesByTime); asort(self::$aFilesByTime);
} }
} } else {
else
{
self::$aFilesByTime[$sNewFilename] = time(); self::$aFilesByTime[$sNewFilename] = time();
self::$iFileCount++; self::$iFileCount++;
} }
if (self::$iFileCount > $iMaxFiles) if (self::$iFileCount > $iMaxFiles) {
{
$iFileNbToRemove = self::$iFileCount - $iMaxFiles; $iFileNbToRemove = self::$iFileCount - $iMaxFiles;
foreach(self::$aFilesByTime as $sFileToRemove => $iTime) foreach (self::$aFilesByTime as $sFileToRemove => $iTime) {
{
@unlink($sFileToRemove); @unlink($sFileToRemove);
if (--$iFileNbToRemove === 0) if (--$iFileNbToRemove === 0) {
{
break; break;
} }
} }
@@ -324,25 +297,19 @@ class apcFile
/** Get the list of files with their associated access time /** Get the list of files with their associated access time
* @param string $sCheck Directory to scan * @param string $sCheck Directory to scan
*/ */
static protected function ListFilesByTime($sCheck = null) protected static function ListFilesByTime($sCheck = null)
{
if (empty($sCheck))
{ {
if (empty($sCheck)) {
$sCheck = self::GetCacheFileName(); $sCheck = self::GetCacheFileName();
} }
// Garbage collection // Garbage collection
$aFiles = array_diff(@scandir($sCheck), array('.', '..')); $aFiles = array_diff(@scandir($sCheck), ['.', '..']);
foreach($aFiles as $sFile) foreach ($aFiles as $sFile) {
{
$sSubFile = $sCheck.'/'.$sFile; $sSubFile = $sCheck.'/'.$sFile;
if (is_dir($sSubFile)) if (is_dir($sSubFile)) {
{
self::ListFilesByTime($sSubFile); self::ListFilesByTime($sSubFile);
} } else {
else if (strpos(basename($sSubFile), '-') === 0) {
{
if (strpos(basename($sSubFile), '-') === 0)
{
self::$aFilesByTime[$sSubFile] = @fileatime($sSubFile); self::$aFilesByTime[$sSubFile] = @fileatime($sSubFile);
} }
} }
@@ -353,7 +320,7 @@ class apcFile
* @param $sFilename * @param $sFilename
* @return bool|string the content of the cache entry or false if error * @return bool|string the content of the cache entry or false if error
*/ */
static protected function ReadCacheLocked($sFilename) protected static function ReadCacheLocked($sFilename)
{ {
$sContent = false; $sContent = false;
$file = @fopen($sFilename, 'r'); $file = @fopen($sFilename, 'r');
@@ -367,7 +334,7 @@ class apcFile
return $sContent; return $sContent;
} }
static protected function ResetFileCount() protected static function ResetFileCount()
{ {
self::$aFilesByTime = null; self::$aFilesByTime = null;
self::$iFileCount = 0; self::$iFileCount = 0;

View File

@@ -4,8 +4,10 @@
* Class ApcService * Class ApcService
* @since 2.7.6 N°4125 * @since 2.7.6 N°4125
*/ */
class ApcService { class ApcService
public function __construct() { {
public function __construct()
{
} }
/** /**
@@ -13,7 +15,8 @@ class ApcService {
* @return bool * @return bool
* @see function_exists() * @see function_exists()
*/ */
public function function_exists($function_name) { public function function_exists($function_name)
{
return function_exists($function_name); return function_exists($function_name);
} }
@@ -22,7 +25,7 @@ class ApcService {
* @return mixed * @return mixed
* @see apc_fetch() * @see apc_fetch()
*/ */
function apc_fetch($key) public function apc_fetch($key)
{ {
return apc_fetch($key); return apc_fetch($key);
} }
@@ -34,9 +37,8 @@ class ApcService {
* @return array|bool * @return array|bool
* @see apc_store() * @see apc_store()
*/ */
function apc_store($key, $var = NULL, $ttl = 0) public function apc_store($key, $var = null, $ttl = 0)
{ {
return apc_store($key, $var, $ttl); return apc_store($key, $var, $ttl);
} }
} }
?>

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.
@@ -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\Service\Notification\Event\EventNotificationNewsroomService; use Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService;
/** /**
* Persistent classes (internal): user defined actions * Persistent classes (internal): user defined actions
* *
@@ -25,7 +25,6 @@ use Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService;
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
class ExecAsyncTask implements iBackgroundProcess class ExecAsyncTask implements iBackgroundProcess
{ {
public function GetPeriodicity() public function GetPeriodicity()
@@ -39,19 +38,16 @@ class ExecAsyncTask implements iBackgroundProcess
// Criteria: planned, and expected to occur... ASAP or in the past // Criteria: planned, and expected to occur... ASAP or in the past
$sOQL = "SELECT AsyncTask WHERE (status = 'planned') AND (ISNULL(planned) OR (planned < '$sNow'))"; $sOQL = "SELECT AsyncTask WHERE (status = 'planned') AND (ISNULL(planned) OR (planned < '$sNow'))";
$iProcessed = 0; $iProcessed = 0;
while (time() < $iTimeLimit) while (time() < $iTimeLimit) {
{
// Next one ? // Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array(), null, 1 /* limit count */); $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), ['created' => true] /* order by*/, [], null, 1 /* limit count */);
$oTask = $oSet->Fetch(); $oTask = $oSet->Fetch();
if (is_null($oTask)) if (is_null($oTask)) {
{
// Nothing to be done // Nothing to be done
break; break;
} }
$iProcessed++; $iProcessed++;
if ($oTask->Process()) if ($oTask->Process()) {
{
$oTask->DBDelete(); $oTask->DBDelete();
} }
} }
@@ -72,46 +68,46 @@ abstract class AsyncTask extends DBObject
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb", "category" => "core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => array('created'), "name_attcode" => ['created'],
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_async_task", "db_table" => "priv_async_task",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "realclass", "db_finalclass_field" => "realclass",
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
// Null is allowed to ease the migration from iTop 2.0.2 and earlier, when the status did not exist, and because the default value is not taken into account in the SQL definition // Null is allowed to ease the migration from iTop 2.0.2 and earlier, when the status did not exist, and because the default value is not taken into account in the SQL definition
// The value is set from null to planned in the setup program // The value is set from null to planned in the setup program
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('planned,running,idle,error'), "sql"=>"status", "default_value"=>"planned", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("status", ["allowed_values" => new ValueSetEnum('planned,running,idle,error'), "sql" => "status", "default_value" => "planned", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("created", ["allowed_values" => null, "sql" => "created", "default_value" => "NOW()", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("started", array("allowed_values"=>null, "sql"=>"started", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("started", ["allowed_values" => null, "sql" => "started", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("planned", ["allowed_values" => null, "sql" => "planned", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", array("targetclass"=>"Event", "jointype"=> "", "allowed_values"=>null, "sql"=>"event_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_SILENT, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", ["targetclass" => "Event", "jointype" => "", "allowed_values" => null, "sql" => "event_id", "is_null_allowed" => true, "on_target_delete" => DEL_SILENT, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", array("allowed_values"=>null, "sql"=>"remaining_retries", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", ["allowed_values" => null, "sql" => "remaining_retries", "default_value" => 0, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("last_error_code", array("allowed_values"=>null, "sql"=>"last_error_code", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("last_error_code", ["allowed_values" => null, "sql" => "last_error_code", "default_value" => 0, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("last_error", ["allowed_values" => null, "sql" => "last_error", "default_value" => '', "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("last_attempt", array("allowed_values"=>null, "sql"=>"last_attempt", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("last_attempt", ["allowed_values" => null, "sql" => "last_attempt", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
} }
/** /**
* Every is fine * Every is fine
*/ */
const OK = 0; public const OK = 0;
/** /**
* The task no longer exists * The task no longer exists
*/ */
const DELETED = 1; public const DELETED = 1;
/** /**
* The task is already being executed * The task is already being executed
*/ */
const ALREADY_RUNNING = 2; public const ALREADY_RUNNING = 2;
/** /**
* The current process requests the ownership on the task. * The current process requests the ownership on the task.
@@ -122,26 +118,19 @@ abstract class AsyncTask extends DBObject
*/ */
public function MarkAsRunning() public function MarkAsRunning()
{ {
try try {
{ if ($this->Get('status') == 'running') {
if ($this->Get('status') == 'running')
{
return self::ALREADY_RUNNING; return self::ALREADY_RUNNING;
} } else {
else
{
$this->Set('status', 'running'); $this->Set('status', 'running');
$this->Set('started', time()); $this->Set('started', time());
$this->DBUpdate(); $this->DBUpdate();
return self::OK; return self::OK;
} }
} } catch (Exception $e) {
catch(Exception $e)
{
// Corrupted task !! (for example: "Failed to reload object") // Corrupted task !! (for example: "Failed to reload object")
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - fatal error, deleting the task.'); IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - fatal error, deleting the task.');
if ($this->Get('event_id') != 0) if ($this->Get('event_id') != 0) {
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage()); $oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
@@ -155,8 +144,7 @@ abstract class AsyncTask extends DBObject
{ {
$iRetryDelay = 600; $iRetryDelay = 600;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries'); $aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) {
{
$aConfig = $aRetries[get_class($this)]; $aConfig = $aRetries[get_class($this)];
$iRetryDelay = $aConfig['retry_delay'] ?? $iRetryDelay; $iRetryDelay = $aConfig['retry_delay'] ?? $iRetryDelay;
} }
@@ -167,8 +155,7 @@ abstract class AsyncTask extends DBObject
{ {
$iMaxRetries = 0; $iMaxRetries = 0;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries'); $aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) {
{
$aConfig = $aRetries[get_class($this)]; $aConfig = $aRetries[get_class($this)];
$iMaxRetries = $aConfig['max_retries'] ?? $iMaxRetries; $iMaxRetries = $aConfig['max_retries'] ?? $iMaxRetries;
} }
@@ -179,8 +166,7 @@ abstract class AsyncTask extends DBObject
{ {
$bExponential = false; $bExponential = false;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries'); $aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries)) {
{
$aConfig = $aRetries[get_class($this)]; $aConfig = $aRetries[get_class($this)];
$bExponential = (bool) ($aConfig['exponential_delay'] ?? $bExponential); $bExponential = (bool) ($aConfig['exponential_delay'] ?? $bExponential);
} }
@@ -191,20 +177,14 @@ abstract class AsyncTask extends DBObject
{ {
$aMessages = []; $aMessages = [];
$aRetries = $oConfig->Get('async_task_retries'); $aRetries = $oConfig->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists($sAsyncTaskClass, $aRetries)) if (is_array($aRetries) && array_key_exists($sAsyncTaskClass, $aRetries)) {
{ $aValidKeys = ["retry_delay", "max_retries", "exponential_delay"];
$aValidKeys = array("retry_delay", "max_retries", "exponential_delay");
$aConfig = $aRetries[$sAsyncTaskClass]; $aConfig = $aRetries[$sAsyncTaskClass];
if (!is_array($aConfig)) if (!is_array($aConfig)) {
{
$aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_Keys', $sAsyncTaskClass, implode(', ', $aValidKeys)); $aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_Keys', $sAsyncTaskClass, implode(', ', $aValidKeys));
} } else {
else foreach ($aConfig as $key => $value) {
{ if (!in_array($key, $aValidKeys)) {
foreach($aConfig as $key => $value)
{
if (!in_array($key, $aValidKeys))
{
$aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys', $sAsyncTaskClass, $key, implode(', ', $aValidKeys)); $aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys', $sAsyncTaskClass, $key, implode(', ', $aValidKeys));
} }
} }
@@ -223,14 +203,13 @@ abstract class AsyncTask extends DBObject
*/ */
public static function GetNextRetryDelay($bIsExponential, $iRetryDelay, $iMaxRetries, $iRemainingRetries) public static function GetNextRetryDelay($bIsExponential, $iRetryDelay, $iMaxRetries, $iRemainingRetries)
{ {
if ($bIsExponential) if ($bIsExponential) {
{
$iExponent = $iMaxRetries - $iRemainingRetries; $iExponent = $iMaxRetries - $iRemainingRetries;
if ($iExponent < 0) $iExponent = 0; // Safety net in case on configuration change in the middle of retries if ($iExponent < 0) {
$iExponent = 0;
} // Safety net in case on configuration change in the middle of retries
return $iRetryDelay * (2 ** $iExponent); return $iRetryDelay * (2 ** $iExponent);
} } else {
else
{
return $iRetryDelay; return $iRetryDelay;
} }
} }
@@ -257,25 +236,19 @@ abstract class AsyncTask extends DBObject
// Attempt to take the ownership // Attempt to take the ownership
$iStatus = $this->MarkAsRunning(); $iStatus = $this->MarkAsRunning();
if ($iStatus == self::OK) if ($iStatus == self::OK) {
{ try {
try
{
$sStatus = $this->DoProcess(); $sStatus = $this->DoProcess();
if ($this->Get('event_id') != 0) if ($this->Get('event_id') != 0) {
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', $sStatus); $oEventLog->Set('message', $sStatus);
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
} }
$bRet = true; $bRet = true;
} catch (Exception $e) } catch (Exception $e) {
{
$this->HandleError($e->getMessage(), $e->getCode()); $this->HandleError($e->getMessage(), $e->getCode());
} }
} } else {
else
{
// Already done or being handled by another process... skip... // Already done or being handled by another process... skip...
$bRet = false; $bRet = false;
} }
@@ -288,8 +261,7 @@ abstract class AsyncTask extends DBObject
*/ */
protected function HandleError($sErrorMessage, $iErrorCode) protected function HandleError($sErrorMessage, $iErrorCode)
{ {
if ($this->Get('last_attempt') == '') if ($this->Get('last_attempt') == '') {
{
// First attempt // First attempt
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode)); $this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
} }
@@ -299,21 +271,16 @@ abstract class AsyncTask extends DBObject
$this->Set('last_attempt', time()); $this->Set('last_attempt', time());
$iRemaining = $this->Get('remaining_retries'); $iRemaining = $this->Get('remaining_retries');
if ($iRemaining > 0) if ($iRemaining > 0) {
{
$iRetryDelay = $this->GetRetryDelay($iErrorCode); $iRetryDelay = $this->GetRetryDelay($iErrorCode);
$iNextRetryDelay = static::GetNextRetryDelay($this->IsRetryDelayExponential(), $iRetryDelay, $this->GetMaxRetries($iErrorCode), $iRemaining); $iNextRetryDelay = static::GetNextRetryDelay($this->IsRetryDelayExponential(), $iRetryDelay, $this->GetMaxRetries($iErrorCode), $iRemaining);
IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage.' - remaining retries: '.$iRemaining.' - next retry in '.$iNextRetryDelay.'s'); IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage.' - remaining retries: '.$iRemaining.' - next retry in '.$iNextRetryDelay.'s');
if ($this->Get('event_id') != 0) if ($this->Get('event_id') != 0) {
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', "$sErrorMessage\nFailed to process async task. Remaining retries: $iRemaining. Next retry in {$iNextRetryDelay}s"); $oEventLog->Set('message', "$sErrorMessage\nFailed to process async task. Remaining retries: $iRemaining. Next retry in {$iNextRetryDelay}s");
try try {
{
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
} } catch (Exception $e) {
catch (Exception $e)
{
$oEventLog->Set('message', "Failed to process async task. Remaining retries: $iRemaining. Next retry in {$iNextRetryDelay}s, more details in the log"); $oEventLog->Set('message', "Failed to process async task. Remaining retries: $iRemaining. Next retry in {$iNextRetryDelay}s, more details in the log");
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
} }
@@ -322,20 +289,14 @@ abstract class AsyncTask extends DBObject
$this->Set('status', 'planned'); $this->Set('status', 'planned');
$this->Set('started', null); $this->Set('started', null);
$this->Set('planned', time() + $iNextRetryDelay); $this->Set('planned', time() + $iNextRetryDelay);
} } else {
else
{
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage); IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage);
if ($this->Get('event_id') != 0) if ($this->Get('event_id') != 0) {
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', "$sErrorMessage\nFailed to process async task."); $oEventLog->Set('message', "$sErrorMessage\nFailed to process async task.");
try try {
{
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
} } catch (Exception $e) {
catch (Exception $e)
{
$oEventLog->Set('message', 'Failed to process async task, more details in the log'); $oEventLog->Set('message', 'Failed to process async task, more details in the log');
$oEventLog->DBUpdate(); $oEventLog->DBUpdate();
} }
@@ -358,9 +319,9 @@ abstract class AsyncTask extends DBObject
/** /**
* Describes the error codes that DoProcess can return by the mean of exceptions * Describes the error codes that DoProcess can return by the mean of exceptions
*/ */
static public function EnumErrorCodes() public static function EnumErrorCodes()
{ {
return array(); return [];
} }
} }
@@ -373,24 +334,24 @@ class AsyncSendEmail extends AsyncTask
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb", "category" => "core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "created", "name_attcode" => "created",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_async_send_email", "db_table" => "priv_async_send_email",
"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 AttributeInteger("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>Email::ORIGINAL_FORMAT, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("version", ["allowed_values" => null, "sql" => "version", "default_value" => Email::ORIGINAL_FORMAT, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("to", ["allowed_values" => null, "sql" => "to", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("subject", ["allowed_values" => null, "sql" => "subject", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeLongText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeLongText("message", ["allowed_values" => null, "sql" => "message", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
// MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list')); // Attributes to be displayed for the complete details // MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list')); // Attributes to be displayed for the complete details
@@ -400,11 +361,10 @@ class AsyncSendEmail extends AsyncTask
// 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
} }
static public function AddToQueue(EMail $oEMail, $oLog) public static function AddToQueue(EMail $oEMail, $oLog)
{ {
$oNew = MetaModel::NewObject(__class__); $oNew = MetaModel::NewObject(__class__);
if ($oLog) if ($oLog) {
{
$oNew->Set('event_id', $oLog->GetKey()); $oNew->Set('event_id', $oLog->GetKey());
} }
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */)); $oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
@@ -425,8 +385,7 @@ class AsyncSendEmail extends AsyncTask
{ {
$sMessage = $this->Get('message'); $sMessage = $this->Get('message');
$iVersion = (int) $this->Get('version'); $iVersion = (int) $this->Get('version');
switch($iVersion) switch ($iVersion) {
{
case Email::FORMAT_V2: case Email::FORMAT_V2:
$oEMail = Email::UnSerializeV2($sMessage); $oEMail = Email::UnSerializeV2($sMessage);
break; break;
@@ -439,8 +398,7 @@ class AsyncSendEmail extends AsyncTask
return 'Unknown version of the serialization format: '.$iVersion; return 'Unknown version of the serialization format: '.$iVersion;
} }
$iRes = $oEMail->Send($aIssues, true /* force synchro !!!!! */); $iRes = $oEMail->Send($aIssues, true /* force synchro !!!!! */);
switch ($iRes) switch ($iRes) {
{
case EMAIL_SEND_OK: case EMAIL_SEND_OK:
return "Sent"; return "Sent";
@@ -463,33 +421,33 @@ class AsyncSendEmail extends AsyncTask
* An async notification to be sent to iTop users through the newsroom * An async notification to be sent to iTop users through the newsroom
* @since 3.2.0 * @since 3.2.0
*/ */
class AsyncSendNewsroom extends AsyncTask { class AsyncSendNewsroom extends AsyncTask
{
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb", "category" => "core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "created", "name_attcode" => "created",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_async_send_newsroom", "db_table" => "priv_async_send_newsroom",
"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 AttributeText("recipients", array("allowed_values"=>null, "sql"=>"recipients", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("recipients", ["allowed_values" => null, "sql" => "recipients", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "allowed_values"=>null, "sql"=>"action_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", ["targetclass" => "Action", "allowed_values" => null, "sql" => "action_id", "default_value" => null, "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "allowed_values"=>null, "sql"=>"trigger_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", ["targetclass" => "Trigger", "allowed_values" => null, "sql" => "trigger_id", "default_value" => null, "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("title", array("allowed_values"=>null, "sql"=>"title", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("title", ["allowed_values" => null, "sql" => "title", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("message", ["allowed_values" => null, "sql" => "message", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values"=>null, "sql"=>"object_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("object_id", ["allowed_values" => null, "sql" => "object_id", "default_value" => null, "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("object_class", array("allowed_values"=>null, "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("object_class", ["allowed_values" => null, "sql" => "object_class", "default_value" => null, "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("url", array("allowed_values"=>null, "sql"=>"url", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("url", ["allowed_values" => null, "sql" => "url", "default_value" => null, "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>'NOW()', "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("date", ["allowed_values" => null, "sql" => "date", "default_value" => 'NOW()', "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
} }
@@ -533,8 +491,7 @@ class AsyncSendNewsroom extends AsyncTask {
$sObjectClass = $this->Get('object_class'); $sObjectClass = $this->Get('object_class');
$sDate = $this->Get('date'); $sDate = $this->Get('date');
foreach ($aRecipients as $iRecipientId) foreach ($aRecipients as $iRecipientId) {
{
$oEvent = EventNotificationNewsroomService::MakeEventFromAction($oAction, $iRecipientId, $iTriggerId, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass, $sDate); $oEvent = EventNotificationNewsroomService::MakeEventFromAction($oAction, $iRecipientId, $iTriggerId, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass, $sDate);
$oEvent->DBInsertNoReload(); $oEvent->DBInsertNoReload();
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -25,7 +26,6 @@ MetaModel::IncludeModule('application/audit.domain.class.inc.php');
MetaModel::IncludeModule('application/query.class.inc.php'); MetaModel::IncludeModule('application/query.class.inc.php');
MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php'); MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php');
MetaModel::IncludeModule('core/event.class.inc.php'); MetaModel::IncludeModule('core/event.class.inc.php');
MetaModel::IncludeModule('core/action.class.inc.php'); MetaModel::IncludeModule('core/action.class.inc.php');
MetaModel::IncludeModule('core/trigger.class.inc.php'); MetaModel::IncludeModule('core/trigger.class.inc.php');

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 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/>
/** /**
* Tasks performed in the background * Tasks performed in the background
* *
@@ -24,7 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
class ObsolescenceDateUpdater implements iBackgroundProcess class ObsolescenceDateUpdater implements iBackgroundProcess
{ {
public function GetPeriodicity() public function GetPeriodicity()
@@ -37,18 +36,17 @@ class ObsolescenceDateUpdater implements iBackgroundProcess
$iCountSet = 0; $iCountSet = 0;
$iCountReset = 0; $iCountReset = 0;
$iClasses = 0; $iClasses = 0;
foreach (MetaModel::EnumObsoletableClasses() as $sClass) foreach (MetaModel::EnumObsoletableClasses() as $sClass) {
{
$oObsoletedToday = new DBObjectSearch($sClass); $oObsoletedToday = new DBObjectSearch($sClass);
$oObsoletedToday->AddCondition('obsolescence_flag', 1, '='); $oObsoletedToday->AddCondition('obsolescence_flag', 1, '=');
$oObsoletedToday->AddCondition('obsolescence_date', null, '='); $oObsoletedToday->AddCondition('obsolescence_date', null, '=');
$sToday = date(AttributeDate::GetSQLFormat()); $sToday = date(AttributeDate::GetSQLFormat());
$iCountSet += MetaModel::BulkUpdate($oObsoletedToday, array('obsolescence_date' => $sToday)); $iCountSet += MetaModel::BulkUpdate($oObsoletedToday, ['obsolescence_date' => $sToday]);
$oObsoletedToday = new DBObjectSearch($sClass); $oObsoletedToday = new DBObjectSearch($sClass);
$oObsoletedToday->AddCondition('obsolescence_flag', 1, '!='); $oObsoletedToday->AddCondition('obsolescence_flag', 1, '!=');
$oObsoletedToday->AddCondition('obsolescence_date', null, '!='); $oObsoletedToday->AddCondition('obsolescence_date', null, '!=');
$iCountReset += MetaModel::BulkUpdate($oObsoletedToday, array('obsolescence_date' => null)); $iCountReset += MetaModel::BulkUpdate($oObsoletedToday, ['obsolescence_date' => null]);
} }
return "Obsolescence date updated (classes: $iClasses ; set: $iCountSet ; reset: $iCountReset)\n"; return "Obsolescence date updated (classes: $iClasses ; set: $iCountSet ; reset: $iCountReset)\n";
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2010-2024 Combodo SAS * Copyright (C) 2010-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
*/ */
interface iProcess interface iProcess
{ {
/** /**
@@ -62,7 +62,6 @@ interface iScheduledProcess extends iProcess
public function GetNextOccurrence(); public function GetNextOccurrence();
} }
/** /**
* Implementation of {@link iScheduledProcess}, using config parameters for module * Implementation of {@link iScheduledProcess}, using config parameters for module
* *
@@ -82,11 +81,11 @@ interface iScheduledProcess extends iProcess
abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
{ {
// param have default names/values but can be overridden // param have default names/values but can be overridden
const MODULE_SETTING_ENABLED = 'enabled'; public const MODULE_SETTING_ENABLED = 'enabled';
const DEFAULT_MODULE_SETTING_ENABLED = true; public const DEFAULT_MODULE_SETTING_ENABLED = true;
const MODULE_SETTING_WEEKDAYS = 'week_days'; public const MODULE_SETTING_WEEKDAYS = 'week_days';
const DEFAULT_MODULE_SETTING_WEEKDAYS = 'monday, tuesday, wednesday, thursday, friday, saturday, sunday'; public const DEFAULT_MODULE_SETTING_WEEKDAYS = 'monday, tuesday, wednesday, thursday, friday, saturday, sunday';
const MODULE_SETTING_TIME = 'time'; public const MODULE_SETTING_TIME = 'time';
/** /**
* @var Config can be used to mock config for tests * @var Config can be used to mock config for tests
@@ -111,15 +110,13 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
*/ */
public function getOConfig() public function getOConfig()
{ {
if (!isset($this->oConfig)) if (!isset($this->oConfig)) {
{
$this->oConfig = MetaModel::GetConfig(); $this->oConfig = MetaModel::GetConfig();
} }
return $this->oConfig; return $this->oConfig;
} }
/** /**
* Interpret current setting for the week days * Interpret current setting for the week days
* *
@@ -128,7 +125,7 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
*/ */
public function InterpretWeekDays() public function InterpretWeekDays()
{ {
static $aWEEKDAYTON = array( static $aWEEKDAYTON = [
'monday' => 1, 'monday' => 1,
'tuesday' => 2, 'tuesday' => 2,
'wednesday' => 3, 'wednesday' => 3,
@@ -136,32 +133,26 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
'friday' => 5, 'friday' => 5,
'saturday' => 6, 'saturday' => 6,
'sunday' => 7, 'sunday' => 7,
); ];
$aDays = array(); $aDays = [];
$sWeekDays = $this->getOConfig()->GetModuleSetting( $sWeekDays = $this->getOConfig()->GetModuleSetting(
$this->GetModuleName(), $this->GetModuleName(),
static::MODULE_SETTING_WEEKDAYS, static::MODULE_SETTING_WEEKDAYS,
static::DEFAULT_MODULE_SETTING_WEEKDAYS static::DEFAULT_MODULE_SETTING_WEEKDAYS
); );
if ($sWeekDays !== '') if ($sWeekDays !== '') {
{
$aWeekDaysRaw = explode(',', $sWeekDays); $aWeekDaysRaw = explode(',', $sWeekDays);
foreach ($aWeekDaysRaw as $sWeekDay) foreach ($aWeekDaysRaw as $sWeekDay) {
{
$sWeekDay = strtolower(trim($sWeekDay)); $sWeekDay = strtolower(trim($sWeekDay));
if (array_key_exists($sWeekDay, $aWEEKDAYTON)) if (array_key_exists($sWeekDay, $aWEEKDAYTON)) {
{
$aDays[] = $aWEEKDAYTON[$sWeekDay]; $aDays[] = $aWEEKDAYTON[$sWeekDay];
} } else {
else
{
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_WEEKDAYS."' (found '$sWeekDay')"); throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_WEEKDAYS."' (found '$sWeekDay')");
} }
} }
} }
if (count($aDays) === 0) if (count($aDays) === 0) {
{
throw new ProcessInvalidConfigException($this->GetModuleName().': missing setting \''.static::MODULE_SETTING_WEEKDAYS.'\''); throw new ProcessInvalidConfigException($this->GetModuleName().': missing setting \''.static::MODULE_SETTING_WEEKDAYS.'\'');
} }
$aDays = array_unique($aDays); $aDays = array_unique($aDays);
@@ -185,8 +176,7 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
static::DEFAULT_MODULE_SETTING_ENABLED static::DEFAULT_MODULE_SETTING_ENABLED
); );
if (!$bEnabled) if (!$bEnabled) {
{
return new DateTime('3000-01-01'); return new DateTime('3000-01-01');
} }
@@ -202,21 +192,17 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
static::GetDefaultModuleSettingTime() static::GetDefaultModuleSettingTime()
); );
$sProcessTime = trim($sProcessTime); $sProcessTime = trim($sProcessTime);
if (!preg_match('/[0-2]\d:[0-5]\d/', $sProcessTime)) if (!preg_match('/[0-2]\d:[0-5]\d/', $sProcessTime)) {
{
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')"); throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')");
} }
$oNow = new DateTime($sCurrentTime); $oNow = new DateTime($sCurrentTime);
$iNextPos = false; $iNextPos = false;
$sDay = $oNow->format('N'); $sDay = $oNow->format('N');
for ($iDay = (int) $sDay; $iDay <= 7; $iDay++) for ($iDay = (int) $sDay; $iDay <= 7; $iDay++) {
{
$iNextPos = array_search($iDay, $aDays, true); $iNextPos = array_search($iDay, $aDays, true);
if ($iNextPos !== false) if ($iNextPos !== false) {
{ if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sProcessTime)) {
if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sProcessTime))
{
break; break;
} }
$iNextPos = false; // necessary on sundays $iNextPos = false; // necessary on sundays
@@ -225,17 +211,14 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
// 3rd - Compute the result // 3rd - Compute the result
// //
if ($iNextPos === false) if ($iNextPos === false) {
{
// Jump to the first day within the next week // Jump to the first day within the next week
$iFirstDayOfWeek = $aDays[0]; $iFirstDayOfWeek = $aDays[0];
$iDayMove = $oNow->format('N') - $iFirstDayOfWeek; $iDayMove = $oNow->format('N') - $iFirstDayOfWeek;
$oRet = clone $oNow; $oRet = clone $oNow;
$oRet->modify(-$iDayMove.' days'); $oRet->modify(-$iDayMove.' days');
$oRet->modify('+1 weeks'); $oRet->modify('+1 weeks');
} } else {
else
{
$iNextDayOfWeek = $aDays[$iNextPos]; $iNextDayOfWeek = $aDays[$iNextPos];
$iMove = $iNextDayOfWeek - $oNow->format('N'); $iMove = $iNextDayOfWeek - $oNow->format('N');
$oRet = clone $oNow; $oRet = clone $oNow;

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 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/>
/** /**
* Class BackgroundTask * Class BackgroundTask
* A class to record information about the execution of background processes ({@link iProcess} impl) * A class to record information about the execution of background processes ({@link iProcess} impl)
@@ -46,33 +46,33 @@ class BackgroundTask extends DBObject
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb", "category" => "core/cmdb",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "class_name", "name_attcode" => "class_name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_backgroundtask", "db_table" => "priv_backgroundtask",
"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("class_name", array("allowed_values"=>null, "sql"=>"class_name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("class_name", ["allowed_values" => null, "sql" => "class_name", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("first_run_date", array("allowed_values"=>null, "sql"=>"first_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("first_run_date", ["allowed_values" => null, "sql" => "first_run_date", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("latest_run_date", array("allowed_values"=>null, "sql"=>"latest_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("latest_run_date", ["allowed_values" => null, "sql" => "latest_run_date", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("next_run_date", array("allowed_values"=>null, "sql"=>"next_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("next_run_date", ["allowed_values" => null, "sql" => "next_run_date", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("total_exec_count", array("allowed_values"=>null, "sql"=>"total_exec_count", "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("total_exec_count", ["allowed_values" => null, "sql" => "total_exec_count", "default_value" => "0", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDecimal("latest_run_duration", array("allowed_values"=>null, "sql"=>"latest_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDecimal("latest_run_duration", ["allowed_values" => null, "sql" => "latest_run_duration", "digits" => 8, "decimals" => 3, "default_value" => "0", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDecimal("min_run_duration", array("allowed_values"=>null, "sql"=>"min_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDecimal("min_run_duration", ["allowed_values" => null, "sql" => "min_run_duration", "digits" => 8, "decimals" => 3, "default_value" => "0", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDecimal("max_run_duration", array("allowed_values"=>null, "sql"=>"max_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDecimal("max_run_duration", ["allowed_values" => null, "sql" => "max_run_duration", "digits" => 8, "decimals" => 3, "default_value" => "0", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", array("allowed_values"=>null, "sql"=>"average_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", ["allowed_values" => null, "sql" => "average_run_duration", "digits" => 8, "decimals" => 3, "default_value" => "0", "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeBoolean("running", array("allowed_values"=>null, "sql"=>"running", "default_value"=>false, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeBoolean("running", ["allowed_values" => null, "sql" => "running", "default_value" => false, "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused,removed'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("status", ["allowed_values" => new ValueSetEnum('active,paused,removed'), "sql" => "status", "default_value" => 'active', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("system_user", array("allowed_values"=>null, "sql"=>"system_user", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("system_user", ["allowed_values" => null, "sql" => "system_user", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
} }
public function ComputeDurations($fLatestDuration) public function ComputeDurations($fLatestDuration)
@@ -81,12 +81,10 @@ class BackgroundTask extends DBObject
$fAverageDuration = ($this->Get('average_run_duration') * $iTotalRun + $fLatestDuration) / (1 + $iTotalRun); $fAverageDuration = ($this->Get('average_run_duration') * $iTotalRun + $fLatestDuration) / (1 + $iTotalRun);
$this->Set('average_run_duration', sprintf('%.3f', $fAverageDuration)); $this->Set('average_run_duration', sprintf('%.3f', $fAverageDuration));
$this->Set('total_exec_count', 1 + $iTotalRun); $this->Set('total_exec_count', 1 + $iTotalRun);
if ($fLatestDuration < $this->Get('min_run_duration')) if ($fLatestDuration < $this->Get('min_run_duration')) {
{
$this->Set('min_run_duration', sprintf('%.3f', $fLatestDuration)); $this->Set('min_run_duration', sprintf('%.3f', $fLatestDuration));
} }
if ($fLatestDuration > $this->Get('max_run_duration')) if ($fLatestDuration > $this->Get('max_run_duration')) {
{
$this->Set('max_run_duration', sprintf('%.3f', $fLatestDuration)); $this->Set('max_run_duration', sprintf('%.3f', $fLatestDuration));
} }
$this->Set('latest_run_duration', sprintf('%.3f', $fLatestDuration)); $this->Set('latest_run_duration', sprintf('%.3f', $fLatestDuration));

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Persistent class (internal) cmdbChange * Persistent class (internal) cmdbChange
* *
@@ -17,26 +18,26 @@ class CMDBChange extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "date", "name_attcode" => "date",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_change", "db_table" => "priv_change",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "", "db_finalclass_field" => "",
'indexes' => array( 'indexes' => [
array('origin'), ['origin'],
), ],
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("date", ["allowed_values" => null, "sql" => "date", "default_value" => "NOW()", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("userinfo", ["allowed_values" => null, "sql" => "userinfo", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"User", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", ["allowed_values" => null, "sql" => "user_id", "targetclass" => "User", "is_null_allowed" => true, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum(implode(',', [CMDBChangeOrigin::INTERACTIVE, CMDBChangeOrigin::CSV_INTERACTIVE, CMDBChangeOrigin::CSV_IMPORT, CMDBChangeOrigin::WEBSERVICE_SOAP, CMDBChangeOrigin::WEBSERVICE_REST, CMDBChangeOrigin::SYNCHRO_DATA_SOURCE, CMDBChangeOrigin::EMAIL_PROCESSING, CMDBChangeOrigin::CUSTOM_EXTENSION])), "sql"=>"origin", "default_value"=>CMDBChangeOrigin::INTERACTIVE, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("origin", ["allowed_values" => new ValueSetEnum(implode(',', [CMDBChangeOrigin::INTERACTIVE, CMDBChangeOrigin::CSV_INTERACTIVE, CMDBChangeOrigin::CSV_IMPORT, CMDBChangeOrigin::WEBSERVICE_SOAP, CMDBChangeOrigin::WEBSERVICE_REST, CMDBChangeOrigin::SYNCHRO_DATA_SOURCE, CMDBChangeOrigin::EMAIL_PROCESSING, CMDBChangeOrigin::CUSTOM_EXTENSION])), "sql" => "origin", "default_value" => CMDBChangeOrigin::INTERACTIVE, "is_null_allowed" => true, "depends_on" => []]));
} }
/** /**
@@ -48,12 +49,9 @@ class CMDBChange extends DBObject
*/ */
public static function GetCurrentUserName() public static function GetCurrentUserName()
{ {
if (UserRights::IsImpersonated()) if (UserRights::IsImpersonated()) {
{
$sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName()); $sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName());
} } else {
else
{
$sUserString = UserRights::GetUserFriendlyName(); $sUserString = UserRights::GetUserFriendlyName();
} }
return $sUserString; return $sUserString;
@@ -74,12 +72,9 @@ class CMDBChange extends DBObject
public function GetUserName() public function GetUserName()
{ {
if (preg_match('/^(.*)\\(CSV\\)$/i', $this->Get('userinfo'), $aMatches)) if (preg_match('/^(.*)\\(CSV\\)$/i', $this->Get('userinfo'), $aMatches)) {
{
$sUser = $aMatches[1]; $sUser = $aMatches[1];
} } else {
else
{
$sUser = $this->Get('userinfo'); $sUser = $this->Get('userinfo');
} }
return $sUser; return $sUser;

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/>
/** /**
* Persistent classes (internal) : cmdbChangeOp and derived * Persistent classes (internal) : cmdbChangeOp and derived
* *
@@ -24,7 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
/** /**
* Various atomic change operations, to be tracked * Various atomic change operations, to be tracked
* *
@@ -50,31 +49,31 @@ class CMDBChangeOp extends DBObject implements iCMDBChangeOp
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop", "db_table" => "priv_changeop",
"db_key_field" => "id", "db_key_field" => "id",
"db_finalclass_field" => "optype", "db_finalclass_field" => "optype",
'indexes' => array( 'indexes' => [
array('objclass', 'objkey'), ['objclass', 'objkey'],
), ],
); ];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes(); //MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("change", ["allowed_values" => null, "sql" => "changeid", "targetclass" => "CMDBChange", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date"))); MetaModel::Init_AddAttribute(new AttributeExternalField("date", ["allowed_values" => null, "extkey_attcode" => "change", "target_attcode" => "date"]));
MetaModel::Init_AddAttribute(new AttributeExternalField("userinfo", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"userinfo"))); MetaModel::Init_AddAttribute(new AttributeExternalField("userinfo", ["allowed_values" => null, "extkey_attcode" => "change", "target_attcode" => "userinfo"]));
MetaModel::Init_AddAttribute(new AttributeExternalField("user_id", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"user_id"))); MetaModel::Init_AddAttribute(new AttributeExternalField("user_id", ["allowed_values" => null, "extkey_attcode" => "change", "target_attcode" => "user_id"]));
MetaModel::Init_AddAttribute(new AttributeString("objclass", array("allowed_values"=>null, "sql"=>"objclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("objclass", ["allowed_values" => null, "sql" => "objclass", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeObjectKey("objkey", array("allowed_values"=>null, "class_attcode"=>"objclass", "sql"=>"objkey", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeObjectKey("objkey", ["allowed_values" => null, "class_attcode" => "objclass", "sql" => "objkey", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_SetZListItems('details', array('change', 'date', 'userinfo')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['change', 'date', 'userinfo']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('change', 'date', 'userinfo')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', ['change', 'date', 'userinfo']); // Attributes to be displayed for the complete details
} }
/** /**
@@ -119,17 +118,17 @@ class CMDBChangeOpCreate extends CMDBChangeOp
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_create", "db_table" => "priv_changeop_create",
"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();
} }
@@ -155,24 +154,24 @@ class CMDBChangeOpDelete extends CMDBChangeOp
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_delete", "db_table" => "priv_changeop_delete",
"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();
// Final class of the object (objclass must be set to the root class for efficiency purposes) // Final class of the object (objclass must be set to the root class for efficiency purposes)
MetaModel::Init_AddAttribute(new AttributeString("fclass", array("allowed_values"=>null, "sql"=>"fclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("fclass", ["allowed_values" => null, "sql" => "fclass", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
// Last friendly name of the object // Last friendly name of the object
MetaModel::Init_AddAttribute(new AttributeString("fname", array("allowed_values"=>null, "sql"=>"fname", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("fname", ["allowed_values" => null, "sql" => "fname", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
} }
/** /**
@@ -196,24 +195,24 @@ class CMDBChangeOpSetAttribute extends CMDBChangeOp
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt", "db_table" => "priv_changeop_setatt",
"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("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("attcode", ["allowed_values" => null, "sql" => "attcode", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
} }
@@ -229,25 +228,25 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_scalar", "db_table" => "priv_changeop_setatt_scalar",
"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("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("oldvalue", ["allowed_values" => null, "sql" => "oldvalue", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("newvalue", ["allowed_values" => null, "sql" => "newvalue", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for a list
} }
/** /**
@@ -262,9 +261,10 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes... return '';
} // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -288,25 +288,25 @@ class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_tagset", "db_table" => "priv_changeop_setatt_tagset",
"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 AttributeText("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("oldvalue", ["allowed_values" => null, "sql" => "oldvalue", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeText("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("newvalue", ["allowed_values" => null, "sql" => "newvalue", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for a list
} }
/** /**
@@ -322,9 +322,10 @@ class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($sTargetObjectClass, $sAttCode, UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($sTargetObjectClass, $sAttCode, UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes... return '';
} // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -348,17 +349,17 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_url", "db_table" => "priv_changeop_setatt_url",
"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();
@@ -371,12 +372,12 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
// 2. from the iTop config // 2. from the iTop config
// 3. config parameter default value // 3. config parameter default value
// see \AttributeURL::GetValidationPattern // see \AttributeURL::GetValidationPattern
MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", array("allowed_values" => null, "sql" => "oldvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "validation_pattern" => '.*'))); MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", ["allowed_values" => null, "sql" => "oldvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => [], "validation_pattern" => '.*']));
MetaModel::Init_AddAttribute(new AttributeURL("newvalue", array("allowed_values" => null, "sql" => "newvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "validation_pattern" => '.*'))); MetaModel::Init_AddAttribute(new AttributeURL("newvalue", ["allowed_values" => null, "sql" => "newvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => [], "validation_pattern" => '.*']));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode', 'oldvalue', 'newvalue']); // Attributes to be displayed for a list
} }
/** /**
@@ -391,9 +392,10 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes... return '';
} // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -417,24 +419,24 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_data", "db_table" => "priv_changeop_setatt_data",
"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 AttributeBlob("prevdata", array("depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeBlob("prevdata", ["depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -452,8 +454,7 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) { if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -496,24 +497,24 @@ class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_pwd", "db_table" => "priv_changeop_setatt_pwd",
"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 AttributeOneWayPassword("prev_pwd", array("sql" => 'data', "default_value" => '', "is_null_allowed"=> true, "allowed_values" => null, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeOneWayPassword("prev_pwd", ["sql" => 'data', "default_value" => '', "is_null_allowed" => true, "allowed_values" => null, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -531,15 +532,11 @@ class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
} } else {
else
{
// The attribute was renamed or removed from the object ? // The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode'); $sAttName = $this->Get('attcode');
} }
@@ -559,24 +556,24 @@ class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_encrypted", "db_table" => "priv_changeop_setatt_encrypted",
"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 AttributeEncryptedString("prevstring", array("sql" => 'data', "default_value" => '', "is_null_allowed"=> true, "allowed_values" => null, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEncryptedString("prevstring", ["sql" => 'data', "default_value" => '', "is_null_allowed" => true, "allowed_values" => null, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -594,15 +591,11 @@ class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
} } else {
else
{
// The attribute was renamed or removed from the object ? // The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode'); $sAttName = $this->Get('attcode');
} }
@@ -625,24 +618,24 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_text", "db_table" => "priv_changeop_setatt_text",
"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 AttributeText("prevdata", array("allowed_values"=>null, "sql"=>"prevdata", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeText("prevdata", ["allowed_values" => null, "sql" => "prevdata", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -660,15 +653,11 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
} } else {
else
{
// The attribute was renamed or removed from the object ? // The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode'); $sAttName = $this->Get('attcode');
} }
@@ -693,24 +682,24 @@ class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_longtext", "db_table" => "priv_changeop_setatt_longtext",
"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 AttributeLongText("prevdata", array("allowed_values"=>null, "sql"=>"prevdata", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeLongText("prevdata", ["allowed_values" => null, "sql" => "prevdata", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -725,15 +714,11 @@ class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
} } else {
else
{
// The attribute was renamed or removed from the object ? // The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode'); $sAttName = $this->Get('attcode');
} }
@@ -758,23 +743,23 @@ class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_html", "db_table" => "priv_changeop_setatt_html",
"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();
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -789,8 +774,7 @@ class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) { if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -822,24 +806,24 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_log", "db_table" => "priv_changeop_setatt_log",
"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 AttributeInteger("lastentry", array("allowed_values"=>null, "sql"=>"lastentry", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("lastentry", ["allowed_values" => null, "sql" => "lastentry", "default_value" => 0, "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -857,15 +841,11 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
} } else {
else
{
// The attribute was renamed or removed from the object ? // The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode'); $sAttName = $this->Get('attcode');
} }
@@ -885,7 +865,7 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
*/ */
protected function ToHtml($sRawText) protected function ToHtml($sRawText)
{ {
return str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sRawText)); return str_replace(["\r\n", "\n", "\r"], "<br/>", utils::EscapeHtml($sRawText));
} }
} }
@@ -901,19 +881,19 @@ class CMDBChangeOpPlugin extends CMDBChangeOp
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_plugin", "db_table" => "priv_changeop_plugin",
"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("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => '', "is_null_allowed" => false, "depends_on" => []]));
/* May be used later when implementing an extension mechanism that will allow the plug-ins to store some extra information and still degrades gracefully when the plug-in is desinstalled /* May be used later when implementing an extension mechanism that will allow the plug-ins to store some extra information and still degrades gracefully when the plug-in is desinstalled
MetaModel::Init_AddAttribute(new AttributeString("extension_class", array("allowed_values"=>null, "sql"=>"extension_class", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("extension_class", array("allowed_values"=>null, "sql"=>"extension_class", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("extension_id", array("allowed_values"=>null, "sql"=>"extension_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("extension_id", array("allowed_values"=>null, "sql"=>"extension_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
@@ -942,24 +922,24 @@ abstract class CMDBChangeOpSetAttributeLinks extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_links", "db_table" => "priv_changeop_links",
"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();
// Note: item class/id points to the link class itself in case of a direct link set (e.g. Server::interface_list => Interface) // Note: item class/id points to the link class itself in case of a direct link set (e.g. Server::interface_list => Interface)
// item class/id points to the remote class in case of a indirect link set (e.g. Server::contract_list => Contract) // item class/id points to the remote class in case of a indirect link set (e.g. Server::contract_list => Contract)
MetaModel::Init_AddAttribute(new AttributeString("item_class", array("allowed_values"=>null, "sql"=>"item_class", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("item_class", ["allowed_values" => null, "sql" => "item_class", "default_value" => '', "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeInteger("item_id", array("allowed_values"=>null, "sql"=>"item_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("item_id", ["allowed_values" => null, "sql" => "item_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => []]));
} }
} }
@@ -975,21 +955,21 @@ class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLin
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_links_addremove", "db_table" => "priv_changeop_links_addremove",
"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 AttributeEnum("type", array("allowed_values"=>new ValueSetEnum('added,removed'), "sql"=>"type", "default_value"=>"added", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeEnum("type", ["allowed_values" => new ValueSetEnum('added,removed'), "sql" => "type", "default_value" => "added", "is_null_allowed" => false, "depends_on" => []]));
} }
/** /**
@@ -1004,9 +984,10 @@ class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLin
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes... return '';
} // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -1014,8 +995,7 @@ class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLin
$sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id')); $sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id'));
$sResult = $sAttName.' - '; $sResult = $sAttName.' - ';
switch ($this->Get('type')) switch ($this->Get('type')) {
{
case 'added': case 'added':
$sResult .= Dict::Format('Change:LinkSet:Added', $sItemDesc); $sResult .= Dict::Format('Change:LinkSet:Added', $sItemDesc);
break; break;
@@ -1042,21 +1022,21 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_links_tune", "db_table" => "priv_changeop_links_tune",
"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 AttributeInteger("link_id", array("allowed_values"=>null, "sql"=>"link_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("link_id", ["allowed_values" => null, "sql" => "link_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => []]));
} }
/** /**
@@ -1071,9 +1051,10 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes... return '';
} // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
@@ -1086,13 +1067,10 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
$oSearch = new DBObjectSearch('CMDBChangeOpSetAttribute'); $oSearch = new DBObjectSearch('CMDBChangeOpSetAttribute');
$oSearch->AddCondition('change', $this->Get('change'), '='); $oSearch->AddCondition('change', $this->Get('change'), '=');
$oSearch->AddCondition('objkey', $this->Get('link_id'), '='); $oSearch->AddCondition('objkey', $this->Get('link_id'), '=');
if (count($aLinkClasses) == 1) if (count($aLinkClasses) == 1) {
{
// Faster than the whole building of the expression below for just one value ?? // Faster than the whole building of the expression below for just one value ??
$oSearch->AddCondition('objclass', $sLinkClass, '='); $oSearch->AddCondition('objclass', $sLinkClass, '=');
} } else {
else
{
$oField = new FieldExpression('objclass', $oSearch->GetClassAlias()); $oField = new FieldExpression('objclass', $oSearch->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($aLinkClasses)).')'; $sListExpr = '('.implode(', ', CMDBSource::Quote($aLinkClasses)).')';
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr"; $sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
@@ -1100,13 +1078,11 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
$oSearch->AddConditionExpression($oNewCondition); $oSearch->AddConditionExpression($oNewCondition);
} }
$oSet = new DBObjectSet($oSearch); $oSet = new DBObjectSet($oSearch);
$aChanges = array(); $aChanges = [];
while ($oChangeOp = $oSet->Fetch()) while ($oChangeOp = $oSet->Fetch()) {
{
$aChanges[] = $oChangeOp->GetDescription(); $aChanges[] = $oChangeOp->GetDescription();
} }
if (count($aChanges) == 0) if (count($aChanges) == 0) {
{
return ''; return '';
} }
@@ -1132,24 +1108,24 @@ class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute
*/ */
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "core/cmdb, grant_by_profile", "category" => "core/cmdb, grant_by_profile",
"key_type" => "", "key_type" => "",
"name_attcode" => "change", "name_attcode" => "change",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_changeop_setatt_custfields", "db_table" => "priv_changeop_setatt_custfields",
"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 AttributeLongText("prevdata", array("allowed_values"=>null, "sql"=>"prevdata", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeLongText("prevdata", ["allowed_values" => null, "sql" => "prevdata", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
// Display lists // Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list MetaModel::Init_SetZListItems('list', ['date', 'userinfo', 'attcode']); // Attributes to be displayed for a list
} }
/** /**
@@ -1158,26 +1134,22 @@ class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute
public function GetDescription() public function GetDescription()
{ {
$sResult = ''; $sResult = '';
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
{
$oTargetObjectClass = $this->Get('objclass'); $oTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey'); $oTargetObjectKey = $this->Get('objkey');
$oTargetSearch = new DBObjectSearch($oTargetObjectClass); $oTargetSearch = new DBObjectSearch($oTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch); $oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
{
$aValues = json_decode($this->Get('prevdata'), true); $aValues = json_decode($this->Get('prevdata'), true);
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel(); $sAttName = $oAttDef->GetLabel();
try try {
{
$oHandler = $oAttDef->GetHandler($aValues); $oHandler = $oAttDef->GetHandler($aValues);
$sValueDesc = $oHandler->GetAsHTML($aValues); $sValueDesc = $oHandler->GetAsHTML($aValues);
} } catch (Exception $e) {
catch (Exception $e) {
$sValueDesc = 'Custom field error: '.utils::EscapeHtml($e->getMessage()); $sValueDesc = 'Custom field error: '.utils::EscapeHtml($e->getMessage());
} }
$sTextView = '<div>'.$sValueDesc.'</div>'; $sTextView = '<div>'.$sValueDesc.'</div>';

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2010-2024 Combodo SAS * Copyright (C) 2010-2024 Combodo SAS
* *
@@ -18,7 +19,6 @@
* along with iTop. If not, see <http://www.gnu.org/licenses/> * along with iTop. If not, see <http://www.gnu.org/licenses/>
*/ */
/** /**
* Any extension to compute things like a stop watch deadline or working hours * Any extension to compute things like a stop watch deadline or working hours
* *
@@ -100,8 +100,7 @@ class DefaultWorkingTimeComputer implements iWorkingTimeComputer
*/ */
public function GetDeadline($oObject, $iDuration, DateTime $oStartDate) public function GetDeadline($oObject, $iDuration, DateTime $oStartDate)
{ {
if (class_exists('WorkingTimeRecorder')) if (class_exists('WorkingTimeRecorder')) {
{
WorkingTimeRecorder::Trace(WorkingTimeRecorder::TRACE_DEBUG, __class__.'::'.__function__); WorkingTimeRecorder::Trace(WorkingTimeRecorder::TRACE_DEBUG, __class__.'::'.__function__);
} }
//echo "GetDeadline - default: ".$oStartDate->format('Y-m-d H:i:s')." + $iDuration<br/>\n"; //echo "GetDeadline - default: ".$oStartDate->format('Y-m-d H:i:s')." + $iDuration<br/>\n";
@@ -109,8 +108,7 @@ class DefaultWorkingTimeComputer implements iWorkingTimeComputer
// the specified duration to the given date/time // the specified duration to the given date/time
$oResult = clone $oStartDate; $oResult = clone $oStartDate;
$oResult->modify($iDuration.' seconds'); $oResult->modify($iDuration.' seconds');
if (class_exists('WorkingTimeRecorder')) if (class_exists('WorkingTimeRecorder')) {
{
WorkingTimeRecorder::SetValues($oStartDate->format('U'), $oResult->format('U'), $iDuration, WorkingTimeRecorder::COMPUTED_END); WorkingTimeRecorder::SetValues($oStartDate->format('U'), $oResult->format('U'), $iDuration, WorkingTimeRecorder::COMPUTED_END);
} }
return $oResult; return $oResult;
@@ -121,14 +119,12 @@ class DefaultWorkingTimeComputer implements iWorkingTimeComputer
*/ */
public function GetOpenDuration($oObject, DateTime $oStartDate, DateTime $oEndDate) public function GetOpenDuration($oObject, DateTime $oStartDate, DateTime $oEndDate)
{ {
if (class_exists('WorkingTimeRecorder')) if (class_exists('WorkingTimeRecorder')) {
{
WorkingTimeRecorder::Trace(WorkingTimeRecorder::TRACE_DEBUG, __class__.'::'.__function__); WorkingTimeRecorder::Trace(WorkingTimeRecorder::TRACE_DEBUG, __class__.'::'.__function__);
} }
//echo "GetOpenDuration - default: ".$oStartDate->format('Y-m-d H:i:s')." to ".$oEndDate->format('Y-m-d H:i:s')."<br/>\n"; //echo "GetOpenDuration - default: ".$oStartDate->format('Y-m-d H:i:s')." to ".$oEndDate->format('Y-m-d H:i:s')."<br/>\n";
$iDuration = abs($oEndDate->format('U') - $oStartDate->format('U')); $iDuration = abs($oEndDate->format('U') - $oStartDate->format('U'));
if (class_exists('WorkingTimeRecorder')) if (class_exists('WorkingTimeRecorder')) {
{
WorkingTimeRecorder::SetValues($oStartDate->format('U'), $oEndDate->format('U'), $iDuration, WorkingTimeRecorder::COMPUTED_DURATION); WorkingTimeRecorder::SetValues($oStartDate->format('U'), $oEndDate->format('U'), $iDuration, WorkingTimeRecorder::COMPUTED_DURATION);
} }
return $iDuration; return $iDuration;

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2016-2024 Combodo SAS // Copyright (C) 2016-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/>
/** /**
* Simple helper class for keeping track of the context inside the call stack * Simple helper class for keeping track of the context inside the call stack
* *
@@ -74,7 +74,7 @@ class ContextTag
*/ */
public const TAG_OBJECT_SEARCH = 'ObjectSearch'; public const TAG_OBJECT_SEARCH = 'ObjectSearch';
protected static $aStack = array(); protected static $aStack = [];
/** /**
* Store a context tag on the stack * Store a context tag on the stack
@@ -124,33 +124,29 @@ class ContextTag
*/ */
public static function GetTags() public static function GetTags()
{ {
$aRawTags = array( $aRawTags = [
ContextTag::TAG_REST, ContextTag::TAG_REST,
ContextTag::TAG_SYNCHRO, ContextTag::TAG_SYNCHRO,
ContextTag::TAG_SETUP, ContextTag::TAG_SETUP,
ContextTag::TAG_CONSOLE, ContextTag::TAG_CONSOLE,
ContextTag::TAG_CRON, ContextTag::TAG_CRON,
ContextTag::TAG_PORTAL); ContextTag::TAG_PORTAL];
$aTags = array(); $aTags = [];
foreach ($aRawTags as $sRawTag) foreach ($aRawTags as $sRawTag) {
{
$aTags[$sRawTag] = Dict::S("Core:Context={$sRawTag}"); $aTags[$sRawTag] = Dict::S("Core:Context={$sRawTag}");
} }
$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);
} }
foreach ($aDispatchers as $sPortalId => $oDispatcher) foreach ($aDispatchers as $sPortalId => $oDispatcher) {
{ if ($sPortalId != 'backoffice') {
if ($sPortalId != 'backoffice')
{
$aTags['Portal:'.$sPortalId] = $oDispatcher->GetLabel(); $aTags['Portal:'.$sPortalId] = $oDispatcher->GetLabel();
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -17,14 +18,12 @@
* 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
*/ */
/** /**
* Class ItopCounter * Class ItopCounter
* *
*/ */
final class ItopCounter final class ItopCounter
{ {
/** /**
* Key based counter. * Key based counter.
* The counter is protected against concurrency script. * The counter is protected against concurrency script.
@@ -48,8 +47,7 @@ final class ItopCounter
$oiTopMutex->Lock(); $oiTopMutex->Lock();
$bIsInsideTransaction = CMDBSource::IsInsideTransaction(); $bIsInsideTransaction = CMDBSource::IsInsideTransaction();
if ($bIsInsideTransaction) if ($bIsInsideTransaction) {
{
// # Transaction isolation hack: // # Transaction isolation hack:
// When inside a transaction, we need to open a new connection for the counter. // When inside a transaction, we need to open a new connection for the counter.
// So it is visible immediately to the connections outside of the transaction. // So it is visible immediately to the connections outside of the transaction.
@@ -59,75 +57,61 @@ final class ItopCounter
// we did not wanted this! As opening a short connection is less prone to starving than a long running one. // we did not wanted this! As opening a short connection is less prone to starving than a long running one.
// Plus it would trigger way more deadlocks! // Plus it would trigger way more deadlocks!
$hDBLink = self::InitMySQLSession(); $hDBLink = self::InitMySQLSession();
} } else {
else
{
$hDBLink = CMDBSource::GetMysqli(); $hDBLink = CMDBSource::GetMysqli();
} }
try try {
{ $oFilter = DBObjectSearch::FromOQL('SELECT KeyValueStore WHERE key_name=:key_name AND namespace=:namespace', [
$oFilter = DBObjectSearch::FromOQL('SELECT KeyValueStore WHERE key_name=:key_name AND namespace=:namespace', array(
'key_name' => $sCounterName, 'key_name' => $sCounterName,
'namespace' => $sSelfClassName, 'namespace' => $sSelfClassName,
)); ]);
$oAttDef = MetaModel::GetAttributeDef(KeyValueStore::class, 'value'); $oAttDef = MetaModel::GetAttributeDef(KeyValueStore::class, 'value');
$aAttToLoad = array(KeyValueStore::class => array('value' => $oAttDef)); $aAttToLoad = [KeyValueStore::class => ['value' => $oAttDef]];
$sSql = $oFilter->MakeSelectQuery(array(), array(), $aAttToLoad); $sSql = $oFilter->MakeSelectQuery([], [], $aAttToLoad);
$hResult = mysqli_query($hDBLink, $sSql); $hResult = mysqli_query($hDBLink, $sSql);
$aCounter = mysqli_fetch_array($hResult, MYSQLI_NUM); $aCounter = mysqli_fetch_array($hResult, MYSQLI_NUM);
mysqli_free_result($hResult); mysqli_free_result($hResult);
//Rebuild the filter, as the MakeSelectQuery polluted the orignal and it cannot be reused //Rebuild the filter, as the MakeSelectQuery polluted the orignal and it cannot be reused
$oFilter = DBObjectSearch::FromOQL('SELECT KeyValueStore WHERE key_name=:key_name AND namespace=:namespace', array( $oFilter = DBObjectSearch::FromOQL('SELECT KeyValueStore WHERE key_name=:key_name AND namespace=:namespace', [
'key_name' => $sCounterName, 'key_name' => $sCounterName,
'namespace' => $sSelfClassName, 'namespace' => $sSelfClassName,
)); ]);
if (is_null($aCounter)) if (is_null($aCounter)) {
{ if (null != $oNewObjectValueProvider) {
if (null != $oNewObjectValueProvider)
{
$iComputedValue = $oNewObjectValueProvider(); $iComputedValue = $oNewObjectValueProvider();
} } else {
else
{
$iComputedValue = 0; $iComputedValue = 0;
} }
$iCurrentValue = $iComputedValue + 1; $iCurrentValue = $iComputedValue + 1;
$aQueryParams = array( $aQueryParams = [
'key_name' => $sCounterName, 'key_name' => $sCounterName,
'value' => "$iCurrentValue", 'value' => "$iCurrentValue",
'namespace' => $sSelfClassName, 'namespace' => $sSelfClassName,
); ];
$sSql = $oFilter->MakeInsertQuery($aQueryParams); $sSql = $oFilter->MakeInsertQuery($aQueryParams);
} } else {
else
{
$iCurrentValue = (int) $aCounter[1]; $iCurrentValue = (int) $aCounter[1];
$iCurrentValue++; $iCurrentValue++;
$aQueryParams = array( $aQueryParams = [
'value' => "$iCurrentValue", 'value' => "$iCurrentValue",
); ];
$sSql = $oFilter->MakeUpdateQuery($aQueryParams); $sSql = $oFilter->MakeUpdateQuery($aQueryParams);
} }
$hResult = mysqli_query($hDBLink, $sSql); $hResult = mysqli_query($hDBLink, $sSql);
} } catch (Exception $e) {
catch(Exception $e)
{
IssueLog::Error($e->getMessage()); IssueLog::Error($e->getMessage());
throw $e; throw $e;
} } finally {
finally if ($bIsInsideTransaction) {
{
if ($bIsInsideTransaction)
{
mysqli_close($hDBLink); mysqli_close($hDBLink);
} }
$oiTopMutex->Unlock(); $oiTopMutex->Unlock();
@@ -157,8 +141,7 @@ final class ItopCounter
{ {
$sRootClass = MetaModel::GetRootClass($sLeafClass); $sRootClass = MetaModel::GetRootClass($sLeafClass);
$oNewObjectCallback = function() use ($sRootClass) $oNewObjectCallback = function () use ($sRootClass) {
{
$sRootTable = MetaModel::DBGetTable($sRootClass); $sRootTable = MetaModel::DBGetTable($sRootClass);
$sIdField = MetaModel::DBGetKey($sRootClass); $sIdField = MetaModel::DBGetKey($sRootClass);
@@ -186,17 +169,14 @@ final class ItopCounter
$hDBLink = CMDBSource::GetMysqliInstance($sDBHost, $sDBUser, $sDBPwd, $sDBName, $bDBTlsEnabled, $sDBTlsCA, false); $hDBLink = CMDBSource::GetMysqliInstance($sDBHost, $sDBUser, $sDBPwd, $sDBName, $bDBTlsEnabled, $sDBTlsCA, false);
if (!$hDBLink) if (!$hDBLink) {
{ throw new MySQLException('Could not connect to the DB server '.mysqli_connect_error().' (mysql errno: '.mysqli_connect_errno(), ['host' => $sDBHost, 'user' => $sDBUser]);
throw new MySQLException('Could not connect to the DB server '.mysqli_connect_error().' (mysql errno: '.mysqli_connect_errno(), array('host' => $sDBHost, 'user' => $sDBUser));
} }
return $hDBLink; return $hDBLink;
} }
} }
/** /**
* Persistent classes for a CMDB * Persistent classes for a CMDB
* *
@@ -208,44 +188,43 @@ class KeyValueStore extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array( $aParams = [
'category' => '', 'category' => '',
'key_type' => 'autoincrement', 'key_type' => 'autoincrement',
'name_attcode' => array('key_name'), 'name_attcode' => ['key_name'],
'state_attcode' => '', 'state_attcode' => '',
'reconc_keys' => array(''), 'reconc_keys' => [''],
'db_table' => 'key_value_store', 'db_table' => 'key_value_store',
'db_key_field' => 'id', 'db_key_field' => 'id',
'db_finalclass_field' => '', 'db_finalclass_field' => '',
'indexes' => array ( 'indexes' => [
array ( [
0 => 'key_name', 0 => 'key_name',
1 => 'namespace', 1 => 'namespace',
), ],
),); ],];
MetaModel::Init_Params($aParams); MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes(); MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("namespace", array("allowed_values"=>null, "sql"=>'namespace', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false))); MetaModel::Init_AddAttribute(new AttributeString("namespace", ["allowed_values" => null, "sql" => 'namespace', "default_value" => null, "is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeString("key_name", array("allowed_values"=>null, "sql"=>'key_name', "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false))); MetaModel::Init_AddAttribute(new AttributeString("key_name", ["allowed_values" => null, "sql" => 'key_name', "default_value" => '', "is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_AddAttribute(new AttributeString("value", array("allowed_values"=>null, "sql"=>'value', "default_value"=>'0', "is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false))); MetaModel::Init_AddAttribute(new AttributeString("value", ["allowed_values" => null, "sql" => 'value', "default_value" => '0', "is_null_allowed" => false, "depends_on" => [], "always_load_in_tables" => false]));
MetaModel::Init_SetZListItems('details', array ( MetaModel::Init_SetZListItems('details', [
0 => 'key_name', 0 => 'key_name',
1 => 'value', 1 => 'value',
2 => 'namespace', 2 => 'namespace',
)); ]);
MetaModel::Init_SetZListItems('standard_search', array ( MetaModel::Init_SetZListItems('standard_search', [
0 => 'key_name', 0 => 'key_name',
1 => 'value', 1 => 'value',
2 => 'namespace', 2 => 'namespace',
)); ]);
MetaModel::Init_SetZListItems('list', array ( MetaModel::Init_SetZListItems('list', [
0 => 'key_name', 0 => 'key_name',
1 => 'value', 1 => 'value',
2 => 'namespace', 2 => 'namespace',
)); ]);
; ;
} }
} }

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
@@ -40,18 +41,14 @@ class CSVBulkExport extends TabularBulkExport
{ {
parent::ReadParameters(); parent::ReadParameters();
$this->aStatusInfo['separator'] = utils::ReadParam('separator', ',', true, 'raw_data'); $this->aStatusInfo['separator'] = utils::ReadParam('separator', ',', true, 'raw_data');
if (strtolower($this->aStatusInfo['separator']) == 'tab') if (strtolower($this->aStatusInfo['separator']) == 'tab') {
{
$this->aStatusInfo['separator'] = "\t"; $this->aStatusInfo['separator'] = "\t";
} } elseif (strtolower($this->aStatusInfo['separator']) == 'other') {
else if (strtolower($this->aStatusInfo['separator']) == 'other')
{
$this->aStatusInfo['separator'] = utils::ReadParam('other-separator', ',', true, 'raw_data'); $this->aStatusInfo['separator'] = utils::ReadParam('other-separator', ',', true, 'raw_data');
} }
$this->aStatusInfo['text_qualifier'] = utils::ReadParam('text-qualifier', '"', true, 'raw_data'); $this->aStatusInfo['text_qualifier'] = utils::ReadParam('text-qualifier', '"', true, 'raw_data');
if (strtolower($this->aStatusInfo['text_qualifier']) == 'other') if (strtolower($this->aStatusInfo['text_qualifier']) == 'other') {
{
$this->aStatusInfo['text_qualifier'] = utils::ReadParam('other-text-qualifier', '"', true, 'raw_data'); $this->aStatusInfo['text_qualifier'] = utils::ReadParam('other-text-qualifier', '"', true, 'raw_data');
} }
@@ -59,8 +56,7 @@ class CSVBulkExport extends TabularBulkExport
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true); $this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
$sDateFormatRadio = utils::ReadParam('csv_date_format_radio', ''); $sDateFormatRadio = utils::ReadParam('csv_date_format_radio', '');
switch($sDateFormatRadio) switch ($sDateFormatRadio) {
{
case 'default': case 'default':
// Export from the UI => format = same as is the UI // Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat(); $this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
@@ -77,19 +73,16 @@ class CSVBulkExport extends TabularBulkExport
} }
} }
protected function SuggestField($sClass, $sAttCode) protected function SuggestField($sClass, $sAttCode)
{ {
switch($sAttCode) switch ($sAttCode) {
{
case 'id': // replace 'id' by 'friendlyname' case 'id': // replace 'id' by 'friendlyname'
$sAttCode = 'friendlyname'; $sAttCode = 'friendlyname';
break; break;
default: default:
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey) if ($oAttDef instanceof AttributeExternalKey) {
{
$sAttCode .= '_friendlyname'; $sAttCode .= '_friendlyname';
} }
} }
@@ -99,7 +92,7 @@ class CSVBulkExport extends TabularBulkExport
public function EnumFormParts() public function EnumFormParts()
{ {
return array_merge(parent::EnumFormParts(), array('csv_options' => array('separator', 'charset', 'text-qualifier', 'no_localize', 'formatted_text'), 'interactive_fields_csv' => array('interactive_fields_csv'))); return array_merge(parent::EnumFormParts(), ['csv_options' => ['separator', 'charset', 'text-qualifier', 'no_localize', 'formatted_text'], 'interactive_fields_csv' => ['interactive_fields_csv']]);
} }
/** /**
@@ -128,11 +121,11 @@ class CSVBulkExport extends TabularBulkExport
$sRawSeparator = utils::ReadParam('separator', ',', true, 'raw_data'); $sRawSeparator = utils::ReadParam('separator', ',', true, 'raw_data');
$sCustomDateTimeFormat = utils::ReadParam('', ',', true, 'raw_data'); $sCustomDateTimeFormat = utils::ReadParam('', ',', true, 'raw_data');
$aSep = array( $aSep = [
';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'), ';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'),
',' => Dict::S('UI:CSVImport:SeparatorComma+'), ',' => Dict::S('UI:CSVImport:SeparatorComma+'),
'tab' => Dict::S('UI:CSVImport:SeparatorTab+'), 'tab' => Dict::S('UI:CSVImport:SeparatorTab+'),
); ];
$sOtherSeparator = ''; $sOtherSeparator = '';
if (!array_key_exists($sRawSeparator, $aSep)) { if (!array_key_exists($sRawSeparator, $aSep)) {
$sOtherSeparator = $sRawSeparator; $sOtherSeparator = $sRawSeparator;
@@ -155,10 +148,10 @@ class CSVBulkExport extends TabularBulkExport
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetTextQualifier)); $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetTextQualifier));
$sRawQualifier = utils::ReadParam('text-qualifier', '"', true, 'raw_data'); $sRawQualifier = utils::ReadParam('text-qualifier', '"', true, 'raw_data');
$aQualifiers = array( $aQualifiers = [
'"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'), '"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'),
'\'' => Dict::S('UI:CSVImport:QualifierSimpleQuote+'), '\'' => Dict::S('UI:CSVImport:QualifierSimpleQuote+'),
); ];
$sOtherQualifier = ''; $sOtherQualifier = '';
if (!array_key_exists($sRawQualifier, $aQualifiers)) { if (!array_key_exists($sRawQualifier, $aQualifiers)) {
$sOtherQualifier = $sRawQualifier; $sOtherQualifier = $sRawQualifier;
@@ -230,7 +223,6 @@ class CSVBulkExport extends TabularBulkExport
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oFieldSetDate->AddSubBlock($oRadioCustom); $oFieldSetDate->AddSubBlock($oRadioCustom);
$oP->add_ready_script( $oP->add_ready_script(
<<<EOF <<<EOF
$('#form_part_csv_options').on('preview_updated', function() { FormatDatesInPreview('csv', 'csv'); }); $('#form_part_csv_options').on('preview_updated', function() { FormatDatesInPreview('csv', 'csv'); });
@@ -243,7 +235,6 @@ EOF
return $oPanel; return $oPanel;
break; break;
default: default:
return parent::GetFormPart($oP, $sPartId); return parent::GetFormPart($oP, $sPartId);
} }
@@ -253,8 +244,7 @@ EOF
{ {
if ($sAttCode != 'id') { if ($sAttCode != 'id') {
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime if ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
{
$sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date';
return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>'; return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>';
@@ -266,8 +256,7 @@ EOF
protected function GetValue($oObj, $sAttCode) protected function GetValue($oObj, $sAttCode)
{ {
switch($sAttCode) switch ($sAttCode) {
{
case 'id': case 'id':
$sRet = $oObj->GetKey(); $sRet = $oObj->GetKey();
break; break;
@@ -285,20 +274,17 @@ EOF
$this->aStatusInfo['position'] = 0; $this->aStatusInfo['position'] = 0;
$this->aStatusInfo['total'] = $oSet->Count(); $this->aStatusInfo['total'] = $oSet->Count();
$aData = array(); $aData = [];
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$aData[] = $aFieldSpec['sColLabel']; $aData[] = $aFieldSpec['sColLabel'];
} }
$sFrom = array("\r\n", $this->aStatusInfo['text_qualifier']); $sFrom = ["\r\n", $this->aStatusInfo['text_qualifier']];
$sTo = array("\n", $this->aStatusInfo['text_qualifier'].$this->aStatusInfo['text_qualifier']); $sTo = ["\n", $this->aStatusInfo['text_qualifier'].$this->aStatusInfo['text_qualifier']];
foreach($aData as $idx => $sData) foreach ($aData as $idx => $sData) {
{
// Escape and encode (if needed) the headers // Escape and encode (if needed) the headers
$sEscaped = str_replace($sFrom, $sTo, (string)$sData); $sEscaped = str_replace($sFrom, $sTo, (string)$sData);
$aData[$idx] = $this->aStatusInfo['text_qualifier'].$sEscaped.$this->aStatusInfo['text_qualifier']; $aData[$idx] = $this->aStatusInfo['text_qualifier'].$sEscaped.$this->aStatusInfo['text_qualifier'];
if ($this->aStatusInfo['charset'] != 'UTF-8') if ($this->aStatusInfo['charset'] != 'UTF-8') {
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string // Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket N°991) // and thus to convert field by field and not the whole row or file at once (see ticket N°991)
$aData[$idx] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $aData[$idx]); $aData[$idx] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $aData[$idx]);
@@ -325,29 +311,24 @@ EOF
$sExportDateTimeFormat = $this->aStatusInfo['date_format']; $sExportDateTimeFormat = $this->aStatusInfo['date_format'];
$oPrevDateTimeFormat = AttributeDateTime::GetFormat(); $oPrevDateTimeFormat = AttributeDateTime::GetFormat();
$oPrevDateFormat = AttributeDate::GetFormat(); $oPrevDateFormat = AttributeDate::GetFormat();
if ($sExportDateTimeFormat !== (string)$oPrevDateTimeFormat) if ($sExportDateTimeFormat !== (string)$oPrevDateTimeFormat) {
{
// Change date & time formats // Change date & time formats
$oDateTimeFormat = new DateTimeFormat($sExportDateTimeFormat); $oDateTimeFormat = new DateTimeFormat($sExportDateTimeFormat);
$oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat()); $oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat());
AttributeDateTime::SetFormat($oDateTimeFormat); AttributeDateTime::SetFormat($oDateTimeFormat);
AttributeDate::SetFormat($oDateFormat); AttributeDate::SetFormat($oDateFormat);
} }
while($aRow = $oSet->FetchAssoc()) while ($aRow = $oSet->FetchAssoc()) {
{
set_time_limit(intval($iLoopTimeLimit)); set_time_limit(intval($iLoopTimeLimit));
$aData = array(); $aData = [];
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$sAlias = $aFieldSpec['sAlias']; $sAlias = $aFieldSpec['sAlias'];
$sAttCode = $aFieldSpec['sAttCode']; $sAttCode = $aFieldSpec['sAttCode'];
$sField = ''; $sField = '';
$oObj = $aRow[$sAlias]; $oObj = $aRow[$sAlias];
if ($oObj != null) if ($oObj != null) {
{ switch ($sAttCode) {
switch($sAttCode)
{
case 'id': case 'id':
$sField = $oObj->GetKey(); $sField = $oObj->GetKey();
break; break;
@@ -356,14 +337,11 @@ EOF
$sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']); $sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']);
} }
} }
if ($this->aStatusInfo['charset'] != 'UTF-8') if ($this->aStatusInfo['charset'] != 'UTF-8') {
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string // Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket N°991) // and thus to convert field by field and not the whole row or file at once (see ticket N°991)
$aData[] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $sField); $aData[] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $sField);
} } else {
else
{
$aData[] = $sField; $aData[] = $sField;
} }
} }
@@ -375,27 +353,23 @@ EOF
AttributeDate::SetFormat($oPrevDateFormat); AttributeDate::SetFormat($oPrevDateFormat);
set_time_limit(intval($iPreviousTimeLimit)); set_time_limit(intval($iPreviousTimeLimit));
$this->aStatusInfo['position'] += $this->iChunkSize; $this->aStatusInfo['position'] += $this->iChunkSize;
if ($this->aStatusInfo['total'] == 0) if ($this->aStatusInfo['total'] == 0) {
{
$iPercentage = 100; $iPercentage = 100;
} } else {
else
{
$iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total'])); $iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total']));
} }
if ($iCount < $this->iChunkSize) if ($iCount < $this->iChunkSize) {
{
$sRetCode = 'done'; $sRetCode = 'done';
} }
$aStatus = array('code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage); $aStatus = ['code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage];
return $sData; return $sData;
} }
public function GetSupportedFormats() public function GetSupportedFormats()
{ {
return array('csv' => Dict::S('Core:BulkExport:CSVFormat')); return ['csv' => Dict::S('Core:BulkExport:CSVFormat')];
} }
public function GetMimeType() public function GetMimeType()

View File

@@ -1,10 +1,10 @@
<?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
*/ */
define('stSTARTING', 1); //grey zone: the type is undetermined define('stSTARTING', 1); //grey zone: the type is undetermined
define('stRAW', 2); //building a non-qualified string define('stRAW', 2); //building a non-qualified string
define('stQUALIFIED', 3); //building qualified string define('stQUALIFIED', 3); //building qualified string
@@ -19,7 +19,6 @@ define('evEND', 5);
define('NULL_VALUE', '<NULL>'); define('NULL_VALUE', '<NULL>');
/** /**
* CSVParser * CSVParser
* *
@@ -41,9 +40,9 @@ class CSVParser
} }
protected $m_sCurrCell = ''; protected $m_sCurrCell = '';
protected $m_aCurrRow = array(); protected $m_aCurrRow = [];
protected $m_iToSkip = 0; protected $m_iToSkip = 0;
protected $m_aDataSet = array(); protected $m_aDataSet = [];
protected function __AddChar($c) protected function __AddChar($c)
{ {
@@ -55,27 +54,20 @@ class CSVParser
} }
protected function __AddCell($c = null, $aFieldMap = null, $bTrimSpaces = false) protected function __AddCell($c = null, $aFieldMap = null, $bTrimSpaces = false)
{ {
if ($bTrimSpaces) if ($bTrimSpaces) {
{
$sCell = trim($this->m_sCurrCell); $sCell = trim($this->m_sCurrCell);
} } else {
else
{
$sCell = $this->m_sCurrCell; $sCell = $this->m_sCurrCell;
} }
if ($sCell == NULL_VALUE) if ($sCell == NULL_VALUE) {
{
$sCell = null; $sCell = null;
} }
if (!is_null($aFieldMap)) if (!is_null($aFieldMap)) {
{
$iNextCol = count($this->m_aCurrRow); $iNextCol = count($this->m_aCurrRow);
$iNextName = $aFieldMap[$iNextCol]; $iNextName = $aFieldMap[$iNextCol];
$this->m_aCurrRow[$iNextName] = $sCell; $this->m_aCurrRow[$iNextName] = $sCell;
} } else {
else
{
$this->m_aCurrRow[] = $sCell; $this->m_aCurrRow[] = $sCell;
} }
$this->m_sCurrCell = ''; $this->m_sCurrCell = '';
@@ -84,33 +76,24 @@ class CSVParser
{ {
$this->__AddCell($c, $aFieldMap, $bTrimSpaces); $this->__AddCell($c, $aFieldMap, $bTrimSpaces);
if ($this->m_iToSkip > 0) if ($this->m_iToSkip > 0) {
{
$this->m_iToSkip--; $this->m_iToSkip--;
} } elseif (count($this->m_aCurrRow) > 1) {
elseif (count($this->m_aCurrRow) > 1)
{
$this->m_aDataSet[] = $this->m_aCurrRow; $this->m_aDataSet[] = $this->m_aCurrRow;
} } elseif (count($this->m_aCurrRow) == 1) {
elseif (count($this->m_aCurrRow) == 1)
{
// Get the unique value // Get the unique value
$aValues = array_values($this->m_aCurrRow); $aValues = array_values($this->m_aCurrRow);
$sValue = $aValues[0]; $sValue = $aValues[0];
if (strlen($sValue) > 0) if (strlen($sValue) > 0) {
{
$this->m_aDataSet[] = $this->m_aCurrRow; $this->m_aDataSet[] = $this->m_aCurrRow;
} }
} } else {
else
{
// blank line, skip silently // blank line, skip silently
} }
$this->m_aCurrRow = array(); $this->m_aCurrRow = [];
// More time for the next row // More time for the next row
if ($this->m_iTimeLimitPerRow !== null) if ($this->m_iTimeLimitPerRow !== null) {
{
set_time_limit(intval($this->m_iTimeLimitPerRow)); set_time_limit(intval($this->m_iTimeLimitPerRow));
} }
} }
@@ -124,87 +107,71 @@ class CSVParser
$this->__AddRow($c, $aFieldMap, true); $this->__AddRow($c, $aFieldMap, true);
} }
function ToArray($iToSkip = 1, $aFieldMap = null, $iMax = 0) public function ToArray($iToSkip = 1, $aFieldMap = null, $iMax = 0)
{ {
$aTransitions = array(); $aTransitions = [];
$aTransitions[stSTARTING][evBLANK] = array('', stSTARTING); $aTransitions[stSTARTING][evBLANK] = ['', stSTARTING];
$aTransitions[stSTARTING][evSEPARATOR] = array('__AddCell', stSTARTING); $aTransitions[stSTARTING][evSEPARATOR] = ['__AddCell', stSTARTING];
$aTransitions[stSTARTING][evNEWLINE] = array('__AddRow', stSTARTING); $aTransitions[stSTARTING][evNEWLINE] = ['__AddRow', stSTARTING];
$aTransitions[stSTARTING][evTEXTQUAL] = array('', stQUALIFIED); $aTransitions[stSTARTING][evTEXTQUAL] = ['', stQUALIFIED];
$aTransitions[stSTARTING][evOTHERCHAR] = array('__AddChar', stRAW); $aTransitions[stSTARTING][evOTHERCHAR] = ['__AddChar', stRAW];
$aTransitions[stSTARTING][evEND] = array('__AddRow', stSTARTING); $aTransitions[stSTARTING][evEND] = ['__AddRow', stSTARTING];
$aTransitions[stRAW][evBLANK] = array('__AddChar', stRAW); $aTransitions[stRAW][evBLANK] = ['__AddChar', stRAW];
$aTransitions[stRAW][evSEPARATOR] = array('__AddCellTrimmed', stSTARTING); $aTransitions[stRAW][evSEPARATOR] = ['__AddCellTrimmed', stSTARTING];
$aTransitions[stRAW][evNEWLINE] = array('__AddRowTrimmed', stSTARTING); $aTransitions[stRAW][evNEWLINE] = ['__AddRowTrimmed', stSTARTING];
$aTransitions[stRAW][evTEXTQUAL] = array('__AddChar', stRAW); $aTransitions[stRAW][evTEXTQUAL] = ['__AddChar', stRAW];
$aTransitions[stRAW][evOTHERCHAR] = array('__AddChar', stRAW); $aTransitions[stRAW][evOTHERCHAR] = ['__AddChar', stRAW];
$aTransitions[stRAW][evEND] = array('__AddRowTrimmed', stSTARTING); $aTransitions[stRAW][evEND] = ['__AddRowTrimmed', stSTARTING];
$aTransitions[stQUALIFIED][evBLANK] = array('__AddChar', stQUALIFIED); $aTransitions[stQUALIFIED][evBLANK] = ['__AddChar', stQUALIFIED];
$aTransitions[stQUALIFIED][evSEPARATOR] = array('__AddChar', stQUALIFIED); $aTransitions[stQUALIFIED][evSEPARATOR] = ['__AddChar', stQUALIFIED];
$aTransitions[stQUALIFIED][evNEWLINE] = array('__AddChar', stQUALIFIED); $aTransitions[stQUALIFIED][evNEWLINE] = ['__AddChar', stQUALIFIED];
$aTransitions[stQUALIFIED][evTEXTQUAL] = array('', stESCAPED); $aTransitions[stQUALIFIED][evTEXTQUAL] = ['', stESCAPED];
$aTransitions[stQUALIFIED][evOTHERCHAR] = array('__AddChar', stQUALIFIED); $aTransitions[stQUALIFIED][evOTHERCHAR] = ['__AddChar', stQUALIFIED];
$aTransitions[stQUALIFIED][evEND] = array('__AddRow', stSTARTING); $aTransitions[stQUALIFIED][evEND] = ['__AddRow', stSTARTING];
$aTransitions[stESCAPED][evBLANK] = array('', stESCAPED); $aTransitions[stESCAPED][evBLANK] = ['', stESCAPED];
$aTransitions[stESCAPED][evSEPARATOR] = array('__AddCell', stSTARTING); $aTransitions[stESCAPED][evSEPARATOR] = ['__AddCell', stSTARTING];
$aTransitions[stESCAPED][evNEWLINE] = array('__AddRow', stSTARTING); $aTransitions[stESCAPED][evNEWLINE] = ['__AddRow', stSTARTING];
$aTransitions[stESCAPED][evTEXTQUAL] = array('__AddChar', stQUALIFIED); $aTransitions[stESCAPED][evTEXTQUAL] = ['__AddChar', stQUALIFIED];
$aTransitions[stESCAPED][evOTHERCHAR] = array('__AddChar', stSTARTING); $aTransitions[stESCAPED][evOTHERCHAR] = ['__AddChar', stSTARTING];
$aTransitions[stESCAPED][evEND] = array('__AddRow', stSTARTING); $aTransitions[stESCAPED][evEND] = ['__AddRow', stSTARTING];
// Reset parser variables // Reset parser variables
$this->m_sCurrCell = ''; $this->m_sCurrCell = '';
$this->m_aCurrRow = array(); $this->m_aCurrRow = [];
$this->m_iToSkip = $iToSkip; $this->m_iToSkip = $iToSkip;
$this->m_aDataSet = array(); $this->m_aDataSet = [];
$iDataLength = strlen($this->m_sCSVData); $iDataLength = strlen($this->m_sCSVData);
$iState = stSTARTING; $iState = stSTARTING;
$iTimeLimit = null; $iTimeLimit = null;
if ($this->m_iTimeLimitPerRow !== null) if ($this->m_iTimeLimitPerRow !== null) {
{
// Give some time for the first row // Give some time for the first row
$iTimeLimit = ini_get('max_execution_time'); $iTimeLimit = ini_get('max_execution_time');
set_time_limit(intval($this->m_iTimeLimitPerRow)); set_time_limit(intval($this->m_iTimeLimitPerRow));
} }
for($i = 0; $i <= $iDataLength ; $i++) for ($i = 0; $i <= $iDataLength ; $i++) {
{ if ($i == $iDataLength) {
if ($i == $iDataLength)
{
$c = null; $c = null;
$iEvent = evEND; $iEvent = evEND;
} } else {
else
{
$c = $this->m_sCSVData[$i]; $c = $this->m_sCSVData[$i];
if ($c == $this->m_sSep) if ($c == $this->m_sSep) {
{
$iEvent = evSEPARATOR; $iEvent = evSEPARATOR;
} } elseif ($c == ' ') {
elseif ($c == ' ')
{
$iEvent = evBLANK; $iEvent = evBLANK;
} } elseif ($c == "\t") {
elseif ($c == "\t")
{
$iEvent = evBLANK; $iEvent = evBLANK;
} } elseif ($c == "\n") {
elseif ($c == "\n")
{
$iEvent = evNEWLINE; $iEvent = evNEWLINE;
} } elseif ($c == $this->m_sTextQualifier) {
elseif ($c == $this->m_sTextQualifier)
{
$iEvent = evTEXTQUAL; $iEvent = evTEXTQUAL;
} } else {
else
{
$iEvent = evOTHERCHAR; $iEvent = evOTHERCHAR;
} }
} }
@@ -212,24 +179,21 @@ class CSVParser
$sAction = $aTransitions[$iState][$iEvent][0]; $sAction = $aTransitions[$iState][$iEvent][0];
$iState = $aTransitions[$iState][$iEvent][1]; $iState = $aTransitions[$iState][$iEvent][1];
if (!empty($sAction)) if (!empty($sAction)) {
{ $aCallSpec = [$this, $sAction];
$aCallSpec = array($this, $sAction); if (is_callable($aCallSpec)) {
if (is_callable($aCallSpec))
{
call_user_func($aCallSpec, $c, $aFieldMap); call_user_func($aCallSpec, $c, $aFieldMap);
} } else {
else
{
throw new CSVParserException("CSVParser: unknown verb '$sAction'"); throw new CSVParserException("CSVParser: unknown verb '$sAction'");
} }
} }
$iLineCount = count($this->m_aDataSet); $iLineCount = count($this->m_aDataSet);
if (($iMax > 0) && ($iLineCount >= $iMax)) break; if (($iMax > 0) && ($iLineCount >= $iMax)) {
break;
} }
if ($iTimeLimit !== null) }
{ if ($iTimeLimit !== null) {
// Restore the previous time limit // Restore the previous time limit
set_time_limit(intval($iTimeLimit)); set_time_limit(intval($iTimeLimit));
} }
@@ -242,6 +206,3 @@ class CSVParser
return $aHeader[0]; return $aHeader[0];
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -23,7 +24,8 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
abstract class CustomFieldsHandler { abstract class CustomFieldsHandler
{
/** @var string $sAttCode */ /** @var string $sAttCode */
protected $sAttCode; protected $sAttCode;
/** @var array{ /** @var array{
@@ -47,7 +49,8 @@ abstract class CustomFieldsHandler {
* *
* @param $sAttCode * @param $sAttCode
*/ */
final public function __construct($sAttCode) { final public function __construct($sAttCode)
{
$this->sAttCode = $sAttCode; $this->sAttCode = $sAttCode;
$this->aValues = null; $this->aValues = null;
} }
@@ -59,7 +62,8 @@ abstract class CustomFieldsHandler {
* @throws \ApplicationException if {@link static::$oForm} attribute not initialized yet * @throws \ApplicationException if {@link static::$oForm} attribute not initialized yet
* @since 3.1.0 N°6322 N°1150 Add template_id checks * @since 3.1.0 N°6322 N°1150 Add template_id checks
*/ */
public function Validate(DBObject $oHostObject) { public function Validate(DBObject $oHostObject)
{
if (false === isset($this->oForm)) { if (false === isset($this->oForm)) {
throw new ApplicationException('oForm attribute not init yet. You must call BuildForm before this method !'); throw new ApplicationException('oForm attribute not init yet. You must call BuildForm before this method !');
} }
@@ -68,9 +72,8 @@ abstract class CustomFieldsHandler {
$this->oForm->Validate(); $this->oForm->Validate();
if ($this->oForm->GetValid()) { if ($this->oForm->GetValid()) {
$ret = true; $ret = true;
} } else {
else { $aMessages = [];
$aMessages = array();
foreach ($this->oForm->GetErrorMessages() as $sFieldId => $aFieldMessages) { foreach ($this->oForm->GetErrorMessages() as $sFieldId => $aFieldMessages) {
$aMessages[] = $sFieldId.': '.implode(', ', $aFieldMessages); $aMessages[] = $sFieldId.': '.implode(', ', $aFieldMessages);
} }
@@ -87,7 +90,8 @@ abstract class CustomFieldsHandler {
* *
* @return \Combodo\iTop\Form\Form * @return \Combodo\iTop\Form\Form
*/ */
public function GetForm() { public function GetForm()
{
return $this->oForm; return $this->oForm;
} }
@@ -96,15 +100,17 @@ abstract class CustomFieldsHandler {
$this->aValues = $aValues; $this->aValues = $aValues;
} }
public static function GetPrerequisiteAttributes($sClass = null) { public static function GetPrerequisiteAttributes($sClass = null)
return array(); {
return [];
} }
/** /**
* List the available verbs for 'GetForTemplate' * List the available verbs for 'GetForTemplate'
*/ */
public static function EnumTemplateVerbs() { public static function EnumTemplateVerbs()
return array(); {
return [];
} }
/** /**
@@ -169,7 +175,6 @@ abstract class CustomFieldsHandler {
return null; return null;
} }
/** /**
* @param DBObject $oHostObject * @param DBObject $oHostObject
* *

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/>
/** /**
* data generator * data generator
* helps the consultants in creating dummy data sets, for various test purposes (validation, usability, scalability) * helps the consultants in creating dummy data sets, for various test purposes (validation, usability, scalability)
@@ -44,48 +44,38 @@ class cmdbDataGenerator
public function __construct($sOrganizationId = "") public function __construct($sOrganizationId = "")
{ {
global $aCompanies, $aCompaniesCode; global $aCompanies, $aCompaniesCode;
if ($sOrganizationId == '') if ($sOrganizationId == '') {
{
// No organization provided, pick a random and unused one from our predefined list // No organization provided, pick a random and unused one from our predefined list
$retries = 5 * count($aCompanies); $retries = 5 * count($aCompanies);
while ( ($retries > 0) && !isset($this->m_sOrganizationCode)) // Stupid algorithm, but I'm too lazy to do something bulletproof tonight while (($retries > 0) && !isset($this->m_sOrganizationCode)) { // Stupid algorithm, but I'm too lazy to do something bulletproof tonight
{
$index = rand(0, count($aCompanies) - 1); $index = rand(0, count($aCompanies) - 1);
if (!$this->OrganizationExists($aCompanies[$index]['code'])) if (!$this->OrganizationExists($aCompanies[$index]['code'])) {
{
$this->m_sOrganizationCode = $aCompanies[$index]['code']; $this->m_sOrganizationCode = $aCompanies[$index]['code'];
$this->m_sOrganizationName = $aCompanies[$index]['name']; $this->m_sOrganizationName = $aCompanies[$index]['name'];
$this->m_OrganizationDomains = $aCompanies[$index]['domain']; $this->m_OrganizationDomains = $aCompanies[$index]['domain'];
} }
$retries--; $retries--;
} }
} } else {
else
{
// A code has been provided, let's take the information we need from the organization itself // A code has been provided, let's take the information we need from the organization itself
$this->m_sOrganizationId = $sOrganizationId; $this->m_sOrganizationId = $sOrganizationId;
$oOrg = $this->GetOrganization($sOrganizationId); $oOrg = $this->GetOrganization($sOrganizationId);
if ($oOrg == null) if ($oOrg == null) {
{
echo "Unable to find the organization '$sOrganisationCode' in the database... can not add objects into this organization.<br/>\n"; echo "Unable to find the organization '$sOrganisationCode' in the database... can not add objects into this organization.<br/>\n";
exit(); exit();
} }
$this->m_sOrganizationCode = $oOrg->Get('code'); $this->m_sOrganizationCode = $oOrg->Get('code');
$this->m_sOrganizationName = $oOrg->Get('name'); $this->m_sOrganizationName = $oOrg->Get('name');
if (!isset($aCompaniesCode[$this->m_sOrganizationCode]['domain'])) if (!isset($aCompaniesCode[$this->m_sOrganizationCode]['domain'])) {
{
// Generate some probable domain names for this organization // Generate some probable domain names for this organization
$this->m_OrganizationDomains = array(strtolower($this->m_sOrganizationCode).".com", strtolower($this->m_sOrganizationCode).".org", strtolower($this->m_sOrganizationCode)."corp.net",); $this->m_OrganizationDomains = [strtolower($this->m_sOrganizationCode).".com", strtolower($this->m_sOrganizationCode).".org", strtolower($this->m_sOrganizationCode)."corp.net",];
} } else {
else
{
// Pick the domain names for this organization from the predefined list // Pick the domain names for this organization from the predefined list
$this->m_OrganizationDomains = $aCompaniesCode[$this->m_sOrganizationCode]['domain']; $this->m_OrganizationDomains = $aCompaniesCode[$this->m_sOrganizationCode]['domain'];
} }
} }
if (!isset($this->m_sOrganizationCode)) if (!isset($this->m_sOrganizationCode)) {
{
echo "Unable to find an organization code which is not already used... can not create a new organization. Enhance the list of fake organizations (\$aCompanies in data_sample.inc.php).<br/>\n"; echo "Unable to find an organization code which is not already used... can not create a new organization. Enhance the list of fake organizations (\$aCompanies in data_sample.inc.php).<br/>\n";
exit(); exit();
} }
@@ -127,7 +117,7 @@ class cmdbDataGenerator
* *
* @return string The organization name * @return string The organization name
*/ */
function GetOrganizationName() public function GetOrganizationName()
{ {
return $this->m_sOrganizationName; return $this->m_sOrganizationName;
} }
@@ -137,7 +127,7 @@ class cmdbDataGenerator
* *
* @return string A random first name * @return string A random first name
*/ */
function GenerateFirstName() public function GenerateFirstName()
{ {
global $aFirstNames; global $aFirstNames;
return $aFirstNames[rand(0, count($aFirstNames) - 1)]; return $aFirstNames[rand(0, count($aFirstNames) - 1)];
@@ -148,7 +138,7 @@ class cmdbDataGenerator
* *
* @return string A random last name * @return string A random last name
*/ */
function GenerateLastName() public function GenerateLastName()
{ {
global $aNames; global $aNames;
return $aNames[rand(0, count($aNames) - 1)]; return $aNames[rand(0, count($aNames) - 1)];
@@ -159,7 +149,7 @@ class cmdbDataGenerator
* *
* @return string A random city name * @return string A random city name
*/ */
function GenerateCountryName() public function GenerateCountryName()
{ {
global $aCountries; global $aCountries;
return $aCountries[rand(0, count($aCountries) - 1)]; return $aCountries[rand(0, count($aCountries) - 1)];
@@ -170,7 +160,7 @@ class cmdbDataGenerator
* *
* @return string A random city name * @return string A random city name
*/ */
function GenerateCityName() public function GenerateCityName()
{ {
global $aCities; global $aCities;
return $aCities[rand(0, count($aCities) - 1)]; return $aCities[rand(0, count($aCities) - 1)];
@@ -181,15 +171,12 @@ class cmdbDataGenerator
* *
* @return string A random email address * @return string A random email address
*/ */
function GenerateEmail($sFirstName, $sLastName) public function GenerateEmail($sFirstName, $sLastName)
{
if (rand(1, 20) > 18)
{ {
if (rand(1, 20) > 18) {
// some people (let's say 5~10%) have an irregular email address // some people (let's say 5~10%) have an irregular email address
$sEmail = strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain()); $sEmail = strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain());
} } else {
else
{
$sEmail = strtolower($this->CleanForEmail($sFirstName)).".".strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain()); $sEmail = strtolower($this->CleanForEmail($sFirstName)).".".strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain());
} }
return $sEmail; return $sEmail;
@@ -215,39 +202,28 @@ class cmdbDataGenerator
* @param string $sTemplate The template used for generating the string * @param string $sTemplate The template used for generating the string
* @return string The generated pseudo random the string * @return string The generated pseudo random the string
*/ */
function GenerateString($sTemplate) public function GenerateString($sTemplate)
{ {
$sResult = ""; $sResult = "";
$aParts = explode("\|", $sTemplate); $aParts = explode("\|", $sTemplate);
foreach($aParts as $sPart) foreach ($aParts as $sPart) {
{ if (preg_match("/domain\(\)/", $sPart, $aMatches)) {
if (preg_match("/domain\(\)/", $sPart, $aMatches))
{
$sResult .= strtolower($this->GenerateDomain()); $sResult .= strtolower($this->GenerateDomain());
} } elseif (preg_match("/enum\((.+)\)/", $sPart, $aMatches)) {
elseif (preg_match("/enum\((.+)\)/", $sPart, $aMatches))
{
$sEnumValues = $aMatches[1]; $sEnumValues = $aMatches[1];
$aEnumValues = explode(",", $sEnumValues); $aEnumValues = explode(",", $sEnumValues);
$sResult .= $aEnumValues[rand(0, count($aEnumValues) - 1)]; $sResult .= $aEnumValues[rand(0, count($aEnumValues) - 1)];
} } elseif (preg_match("/number\((\d+)-(\d+)\)/", $sPart, $aMatches)) {
elseif (preg_match("/number\((\d+)-(\d+)\)/", $sPart, $aMatches))
{
$sStartNumber = $aMatches[1]; $sStartNumber = $aMatches[1];
if ($sStartNumber[0] == '0') if ($sStartNumber[0] == '0') {
{
// number must be zero padded // number must be zero padded
$sFormat = "%0".strlen($sStartNumber)."d"; $sFormat = "%0".strlen($sStartNumber)."d";
} } else {
else
{
$sFormat = "%d"; $sFormat = "%d";
} }
$sEndNumber = $aMatches[2]; $sEndNumber = $aMatches[2];
$sResult .= sprintf($sFormat, rand($sStartNumber, $sEndNumber)); $sResult .= sprintf($sFormat, rand($sStartNumber, $sEndNumber));
} } else {
else
{
$sResult .= $sPart; $sResult .= $sPart;
} }
} }
@@ -264,27 +240,22 @@ class cmdbDataGenerator
* @param string $aFilterCriteria A hash array of filterCOde => FilterValue (the strict operator '=' is used ) * @param string $aFilterCriteria A hash array of filterCOde => FilterValue (the strict operator '=' is used )
* @return mixed The key to an object of the given class, or null if none are found * @return mixed The key to an object of the given class, or null if none are found
*/ */
function GenerateKey($sClass, $aFilterCriteria) public function GenerateKey($sClass, $aFilterCriteria)
{ {
$retKey = null; $retKey = null;
$oFilter = new DBObjectSearch($sClass); $oFilter = new DBObjectSearch($sClass);
foreach($aFilterCriteria as $sFilterCode => $filterValue) foreach ($aFilterCriteria as $sFilterCode => $filterValue) {
{
$oFilter->AddCondition($sFilterCode, $filterValue, '='); $oFilter->AddCondition($sFilterCode, $filterValue, '=');
} }
$oSet = new CMDBObjectSet($oFilter); $oSet = new CMDBObjectSet($oFilter);
if ($oSet->Count() > 0) if ($oSet->Count() > 0) {
{
$max_count = $index = rand(1, $oSet->Count()); $max_count = $index = rand(1, $oSet->Count());
do do {
{
$oObj = $oSet->Fetch(); $oObj = $oSet->Fetch();
$index--; $index--;
} } while ($index > 0);
while($index > 0);
if (!is_object($oObj)) if (!is_object($oObj)) {
{
echo "<pre>"; echo "<pre>";
echo "ERROR: non empty set, but invalid object picked! class='$sClass'\n"; echo "ERROR: non empty set, but invalid object picked! class='$sClass'\n";
echo "Index chosen: $max_count\n"; echo "Index chosen: $max_count\n";
@@ -292,9 +263,7 @@ class cmdbDataGenerator
echo "Filter criteria:\n"; echo "Filter criteria:\n";
print_r($aFilterCriteria); print_r($aFilterCriteria);
echo "</pre>"; echo "</pre>";
} } else {
else
{
$retKey = $oObj->GetKey(); $retKey = $oObj->GetKey();
} }
} }
@@ -316,12 +285,9 @@ class cmdbDataGenerator
*/ */
protected function GenerateDomain() protected function GenerateDomain()
{ {
if (is_array($this->m_OrganizationDomains)) if (is_array($this->m_OrganizationDomains)) {
{
$sDomain = $this->m_OrganizationDomains[rand(0, count($this->m_OrganizationDomains) - 1)]; $sDomain = $this->m_OrganizationDomains[rand(0, count($this->m_OrganizationDomains) - 1)];
} } else {
else
{
$sDomain = $this->m_OrganizationDomains; $sDomain = $this->m_OrganizationDomains;
} }
return $sDomain; return $sDomain;
@@ -335,7 +301,7 @@ class cmdbDataGenerator
*/ */
protected function CleanForEmail($sText) protected function CleanForEmail($sText)
{ {
return str_replace(array("'", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>"), array("", "e", "e", "e", "c", "a", "a", "n", "oe", "ae"), $sText); return str_replace(["'", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>", "<EFBFBD>"], ["", "e", "e", "e", "c", "a", "a", "n", "oe", "ae"], $sText);
} }
/** /**
@@ -364,11 +330,9 @@ class cmdbDataGenerator
$oFilter = new DBObjectSearch('Organization'); $oFilter = new DBObjectSearch('Organization');
$oFilter->AddCondition('id', $sId, '='); $oFilter->AddCondition('id', $sId, '=');
$oSet = new CMDBObjectSet($oFilter); $oSet = new CMDBObjectSet($oFilter);
if ($oSet->Count() > 0) if ($oSet->Count() > 0) {
{
$oOrg = $oSet->Fetch(); // Let's take the first one found $oOrg = $oSet->Fetch(); // Let's take the first one found
} }
return $oOrg; return $oOrg;
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 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/>
/** /**
* Helper class to generate Date & Time formatting strings in the various conventions * Helper class to generate Date & Time formatting strings in the various conventions
* from the PHP DateTime::createFromFormat convention. * from the PHP DateTime::createFromFormat convention.
@@ -56,28 +56,28 @@ class DateTimeFormat
*/ */
protected static function GetFormatMapping() protected static function GetFormatMapping()
{ {
return array( return [
// Days // Days
'd' => array('regexpr' => '(0[1-9]|[1-2][0-9]|3[0-1])', 'datepicker' => 'dd', 'excel' => 'dd', 'moment' => 'DD'), // Day of the month: 2 digits (with leading zero) 'd' => ['regexpr' => '(0[1-9]|[1-2][0-9]|3[0-1])', 'datepicker' => 'dd', 'excel' => 'dd', 'moment' => 'DD'], // Day of the month: 2 digits (with leading zero)
'j' => array('regexpr' => '([1-9]|[1-2][0-9]|3[0-1])', 'datepicker' => 'd', 'excel' => 'd', 'moment' => 'D'), // Day of the month: 1 or 2 digits (without leading zero) 'j' => ['regexpr' => '([1-9]|[1-2][0-9]|3[0-1])', 'datepicker' => 'd', 'excel' => 'd', 'moment' => 'D'], // Day of the month: 1 or 2 digits (without leading zero)
// Months // Months
'm' => array('regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'mm', 'excel' => 'MM', 'moment' => 'MM' ), // Month on 2 digits i.e. 01-12 'm' => ['regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'mm', 'excel' => 'MM', 'moment' => 'MM' ], // Month on 2 digits i.e. 01-12
'n' => array('regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'm', 'excel' => 'm', 'moment' => 'M'), // Month on 1 or 2 digits 1-12 'n' => ['regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'm', 'excel' => 'm', 'moment' => 'M'], // Month on 1 or 2 digits 1-12
// Years // Years
'Y' => array('regexpr' => '([0-9]{4})', 'datepicker' => 'yy', 'excel' => 'YYYY', 'moment' => 'YYYY'), // Year on 4 digits 'Y' => ['regexpr' => '([0-9]{4})', 'datepicker' => 'yy', 'excel' => 'YYYY', 'moment' => 'YYYY'], // Year on 4 digits
'y' => array('regexpr' => '([0-9]{2})', 'datepicker' => 'y', 'excel' => 'YY', 'moment' => 'YY'), // Year on 2 digits 'y' => ['regexpr' => '([0-9]{2})', 'datepicker' => 'y', 'excel' => 'YY', 'moment' => 'YY'], // Year on 2 digits
// Hours // Hours
'H' => array('regexpr' => '([0-1][0-9]|2[0-3])', 'datepicker' => 'HH', 'excel' => 'HH', 'moment' => 'HH'), // Hour 00..23 'H' => ['regexpr' => '([0-1][0-9]|2[0-3])', 'datepicker' => 'HH', 'excel' => 'HH', 'moment' => 'HH'], // Hour 00..23
'h' => array('regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'hh', 'excel' => 'hh', 'moment' => 'hh'), // Hour 01..12 'h' => ['regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'hh', 'excel' => 'hh', 'moment' => 'hh'], // Hour 01..12
'G' => array('regexpr' => '([0-9]|1[0-9]|2[0-3])', 'datepicker' => 'H', 'excel' => 'H', 'moment' => 'H'), // Hour 0..23 'G' => ['regexpr' => '([0-9]|1[0-9]|2[0-3])', 'datepicker' => 'H', 'excel' => 'H', 'moment' => 'H'], // Hour 0..23
'g' => array('regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'h', 'excel' => 'h', 'moment' => 'h'), // Hour 1..12 'g' => ['regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'h', 'excel' => 'h', 'moment' => 'h'], // Hour 1..12
'a' => array('regexpr' => '(am|pm)', 'datepicker' => 'tt', 'excel' => 'am/pm', 'moment' => 'a'), 'a' => ['regexpr' => '(am|pm)', 'datepicker' => 'tt', 'excel' => 'am/pm', 'moment' => 'a'],
'A' => array('regexpr' => '(AM|PM)', 'datepicker' => 'TT', 'excel' => 'AM/PM', 'moment' => 'A'), 'A' => ['regexpr' => '(AM|PM)', 'datepicker' => 'TT', 'excel' => 'AM/PM', 'moment' => 'A'],
// Minutes // Minutes
'i' => array('regexpr' => '([0-5][0-9])', 'datepicker' => 'mm', 'excel' => 'mm', 'moment' => 'mm'), 'i' => ['regexpr' => '([0-5][0-9])', 'datepicker' => 'mm', 'excel' => 'mm', 'moment' => 'mm'],
// Seconds // Seconds
's' => array('regexpr' => '([0-5][0-9])', 'datepicker' => 'ss', 'excel' => 'ss', 'moment' => 'ss'), 's' => ['regexpr' => '([0-5][0-9])', 'datepicker' => 'ss', 'excel' => 'ss', 'moment' => 'ss'],
); ];
} }
/** /**
@@ -95,40 +95,27 @@ class DateTimeFormat
$sResult = ''; $sResult = '';
$bEscaping = false; $bEscaping = false;
for($i=0; $i < strlen($this->sPHPFormat); $i++) for ($i = 0; $i < strlen($this->sPHPFormat); $i++) {
{ if (($this->sPHPFormat[$i] == '\\')) {
if (($this->sPHPFormat[$i] == '\\'))
{
$bEscaping = true; $bEscaping = true;
continue; continue;
} }
if ($bEscaping) if ($bEscaping) {
{ if (($sSpecialChars === '') || (strpos($sSpecialChars, $this->sPHPFormat[$i]) !== false)) {
if (($sSpecialChars === '') || (strpos($sSpecialChars, $this->sPHPFormat[$i]) !== false))
{
$sResult .= sprintf($sEscapePattern, $this->sPHPFormat[$i]); $sResult .= sprintf($sEscapePattern, $this->sPHPFormat[$i]);
} } else {
else
{
$sResult .= $this->sPHPFormat[$i]; $sResult .= $this->sPHPFormat[$i];
} }
$bEscaping = false; $bEscaping = false;
} } elseif (array_key_exists($this->sPHPFormat[$i], $aMappings)) {
else if(array_key_exists($this->sPHPFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by its regular expression pattern // Not a litteral value, must be replaced by its regular expression pattern
$sResult .= $aMappings[$this->sPHPFormat[$i]][$sOutputFormatCode]; $sResult .= $aMappings[$this->sPHPFormat[$i]][$sOutputFormatCode];
} } else {
else if ($bEscapeAll || (strpos($sSpecialChars, $this->sPHPFormat[$i]) !== false)) {
{
if ($bEscapeAll || (strpos($sSpecialChars, $this->sPHPFormat[$i]) !== false))
{
$sResult .= sprintf($sEscapePattern, $this->sPHPFormat[$i]); $sResult .= sprintf($sEscapePattern, $this->sPHPFormat[$i]);
} } else {
else
{
// Normal char with no special meaning, no need to escape it // Normal char with no special meaning, no need to escape it
$sResult .= $this->sPHPFormat[$i]; $sResult .= $this->sPHPFormat[$i];
} }
@@ -146,33 +133,22 @@ class DateTimeFormat
*/ */
public function Format($date) public function Format($date)
{ {
if ($date == null) if ($date == null) {
{
$sDate = ''; $sDate = '';
} } elseif (($date === '0000-00-00') || ($date === '0000-00-00 00:00:00')) {
else if (($date === '0000-00-00') || ($date === '0000-00-00 00:00:00'))
{
$sDate = ''; $sDate = '';
} } elseif ($date instanceof DateTime) {
else if ($date instanceof DateTime)
{
// Parameter is a DateTime // Parameter is a DateTime
$sDate = $date->format($this->sPHPFormat); $sDate = $date->format($this->sPHPFormat);
} } elseif (is_int($date)) {
else if (is_int($date))
{
// Parameter is a Unix timestamp // Parameter is a Unix timestamp
$oDate = new DateTime(); $oDate = new DateTime();
$oDate->setTimestamp($date); $oDate->setTimestamp($date);
$sDate = $oDate->format($this->sPHPFormat); $sDate = $oDate->format($this->sPHPFormat);
} } elseif (is_string($date)) {
else if (is_string($date))
{
$oDate = new DateTime($date); $oDate = new DateTime($date);
$sDate = $oDate->format($this->sPHPFormat); $sDate = $oDate->format($this->sPHPFormat);
} } else {
else
{
throw new Exception(__CLASS__."::Format: Unexpected date value: ".print_r($date, true)); throw new Exception(__CLASS__."::Format: Unexpected date value: ".print_r($date, true));
} }
return $sDate; return $sDate;
@@ -187,16 +163,12 @@ class DateTimeFormat
*/ */
public function Parse($sDate) public function Parse($sDate)
{ {
if (($sDate == null) || ($sDate == '0000-00-00 00:00:00') || ($sDate == '0000-00-00')) if (($sDate == null) || ($sDate == '0000-00-00 00:00:00') || ($sDate == '0000-00-00')) {
{
return null; return null;
} } else {
else
{
$sFormat = preg_replace('/\\?/', '', $this->sPHPFormat); // replace escaped characters by a wildcard for parsing $sFormat = preg_replace('/\\?/', '', $this->sPHPFormat); // replace escaped characters by a wildcard for parsing
$oDate = DateTime::createFromFormat($this->sPHPFormat, $sDate); $oDate = DateTime::createFromFormat($this->sPHPFormat, $sDate);
if ($oDate === false) if ($oDate === false) {
{
throw new Exception(__CLASS__."::Parse: Unable to parse the date: '$sDate' using the format: '{$this->sPHPFormat}'"); throw new Exception(__CLASS__."::Parse: Unable to parse the date: '$sDate' using the format: '{$this->sPHPFormat}'");
} }
return $oDate; return $oDate;
@@ -232,9 +204,8 @@ class DateTimeFormat
public static function GetJSSQLToCustomFormat() public static function GetJSSQLToCustomFormat()
{ {
$aPHPToMoment = array(); $aPHPToMoment = [];
foreach(self::GetFormatMapping() as $sPHPCode => $aMapping) foreach (self::GetFormatMapping() as $sPHPCode => $aMapping) {
{
$aPHPToMoment[$sPHPCode] = $aMapping['moment']; $aPHPToMoment[$sPHPCode] = $aMapping['moment'];
} }
$sJSMapping = json_encode($aPHPToMoment); $sJSMapping = json_encode($aPHPToMoment);
@@ -336,26 +307,19 @@ EOF
$sResult = ''; $sResult = '';
$bEscaping = false; $bEscaping = false;
for($i=0; $i < strlen($this->sPHPFormat); $i++) for ($i = 0; $i < strlen($this->sPHPFormat); $i++) {
{ if (($this->sPHPFormat[$i] == '\\')) {
if (($this->sPHPFormat[$i] == '\\'))
{
$bEscaping = true; $bEscaping = true;
continue; continue;
} }
if ($bEscaping) if ($bEscaping) {
{
$sResult .= $this->sPHPFormat[$i]; // No need to escape characters in the placeholder $sResult .= $this->sPHPFormat[$i]; // No need to escape characters in the placeholder
$bEscaping = false; $bEscaping = false;
} } elseif (array_key_exists($this->sPHPFormat[$i], $aMappings)) {
else if(array_key_exists($this->sPHPFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by Dict equivalent // Not a litteral value, must be replaced by Dict equivalent
$sResult .= Dict::S('Core:DateTime:Placeholder_'.$this->sPHPFormat[$i]); $sResult .= Dict::S('Core:DateTime:Placeholder_'.$this->sPHPFormat[$i]);
} } else {
else
{
// Normal char with no special meaning // Normal char with no special meaning
$sResult .= $this->sPHPFormat[$i]; $sResult .= $this->sPHPFormat[$i];
@@ -374,13 +338,10 @@ EOF
$iStart = 999; $iStart = 999;
$iEnd = 0; $iEnd = 0;
foreach($aPlaceholders as $sChar) foreach ($aPlaceholders as $sChar) {
{
$iPos = strpos($this->sPHPFormat, $sChar); $iPos = strpos($this->sPHPFormat, $sChar);
if ($iPos !== false) if ($iPos !== false) {
{ if (($iPos > 0) && ($this->sPHPFormat[$iPos - 1] == '\\')) {
if (($iPos > 0) && ($this->sPHPFormat[$iPos-1] == '\\'))
{
// The placeholder is actually escaped, it's a litteral character, ignore it // The placeholder is actually escaped, it's a litteral character, ignore it
continue; continue;
} }
@@ -398,7 +359,7 @@ EOF
*/ */
public function ToDateFormat() public function ToDateFormat()
{ {
return $this->ToSubFormat(array('Y', 'y', 'd', 'j', 'm', 'n')); return $this->ToSubFormat(['Y', 'y', 'd', 'j', 'm', 'n']);
} }
/** /**
@@ -407,7 +368,7 @@ EOF
*/ */
public function ToTimeFormat() public function ToTimeFormat()
{ {
return $this->ToSubFormat(array('H', 'h', 'G', 'g', 'i', 's', 'a', 'A')); return $this->ToSubFormat(['H', 'h', 'G', 'g', 'i', 's', 'a', 'A']);
} }
/** /**
@@ -419,8 +380,7 @@ EOF
public function ToRegExpr($sDelimiter = null) public function ToRegExpr($sDelimiter = null)
{ {
$sRet = '^'.$this->Transform('regexpr', "\\%s", false /* escape all */, '.?*$^()[]:').'$'; $sRet = '^'.$this->Transform('regexpr', "\\%s", false /* escape all */, '.?*$^()[]:').'$';
if ($sDelimiter !== null) if ($sDelimiter !== null) {
{
$sRet = $sDelimiter.str_replace($sDelimiter, '\\'.$sDelimiter, $sRet).$sDelimiter; $sRet = $sDelimiter.str_replace($sDelimiter, '\\'.$sDelimiter, $sRet).$sDelimiter;
} }
return $sRet; return $sRet;

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/>
/** /**
* A set of persistent objects, could be heterogeneous as long as the objects in the set have a common ancestor class * A set of persistent objects, could be heterogeneous as long as the objects in the set have a common ancestor class
* *

File diff suppressed because it is too large Load Diff

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/>
/** /**
* Database properties - manage database instances in a complex installation * Database properties - manage database instances in a complex installation
* *
@@ -24,7 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
/** /**
* A database property * A database property
* *
@@ -34,25 +33,25 @@ class DBProperty extends DBObject
{ {
public static function Init() public static function Init()
{ {
$aParams = array $aParams =
( [
"category" => "cloud", "category" => "cloud",
"key_type" => "autoincrement", "key_type" => "autoincrement",
"name_attcode" => "name", "name_attcode" => "name",
"state_attcode" => "", "state_attcode" => "",
"reconc_keys" => array(), "reconc_keys" => [],
"db_table" => "priv_db_properties", "db_table" => "priv_db_properties",
"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"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("value", array("allowed_values"=>null, "sql"=>"value", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("value", ["allowed_values" => null, "sql" => "value", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeDateTime("change_date", array("allowed_values"=>null, "sql"=>"change_date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("change_date", ["allowed_values" => null, "sql" => "change_date", "default_value" => "NOW()", "is_null_allowed" => false, "depends_on" => []]));
MetaModel::Init_AddAttribute(new AttributeString("change_comment", array("allowed_values"=>null, "sql"=>"change_comment", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("change_comment", ["allowed_values" => null, "sql" => "change_comment", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
} }
/** /**
@@ -62,12 +61,9 @@ class DBProperty extends DBObject
public static function IsInstalled() public static function IsInstalled()
{ {
$sTable = MetaModel::DBGetTable(__CLASS__); $sTable = MetaModel::DBGetTable(__CLASS__);
if (CMDBSource::IsTable($sTable)) if (CMDBSource::IsTable($sTable)) {
{
return true; return true;
} } else {
else
{
return false; return false;
} }
return false; return false;
@@ -75,12 +71,10 @@ class DBProperty extends DBObject
public static function SetProperty($sName, $sValue, $sComment = '', $sDescription = null) public static function SetProperty($sName, $sValue, $sComment = '', $sDescription = null)
{ {
try try {
{
$oSearch = DBObjectSearch::FromOQL('SELECT DBProperty WHERE name = :name'); $oSearch = DBObjectSearch::FromOQL('SELECT DBProperty WHERE name = :name');
$oSet = new DBObjectSet($oSearch, array(), array('name' => $sName)); $oSet = new DBObjectSet($oSearch, [], ['name' => $sName]);
if ($oSet->Count() == 0) if ($oSet->Count() == 0) {
{
$oProp = new DBProperty(); $oProp = new DBProperty();
$oProp->Set('name', $sName); $oProp->Set('name', $sName);
$oProp->Set('description', $sDescription); $oProp->Set('description', $sDescription);
@@ -88,31 +82,23 @@ class DBProperty extends DBObject
$oProp->Set('change_date', time()); $oProp->Set('change_date', time());
$oProp->Set('change_comment', $sComment); $oProp->Set('change_comment', $sComment);
$oProp->DBInsert(); $oProp->DBInsert();
} } elseif ($oSet->Count() == 1) {
elseif ($oSet->Count() == 1)
{
$oProp = $oSet->fetch(); $oProp = $oSet->fetch();
if (!is_null($sDescription)) if (!is_null($sDescription)) {
{
$oProp->Set('description', $sDescription); $oProp->Set('description', $sDescription);
} }
$oProp->Set('value', $sValue); $oProp->Set('value', $sValue);
$oProp->Set('change_date', time()); $oProp->Set('change_date', time());
$oProp->Set('change_comment', $sComment); $oProp->Set('change_comment', $sComment);
$oProp->DBUpdate(); $oProp->DBUpdate();
} } else {
else
{
// Houston... // Houston...
throw new CoreException('duplicate db property'); throw new CoreException('duplicate db property');
} }
} } catch (MySQLException $e) {
catch (MySQLException $e)
{
// This might be because the table could not be found, // This might be because the table could not be found,
// let's check it and discard silently if this is really the case // let's check it and discard silently if this is really the case
if (self::IsInstalled()) if (self::IsInstalled()) {
{
throw $e; throw $e;
} }
IssueLog::Error('Attempting to write a DBProperty while the module has not been installed'); IssueLog::Error('Attempting to write a DBProperty while the module has not been installed');
@@ -121,34 +107,25 @@ class DBProperty extends DBObject
public static function GetProperty($sName, $default = null) public static function GetProperty($sName, $default = null)
{ {
try try {
{
$oSearch = DBObjectSearch::FromOQL('SELECT DBProperty WHERE name = :name'); $oSearch = DBObjectSearch::FromOQL('SELECT DBProperty WHERE name = :name');
$oSet = new DBObjectSet($oSearch, array(), array('name' => $sName)); $oSet = new DBObjectSet($oSearch, [], ['name' => $sName]);
$iCount = $oSet->Count(); $iCount = $oSet->Count();
if ($iCount == 0) if ($iCount == 0) {
{
//throw new CoreException('unknown db property', array('name' => $sName)); //throw new CoreException('unknown db property', array('name' => $sName));
$sValue = $default; $sValue = $default;
} } elseif ($iCount == 1) {
elseif ($iCount == 1)
{
$oProp = $oSet->fetch(); $oProp = $oSet->fetch();
$sValue = $oProp->Get('value'); $sValue = $oProp->Get('value');
} } else {
else
{
// $iCount > 1 // $iCount > 1
// Houston... // Houston...
throw new CoreException('duplicate db property', array('name' => $sName, 'count' => $iCount)); throw new CoreException('duplicate db property', ['name' => $sName, 'count' => $iCount]);
} }
} } catch (MySQLException $e) {
catch (MySQLException $e)
{
// This might be because the table could not be found, // This might be because the table could not be found,
// let's check it and discard silently if this is really the case // let's check it and discard silently if this is really the case
if (self::IsInstalled()) if (self::IsInstalled()) {
{
throw $e; throw $e;
} }
$sValue = $default; $sValue = $default;
@@ -156,5 +133,3 @@ class DBProperty extends DBObject
return $sValue; return $sValue;
} }
} }
?>

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
@@ -28,31 +29,31 @@ class DeletionPlan
protected $m_aToDelete; protected $m_aToDelete;
protected $m_aToUpdate; protected $m_aToUpdate;
protected static $m_aModeUpdate = array( protected static $m_aModeUpdate = [
DEL_SILENT => array( DEL_SILENT => [
DEL_SILENT => DEL_SILENT, DEL_SILENT => DEL_SILENT,
DEL_AUTO => DEL_AUTO, DEL_AUTO => DEL_AUTO,
DEL_MANUAL => DEL_MANUAL DEL_MANUAL => DEL_MANUAL,
), ],
DEL_MANUAL => array( DEL_MANUAL => [
DEL_SILENT => DEL_MANUAL, DEL_SILENT => DEL_MANUAL,
DEL_AUTO => DEL_AUTO, DEL_AUTO => DEL_AUTO,
DEL_MANUAL => DEL_MANUAL DEL_MANUAL => DEL_MANUAL,
), ],
DEL_AUTO => array( DEL_AUTO => [
DEL_SILENT => DEL_AUTO, DEL_SILENT => DEL_AUTO,
DEL_AUTO => DEL_AUTO, DEL_AUTO => DEL_AUTO,
DEL_MANUAL => DEL_AUTO DEL_MANUAL => DEL_AUTO,
) ],
); ];
public function __construct() public function __construct()
{ {
$this->m_iToDelete = 0; $this->m_iToDelete = 0;
$this->m_iToUpdate = 0; $this->m_iToUpdate = 0;
$this->m_aToDelete = array(); $this->m_aToDelete = [];
$this->m_aToUpdate = array(); $this->m_aToUpdate = [];
$this->m_bFoundStopper = false; $this->m_bFoundStopper = false;
$this->m_bFoundSecurityIssue = false; $this->m_bFoundSecurityIssue = false;
@@ -65,22 +66,17 @@ class DeletionPlan
$this->m_iToDelete = 0; $this->m_iToDelete = 0;
$this->m_iToUpdate = 0; $this->m_iToUpdate = 0;
foreach($this->m_aToDelete as $sClass => $aToDelete) foreach ($this->m_aToDelete as $sClass => $aToDelete) {
{ foreach ($aToDelete as $iId => $aData) {
foreach($aToDelete as $iId => $aData)
{
$this->m_iToDelete++; $this->m_iToDelete++;
if (isset($aData['issue'])) if (isset($aData['issue'])) {
{
$this->m_bFoundStopper = true; $this->m_bFoundStopper = true;
$this->m_bFoundManualOperation = true; $this->m_bFoundManualOperation = true;
if (isset($aData['issue_security'])) if (isset($aData['issue_security'])) {
{
$this->m_bFoundSecurityIssue = true; $this->m_bFoundSecurityIssue = true;
} }
} }
if ($aData['mode'] == DEL_MANUAL) if ($aData['mode'] == DEL_MANUAL) {
{
$this->m_aToDelete[$sClass][$iId]['issue'] = $sClass.'::'.$iId.' '.Dict::S('UI:Delete:MustBeDeletedManually'); $this->m_aToDelete[$sClass][$iId]['issue'] = $sClass.'::'.$iId.' '.Dict::S('UI:Delete:MustBeDeletedManually');
$this->m_bFoundStopper = true; $this->m_bFoundStopper = true;
$this->m_bFoundManualDelete = true; $this->m_bFoundManualDelete = true;
@@ -92,30 +88,25 @@ class DeletionPlan
// www.php.net/manual/fr/function.set-time-limit.php#72305 // www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time'); $iPreviousTimeLimit = ini_get('max_execution_time');
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
foreach($this->m_aToUpdate as $sClass => $aToUpdate) foreach ($this->m_aToUpdate as $sClass => $aToUpdate) {
{ foreach ($aToUpdate as $iId => $aData) {
foreach($aToUpdate as $iId => $aData)
{
set_time_limit(intval($iLoopTimeLimit)); set_time_limit(intval($iLoopTimeLimit));
$this->m_iToUpdate++; $this->m_iToUpdate++;
$oObject = $aData['to_reset']; $oObject = $aData['to_reset'];
$aExtKeyLabels = array(); $aExtKeyLabels = [];
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) {
{
$oObject->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]); $oObject->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
$aExtKeyLabels[] = $aRemoteAttDef->GetLabel(); $aExtKeyLabels[] = $aRemoteAttDef->GetLabel();
} }
$this->m_aToUpdate[$sClass][$iId]['attributes_list'] = implode(', ', $aExtKeyLabels); $this->m_aToUpdate[$sClass][$iId]['attributes_list'] = implode(', ', $aExtKeyLabels);
list($bRes, $aIssues, $bSecurityIssues) = $oObject->CheckToWrite(); list($bRes, $aIssues, $bSecurityIssues) = $oObject->CheckToWrite();
if (!$bRes) if (!$bRes) {
{
$this->m_aToUpdate[$sClass][$iId]['issue'] = implode(', ', $aIssues); $this->m_aToUpdate[$sClass][$iId]['issue'] = implode(', ', $aIssues);
$this->m_bFoundStopper = true; $this->m_bFoundStopper = true;
if ($bSecurityIssues) if ($bSecurityIssues) {
{
$this->m_aToUpdate[$sClass][$iId]['issue_security'] = true; $this->m_aToUpdate[$sClass][$iId]['issue_security'] = true;
$this->m_bFoundSecurityIssue = true; $this->m_bFoundSecurityIssue = true;
} }
@@ -127,23 +118,17 @@ class DeletionPlan
public function GetIssues() public function GetIssues()
{ {
$aIssues = array(); $aIssues = [];
foreach ($this->m_aToDelete as $sClass => $aToDelete) foreach ($this->m_aToDelete as $sClass => $aToDelete) {
{ foreach ($aToDelete as $iId => $aData) {
foreach ($aToDelete as $iId => $aData) if (isset($aData['issue'])) {
{
if (isset($aData['issue']))
{
$aIssues[] = $aData['issue']; $aIssues[] = $aData['issue'];
} }
} }
} }
foreach ($this->m_aToUpdate as $sClass => $aToUpdate) foreach ($this->m_aToUpdate as $sClass => $aToUpdate) {
{ foreach ($aToUpdate as $iId => $aData) {
foreach ($aToUpdate as $iId => $aData) if (isset($aData['issue'])) {
{
if (isset($aData['issue']))
{
$aIssues[] = $aData['issue']; $aIssues[] = $aData['issue'];
} }
} }
@@ -192,63 +177,50 @@ class DeletionPlan
public function AddToDelete($oObject, $iDeletionMode = null) public function AddToDelete($oObject, $iDeletionMode = null)
{ {
if (is_null($iDeletionMode)) if (is_null($iDeletionMode)) {
{
$bRequestedExplicitely = true; $bRequestedExplicitely = true;
$iDeletionMode = DEL_AUTO; $iDeletionMode = DEL_AUTO;
} } else {
else
{
$bRequestedExplicitely = false; $bRequestedExplicitely = false;
} }
$sClass = get_class($oObject); $sClass = get_class($oObject);
$iId = $oObject->GetKey(); $iId = $oObject->GetKey();
if (isset($this->m_aToUpdate[$sClass][$iId])) if (isset($this->m_aToUpdate[$sClass][$iId])) {
{
unset($this->m_aToUpdate[$sClass][$iId]); unset($this->m_aToUpdate[$sClass][$iId]);
} }
if (isset($this->m_aToDelete[$sClass][$iId])) if (isset($this->m_aToDelete[$sClass][$iId])) {
{ if ($this->m_aToDelete[$sClass][$iId]['requested_explicitely']) {
if ($this->m_aToDelete[$sClass][$iId]['requested_explicitely'])
{
// No change: let it in mode DEL_AUTO // No change: let it in mode DEL_AUTO
} } else {
else
{
$iPrevDeletionMode = $this->m_aToDelete[$sClass][$iId]['mode']; $iPrevDeletionMode = $this->m_aToDelete[$sClass][$iId]['mode'];
$iNewDeletionMode = self::$m_aModeUpdate[$iPrevDeletionMode][$iDeletionMode]; $iNewDeletionMode = self::$m_aModeUpdate[$iPrevDeletionMode][$iDeletionMode];
$this->m_aToDelete[$sClass][$iId]['mode'] = $iNewDeletionMode; $this->m_aToDelete[$sClass][$iId]['mode'] = $iNewDeletionMode;
if ($bRequestedExplicitely) if ($bRequestedExplicitely) {
{
// This object was in the root list // This object was in the root list
$this->m_aToDelete[$sClass][$iId]['requested_explicitely'] = true; $this->m_aToDelete[$sClass][$iId]['requested_explicitely'] = true;
$this->m_aToDelete[$sClass][$iId]['mode'] = DEL_AUTO; $this->m_aToDelete[$sClass][$iId]['mode'] = DEL_AUTO;
} }
} }
} } else {
else $this->m_aToDelete[$sClass][$iId] = [
{
$this->m_aToDelete[$sClass][$iId] = array(
'to_delete' => $oObject, 'to_delete' => $oObject,
'mode' => $iDeletionMode, 'mode' => $iDeletionMode,
'requested_explicitely' => $bRequestedExplicitely, 'requested_explicitely' => $bRequestedExplicitely,
); ];
} }
} }
public function SetDeletionIssues($oObject, $aIssues, $bSecurityIssue) public function SetDeletionIssues($oObject, $aIssues, $bSecurityIssue)
{ {
if (count($aIssues ?? []) > 0) if (count($aIssues ?? []) > 0) {
{
$sClass = get_class($oObject); $sClass = get_class($oObject);
$iId = $oObject->GetKey(); $iId = $oObject->GetKey();
$this->m_aToDelete[$sClass][$iId]['issue'] = implode(', ', $aIssues); $this->m_aToDelete[$sClass][$iId]['issue'] = implode(', ', $aIssues);
if ($bSecurityIssue) if ($bSecurityIssue) {
{
$this->m_aToDelete[$sClass][$iId]['issue_security'] = true; $this->m_aToDelete[$sClass][$iId]['issue_security'] = true;
} }
} }
@@ -258,21 +230,16 @@ class DeletionPlan
{ {
$sClass = get_class($oObject); $sClass = get_class($oObject);
$iId = $oObject->GetKey(); $iId = $oObject->GetKey();
if (isset($this->m_aToDelete[$sClass][$iId])) if (isset($this->m_aToDelete[$sClass][$iId])) {
{
// skip... it should be deleted anyhow ! // skip... it should be deleted anyhow !
} } else {
else if (!isset($this->m_aToUpdate[$sClass][$iId])) {
{ $this->m_aToUpdate[$sClass][$iId] = [
if (!isset($this->m_aToUpdate[$sClass][$iId]))
{
$this->m_aToUpdate[$sClass][$iId] = array(
'to_reset' => $oObject, 'to_reset' => $oObject,
); ];
} }
$this->m_aToUpdate[$sClass][$iId]['attributes'][$oAttDef->GetCode()] = $oAttDef; $this->m_aToUpdate[$sClass][$iId]['attributes'][$oAttDef->GetCode()] = $oAttDef;
$this->m_aToUpdate[$sClass][$iId]['values'][$oAttDef->GetCode()] = $value; $this->m_aToUpdate[$sClass][$iId]['values'][$oAttDef->GetCode()] = $value;
} }
} }
} }
?>

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (c) 2010-2024 Combodo SAS * Copyright (c) 2010-2024 Combodo SAS
* *
@@ -46,11 +47,9 @@ use utils;
*/ */
class DesignDocument extends DOMDocument class DesignDocument extends DOMDocument
{ {
/** To fix DOMNode::getLineNo() ref https://www.php.net/manual/en/domnode.getlineno.php */ /** To fix DOMNode::getLineNo() ref https://www.php.net/manual/en/domnode.getlineno.php */
public const XML_PARSE_BIG_LINES = 4194304; public const XML_PARSE_BIG_LINES = 4194304;
/** /**
* @throws \Exception * @throws \Exception
*/ */
@@ -135,13 +134,10 @@ class DesignDocument extends DOMDocument
*/ */
public static function XPathQuote($sValue) public static function XPathQuote($sValue)
{ {
if (strpos($sValue, '"') !== false) if (strpos($sValue, '"') !== false) {
{
$aParts = explode('"', $sValue); $aParts = explode('"', $sValue);
$sRet = 'concat("'.implode('", \'"\', "', $aParts).'")'; $sRet = 'concat("'.implode('", \'"\', "', $aParts).'")';
} } else {
else
{
$sRet = '"'.$sValue.'"'; $sRet = '"'.$sValue.'"';
} }
return $sRet; return $sRet;
@@ -156,12 +152,9 @@ class DesignDocument extends DOMDocument
public function GetNodes($sXPath, $oContextNode = null) public function GetNodes($sXPath, $oContextNode = null)
{ {
$oXPath = new \DOMXPath($this); $oXPath = new \DOMXPath($this);
if (is_null($oContextNode)) if (is_null($oContextNode)) {
{
$oResult = $oXPath->query($sXPath); $oResult = $oXPath->query($sXPath);
} } else {
else
{
$oResult = $oXPath->query($sXPath, $oContextNode); $oResult = $oXPath->query($sXPath, $oContextNode);
} }
return $oResult; return $oResult;
@@ -174,8 +167,12 @@ class DesignDocument extends DOMDocument
*/ */
public static function GetItopNodePath($oNode) public static function GetItopNodePath($oNode)
{ {
if ($oNode instanceof \DOMDocument) return ''; if ($oNode instanceof \DOMDocument) {
if (is_null($oNode)) return ''; return '';
}
if (is_null($oNode)) {
return '';
}
$sId = $oNode->getAttribute('id'); $sId = $oNode->getAttribute('id');
$sNodeDesc = ($sId != '') ? $oNode->nodeName.'['.$sId.']' : $oNode->nodeName; $sNodeDesc = ($sId != '') ? $oNode->nodeName.'['.$sId.']' : $oNode->nodeName;
@@ -303,16 +300,13 @@ class DesignElement extends \DOMElement
public function GetUniqueElement($sTagName, $bMustExist = true) public function GetUniqueElement($sTagName, $bMustExist = true)
{ {
$oNode = null; $oNode = null;
foreach($this->childNodes as $oChildNode) foreach ($this->childNodes as $oChildNode) {
{ if ($oChildNode->nodeName == $sTagName) {
if ($oChildNode->nodeName == $sTagName)
{
$oNode = $oChildNode; $oNode = $oChildNode;
break; break;
} }
} }
if ($bMustExist && is_null($oNode)) if ($bMustExist && is_null($oNode)) {
{
throw new DOMFormatException('Missing unique tag: '.$sTagName); throw new DOMFormatException('Missing unique tag: '.$sTagName);
} }
return $oNode; return $oNode;
@@ -337,20 +331,17 @@ class DesignElement extends \DOMElement
public function GetText($sDefault = null) public function GetText($sDefault = null)
{ {
$sText = null; $sText = null;
foreach($this->childNodes as $oChildNode) foreach ($this->childNodes as $oChildNode) {
{ if ($oChildNode instanceof \DOMText) {
if ($oChildNode instanceof \DOMText) if (is_null($sText)) {
{ $sText = '';
if (is_null($sText)) $sText = ''; }
$sText .= $oChildNode->wholeText; $sText .= $oChildNode->wholeText;
} }
} }
if (is_null($sText)) if (is_null($sText)) {
{
return $sDefault; return $sDefault;
} } else {
else
{
return $sText; return $sText;
} }
} }
@@ -367,8 +358,7 @@ class DesignElement extends \DOMElement
public function GetChildText($sTagName, $sDefault = null) public function GetChildText($sTagName, $sDefault = null)
{ {
$sRet = $sDefault; $sRet = $sDefault;
if ($oChild = $this->GetOptionalElement($sTagName)) if ($oChild = $this->GetOptionalElement($sTagName)) {
{
$sRet = $oChild->GetText($sDefault); $sRet = $oChild->GetText($sDefault);
} }
return $sRet; return $sRet;
@@ -427,7 +417,6 @@ class DesignElement extends \DOMElement
return self::_FindNode($this, $oRefNode, $sSearchId); return self::_FindNode($this, $oRefNode, $sSearchId);
} }
/** /**
* Find the child node matching the given node. * Find the child node matching the given node.
* UNSAFE: may return nodes marked as _alteration="removed" * UNSAFE: may return nodes marked as _alteration="removed"
@@ -482,32 +471,25 @@ class DesignElement extends \DOMElement
*/ */
public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null) public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null)
{ {
if ($oParent instanceof DOMDocument) if ($oParent instanceof DOMDocument) {
{
$oDoc = $oParent->firstChild->ownerDocument; $oDoc = $oParent->firstChild->ownerDocument;
$oRoot = $oParent; $oRoot = $oParent;
} } else {
else
{
$oDoc = $oParent->ownerDocument; $oDoc = $oParent->ownerDocument;
$oRoot = $oParent; $oRoot = $oParent;
} }
$oXPath = new DOMXPath($oDoc); $oXPath = new DOMXPath($oDoc);
if ($oRefNode->hasAttribute('id')) if ($oRefNode->hasAttribute('id')) {
{
// Find the elements having the same tag name and id // Find the elements having the same tag name and id
if (!$sSearchId) if (!$sSearchId) {
{
$sSearchId = $oRefNode->getAttribute('id'); $sSearchId = $oRefNode->getAttribute('id');
} }
$sQuotedId = DesignDocument::XPathQuote($sSearchId); $sQuotedId = DesignDocument::XPathQuote($sSearchId);
$sXPath = './'.$oRefNode->tagName."[@id=$sQuotedId]"; $sXPath = './'.$oRefNode->tagName."[@id=$sQuotedId]";
$oRes = $oXPath->query($sXPath, $oRoot); $oRes = $oXPath->query($sXPath, $oRoot);
} } else {
else
{
// Get the elements having the same tag name // Get the elements having the same tag name
$sXPath = './'.$oRefNode->tagName; $sXPath = './'.$oRefNode->tagName;

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,12 +17,10 @@
// 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/>
define('DICT_ERR_STRING', 1); // when a string is missing, return the identifier define('DICT_ERR_STRING', 1); // when a string is missing, return the identifier
define('DICT_ERR_EXCEPTION', 2); // when a string is missing, throw an exception define('DICT_ERR_EXCEPTION', 2); // when a string is missing, throw an exception
//define('DICT_ERR_LOG', 3); // when a string is missing, log an error //define('DICT_ERR_LOG', 3); // when a string is missing, log an error
/** /**
* Class Dict * Class Dict
* Management of localizable strings * Management of localizable strings
@@ -32,8 +31,8 @@ class Dict
protected static $m_sDefaultLanguage = 'EN US'; protected static $m_sDefaultLanguage = 'EN US';
protected static $m_sCurrentLanguage = null; // No language selected by default protected static $m_sCurrentLanguage = null; // No language selected by default
protected static $m_aLanguages = array(); // array( code => array( 'description' => '...', 'localized_description' => '...') ...) protected static $m_aLanguages = []; // array( code => array( 'description' => '...', 'localized_description' => '...') ...)
protected static $m_aData = array(); protected static $m_aData = [];
protected static $m_sApplicationPrefix = null; protected static $m_sApplicationPrefix = null;
/** @var \ApcService $m_oApcService */ /** @var \ApcService $m_oApcService */
protected static $m_oApcService = null; protected static $m_oApcService = null;
@@ -45,8 +44,7 @@ class Dict
*/ */
public static function SetDefaultLanguage($sLanguageCode) public static function SetDefaultLanguage($sLanguageCode)
{ {
if (!array_key_exists($sLanguageCode, self::$m_aLanguages)) if (!array_key_exists($sLanguageCode, self::$m_aLanguages)) {
{
throw new DictExceptionUnknownLanguage($sLanguageCode); throw new DictExceptionUnknownLanguage($sLanguageCode);
} }
self::$m_sDefaultLanguage = $sLanguageCode; self::$m_sDefaultLanguage = $sLanguageCode;
@@ -60,18 +58,15 @@ class Dict
*/ */
public static function SetUserLanguage($sLanguageCode = null) public static function SetUserLanguage($sLanguageCode = null)
{ {
if (!is_null($sLanguageCode) && !array_key_exists($sLanguageCode, self::$m_aLanguages)) if (!is_null($sLanguageCode) && !array_key_exists($sLanguageCode, self::$m_aLanguages)) {
{
throw new DictExceptionUnknownLanguage($sLanguageCode); throw new DictExceptionUnknownLanguage($sLanguageCode);
} }
self::$m_sCurrentLanguage = $sLanguageCode; self::$m_sCurrentLanguage = $sLanguageCode;
} }
public static function GetUserLanguage() public static function GetUserLanguage()
{ {
if (self::$m_sCurrentLanguage == null) // May happen when no user is logged in (i.e. login screen, non-authenticated page) if (self::$m_sCurrentLanguage == null) { // May happen when no user is logged in (i.e. login screen, non-authenticated page)
{
// In which case let's use the default language // In which case let's use the default language
return self::$m_sDefaultLanguage; return self::$m_sDefaultLanguage;
} }
@@ -99,8 +94,7 @@ class Dict
public static function Exists($sStringCode) public static function Exists($sStringCode)
{ {
$sImpossibleString = 'aVlHYKEI3TZuDV5o0pghv7fvhYNYuzYkTk7WL0Zoqw8rggE7aq'; $sImpossibleString = 'aVlHYKEI3TZuDV5o0pghv7fvhYNYuzYkTk7WL0Zoqw8rggE7aq';
if (static::S($sStringCode, $sImpossibleString) === $sImpossibleString) if (static::S($sStringCode, $sImpossibleString) === $sImpossibleString) {
{
return false; return false;
} }
return true; return true;
@@ -139,26 +133,22 @@ class Dict
$sLangCode = self::GetUserLanguage(); $sLangCode = self::GetUserLanguage();
self::InitLangIfNeeded($sLangCode); self::InitLangIfNeeded($sLangCode);
if (! array_key_exists($sLangCode, self::$m_aData)) if (! array_key_exists($sLangCode, self::$m_aData)) {
{
IssueLog::Warning("Cannot find $sLangCode in all registered dictionaries."); IssueLog::Warning("Cannot find $sLangCode in all registered dictionaries.");
// It may happen, when something happens before the dictionaries get loaded // It may happen, when something happens before the dictionaries get loaded
return [ 'label' => $sStringCode, 'lang' => $sLangCode ]; return [ 'label' => $sStringCode, 'lang' => $sLangCode ];
} }
$aCurrentDictionary = self::$m_aData[$sLangCode]; $aCurrentDictionary = self::$m_aData[$sLangCode];
if (is_array($aCurrentDictionary) && array_key_exists($sStringCode, $aCurrentDictionary)) if (is_array($aCurrentDictionary) && array_key_exists($sStringCode, $aCurrentDictionary)) {
{
return [ 'label' => $aCurrentDictionary[$sStringCode], 'lang' => $sLangCode ]; return [ 'label' => $aCurrentDictionary[$sStringCode], 'lang' => $sLangCode ];
} }
if (!$bUserLanguageOnly) if (!$bUserLanguageOnly) {
{
// Attempt to find the string in the default language // Attempt to find the string in the default language
// //
self::InitLangIfNeeded(self::$m_sDefaultLanguage); self::InitLangIfNeeded(self::$m_sDefaultLanguage);
$aDefaultDictionary = self::$m_aData[self::$m_sDefaultLanguage]; $aDefaultDictionary = self::$m_aData[self::$m_sDefaultLanguage];
if (is_array($aDefaultDictionary) && array_key_exists($sStringCode, $aDefaultDictionary)) if (is_array($aDefaultDictionary) && array_key_exists($sStringCode, $aDefaultDictionary)) {
{
return [ 'label' => $aDefaultDictionary[$sStringCode], 'lang' => self::$m_sDefaultLanguage ]; return [ 'label' => $aDefaultDictionary[$sStringCode], 'lang' => self::$m_sDefaultLanguage ];
} }
// Attempt to find the string in english // Attempt to find the string in english
@@ -166,22 +156,19 @@ class Dict
self::InitLangIfNeeded('EN US'); self::InitLangIfNeeded('EN US');
$aDefaultDictionary = self::$m_aData['EN US']; $aDefaultDictionary = self::$m_aData['EN US'];
if (is_array($aDefaultDictionary) && array_key_exists($sStringCode, $aDefaultDictionary)) if (is_array($aDefaultDictionary) && array_key_exists($sStringCode, $aDefaultDictionary)) {
{
return [ 'label' => $aDefaultDictionary[$sStringCode], 'lang' => 'EN US' ]; return [ 'label' => $aDefaultDictionary[$sStringCode], 'lang' => 'EN US' ];
} }
} }
// Could not find the string... // Could not find the string...
// //
if (is_null($sDefault)) if (is_null($sDefault)) {
{
return [ 'label' => $sStringCode, 'lang' => null ]; return [ 'label' => $sStringCode, 'lang' => null ];
} }
return [ 'label' => $sDefault, 'lang' => null ]; return [ 'label' => $sDefault, 'lang' => null ];
} }
/** /**
* Formats a localized string with numbered placeholders (%1$s...) for the additional arguments * Formats a localized string with numbered placeholders (%1$s...) for the additional arguments
* See vsprintf for more information about the syntax of the placeholders * See vsprintf for more information about the syntax of the placeholders
@@ -199,8 +186,7 @@ class Dict
$aArguments = func_get_args(); $aArguments = func_get_args();
array_shift($aArguments); array_shift($aArguments);
if ($sLocalizedFormat == $sFormatCode) if ($sLocalizedFormat == $sFormatCode) {
{
// Make sure the information will be displayed (ex: an error occurring before the dictionary gets loaded) // Make sure the information will be displayed (ex: an error occurring before the dictionary gets loaded)
return $sFormatCode.' - '.implode(', ', $aArguments); return $sFormatCode.' - '.implode(', ', $aArguments);
} }
@@ -236,7 +222,8 @@ class Dict
* @since 2.7.6 N°4125 * @since 2.7.6 N°4125
* @return \ApcService * @return \ApcService
*/ */
public static function GetApcService() { public static function GetApcService()
{
if (self::$m_oApcService === null) { if (self::$m_oApcService === null) {
self::$m_oApcService = new ApcService(); self::$m_oApcService = new ApcService();
} }
@@ -247,7 +234,8 @@ class Dict
* @since 2.7.6 N°4125 * @since 2.7.6 N°4125
* @param \ApcService $m_oApcService * @param \ApcService $m_oApcService
*/ */
public static function SetApcService($oApcService) { public static function SetApcService($oApcService)
{
self::$m_oApcService = $oApcService; self::$m_oApcService = $oApcService;
} }
@@ -258,13 +246,14 @@ class Dict
*/ */
public static function InitLangIfNeeded($sLangCode) public static function InitLangIfNeeded($sLangCode)
{ {
if (array_key_exists($sLangCode, self::$m_aData)) return true; if (array_key_exists($sLangCode, self::$m_aData)) {
return true;
}
$bResult = false; $bResult = false;
if (self::GetApcService()->function_exists('apc_fetch') if (self::GetApcService()->function_exists('apc_fetch')
&& (self::$m_sApplicationPrefix !== null)) && (self::$m_sApplicationPrefix !== null)) {
{
// Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter // Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter
// //
self::$m_aData[$sLangCode] = self::GetApcService()->apc_fetch(self::$m_sApplicationPrefix.'-dict-'.$sLangCode); self::$m_aData[$sLangCode] = self::GetApcService()->apc_fetch(self::$m_sApplicationPrefix.'-dict-'.$sLangCode);
@@ -279,14 +268,12 @@ class Dict
$bResult = true; $bResult = true;
} }
} }
if (!$bResult) if (!$bResult) {
{
$sDictFile = APPROOT.'env-'.utils::GetCurrentEnvironment().'/dictionaries/'.str_replace(' ', '-', strtolower($sLangCode)).'.dict.php'; $sDictFile = APPROOT.'env-'.utils::GetCurrentEnvironment().'/dictionaries/'.str_replace(' ', '-', strtolower($sLangCode)).'.dict.php';
require_once($sDictFile); require_once($sDictFile);
if (self::GetApcService()->function_exists('apc_store') if (self::GetApcService()->function_exists('apc_store')
&& (self::$m_sApplicationPrefix !== null)) && (self::$m_sApplicationPrefix !== null)) {
{
self::GetApcService()->apc_store(self::$m_sApplicationPrefix.'-dict-'.$sLangCode, self::$m_aData[$sLangCode]); self::GetApcService()->apc_store(self::$m_sApplicationPrefix.'-dict-'.$sLangCode, self::$m_aData[$sLangCode]);
} }
$bResult = true; $bResult = true;
@@ -309,10 +296,8 @@ class Dict
*/ */
public static function ResetCache($sApplicationPrefix) public static function ResetCache($sApplicationPrefix)
{ {
if (function_exists('apc_delete')) if (function_exists('apc_delete')) {
{ foreach (self::$m_aLanguages as $sLang => $void) {
foreach(self::$m_aLanguages as $sLang => $void)
{
apc_delete($sApplicationPrefix.'-dict-'.$sLang); apc_delete($sApplicationPrefix.'-dict-'.$sLang);
} }
} }
@@ -320,7 +305,6 @@ class Dict
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
/** /**
* Clone a string in every language (if it exists in that language) * Clone a string in every language (if it exists in that language)
* *
@@ -339,40 +323,31 @@ class Dict
public static function MakeStats($sLanguageCode, $sLanguageRef = 'EN US') public static function MakeStats($sLanguageCode, $sLanguageRef = 'EN US')
{ {
$aMissing = array(); // Strings missing for the target language $aMissing = []; // Strings missing for the target language
$aUnexpected = array(); // Strings defined for the target language, but not found in the reference dictionary $aUnexpected = []; // Strings defined for the target language, but not found in the reference dictionary
$aNotTranslated = array(); // Strings having the same value in both dictionaries $aNotTranslated = []; // Strings having the same value in both dictionaries
$aOK = array(); // Strings having different values in both dictionaries $aOK = []; // Strings having different values in both dictionaries
foreach (self::$m_aData[$sLanguageRef] as $sStringCode => $sValue) foreach (self::$m_aData[$sLanguageRef] as $sStringCode => $sValue) {
{ if (!array_key_exists($sStringCode, self::$m_aData[$sLanguageCode])) {
if (!array_key_exists($sStringCode, self::$m_aData[$sLanguageCode]))
{
$aMissing[$sStringCode] = $sValue; $aMissing[$sStringCode] = $sValue;
} }
} }
foreach (self::$m_aData[$sLanguageCode] as $sStringCode => $sValue) foreach (self::$m_aData[$sLanguageCode] as $sStringCode => $sValue) {
{ if (!array_key_exists($sStringCode, self::$m_aData[$sLanguageRef])) {
if (!array_key_exists($sStringCode, self::$m_aData[$sLanguageRef]))
{
$aUnexpected[$sStringCode] = $sValue; $aUnexpected[$sStringCode] = $sValue;
} } else {
else
{
// The value exists in the reference // The value exists in the reference
$sRefValue = self::$m_aData[$sLanguageRef][$sStringCode]; $sRefValue = self::$m_aData[$sLanguageRef][$sStringCode];
if ($sValue == $sRefValue) if ($sValue == $sRefValue) {
{
$aNotTranslated[$sStringCode] = $sValue; $aNotTranslated[$sStringCode] = $sValue;
} } else {
else
{
$aOK[$sStringCode] = $sValue; $aOK[$sStringCode] = $sValue;
} }
} }
} }
return array($aMissing, $aUnexpected, $aNotTranslated, $aOK); return [$aMissing, $aUnexpected, $aNotTranslated, $aOK];
} }
public static function Dump() public static function Dump()
@@ -389,10 +364,9 @@ class Dict
// ~~ or ~* can be used to indicate entries still to be translated. // ~~ or ~* can be used to indicate entries still to be translated.
public static function Add($sLanguageCode, $sEnglishLanguageDesc, $sLocalizedLanguageDesc, $aEntries) public static function Add($sLanguageCode, $sEnglishLanguageDesc, $sLocalizedLanguageDesc, $aEntries)
{ {
if (!array_key_exists($sLanguageCode, self::$m_aLanguages)) if (!array_key_exists($sLanguageCode, self::$m_aLanguages)) {
{ self::$m_aLanguages[$sLanguageCode] = ['description' => $sEnglishLanguageDesc, 'localized_description' => $sLocalizedLanguageDesc];
self::$m_aLanguages[$sLanguageCode] = array('description' => $sEnglishLanguageDesc, 'localized_description' => $sLocalizedLanguageDesc); self::$m_aData[$sLanguageCode] = [];
self::$m_aData[$sLanguageCode] = array();
} }
// No need to actually load the strings since it's only used to know the list of languages // No need to actually load the strings since it's only used to know the list of languages
// at setup time !! // at setup time !!
@@ -408,27 +382,22 @@ class Dict
{ {
self::InitLangIfNeeded(self::GetUserLanguage()); self::InitLangIfNeeded(self::GetUserLanguage());
self::InitLangIfNeeded(self::$m_sDefaultLanguage); self::InitLangIfNeeded(self::$m_sDefaultLanguage);
$aEntries = array(); $aEntries = [];
$iLength = strlen($sStartingWith); $iLength = strlen($sStartingWith);
// First prefill the array with entries from the default language // First prefill the array with entries from the default language
foreach(self::$m_aData[self::$m_sDefaultLanguage] as $sCode => $sEntry) foreach (self::$m_aData[self::$m_sDefaultLanguage] as $sCode => $sEntry) {
{ if (substr($sCode, 0, $iLength) == $sStartingWith) {
if (substr($sCode, 0, $iLength) == $sStartingWith)
{
$aEntries[$sCode] = $sEntry; $aEntries[$sCode] = $sEntry;
} }
} }
// Now put (overwrite) the entries for the user language // Now put (overwrite) the entries for the user language
foreach(self::$m_aData[self::GetUserLanguage()] as $sCode => $sEntry) foreach (self::$m_aData[self::GetUserLanguage()] as $sCode => $sEntry) {
{ if (substr($sCode, 0, $iLength) == $sStartingWith) {
if (substr($sCode, 0, $iLength) == $sStartingWith)
{
$aEntries[$sCode] = $sEntry; $aEntries[$sCode] = $sEntry;
} }
} }
return $aEntries; return $aEntries;
} }
} }
?>

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/>
/** /**
* Send an email (abstraction for synchronous/asynchronous modes) * Send an email (abstraction for synchronous/asynchronous modes)
* *
@@ -43,18 +43,18 @@ class EMail implements iEMail
protected $oMailer; protected $oMailer;
// Serialization formats // Serialization formats
const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object. public const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object.
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string // Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed) public const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed)
/** @var int ENUM_SEND_DEFAULT This option can be used when sending an e-mail to respect the default configuration parameter. */ /** @var int ENUM_SEND_DEFAULT This option can be used when sending an e-mail to respect the default configuration parameter. */
const ENUM_SEND_DEFAULT = 0; public const ENUM_SEND_DEFAULT = 0;
/** @var int ENUM_SEND_FORCE_SYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: instant e-mail test. */ /** @var int ENUM_SEND_FORCE_SYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: instant e-mail test. */
const ENUM_SEND_FORCE_SYNCHRONOUS = 1; public const ENUM_SEND_FORCE_SYNCHRONOUS = 1;
/** @var int ENUM_SEND_FORCE_ASYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: Bulk mails. */ /** @var int ENUM_SEND_FORCE_ASYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: Bulk mails. */
const ENUM_SEND_FORCE_ASYNCHRONOUS = 2; public const ENUM_SEND_FORCE_ASYNCHRONOUS = 2;
public function __construct() public function __construct()
{ {

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
@@ -47,8 +48,7 @@ class ExcelBulkExport extends TabularBulkExport
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true); $this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
$sDateFormatRadio = utils::ReadParam('excel_date_format_radio', ''); $sDateFormatRadio = utils::ReadParam('excel_date_format_radio', '');
switch($sDateFormatRadio) switch ($sDateFormatRadio) {
{
case 'default': case 'default':
// Export from the UI => format = same as is the UI // Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat(); $this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
@@ -67,7 +67,7 @@ class ExcelBulkExport extends TabularBulkExport
public function EnumFormParts() public function EnumFormParts()
{ {
return array_merge(parent::EnumFormParts(), array('xlsx_options' => array('formatted_text'), 'interactive_fields_xlsx' => array('interactive_fields_xlsx'))); return array_merge(parent::EnumFormParts(), ['xlsx_options' => ['formatted_text'], 'interactive_fields_xlsx' => ['interactive_fields_xlsx']]);
} }
/** /**
@@ -121,7 +121,6 @@ class ExcelBulkExport extends TabularBulkExport
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oFieldSetDate->AddSubBlock($oRadioCustom); $oFieldSetDate->AddSubBlock($oRadioCustom);
$oP->add_ready_script( $oP->add_ready_script(
<<<EOF <<<EOF
$('#form_part_xlsx_options').on('preview_updated', function() { FormatDatesInPreview('excel', 'xlsx'); }); $('#form_part_xlsx_options').on('preview_updated', function() { FormatDatesInPreview('excel', 'xlsx'); });
@@ -141,16 +140,14 @@ EOF
protected function SuggestField($sClass, $sAttCode) protected function SuggestField($sClass, $sAttCode)
{ {
switch($sAttCode) switch ($sAttCode) {
{
case 'id': // replace 'id' by 'friendlyname' case 'id': // replace 'id' by 'friendlyname'
$sAttCode = 'friendlyname'; $sAttCode = 'friendlyname';
break; break;
default: default:
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey) if ($oAttDef instanceof AttributeExternalKey) {
{
$sAttCode .= '_friendlyname'; $sAttCode .= '_friendlyname';
} }
} }
@@ -162,8 +159,7 @@ EOF
{ {
if ($sAttCode != 'id') { if ($sAttCode != 'id') {
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime if ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
{
$sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date';
return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>'; return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>';
@@ -175,71 +171,47 @@ EOF
protected function GetValue($oObj, $sAttCode) protected function GetValue($oObj, $sAttCode)
{ {
switch($sAttCode) switch ($sAttCode) {
{
case 'id': case 'id':
$sRet = $oObj->GetKey(); $sRet = $oObj->GetKey();
break; break;
default: default:
$value = $oObj->Get($sAttCode); $value = $oObj->Get($sAttCode);
if ($value instanceOf ormCaseLog) if ($value instanceof ormCaseLog) {
{ if (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text']) {
if (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text'])
{
$sText = $value->GetText(); $sText = $value->GetText();
} } else {
else
{
$sText = $value->GetAsPlainText(); $sText = $value->GetAsPlainText();
} }
// 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! // 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!
$sRet = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $sText)); $sRet = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $sText));
} } elseif ($value instanceof DBObjectSet) {
else if ($value instanceOf DBObjectSet)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj); $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
} } elseif ($value instanceof ormDocument) {
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj); $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
} } elseif ($value instanceof ormSet) {
else if ($value instanceOf ormSet)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj); $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
} } else {
else
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
if ($oAttDef instanceof AttributeDateTime) if ($oAttDef instanceof AttributeDateTime) {
{
// Date and times are formatted using the ISO encoding, not the localized format // Date and times are formatted using the ISO encoding, not the localized format
if ($oAttDef->IsNull($value)) if ($oAttDef->IsNull($value)) {
{
// NOt a valid date // NOt a valid date
$sRet = ''; $sRet = '';
} } else {
else
{
$sRet = $value; $sRet = $value;
} }
} } elseif (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text']) {
else if (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text']) if ($oAttDef instanceof AttributeText && $oAttDef->GetFormat() == 'html') {
{
if ($oAttDef instanceof AttributeText && $oAttDef->GetFormat()=='html')
{
$sRet = str_replace("&gt;", ">", $value); $sRet = str_replace("&gt;", ">", $value);
} } else {
else
{
$sRet = $oAttDef->GetEditValue($value, $oObj); $sRet = $oAttDef->GetEditValue($value, $oObj);
} }
} } else {
else
{
$sRet = $oAttDef->GetAsPlainText($value, $oObj); $sRet = $oAttDef->GetAsPlainText($value, $oObj);
} }
} }
@@ -255,14 +227,12 @@ EOF
$this->aStatusInfo['position'] = 0; $this->aStatusInfo['position'] = 0;
$this->aStatusInfo['total'] = $oSet->Count(); $this->aStatusInfo['total'] = $oSet->Count();
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$sExtendedAttCode = $aFieldSpec['sFieldSpec']; $sExtendedAttCode = $aFieldSpec['sFieldSpec'];
$sAttCode = $aFieldSpec['sAttCode']; $sAttCode = $aFieldSpec['sAttCode'];
$sColLabel = $aFieldSpec['sColLabel']; $sColLabel = $aFieldSpec['sColLabel'];
switch($sAttCode) switch ($sAttCode) {
{
case 'id': case 'id':
$sType = '0'; $sType = '0';
break; break;
@@ -270,22 +240,18 @@ EOF
default: default:
$oAttDef = MetaModel::GetAttributeDef($aFieldSpec['sClass'], $aFieldSpec['sAttCode']); $oAttDef = MetaModel::GetAttributeDef($aFieldSpec['sClass'], $aFieldSpec['sAttCode']);
$sType = 'string'; $sType = 'string';
if($oAttDef instanceof AttributeDate) if ($oAttDef instanceof AttributeDate) {
{
$sType = 'date'; $sType = 'date';
} } elseif ($oAttDef instanceof AttributeDateTime) {
else if($oAttDef instanceof AttributeDateTime)
{
$sType = 'datetime'; $sType = 'datetime';
} }
} }
$aTableHeaders[] = array('label' => $sColLabel, 'type' => $sType); $aTableHeaders[] = ['label' => $sColLabel, 'type' => $sType];
} }
$sRow = json_encode($aTableHeaders); $sRow = json_encode($aTableHeaders);
$hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab'); $hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab');
if ($hFile === false) if ($hFile === false) {
{
throw new Exception('ExcelBulkExport: Failed to open temporary data file: "'.$this->aStatusInfo['tmp_file'].'" for writing.'); throw new Exception('ExcelBulkExport: Failed to open temporary data file: "'.$this->aStatusInfo['tmp_file'].'" for writing.');
} }
fwrite($hFile, $sRow."\n"); fwrite($hFile, $sRow."\n");
@@ -307,19 +273,16 @@ EOF
$iCount = 0; $iCount = 0;
$iPreviousTimeLimit = ini_get('max_execution_time'); $iPreviousTimeLimit = ini_get('max_execution_time');
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
while($aRow = $oSet->FetchAssoc()) while ($aRow = $oSet->FetchAssoc()) {
{
set_time_limit(intval($iLoopTimeLimit)); set_time_limit(intval($iLoopTimeLimit));
$aData = array(); $aData = [];
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$sAlias = $aFieldSpec['sAlias']; $sAlias = $aFieldSpec['sAlias'];
$sAttCode = $aFieldSpec['sAttCode']; $sAttCode = $aFieldSpec['sAttCode'];
$oObj = $aRow[$sAlias]; $oObj = $aRow[$sAlias];
$sField = ''; $sField = '';
if ($oObj) if ($oObj) {
{
$sField = $this->GetValue($oObj, $sAttCode); $sField = $this->GetValue($oObj, $sAttCode);
} }
$aData[] = $sField; $aData[] = $sField;
@@ -329,36 +292,30 @@ EOF
} }
set_time_limit(intval($iPreviousTimeLimit)); set_time_limit(intval($iPreviousTimeLimit));
$this->aStatusInfo['position'] += $this->iChunkSize; $this->aStatusInfo['position'] += $this->iChunkSize;
if ($this->aStatusInfo['total'] == 0) if ($this->aStatusInfo['total'] == 0) {
{
$iPercentage = 100; $iPercentage = 100;
$sRetCode = 'done'; // Next phase (GetFooter) will be to build the xlsx file $sRetCode = 'done'; // Next phase (GetFooter) will be to build the xlsx file
} } else {
else
{
$iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total'])); $iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total']));
} }
if ($iCount < $this->iChunkSize) if ($iCount < $this->iChunkSize) {
{
$sRetCode = 'done'; $sRetCode = 'done';
} }
$aStatus = array('code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage); $aStatus = ['code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage];
return ''; // The actual XLSX file is built in GetFooter(); return ''; // The actual XLSX file is built in GetFooter();
} }
public function GetFooter() public function GetFooter()
{ {
$hFile = @fopen($this->aStatusInfo['tmp_file'], 'rb'); $hFile = @fopen($this->aStatusInfo['tmp_file'], 'rb');
if ($hFile === false) if ($hFile === false) {
{
throw new Exception('ExcelBulkExport: Failed to open temporary data file: "'.$this->aStatusInfo['tmp_file'].'" for reading.'); throw new Exception('ExcelBulkExport: Failed to open temporary data file: "'.$this->aStatusInfo['tmp_file'].'" for reading.');
} }
$sHeaders = fgets($hFile); $sHeaders = fgets($hFile);
$aHeaders = json_decode($sHeaders, true); $aHeaders = json_decode($sHeaders, true);
$aData = array(); $aData = [];
while($sLine = fgets($hFile)) while ($sLine = fgets($hFile)) {
{
$aRow = json_decode($sLine); $aRow = json_decode($sLine);
$aData[] = $aRow; $aData[] = $aRow;
} }
@@ -372,10 +329,9 @@ EOF
$oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat()); $oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat());
$writer->setDateFormat($oDateFormat->ToExcel()); $writer->setDateFormat($oDateFormat->ToExcel());
$writer->setAuthor(UserRights::GetUserFriendlyName()); $writer->setAuthor(UserRights::GetUserFriendlyName());
$aHeaderTypes = array(); $aHeaderTypes = [];
$aHeaderNames = array(); $aHeaderNames = [];
foreach($aHeaders as $Header) foreach ($aHeaders as $Header) {
{
$aHeaderNames[] = $Header['label']; $aHeaderNames[] = $Header['label'];
$aHeaderTypes[] = $Header['type']; $aHeaderTypes[] = $Header['type'];
} }
@@ -405,6 +361,6 @@ EOF
public function GetSupportedFormats() public function GetSupportedFormats()
{ {
return array('xlsx' => Dict::S('Core:BulkExport:XLSXFormat')); return ['xlsx' => Dict::S('Core:BulkExport:XLSXFormat')];
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2024 Combodo SAS // Copyright (C) 2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -35,7 +36,7 @@ class HTMLBulkExport extends TabularBulkExport
public function EnumFormParts() public function EnumFormParts()
{ {
return array_merge(parent::EnumFormParts(), array('interactive_fields_html' => array('interactive_fields_html'))); return array_merge(parent::EnumFormParts(), ['interactive_fields_html' => ['interactive_fields_html']]);
} }
/** /**
@@ -58,11 +59,9 @@ class HTMLBulkExport extends TabularBulkExport
protected function GetSampleData($oObj, $sAttCode) protected function GetSampleData($oObj, $sAttCode)
{ {
if ($sAttCode != 'id') if ($sAttCode != 'id') {
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime if ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
{
$sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date';
return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>'; return '<div class="'.$sClass.'" data-date="'.$oObj->Get($sAttCode).'">'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'</div>';
@@ -73,24 +72,18 @@ class HTMLBulkExport extends TabularBulkExport
protected function GetValue($oObj, $sAttCode) protected function GetValue($oObj, $sAttCode)
{ {
switch($sAttCode) switch ($sAttCode) {
{
case 'id': case 'id':
$sRet = $oObj->GetHyperlink(); $sRet = $oObj->GetHyperlink();
break; break;
default: default:
$value = $oObj->Get($sAttCode); $value = $oObj->Get($sAttCode);
if ($value instanceof ormCaseLog) if ($value instanceof ormCaseLog) {
{
$sRet = $value->GetAsSimpleHtml(); $sRet = $value->GetAsSimpleHtml();
} } elseif ($value instanceof ormStopWatch) {
elseif ($value instanceof ormStopWatch)
{
$sRet = $value->GetTimeSpent(); $sRet = $value->GetTimeSpent();
} } else {
else
{
$sRet = $oObj->GetAsHtml($sAttCode); $sRet = $oObj->GetAsHtml($sAttCode);
} }
} }
@@ -109,8 +102,7 @@ class HTMLBulkExport extends TabularBulkExport
$sData .= "<table class=\"listResults\">\n"; $sData .= "<table class=\"listResults\">\n";
$sData .= "<thead>\n"; $sData .= "<thead>\n";
$sData .= "<tr>\n"; $sData .= "<tr>\n";
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$sData .= "<th>".$aFieldSpec['sColLabel']."</th>\n"; $sData .= "<th>".$aFieldSpec['sColLabel']."</th>\n";
} }
$sData .= "</tr>\n"; $sData .= "</tr>\n";
@@ -135,32 +127,25 @@ class HTMLBulkExport extends TabularBulkExport
$sData = ''; $sData = '';
$iPreviousTimeLimit = ini_get('max_execution_time'); $iPreviousTimeLimit = ini_get('max_execution_time');
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
while($aRow = $oSet->FetchAssoc()) while ($aRow = $oSet->FetchAssoc()) {
{
set_time_limit(intval($iLoopTimeLimit)); set_time_limit(intval($iLoopTimeLimit));
$oMainObj = $aRow[$sFirstAlias]; $oMainObj = $aRow[$sFirstAlias];
$sHilightClass = ''; $sHilightClass = '';
if ($oMainObj) if ($oMainObj) {
{
$sHilightClass = MetaModel::GetHilightClass($sClass, $aRow[$sFirstAlias]); $sHilightClass = MetaModel::GetHilightClass($sClass, $aRow[$sFirstAlias]);
} }
if ($sHilightClass != '') if ($sHilightClass != '') {
{
$sData .= "<tr class=\"$sHilightClass\">"; $sData .= "<tr class=\"$sHilightClass\">";
} } else {
else
{
$sData .= "<tr>"; $sData .= "<tr>";
} }
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
{
$sAlias = $aFieldSpec['sAlias']; $sAlias = $aFieldSpec['sAlias'];
$sAttCode = $aFieldSpec['sAttCode']; $sAttCode = $aFieldSpec['sAttCode'];
$oObj = $aRow[$sAlias]; $oObj = $aRow[$sAlias];
$sField = ''; $sField = '';
if ($oObj) if ($oObj) {
{
$sField = $this->GetValue($oObj, $sAttCode); $sField = $this->GetValue($oObj, $sAttCode);
} }
$sValue = ($sField === '') ? '&nbsp;' : $sField; $sValue = ($sField === '') ? '&nbsp;' : $sField;
@@ -171,21 +156,17 @@ class HTMLBulkExport extends TabularBulkExport
} }
set_time_limit(intval($iPreviousTimeLimit)); set_time_limit(intval($iPreviousTimeLimit));
$this->aStatusInfo['position'] += $this->iChunkSize; $this->aStatusInfo['position'] += $this->iChunkSize;
if ($this->aStatusInfo['total'] == 0) if ($this->aStatusInfo['total'] == 0) {
{
$iPercentage = 100; $iPercentage = 100;
} } else {
else
{
$iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total'])); $iPercentage = floor(min(100.0, 100.0 * $this->aStatusInfo['position'] / $this->aStatusInfo['total']));
} }
if ($iCount < $this->iChunkSize) if ($iCount < $this->iChunkSize) {
{
$sRetCode = 'done'; $sRetCode = 'done';
} }
$aStatus = array('code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage); $aStatus = ['code' => $sRetCode, 'message' => Dict::S('Core:BulkExport:RetrievingData'), 'percentage' => $iPercentage];
return $sData; return $sData;
} }
@@ -198,7 +179,7 @@ class HTMLBulkExport extends TabularBulkExport
public function GetSupportedFormats() public function GetSupportedFormats()
{ {
return array('html' => Dict::S('Core:BulkExport:HTMLFormat')); return ['html' => Dict::S('Core:BulkExport:HTMLFormat')];
} }
public function GetMimeType() public function GetMimeType()

View File

@@ -1,4 +1,5 @@
<?php <?php
// Copyright (C) 2016-2024 Combodo SAS // Copyright (C) 2016-2024 Combodo SAS
// //
// This file is part of iTop. // This file is part of iTop.
@@ -62,17 +63,14 @@ abstract class HTMLSanitizer
try { try {
$oSanitizer = new $sSanitizerClass(); $oSanitizer = new $sSanitizerClass();
$sCleanHTML = $oSanitizer->DoSanitize($sHTML); $sCleanHTML = $oSanitizer->DoSanitize($sHTML);
} } catch (Exception $e) {
catch (Exception $e) {
if ($sSanitizerClass != 'HTMLDOMSanitizer') { if ($sSanitizerClass != 'HTMLDOMSanitizer') {
IssueLog::Warning('Failed to sanitize an HTML string with "'.$sSanitizerClass.'". The following exception occured: '.$e->getMessage()); IssueLog::Warning('Failed to sanitize an HTML string with "'.$sSanitizerClass.'". The following exception occured: '.$e->getMessage());
IssueLog::Warning('Will try to sanitize with HTMLDOMSanitizer.'); IssueLog::Warning('Will try to sanitize with HTMLDOMSanitizer.');
// try again with the HTMLDOMSanitizer // try again with the HTMLDOMSanitizer
$oSanitizer = new HTMLDOMSanitizer(); $oSanitizer = new HTMLDOMSanitizer();
$sCleanHTML = $oSanitizer->DoSanitize($sHTML); $sCleanHTML = $oSanitizer->DoSanitize($sHTML);
} } else {
else
{
IssueLog::Error('Failed to sanitize an HTML string with "HTMLDOMSanitizer". The following exception occured: '.$e->getMessage()); IssueLog::Error('Failed to sanitize an HTML string with "HTMLDOMSanitizer". The following exception occured: '.$e->getMessage());
IssueLog::Error('The HTML will NOT be sanitized.'); IssueLog::Error('The HTML will NOT be sanitized.');
$sCleanHTML = $sHTML; $sCleanHTML = $sHTML;
@@ -104,8 +102,6 @@ class HTMLNullSanitizer extends HTMLSanitizer
} }
} }
/** /**
* Common implementation for sanitizer using DOM parsing * Common implementation for sanitizer using DOM parsing
*/ */
@@ -166,7 +162,7 @@ abstract class DOMSanitizer extends HTMLSanitizer
protected function CleanNode(DOMNode $oElement) protected function CleanNode(DOMNode $oElement)
{ {
$aAttrToRemove = array(); $aAttrToRemove = [];
// Gather the attributes to remove // Gather the attributes to remove
if ($oElement->hasAttributes()) { if ($oElement->hasAttributes()) {
foreach ($oElement->attributes as $oAttr) { foreach ($oElement->attributes as $oAttr) {
@@ -192,15 +188,13 @@ abstract class DOMSanitizer extends HTMLSanitizer
} }
} }
// Now remove them // Now remove them
foreach($aAttrToRemove as $sName) foreach ($aAttrToRemove as $sName) {
{
$oElement->removeAttribute($sName); $oElement->removeAttribute($sName);
} }
} }
if ($oElement->hasChildNodes()) if ($oElement->hasChildNodes()) {
{ $aChildElementsToRemove = [];
$aChildElementsToRemove = array();
// Gather the child noes to remove // Gather the child noes to remove
foreach ($oElement->childNodes as $oNode) { foreach ($oElement->childNodes as $oNode) {
if ($oNode instanceof DOMElement) { if ($oNode instanceof DOMElement) {
@@ -225,8 +219,7 @@ abstract class DOMSanitizer extends HTMLSanitizer
} }
} }
// Now remove them // Now remove them
foreach($aChildElementsToRemove as $oDomElement) foreach ($aChildElementsToRemove as $oDomElement) {
{
$oElement->removeChild($oDomElement); $oElement->removeChild($oDomElement);
} }
} }
@@ -252,7 +245,7 @@ abstract class DOMSanitizer extends HTMLSanitizer
return $sStyle; return $sStyle;
} }
$aAllowedStyles = array(); $aAllowedStyles = [];
$aItems = explode(';', $sStyle); $aItems = explode(';', $sStyle);
{ {
foreach ($aItems as $sItem) { foreach ($aItems as $sItem) {
@@ -267,78 +260,76 @@ abstract class DOMSanitizer extends HTMLSanitizer
} }
} }
class HTMLDOMSanitizer extends DOMSanitizer class HTMLDOMSanitizer extends DOMSanitizer
{ {
/** /**
* @var array * @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations * @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
*/ */
protected static $aTagsWhiteList = array( protected static $aTagsWhiteList = [
'html' => array(), 'html' => [],
'body' => array(), 'body' => [],
'a' => array('href', 'name', 'style', 'class', 'target', 'title', 'data-role', 'data-object-class', 'data-object-id', 'data-object-key'), 'a' => ['href', 'name', 'style', 'class', 'target', 'title', 'data-role', 'data-object-class', 'data-object-id', 'data-object-key'],
'p' => array('style', 'class'), 'p' => ['style', 'class'],
'blockquote' => array('style', 'class'), 'blockquote' => ['style', 'class'],
'br' => array(), 'br' => [],
'span' => array('style', 'class'), 'span' => ['style', 'class'],
'div' => array('style', 'class'), 'div' => ['style', 'class'],
'b' => array('class'), 'b' => ['class'],
'i' => array('class'), 'i' => ['class'],
'u' => array('class'), 'u' => ['class'],
'em' => array('class'), 'em' => ['class'],
'strong' => array('class'), 'strong' => ['class'],
'img' => array('src', 'style', 'class', 'alt', 'title', 'width', 'height'), 'img' => ['src', 'style', 'class', 'alt', 'title', 'width', 'height'],
'ul' => array('style', 'class'), 'ul' => ['style', 'class'],
'ol' => array('reversed', 'start', 'style', 'class', 'type'), 'ol' => ['reversed', 'start', 'style', 'class', 'type'],
'li' => array('style', 'class', 'value'), 'li' => ['style', 'class', 'value'],
'h1' => array('style', 'class'), 'h1' => ['style', 'class'],
'h2' => array('style', 'class'), 'h2' => ['style', 'class'],
'h3' => array('style', 'class'), 'h3' => ['style', 'class'],
'h4' => array('style', 'class'), 'h4' => ['style', 'class'],
'nav' => array('style', 'class'), 'nav' => ['style', 'class'],
'section' => array('style', 'class'), 'section' => ['style', 'class'],
'code' => array('style', 'class'), 'code' => ['style', 'class'],
'table' => array('style', 'class', 'width', 'summary', 'align', 'border', 'cellpadding', 'cellspacing'), 'table' => ['style', 'class', 'width', 'summary', 'align', 'border', 'cellpadding', 'cellspacing'],
'colgroup' => array(), 'colgroup' => [],
'col' => array('style'), 'col' => ['style'],
'thead' => array('style', 'class'), 'thead' => ['style', 'class'],
'tbody' => array('style', 'class'), 'tbody' => ['style', 'class'],
'tr' => array('style', 'class', 'colspan', 'rowspan'), 'tr' => ['style', 'class', 'colspan', 'rowspan'],
'td' => array('style', 'class', 'colspan', 'rowspan'), 'td' => ['style', 'class', 'colspan', 'rowspan'],
'th' => array('style', 'class', 'colspan', 'rowspan'), 'th' => ['style', 'class', 'colspan', 'rowspan'],
'fieldset' => array('style', 'class'), 'fieldset' => ['style', 'class'],
'legend' => array('style', 'class'), 'legend' => ['style', 'class'],
'font' => array('face', 'color', 'style', 'class', 'size'), 'font' => ['face', 'color', 'style', 'class', 'size'],
'big' => array(), 'big' => [],
'small' => array(), 'small' => [],
'tt' => array(), 'tt' => [],
'kbd' => array(), 'kbd' => [],
'samp' => array(), 'samp' => [],
'var' => array(), 'var' => [],
'del' => array(), 'del' => [],
's' => array(), // strikethrough 's' => [], // strikethrough
'ins' => array(), 'ins' => [],
'cite' => array(), 'cite' => [],
'q' => array(), 'q' => [],
'hr' => array('style', 'class'), 'hr' => ['style', 'class'],
'pre' => array('class'), 'pre' => ['class'],
'center' => array(), 'center' => [],
'figure' => array('style', 'class'), // Ckeditor 5 puts images in figures 'figure' => ['style', 'class'], // Ckeditor 5 puts images in figures
'figcaption' => array('class'), 'figcaption' => ['class'],
'mark' => array('class') 'mark' => ['class'],
); ];
protected static $aAttrsWhiteList = array( protected static $aAttrsWhiteList = [
'src' => '/^(http:|https:|data:)/i', 'src' => '/^(http:|https:|data:)/i',
); ];
/** /**
* @var array * @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations * @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
*/ */
protected static $aStylesWhiteList = array( protected static $aStylesWhiteList = [
'aspect-ratio', 'aspect-ratio',
'background-color', 'background-color',
'border', 'border',
@@ -361,7 +352,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
'vertical-align', 'vertical-align',
'width', 'width',
'white-space', 'white-space',
); ];
public function __construct($sInlineImageClassName = InlineImage::class) public function __construct($sInlineImageClassName = InlineImage::class)
{ {
@@ -431,15 +422,13 @@ class HTMLDOMSanitizer extends DOMSanitizer
// Export only the content of the body tag // Export only the content of the body tag
$sCleanHtml = $this->oDoc->saveHTML($oNodesList->item(0)); $sCleanHtml = $this->oDoc->saveHTML($oNodesList->item(0));
// remove the body tag itself // remove the body tag itself
$sCleanHtml = str_replace(array('<body>', '</body>'), '', $sCleanHtml); $sCleanHtml = str_replace(['<body>', '</body>'], '', $sCleanHtml);
} }
return $sCleanHtml; return $sCleanHtml;
} }
} }
/** /**
* @since 2.6.5 2.7.6 3.0.0 N°4360 * @since 2.6.5 2.7.6 3.0.0 N°4360
*/ */

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Created by Bruno DA SILVA, working for Combodo * Created by Bruno DA SILVA, working for Combodo
* Date: 31/12/2019 * Date: 31/12/2019
@@ -13,7 +14,6 @@ use PhpParser\PrettyPrinter\Standard;
class iTopConfigParser class iTopConfigParser
{ {
/** @var \PhpParser\Node[] */ /** @var \PhpParser\Node[] */
private $aInitialNodes; private $aInitialNodes;
@@ -39,14 +39,13 @@ class iTopConfigParser
{ {
$oParser = (new ParserFactory())->createForNewestSupportedVersion(); $oParser = (new ParserFactory())->createForNewestSupportedVersion();
$this->aVarsMap = array( $this->aVarsMap = [
'MySettings' => array(), 'MySettings' => [],
'MyModuleSettings' => array(), 'MyModuleSettings' => [],
'MyModules' => array(), 'MyModules' => [],
); ];
if ($sConfig !== null) if ($sConfig !== null) {
{
$this->BrowseFile($oParser, $sConfig); $this->BrowseFile($oParser, $sConfig);
} }
} }
@@ -68,14 +67,14 @@ class iTopConfigParser
public function GetVarValue($arrayName, $key) public function GetVarValue($arrayName, $key)
{ {
if (!array_key_exists($arrayName, $this->aVarsMap)) { if (!array_key_exists($arrayName, $this->aVarsMap)) {
return array('found' => false); return ['found' => false];
} }
$arrayValue = $this->aVarsMap[$arrayName]; $arrayValue = $this->aVarsMap[$arrayName];
if (!array_key_exists($key, $arrayValue)) { if (!array_key_exists($key, $arrayValue)) {
return array('found' => false); return ['found' => false];
} }
return array('found' => true, return ['found' => true,
'value' => $arrayValue[$key]); 'value' => $arrayValue[$key]];
} }
/** /**
@@ -90,8 +89,7 @@ class iTopConfigParser
try { try {
$aNodes = $oParser->parse($sConfig); $aNodes = $oParser->parse($sConfig);
} } catch (\Error $e) {
catch (\Error $e) {
$sMessage = Dict::Format('config-parse-error', $e->getMessage(), $e->getLine()); $sMessage = Dict::Format('config-parse-error', $e->getMessage(), $e->getLine());
$this->oException = new \Exception($sMessage, 0, $e); $this->oException = new \Exception($sMessage, 0, $e);
} }

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