Compare commits

..

14 Commits

Author SHA1 Message Date
vdumas
f805c2f834 N°6203 - Add complementary name to CMDB classes 2023-05-22 18:30:33 +02:00
vdumas
976c9c1523 N°6311 - Add a Log on User Local, LDAP and External 2023-05-20 18:54:10 +02:00
vdumas
22a14a2de2 N°6323 - n:n Add filter on lnk ExtKey aligned to PrefillSearchForm 2023-05-20 17:21:10 +02:00
vdumas
bd04b2a24c N°6203 - Standard DM overcard, complementary name 2023-05-20 17:20:16 +02:00
Eric Espie
0188108a68 Add EVENT_DB_BEFORE_CREATE and EVENT_DB_BEFORE_UPDATE events in CRUD calls 2023-05-17 10:16:18 +02:00
Pierre Goiffon
4038d4d925 N°6314 N°1150 Fix cannot reopen or close a UR in the user portal
Since introduction of MultipleChoicesField and SelectObjectField value checks with b71cd218, when a portal user was trying to do an action on a resolved UR the agent_id field was rejected. The reason for the rejection is the corresponding SelectObjectField query is containing the portal user scopes (query generated in ObjectFormManager::Build), and of course the agent_id set isn't in this scope...

As a workaround we are disabling those checks for read only fields (values are set server side and possibly in a different context than the portal user)
2023-05-16 17:54:24 +02:00
acognet
ea88aa85df N°4517 - PHP 8.1 compatibility : Replace htmlentities(***, ENT_QUOTES,'UTF-8') with utils::EscapeHtml 2023-05-16 17:45:58 +02:00
Eric Espie
8f2814a590 Undo... Move event declaration where the object is defined 2023-05-16 15:59:50 +02:00
Eric Espie
ad25d8823f Add EVENT_DB_BEFORE_CREATE and EVENT_DB_BEFORE_UPDATE events in CRUD calls 2023-05-16 15:52:02 +02:00
Eric Espie
59cd489e72 N°6252 - Make designer itop 3.1 compatible - Fix deprecated calls of opendir() with null value 2023-05-16 14:06:01 +02:00
Pierre Goiffon
4b9b0a91a9 N°6307 Fix alert when caselog filled and submitting form
Regression was introduced in 8dc7d68b
Temporary fix, as the alert is caused by activity-panel.js which is disabled only if another handler is registered before 🤯 As a temporary fix I add an empty handler at the same place as the one that was there before, but we need a better way to disable activity-panel.js handler !
2023-05-16 12:14:26 +02:00
vdumas
a21def5329 N°4010 - Configuration file overwritten - fine tune messages 2023-05-16 12:06:26 +02:00
vdumas
55f8efe0db N°4010 - Configuration file overwritten - fine tune messages 2023-05-16 12:06:26 +02:00
Eric Espie
0cc28b42b2 Move EventService init to Metamodel::Startup() for unit tests 2023-05-16 10:23:01 +02:00
31 changed files with 564 additions and 240 deletions

View File

@@ -2955,6 +2955,9 @@ JS
$oPage->add_ready_script(<<<JS
// Try to release concurrent lock when leaving the page
$(window).on('unload',function() { return OnUnload('$iTransactionId', '$sClass', $iKey, $sJSToken) } );
window.onbeforeunload = function() {
// N°6307 just an empty function to disable activity-panel.js handler
};
// Leave handler for the current form (check if in a modal or not)
// Note: We use a self-invoking function to avoid making unique vars. names to avoid collision (this can be called multiple time if modal forms are displayed)
@@ -5874,6 +5877,11 @@ JS
$this->FireEvent(EVENT_DB_CHECK_TO_WRITE);
}
final protected function FireEventBeforeObjectCreate()
{
$this->FireEvent(EVENT_DB_BEFORE_CREATE);
}
/**
* @return void
* @throws \CoreException
@@ -5891,6 +5899,16 @@ JS
/// UPDATE
///
/**
* @return void
* @throws \CoreException
*/
final protected function FireEventBeforeObjectUpdate()
{
$this->FireEvent(EVENT_DB_BEFORE_UPDATE);
}
/**
* @param array $aChanges
*

View File

@@ -203,6 +203,23 @@
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_BEFORE_CREATE" _delta="define">
<description>An object is about to be created into the database. The object can be modified.</description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
<replaces>DBObject::OnInsert</replaces>
<event_data>
<event_datum id="object">
<description>The object inserted</description>
<type>DBObject</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_CREATE_DONE" _delta="define">
<description>An object has been created into the database. The modifications can be propagated to other objects.</description>
<sources>
@@ -220,6 +237,23 @@
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_BEFORE_UPDATE" _delta="define">
<description>An object is about to be updated into the database. The object can be modified.</description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
<replaces>DBObject::OnUpdate</replaces>
<event_data>
<event_datum id="object">
<description>The object updated</description>
<type>DBObject</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_UPDATE_DONE" _delta="define">
<description>An object has been updated into the database and reloaded.</description>
<sources>
@@ -490,6 +524,9 @@
</event>
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
<description>A document has been downloaded from the GUI</description>
<sources>
<source id="Document">Document</source>
</sources>
<event_data>
<event_datum id="object">
<description>The object containing the document</description>

View File

@@ -15,10 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\EventRegister\ApplicationEvents;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
require_once(APPROOT.'core/cmdbobject.class.inc.php');
require_once(APPROOT.'application/utils.inc.php');
@@ -103,6 +100,3 @@ else
}
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
EventService::InitService();
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));

View File

@@ -1305,14 +1305,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'navigation_menu.sorted_popup_user_menu_items' => [
'type' => 'array',
'description' => 'Sort user menu items after setup on page load',
'default' => [],
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'quick_create.enabled' => [
'type' => 'bool',
'description' => 'Whether or not the quick create is enabled',

View File

@@ -3066,6 +3066,8 @@ abstract class DBObject implements iDisplay
$this->DoComputeValues();
$this->OnInsert();
$this->FireEventBeforeObjectCreate();
// If not automatically computed, then check that the key is given by the caller
if (!MetaModel::IsAutoIncrementKey($sRootClass)) {
if (empty($this->m_iKey)) {
@@ -3085,7 +3087,7 @@ abstract class DBObject implements iDisplay
}
$this->ComputeStopWatchesDeadline(true);
$iTransactionRetry = 1;
$bIsTransactionEnabled = MetaModel::GetConfig()->Get('db_core_transactions_enabled');
if ($bIsTransactionEnabled) {
@@ -3276,6 +3278,8 @@ abstract class DBObject implements iDisplay
$this->ComputeStopWatchesDeadline(false);
$this->OnUpdate();
$this->FireEventBeforeObjectUpdate();
// Freeze the changes at this point
$this->InitPreviousValuesForUpdatedAttributes();
$aChanges = $this->ListChanges();
@@ -6053,6 +6057,14 @@ abstract class DBObject implements iDisplay
{
}
/**
* @return void
* @since 3.1.0
*/
protected function FireEventBeforeObjectCreate()
{
}
/**
* @return void
* @since 3.1.0
@@ -6069,6 +6081,16 @@ abstract class DBObject implements iDisplay
* @return void
* @since 3.1.0
*/
protected function FireEventBeforeObjectUpdate()
{
}
/**
* @param array $aChanges
*
* @return void
* @since 3.1.0
*/
protected function FireEventUpdateDone(array $aChanges): void
{
}
@@ -6078,6 +6100,8 @@ abstract class DBObject implements iDisplay
///
/**
* @param \DeletionPlan $oDeletionPlan
*
* @return void
* @since 3.1.0
*/

View File

@@ -17,7 +17,10 @@
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
use Combodo\iTop\Application\EventRegister\ApplicationEvents;
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
require_once APPROOT.'core/modulehandler.class.inc.php';
require_once APPROOT.'core/querymodifier.class.inc.php';
@@ -6343,36 +6346,37 @@ abstract class MetaModel
{
self::$m_sEnvironment = $sEnvironment;
if (!defined('MODULESROOT'))
{
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
try {
if (!defined('MODULESROOT')) {
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
// $config can be either a filename, or a Configuration object (volatile!)
if ($config instanceof Config)
{
self::LoadConfig($config, $bAllowCache);
}
else
{
self::LoadConfig(new Config($config), $bAllowCache);
// $config can be either a filename, or a Configuration object (volatile!)
if ($config instanceof Config) {
self::LoadConfig($config, $bAllowCache);
} else {
self::LoadConfig(new Config($config), $bAllowCache);
}
if ($bModelOnly) {
return;
}
}
if ($bModelOnly)
{
return;
CMDBSource::SelectDB(self::$m_sDBName);
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
$oPHPClass::OnMetaModelStarted();
}
ExpressionCache::Warmup();
}
finally {
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
EventService::InitService();
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
}
CMDBSource::SelectDB(self::$m_sDBName);
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMetaModelStarted();
}
ExpressionCache::Warmup();
}
/**

View File

@@ -235,15 +235,26 @@ abstract class User extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("login", array("allowed_values" => null, "sql" => "login", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql"=>"language", "default_value"=>"EN US", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values" => new ValueSetEnum('enabled,disabled'), "styled_values"=>['enabled' => new ormStyle('ibo-dm-enum--User-status-enabled', 'ibo-dm-enum-alt--User-status-enabled', 'var(--ibo-dm-enum--User-status-enabled--main-color)', 'var(--ibo-dm-enum--User-status-enabled--complementary-color)', null, null),'disabled' => new ormStyle('ibo-dm-enum--User-status-disabled', 'ibo-dm-enum-alt--User-status-disabled', 'var(--ibo-dm-enum--User-status-disabled--main-color)', 'var(--ibo-dm-enum--User-status-disabled--complementary-color)', null, null)], "sql"=>"status", "default_value"=>"enabled", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql" => "language", "default_value" => "EN US", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array(
"allowed_values" => new ValueSetEnum('enabled,disabled'),
"styled_values" => [
'enabled' => new ormStyle('ibo-dm-enum--User-status-enabled', 'ibo-dm-enum-alt--User-status-enabled', 'var(--ibo-dm-enum--User-status-enabled--main-color)', 'var(--ibo-dm-enum--User-status-enabled--complementary-color)', null, null),
'disabled' => new ormStyle('ibo-dm-enum--User-status-disabled', 'ibo-dm-enum-alt--User-status-disabled', 'var(--ibo-dm-enum--User-status-disabled--main-color)', 'var(--ibo-dm-enum--User-status-disabled--complementary-color)', null, null),
],
"sql" => "status",
"default_value" => "enabled",
"is_null_allowed" => false,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("profile_list",
array("linked_class" => "URP_UserProfile", "ext_key_to_me" => "userid", "ext_key_to_remote" => "profileid", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array(), "display_style" => 'property')));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("allowed_org_list", array("linked_class" => "URP_UserOrg", "ext_key_to_me" => "userid", "ext_key_to_remote" => "allowed_org_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeCaseLog("log", array("sql" => 'log', "is_null_allowed" => true, "default_value" => '', "allowed_values" => null, "depends_on" => array(), "always_load_in_tables" => false)));
// Display lists
MetaModel::Init_SetZListItems('details', array('contactid', 'org_id', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Unused as it's an abstract class !
MetaModel::Init_SetZListItems('details', array('contactid', 'org_id', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list', 'log')); // Unused as it's an abstract class !
MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'status', 'org_id')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'email', 'language', 'status', 'org_id')); // Criteria of the std search form
@@ -640,23 +651,23 @@ abstract class UserInternal extends User
{
$aParams = array
(
"category" => "core,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "login",
"state_attcode" => "",
"reconc_keys" => array('login'),
"db_table" => "priv_internaluser",
"db_key_field" => "id",
"category" => "core,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "login",
"state_attcode" => "",
"reconc_keys" => array('login'),
"db_table" => "priv_internaluser",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// When set, this token allows for password reset
MetaModel::Init_AddAttribute(new AttributeOneWayPassword("reset_pwd_token", array("allowed_values"=>null, "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeOneWayPassword("reset_pwd_token", array("allowed_values" => null, "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('contactid', 'org_id', 'email', 'login', 'status', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('contactid', 'org_id', 'email', 'login', 'status', 'language', 'profile_list', 'allowed_org_list', 'log')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'status', 'org_id')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status', 'org_id')); // Criteria of the std search form

View File

@@ -61,6 +61,7 @@ class UserExternal extends User
'fieldset:User:profiles' => array('profile_list'),
),
'allowed_org_list',
'log',
)
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list

View File

@@ -309,6 +309,9 @@
<item id="allowed_org_list">
<rank>80</rank>
</item>
<item id="log">
<rank>90</rank>
</item>
</items>
</details>
<search>

View File

@@ -108,6 +108,7 @@ class UserLocal extends UserInternal
'fieldset:UserLocal:password:expiration' => array('expiration', 'password_renewed_date',),
),
'allowed_org_list',
'log',
)
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'org_id')); // Attributes to be displayed for a list

View File

@@ -14,6 +14,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server.svg</icon>
@@ -269,6 +272,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -518,6 +525,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server.svg</icon>
@@ -689,6 +700,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server.svg</icon>
@@ -978,6 +993,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="networkdevicetype_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-switch.svg</icon>
@@ -1254,6 +1273,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server.svg</icon>
@@ -1557,6 +1580,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -1719,6 +1745,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -1850,6 +1879,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -2049,6 +2081,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-automatic.svg</icon>
@@ -2180,6 +2215,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-database.svg</icon>
@@ -2311,6 +2349,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server-custom.svg</icon>
@@ -2442,6 +2483,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-desktop.svg</icon>
@@ -2550,6 +2594,9 @@
<attribute id="name"/>
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-software-other.svg</icon>
@@ -2657,6 +2704,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="middleware_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-automatic.svg</icon>
@@ -2776,6 +2827,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-database-custom.svg</icon>
@@ -2893,6 +2947,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="webserver_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-web.svg</icon>
@@ -3020,6 +3078,10 @@
<attribute id="name"/>
<attribute id="version"/>
</attributes>
<complementary_attributes>
<attribute id="vendor"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-software.svg</icon>
@@ -3284,6 +3346,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="osversion_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-bandage.svg</icon>
@@ -3374,6 +3439,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="software_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-bandage.svg</icon>
@@ -3464,6 +3532,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-licence.svg</icon>
@@ -3650,6 +3721,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="osversion_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-licence.svg</icon>
@@ -3793,6 +3868,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="software_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-software-license.svg</icon>
@@ -4020,6 +4099,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="osfamily_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon/>
@@ -4208,6 +4290,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="brand_name"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<style>
<icon/>
@@ -5061,6 +5147,10 @@
<attribute id="ip"/>
<attribute id="ip_mask"/>
</attributes>
<complementary_attributes>
<attribute id="org_name"></attribute>
<attribute id="subnet_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-network.svg</icon>
@@ -5545,6 +5635,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="ipaddress"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-globe-cable.svg</icon>
@@ -6412,6 +6505,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="owner_name"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>

View File

@@ -142,6 +142,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:PhysicalDevice' => 'Physical Device',
'Class:PhysicalDevice+' => '',
'Class:PhysicalDevice/ComplementaryName' => '%1$s - %2$s',
'Class:PhysicalDevice/Attribute:serialnumber' => 'Serial number',
'Class:PhysicalDevice/Attribute:serialnumber+' => '',
'Class:PhysicalDevice/Attribute:location_id' => 'Location',
@@ -181,6 +182,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Rack' => 'Rack',
'Class:Rack+' => '',
'Class:Rack/ComplementaryName' => '%1$s - %2$s',
'Class:Rack/Attribute:nb_u' => 'Rack units',
'Class:Rack/Attribute:nb_u+' => '',
'Class:Rack/Attribute:device_list' => 'Devices',
@@ -247,6 +249,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:ConnectableCI' => 'Connectable CI',
'Class:ConnectableCI+' => 'Physical CI',
'Class:ConnectableCI/ComplementaryName' => '%1$s - %2$s',
'Class:ConnectableCI/Attribute:networkdevice_list' => 'Network devices',
'Class:ConnectableCI/Attribute:networkdevice_list+' => 'All network devices connected to this device',
'Class:ConnectableCI/Attribute:physicalinterface_list' => 'Network interfaces',
@@ -260,6 +263,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:DatacenterDevice' => 'Datacenter Device',
'Class:DatacenterDevice+' => '',
'Class:DatacenterDevice/ComplementaryName' => '%1$s - %2$s',
'Class:DatacenterDevice/Attribute:rack_id' => 'Rack',
'Class:DatacenterDevice/Attribute:rack_id+' => '',
'Class:DatacenterDevice/Attribute:rack_name' => 'Rack name',
@@ -298,6 +302,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:NetworkDevice' => 'Network Device',
'Class:NetworkDevice+' => '',
'Class:NetworkDevice/ComplementaryName' => '%1$s - %2$s',
'Class:NetworkDevice/Attribute:networkdevicetype_id' => 'Network type',
'Class:NetworkDevice/Attribute:networkdevicetype_id+' => '',
'Class:NetworkDevice/Attribute:networkdevicetype_name' => 'Network type name',
@@ -319,6 +324,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Server' => 'Server',
'Class:Server+' => '',
'Class:Server/ComplementaryName' => '%1$s - %2$s',
'Class:Server/Attribute:osfamily_id' => 'OS family',
'Class:Server/Attribute:osfamily_id+' => '',
'Class:Server/Attribute:osfamily_name' => 'OS family name',
@@ -346,6 +352,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:StorageSystem' => 'Storage System',
'Class:StorageSystem+' => '',
'Class:StorageSystem/ComplementaryName' => '%1$s - %2$s',
'Class:StorageSystem/Attribute:logicalvolume_list' => 'Logical volumes',
'Class:StorageSystem/Attribute:logicalvolume_list+' => 'All the logical volumes in this storage system',
));
@@ -357,6 +364,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:SANSwitch' => 'SAN Switch',
'Class:SANSwitch+' => '',
'Class:SANSwitch/ComplementaryName' => '%1$s - %2$s',
'Class:SANSwitch/Attribute:datacenterdevice_list' => 'Devices',
'Class:SANSwitch/Attribute:datacenterdevice_list+' => 'All the devices connected to this SAN switch',
));
@@ -368,6 +376,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:TapeLibrary' => 'Tape Library',
'Class:TapeLibrary+' => '',
'Class:TapeLibrary/ComplementaryName' => '%1$s - %2$s',
'Class:TapeLibrary/Attribute:tapes_list' => 'Tapes',
'Class:TapeLibrary/Attribute:tapes_list+' => 'All the tapes in the tape library',
));
@@ -379,6 +388,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:NAS' => 'NAS',
'Class:NAS+' => '',
'Class:NAS/ComplementaryName' => '%1$s - %2$s',
'Class:NAS/Attribute:nasfilesystem_list' => 'Filesystems',
'Class:NAS/Attribute:nasfilesystem_list+' => 'All the file systems in this NAS',
));
@@ -390,6 +400,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:PC' => 'PC',
'Class:PC+' => '',
'Class:PC/ComplementaryName' => '%1$s - %2$s',
'Class:PC/Attribute:osfamily_id' => 'OS family',
'Class:PC/Attribute:osfamily_id+' => '',
'Class:PC/Attribute:osfamily_name' => 'OS family name',
@@ -417,6 +428,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Printer' => 'Printer',
'Class:Printer+' => '',
'Class:Printer/ComplementaryName' => '%1$s - %2$s',
));
//
@@ -426,6 +438,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:PowerConnection' => 'Power Connection',
'Class:PowerConnection+' => '',
'Class:PowerConnection/ComplementaryName' => '%1$s - %2$s',
));
//
@@ -435,6 +448,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:PowerSource' => 'Power Source',
'Class:PowerSource+' => '',
'Class:PowerSource/ComplementaryName' => '%1$s - %2$s',
'Class:PowerSource/Attribute:pdus_list' => 'PDUs',
'Class:PowerSource/Attribute:pdus_list+' => 'All the PDUs using this power source',
));
@@ -446,6 +460,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:PDU' => 'PDU',
'Class:PDU+' => '',
'Class:PDU/ComplementaryName' => '%1$s - %2$s - %3$s',
'Class:PDU/Attribute:rack_id' => 'Rack',
'Class:PDU/Attribute:rack_id+' => '',
'Class:PDU/Attribute:rack_name' => 'Rack name',
@@ -463,6 +478,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Peripheral' => 'Peripheral',
'Class:Peripheral+' => '',
'Class:Peripheral/ComplementaryName' => '%1$s - %2$s',
));
//
@@ -472,6 +488,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Enclosure' => 'Enclosure',
'Class:Enclosure+' => '',
'Class:Enclosure/ComplementaryName' => '%1$s - %2$s - %3$s',
'Class:Enclosure/Attribute:rack_id' => 'Rack',
'Class:Enclosure/Attribute:rack_id+' => '',
'Class:Enclosure/Attribute:rack_name' => 'Rack name',
@@ -609,6 +626,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:MiddlewareInstance' => 'Middleware Instance',
'Class:MiddlewareInstance+' => '',
'Class:MiddlewareInstance/ComplementaryName' => '%1$s - %2$s',
'Class:MiddlewareInstance/Attribute:middleware_id' => 'Middleware',
'Class:MiddlewareInstance/Attribute:middleware_id+' => '',
'Class:MiddlewareInstance/Attribute:middleware_name' => 'Middleware name',
@@ -635,6 +653,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:WebApplication' => 'Web Application',
'Class:WebApplication+' => '',
'Class:WebApplication/ComplementaryName' => '%1$s - %2$s',
'Class:WebApplication/Attribute:webserver_id' => 'Web server',
'Class:WebApplication/Attribute:webserver_id+' => '',
'Class:WebApplication/Attribute:webserver_name' => 'Web server name',
@@ -715,6 +734,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:VirtualMachine' => 'Virtual Machine',
'Class:VirtualMachine+' => '',
'Class:VirtualMachine/ComplementaryName' => '%1$s - %2$s',
'Class:VirtualMachine/Attribute:virtualhost_id' => 'Virtual host',
'Class:VirtualMachine/Attribute:virtualhost_id+' => '',
'Class:VirtualMachine/Attribute:virtualhost_name' => 'Virtual host name',
@@ -877,6 +897,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Software' => 'Software',
'Class:Software+' => '',
'Class:Software/ComplementaryName' => '%1$s - %2$s',
'Class:Software/Attribute:name' => 'Name',
'Class:Software/Attribute:name+' => '',
'Class:Software/Attribute:vendor' => 'Vendor',
@@ -959,6 +980,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Licence' => 'License',
'Class:Licence+' => '',
'Class:Licence/Attribute:name' => 'Name',
'Class:Licence/Attribute:name+' => '',
'Class:Licence/Attribute:documents_list' => 'Documents',
@@ -994,6 +1016,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:OSLicence' => 'OS License',
'Class:OSLicence+' => '',
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'OS version',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'OS version name',
@@ -1011,6 +1034,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:SoftwareLicence' => 'Software License',
'Class:SoftwareLicence+' => '',
'Class:SoftwareLicence/ComplementaryName' => '%1$s - %2$s',
'Class:SoftwareLicence/Attribute:software_id' => 'Software',
'Class:SoftwareLicence/Attribute:software_id+' => '',
'Class:SoftwareLicence/Attribute:software_name' => 'Software name',
@@ -1079,6 +1103,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Model' => 'Model',
'Class:Model+' => '',
'Class:Model/ComplementaryName' => '%1$s - %2$s',
'Class:Model/Attribute:brand_id' => 'Brand',
'Class:Model/Attribute:brand_id+' => '',
'Class:Model/Attribute:brand_name' => 'Brand name',
@@ -1230,14 +1255,16 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Subnet' => 'Subnet',
'Class:Subnet+' => '',
'Class:Subnet/Name' => '%1$s/%2$s',
'Class:Subnet/ComplementaryName' => '%1$s - %2$s',
'Class:Subnet/Attribute:description' => 'Description',
'Class:Subnet/Attribute:description+' => '',
'Class:Subnet/Attribute:subnet_name' => 'Subnet name',
'Class:Subnet/Attribute:subnet_name+' => '',
'Class:Subnet/Attribute:org_id' => 'Owner organization',
'Class:Subnet/Attribute:org_id+' => '',
'Class:Subnet/Attribute:org_name' => 'Name',
'Class:Subnet/Attribute:org_name+' => 'Common name',
'Class:Subnet/Attribute:org_name' => 'Organization name',
'Class:Subnet/Attribute:org_name+' => '',
'Class:Subnet/Attribute:ip' => 'IP',
'Class:Subnet/Attribute:ip+' => '',
'Class:Subnet/Attribute:ip_mask' => 'IP Mask',
@@ -1260,7 +1287,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:VLAN/Attribute:org_id' => 'Organization',
'Class:VLAN/Attribute:org_id+' => '',
'Class:VLAN/Attribute:org_name' => 'Organization name',
'Class:VLAN/Attribute:org_name+' => 'Common name',
'Class:VLAN/Attribute:org_name+' => '',
'Class:VLAN/Attribute:subnets_list' => 'Subnets',
'Class:VLAN/Attribute:subnets_list+' => '',
'Class:VLAN/Attribute:physicalinterfaces_list' => 'Physical network interfaces',
@@ -1465,6 +1492,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Group' => 'Group',
'Class:Group+' => '',
'Class:Group/ComplementaryName' => '%1$s - %2$s',
'Class:Group/Attribute:name' => 'Name',
'Class:Group/Attribute:name+' => '',
'Class:Group/Attribute:status' => 'Status',

View File

@@ -37,7 +37,7 @@ Dict::Add('EN US', 'English', 'English', array(
'config-current-line' => 'Editing line: %1$s',
'config-saved-warning-db-password' => 'Successfully recorded, but the backup won\'t work due to unsupported characters in the database password.',
'config-error-transaction' => 'Error: invalid Transaction ID. The configuration was <b>NOT</b> modified.',
'config-error-file-changed' => 'Error: The configuration was changed on the server, the configuration has not been saved',
'config-error-file-changed' => 'Error: The Configuration file has changed since you opened it and cannot be saved. Refresh and apply your changes again.',
'config-not-allowed-in-demo' => 'Sorry, '.ITOP_APPLICATION_SHORT.' is in <b>demonstration mode</b>: the configuration file cannot be edited.',
'config-interactive-not-allowed' => ITOP_APPLICATION_SHORT." interactive edition of the configuration as been disabled. See <code>'config_editor' => 'disabled'</code> in the configuration file.",
));

View File

@@ -19,9 +19,9 @@ Dict::Add('FR FR', 'French', 'Français', array(
'config-reverted' => 'Vos modifications ont été écrasées par la version enregistrée.',
'config-parse-error' => 'Ligne %2$d: %1$s.<br/>Le fichier n\'a PAS été modifié.',
'config-current-line' => 'Ligne en édition : %1$s',
'config-saved-warning-db-password' => 'Configuration enregistrée. Les sauvegardes ne fonctionneront pas à cause du format du pot de passe de la base.',
'config-saved-warning-db-password' => 'Configuration enregistrée. Les sauvegardes ne fonctionneront pas à cause du format du mot de passe de la base.',
'config-error-transaction' => "Erreur : La transaction n'est plus valide. Les modifications n'ont <b>PAS</b> été enregistrées.",
'config-error-file-changed' => "Erreur : La configuration a été modifiée sur le serveur par une autre action. Les modifications n'ont <b>PAS</b> été enregistrées.",
'config-error-file-changed' => "Erreur : La configuration a été modifiée depuis que vous l\'avez ouvert. Vos modifications ne peuvent <b>PAS</b> être enregistrées. Rechargez la page et recommencez.",
'config-not-allowed-in-demo' => 'Désolé, '.ITOP_APPLICATION_SHORT.' est en <b>mode démonstration</b> : la configuration ne peut pas être modifiée.',
'config-interactive-not-allowed' => "La modification interactive de la configuration n'est pas autorisée. Voir le paramètre <code>'config_editor' => 'disabled'</code> dans le fichier de configuration.",
));

View File

@@ -14,6 +14,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-rack.svg</icon>
@@ -196,6 +200,11 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
<attribute id="rack_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-enclosure-for-servers.svg</icon>
@@ -383,6 +392,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-electrical.svg</icon>
@@ -545,6 +558,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-electricity.svg</icon>
@@ -702,6 +719,11 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
<attribute id="rack_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-plug-socket.svg</icon>

View File

@@ -14,6 +14,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-phone.svg</icon>
@@ -168,6 +172,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-telephone.svg</icon>
@@ -315,6 +323,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-mobile.svg</icon>
@@ -485,6 +497,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-office-phone.svg</icon>
@@ -632,6 +648,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-smartphone-tablet.svg</icon>
@@ -776,6 +795,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-laptop.svg</icon>
@@ -1026,6 +1049,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-print.svg</icon>
@@ -1206,6 +1233,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-electronics.svg</icon>

View File

@@ -29,6 +29,7 @@ use Dict;
use Exception;
use IssueLog;
use MetaModel;
use utils;
/**
* Contains static methods to help loading / registering classes of the application.

View File

@@ -803,9 +803,21 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="customer_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>org_id</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="contact_id" xsi:type="AttributeExternalKey">
<sql>contact_id</sql>
<target_class>Contact</target_class>
<filter><![CDATA[SELECT Contact WHERE org_id IN (:this->customer_id, :this->provider_id)]]></filter>
<dependencies>
<attribute id="contract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
@@ -896,9 +908,21 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="customer_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>org_id</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="document_id" xsi:type="AttributeExternalKey">
<sql>document_id</sql>
<target_class>Document</target_class>
<filter><![CDATA[SELECT Document WHERE org_id IN (:this->customer_id, :this->provider_id)]]></filter>
<dependencies>
<attribute id="contract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
@@ -1043,6 +1067,10 @@ public function PrefillSearchForm(&$aContextParam)
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="status"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<image_attribute>icon</image_attribute>
@@ -1234,6 +1262,16 @@ public function PrefillSearchForm(&$aContextParam)
</item>
</items>
</list>
<summary>
<items>
<item id="org_id">
<rank>10</rank>
</item>
<item id="description">
<rank>20</rank>
</item>
</items>
</summary>
</presentation>
</class>
<class id="lnkDocumentToService" _delta="define">
@@ -1435,6 +1473,10 @@ public function PrefillSearchForm(&$aContextParam)
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="service_provider"></attribute>
<attribute id="status"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -1587,6 +1629,19 @@ public function PrefillSearchForm(&$aContextParam)
</item>
</items>
</list>
<summary>
<items>
<item id="service_provider">
<rank>10</rank>
</item>
<item id="request_type">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
</items>
</summary>
</presentation>
</class>
<class id="SLA" _delta="define">
@@ -2080,9 +2135,17 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>customercontract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>customercontract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="service_id" xsi:type="AttributeExternalKey">
<sql>service_id</sql>
<target_class>Service</target_class>
<filter><![CDATA[SELECT Service WHERE org_id = :this->provider_id]]></filter>
<dependencies>
<attribute id="customercontract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>

View File

@@ -255,6 +255,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Service' => 'Service',
'Class:Service+' => '',
'Class:Service/ComplementaryName' => '%1$s - %2$s',
'Class:Service/Attribute:name' => 'Name',
'Class:Service/Attribute:name+' => '',
'Class:Service/Attribute:org_id' => 'Provider',
@@ -330,6 +331,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:ServiceSubcategory' => 'Service Subcategory',
'Class:ServiceSubcategory+' => '',
'Class:ServiceSubcategory/ComplementaryName' => '%1$s - %2$s',
'Class:ServiceSubcategory/Attribute:name' => 'Name',
'Class:ServiceSubcategory/Attribute:name+' => '',
'Class:ServiceSubcategory/Attribute:description' => 'Description',

View File

@@ -773,9 +773,21 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="customer_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>org_id</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="contact_id" xsi:type="AttributeExternalKey">
<sql>contact_id</sql>
<target_class>Contact</target_class>
<filter><![CDATA[SELECT Contact WHERE org_id IN (:this->customer_id, :this->provider_id)]]></filter>
<dependencies>
<attribute id="contract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
@@ -794,6 +806,12 @@ public function PrefillSearchForm(&$aContextParam)
<item id="contract_id">
<rank>20</rank>
</item>
<item id="customer_id">
<rank>30</rank>
</item>
<item id="provider_id">
<rank>40</rank>
</item>
</items>
</details>
<search>
@@ -866,9 +884,21 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="customer_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>org_id</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>contract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="document_id" xsi:type="AttributeExternalKey">
<sql>document_id</sql>
<target_class>Document</target_class>
<filter><![CDATA[SELECT Document WHERE org_id IN (:this->customer_id, :this->provider_id)]]></filter>
<dependencies>
<attribute id="contract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
@@ -1013,6 +1043,10 @@ public function PrefillSearchForm(&$aContextParam)
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="status"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<image_attribute>icon</image_attribute>
@@ -1228,6 +1262,16 @@ public function PrefillSearchForm(&$aContextParam)
</item>
</items>
</list>
<summary>
<items>
<item id="org_id">
<rank>10</rank>
</item>
<item id="description">
<rank>20</rank>
</item>
</items>
</summary>
</presentation>
</class>
<class id="lnkDocumentToService" _delta="define">
@@ -1429,6 +1473,10 @@ public function PrefillSearchForm(&$aContextParam)
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="service_provider"></attribute>
<attribute id="status"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -1581,6 +1629,19 @@ public function PrefillSearchForm(&$aContextParam)
</item>
</items>
</list>
<summary>
<items>
<item id="service_provider">
<rank>10</rank>
</item>
<item id="request_type">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
</items>
</summary>
</presentation>
</class>
<class id="SLA" _delta="define">
@@ -2083,9 +2144,17 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>customercontract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>customercontract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="service_id" xsi:type="AttributeExternalKey">
<sql>service_id</sql>
<target_class>Service</target_class>
<filter><![CDATA[SELECT Service WHERE org_id = :this->provider_id]]></filter>
<dependencies>
<attribute id="customercontract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
@@ -2182,16 +2251,6 @@ public function PrefillSearchForm(&$aContextParam)
</uniqueness_rules>
</properties>
<fields>
<field id="service_id" xsi:type="AttributeExternalKey">
<sql>service_id</sql>
<target_class>Service</target_class>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
<field id="service_name" xsi:type="AttributeExternalField">
<extkey_attcode>service_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="providercontract_id" xsi:type="AttributeExternalKey">
<sql>providercontract_id</sql>
<target_class>ProviderContract</target_class>
@@ -2202,6 +2261,24 @@ public function PrefillSearchForm(&$aContextParam)
<extkey_attcode>providercontract_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="provider_id" xsi:type="AttributeExternalField">
<extkey_attcode>providercontract_id</extkey_attcode>
<target_attcode>provider_id</target_attcode>
</field>
<field id="service_id" xsi:type="AttributeExternalKey">
<sql>service_id</sql>
<target_class>Service</target_class>
<filter><![CDATA[SELECT Service WHERE org_id = :this->provider_id]]></filter>
<dependencies>
<attribute id="providercontract_id"/>
</dependencies>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_AUTO</on_target_delete>
</field>
<field id="service_name" xsi:type="AttributeExternalField">
<extkey_attcode>service_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
</fields>
<methods/>
<presentation>

View File

@@ -224,6 +224,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Service' => 'Service',
'Class:Service+' => '',
'Class:Service/ComplementaryName' => '%1$s - %2$s',
'Class:Service/Attribute:name' => 'Name',
'Class:Service/Attribute:name+' => '',
'Class:Service/Attribute:org_id' => 'Provider',
@@ -303,6 +304,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:ServiceSubcategory' => 'Service Subcategory',
'Class:ServiceSubcategory+' => '',
'Class:ServiceSubcategory/ComplementaryName' => '%1$s - %2$s',
'Class:ServiceSubcategory/Attribute:name' => 'Name',
'Class:ServiceSubcategory/Attribute:name+' => '',
'Class:ServiceSubcategory/Attribute:description' => 'Description',

View File

@@ -14,6 +14,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-server-storage.svg</icon>
@@ -261,6 +265,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-switch-san.svg</icon>
@@ -504,6 +512,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-tape-library.svg</icon>
@@ -748,6 +760,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-nas.svg</icon>

View File

@@ -407,6 +407,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="email"></attribute>
<attribute id="org_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -1302,6 +1306,11 @@
<db_final_class_field>finalclass</db_final_class_field>
<naming>
<attributes/>
<complementary_attributes>
<attribute id="org_name"></attribute>
<attribute id="status"></attribute>
<attribute id="documenttype_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>

View File

@@ -119,6 +119,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Contact' => 'Contact',
'Class:Contact+' => '',
'Class:Contact/ComplementaryName' => '%1$s - %2$s',
'Class:Contact/Attribute:name' => 'Name',
'Class:Contact/Attribute:name+' => '',
'Class:Contact/Attribute:status' => 'Status',
@@ -211,6 +212,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Document' => 'Document',
'Class:Document+' => '',
'Class:Document/ComplementaryName' => '%1$s - %2$s - %3$s',
'Class:Document/Attribute:name' => 'Name',
'Class:Document/Attribute:name+' => '',
'Class:Document/Attribute:org_id' => 'Organization',

View File

@@ -14,6 +14,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
<state_attribute>status</state_attribute>
@@ -153,6 +156,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon/>
@@ -275,6 +281,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-hypervisor.svg</icon>
@@ -418,6 +427,9 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-farm.svg</icon>
@@ -541,6 +553,10 @@
<attributes>
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"></attribute>
<attribute id="virtualhost_name"></attribute>
</complementary_attributes>
</naming>
<style>
<icon>../../images/icons/icons8-virtual-machine.svg</icon>

View File

@@ -176,6 +176,10 @@ class MFModule
$this->sAutoSelect = 'false';
$this->aFilesToInclude = array('addons' => array(), 'business' => array(), 'webservices' => array(),);
if (is_null($sRootDir)) {
return;
}
// Scan the module's root directory to find the datamodel(*).xml files
if ($hDir = opendir($sRootDir))
{

View File

@@ -21,14 +21,13 @@ namespace Combodo\iTop\Application\UI\Base\Component\PopoverMenu;
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItem;
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItemFactory;
use Dict;
use iPopupMenuExtension;
use JSPopupMenuItem;
use MetaModel;
use SeparatorPopupMenuItem;
use URLPopupMenuItem;
use iPopupMenuExtension;
use UserRights;
use utils;
@@ -57,69 +56,31 @@ class PopoverMenuFactory
->SetHorizontalPosition(PopoverMenu::ENUM_HORIZONTAL_POSITION_ALIGN_OUTER_RIGHT)
->SetVerticalPosition(PopoverMenu::ENUM_VERTICAL_POSITION_ABOVE);
$aUserMenuItems = [];
// Allowed portals
$aAllowedPortalsItems = static::PrepareAllowedPortalsItemsForUserMenu();
self::AddPopoverMenuItems($aAllowedPortalsItems, $aUserMenuItems);
if (!empty($aAllowedPortalsItems)) {
$oMenu->AddSection('allowed_portals')
->SetItems('allowed_portals', $aAllowedPortalsItems);
}
// User related pages
self::AddPopoverMenuItems(static::PrepareUserRelatedItemsForUserMenu(), $aUserMenuItems);
$oMenu->AddSection('user_related')
->SetItems('user_related', static::PrepareUserRelatedItemsForUserMenu());
// API: iPopupMenuExtension::MENU_USER_ACTIONS
$aAPIItems = static::PrepareAPIItemsForUserMenu($oMenu);
self::AddPopoverMenuItems($aAPIItems, $aUserMenuItems);
if (count($aAPIItems) > 0) {
$oMenu->AddSection('popup_menu_extension-menu_user_actions')
->SetItems('popup_menu_extension-menu_user_actions', $aAPIItems);
}
// Misc links
/*$oMenu->AddSection('misc')
->SetItems('misc', static::PrepareMiscItemsForUserMenu());*/
self::AddPopoverMenuItems(static::PrepareMiscItemsForUserMenu(), $aUserMenuItems);
self::SortPopoverMenuItems($aUserMenuItems);
$oMenu->AddSection('misc')
->AddItems('misc', $aUserMenuItems);
->SetItems('misc', static::PrepareMiscItemsForUserMenu());
return $oMenu;
}
/**
* @param PopoverMenuItem[] $aPopoverMenuItem
* @param PopoverMenuItem[] $aUserMenuItems
*
* @return void
*/
private static function AddPopoverMenuItems(array $aPopoverMenuItem, array &$aUserMenuItems) : void {
foreach ($aPopoverMenuItem as $oPopoverMenuItem){
$aUserMenuItems[$oPopoverMenuItem->GetUID()] = $oPopoverMenuItem;
}
}
/**
* @param PopoverMenuItem[] $aPopoverMenuItem
* @param PopoverMenuItem[] $aUserMenuItems
*
* @return void
*/
private static function SortPopoverMenuItems(array &$aUserMenuItems) : void {
$aSortedMenusFromConfig = MetaModel::GetConfig()->Get('navigation_menu.sorted_popup_user_menu_items');
if (!is_array($aSortedMenusFromConfig) || empty($aSortedMenusFromConfig)){
return;
}
$aSortedMenus = [];
foreach ($aSortedMenusFromConfig as $sMenuUID){
if (array_key_exists($sMenuUID, $aUserMenuItems)){
$aSortedMenus[]=$aUserMenuItems[$sMenuUID];
unset($aUserMenuItems[$sMenuUID]);
}
}
foreach ($aUserMenuItems as $oMenu){
$aSortedMenus[]=$oMenu;
}
$aUserMenuItems = $aSortedMenus;
}
/**
* Return the allowed portals items for the current user
*
@@ -312,4 +273,4 @@ class PopoverMenuFactory
return $oMenu;
}
}
}

View File

@@ -218,14 +218,16 @@ abstract class MultipleChoicesField extends Field
$this->SetValid(true);
$this->EmptyErrorMessages();
if (count($this->currentValue) > 0) {
foreach ($this->currentValue as $sCode => $value) {
if (utils::IsNullOrEmptyString($value)) {
continue;
}
if (false === array_key_exists($value, $this->aChoices)) {
$this->SetValid(false);
$this->AddErrorMessage("Value ({$value}) is not part of the field possible values list");
if ($this->GetReadOnly() === false) {
if (count($this->currentValue) > 0) {
foreach ($this->currentValue as $sCode => $value) {
if (utils::IsNullOrEmptyString($value)) {
continue;
}
if (false === array_key_exists($value, $this->aChoices)) {
$this->SetValid(false);
$this->AddErrorMessage("Value ({$value}) is not part of the field possible values list");
}
}
}
}

View File

@@ -250,22 +250,24 @@ class SelectObjectField extends Field
}
public function Validate() {
$sCurrentValueForExtKey = $this->currentValue;
if (utils::IsNotNullOrEmptyString($sCurrentValueForExtKey) && ($sCurrentValueForExtKey !== 0)) {
$oSearchForExistingCurrentValue = $this->oSearch->DeepClone();
$oSearchForExistingCurrentValue->AddCondition('id', $sCurrentValueForExtKey, '=');
$oCheckIdAgainstCurrentValueExpression = new BinaryExpression(
new FieldExpression('id', $oSearchForExistingCurrentValue->GetClassAlias()), '=', new ScalarExpression($sCurrentValueForExtKey)
);
$oSearchForExistingCurrentValue->AddConditionExpression($oCheckIdAgainstCurrentValueExpression);
$oSetForExistingCurrentValue = new DBObjectSet($oSearchForExistingCurrentValue);
$iObjectsCount = $oSetForExistingCurrentValue->CountWithLimit(1);
if ($this->GetReadOnly() === false) {
$sCurrentValueForExtKey = $this->currentValue;
if (utils::IsNotNullOrEmptyString($sCurrentValueForExtKey) && ($sCurrentValueForExtKey !== 0)) {
$oSearchForExistingCurrentValue = $this->oSearch->DeepClone();
$oSearchForExistingCurrentValue->AddCondition('id', $sCurrentValueForExtKey, '=');
$oCheckIdAgainstCurrentValueExpression = new BinaryExpression(
new FieldExpression('id', $oSearchForExistingCurrentValue->GetClassAlias()), '=', new ScalarExpression($sCurrentValueForExtKey)
);
$oSearchForExistingCurrentValue->AddConditionExpression($oCheckIdAgainstCurrentValueExpression);
$oSetForExistingCurrentValue = new DBObjectSet($oSearchForExistingCurrentValue);
$iObjectsCount = $oSetForExistingCurrentValue->CountWithLimit(1);
if ($iObjectsCount === 0) {
$this->SetValid(false);
$this->AddErrorMessage("Value $sCurrentValueForExtKey does not match the corresponding filter set");
if ($iObjectsCount === 0) {
$this->SetValid(false);
$this->AddErrorMessage("Value $sCurrentValueForExtKey does not match the corresponding filter set");
return $this->GetValid();
return $this->GetValid();
}
}
}

View File

@@ -340,7 +340,7 @@ final class EventService
foreach (self::$aEventDescriptions as $sEvent => $aEventInfo) {
if (is_array($aEventInfo['description']->GetEventSources())) {
foreach ($aEventInfo['description']->GetEventSources() as $sSource) {
if (\MetaModel::IsValidClass($sSource) && ($sClass == $sSource || $oClass->isSubclassOf($sSource))) {
if (class_exists($sSource) && ($sClass == $sSource || $oClass->isSubclassOf($sSource))) {
$aRes[$sEvent] = $aEventInfo;
}
}

View File

@@ -1,96 +0,0 @@
<?php
namespace UI\Base\Component\PopoverMenu;
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuFactory;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
/**
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
* @backupGlobals disabled
*/
class PopoverMenuFactoryTest extends ItopDataTestCase {
public function MakeUserMenuForNavigationMenuProvider(){
$aNotSortedMenuUIDs = [
'portal_itop_portal',
'UI_Preferences',
'UI_Help',
'UI_AboutBox'
];
return [
'no conf' => [
'aConf' => null,
'aExpectedMenuUIDs' => $aNotSortedMenuUIDs
],
'not an array conf' => [
'aConf' => "wrong conf",
'aExpectedMenuUIDs' => $aNotSortedMenuUIDs
],
'default conf' => [
'aConf' => [],
'aExpectedMenuUIDs' => $aNotSortedMenuUIDs
],
'same order in conf' => [
'aConf' => [
'portal:itop-portal',
'UI:Preferences',
'UI:Help',
'UI:AboutBox',
],
'aExpectedMenuUIDs' => $aNotSortedMenuUIDs
],
'first menus sorted and last one missing in conf' => [
'aConf' => [
"portal:itop-portal",
"UI:Preferences",
],
'aExpectedMenuUIDs' => $aNotSortedMenuUIDs
],
'some menus but not all sorted' => [
'aConf' => [
'UI:Preferences',
'UI:AboutBox',
],
'aExpectedMenuUIDs' => [
'UI_Preferences',
'UI_AboutBox',
'portal_itop_portal',
'UI_Help',
]
],
'all user menu sorted' => [
'aConf' => [
'UI:Preferences',
'UI:AboutBox',
'portal:itop-portal',
'UI:Help',
],
'aExpectedMenuUIDs' => [
'UI_Preferences',
'UI_AboutBox',
'portal_itop_portal',
'UI_Help',
]
],
];
}
/**
* @dataProvider MakeUserMenuForNavigationMenuProvider
*/
public function testMakeUserMenuForNavigationMenu($aConf, $aExpectedMenuUIDs){
if (! is_null($aConf)){
\MetaModel::GetConfig()->Set('navigation_menu.sorted_popup_user_menu_items', $aConf);
}
$aRes = PopoverMenuFactory::MakeUserMenuForNavigationMenu()->GetSections();
$this->assertTrue(array_key_exists('misc', $aRes));
$aUIDsWithDummyRandoString = array_keys($aRes['misc']['aItems']);
//replace ibo-popover-menu--item-6464cdca5ecf4214716943--UI_AboutBox by UI_AboutBox (for ex)
$aUIDs = preg_replace('/ibo-popover-menu--item-([^\-]+)--/', '', $aUIDsWithDummyRandoString);
$this->assertEquals($aExpectedMenuUIDs, $aUIDs);
}
}