Compare commits

...

926 Commits

Author SHA1 Message Date
Anne-Cath
8fc5dadad9 WIP 2025-09-08 16:13:17 +02:00
Anne-Cath
036a5d623b WIP 2025-09-08 16:10:52 +02:00
Anne-Cath
e8e8828f66 WIP 2025-09-08 16:03:52 +02:00
Anne-Cath
bbdef6b730 WIP 2025-09-08 15:56:15 +02:00
Anne-Cath
dd2f6e7413 WIP 2025-09-08 15:21:34 +02:00
Anne-Cath
ab4993debe WIP 2025-09-08 15:10:56 +02:00
Anne-Cath
455ce42a2f composer 2025-09-04 11:30:54 +02:00
Anne-Cath
f4ebbfe8ea move file 2025-09-04 11:25:44 +02:00
Anne-Cath
8d9069728a Rename file 2025-09-04 11:22:41 +02:00
Anne-Cath
80c699c56a move file 2025-09-04 11:22:30 +02:00
Anne-Cath
e923c0fef3 move file 2025-09-04 11:21:24 +02:00
Anne-Cath
70fd8ed128 Rename file 2025-09-04 11:20:14 +02:00
anne-catherine
196ceba1bb Merge branch 'split-file_counter.class.inc.php' into feature/2535-split_file 2025-09-04 09:12:58 +00:00
Potherca-Bot
7d82057e66 Merge branch 'split-file_counter.class.inc.php_KeyValueStore.php' into split-file_counter.class.inc.php 2025-09-04 09:10:58 +00:00
Potherca-Bot
fc9abc95cb Merge branch 'split-file_counter.class.inc.php_ItopCounter.php' into split-file_counter.class.inc.php 2025-09-04 09:10:57 +00:00
Potherca-Bot
ddff020a1d Changes content in separated file 'KeyValueStore.php'. 2025-09-04 09:10:57 +00:00
Potherca-Bot
b803db38b9 Changes content in separated file 'ItopCounter.php'. 2025-09-04 09:10:57 +00:00
Potherca-Bot
010edf1407 Adds separate file for 'KeyValueStore.php'. 2025-09-04 09:10:57 +00:00
Potherca-Bot
0006491304 Adds separate file for 'ItopCounter.php'. 2025-09-04 09:10:57 +00:00
anne-catherine
e0674fb797 end merge 2025-09-04 07:53:12 +00:00
Anne-Cath
f4fbbf3a4f Rename folder 2025-09-04 09:44:43 +02:00
Anne-Cath
392957d849 Move folder 2025-09-04 09:40:39 +02:00
Anne-Cath
71604e65d2 Rename folder 2025-09-04 09:38:12 +02:00
Anne-Cath
648692409b Move folder 2025-09-04 09:35:39 +02:00
Anne-Cath
950f283e9b Rename file 2025-09-04 09:29:46 +02:00
Anne-Cath
10e2679887 WIP 2025-09-04 09:28:59 +02:00
anne-catherine
8e789d51ce end merge 2025-09-03 09:18:40 +00:00
Anne-Cath
7ed43c3e50 N°6932 - Split files 2025-09-03 11:16:06 +02:00
Potherca-Bot
90fc39c409 Merge branch 'split-file_relationgraph.class.inc.php_RelationRedundancyNode.php' into split-file_relationgraph.class.inc.php 2025-09-03 09:12:57 +00:00
Potherca-Bot
88a0678149 Merge branch 'split-file_relationgraph.class.inc.php_RelationObjectNode.php' into split-file_relationgraph.class.inc.php 2025-09-03 09:12:57 +00:00
Potherca-Bot
1f7d9c0d0f Merge branch 'split-file_relationgraph.class.inc.php_RelationEdge.php' into split-file_relationgraph.class.inc.php 2025-09-03 09:12:57 +00:00
Potherca-Bot
e4c025a7f6 Changes content in separated file 'RelationRedundancyNode.php'. 2025-09-03 09:12:56 +00:00
Potherca-Bot
f9d1475147 Changes content in separated file 'RelationObjectNode.php'. 2025-09-03 09:12:56 +00:00
Potherca-Bot
be173eaf1b Adds separate file for 'RelationRedundancyNode.php'. 2025-09-03 09:12:56 +00:00
Potherca-Bot
b7e69c65a8 Adds separate file for 'RelationObjectNode.php'. 2025-09-03 09:12:56 +00:00
Potherca-Bot
980cecccad Changes content in separated file 'RelationEdge.php'. 2025-09-03 09:12:55 +00:00
Potherca-Bot
e2115e61df Adds separate file for 'RelationEdge.php'. 2025-09-03 09:12:55 +00:00
anne-catherine
e013c28d67 Merge branch 'split-file_bulkexport.class.inc.php' into feature/2535-split_file 2025-09-03 09:02:36 +00:00
Potherca-Bot
f7d37b7ee1 Merge branch 'split-file_bulkexport.class.inc.php_BulkExportResult.php' into split-file_bulkexport.class.inc.php 2025-09-03 09:01:49 +00:00
Potherca-Bot
a2b1b77798 Merge branch 'split-file_bulkexport.class.inc.php_BulkExportResultGC.php' into split-file_bulkexport.class.inc.php 2025-09-03 09:01:49 +00:00
Potherca-Bot
aa048b65f3 Merge branch 'split-file_bulkexport.class.inc.php_BulkExport.php' into split-file_bulkexport.class.inc.php 2025-09-03 09:01:49 +00:00
Potherca-Bot
c1e915188a Changes content in separated file 'BulkExportResult.php'. 2025-09-03 09:01:48 +00:00
Potherca-Bot
4b374c7e9e Merge branch 'split-file_bulkexport.class.inc.php_BulkExportMissingParameterException.php' into split-file_bulkexport.class.inc.php 2025-09-03 09:01:48 +00:00
Potherca-Bot
554fec71f0 Merge branch 'split-file_bulkexport.class.inc.php_BulkExportException.php' into split-file_bulkexport.class.inc.php 2025-09-03 09:01:48 +00:00
Potherca-Bot
c4385c1627 Changes content in separated file 'BulkExportResultGC.php'. 2025-09-03 09:01:47 +00:00
Potherca-Bot
2cf62dc72e Changes content in separated file 'BulkExport.php'. 2025-09-03 09:01:47 +00:00
Potherca-Bot
ecf4658d2c Adds separate file for 'BulkExportResult.php'. 2025-09-03 09:01:47 +00:00
Potherca-Bot
26826197ce Adds separate file for 'BulkExportResultGC.php'. 2025-09-03 09:01:47 +00:00
Potherca-Bot
f52bfddc58 Adds separate file for 'BulkExport.php'. 2025-09-03 09:01:47 +00:00
Potherca-Bot
540ff50ce1 Changes content in separated file 'BulkExportMissingParameterException.php'. 2025-09-03 09:01:46 +00:00
Potherca-Bot
fa41afccc8 Changes content in separated file 'BulkExportException.php'. 2025-09-03 09:01:46 +00:00
Potherca-Bot
31db7201c6 Adds separate file for 'BulkExportMissingParameterException.php'. 2025-09-03 09:01:46 +00:00
Potherca-Bot
4375e4085c Adds separate file for 'BulkExportException.php'. 2025-09-03 09:01:45 +00:00
anne-catherine
fbfbc78e2d Merge branch 'split-file_cmdbchangeop.class.inc.php' into feature/2535-split_file 2025-09-02 22:31:02 +00:00
Potherca-Bot
6746136db3 Merge branch 'split-file_cmdbchangeop.class.inc.php_iCMDBChangeOp.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:27 +00:00
Potherca-Bot
ccb60a2d41 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeURL.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:27 +00:00
Potherca-Bot
b799a38ec4 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeText.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:27 +00:00
Potherca-Bot
ff3da21f36 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeTagSet.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:27 +00:00
Potherca-Bot
2ee4595952 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeScalar.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
40a1ca98e1 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttribute.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
ab28f59a19 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeOneWayPassword.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
4a6804d084 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeLongText.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
1e4cf8931b Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeLinksTune.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
3c2a4c880b Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeLinks.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:26 +00:00
Potherca-Bot
28ddfe763c Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeLinksAddRemove.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
ad814df467 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeHTML.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
bcc42a09e3 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeEncrypted.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
e655e80157 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeCustomFields.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
1098e68bd0 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeCaseLog.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
b48e3e8bc5 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpSetAttributeBlob.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:25 +00:00
Potherca-Bot
346b105054 Changes content in separated file 'iCMDBChangeOp.php'. 2025-09-02 22:28:24 +00:00
Potherca-Bot
14095baf67 Changes content in separated file 'CMDBChangeOpSetAttributeURL.php'. 2025-09-02 22:28:24 +00:00
Potherca-Bot
199e02aa43 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpPlugin.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:24 +00:00
Potherca-Bot
30ff03bce0 Adds separate file for 'iCMDBChangeOp.php'. 2025-09-02 22:28:24 +00:00
Potherca-Bot
a4d1218707 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOp.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:24 +00:00
Potherca-Bot
b0bf38f0a4 Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpDelete.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:24 +00:00
Potherca-Bot
ec72dc9cff Merge branch 'split-file_cmdbchangeop.class.inc.php_CMDBChangeOpCreate.php' into split-file_cmdbchangeop.class.inc.php 2025-09-02 22:28:24 +00:00
Potherca-Bot
ea9c458c9f Changes content in separated file 'CMDBChangeOpSetAttributeText.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
500ae157b3 Changes content in separated file 'CMDBChangeOpSetAttributeTagSet.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
5de3a5331b Changes content in separated file 'CMDBChangeOpSetAttributeScalar.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
fddf54b863 Adds separate file for 'CMDBChangeOpSetAttributeURL.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
9fba36ae29 Adds separate file for 'CMDBChangeOpSetAttributeText.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
d2ca1d59a6 Adds separate file for 'CMDBChangeOpSetAttributeTagSet.php'. 2025-09-02 22:28:23 +00:00
Potherca-Bot
714079df9f Changes content in separated file 'CMDBChangeOpSetAttribute.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
b18733ac31 Changes content in separated file 'CMDBChangeOpSetAttributeOneWayPassword.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
32ce6ac336 Changes content in separated file 'CMDBChangeOpSetAttributeLongText.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
36de69b3d0 Adds separate file for 'CMDBChangeOpSetAttributeScalar.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
17b05efbba Adds separate file for 'CMDBChangeOpSetAttribute.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
079cceb48b Adds separate file for 'CMDBChangeOpSetAttributeOneWayPassword.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
0c5e032d9a Adds separate file for 'CMDBChangeOpSetAttributeLongText.php'. 2025-09-02 22:28:22 +00:00
Potherca-Bot
407b41155c Changes content in separated file 'CMDBChangeOpSetAttributeLinksTune.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
c2479757f4 Changes content in separated file 'CMDBChangeOpSetAttributeLinks.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
2d27794f85 Changes content in separated file 'CMDBChangeOpSetAttributeLinksAddRemove.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
47f0302967 Adds separate file for 'CMDBChangeOpSetAttributeLinksTune.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
d9f49a7958 Adds separate file for 'CMDBChangeOpSetAttributeLinks.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
8da798be3b Adds separate file for 'CMDBChangeOpSetAttributeLinksAddRemove.php'. 2025-09-02 22:28:21 +00:00
Potherca-Bot
e49b3c7366 Changes content in separated file 'CMDBChangeOpSetAttributeHTML.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
d54abbe401 Changes content in separated file 'CMDBChangeOpSetAttributeEncrypted.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
23a84b7864 Changes content in separated file 'CMDBChangeOpSetAttributeCustomFields.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
5836b2a403 Changes content in separated file 'CMDBChangeOpSetAttributeCaseLog.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
50feffe40f Adds separate file for 'CMDBChangeOpSetAttributeHTML.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
c9682227b8 Adds separate file for 'CMDBChangeOpSetAttributeEncrypted.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
b7f0915e2f Adds separate file for 'CMDBChangeOpSetAttributeCustomFields.php'. 2025-09-02 22:28:20 +00:00
Potherca-Bot
de93208fde Changes content in separated file 'CMDBChangeOpSetAttributeBlob.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
e07e435f65 Changes content in separated file 'CMDBChangeOpPlugin.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
d8876eef24 Changes content in separated file 'CMDBChangeOp.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
e05b519215 Adds separate file for 'CMDBChangeOpSetAttributeCaseLog.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
67e288fbc8 Adds separate file for 'CMDBChangeOpSetAttributeBlob.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
621b71f672 Adds separate file for 'CMDBChangeOpPlugin.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
4adefa5cd8 Adds separate file for 'CMDBChangeOp.php'. 2025-09-02 22:28:19 +00:00
Potherca-Bot
4993240c19 Changes content in separated file 'CMDBChangeOpDelete.php'. 2025-09-02 22:28:18 +00:00
Potherca-Bot
c21169d6a7 Changes content in separated file 'CMDBChangeOpCreate.php'. 2025-09-02 22:28:18 +00:00
Potherca-Bot
af78129b7d Adds separate file for 'CMDBChangeOpDelete.php'. 2025-09-02 22:28:18 +00:00
Potherca-Bot
3175734b4f Adds separate file for 'CMDBChangeOpCreate.php'. 2025-09-02 22:28:18 +00:00
anne-catherine
a27a4d9f64 Merge branch 'split-file_simplecrypt.class.inc.php' into feature/2535-split_file 2025-09-02 21:02:57 +00:00
Potherca-Bot
132876fc57 Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCryptSodiumEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:35 +00:00
Potherca-Bot
a454e9cb84 Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCryptSimpleEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:35 +00:00
Potherca-Bot
7e6389eac2 Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCrypt.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:34 +00:00
Potherca-Bot
4b86b1680b Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCryptOpenSSLMcryptCompatibilityEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:34 +00:00
Potherca-Bot
1d6d58384c Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCryptOpenSSLEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:34 +00:00
Potherca-Bot
f1f2a74394 Merge branch 'split-file_simplecrypt.class.inc.php_SimpleCryptMcryptEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:34 +00:00
Potherca-Bot
bf575889cc Merge branch 'split-file_simplecrypt.class.inc.php_CryptEngine.php' into split-file_simplecrypt.class.inc.php 2025-09-02 18:15:34 +00:00
Potherca-Bot
43a9fee52b Changes content in separated file 'SimpleCryptSodiumEngine.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
fd1a457ac3 Changes content in separated file 'SimpleCryptSimpleEngine.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
afd8c487c4 Changes content in separated file 'SimpleCrypt.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
41b92e2d3d Changes content in separated file 'SimpleCryptOpenSSLMcryptCompatibilityEngine.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
b12d185376 Adds separate file for 'SimpleCryptSodiumEngine.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
eaac1c293e Adds separate file for 'SimpleCryptSimpleEngine.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
f7a97bd590 Adds separate file for 'SimpleCrypt.php'. 2025-09-02 18:15:33 +00:00
Potherca-Bot
29136c269a Changes content in separated file 'SimpleCryptOpenSSLEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
1db8aa811e Changes content in separated file 'SimpleCryptMcryptEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
d44d538faf Changes content in separated file 'CryptEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
8f5cb404c4 Adds separate file for 'SimpleCryptOpenSSLMcryptCompatibilityEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
caef7a244e Adds separate file for 'SimpleCryptOpenSSLEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
bd514f7a9a Adds separate file for 'SimpleCryptMcryptEngine.php'. 2025-09-02 18:15:32 +00:00
Potherca-Bot
212b98724b Adds separate file for 'CryptEngine.php'. 2025-09-02 18:15:31 +00:00
anne-catherine
afcbc8ce40 Merge branch 'split-file_trigger.class.inc.php' into feature/2535-split_file 2025-09-02 18:02:45 +00:00
Potherca-Bot
df68d2a8da Merge branch 'split-file_trigger.class.inc.php_Trigger.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
6870d4f4db Merge branch 'split-file_trigger.class.inc.php_TriggerOnThresholdReached.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
7553ee2510 Merge branch 'split-file_trigger.class.inc.php_TriggerOnStateLeave.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
1a999b1a1c Merge branch 'split-file_trigger.class.inc.php_TriggerOnStateEnter.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
182ae5d3aa Merge branch 'split-file_trigger.class.inc.php_TriggerOnStateChange.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
4edaacc2f5 Merge branch 'split-file_trigger.class.inc.php_TriggerOnPortalUpdate.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:48 +00:00
Potherca-Bot
c98a11623e Merge branch 'split-file_trigger.class.inc.php_TriggerOnObjectUpdate.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
9feb15f5f6 Merge branch 'split-file_trigger.class.inc.php_TriggerOnObject.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
a7941c932b Merge branch 'split-file_trigger.class.inc.php_TriggerOnObjectMention.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
4cfc2a1b26 Merge branch 'split-file_trigger.class.inc.php_TriggerOnObjectDelete.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
7db88f256f Merge branch 'split-file_trigger.class.inc.php_TriggerOnObjectCreate.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
0066b24e8f Merge branch 'split-file_trigger.class.inc.php_TriggerOnAttributeBlobDownload.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:47 +00:00
Potherca-Bot
1b96f5b071 Changes content in separated file 'Trigger.php'. 2025-09-02 18:00:46 +00:00
Potherca-Bot
4b2ae38173 Changes content in separated file 'TriggerOnThresholdReached.php'. 2025-09-02 18:00:46 +00:00
Potherca-Bot
a13e2b0b00 Changes content in separated file 'TriggerOnStateLeave.php'. 2025-09-02 18:00:46 +00:00
Potherca-Bot
8f09b8149b Merge branch 'split-file_trigger.class.inc.php_lnkTriggerAction.php' into split-file_trigger.class.inc.php 2025-09-02 18:00:46 +00:00
Potherca-Bot
ff69719b8e Adds separate file for 'Trigger.php'. 2025-09-02 18:00:46 +00:00
Potherca-Bot
9c35d9edc2 Adds separate file for 'TriggerOnThresholdReached.php'. 2025-09-02 18:00:46 +00:00
Potherca-Bot
f9f75f9117 Changes content in separated file 'TriggerOnStateEnter.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
48e3d7f67f Changes content in separated file 'TriggerOnStateChange.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
0246951cf8 Changes content in separated file 'TriggerOnPortalUpdate.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
fbd76e6969 Adds separate file for 'TriggerOnStateLeave.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
559fe0be01 Adds separate file for 'TriggerOnStateEnter.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
e6a8238924 Adds separate file for 'TriggerOnStateChange.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
496f548aea Adds separate file for 'TriggerOnPortalUpdate.php'. 2025-09-02 18:00:45 +00:00
Potherca-Bot
4a2e37fa84 Changes content in separated file 'TriggerOnObjectUpdate.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
315f275a6d Changes content in separated file 'TriggerOnObject.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
d6118d5a96 Changes content in separated file 'TriggerOnObjectMention.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
572793b7b8 Adds separate file for 'TriggerOnObjectUpdate.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
391ec877c8 Adds separate file for 'TriggerOnObject.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
4151aa5ac1 Adds separate file for 'TriggerOnObjectMention.php'. 2025-09-02 18:00:44 +00:00
Potherca-Bot
c36939cf85 Changes content in separated file 'TriggerOnObjectDelete.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
3b0897fd9c Changes content in separated file 'TriggerOnObjectCreate.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
a11c87c6c2 Changes content in separated file 'TriggerOnAttributeBlobDownload.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
0a2492228b Adds separate file for 'TriggerOnObjectDelete.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
36a1dbd34d Adds separate file for 'TriggerOnObjectCreate.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
fc988d1eb0 Adds separate file for 'TriggerOnAttributeBlobDownload.php'. 2025-09-02 18:00:43 +00:00
Potherca-Bot
8d0f685fad Changes content in separated file 'lnkTriggerAction.php'. 2025-09-02 18:00:42 +00:00
Potherca-Bot
9974d59f15 Adds separate file for 'lnkTriggerAction.php'. 2025-09-02 18:00:42 +00:00
Anne-Cath
47aee14362 Move to sources Core BulkChange 2025-09-02 18:49:32 +02:00
anne-catherine
a31e3450bf Merge branch 'split-file_bulkchange.class.inc.php' into feature/2535-split_file 2025-09-02 16:46:15 +00:00
Potherca-Bot
c931e3f18a Merge branch 'split-file_bulkchange.class.inc.php_RowStatus.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:23 +00:00
Potherca-Bot
185e03d8e8 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_NoChange.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:23 +00:00
Potherca-Bot
e8f0542f11 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_NewObj.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:22 +00:00
Potherca-Bot
69fa0f71d0 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_Modify.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:22 +00:00
Potherca-Bot
03e8e77596 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_Issue.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:22 +00:00
Potherca-Bot
c67bf66bd9 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_Error.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:21 +00:00
Potherca-Bot
3c23b04608 Merge branch 'split-file_bulkchange.class.inc.php_RowStatus_Disappeared.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:21 +00:00
Potherca-Bot
0891272aa3 Merge branch 'split-file_bulkchange.class.inc.php_ReportValue.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:21 +00:00
Potherca-Bot
c6c3f7b421 Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_Void.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:21 +00:00
Potherca-Bot
5f3aa0d083 Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_SearchIssue.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:20 +00:00
Potherca-Bot
046ce13073 Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_NullIssue.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:20 +00:00
Potherca-Bot
a64ab695ce Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_Modify.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:20 +00:00
Potherca-Bot
020e58b112 Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_Issue.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:20 +00:00
Potherca-Bot
c372707124 Merge branch 'split-file_bulkchange.class.inc.php_CellStatus_Ambiguous.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:20 +00:00
Potherca-Bot
6a462d25e0 Changes content in separated file 'RowStatus.php'. 2025-09-02 16:42:19 +00:00
Potherca-Bot
288ffd1830 Merge branch 'split-file_bulkchange.class.inc.php_CellChangeSpec.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:19 +00:00
Potherca-Bot
02c3ca4724 Merge branch 'split-file_bulkchange.class.inc.php_BulkChange.php' into split-file_bulkchange.class.inc.php 2025-09-02 16:42:19 +00:00
Potherca-Bot
5b5ab86862 Changes content in separated file 'RowStatus_NoChange.php'. 2025-09-02 16:42:18 +00:00
Potherca-Bot
62122b0ee6 Changes content in separated file 'RowStatus_NewObj.php'. 2025-09-02 16:42:18 +00:00
Potherca-Bot
7aaa4a2b0d Adds separate file for 'RowStatus.php'. 2025-09-02 16:42:18 +00:00
Potherca-Bot
786651b35c Adds separate file for 'RowStatus_NoChange.php'. 2025-09-02 16:42:18 +00:00
Potherca-Bot
30b793eed8 Changes content in separated file 'RowStatus_Modify.php'. 2025-09-02 16:42:17 +00:00
Potherca-Bot
3f3d9b3d2e Changes content in separated file 'RowStatus_Issue.php'. 2025-09-02 16:42:17 +00:00
Potherca-Bot
dc3c6ea6ce Adds separate file for 'RowStatus_NewObj.php'. 2025-09-02 16:42:17 +00:00
Potherca-Bot
a73321dd02 Adds separate file for 'RowStatus_Modify.php'. 2025-09-02 16:42:17 +00:00
Potherca-Bot
3edcdc452e Changes content in separated file 'RowStatus_Error.php'. 2025-09-02 16:42:16 +00:00
Potherca-Bot
0c93971e13 Changes content in separated file 'RowStatus_Disappeared.php'. 2025-09-02 16:42:16 +00:00
Potherca-Bot
5a59b1870d Adds separate file for 'RowStatus_Issue.php'. 2025-09-02 16:42:16 +00:00
Potherca-Bot
19bb7e5043 Adds separate file for 'RowStatus_Error.php'. 2025-09-02 16:42:16 +00:00
Potherca-Bot
8e08be2258 Adds separate file for 'RowStatus_Disappeared.php'. 2025-09-02 16:42:16 +00:00
Potherca-Bot
22834d32a3 Changes content in separated file 'ReportValue.php'. 2025-09-02 16:42:15 +00:00
Potherca-Bot
23407cd095 Changes content in separated file 'CellStatus_Void.php'. 2025-09-02 16:42:15 +00:00
Potherca-Bot
8403273c0b Adds separate file for 'ReportValue.php'. 2025-09-02 16:42:15 +00:00
Potherca-Bot
d5dc3c0d74 Adds separate file for 'CellStatus_Void.php'. 2025-09-02 16:42:15 +00:00
Potherca-Bot
fbbdcfa7b9 Changes content in separated file 'CellStatus_SearchIssue.php'. 2025-09-02 16:42:14 +00:00
Potherca-Bot
7a528e276f Changes content in separated file 'CellStatus_NullIssue.php'. 2025-09-02 16:42:14 +00:00
Potherca-Bot
ed55bfa6aa Adds separate file for 'CellStatus_SearchIssue.php'. 2025-09-02 16:42:14 +00:00
Potherca-Bot
7f62a78529 Adds separate file for 'CellStatus_NullIssue.php'. 2025-09-02 16:42:14 +00:00
Potherca-Bot
cf51bddbc9 Changes content in separated file 'CellStatus_Modify.php'. 2025-09-02 16:42:13 +00:00
Potherca-Bot
adf3902c37 Changes content in separated file 'CellStatus_Issue.php'. 2025-09-02 16:42:13 +00:00
Potherca-Bot
6f5bed6b98 Changes content in separated file 'CellStatus_Ambiguous.php'. 2025-09-02 16:42:13 +00:00
Potherca-Bot
7079cab1de Adds separate file for 'CellStatus_Modify.php'. 2025-09-02 16:42:13 +00:00
Potherca-Bot
19188ac2fc Adds separate file for 'CellStatus_Issue.php'. 2025-09-02 16:42:13 +00:00
Potherca-Bot
d543e311dd Changes content in separated file 'CellChangeSpec.php'. 2025-09-02 16:42:12 +00:00
Potherca-Bot
19ea531961 Changes content in separated file 'BulkChange.php'. 2025-09-02 16:42:12 +00:00
Potherca-Bot
9bee4bdb5c Adds separate file for 'CellStatus_Ambiguous.php'. 2025-09-02 16:42:12 +00:00
Potherca-Bot
2b4e2939fe Adds separate file for 'CellChangeSpec.php'. 2025-09-02 16:42:12 +00:00
Potherca-Bot
2c8eac0e3b Adds separate file for 'BulkChange.php'. 2025-09-02 16:42:12 +00:00
Anne-Cath
2dd38e81c5 rollback file autoload.php 2025-08-28 14:49:54 +02:00
Anne-Cath
c052c40f9d update autoloader 2025-08-28 11:17:43 +02:00
anne-catherine
89fff9075d end merge 2025-08-28 09:08:22 +00:00
anne-catherine
97b4c80e0b update attributedef.class.inc.php 2025-08-28 09:07:44 +00:00
Potherca-Bot
905388825c Merge branch 'split-file_attributedef.class.inc.php_MissingColumnException.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:42 +00:00
Potherca-Bot
d02dec7a09 Merge branch 'split-file_attributedef.class.inc.php_iAttributeNoGroupBy.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:41 +00:00
Potherca-Bot
438ecfebdf Merge branch 'split-file_attributedef.class.inc.php_AttributeURL.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:41 +00:00
Potherca-Bot
8aa7e52fa2 Merge branch 'split-file_attributedef.class.inc.php_AttributeText.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:41 +00:00
Potherca-Bot
27642d5872 Merge branch 'split-file_attributedef.class.inc.php_AttributeTemplateText.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:41 +00:00
Potherca-Bot
4754009d4f Merge branch 'split-file_attributedef.class.inc.php_AttributeTemplateString.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:40 +00:00
Potherca-Bot
967911c538 Merge branch 'split-file_attributedef.class.inc.php_AttributeTemplateHTML.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:40 +00:00
Potherca-Bot
b3f069fec0 Merge branch 'split-file_attributedef.class.inc.php_AttributeTagSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:40 +00:00
Potherca-Bot
59db7535c3 Merge branch 'split-file_attributedef.class.inc.php_AttributeTable.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:39 +00:00
Potherca-Bot
f1657ac695 Merge branch 'split-file_attributedef.class.inc.php_AttributeSubItem.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:39 +00:00
Potherca-Bot
d307f4861f Merge branch 'split-file_attributedef.class.inc.php_AttributeString.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:39 +00:00
Potherca-Bot
6341e7e263 Merge branch 'split-file_attributedef.class.inc.php_AttributeStopWatch.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:38 +00:00
Potherca-Bot
0efec39071 Merge branch 'split-file_attributedef.class.inc.php_AttributeSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:38 +00:00
Potherca-Bot
e1ebeac986 Merge branch 'split-file_attributedef.class.inc.php_AttributeRedundancySettings.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:38 +00:00
Potherca-Bot
68c5d7d33b Merge branch 'split-file_attributedef.class.inc.php_AttributeQueryAttCodeSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:37 +00:00
Potherca-Bot
2cefaba0d8 Merge branch 'split-file_attributedef.class.inc.php_AttributePropertySet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:37 +00:00
Potherca-Bot
a57de6f090 Merge branch 'split-file_attributedef.class.inc.php_AttributePhoneNumber.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:37 +00:00
Potherca-Bot
6e63254a6b Merge branch 'split-file_attributedef.class.inc.php_AttributePercentage.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:36 +00:00
Potherca-Bot
2ae2407c24 Merge branch 'split-file_attributedef.class.inc.php_AttributePassword.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:36 +00:00
Potherca-Bot
d970f0e1e4 Merge branch 'split-file_attributedef.class.inc.php_AttributeOQL.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:36 +00:00
Potherca-Bot
b3ce941e5a Merge branch 'split-file_attributedef.class.inc.php_AttributeOneWayPassword.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:36 +00:00
Potherca-Bot
8976ad3635 Merge branch 'split-file_attributedef.class.inc.php_AttributeObsolescenceFlag.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:35 +00:00
Potherca-Bot
03d12d2485 Merge branch 'split-file_attributedef.class.inc.php_AttributeObsolescenceDate.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:35 +00:00
Potherca-Bot
582da19aaa Merge branch 'split-file_attributedef.class.inc.php_AttributeObjectKey.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:35 +00:00
Potherca-Bot
62aa33f0f3 Merge branch 'split-file_attributedef.class.inc.php_AttributeMetaEnum.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:34 +00:00
Potherca-Bot
8bb75006ba Merge branch 'split-file_attributedef.class.inc.php_AttributeLongText.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:34 +00:00
Potherca-Bot
b1881f1847 Merge branch 'split-file_attributedef.class.inc.php_AttributeLinkedSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:34 +00:00
Potherca-Bot
03759dffbb Merge branch 'split-file_attributedef.class.inc.php_AttributeLinkedSetIndirect.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:33 +00:00
Potherca-Bot
ada0126f9e Merge branch 'split-file_attributedef.class.inc.php_AttributeIPAddress.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:33 +00:00
Potherca-Bot
d897ddeed3 Merge branch 'split-file_attributedef.class.inc.php_AttributeInteger.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:33 +00:00
Potherca-Bot
eb14ef3c30 Merge branch 'split-file_attributedef.class.inc.php_AttributeImage.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:32 +00:00
Potherca-Bot
e12f6c92b2 Merge branch 'split-file_attributedef.class.inc.php_AttributeHTML.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:32 +00:00
Potherca-Bot
1dbc62ddf1 Merge branch 'split-file_attributedef.class.inc.php_AttributeHierarchicalKey.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:32 +00:00
Potherca-Bot
e6ac5f48b7 Merge branch 'split-file_attributedef.class.inc.php_AttributeFriendlyName.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:32 +00:00
Potherca-Bot
d32b6cc0b9 Merge branch 'split-file_attributedef.class.inc.php_AttributeFinalClass.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:31 +00:00
Potherca-Bot
63b70aa99b Merge branch 'split-file_attributedef.class.inc.php_AttributeExternalKey.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:31 +00:00
Potherca-Bot
71e006054d Merge branch 'split-file_attributedef.class.inc.php_AttributeExternalField.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:31 +00:00
Potherca-Bot
65c23c58c3 Merge branch 'split-file_attributedef.class.inc.php_AttributeEnumSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:30 +00:00
Potherca-Bot
8605d8667d Merge branch 'split-file_attributedef.class.inc.php_AttributeEnum.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:30 +00:00
Potherca-Bot
084b10a9a6 Merge branch 'split-file_attributedef.class.inc.php_AttributeEncryptedString.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:30 +00:00
Potherca-Bot
5ee18637bb Merge branch 'split-file_attributedef.class.inc.php_AttributeEmailAddress.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:30 +00:00
Potherca-Bot
bdbdd812e9 Merge branch 'split-file_attributedef.class.inc.php_AttributeDuration.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:29 +00:00
Potherca-Bot
2d43b8946d Merge branch 'split-file_attributedef.class.inc.php_AttributeDefinition.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:29 +00:00
Potherca-Bot
e5100ddeed Merge branch 'split-file_attributedef.class.inc.php_AttributeDecimal.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:29 +00:00
Potherca-Bot
ea9588761d Merge branch 'split-file_attributedef.class.inc.php_AttributeDeadline.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:28 +00:00
Potherca-Bot
16b34ab4e7 Merge branch 'split-file_attributedef.class.inc.php_AttributeDBFieldVoid.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:28 +00:00
Potherca-Bot
7bb8fbc793 Merge branch 'split-file_attributedef.class.inc.php_AttributeDBField.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:28 +00:00
Potherca-Bot
0816d3c84a Merge branch 'split-file_attributedef.class.inc.php_AttributeDateTime.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:28 +00:00
Potherca-Bot
66c5034ff2 Merge branch 'split-file_attributedef.class.inc.php_AttributeDate.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:27 +00:00
Potherca-Bot
03c097f5a1 Merge branch 'split-file_attributedef.class.inc.php_AttributeDashboard.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:27 +00:00
Potherca-Bot
87ca02dba3 Merge branch 'split-file_attributedef.class.inc.php_AttributeCustomFields.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:27 +00:00
Potherca-Bot
f4ba1a15fe Merge branch 'split-file_attributedef.class.inc.php_AttributeClassState.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:26 +00:00
Potherca-Bot
1977fe8cb0 Merge branch 'split-file_attributedef.class.inc.php_AttributeClass.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:26 +00:00
Potherca-Bot
91d0209253 Merge branch 'split-file_attributedef.class.inc.php_AttributeClassAttCodeSet.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:26 +00:00
Potherca-Bot
3bee8de25e Merge branch 'split-file_attributedef.class.inc.php_AttributeCaseLog.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:25 +00:00
Potherca-Bot
52db2a58ea Merge branch 'split-file_attributedef.class.inc.php_AttributeBoolean.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:25 +00:00
Potherca-Bot
16f0927d92 Merge branch 'split-file_attributedef.class.inc.php_AttributeBlob.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:25 +00:00
Potherca-Bot
bd64479687 Merge branch 'split-file_attributedef.class.inc.php_AttributeArchiveFlag.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:24 +00:00
Potherca-Bot
8436970132 Merge branch 'split-file_attributedef.class.inc.php_AttributeArchiveDate.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:24 +00:00
Potherca-Bot
08f35f451f Merge branch 'split-file_attributedef.class.inc.php_AttributeApplicationLanguage.php' into split-file_attributedef.class.inc.php 2025-08-28 09:06:24 +00:00
Potherca-Bot
dd441afa22 Changes content in separated file 'MissingColumnException.php'. 2025-08-28 09:06:23 +00:00
Potherca-Bot
5d8184a673 Changes content in separated file 'iAttributeNoGroupBy.php'. 2025-08-28 09:06:23 +00:00
Potherca-Bot
db91ed0c1d Adds separate file for 'MissingColumnException.php'. 2025-08-28 09:06:23 +00:00
Potherca-Bot
e890d62ab1 Changes content in separated file 'AttributeURL.php'. 2025-08-28 09:06:22 +00:00
Potherca-Bot
6d2b457185 Adds separate file for 'iAttributeNoGroupBy.php'. 2025-08-28 09:06:22 +00:00
Potherca-Bot
4328fc78dc Adds separate file for 'AttributeURL.php'. 2025-08-28 09:06:22 +00:00
Potherca-Bot
37914e2b7f Changes content in separated file 'AttributeText.php'. 2025-08-28 09:06:21 +00:00
Potherca-Bot
0551102364 Changes content in separated file 'AttributeTemplateText.php'. 2025-08-28 09:06:21 +00:00
Potherca-Bot
1ca369041d Adds separate file for 'AttributeText.php'. 2025-08-28 09:06:21 +00:00
Potherca-Bot
2a6a4d3460 Adds separate file for 'AttributeTemplateText.php'. 2025-08-28 09:06:21 +00:00
Potherca-Bot
9edc15f50d Changes content in separated file 'AttributeTemplateString.php'. 2025-08-28 09:06:20 +00:00
Potherca-Bot
6acb89a2fc Changes content in separated file 'AttributeTemplateHTML.php'. 2025-08-28 09:06:20 +00:00
Potherca-Bot
19803c004d Adds separate file for 'AttributeTemplateString.php'. 2025-08-28 09:06:20 +00:00
Potherca-Bot
20de262e25 Changes content in separated file 'AttributeTagSet.php'. 2025-08-28 09:06:19 +00:00
Potherca-Bot
c870fc5922 Adds separate file for 'AttributeTemplateHTML.php'. 2025-08-28 09:06:19 +00:00
Potherca-Bot
09c4a4361a Adds separate file for 'AttributeTagSet.php'. 2025-08-28 09:06:19 +00:00
Potherca-Bot
3544aa4d50 Changes content in separated file 'AttributeTable.php'. 2025-08-28 09:06:18 +00:00
Potherca-Bot
d080898b1d Changes content in separated file 'AttributeSubItem.php'. 2025-08-28 09:06:18 +00:00
Potherca-Bot
78282a80ef Adds separate file for 'AttributeTable.php'. 2025-08-28 09:06:18 +00:00
Potherca-Bot
3c8a198738 Adds separate file for 'AttributeSubItem.php'. 2025-08-28 09:06:18 +00:00
Potherca-Bot
4205988f79 Changes content in separated file 'AttributeString.php'. 2025-08-28 09:06:17 +00:00
Potherca-Bot
517ef9f3cf Changes content in separated file 'AttributeStopWatch.php'. 2025-08-28 09:06:17 +00:00
Potherca-Bot
f6d94ec2b5 Adds separate file for 'AttributeString.php'. 2025-08-28 09:06:17 +00:00
Potherca-Bot
0d9210777c Adds separate file for 'AttributeStopWatch.php'. 2025-08-28 09:06:17 +00:00
Potherca-Bot
bd86e02872 Changes content in separated file 'AttributeSet.php'. 2025-08-28 09:06:16 +00:00
Potherca-Bot
095fed9d4c Changes content in separated file 'AttributeRedundancySettings.php'. 2025-08-28 09:06:16 +00:00
Potherca-Bot
734424aa8a Adds separate file for 'AttributeSet.php'. 2025-08-28 09:06:16 +00:00
Potherca-Bot
bf467f664c Changes content in separated file 'AttributeQueryAttCodeSet.php'. 2025-08-28 09:06:15 +00:00
Potherca-Bot
51d960a229 Adds separate file for 'AttributeRedundancySettings.php'. 2025-08-28 09:06:15 +00:00
Potherca-Bot
63d7a25982 Adds separate file for 'AttributeQueryAttCodeSet.php'. 2025-08-28 09:06:15 +00:00
Potherca-Bot
614cf7b3c8 Changes content in separated file 'AttributePropertySet.php'. 2025-08-28 09:06:14 +00:00
Potherca-Bot
ea20d30ad1 Changes content in separated file 'AttributePhoneNumber.php'. 2025-08-28 09:06:14 +00:00
Potherca-Bot
3fc16deed2 Adds separate file for 'AttributePropertySet.php'. 2025-08-28 09:06:14 +00:00
Potherca-Bot
78e51c1209 Adds separate file for 'AttributePhoneNumber.php'. 2025-08-28 09:06:14 +00:00
Potherca-Bot
b96ff56dfd Changes content in separated file 'AttributePercentage.php'. 2025-08-28 09:06:13 +00:00
Potherca-Bot
bdeed2a14c Changes content in separated file 'AttributePassword.php'. 2025-08-28 09:06:13 +00:00
Potherca-Bot
a63813f284 Adds separate file for 'AttributePercentage.php'. 2025-08-28 09:06:13 +00:00
Potherca-Bot
0ec54bccd2 Adds separate file for 'AttributePassword.php'. 2025-08-28 09:06:13 +00:00
Potherca-Bot
aa83d1160c Changes content in separated file 'AttributeOQL.php'. 2025-08-28 09:06:12 +00:00
Potherca-Bot
dab7fb6c53 Changes content in separated file 'AttributeOneWayPassword.php'. 2025-08-28 09:06:12 +00:00
Potherca-Bot
bdd188f9e8 Adds separate file for 'AttributeOQL.php'. 2025-08-28 09:06:12 +00:00
Potherca-Bot
6d1abd17a2 Adds separate file for 'AttributeOneWayPassword.php'. 2025-08-28 09:06:12 +00:00
Potherca-Bot
149fdbe9e4 Changes content in separated file 'AttributeObsolescenceFlag.php'. 2025-08-28 09:06:11 +00:00
Potherca-Bot
23ba1b41e3 Changes content in separated file 'AttributeObsolescenceDate.php'. 2025-08-28 09:06:11 +00:00
Potherca-Bot
c958f45433 Adds separate file for 'AttributeObsolescenceFlag.php'. 2025-08-28 09:06:11 +00:00
Potherca-Bot
506780ceed Changes content in separated file 'AttributeObjectKey.php'. 2025-08-28 09:06:10 +00:00
Potherca-Bot
bf2d70f952 Changes content in separated file 'AttributeMetaEnum.php'. 2025-08-28 09:06:10 +00:00
Potherca-Bot
73f2311ca4 Adds separate file for 'AttributeObsolescenceDate.php'. 2025-08-28 09:06:10 +00:00
Potherca-Bot
6c4e0c3718 Adds separate file for 'AttributeObjectKey.php'. 2025-08-28 09:06:10 +00:00
Potherca-Bot
28c4ebc7ea Changes content in separated file 'AttributeLongText.php'. 2025-08-28 09:06:09 +00:00
Potherca-Bot
d692e1562d Adds separate file for 'AttributeMetaEnum.php'. 2025-08-28 09:06:09 +00:00
Potherca-Bot
4284ed955b Adds separate file for 'AttributeLongText.php'. 2025-08-28 09:06:09 +00:00
Potherca-Bot
854290dd2d Changes content in separated file 'AttributeLinkedSet.php'. 2025-08-28 09:06:08 +00:00
Potherca-Bot
1cf995b0c1 Changes content in separated file 'AttributeLinkedSetIndirect.php'. 2025-08-28 09:06:08 +00:00
Potherca-Bot
284aa0a20f Adds separate file for 'AttributeLinkedSet.php'. 2025-08-28 09:06:08 +00:00
Potherca-Bot
a5887e20be Changes content in separated file 'AttributeIPAddress.php'. 2025-08-28 09:06:07 +00:00
Potherca-Bot
f0acbdf478 Changes content in separated file 'AttributeInteger.php'. 2025-08-28 09:06:07 +00:00
Potherca-Bot
8a2770cf13 Adds separate file for 'AttributeLinkedSetIndirect.php'. 2025-08-28 09:06:07 +00:00
Potherca-Bot
27c1a23ecf Adds separate file for 'AttributeIPAddress.php'. 2025-08-28 09:06:07 +00:00
Potherca-Bot
67089a6ad2 Changes content in separated file 'AttributeImage.php'. 2025-08-28 09:06:06 +00:00
Potherca-Bot
a711e39976 Adds separate file for 'AttributeInteger.php'. 2025-08-28 09:06:06 +00:00
Potherca-Bot
c1535f07fb Adds separate file for 'AttributeImage.php'. 2025-08-28 09:06:06 +00:00
Potherca-Bot
97ddb2e214 Changes content in separated file 'AttributeHTML.php'. 2025-08-28 09:06:05 +00:00
Potherca-Bot
a2adfe31d8 Changes content in separated file 'AttributeHierarchicalKey.php'. 2025-08-28 09:06:05 +00:00
Potherca-Bot
b3c4edc332 Changes content in separated file 'AttributeFriendlyName.php'. 2025-08-28 09:06:05 +00:00
Potherca-Bot
3b680a6f94 Adds separate file for 'AttributeHTML.php'. 2025-08-28 09:06:05 +00:00
Potherca-Bot
9e92a88cba Adds separate file for 'AttributeHierarchicalKey.php'. 2025-08-28 09:06:05 +00:00
Potherca-Bot
38dbae2bb6 Changes content in separated file 'AttributeFinalClass.php'. 2025-08-28 09:06:04 +00:00
Potherca-Bot
b830398ca3 Adds separate file for 'AttributeFriendlyName.php'. 2025-08-28 09:06:04 +00:00
Potherca-Bot
1e7d1c48c3 Adds separate file for 'AttributeFinalClass.php'. 2025-08-28 09:06:04 +00:00
Potherca-Bot
5bfe501bf4 Changes content in separated file 'AttributeExternalKey.php'. 2025-08-28 09:06:03 +00:00
Potherca-Bot
e55d12fae6 Changes content in separated file 'AttributeExternalField.php'. 2025-08-28 09:06:03 +00:00
Potherca-Bot
0d8857f989 Adds separate file for 'AttributeExternalKey.php'. 2025-08-28 09:06:03 +00:00
Potherca-Bot
81688e9c86 Adds separate file for 'AttributeExternalField.php'. 2025-08-28 09:06:03 +00:00
Potherca-Bot
51ceadd882 Changes content in separated file 'AttributeEnumSet.php'. 2025-08-28 09:06:02 +00:00
Potherca-Bot
71d2ed0402 Changes content in separated file 'AttributeEnum.php'. 2025-08-28 09:06:02 +00:00
Potherca-Bot
a09521ca6b Adds separate file for 'AttributeEnumSet.php'. 2025-08-28 09:06:02 +00:00
Potherca-Bot
17b2bb058d Changes content in separated file 'AttributeEncryptedString.php'. 2025-08-28 09:06:01 +00:00
Potherca-Bot
9433fbbfd1 Changes content in separated file 'AttributeEmailAddress.php'. 2025-08-28 09:06:01 +00:00
Potherca-Bot
ae5b9aac8a Adds separate file for 'AttributeEnum.php'. 2025-08-28 09:06:01 +00:00
Potherca-Bot
7088047a5e Adds separate file for 'AttributeEncryptedString.php'. 2025-08-28 09:06:01 +00:00
Potherca-Bot
b5d8740ab0 Changes content in separated file 'AttributeDuration.php'. 2025-08-28 09:06:00 +00:00
Potherca-Bot
e0e5b094a4 Adds separate file for 'AttributeEmailAddress.php'. 2025-08-28 09:06:00 +00:00
Potherca-Bot
9dc21cc91f Adds separate file for 'AttributeDuration.php'. 2025-08-28 09:06:00 +00:00
Potherca-Bot
99c16135c3 Changes content in separated file 'AttributeDefinition.php'. 2025-08-28 09:05:59 +00:00
Potherca-Bot
849f74147c Changes content in separated file 'AttributeDecimal.php'. 2025-08-28 09:05:59 +00:00
Potherca-Bot
3543115730 Changes content in separated file 'AttributeDeadline.php'. 2025-08-28 09:05:59 +00:00
Potherca-Bot
1f5c1df50c Adds separate file for 'AttributeDefinition.php'. 2025-08-28 09:05:59 +00:00
Potherca-Bot
d917a4cad3 Adds separate file for 'AttributeDecimal.php'. 2025-08-28 09:05:59 +00:00
Potherca-Bot
6bc96fb6eb Changes content in separated file 'AttributeDBFieldVoid.php'. 2025-08-28 09:05:58 +00:00
Potherca-Bot
22dbb0984d Adds separate file for 'AttributeDeadline.php'. 2025-08-28 09:05:58 +00:00
Potherca-Bot
5c5a184388 Adds separate file for 'AttributeDBFieldVoid.php'. 2025-08-28 09:05:58 +00:00
Potherca-Bot
3ee0b3a5e1 Changes content in separated file 'AttributeDBField.php'. 2025-08-28 09:05:57 +00:00
Potherca-Bot
16907d414e Changes content in separated file 'AttributeDateTime.php'. 2025-08-28 09:05:57 +00:00
Potherca-Bot
e928054e9c Adds separate file for 'AttributeDBField.php'. 2025-08-28 09:05:57 +00:00
Potherca-Bot
b5eb93dbd1 Adds separate file for 'AttributeDateTime.php'. 2025-08-28 09:05:57 +00:00
Potherca-Bot
31a4c38638 Changes content in separated file 'AttributeDate.php'. 2025-08-28 09:05:56 +00:00
Potherca-Bot
d6c73c8142 Changes content in separated file 'AttributeDashboard.php'. 2025-08-28 09:05:56 +00:00
Potherca-Bot
2ed9dc6f31 Adds separate file for 'AttributeDate.php'. 2025-08-28 09:05:56 +00:00
Potherca-Bot
fa51ef1adb Changes content in separated file 'AttributeCustomFields.php'. 2025-08-28 09:05:55 +00:00
Potherca-Bot
f2b2d422a6 Changes content in separated file 'AttributeClassState.php'. 2025-08-28 09:05:55 +00:00
Potherca-Bot
c58161b9b4 Adds separate file for 'AttributeDashboard.php'. 2025-08-28 09:05:55 +00:00
Potherca-Bot
0a32ddb8e2 Adds separate file for 'AttributeCustomFields.php'. 2025-08-28 09:05:55 +00:00
Potherca-Bot
161a05132b Changes content in separated file 'AttributeClass.php'. 2025-08-28 09:05:54 +00:00
Potherca-Bot
3967a82719 Changes content in separated file 'AttributeClassAttCodeSet.php'. 2025-08-28 09:05:54 +00:00
Potherca-Bot
ce9425f273 Adds separate file for 'AttributeClassState.php'. 2025-08-28 09:05:54 +00:00
Potherca-Bot
4af8f54f26 Adds separate file for 'AttributeClass.php'. 2025-08-28 09:05:54 +00:00
Potherca-Bot
bb904d7ec3 Changes content in separated file 'AttributeCaseLog.php'. 2025-08-28 09:05:53 +00:00
Potherca-Bot
426da64c46 Adds separate file for 'AttributeClassAttCodeSet.php'. 2025-08-28 09:05:53 +00:00
Potherca-Bot
6b4bfb0238 Adds separate file for 'AttributeCaseLog.php'. 2025-08-28 09:05:53 +00:00
Potherca-Bot
8420ef38ac Changes content in separated file 'AttributeBoolean.php'. 2025-08-28 09:05:52 +00:00
Potherca-Bot
db8f657c8e Changes content in separated file 'AttributeBlob.php'. 2025-08-28 09:05:52 +00:00
Potherca-Bot
a3d881715e Adds separate file for 'AttributeBoolean.php'. 2025-08-28 09:05:52 +00:00
Potherca-Bot
db9e932fc1 Adds separate file for 'AttributeBlob.php'. 2025-08-28 09:05:52 +00:00
Potherca-Bot
0cd9b08bcb Changes content in separated file 'AttributeArchiveFlag.php'. 2025-08-28 09:05:51 +00:00
Potherca-Bot
4b7d589c9f Changes content in separated file 'AttributeArchiveDate.php'. 2025-08-28 09:05:51 +00:00
Potherca-Bot
2554477987 Adds separate file for 'AttributeArchiveFlag.php'. 2025-08-28 09:05:51 +00:00
Potherca-Bot
3d0dc422dc Adds separate file for 'AttributeArchiveDate.php'. 2025-08-28 09:05:51 +00:00
Potherca-Bot
b469a16a05 Changes content in separated file 'AttributeApplicationLanguage.php'. 2025-08-28 09:05:50 +00:00
Potherca-Bot
995d6654fd Adds separate file for 'AttributeApplicationLanguage.php'. 2025-08-28 09:05:50 +00:00
anne-catherine
57892f58d8 end merge 2025-08-28 09:04:27 +00:00
anne-catherine
5c4def502c update asynctask.class.inc.php 2025-08-28 09:03:41 +00:00
Potherca-Bot
0d61f5ac6b Merge branch 'split-file_asynctask.class.inc.php_ExecAsyncTask.php' into split-file_asynctask.class.inc.php 2025-08-28 09:02:25 +00:00
Potherca-Bot
86cfe10e96 Merge branch 'split-file_asynctask.class.inc.php_AsyncTask.php' into split-file_asynctask.class.inc.php 2025-08-28 09:02:24 +00:00
Potherca-Bot
8042364a3b Merge branch 'split-file_asynctask.class.inc.php_AsyncSendNewsroom.php' into split-file_asynctask.class.inc.php 2025-08-28 09:02:24 +00:00
Potherca-Bot
9b29c45f2b Merge branch 'split-file_asynctask.class.inc.php_AsyncSendEmail.php' into split-file_asynctask.class.inc.php 2025-08-28 09:02:24 +00:00
Potherca-Bot
d10d5a6062 Changes content in separated file 'ExecAsyncTask.php'. 2025-08-28 09:02:23 +00:00
Potherca-Bot
cc38a03d17 Changes content in separated file 'AsyncTask.php'. 2025-08-28 09:02:23 +00:00
Potherca-Bot
e640443ea5 Adds separate file for 'ExecAsyncTask.php'. 2025-08-28 09:02:23 +00:00
Potherca-Bot
7f7cf50143 Adds separate file for 'AsyncTask.php'. 2025-08-28 09:02:23 +00:00
Potherca-Bot
3c639bdce3 Changes content in separated file 'AsyncSendNewsroom.php'. 2025-08-28 09:02:22 +00:00
Potherca-Bot
77448a7fc9 Changes content in separated file 'AsyncSendEmail.php'. 2025-08-28 09:02:22 +00:00
Potherca-Bot
41c2a9e97a Adds separate file for 'AsyncSendNewsroom.php'. 2025-08-28 09:02:22 +00:00
Potherca-Bot
080c72eec7 Adds separate file for 'AsyncSendEmail.php'. 2025-08-28 09:02:22 +00:00
anne-catherine
c8de4a4682 end merge 2025-08-28 08:59:06 +00:00
anne-catherine
c4d465574c update action.class.inc.php 2025-08-28 08:53:41 +00:00
Potherca-Bot
d776589fed Merge branch 'split-file_action.class.inc.php_Action.php' into split-file_action.class.inc.php 2025-08-28 08:48:41 +00:00
Potherca-Bot
22895462df Merge branch 'split-file_action.class.inc.php_ActionNotification.php' into split-file_action.class.inc.php 2025-08-28 08:48:40 +00:00
Potherca-Bot
34f4c4102d Changes content in separated file 'Action.php'. 2025-08-28 08:48:40 +00:00
Potherca-Bot
8c79499ace Merge branch 'split-file_action.class.inc.php_ActionEmail.php' into split-file_action.class.inc.php 2025-08-28 08:48:40 +00:00
Potherca-Bot
e7c62c9ef2 Changes content in separated file 'ActionNotification.php'. 2025-08-28 08:48:40 +00:00
Potherca-Bot
96154bd02d Adds separate file for 'Action.php'. 2025-08-28 08:48:40 +00:00
Potherca-Bot
6ecf784bc5 Changes content in separated file 'ActionEmail.php'. 2025-08-28 08:48:39 +00:00
Potherca-Bot
8748a1e51d Adds separate file for 'ActionNotification.php'. 2025-08-28 08:48:39 +00:00
Potherca-Bot
ffad7784aa Adds separate file for 'ActionEmail.php'. 2025-08-28 08:48:39 +00:00
anne-catherine
d4dc6c1860 Merge branch 'split-file_valuesetdef.class.inc.php' into feature/2535-split_file 2025-08-28 08:35:10 +00:00
anne-catherine
a1f92a1b4c update original file 2025-08-28 08:34:03 +00:00
Potherca-Bot
33a61a6daa Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetRange.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:43 +00:00
Potherca-Bot
0ddd73bb36 Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetObjects.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:43 +00:00
Potherca-Bot
a0a61837e7 Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetEnum.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:43 +00:00
Potherca-Bot
b8d6990f17 Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetEnumPadded.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:43 +00:00
Potherca-Bot
4b47eae92c Changes content in separated file 'ValueSetRange.php'. 2025-08-27 21:11:42 +00:00
Potherca-Bot
7dff1bb26f Changes content in separated file 'ValueSetObjects.php'. 2025-08-27 21:11:42 +00:00
Potherca-Bot
7e0e511b4b Changes content in separated file 'ValueSetEnum.php'. 2025-08-27 21:11:42 +00:00
Potherca-Bot
1e5cb01b15 Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetEnumClasses.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:42 +00:00
Potherca-Bot
159496afd7 Adds separate file for 'ValueSetRange.php'. 2025-08-27 21:11:42 +00:00
Potherca-Bot
9178144675 Adds separate file for 'ValueSetObjects.php'. 2025-08-27 21:11:42 +00:00
Potherca-Bot
5264edb7ea Merge branch 'split-file_valuesetdef.class.inc.php_ValueSetDefinition.php' into split-file_valuesetdef.class.inc.php 2025-08-27 21:11:42 +00:00
Potherca-Bot
bcf05493d7 Changes content in separated file 'ValueSetEnumPadded.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
599d34921f Adds separate file for 'ValueSetEnum.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
f5646d6794 Changes content in separated file 'ValueSetEnumClasses.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
842dce7c9c Changes content in separated file 'ValueSetDefinition.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
cf15f087d4 Adds separate file for 'ValueSetEnumPadded.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
376ec1763f Adds separate file for 'ValueSetEnumClasses.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
45d29cf3b4 Adds separate file for 'ValueSetDefinition.php'. 2025-08-27 21:11:41 +00:00
Potherca-Bot
68d16625ce Merge branch 'split-file_event.class.inc.php_EventWebService.php' into split-file_event.class.inc.php 2025-08-27 20:39:13 +00:00
Potherca-Bot
412cef4893 Merge branch 'split-file_event.class.inc.php_EventRestService.php' into split-file_event.class.inc.php 2025-08-27 20:39:13 +00:00
Potherca-Bot
2f6980ab2b Merge branch 'split-file_event.class.inc.php_Event.php' into split-file_event.class.inc.php 2025-08-27 20:39:13 +00:00
Potherca-Bot
cab3705ed1 Changes content in separated file 'EventWebService.php'. 2025-08-27 20:39:12 +00:00
Potherca-Bot
69d33d03c8 Merge branch 'split-file_event.class.inc.php_EventOnObject.php' into split-file_event.class.inc.php 2025-08-27 20:39:12 +00:00
Potherca-Bot
9a7a4b6056 Merge branch 'split-file_event.class.inc.php_EventNotification.php' into split-file_event.class.inc.php 2025-08-27 20:39:12 +00:00
Potherca-Bot
b3b0c2966b Merge branch 'split-file_event.class.inc.php_EventNotificationEmail.php' into split-file_event.class.inc.php 2025-08-27 20:39:12 +00:00
Potherca-Bot
92b4e4bb94 Merge branch 'split-file_event.class.inc.php_EventLoginUsage.php' into split-file_event.class.inc.php 2025-08-27 20:39:12 +00:00
Potherca-Bot
3e28ec3cd4 Merge branch 'split-file_event.class.inc.php_EventIssue.php' into split-file_event.class.inc.php 2025-08-27 20:39:12 +00:00
Potherca-Bot
a4fae555c7 Changes content in separated file 'EventRestService.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
dbc6b955b4 Changes content in separated file 'Event.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
786be188e4 Adds separate file for 'EventWebService.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
7821a9552d Changes content in separated file 'EventOnObject.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
2377bd8eac Adds separate file for 'EventRestService.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
3be8fa7a80 Adds separate file for 'Event.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
12bdead661 Adds separate file for 'EventOnObject.php'. 2025-08-27 20:39:11 +00:00
Potherca-Bot
ad8d49a6af Changes content in separated file 'EventNotification.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
0612903c7b Changes content in separated file 'EventNotificationEmail.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
3c68bd0c37 Changes content in separated file 'EventLoginUsage.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
7a178e9d9f Adds separate file for 'EventNotification.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
1c643aa36c Adds separate file for 'EventNotificationEmail.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
40c76eb36a Adds separate file for 'EventLoginUsage.php'. 2025-08-27 20:39:10 +00:00
Potherca-Bot
f5190a9dcd Changes content in separated file 'EventIssue.php'. 2025-08-27 20:39:09 +00:00
Potherca-Bot
254c4f5065 Adds separate file for 'EventIssue.php'. 2025-08-27 20:39:09 +00:00
Anne-Cath
2ba4109343 N°6932 - Split applicationextension.inc.php APIs in separate files 2025-08-26 17:46:10 +02:00
Timmy38
738664e560 N°4107 - DBObject::GetName() is now final 2025-08-26 14:39:43 +02:00
Anne-Cath
d48bc15211 N°8190 - Userrights management should not be overridable anymore 2025-08-26 09:50:14 +02:00
Anne-Cath
32f0cfb091 Remove deprecated message 2025-08-26 09:32:31 +02:00
Anne-Cath
20393b55b9 N°8190 - Userrights management should not be overridable anymore 2025-08-26 09:17:51 +02:00
Anne-Cath
f03b008ebf N°8189 - Addons userrights - one is enough - remove files 2025-08-19 13:54:51 +02:00
jf-cbd
7f98ef3478 Update README.md 2025-08-18 16:02:50 +02:00
odain
d80e26791d N°8511 - Enhance DBObjectSet to be able to order by id 2025-08-18 14:42:06 +02:00
Anne-Cath
e6a0d95cba N°7835 - Dashboard - modification on iTop UI with header static without icon 2025-08-18 13:16:29 +02:00
Anne-Cath
965c9dba14 N°4718 - Remove "FilterCodes" - fix $m_aFilterForbiddenAttributes init 2025-08-14 11:04:47 +02:00
Benjamin Dalsass
8bca3ac830 N°7176 - Update nikic/php-parser to 5.0.0 (#735) 2025-08-14 09:03:32 +02:00
Stephen Abello
a975f67bd5 N°8455 - Fix portal environment banner displaying poorly 2025-08-13 17:02:48 +02:00
Anne-Cath
f5b86ff4d9 N°4718 - Remove "FilterCodes" - rename GetMagicAttributes to GetMagicFields 2025-08-13 16:59:40 +02:00
Anne-Cath
0deeeeb587 N°4718 - Remove "FilterCodes" - rename GetMagicAttributes to GetMagicField 2025-08-13 16:56:46 +02:00
Anne-Cath
2011570b84 N°4718 - Remove "FilterCodes" - case of AttributeStopWatch and AttributePassword 2025-08-12 15:50:51 +02:00
Benjamin Dalsass
1458ba877b N°7659 - Remove utils::GetClassesForInterface (#732) 2025-08-12 14:06:26 +02:00
Timmy38
71386198cf N°3124 - Refactorize ResizeImageToFit methods (#734) 2025-08-08 10:43:35 +02:00
Anne-Cath
5b9e0a1d4f N°3817 - Audit and fix calls to deprecated jQuery method 2025-08-06 19:47:57 +02:00
Anne-Cath
1667f834b9 Remove unusued lines 2025-08-06 09:44:35 +02:00
Benjamin Dalsass
cdbcd14767 N°8017 - Security - dependabot - Symfony's VarDumper vulnerable to un… (#731)
Upgrade all Symfony components to last security fix (~6.4.0)
2025-08-06 08:54:56 +02:00
Benjamin Dalsass
603340b852 Correct tcpdf composer update fonts script case issue 2025-08-06 08:33:50 +02:00
Anne-Cath
820087e4d1 N°4500 - Remove iPageUIExtension & AbstractPageUIExtension API 2025-08-04 10:30:38 +02:00
Benjamin Dalsass
c5ee123f88 Restore compilation symlinks file 2025-08-04 10:19:56 +02:00
Benjamin Dalsass
69d5015a24 N°7320 - Remove WebPage::add_linked_stylesheet method 2025-08-04 10:19:05 +02:00
Benjamin Dalsass
1d1365d951 N°7319 - Remove WebPage::add_linked_script method 2025-08-04 10:19:05 +02:00
Thomas Casteleyn
3da33c4c64 chore(auth-ldap): Prepare for php 8.3 deprecation (#720) 2025-08-01 15:28:19 +02:00
Anne-Cath
7b95d65f60 N°3653 - Remove parameter for \DBObjectSearch::GetQueryParams 2025-08-01 10:05:40 +02:00
Stephen Abello
d3e450c54e N°3749 - Remove old JS tooltip libs (qTip, jQuery tooltip, Bootstrap tooltip) calls 2025-08-01 10:01:30 +02:00
Anne-Cath
5a50398dba N°2592 - API : remove \CMDBObject::CheckUserRights 2025-08-01 09:32:52 +02:00
Anne-Cath
387ca19ec2 N°2711 - Portal: Remove "goto" xsi:type in action rules 2025-08-01 09:21:59 +02:00
Anne-Cath
c0651edaa1 N°8578 - Remove CollapsibleSection functions deprecated in 3.0.0 2025-08-01 09:19:21 +02:00
Anne-Cath
b06f3cd13e N°2711 - Portal: Remove "goto" xsi:type in action rules 2025-08-01 09:14:05 +02:00
Benjamin Dalsass
5aeb408edd N°4717 - Remove ajax.render.php xlsx_* operations 2025-08-01 08:15:26 +02:00
Benjamin Dalsass
7456383d72 N°4716 - Remove core/expression.class.inc.php 2025-08-01 08:03:59 +02:00
Anne-Cath
9c6b8f90f0 N°8189 - Addons userrights - one is enough - deprecate other files 2025-07-31 17:09:05 +02:00
Anne-Cath
e6ea2fd541 N°3815 - Remove "DisplayTemplate" PHP classes - modify comment 2025-07-31 17:07:48 +02:00
Anne-Cath
7d94e6f1f8 N°8578 - Remove CollapsibleSection functions deprecated in 3.0.0 2025-07-31 14:25:20 +02:00
Anne-Cath
2bd7c7a01a N°3815 - Remove "DisplayTemplate" PHP classes 2025-07-31 14:23:35 +02:00
Anne-Cath
f1762845f0 N°4720 - Remove old unreferenced methods that are @deprecated 2025-07-31 11:06:09 +02:00
Anne-Cath
3eb8437c32 N°4693 - Restore API to add sass entries in the backoffice pages - rename Interface 2025-07-31 10:07:15 +02:00
Anne-Cath
9acc6a8bd4 N°4693 - Restore API to add saas entries in the backoffice pages 2025-07-30 16:41:31 +02:00
Anne-Cath
4d794fe656 N°4813 - Remove DataTable class and file 2025-07-30 15:29:15 +02:00
Stephen Abello
c9f88a16ef N°6792 - Remove deprecated method \cmdbAbstract::DisplayCaseLog 2025-07-30 10:54:45 +02:00
Stephen Abello
95f84a98cc N°4455 - Remove old PNG icons for datamodel classes 2025-07-30 09:35:13 +02:00
Anne-Cath
6cb10ab13a N°4718 - Remove "FilterCodes" 2025-07-29 17:26:15 +02:00
Stephen Abello
048aaeb854 N°5312 - Remove old backoffice stylesheets 2025-07-29 15:05:18 +02:00
Benjamin Dalsass
2b18ab9690 N°6491 - Remove \Combodo\iTop\Form\Validator\Validator class 2025-07-29 15:03:19 +02:00
Stephen Abello
36dc71fdce N°4035 - Remove duplicated TWIG extensions class 2025-07-29 14:51:14 +02:00
Benjamin Dalsass
db2ad86c70 N°6533 - Remove core/coreexception.class.inc.php 2025-07-29 14:22:50 +02:00
Anne-Cath
56616ab08e N°8397 - Suppress export V1 from iTop packages - fix tests 2025-07-29 12:03:46 +02:00
Anne-Cath
f339498497 N°7002 - API : remove DisplayableGraph::Display and DisplayableGraph::DisplayFiltering 2025-07-29 11:46:27 +02:00
Anne-Cath
b24a359b36 N°6982 - Remove \cmdbAbstractObject::DBDeleteTracked_Internal 2025-07-29 11:39:54 +02:00
Anne-Cath
78c63f7502 N°6980 - Remove cmdbAbstractObject::DBCloneTracked_Internal 2025-07-29 11:35:45 +02:00
Anne-Cath
2f8b35c153 N°3393 - Remove WebPages deprecated in 3.0.0 2025-07-29 10:59:04 +02:00
Stephen Abello
271a1f66c1 N°6262 - Remove \DataTableUIBlockFactory::MakeForRenderingObject() method 2025-07-29 10:51:48 +02:00
Stephen Abello
738c7e1b8e N°6490 - Remove SelectObjectField::VerifyCurrentValue 2025-07-29 10:41:44 +02:00
Stephen Abello
54278f8c02 N°5233 - Remove \CMDBObject::DBCloneTracked 2025-07-29 10:36:29 +02:00
Stephen Abello
00e117b05f N°3898 - Remove ThemeHandler::GetCurrentThemeId() 2025-07-29 10:11:20 +02:00
Stephen Abello
504261a2c2 N°6775 - Remove WizardHelper::GetJsForUpdateFields() 2025-07-29 10:02:31 +02:00
Anne-Cath
14a1a4e9c7 N°8397 - Suppress export V1 from iTop packages 2025-07-29 09:53:12 +02:00
Stephen Abello
cfc4a43d0b N°7072 - Remove \iNewsroomProvider from \MetaModel::InitExtensions() 2025-07-29 09:48:55 +02:00
Stephen Abello
503a5ec25a N°4379 - Removed deprecated methods AbstractController::ForwardFromRoute and AbstractController::GetControllerNameFromRoute 2025-07-29 09:31:32 +02:00
Stephen Abello
09364ccf84 N°4386 - Remove deprecated EncodeHtml in utils.js 2025-07-29 08:48:44 +02:00
BenGrenoble
4bbd1fea5c N°8286 - Be able to add additional data in iTop session files via custom classes
Change to fit convention.
2025-07-24 10:59:12 +02:00
BenGrenoble
3c27847a04 N°8286 - Be able to add additional data in iTop session files via custom classes
Experimental warning
2025-07-24 10:29:48 +02:00
Benjamin Dalsass
8523da3329 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-23 16:37:12 +02:00
Benjamin Dalsass
8580cb70a4 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-16 16:46:42 +02:00
v-dumas
bfbc939bac N°3610 - shortcut_actions supports menu with JS code (2) 2025-07-10 11:48:24 +02:00
bdalsass
dffce3f2f7 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-10 10:21:45 +02:00
v-dumas
e96095e02d Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-09 17:16:02 +02:00
v-dumas
8330582f86 N°3610 - shortcut_actions supports menu with JS code 2025-07-09 15:34:37 +02:00
v-dumas
5a4ad7b8c3 N°6925 - Add a dedicated dict entry for "View the OQL query" 2025-07-09 15:03:40 +02:00
v-dumas
a116967b0a N°8520 - 'shortcut_actions' support any standard menu 2025-07-09 14:58:52 +02:00
v-dumas
a13f353721 N°8520 - 'shortcut_actions' support blanks between menu ids 2025-07-09 14:53:29 +02:00
bdalsass
bd254e56d1 Portal fix unpatched template.
Note: The new look extension is already fixed.
2025-07-09 07:46:08 +02:00
bdalsass
346bd5de47 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-09 07:38:59 +02:00
Romain Quetiez
599e08f150 N°8440 XML assembly failing when a file name contains a quote 2025-07-08 17:31:42 +02:00
v-dumas
0462298cd3 N°7796 - Fix impact analyses without functionalcis_list on Ticket 2025-07-08 09:42:18 +02:00
jf-cbd
80abaec9a6 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-07 16:09:04 +02:00
bdalsass
a7877dc6a6 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-07 14:04:18 +02:00
v-dumas
a2d6423f32 N°7796 - Fix impact analyses without functionalcis_list on Ticket 2025-07-04 18:30:16 +02:00
bdalsass
57d610fc16 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-03 13:41:47 +02:00
bdalsass
d2d422afcf Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-01 16:11:20 +02:00
bdalsass
278ac66637 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-06-30 10:08:47 +02:00
odain
87db141c3c Merge branch 'support/3.2' into develop 2025-06-19 11:32:58 +02:00
jf-cbd
f062f994f0 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-06-16 17:01:49 +02:00
jf-cbd
fb81e54ed9 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	core/kpi.class.inc.php
#	datamodels/2.x/itop-profiles-itil/datamodel.itop-profiles-itil.xml
2025-06-16 15:03:36 +02:00
Eric Espie
916467ea61 Better perf for KPI logging 2025-06-13 15:26:43 +02:00
Romain Quetiez
8a4ad87b06 N°8440 Allow icon file ids to contain quotes, by correctly escaping language literals (XPath or PHP) 2025-06-13 09:58:59 +02:00
Romain Quetiez
2086052d60 N°8440 Allow icon file ids to contain quotes, by correctly escaping language literals (XPath or PHP) 2025-06-13 09:55:25 +02:00
Anne-Cath
0a4f9e95c5 N°7216 - CSV Import failling with cryptic message when some lines have a missing separator - fix test 2025-06-06 10:29:26 +02:00
Anne-Cath
282fb13973 N°7216 - CSV Import failling with cryptic message when some lines have a missing separator - fix import with ignored values 2025-06-03 13:32:49 +02:00
bdalsass
0b92535fda Merge remote-tracking branch 'origin/support/3.2' into develop 2025-06-02 17:18:34 +02:00
Stephen Abello
a0f4c62bcc Fix browse brick items color not being overloadable 2025-05-28 16:35:12 +02:00
bdalsass
cd4e2608ee Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-23 10:19:16 +02:00
bdalsass
d6c9a6d318 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-23 09:14:26 +02:00
Pavel Stetina
ca937b829b Typo correction (#718) 2025-05-22 14:43:31 +02:00
Stephen Abello
e0b8ee2143 Merge branch 'support/3.2' into develop 2025-05-20 09:50:11 +02:00
bdalsass
20a7a945fc Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-16 14:36:36 +02:00
bdalsass
0640c1e9b6 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	application/utils.inc.php
2025-05-16 14:22:12 +02:00
Guy Couronné
cad40ed758 N°7799 - Allow AttributeSet in XML sample file (#654)
*  Allow AttributeSet in XML sample file

In XML Data Loader, manage AttributeSet class and its children to be imported , in sample XML files.
2025-05-15 16:00:50 +02:00
Stephen Abello
11d23ac99b N°8274 - Make linkset toggler follow primary colors 2025-05-15 11:04:57 +02:00
Stephen Abello
1eeb98d2e2 N°8274 - Make hardcoded string a dict entry 2025-05-15 11:04:57 +02:00
Stephen Abello
92e2d22248 N°8274 - Change ui version 2025-05-15 11:04:57 +02:00
jf-cbd
5811dc06e3 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-15 09:48:22 +02:00
Stephen Abello
6bd11fb9bf N°8361 - Make vertical the default value for portal's menu 2025-05-06 10:43:34 +02:00
jf-cbd
624573d088 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php
2025-04-22 10:22:25 +02:00
Anne-Catherine
b21a02dcb8 N°7385 - Trigger on mention executed even if it's not a mention with @ (#638) 2025-04-18 14:52:23 +02:00
Anne-Catherine
3b60e63c97 N°6663 - Request template fields do not apply portal silos (#684) 2025-04-18 13:01:19 +02:00
Benjamin Dalsass
adc8b47945 N°8318 - Managing menu in itop portal new look (#710) 2025-04-14 16:38:36 +02:00
Stephen Abello
5e6d96019d N°8274 - Move mixins declarations to utils, move their usage to themes/ to be able to have their variables overloaded 2025-04-11 10:43:03 +02:00
Stephen Abello
06cc64f6d6 N°8274 - Move CSS color declaration to themes/ to avoid them being redeclared with every file importing utils 2025-04-11 10:09:18 +02:00
Stephen Abello
a5c14c3a48 N°8274 - Move body colors from legacy file to current theme files 2025-04-11 10:08:17 +02:00
Stephen Abello
8f6f243716 N°8274 - Fix typo 2025-04-11 09:47:50 +02:00
Stephen Abello
3c574819b2 N°8274 - Update precompiled stylesheets 2025-04-10 10:35:01 +02:00
Stephen Abello
5b1ea20407 N°8274 - Move every color style to themes/ to ease color customization, add illustration to export popup 2025-04-10 10:33:34 +02:00
Ben
4d88ef6ed4 Update contributors 2025-04-08 09:55:20 +02:00
Stephen Abello
5cb1102e6e N°8274 - Update precompiled stylesheets 2025-04-03 15:51:44 +02:00
Stephen Abello
bf23e4d98d N°8274 - Fix portal additional user profile tabs display 2025-04-03 15:51:36 +02:00
Stephen Abello
8645b28baa N°8274 - Update precompiled stylesheets 2025-04-02 15:50:29 +02:00
Stephen Abello
eff6fcff49 N°8274 - Fix input followed by input control (such as date time picker) display 2025-04-02 15:48:42 +02:00
Stephen Abello
994b08f94a N°8274 - Add no item illustration to browse brick 2025-04-02 15:45:28 +02:00
Stephen Abello
19495d8acf N°8274 - Update precompiled stylesheets 2025-04-02 14:32:38 +02:00
Stephen Abello
48a3ea1945 N°8274 - Replace color for selected rows in datatables 2025-04-02 14:31:33 +02:00
Stephen Abello
a11b2845f7 N°8274 - Correctly vertical align following dot in modal title 2025-04-02 12:07:21 +02:00
Stephen Abello
ee72325451 N°8274 - Make color slightly different for nested fieldset 2025-04-02 12:07:04 +02:00
Stephen Abello
ebb59d3ddc N°8274 - Align modal header and footer padding 2025-04-02 11:35:23 +02:00
Stephen Abello
0193db609d N°8274 - Add illustration on empty manage brick 2025-04-02 11:30:14 +02:00
Stephen Abello
ea2caed98a N°8274 - Correctly vertical align following dot 2025-04-02 11:29:42 +02:00
Stephen Abello
09c092782c N°8274 - Add approot to portal's Symfony variables. Allow portal's twig to display images located in /images in twig 2025-04-02 11:15:45 +02:00
Stephen Abello
a4166f874e N°8274 - Allow to recolor illustrations in portal 2025-04-01 16:28:40 +02:00
Stephen Abello
96382377ee N°8274 - Polishing new look portal (#707)
* Remove precompiled CSS files

* Fix mosaic design, polish mosaic and treeview hover colors

* Fix modal close button not being visible, clean modal code

* Fix mandatory and tooltip indicator on fields

* Fix treeview filter data display

* N°8274 - Improve profile brick display

* N°8274 - Use ipb alert instead of bootstrap alerts

* N°8274 - Make sure dropdown items use all available space

* N°8274 - Remove class name from the object brick title and add it to a separate title complement

* N°8274 - Polishing new look portal
- La police des informations dans l'annonce est trop petite (Quitte a agrandir le bloc information pour ne pas perdre de ligne d'affichage)

* N°8274 - Add visual indicator to selected tab

* N°8274 - Set the icon url to home page if it's not customized

* N°8274 - Polishing new look portal
- fix manage bricks pills click event

* N°8274 - Make panel title and tab text bigger

* N°8274 - Make datatables more similar to backoffice

* Add precompiled stylesheets

---------

Co-authored-by: Benjamin <benjamin.dalsass@combodo.com>
2025-03-31 15:41:55 +02:00
Stephen Abello
84708fb327 Merge branch 'support/3.2' into develop 2025-03-26 09:31:38 +01:00
Romain Quetiez
02adca0a1f 🎨 N°8231 Code format and comments 2025-03-25 11:48:23 +01:00
jf-cbd
90370fce3b Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/composer.json
2025-03-24 11:45:49 +01:00
jf-cbd
fe913524fd Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-13 16:04:19 +01:00
jf-cbd
9f2375999a Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php
2025-03-13 15:57:15 +01:00
jf-cbd
4b86639d71 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-12 11:55:15 +01:00
Stephen Abello
911a204f37 N°4685 - Fix padding in browse brick's treeview toolbar 2025-03-07 10:39:42 +01:00
jf-cbd
69f9a0b369 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-06 16:25:43 +01:00
jf-cbd
25e8ec38d6 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-06 15:31:19 +01:00
Stephen Abello
1574993a28 N°4685 - Update precompiled stylesheets 2025-03-06 10:35:51 +01:00
Stephen Abello
43120bfb60 N°4685 - Make user card display nicer when user's name is short 2025-03-06 10:31:11 +01:00
Stephen Abello
9c1a1d08a1 N°4685 - Fix navigation menu hover having the same color as regular background 2025-03-06 10:30:53 +01:00
Stephen Abello
f095f93326 N°4684 - Align portal default theme with backoffice one (#702)
* Prepare SCSS files and move nav menu / main wrapper from Bootstrap positioning

* Small work on navigation menu

* Split bootstrap theme file into multiple files inside themes/

* Fix unit test missing css/ import path

* Better display for usercard

* Upload precompiled portal stylesheets to fix unit test based on portal.css

* Polish menu

* Stylize home tiles

* Stylize home tiles and layout pages

* Stylize home tiles and layout pages

* Stylize home tiles and layout pages

* Stylize home tiles and layout pages

* Define default font in a more elegant way

* Small implementation for open/close navigation_menu

* Fix navigation menu dropdown menu not working

* Fix menu colors

* Set  <html> lang attribute

* Add accessibility attributes to menu toggler

* Fix bricks / page title dot spacing

* new look adaptation

* Fix padding in manage brick

* Fix menu entries font size and color

* Change manage export color

* Fix icon size in tiles

* Add style to manage brick panels

* Redesign browse brick mosaic view

* Fix variable name collision

* - Set templates cache in dev mode to 1s
- Implements components classes JS
- Move navigations layouts outside the global layout
- Update tiles

* Fix tile description font size

* Redesign browse brick tree mode

* Tweak navigation menu css

* - use custom elements for js components
- adjust layouts

* Modify forms/modals

* Modify method name following code review

* Add a dropdown element to replace bootstrap one

* improvement to dropdown

* datatable prevent column sort icon to wrap

* update composer json file.
Without classmap-authoritative flag, classmap are not generated
There is no test folder

* remove colored circle in manage brick tile titles

* remove white span between title and title additional part in brick layout

* convert navigation menu js to custom element

* navigation menu (WIP)

* Improvement to dropdown

* Fix some caselog classes

* Improvement to dropdown

* Improvement to dropdown

* navigation menu (WIP)

* portal ui version  2025

* datatable sort icon issue on link sets

* portal ui settings

* Fix dropdown for browse brick

* add portal scss colors

* add alerts scss=

* Buttons improvement

* Correction list table action issue

* responsive adjustments

* restore ben-j erased stephen

* ipb-button integration

* remove table header bottom border

* remove brick page ipb-page--main-header duplicate

* Adjust button styel

* Fix browse brick buttons

* Correctly overload approot and fix scsss imports

* Fix treeview expand buttons, fix mosaic first display glitch and add animation to each mosaic tile drawn

* Fix treeview toolbar

* remove wrap from ipb-button-groups

* Fix hover and clickable space in mosaics

* Clean dropdown css

* Fix dropdown menu content for a better display

* Align pagination buttons with theme buttons

* Align pagination buttons with theme buttons

* Fix drowdown

* Add precompiled stylesheets for merge to main branch

---------

Co-authored-by: Benjamin Dalsass <95754414+bdalsass@users.noreply.github.com>
2025-03-05 14:31:00 +01:00
Eric Espie
c9c3b6c108 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-05 11:15:54 +01:00
jf-cbd
5caddf81b8 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-03 17:08:14 +01:00
jf-cbd
73fe07a745 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-03 14:38:35 +01:00
jf-cbd
1760727879 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-02-25 11:40:02 +01:00
jf-cbd
d982652228 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-02-25 09:22:04 +01:00
Timothee
1d26cac8e3 Fix translations 2025-02-21 18:23:31 +01:00
Timothee
cc47d27fd8 Merge branch 'support/3.2' into develop
# Conflicts:
#	datamodels/2.x/itop-attachments/dictionaries/cs.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/da.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/de.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/es_cr.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/fr.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/hu.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/it.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/ja.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/nl.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/pl.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/pt_br.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/ru.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/sk.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/tr.dict.itop-attachments.php
#	datamodels/2.x/itop-attachments/dictionaries/zh_cn.dict.itop-attachments.php
#	datamodels/2.x/itop-config-mgmt/dictionaries/it.dict.itop-config-mgmt.php
#	datamodels/2.x/itop-config/dictionaries/it.dict.itop-config.php
#	datamodels/2.x/itop-incident-mgmt-itil/dictionaries/it.dict.itop-incident-mgmt-itil.php
#	datamodels/2.x/itop-knownerror-mgmt/dictionaries/it.dict.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-portal/dictionaries/it.dict.itop-portal.php
#	datamodels/2.x/itop-problem-mgmt/dictionaries/it.dict.itop-problem-mgmt.php
#	datamodels/2.x/itop-request-mgmt-itil/dictionaries/it.dict.itop-request-mgmt-itil.php
#	datamodels/2.x/itop-request-mgmt/dictionaries/it.dict.itop-request-mgmt.php
#	dictionaries/cs.dictionary.itop.core.php
#	dictionaries/da.dictionary.itop.core.php
#	dictionaries/de.dictionary.itop.core.php
#	dictionaries/es_cr.dictionary.itop.core.php
#	dictionaries/fr.dictionary.itop.core.php
#	dictionaries/fr.dictionary.itop.ui.php
#	dictionaries/hu.dictionary.itop.core.php
#	dictionaries/it.dictionary.itop.core.php
#	dictionaries/it.dictionary.itop.ui.php
#	dictionaries/ja.dictionary.itop.core.php
#	dictionaries/nl.dictionary.itop.core.php
#	dictionaries/pl.dictionary.itop.core.php
#	dictionaries/pt_br.dictionary.itop.core.php
#	dictionaries/ru.dictionary.itop.core.php
#	dictionaries/sk.dictionary.itop.core.php
#	dictionaries/tr.dictionary.itop.core.php
#	dictionaries/ui/components/quick-create/cs.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/da.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/de.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/es_cr.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/fr.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/hu.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/it.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/ja.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/nl.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/pl.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/pt_br.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/ru.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/sk.dictionary.itop.quick-create.php
#	dictionaries/ui/components/quick-create/tr.dictionary.itop.quick-create.php
2025-02-21 17:58:13 +01:00
jf-cbd
1e5334ab2b Update comment on logout.html.twig 2025-02-11 09:43:33 +01:00
Anne-Cath
05419f3d7f N°7216 import improves error handling missing or null data - fix test 2025-02-07 22:59:59 +01:00
jf-cbd
534b087a2c N°8163 - Increase page redirection timeout on logout 2025-02-07 14:36:01 +01:00
denis.flaven@combodo.com
e85ec6bb47 Merge branch 'support/3.2' into develop 2025-02-07 10:36:32 +01:00
Anne-Cath
533fe0ae01 N°7216 import improves error handling missing or null data - case if an ext key use more than 1 field for reconciliation add test 2025-02-06 17:43:18 +01:00
Anne-Cath
efd117eac7 N°7216 import improves error handling missing or null data - case if an ext key use more than 1 field for reconciliation 2025-02-06 17:28:47 +01:00
jf-cbd
01a17b5f9b Merge branch 'support/3.2' into develop 2025-02-06 17:13:58 +01:00
Ben
92d49c6c47 Adding new modules 2025-02-04 11:56:57 +01:00
jf-cbd
623d2823ff Fix merge conflict 2025-02-04 11:29:19 +01:00
jf-cbd
5d5849b724 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php
2025-02-04 10:52:18 +01:00
XGUI
902e2259a9 N°8129 - Remove duplicated test method 2025-02-04 10:33:35 +01:00
XGUI
b87fb65ac4 Merge branch 'support/3.2' into develop
# Conflicts:
#	core/attributedef.class.inc.php
#	datamodels/2.x/version.xml
#	tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
#	tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php
2025-02-04 10:14:41 +01:00
Tommaso Rossi
ab929571c7 🐛 N°8115 - Unattended Install: unable to connect to MySQL with TLS (#694)
🐛 Support TLS connections to MySQL in unattended-install process
2025-01-31 14:45:52 +01:00
Anne-Catherine
8e0e01ad40 N°7216 import improves error handling missing or null data (#612)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2025-01-30 16:14:14 +01:00
Anne-Catherine
8a604c643e N°7371 - Remembers the choice done in the popup that appears when saving public and private logs at the same time (#636) 2025-01-30 15:55:34 +01:00
XGUI
f1594ad974 Merge remote-tracking branch 'origin/develop' into develop 2025-01-29 15:58:06 +01:00
XGUI
805e208e32 Merge branch 'issue/8129-dont_crash_if_datetime_default_value_has_bad_format' into develop 2025-01-29 15:56:50 +01:00
XGUI
9e3f99a150 N°8129 - Dont crash if date/time default value has a bad format 2025-01-29 15:55:20 +01:00
XGUI
e9d21bca39 N°8129 Handle badly formatted default date (e.g. "27/01/2025") 2025-01-29 15:35:26 +01:00
XGUI
807283505d N°8129 - Dont crash if date/time default value has a bad format 2025-01-29 11:08:21 +01:00
Eric Espie
71244e5c15 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-29 09:37:10 +01:00
Eric Espie
72e0750c1b Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-28 11:13:05 +01:00
jf-cbd
ac8004561b Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-28 10:53:15 +01:00
Eric Espie
766d3b51ad Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-24 14:36:14 +01:00
Eric Espie
3215bffbcb Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-24 12:07:13 +01:00
Eric Espie
51bb0add8e Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-22 17:11:13 +01:00
jf-cbd
4c8392b332 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-21 17:43:35 +01:00
jf-cbd
fb180e8370 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-21 17:03:52 +01:00
jf-cbd
2dd1224219 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-21 13:50:19 +01:00
jf-cbd
e7b87128b1 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-16 17:18:02 +01:00
odain
d0bdde30ad Merge branch 'support/3.2' into develop 2025-01-14 08:34:41 +01:00
Benjamin Dalsass
3fe8b6c696 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-13 15:01:55 +01:00
Tommaso Rossi
6539687f16 🌐 Italian translation enhancements (#697) 2025-01-13 12:07:33 +01:00
Eric Espie
e0b12144cb Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanel.php
2025-01-13 09:18:00 +01:00
Eric Espie
79a46581ef Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php
2025-01-07 13:31:49 +01:00
jf-cbd
5a59d16c99 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-02 09:34:32 +01:00
odain
a63a3d3d9c Merge branch 'support/3.2' into develop 2024-12-27 11:14:21 +01:00
odain
ed6e4f612a Merge branch 'support/3.2' into develop 2024-12-27 09:24:49 +01:00
Eric Espie
16279233e0 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-26 14:54:14 +01:00
Stephen Abello
07964cc404 Merge branch 'support/3.2' into develop 2024-12-20 10:16:11 +01:00
Stephen Abello
ea5473ad77 Merge branch 'support/3.2' into develop 2024-12-19 15:16:51 +01:00
Tommaso Rossi
2a888cf5af 🌐 Update IT IT dictionaries (#693) 2024-12-19 14:13:13 +01:00
Stephen Abello
548131482a Merge branch 'support/3.2' into develop 2024-12-18 11:10:43 +01:00
Stephen Abello
5ac6c84813 N°8031 - Make all portal bricks use custom templates for all templates (#691)
* N°8031 - Make all portal bricks use custom templates for all templates

* Rename parameter following code review

* Add const variables following code review

* Modify method name following code review
2024-12-18 11:03:52 +01:00
jf-cbd
0c3a35fc43 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-18 10:49:22 +01:00
jf-cbd
881dbd3c01 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-18 10:12:13 +01:00
jf-cbd
81887f480a 🌐 Update ZH CN dictionaries 2024-12-18 10:08:55 +01:00
odain
d25bf4ef66 Merge branch 'support/3.2' into develop 2024-12-17 17:32:17 +01:00
jf-cbd
90f58721b1 🌐 Update ZH CN dictionaries 2024-12-17 17:21:55 +01:00
Eric Espie
b20b4b7e82 Revert GetDataPath() usage 2024-12-17 15:53:57 +01:00
jf-cbd
eeabad895d 🌐 Update EN dic 2024-12-16 18:48:48 +01:00
jf-cbd
9fdf183851 Merge branch 'support/3.2' into develop
# Conflicts:
#	dictionaries/ui/components/quick-create/zh_cn.dictionary.itop.quick-create.php
#	dictionaries/zh_cn.dictionary.itop.core.php
#	setup/runtimeenv.class.inc.php
2024-12-16 18:38:07 +01:00
jf-cbd
96414dcc98 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-16 11:07:32 +01:00
Anne-Cath
6ab19d29b9 fix tests in all iTop configurations 2024-12-16 10:38:44 +01:00
Eric Espie
5c5c5d769f Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-13 10:17:40 +01:00
Anne-Cath
ecce0a3376 fix tests 2024-12-13 09:20:19 +01:00
Anne-Cath
f8e761abe0 fix tests 2024-12-12 11:45:09 +01:00
Eric Espie
d3a9e30178 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-12 09:55:58 +01:00
Eric Espie
0fd2cf85a2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-12 08:44:38 +01:00
Anne-Cath
a64fed66a3 N°1681 - Add/fix @since 2024-12-10 09:48:25 +01:00
Anne-Catherine
261106fa9d N°1681 - Add new triggers for attachment creation and removal (#534) 2024-12-10 09:33:20 +01:00
Eric Espie
1556b95653 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-09 17:06:40 +01:00
Anne-Catherine
324cb5eb6c N°7636 - Too many OQL requests executed in order to display a lnk (#661) 2024-12-09 15:15:33 +01:00
Timmy38
eedbf3d266 N°6617 Fix issue when providing invalid dashboard layout class (#689)
N°6617 Fix issue when providing invalid dashboard layout class
2024-12-09 14:10:03 +01:00
Eric Espie
3b197692ec Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-09 10:40:06 +01:00
Stephen Abello
ecfc26f1ec Merge branch 'support/3.2' into develop 2024-12-03 10:47:42 +01:00
Stephen Abello
a34baf840a N°7995 - Allow to redefine portal twig template for all bricks in a portal (#686)
* N°7995 - Allow to redefine portal twig template for all bricks in a portal

* Apply modifications from code review

* Fix variable name

* Apply changes from code review
2024-12-03 10:41:25 +01:00
Eric Espie
6f9bd9bae5 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-03 10:31:35 +01:00
XGUI
c32b2f9dfe Issue/7984 (#688)
* N°7984 - Change ? for field description (tooltip) by 🛈 in console and portal
2024-12-03 10:20:47 +01:00
jf-cbd
a1860c82fb Merge branch 'support/3.2' into develop 2024-12-02 17:47:10 +01:00
jf-cbd
d47d65df10 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-29 16:49:57 +01:00
XGUI
b42297ad84 Merge branch 'issue/7726' into develop
# Conflicts:
#	core/datamodel.core.xml
2024-11-29 16:28:50 +01:00
XavierGR
6cb1cf7b7e N°7726 - Fatal error if a newsroom is sent without any message 2024-11-29 16:26:32 +01:00
odain
a65dd1c27c Merge branch 'support/3.2' into develop 2024-11-29 12:09:08 +01:00
XGUI
d85d611642 Merge branch 'feature/5874' into develop 2024-11-29 08:38:52 +01:00
XavierGR
6a00786535 N° 5874 - Quick create: improvement for newcomer 2024-11-29 08:37:11 +01:00
XGUI
6490fe93a1 Merge branch 'issue/7746' into develop 2024-11-29 08:24:27 +01:00
xavier.guiboud-ribaud@combodo.com
642a13ad0d N°7984 - Change ? for field description (tooltip) by 🛈 in console and portal 2024-11-29 08:23:40 +01:00
xavier.guiboud-ribaud@combodo.com
e1bfe9a3b6 * N°7746 - Caselog edition button active even if the user has a read-only access to the object 2024-11-29 08:23:32 +01:00
XGUI
af8ff9b29f Issue/7707 (#687)
* N°7707 - Newsroom user preference display counter not changeable
2024-11-28 16:02:35 +01:00
Benjamin Dalsass
fcfdac2844 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-27 09:56:35 +01:00
Romain Quetiez
ce68e270c3 N°7985 Remove OQL grammar ambiguity leading to scary warnings when generating the parser (4 parsing conflicts) 2024-11-21 10:29:45 +01:00
jf-cbd
0d8a20c35e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-19 08:50:29 +01:00
Thomas Casteleyn
1f3780f338 Correctly identify as iTop in cURL requests (#652)
* Correctly identify as iTop in cURL requests (with configuration option)
2024-11-14 15:18:47 +01:00
Eric Espie
85f6195a51 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-14 14:34:05 +01:00
Thomas Casteleyn
7e1b1779a9 ️ Add faster way to rename column on the same table (#676)
* Add faster way to rename column on the same table
2024-11-14 14:24:45 +01:00
Benjamin Dalsass
d95e7168aa Merge branch 'support/3.2' into develop 2024-11-13 13:32:53 +01:00
jf-cbd
a7c22c06af Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-12 09:37:41 +01:00
denis.flaven@combodo.com
a72d1ca1b3 🔨 Replace gitmojis by their UTF-8 equivalent in output. 2024-11-08 16:08:06 +01:00
Stephen Abello
be5e4458ba N°7793 Add breaking changes introduced by adding common SCSS variables between backoffice and end-user portal (#675)
* N°7793 Add breaking changes induce by adding common SCSS variables between backoffice and end-user portal

* N°7793 Handle breaking changes in darkmoon theme
2024-11-08 10:04:56 +01:00
Stephen Abello
317cd585b2 Merge branch 'support/3.2' into develop 2024-11-08 09:45:05 +01:00
jf-cbd
5d8db176f4 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	dictionaries/es_cr.dictionary.itop.core.php
2024-11-07 14:57:54 +01:00
Stephen Abello
c6039f4b51 Merge branch 'support/3.2' into develop 2024-11-06 09:57:03 +01:00
Stephen Abello
d0f9e57bf1 Merge branch 'support/3.2' into develop 2024-11-04 14:40:52 +01:00
jf-cbd
385c60e993 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-10-31 09:41:38 +01:00
Eric Espie
58c68bade9 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-10-29 11:18:45 +01:00
Anne-Cath
eb992c7b45 N°7915 - declaration of DisplayBareProperties function in DocumentFile class has wrong id 2024-10-25 15:40:43 +02:00
Anne-Catherine
0688405f86 N°7348 - Enable to param maximum depth of impact analysis in function Ticket::UpdateImpactedItems (#633) 2024-10-25 15:29:09 +02:00
jf-cbd
dd34fda42e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-10-23 17:56:09 +02:00
jf-cbd
6becd73ac2 Update tests to be minimal and removed hard-coded ITOP_DESIGN_LATEST_VERSION VERSION 2024-10-22 11:47:25 +02:00
jf-cbd
72d6e251b8 🔖 Update tests for XML 3.3.0 version 2024-10-21 18:39:39 +02:00
jf-cbd
9491c9102c 🔖 Update tests for XML 3.3.0 version 2024-10-21 18:28:50 +02:00
jf-cbd
a728cf312d 🔖 Update XML 3.3.0 version 2024-10-21 18:21:37 +02:00
jf-cbd
e321e27899 🔖 Prepare 3.3.0 version 2024-10-21 18:07:54 +02:00
jf-cbd
96e8467e13 Temporary rollback : waiting for datamodel upgrade 2024-10-21 18:01:58 +02:00
jf-cbd
508918a684 Temporary rollback : waiting for datamodel upgrade 2024-10-21 17:56:43 +02:00
jf-cbd
8adef26d18 🔖 Prepare 3.3.0 version 2024-10-21 17:36:45 +02:00
jf-cbd
2d45abd12b 🔖 Prepare 3.3.0 version 2024-10-21 17:34:30 +02:00
jf-cbd
bd5e55aad9 🔖 Prepare 3.3.0 version 2024-10-21 17:26:15 +02:00
Eric Espie
b57e4fce07 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-10-14 09:27:25 +02:00
jf-cbd
b460705831 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	.doc/itop-version-history.md
2024-09-30 11:46:20 +02:00
Eric Espie
58c47f4c0a Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-26 17:41:05 +02:00
Anne-Catherine
f3a6b064c8 N°824 - Allow OQL JOIN on object ON EventNotification (#642) 2024-09-19 08:58:27 +02:00
Anne-Cath
5e6fb33ed7 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-19 08:11:56 +02:00
Anne-Cath
5e7137e0c4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-19 07:51:37 +02:00
BenGrenoble
4cf5e47ec3 N°7796 - itop-ticket and itop-bridge-cmdb-ticket not coherents 2024-09-18 16:06:06 +02:00
Anne-Cath
143a59a19d Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-18 11:59:16 +02:00
Eric Espie
61b247b156 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-11 17:34:34 +02:00
Molkobain
c1aa013053 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-09-06 11:59:46 +02:00
Benjamin Dalsass
a3f9eed6e2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-08-20 16:55:11 +02:00
jf-cbd
21c9332a7f Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-08-07 18:01:38 +02:00
Benjamin Dalsass
ae6e0a08ea Merge remote-tracking branch 'origin/support/3.2' into develop 2024-08-07 08:33:27 +02:00
Benjamin Dalsass
d9d2e851f4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-08-07 07:57:33 +02:00
Molkobain
91c63cb12e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-08-05 17:28:36 +02:00
Molkobain
4ff354dd41 Update itop-version-history.md 2024-07-29 10:04:48 +02:00
Molkobain
bd8c325306 📝 Fix version history 2024-07-29 10:02:08 +02:00
Molkobain
9902cedc06 📝 Update version history 2024-07-29 09:56:52 +02:00
Molkobain
b64ee96636 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-29 09:56:15 +02:00
Molkobain
8c1ff2dc1c Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-25 10:53:55 +02:00
Molkobain
f2ab409c9c Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-25 08:32:28 +02:00
Molkobain
db46763e13 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-24 11:02:36 +02:00
Molkobain
7ee1af3cc8 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-24 10:58:05 +02:00
Timothee
32b371eac1 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-16 09:57:16 +02:00
Benjamin Dalsass
f65cadd24c Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-15 10:59:01 +02:00
jf-cbd
40551b36e5 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-07-12 10:40:09 +02:00
Molkobain
c0056e75d0 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-10 11:39:14 +02:00
jf-cbd
e5825b5fcd Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-07-05 14:06:00 +02:00
Benjamin Dalsass
d3dc59c5da Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-05 09:25:53 +02:00
Molkobain
642a097b4b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-05 00:19:17 +02:00
jf-cbd
1c615c42b6 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-07-04 13:56:53 +02:00
jf-cbd
b1f708dcad Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-07-04 11:01:53 +02:00
Benjamin Dalsass
55f202b7cb Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-04 07:57:38 +02:00
jf-cbd
247f1045fe Merge branch 'refs/heads/support/3.2' into develop 2024-07-03 15:52:49 +02:00
jf-cbd
42e78ad3a3 Merge branch 'refs/heads/support/3.2' into develop 2024-07-02 17:21:43 +02:00
odain
113826b2e7 Merge branch 'support/3.2' into develop 2024-07-02 17:13:30 +02:00
odain
7fe8da8590 Merge branch 'support/3.2' into develop 2024-07-02 14:10:54 +02:00
Eric Espie
821251a53f Merge remote-tracking branch 'origin/support/3.2' into develop 2024-07-02 10:43:23 +02:00
Molkobain
5334bbb303 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	.doc/itop-version-history.md
2024-06-28 15:08:31 +02:00
Eric Espie
012d5e7ae0 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-24 14:36:53 +02:00
Eric Espie
03f4e9f621 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-20 11:08:59 +02:00
Romain Quetiez
055968bea9 Update README.md 2024-06-17 14:40:31 +02:00
Romain Quetiez
d0457b73ec Merge branch 'refs/heads/support/3.2' into develop 2024-06-13 18:52:40 +02:00
jf-cbd
7e8ff50886 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop
# Conflicts:
#	js/ckeditor/src/plugins/maximize/maximize.plugin.ts
2024-06-13 17:53:06 +02:00
Eric Espie
36a6ee4fc9 Merge remote-tracking branch 'origin/feature/3.2-post-beta' into develop 2024-06-12 16:50:02 +02:00
Benjamin Dalsass
db8b00e8df Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-10 16:15:20 +02:00
Benjamin Dalsass
5d31c372fa Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-10 10:08:11 +02:00
Benjamin Dalsass
0497122e25 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-07 08:55:30 +02:00
Benjamin Dalsass
645d68d5d0 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-07 08:20:40 +02:00
Romain Quetiez
f04b8368aa List explicitely the modules when finding inconsistencies in installation.xml 2024-06-04 21:58:18 +02:00
vdumas
f9fd4f1e2a N°6303 - Add search ticket bricks in portal 2024-06-04 21:58:18 +02:00
Benjamin Dalsass
55ed552ba7 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-04 10:59:39 +02:00
Benjamin Dalsass
7bfa23fab7 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-06-03 15:51:14 +02:00
Eric Espie
7bd427b4e7 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-30 12:08:40 +02:00
Benjamin Dalsass
a9a9fb1da2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-30 09:21:58 +02:00
Eric Espie
6653b13144 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-29 18:21:06 +02:00
Benjamin Dalsass
8bea29f0e7 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-28 16:07:36 +02:00
Benjamin Dalsass
d556564ee1 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-28 08:31:18 +02:00
Benjamin Dalsass
2286a9e2a4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-28 08:17:19 +02:00
Molkobain
30c10cb67f Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-24 23:58:32 +02:00
Benjamin Dalsass
74a42a4d4f Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-24 16:14:44 +02:00
Eric Espie
c31443cb79 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-24 10:18:48 +02:00
Eric Espie
a698aec7a5 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-21 15:08:32 +02:00
Eric Espie
04d2aaf05c Merge remote-tracking branch 'origin/support/3.2' into develop 2024-05-21 14:30:30 +02:00
jf-cbd
5103f898e1 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-05-17 11:23:08 +02:00
Romain Quetiez
68ee3231f4 Merge branch 'support/3.2' into develop
# Conflicts:
#	tests/php-unit-tests/src/Hook/TestsRunStartHook.php
2024-05-16 20:24:38 +02:00
jf-cbd
62a7850a0b Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-04-30 15:12:21 +02:00
jf-cbd
20f1ec42b1 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-04-30 10:58:35 +02:00
jf-cbd
e51e55b634 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop
# Conflicts:
#	pages/ajax.render.php
2024-04-30 08:18:57 +02:00
Benjamin Dalsass
bc7db973ad Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-25 09:17:33 +02:00
jf-cbd
0489103e11 Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-04-24 17:13:36 +02:00
Eric Espie
b99249d2d2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-24 16:11:58 +02:00
jf-cbd
23aed5415c Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop 2024-04-23 15:24:52 +02:00
jf-cbd
2adbcf5e6f Merge remote-tracking branch 'refs/remotes/origin/support/3.2' into develop
# Conflicts:
#	pages/ajax.render.php
2024-04-19 15:37:52 +02:00
jf-cbd
6a99e3c1c9 Revert "Merge branch 'refs/heads/support/3.2' into develop"
This reverts commit 8e1de5bf2d, reversing
changes made to f6808ee522.
2024-04-19 15:34:56 +02:00
jf-cbd
8e1de5bf2d Merge branch 'refs/heads/support/3.2' into develop 2024-04-19 11:28:55 +02:00
Molkobain
f6808ee522 Fix typo in README.md 2024-04-19 11:22:33 +02:00
Molkobain
4f650d3c5b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-19 09:26:10 +02:00
Molkobain
ba641d96d5 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-18 18:51:05 +02:00
Molkobain
3dc514c67d Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-18 18:19:52 +02:00
Molkobain
5df7c58b1b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-18 17:03:24 +02:00
Benjamin Dalsass
bb680ac514 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-17 16:05:56 +02:00
Stephen Abello
e18018cacd Merge branch 'support/3.2' into develop 2024-04-16 09:22:58 +02:00
odain
5d91c8832b Merge branch 'support/3.2' into develop 2024-04-15 10:25:01 +02:00
odain
c96c8ac30d Merge branch 'support/3.2' into develop 2024-04-12 17:19:45 +02:00
Molkobain
f930533d8b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-12 11:08:59 +02:00
odain
29bfb8a8bf Merge branch 'support/3.2' into develop 2024-04-11 18:56:02 +02:00
Molkobain
f04359f398 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-11 17:04:13 +02:00
odain
c24052e976 Merge branch 'support/3.2' into develop 2024-04-10 15:35:17 +02:00
odain
5f8e43fc67 Merge branch 'support/3.2' into develop 2024-04-10 14:26:43 +02:00
jf-cbd
5427b146cf Merge branch 'refs/heads/support/3.2' into develop 2024-04-10 10:36:40 +02:00
odain
6f231ce800 Merge branch 'support/3.2' into develop 2024-04-09 21:37:20 +02:00
odain
d66d1c8739 Merge branch 'support/3.2' into develop 2024-04-09 11:07:21 +02:00
odain
50b4388b8d Merge branch 'support/3.2' into develop 2024-04-09 11:02:32 +02:00
odain
9cc8b75ffb Merge branch 'support/3.2' into develop
# Conflicts:
#	setup/applicationinstaller.class.inc.php
2024-04-09 10:13:45 +02:00
jf-cbd
e715342f7a Merge branch 'refs/heads/support/3.2' into develop 2024-04-08 17:26:40 +02:00
jf-cbd
c86ac4f9a7 Merge branch 'refs/heads/support/3.2' into develop 2024-04-08 17:13:34 +02:00
Molkobain
b79fe06be4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-08 15:14:30 +02:00
jf-cbd
e5764ac495 Merge branch 'refs/heads/support/3.2' into develop 2024-04-08 14:14:31 +02:00
Molkobain
2ff7cb8956 Add Vincenzo Katriel Giuva (@DarkNight97boss) to the contributors list! 🙌 2024-04-05 16:18:52 +02:00
jf-cbd
3064ab4b25 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-05 15:01:41 +02:00
Molkobain
d2f8d2e903 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-04 15:22:25 +02:00
odain
036c7796e5 Merge branch 'support/3.2' into develop 2024-04-02 15:08:29 +02:00
Molkobain
356dd46537 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-02 10:40:57 +02:00
Molkobain
bb30e1abb8 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-04-02 10:29:30 +02:00
Stephen Abello
84d225e389 Merge branch 'support/3.2' into develop 2024-03-29 11:20:07 +01:00
Eric Espie
dcf2780cac Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-28 13:33:04 +01:00
Eric Espie
3e421c770b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-27 11:30:02 +01:00
Anne-Cath
19cb0e873a Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-26 11:41:26 +01:00
Molkobain
ed81dbc4a2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-21 17:43:41 +01:00
Eric Espie
a93d5b87e1 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-19 17:16:35 +01:00
Molkobain
d40a52e403 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-19 14:55:15 +01:00
Eric Espie
a4a3797cc1 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-19 14:07:55 +01:00
Pierre Goiffon
bd29e5f13a Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-18 18:20:19 +01:00
Pierre Goiffon
ce13ee8a55 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-18 18:17:20 +01:00
Pierre Goiffon
e5ed5fbc6a Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-14 17:28:11 +01:00
jf-cbd
ff7eca2f08 Merge branch 'support/3.2' into develop
# Conflicts:
#	lib/composer/installed.php
2024-03-14 17:17:55 +01:00
Pierre Goiffon
06be217030 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-13 10:08:40 +01:00
Pierre Goiffon
4880052559 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-13 09:28:07 +01:00
Pierre Goiffon
147043857b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-12 18:39:44 +01:00
Pierre Goiffon
1bfa1a7746 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-12 17:44:49 +01:00
Benjamin Dalsass
3747a6a454 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-12 09:48:37 +01:00
Pierre Goiffon
f1e6246962 N°7299 Remove moment.js (moved to NPM) 2024-03-11 16:56:41 +01:00
Pierre Goiffon
d2c6190b59 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-11 16:40:49 +01:00
Pierre Goiffon
0f8247ce69 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-11 16:32:03 +01:00
Benjamin Dalsass
dae3be99ce Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-11 16:05:34 +01:00
Pierre Goiffon
6e625e0cc9 N°7329 remove js/jquery.autocomplete.js 2024-03-08 16:19:29 +01:00
Pierre Goiffon
a602101695 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	js/jquery-ui-1.11.4.custom.min.js
#	js/jquery-ui.custom.min.js
2024-03-08 16:16:18 +01:00
Pierre Goiffon
48d86fdbf5 N°4797 Remove js/jquery-ui-1.11.4.custom.min.js
File was deprecated in 3.0.0 with N°3184
Use instead JQuery lib in NPM (since 3.2.0 N°5621)
2024-03-08 12:47:14 +01:00
Pierre Goiffon
d6cfde0f94 N°7299 Remove jquery-migrate (moved to NPM) 2024-03-07 15:33:07 +01:00
Pierre Goiffon
1b9b4fdd39 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-07 15:28:27 +01:00
Benjamin Dalsass
8bb551eb10 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-07 14:34:20 +01:00
Molkobain
6177035f84 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-07 13:26:29 +01:00
Pierre Goiffon
e6d3ce5918 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-07 11:12:39 +01:00
Molkobain
9e08143981 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-06 14:47:29 +01:00
Pierre Goiffon
2014a48d22 N°7299 Remove CSS & JS files moved to NPM
Migration was made in 3.2 with N°5621
2024-03-04 11:19:59 +01:00
Pierre Goiffon
b7e1202cf1 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-04 10:43:16 +01:00
Pierre Goiffon
44b994414d Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-04 08:42:18 +01:00
Pierre Goiffon
a7265c2493 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-01 17:26:55 +01:00
jf-cbd
261ec270c5 ✏️ fix a typo 2024-03-01 17:24:39 +01:00
Eric Espie
356be511a8 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-03-01 09:44:24 +01:00
Anne-Cath
f896e72013 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-29 16:57:24 +01:00
Benjamin Dalsass
187a895265 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-28 17:16:55 +01:00
Pierre Goiffon
6224f8ca51 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-28 16:44:29 +01:00
Pierre Goiffon
3b27e6e466 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-28 15:13:06 +01:00
Anne-Cath
4e53deec9d Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-28 10:37:15 +01:00
Anne-Cath
2cafa78339 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-27 18:22:22 +01:00
Eric Espie
f3f86017b6 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-27 18:14:28 +01:00
Eric Espie
5479080eb2 Merge remote-tracking branch 'origin/support/3.1' into develop 2024-02-27 17:40:56 +01:00
Benjamin Dalsass
3cb3e8a7f9 N°6937 - Symfony 6.4 - Handle Symfony configuration files 2024-02-26 10:38:36 +01:00
Molkobain
6a907f1fed Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-22 16:08:09 +01:00
Benjamin Dalsass
241f845c08 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-21 10:50:44 +01:00
Benjamin Dalsass
623f63abb3 N°7279 - AttributeClass defined in XML datamodel compilation issue 2024-02-21 09:53:57 +01:00
Pierre Goiffon
293adc3a99 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-20 12:12:51 +01:00
Pierre Goiffon
dee9f90a0b Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-20 09:27:51 +01:00
Pierre Goiffon
a7348f0eb9 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-20 09:13:10 +01:00
Molkobain
7457735c04 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-19 20:24:26 +01:00
Molkobain
0f389b2a48 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-19 10:00:21 +01:00
Stephen Abello
bfe01899a4 N°7243 - Add toast notifications to iTop (#614)
* N°7243 - Add toast notifications to iTop

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update js/pages/backoffice/toolbox.js

* Update js/utils.js

* N°7243 - Move some rules to a dedicated partial and use spacing variables

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-16 10:59:05 +01:00
Pierre Goiffon
9531762c44 N°7252 Remove unused files in /js 2024-02-15 17:23:02 +01:00
Pierre Goiffon
e59a35e804 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-15 17:20:55 +01:00
Pierre Goiffon
21f5f5fe5e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-15 14:53:43 +01:00
Pierre Goiffon
e6483fed98 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-15 11:11:59 +01:00
Pierre Goiffon
98bc04697e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-15 09:51:46 +01:00
Pierre Goiffon
38e9b59b89 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-14 15:17:48 +01:00
Pierre Goiffon
118b22fe56 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-14 15:13:54 +01:00
Pierre Goiffon
8062694331 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-09 13:41:47 +01:00
Pierre Goiffon
e576235307 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-09 12:05:24 +01:00
Pierre Goiffon
e87502e7bf Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-08 11:35:03 +01:00
Molkobain
400ed9e999 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-07 15:05:19 +01:00
Molkobain
5b01ad23c4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-06 21:53:38 +01:00
Pierre Goiffon
9a06fa4704 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-01 16:12:34 +01:00
Pierre Goiffon
c5555ad365 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-02-01 10:30:17 +01:00
Pierre Goiffon
9c6db1d730 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-30 11:47:04 +01:00
Molkobain
30cfe69e26 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-30 09:00:45 +01:00
Pierre Goiffon
e45049a602 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-29 17:20:46 +01:00
Pierre Goiffon
82129ff3bd Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-29 16:31:52 +01:00
Timothee
593b603295 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-29 15:43:33 +01:00
Molkobain
54b2e41afd Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-29 15:07:10 +01:00
Molkobain
ede6e6dd87 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-24 15:22:21 +01:00
Molkobain
e18ea88735 N°6648 - Use \utils::GetDataPath() instead of hard-coded paths (#555)
* N°6648 - Use \utils::GetDataPath() instead of hard-coded paths

* Update setup/applicationinstaller.class.inc.php

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>

---------

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2024-01-22 21:06:08 +01:00
Pierre Goiffon
750dfe746e Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-22 16:19:59 +01:00
Molkobain
53404f1002 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-17 23:06:16 +01:00
jf-cbd
5623784c59 N°7134 - Can't retrieve the list of changes when editing URP_UserProfile 2024-01-17 15:15:11 +01:00
Molkobain
d122de04e4 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-01-16 19:57:16 +01:00
Pierre Goiffon
2fa9774955 📝 Version history: add 2.7.10 and 3.0.4 2024-01-16 18:22:44 +01:00
1895 changed files with 62330 additions and 89209 deletions

View File

@@ -79,6 +79,8 @@ Then, **for a method** of an eligible class:
## Installation
Note : PHP7 is required. Migrating to PHP8 requires some additional work which is questionable as an alternative way to generate a documentation is being considered.
```
cd .doc
composer require phpdocumentor/phpdocumentor:~2 --dev

View File

@@ -23,7 +23,7 @@
$(document).ready(function() {
$("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
$('#viewer img').bind('dragstart', function(event){
$('#viewer img').on('dragstart', function(event){
event.preventDefault();
});
$(window).resize();

View File

@@ -25,7 +25,7 @@ if (false === file_exists($sTcPdfRootFolder)) {
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
return;
}
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/Fonts/';
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/fonts/';
/**

View File

@@ -25,12 +25,34 @@
if (count($argv) === 1) {
echo '⚠ You must pass the base tag/sha1 as parameter';
echo "⚠ You must pass the base tag/sha1 as parameter\n";
exit(1);
}
$sBaseReference = $argv[1];
/**
* Replace the Github emojis codes by their UTF-8 character equivalent
*/
function ReplaceGitmojis(string $sLine)
{
static $aGitmojis = null;
if ($aGitmojis === null) {
$aRawGitmojis = json_decode(trim(file_get_contents(__DIR__.'/gitmojis.json')), true);
if ($aRawGitmojis === false) {
echo "\nFailed to parse ".__DIR__."/gitmojis.json, emoji codes will not be replaced by their unicode equivalent.\n";
} else {
foreach($aRawGitmojis["gitmojis"] as $aGitmoji) {
$aGitmojis[$aGitmoji['code']] = $aGitmoji['emoji'];
}
}
}
if (is_array($aGitmojis)) {
return str_replace(array_keys($aGitmojis), array_values($aGitmojis), $sLine);
}
}
//--- Get log
$sGitLogCommand = 'git log --decorate --pretty="%h;%s" --date-order --no-merges '.$sBaseReference.'..HEAD';
$sGitLogRaw = shell_exec($sGitLogCommand);
@@ -73,5 +95,5 @@ echo "\n";
echo "# Logs line without bug referenced\n";
echo "sha1;subject\n";
foreach ($aLogLineNoBug as $sLogLine) {
echo "$sLogLine\n";
}
echo ReplaceGitmojis($sLogLine)."\n";
}

589
.make/release/gitmojis.json Normal file
View File

@@ -0,0 +1,589 @@
{
"$schema": "https://gitmoji.dev/api/gitmojis/schema",
"gitmojis": [
{
"emoji": "🎨",
"entity": "&#x1f3a8;",
"code": ":art:",
"description": "Improve structure / format of the code.",
"name": "art",
"semver": null
},
{
"emoji": "⚡️",
"entity": "&#x26a1;",
"code": ":zap:",
"description": "Improve performance.",
"name": "zap",
"semver": "patch"
},
{
"emoji": "🔥",
"entity": "&#x1f525;",
"code": ":fire:",
"description": "Remove code or files.",
"name": "fire",
"semver": null
},
{
"emoji": "🐛",
"entity": "&#x1f41b;",
"code": ":bug:",
"description": "Fix a bug.",
"name": "bug",
"semver": "patch"
},
{
"emoji": "🚑️",
"entity": "&#128657;",
"code": ":ambulance:",
"description": "Critical hotfix.",
"name": "ambulance",
"semver": "patch"
},
{
"emoji": "✨",
"entity": "&#x2728;",
"code": ":sparkles:",
"description": "Introduce new features.",
"name": "sparkles",
"semver": "minor"
},
{
"emoji": "📝",
"entity": "&#x1f4dd;",
"code": ":memo:",
"description": "Add or update documentation.",
"name": "memo",
"semver": null
},
{
"emoji": "🚀",
"entity": "&#x1f680;",
"code": ":rocket:",
"description": "Deploy stuff.",
"name": "rocket",
"semver": null
},
{
"emoji": "💄",
"entity": "&#ff99cc;",
"code": ":lipstick:",
"description": "Add or update the UI and style files.",
"name": "lipstick",
"semver": "patch"
},
{
"emoji": "🎉",
"entity": "&#127881;",
"code": ":tada:",
"description": "Begin a project.",
"name": "tada",
"semver": null
},
{
"emoji": "✅",
"entity": "&#x2705;",
"code": ":white_check_mark:",
"description": "Add, update, or pass tests.",
"name": "white-check-mark",
"semver": null
},
{
"emoji": "🔒️",
"entity": "&#x1f512;",
"code": ":lock:",
"description": "Fix security or privacy issues.",
"name": "lock",
"semver": "patch"
},
{
"emoji": "🔐",
"entity": "&#x1f510;",
"code": ":closed_lock_with_key:",
"description": "Add or update secrets.",
"name": "closed-lock-with-key",
"semver": null
},
{
"emoji": "🔖",
"entity": "&#x1f516;",
"code": ":bookmark:",
"description": "Release / Version tags.",
"name": "bookmark",
"semver": null
},
{
"emoji": "🚨",
"entity": "&#x1f6a8;",
"code": ":rotating_light:",
"description": "Fix compiler / linter warnings.",
"name": "rotating-light",
"semver": null
},
{
"emoji": "🚧",
"entity": "&#x1f6a7;",
"code": ":construction:",
"description": "Work in progress.",
"name": "construction",
"semver": null
},
{
"emoji": "💚",
"entity": "&#x1f49a;",
"code": ":green_heart:",
"description": "Fix CI Build.",
"name": "green-heart",
"semver": null
},
{
"emoji": "⬇️",
"entity": "⬇️",
"code": ":arrow_down:",
"description": "Downgrade dependencies.",
"name": "arrow-down",
"semver": "patch"
},
{
"emoji": "⬆️",
"entity": "⬆️",
"code": ":arrow_up:",
"description": "Upgrade dependencies.",
"name": "arrow-up",
"semver": "patch"
},
{
"emoji": "📌",
"entity": "&#x1F4CC;",
"code": ":pushpin:",
"description": "Pin dependencies to specific versions.",
"name": "pushpin",
"semver": "patch"
},
{
"emoji": "👷",
"entity": "&#x1f477;",
"code": ":construction_worker:",
"description": "Add or update CI build system.",
"name": "construction-worker",
"semver": null
},
{
"emoji": "📈",
"entity": "&#x1F4C8;",
"code": ":chart_with_upwards_trend:",
"description": "Add or update analytics or track code.",
"name": "chart-with-upwards-trend",
"semver": "patch"
},
{
"emoji": "♻️",
"entity": "&#x267b;",
"code": ":recycle:",
"description": "Refactor code.",
"name": "recycle",
"semver": null
},
{
"emoji": "",
"entity": "&#10133;",
"code": ":heavy_plus_sign:",
"description": "Add a dependency.",
"name": "heavy-plus-sign",
"semver": "patch"
},
{
"emoji": "",
"entity": "&#10134;",
"code": ":heavy_minus_sign:",
"description": "Remove a dependency.",
"name": "heavy-minus-sign",
"semver": "patch"
},
{
"emoji": "🔧",
"entity": "&#x1f527;",
"code": ":wrench:",
"description": "Add or update configuration files.",
"name": "wrench",
"semver": "patch"
},
{
"emoji": "🔨",
"entity": "&#128296;",
"code": ":hammer:",
"description": "Add or update development scripts.",
"name": "hammer",
"semver": null
},
{
"emoji": "🌐",
"entity": "&#127760;",
"code": ":globe_with_meridians:",
"description": "Internationalization and localization.",
"name": "globe-with-meridians",
"semver": "patch"
},
{
"emoji": "✏️",
"entity": "&#59161;",
"code": ":pencil2:",
"description": "Fix typos.",
"name": "pencil2",
"semver": "patch"
},
{
"emoji": "💩",
"entity": "&#58613;",
"code": ":poop:",
"description": "Write bad code that needs to be improved.",
"name": "poop",
"semver": null
},
{
"emoji": "⏪️",
"entity": "&#9194;",
"code": ":rewind:",
"description": "Revert changes.",
"name": "rewind",
"semver": "patch"
},
{
"emoji": "🔀",
"entity": "&#128256;",
"code": ":twisted_rightwards_arrows:",
"description": "Merge branches.",
"name": "twisted-rightwards-arrows",
"semver": null
},
{
"emoji": "📦️",
"entity": "&#1F4E6;",
"code": ":package:",
"description": "Add or update compiled files or packages.",
"name": "package",
"semver": "patch"
},
{
"emoji": "👽️",
"entity": "&#1F47D;",
"code": ":alien:",
"description": "Update code due to external API changes.",
"name": "alien",
"semver": "patch"
},
{
"emoji": "🚚",
"entity": "&#1F69A;",
"code": ":truck:",
"description": "Move or rename resources (e.g.: files, paths, routes).",
"name": "truck",
"semver": null
},
{
"emoji": "📄",
"entity": "&#1F4C4;",
"code": ":page_facing_up:",
"description": "Add or update license.",
"name": "page-facing-up",
"semver": null
},
{
"emoji": "💥",
"entity": "&#x1f4a5;",
"code": ":boom:",
"description": "Introduce breaking changes.",
"name": "boom",
"semver": "major"
},
{
"emoji": "🍱",
"entity": "&#1F371",
"code": ":bento:",
"description": "Add or update assets.",
"name": "bento",
"semver": "patch"
},
{
"emoji": "♿️",
"entity": "&#9855;",
"code": ":wheelchair:",
"description": "Improve accessibility.",
"name": "wheelchair",
"semver": "patch"
},
{
"emoji": "💡",
"entity": "&#128161;",
"code": ":bulb:",
"description": "Add or update comments in source code.",
"name": "bulb",
"semver": null
},
{
"emoji": "🍻",
"entity": "&#x1f37b;",
"code": ":beers:",
"description": "Write code drunkenly.",
"name": "beers",
"semver": null
},
{
"emoji": "💬",
"entity": "&#128172;",
"code": ":speech_balloon:",
"description": "Add or update text and literals.",
"name": "speech-balloon",
"semver": "patch"
},
{
"emoji": "🗃️",
"entity": "&#128451;",
"code": ":card_file_box:",
"description": "Perform database related changes.",
"name": "card-file-box",
"semver": "patch"
},
{
"emoji": "🔊",
"entity": "&#128266;",
"code": ":loud_sound:",
"description": "Add or update logs.",
"name": "loud-sound",
"semver": null
},
{
"emoji": "🔇",
"entity": "&#128263;",
"code": ":mute:",
"description": "Remove logs.",
"name": "mute",
"semver": null
},
{
"emoji": "👥",
"entity": "&#128101;",
"code": ":busts_in_silhouette:",
"description": "Add or update contributor(s).",
"name": "busts-in-silhouette",
"semver": null
},
{
"emoji": "🚸",
"entity": "&#128696;",
"code": ":children_crossing:",
"description": "Improve user experience / usability.",
"name": "children-crossing",
"semver": "patch"
},
{
"emoji": "🏗️",
"entity": "&#1f3d7;",
"code": ":building_construction:",
"description": "Make architectural changes.",
"name": "building-construction",
"semver": null
},
{
"emoji": "📱",
"entity": "&#128241;",
"code": ":iphone:",
"description": "Work on responsive design.",
"name": "iphone",
"semver": "patch"
},
{
"emoji": "🤡",
"entity": "&#129313;",
"code": ":clown_face:",
"description": "Mock things.",
"name": "clown-face",
"semver": null
},
{
"emoji": "🥚",
"entity": "&#129370;",
"code": ":egg:",
"description": "Add or update an easter egg.",
"name": "egg",
"semver": "patch"
},
{
"emoji": "🙈",
"entity": "&#8bdfe7;",
"code": ":see_no_evil:",
"description": "Add or update a .gitignore file.",
"name": "see-no-evil",
"semver": null
},
{
"emoji": "📸",
"entity": "&#128248;",
"code": ":camera_flash:",
"description": "Add or update snapshots.",
"name": "camera-flash",
"semver": null
},
{
"emoji": "⚗️",
"entity": "&#x2697;",
"code": ":alembic:",
"description": "Perform experiments.",
"name": "alembic",
"semver": "patch"
},
{
"emoji": "🔍️",
"entity": "&#128269;",
"code": ":mag:",
"description": "Improve SEO.",
"name": "mag",
"semver": "patch"
},
{
"emoji": "🏷️",
"entity": "&#127991;",
"code": ":label:",
"description": "Add or update types.",
"name": "label",
"semver": "patch"
},
{
"emoji": "🌱",
"entity": "&#127793;",
"code": ":seedling:",
"description": "Add or update seed files.",
"name": "seedling",
"semver": null
},
{
"emoji": "🚩",
"entity": "&#x1F6A9;",
"code": ":triangular_flag_on_post:",
"description": "Add, update, or remove feature flags.",
"name": "triangular-flag-on-post",
"semver": "patch"
},
{
"emoji": "🥅",
"entity": "&#x1F945;",
"code": ":goal_net:",
"description": "Catch errors.",
"name": "goal-net",
"semver": "patch"
},
{
"emoji": "💫",
"entity": "&#x1f4ab;",
"code": ":dizzy:",
"description": "Add or update animations and transitions.",
"name": "dizzy",
"semver": "patch"
},
{
"emoji": "🗑️",
"entity": "&#x1F5D1;",
"code": ":wastebasket:",
"description": "Deprecate code that needs to be cleaned up.",
"name": "wastebasket",
"semver": "patch"
},
{
"emoji": "🛂",
"entity": "&#x1F6C2;",
"code": ":passport_control:",
"description": "Work on code related to authorization, roles and permissions.",
"name": "passport-control",
"semver": "patch"
},
{
"emoji": "🩹",
"entity": "&#x1FA79;",
"code": ":adhesive_bandage:",
"description": "Simple fix for a non-critical issue.",
"name": "adhesive-bandage",
"semver": "patch"
},
{
"emoji": "🧐",
"entity": "&#x1F9D0;",
"code": ":monocle_face:",
"description": "Data exploration/inspection.",
"name": "monocle-face",
"semver": null
},
{
"emoji": "⚰️",
"entity": "&#x26B0;",
"code": ":coffin:",
"description": "Remove dead code.",
"name": "coffin",
"semver": null
},
{
"emoji": "🧪",
"entity": "&#x1F9EA;",
"code": ":test_tube:",
"description": "Add a failing test.",
"name": "test-tube",
"semver": null
},
{
"emoji": "👔",
"entity": "&#128084;",
"code": ":necktie:",
"description": "Add or update business logic.",
"name": "necktie",
"semver": "patch"
},
{
"emoji": "🩺",
"entity": "&#x1FA7A;",
"code": ":stethoscope:",
"description": "Add or update healthcheck.",
"name": "stethoscope",
"semver": null
},
{
"emoji": "🧱",
"entity": "&#x1f9f1;",
"code": ":bricks:",
"description": "Infrastructure related changes.",
"name": "bricks",
"semver": null
},
{
"emoji": "🧑‍💻",
"entity": "&#129489;&#8205;&#128187;",
"code": ":technologist:",
"description": "Improve developer experience.",
"name": "technologist",
"semver": null
},
{
"emoji": "💸",
"entity": "&#x1F4B8;",
"code": ":money_with_wings:",
"description": "Add sponsorships or money related infrastructure.",
"name": "money-with-wings",
"semver": null
},
{
"emoji": "🧵",
"entity": "&#x1F9F5;",
"code": ":thread:",
"description": "Add or update code related to multithreading or concurrency.",
"name": "thread",
"semver": null
},
{
"emoji": "🦺",
"entity": "&#x1F9BA;",
"code": ":safety_vest:",
"description": "Add or update code related to validation.",
"name": "safety-vest",
"semver": null
}
]
}

View File

@@ -1,4 +1,4 @@
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
<p align="center"><a href="https://combodo.com" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/images/logos/logo-itop-baseline-light.svg">
<source media="(prefers-color-scheme: light)" srcset="/images/logos/logo-itop-baseline-dark.svg">
@@ -80,7 +80,9 @@ We would like to give a special thank you 🤗 to the people from the community
### Names
- Al Hallak, Amr (a.k.a [@v4yne1](https://github.com/v4yne1))
- Alves, David
- Audon, Florian
- Beck, Pedro
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
- Bilger, Jean-François
@@ -92,19 +94,26 @@ We would like to give a special thank you 🤗 to the people from the community
- Colantoni, Maria Laura
- Couronné, Guy
- Dejin, Bie (a.k.a [@bdejin](https://github.com/bdejin))
- Delicado, Elodie
- Dvořák, Lukáš
- Goethals, Stefan
- Giuva, Vincenzo Katriel (a.k.a [@DarkNight97boss](https://github.com/DarkNight97boss))
- Gumble, David
- Heloir, Arthur
- Janssens, Jelle (a.k.a [@janssensjelle](https://github.com/janssensjelle))
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
- Khamit, Shamil
- Kincel, Martin
- Konečný, Kamil
- Kunin, Vladimir
- Lassiter, Dennis
- Lassiter, Denis (a.k.a [@delassiter](https://github.com/delassiter))
- Lazcano, Federico
- Lucas, Jonathan
- Malik, Remie
- Mantel, Ina
- Martin, Pierre (a.k.a [@Worty](https://github.com/worty-syn))
- Melchiorre, Romain
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
- Mozart de Oliveira, Eduardo (a.k.a [@eduardomozart](https://github.com/eduardomozart))
- Raenker, Martin
@@ -116,10 +125,12 @@ We would like to give a special thank you 🤗 to the people from the community
- Seki, Shoji
- Shilov, Vladimir
- Stetina, Pavel (a.k.a [@Stetinac](https://github.com/Stetinac))
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya-stukalov))
- Tarjányi, Csaba (a.k.a [@tacsaby](https://github.com/tacsaby))
- Toraya, Chairat (a.k.a [@Kyokito1412](https://github.com/Kyokito1412))
- Tulio, Marco
- Turrubiates, Miguel
- Višnjić, Aldin (a.k.a[@viliald](https://github.com/viliald))
- Vlk, Karel (a.k.a [@vlk-charles](https://www.github.com/vlk-charles))
### Aliases
@@ -141,4 +152,6 @@ We would like to give a special thank you 🤗 to the people from the community
- [ITOMIG](https://www.itomig.de/)
- [Pimkie](https://www.pimkie.com/)
- [Super-Visions](https://www.super-visions.com/)
- [Defence Tech Cyber Security - Malware Lab](https://github.com/DefenceTechSecurity)
- Orange Cyberdefense
- MipihSIB

View File

@@ -1,362 +0,0 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsMatrix (User management Module)
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UserRightsMatrixClassGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixclasses",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
}
}
class UserRightsMatrixClassStimulusGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixclassesstimulus",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
}
}
class UserRightsMatrixAttributeGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixattributes",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
}
}
class UserRightsMatrix extends UserRightsAddOnAPI
{
static public $m_aActionCodes = array(
UR_ACTION_READ => 'read',
UR_ACTION_MODIFY => 'modify',
UR_ACTION_DELETE => 'delete',
UR_ACTION_BULK_READ => 'bulk read',
UR_ACTION_BULK_MODIFY => 'bulk modify',
UR_ACTION_BULK_DELETE => 'bulk delete',
);
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
{
// Maybe we should check that no other user with userid == 0 exists
$oUser = new UserLocal();
$oUser->Set('login', $sAdminUser);
$oUser->Set('password', $sAdminPwd);
$oUser->Set('contactid', 1); // one is for root !
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
// Now record the admin user object
$iUserId = $oUser->DBInsertNoReload();
$this->SetupUser($iUserId, true);
return true;
}
public function IsAdministrator($oUser)
{
return ($oUser->GetKey() == 1);
}
public function IsPortalUser($oUser)
{
return ($oUser->GetKey() == 1);
}
// Deprecated - create a new module !
public function Setup()
{
// Users must be added manually
// This procedure will then update the matrix when a new user is found or a new class/attribute appears
$oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT User"));
while ($oUser = $oUserSet->Fetch())
{
$this->SetupUser($oUser->GetKey());
}
return true;
}
protected function SetupUser($iUserId, $bNewUser = false)
{
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory)
{
foreach (MetaModel::GetClasses($sCategory) as $sClass)
{
foreach (self::$m_aActionCodes as $iActionCode => $sAction)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
$oMyClassGrant->Set("userid", $iUserId);
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("action", $sAction);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsertNoReload();
}
}
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
$oMyClassGrant->Set("userid", $iUserId);
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("stimulus", $sStimulusCode);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsertNoReload();
}
}
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
foreach (array('read', 'modify') as $sAction)
{
// Create a new entry
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
$oMyAttGrant->Set("userid", $iUserId);
$oMyAttGrant->Set("class", $sClass);
$oMyAttGrant->Set("attcode", $sAttCode);
$oMyAttGrant->Set("action", $sAction);
$oMyAttGrant->Set("permission", "yes");
$iId = $oMyAttGrant->DBInsertNoReload();
}
}
}
}
}
/*
// Create the "My Bookmarks" menu item (parent_id = 0, rank = 6)
if ($bNewUser)
{
$bAddMenu = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT menuNode WHERE type = 'user' AND parent_id = 0 AND user_id = $iUserId"));
$bAddMenu = ($oSet->Count() < 1);
}
if ($bAddMenu)
{
$oMenu = MetaModel::NewObject('menuNode');
$oMenu->Set('type', 'user');
$oMenu->Set('parent_id', 0); // It's a toplevel entry
$oMenu->Set('rank', 6); // Located just above the Admin Tools section (=7)
$oMenu->Set('name', 'My Bookmarks');
$oMenu->Set('label', 'My Favorite Items');
$oMenu->Set('hyperlink', 'UI.php');
$oMenu->Set('template', '<p></p><p></p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:32px;">My bookmarks</p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:14px;"><i>This section contains my most favorite search results</i></p>');
$oMenu->Set('user_id', $iUserId);
$oMenu->DBInsert();
}
*/
}
public function Init()
{
// Could be loaded in a shared memory (?)
return true;
}
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
{
$oNullFilter = new DBObjectSearch($sClass);
return $oNullFilter;
}
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
{
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
{
return UR_ALLOWED_NO;
}
$sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
{
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
{
return UR_ALLOWED_NO;
}
$sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = '{$oUser->GetKey()}'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
public function FlushPrivileges()
{
}
}
UserRights::SelectModule('UserRightsMatrix');
?>

View File

@@ -1,78 +0,0 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsNull
* User management Module - say Yeah! to everything
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UserRightsNull extends UserRightsAddOnAPI
{
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
{
return true;
}
public function IsAdministrator($oUser)
{
return true;
}
public function IsPortalUser($oUser)
{
return true;
}
public function Init()
{
return true;
}
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
{
$oNullFilter = new DBObjectSearch($sClass);
return $oNullFilter;
}
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
{
return UR_ALLOWED_YES;
}
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
{
return UR_ALLOWED_YES;
}
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
{
return UR_ALLOWED_YES;
}
public function FlushPrivileges()
{
}
}
UserRights::SelectModule('UserRightsNull');
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +0,0 @@
<?php
/**
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2024 Combodo SAS
*/
// cannot notify depreciation for now as this is still load in autoloader
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader');
use Combodo\iTop\Application\WebPage\AjaxPage;
/**
* Class ajax_page
*
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to AjaxPage
*/
class ajax_page extends AjaxPage
{
function __construct($s_title)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead');
parent::__construct($s_title);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
<?php
/**
* Extend this class instead of iApplicationObjectExtension if you don't need to overload all methods
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method
* @package ORMExtensibilityAPI
* @since 2.7.0
*/
abstract class AbstractApplicationObjectExtension implements iApplicationObjectExtension
{
/**
* @inheritDoc
*/
public function OnIsModified($oObject)
{
return false;
}
/**
* @inheritDoc
*/
public function OnCheckToWrite($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function OnCheckToDelete($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function OnDBUpdate($oObject, $oChange = null)
{
}
/**
* @inheritDoc
*/
public function OnDBInsert($oObject, $oChange = null)
{
}
/**
* @inheritDoc
*/
public function OnDBDelete($oObject, $oChange = null)
{
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Extend this class instead of implementing iApplicationUIExtension if you don't need to overload
*
* @api
* @package UIExtensibilityAPI
* @since 2.7.0
*/
abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
{
/**
* @inheritDoc
*/
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
{
}
/**
* @inheritDoc
*/
public function OnFormSubmit($oObject, $sFormPrefix = '')
{
}
/**
* @inheritDoc
*/
public function OnFormCancel($sTempId)
{
}
/**
* @inheritDoc
*/
public function EnumUsedAttributes($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function GetIcon($oObject)
{
return '';
}
/**
* @inheritDoc
*/
public function GetHilightClass($oObject)
{
return HILIGHT_CLASS_NONE;
}
/**
* @inheritDoc
*/
public function EnumAllowedActions(DBObjectSet $oSet)
{
return array();
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Extend this class instead of iPageUIBlockExtension if you don't need to overload all methods
*
* @api
* @package UIBlockExtensibilityAPI
* @since 3.0.0
*/
abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
{
/**
* @inheritDoc
*/
public function GetBannerBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetHeaderBlock()
{
return null;
}
/**
* @inheritDoc
*/
public function GetFooterBlock()
{
return null;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Extend this class instead of implementing iPreferencesExtension if you don't need to overload all methods
*
* @api
* @package PreferencesExtensibilityAPI
* @since 2.7.0
*/
abstract class AbstractPreferencesExtension implements iPreferencesExtension
{
/**
* @inheritDoc
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage)
{
// Do nothing
}
/**
* @inheritDoc
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation)
{
// Do nothing
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Inherit from this class to provide messages to be displayed in the "Welcome Popup"
*
* @api
* @since 3.2.0
*/
abstract class AbstractWelcomePopupExtension implements iWelcomePopupExtension
{
/**
* @inheritDoc
*/
public function GetIconRelPath(): string
{
return \Combodo\iTop\Application\Branding::$aLogoPaths[\Combodo\iTop\Application\Branding::ENUM_LOGO_TYPE_MAIN_LOGO_COMPACT]['default'];
}
/**
* @inheritDoc
*/
public function GetMessages(): array
{
return [];
}
/**
* @inheritDoc
*/
public function AcknowledgeMessage(string $sMessageId): void
{
// No need to process the acknowledgment notice by default
return;
}
}

View File

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

View File

@@ -0,0 +1,13 @@
<?php
/**
* Class for adding an item as a button that runs some JS code
*
* @api
* @package UIExtensibilityAPI
* @since 2.0
*/
class JSButtonItem extends JSPopupMenuItem
{
}

View File

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

View File

@@ -0,0 +1,29 @@
<?php
/**
* Class for adding a separator (horizontal line, not selectable) the output
* will automatically reduce several consecutive separators to just one
*
* @api
* @package UIExtensibilityAPI
* @since 2.0
*/
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
{
static $idx = 0;
/**
* Constructor
* @api
*/
public function __construct()
{
parent::__construct('_separator_' . (self::$idx++), '');
}
/** @ignore */
public function GetMenuItem()
{
return array('label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses);
}
}

View File

@@ -0,0 +1,13 @@
<?php
/**
* Class for adding an item as a button that browses to the given URL
*
* @api
* @package UIExtensibilityAPI
* @since 2.0
*/
class URLButtonItem extends URLPopupMenuItem
{
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Class for adding an item into a popup menu that browses to the given URL
*
* Note: This works only in the backoffice, {@see \URLButtonItem} for the end-user portal
*
* @api
* @package UIExtensibilityAPI
* @since 2.0
*/
class URLPopupMenuItem extends ApplicationPopupMenuItem
{
/** @ignore */
protected $sUrl;
/** @ignore */
protected $sTarget;
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
* @api
*/
public function __construct($sUID, $sLabel, $sUrl, $sTarget = '_top')
{
parent::__construct($sUID, $sLabel);
$this->sUrl = $sUrl;
$this->sTarget = $sTarget;
}
/** @ignore */
public function GetMenuItem()
{
return array('label' => $this->GetLabel(),
'url' => $this->GetUrl(),
'target' => $this->GetTarget(),
'css_classes' => $this->aCssClasses,
'icon_class' => $this->sIconClass,
'tooltip' => $this->sTooltip
);
}
/** @ignore */
public function GetUrl()
{
return $this->sUrl;
}
/** @ignore */
public function GetTarget()
{
return $this->sTarget;
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* Implement this interface to perform specific operations when objects are manipulated
*
* Note that those methods will be called when objects are manipulated, either in a programmatic way
* or through the GUI.
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method. More details on each method PHPDoc.
* @package ORMExtensibilityAPI
*/
interface iApplicationObjectExtension
{
/**
* Invoked to determine whether an object has been modified in memory
*
* The GUI calls this verb to determine the message that will be displayed to the end-user.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* If the extension returns false, then the framework will perform the usual evaluation.
* Otherwise, the answer is definitively "yes, the object has changed".
*
* @param /cmdbAbstractObject $oObject The target object
*
* @return boolean True if something has changed for the target object
* @api
* @deprecated 3.1.0 N°4756 No alternative available, this API was unstable and is abandoned
*/
public function OnIsModified($oObject);
/**
* Invoked to determine whether an object can be written to the database
*
* The GUI calls this verb and reports any issue.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_WRITE event instead
*/
public function OnCheckToWrite($oObject);
/**
* Invoked to determine wether an object can be deleted from the database
*
* The GUI calls this verb and stops the deletion process if any issue is reported.
*
* Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled.
*
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_DELETE event instead
*/
public function OnCheckToDelete($oObject);
/**
* Invoked when an object is updated into the database. The method is called right <b>after</b> the object has been written to the
* database.
*
* Useful methods you can call on $oObject :
*
* * {@see DBObject::ListPreviousValuesForUpdatedAttributes()} : list of changed attributes and their values before the change
* * {@see DBObject::Get()} : for a given attribute the new value that was persisted
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
*
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @api
* @since 2.7.0 N°2293 can access object changes by calling {@see DBObject::ListPreviousValuesForUpdatedAttributes()} on $oObject
*/
public function OnDBUpdate($oObject, $oChange = null);
/**
* Invoked when an object is created into the database
*
* The method is called right <b>after</b> the object has been written to the database.
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @api
*/
public function OnDBInsert($oObject, $oChange = null);
/**
* Invoked when an object is deleted from the database
*
* The method is called right <b>before</b> the object will be deleted from the database.
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_DELETE event instead
* @api
*/
public function OnDBDelete($oObject, $oChange = null);
}

View File

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

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add Dict entries
*
* @see \iTopWebPage::$a_dict_entries
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeDictEntriesExtension
{
/**
* @return array
* @see \iTopWebPage::a_dict_entries
* @api
*/
public function GetDictEntries(): array;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add Dict entries prefixes
*
* @see \iTopWebPage::$a_dict_entries_prefixes
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeDictEntriesPrefixesExtension
{
/**
* @return array
* @see \iTopWebPage::a_dict_entries_prefixes
* @api
*/
public function GetDictEntriesPrefixes(): array;
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Implement this interface to add inline script (JS) to the backoffice pages' head.
* Will be executed first, BEFORE the DOM interpretation.
*
* @see \iTopWebPage::$a_early_scripts
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeEarlyScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_early_scripts
* @api
*/
public function GetEarlyScript(): string;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed right when the DOM is ready.
*
* @see \iTopWebPage::$a_init_scripts
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeInitScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_init_scripts
* @api
*/
public function GetInitScript(): string;
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Implement this interface to add script (JS) files to the backoffice pages
*
* @see \iTopWebPage::$a_linked_scripts
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeLinkedScriptsExtension
{
/**
* Each script will be included using this property
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_scripts
* @api
*/
public function GetLinkedScriptsAbsUrls(): array;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add stylesheets (CSS) to the backoffice pages
*
* @see \iTopWebPage::$a_linked_stylesheets
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeLinkedStylesheetsExtension
{
/**
* @return array An array of absolute URLs to the files to include
* @see \iTopWebPage::$a_linked_stylesheets
* @api
*/
public function GetLinkedStylesheetsAbsUrls(): array;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed slightly AFTER the DOM is ready (just after the init. scripts).
*
* @see \iTopWebPage::$a_ready_scripts
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeReadyScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_ready_scripts
* @api
*/
public function GetReadyScript(): string;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add sass file (SCSS) to the backoffice pages.
* example: return "css/setup.scss"
*
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.3.0
*/
interface iBackofficeSassExtension
{
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetSass(): string;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed immediately, without waiting for the DOM to be ready.
*
* @see \iTopWebPage::$a_scripts
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeScriptExtension
{
/**
* @return string
* @see \iTopWebPage::$a_scripts
* @api
*/
public function GetScript(): string;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Implement this interface to add inline style (CSS) to the backoffice pages' head.
*
* @see \iTopWebPage::$a_styles
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iBackofficeStyleExtension
{
/**
* @return string
* @see \iTopWebPage::$a_styles
* @api
*/
public function GetStyle(): string;
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Implement this interface to register a new field renderer mapping to either:
* - Add the rendering of a new attribute type
* - Overload the default rendering of an attribute type
*
* @since 3.1.0 N°6041
*
* @experimental Form / Field / Renderer should be used in more places in next iTop releases, which may introduce major API changes
*/
interface iFieldRendererMappingsExtension
{
/**
* @return array {
* array: {
* field: string,
* form_renderer: string,
* field_renderer: string
* }
* } List of field renderer mapping: FQCN field class, FQCN Form Renderer class, FQCN Field Renderer class
*
* Example:
*
* ```php
* [
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
* ]
* ```
*/
public static function RegisterSupportedFields(): array;
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Implement this interface to add content to any iTopWebPage
*
* There are 3 places where content can be added:
*
* * The north pane: (normaly empty/hidden) at the top of the page, spanning the whole
* width of the page
* * The south pane: (normaly empty/hidden) at the bottom of the page, spanning the whole
* width of the page
* * The admin banner (two tones gray background) at the left of the global search.
* Limited space, use it for short messages
*
* Each of the methods of this interface is supposed to return the HTML to be inserted at
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
*
* @api
* @package BackofficeUIExtensibilityAPI
* @since 3.0.0
*/
interface iPageUIBlockExtension
{
/**
* Add content to the "admin banner"
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetBannerBlock();
/**
* Add content to the header of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetHeaderBlock();
/**
* Add content to the footer of the page
*
* @api
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
*/
public function GetFooterBlock();
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* New extension to add menu items in the "popup" menus inside iTop. Provides a greater flexibility than
* iApplicationUIExtension::EnumAllowedActions.
*
* To add some menus into iTop, declare a class that implements this interface, it will be called automatically
* by the application, as long as the class definition is included somewhere in the code
*
* @api
* @package UIExtensibilityAPI
* @since 2.0
*/
interface iPopupMenuExtension
{
/**
* Insert an item into the Actions menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
const MENU_OBJLIST_ACTIONS = 1;
/**
* Insert an item into the Toolkit menu of a list
*
* $param is a DBObjectSet containing the list of objects
* @api
*/
const MENU_OBJLIST_TOOLKIT = 2;
/**
* Insert an item into the Actions menu on an object details page
*
* $param is a DBObject instance: the object currently displayed
* @api
*/
const MENU_OBJDETAILS_ACTIONS = 3;
/**
* Insert an item into the Dashboard menu
*
* The dashboad menu is shown on the top right corner when a dashboard
* is being displayed.
*
* $param is a Dashboard instance: the dashboard currently displayed
* @api
*/
const MENU_DASHBOARD_ACTIONS = 4;
/**
* Insert an item into the User menu (upper right corner)
*
* $param is null
* @api
*/
const MENU_USER_ACTIONS = 5;
/**
* Insert an item into the Action menu on an object item in an objects list in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object on
* the current line)
* @api
*/
const PORTAL_OBJLISTITEM_ACTIONS = 7;
/**
* Insert an item into the Action menu on an object details page in the portal
*
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object
* currently displayed)
* @api
*/
const PORTAL_OBJDETAILS_ACTIONS = 8;
/**
* Insert an item into the Actions menu of a list in the portal
* Note: This is not implemented yet !
*
* $param is an array('portal_id' => $sPortalId, 'object_set' => $oSet) containing DBObjectSet containing the list of objects
*
* @todo
*/
const PORTAL_OBJLIST_ACTIONS = 6;
/**
* Insert an item into the user menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
const PORTAL_USER_ACTIONS = 9;
/**
* Insert an item into the navigation menu of the portal
* Note: This is not implemented yet !
*
* $param is the portal id
*
* @todo
*/
const PORTAL_MENU_ACTIONS = 10;
/**
* Get the list of items to be added to a menu.
*
* This method is called by the framework for each menu.
* The items will be inserted in the menu in the order of the returned array.
*
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
* @param mixed $param Depends on $iMenuId, see the constants defined above
*
* @return object[] An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
* @api
*/
public static function EnumItems($iMenuId, $param);
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* @api
* @package PreferencesExtensibilityAPI
* @since 2.7.0
*/
interface iPreferencesExtension
{
/**
* @api
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
*/
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage);
/**
* @api
*
* @param string $sOperation
*
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
* @return bool true if the operation has been used
*/
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation);
}

View File

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

View File

@@ -0,0 +1,16 @@
<?php
/**
* Implement this interface to add files to the backup
*
* @api
* @since 3.2.0
*/
interface iBackupExtraFilesExtension
{
/**
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
* @api
*/
public function GetExtraFilesRelPaths(): array;
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* KPI logging extensibility point
*
* KPI Logger extension
*/
interface iKPILoggerExtension
{
/**
* Init the statistics collected
*
* @return void
*/
public function InitStats();
/**
* Add a new KPI to the stats
*
* @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData
*
* @return mixed
*/
public function LogOperation($oKpiLogData);
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* Helpers for modules extensibility, with discover performed by the MetaModel.
*
*
* @api
* @package Extensibility
*/
interface iModuleExtension
{
/**
* @api
*/
public function __construct();
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* Login finite state machine
*
* Execute the action corresponding to the current login state.
*
* * If a page is displayed, the action must exit at this point
* * if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
* * if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
* * if LoginWebPage::LOGIN_FSM_CONTINUE is returned then the FSM will proceed to next plugin or to next state
*
* @api
* @package LoginExtensibilityAPI
* @since 2.7.0
*/
abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
{
/**
* @inheritDoc
*/
abstract public function ListSupportedLoginModes();
/**
* @inheritDoc
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState) {
case LoginWebPage::LOGIN_STATE_START:
return $this->OnStart($iErrorCode);
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
return $this->OnModeDetection($iErrorCode);
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
return $this->OnReadCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
return $this->OnCheckCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK:
return $this->OnCredentialsOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_USER_OK:
return $this->OnUsersOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_CONNECTED:
return $this->OnConnected($iErrorCode);
case LoginWebPage::LOGIN_STATE_ERROR:
return $this->OnError($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Initialization
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnStart(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Detect login mode explicitly without respecting configured order (legacy mode)
* In most case do nothing here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnModeDetection(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Obtain the credentials either if login mode is empty or set to yours.
* This step can be called multiple times by the FSM:
* for example:
* 1 - display login form
* 2 - read the values posted by the user (store that in session)
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnReadCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* Control the validity of the data from the session
* Automatic user provisioning can be done here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCheckCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnCredentialsOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnUsersOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnConnected(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
/**
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
* @api
*/
protected function OnError(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* @api
* @package LoginExtensibilityAPI
* @since 2.7.0
*/
interface iLoginExtension
{
/**
* Return the list of supported login modes for this plugin
*
* @return array of supported login modes
* @api
*/
public function ListSupportedLoginModes();
}

View File

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

View File

@@ -0,0 +1,17 @@
<?php
/**
* Login page extensibility
*
* @api
* @package UIExtensibilityAPI
* @since 2.7.0
*/
interface iLoginUIExtension extends iLoginExtension
{
/**
* @return LoginTwigContext
* @api
*/
public function GetTwigContext();
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @api
* @package LoginExtensibilityAPI
* @since 2.7.0
*/
interface iLogoutExtension extends iLoginExtension
{
/**
* Execute all actions to log out properly
* @api
*/
public function LogoutAction();
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
*
* @api
* @package PortalExtensibilityAPI
* @since 2.4.0
*/
abstract class AbstractPortalUIExtension implements iPortalUIExtension
{
/**
* @inheritDoc
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return array();
}
/**
* @inheritDoc
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return array();
}
/**
* @inheritDoc
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
/**
* @inheritDoc
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
{
return null;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* Implement this interface to add content to any enhanced portal page
*
* @api
* @package PortalExtensibilityAPI
*
* @since 2.4.0 interface creation
* @since 2.7.0 change method signatures due to Silex to Symfony migration
*/
interface iPortalUIExtension
{
const ENUM_PORTAL_EXT_UI_BODY = 'Body';
const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu';
const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent';
/**
* Returns an array of CSS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns inline (raw) CSS
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns an array of JS file urls
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @api
*/
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw JS code
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the <body> tag
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the #main-wrapper element
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
/**
* Returns raw HTML code to put at the end of the #topbar and #sidebar elements
*
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return string
* @api
*/
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
}

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
<?php
/**
* A REST service provider implementing this interface will have its input JSON data sanitized for logging purposes
*
* @see \iRestServiceProvider
* @since 2.7.13, 3.2.1-1
*/
interface iRestInputSanitizer
{
public function SanitizeJsonInput(string $sJsonInput): string;
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Implement this interface to add new operations to the REST/JSON web service
*
* @api
* @package RESTExtensibilityAPI
* @since 2.0.1
*/
interface iRestServiceProvider
{
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
*
* @return array An array of hash 'verb' => verb, 'description' => description
* @api
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param array $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @api
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}

View File

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

View File

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

View File

@@ -698,10 +698,10 @@ HTML
$sLinkedClass = $oAttDef->GetLinkedClass();
// Filter out links pointing to obsolete objects (if relevant)
$oOrmLinkSet = $this->Get($sAttCode);
$oLinkSet = $oOrmLinkSet->ToDBObjectSet(utils::ShowObsoleteData());
$oOrmLinkSet = $this->Get($sAttCode);
$oLinkSet = $oOrmLinkSet->ToDBObjectSet(utils::ShowObsoleteData());
$iCount = $oLinkSet->Count();
$iCount = $oLinkSet->Count();
if ($this->IsNew()) {
$iFlags = $this->GetInitialStateAttributeFlags($sAttCode);
} else {
@@ -766,9 +766,9 @@ HTML
$oPage->add($sHTMLValue);
} else {
if ($oAttDef->IsIndirect()) {
$oBlockLinkSetViewTable = new BlockIndirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly);
$oBlockLinkSetViewTable = new BlockIndirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly, $iCount);
} else {
$oBlockLinkSetViewTable = new BlockDirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly);
$oBlockLinkSetViewTable = new BlockDirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly, $iCount);
}
$oPage->AddUiBlock($oBlockLinkSetViewTable);
}
@@ -805,16 +805,16 @@ HTML
if (!$this->IsNew()) {
// Look for any trigger that considers this object as "In Scope"
// If any trigger has been found then display a tab with notifications
//
// If all triggers on an object have been deleted, we consider that we no longer need the event notification information
$aTriggers = $this->GetRelatedTriggersIDs();
if (count($aTriggers) > 0) {
$iId = $this->GetKey();
$aParams = array('triggers' => $aTriggers, 'id' => $iId);
$aParams = array('class' => get_class($this), 'id' => $iId);
$aNotifSearches = array();
$iNotifsCount = 0;
$aNotificationClasses = MetaModel::EnumChildClasses('EventNotification');
foreach ($aNotificationClasses as $sNotifClass) {
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev JOIN Trigger AS T ON Ev.trigger_id = T.id WHERE T.id IN (:triggers) AND Ev.object_id = :id");
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev WHERE Ev.object_id = :id AND Ev.object_class = :class");
$aNotifSearches[$sNotifClass]->SetInternalParams($aParams);
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass], array());
$iNotifsCount += $oNotifSet->Count();
@@ -2931,11 +2931,11 @@ JS
$sStatesSelection .= '</select>';
$sStatesSelection .= '<input type="hidden" id="obj_state_orig" name="obj_state_orig" value="'.$this->GetState().'"/>';
$oPage->add_ready_script(<<<JS
$('.state_select_{$this->m_iFormId}').change( function() {
$('.state_select_{$this->m_iFormId}').on('change', function() {
if ($('#obj_state_orig').val() != $(this).val()) {
$('.state_select_{$this->m_iFormId}').val($(this).val());
$('#form_{$this->m_iFormId}').data('force_submit', true);
$('#form_{$this->m_iFormId}').submit();
$('#form_{$this->m_iFormId}').trigger('submit');
}
});
JS
@@ -3925,7 +3925,7 @@ HTML;
public static function GetShortcutActions($sFinalClass)
{
$sShortcutActions = MetaModel::GetConfig()->Get('shortcut_actions');
$aShortcutActions = explode(',', $sShortcutActions);
$aShortcutActions = array_map('trim', explode(',', $sShortcutActions));
return $aShortcutActions;
}
@@ -4313,24 +4313,15 @@ HTML;
case 'Image':
$value = null;
$aDimensions = null;
$oImage = utils::ReadPostedDocument("attr_{$sFormPrefix}{$sAttCode}", 'fcontents');
if (!is_null($oImage->GetData()))
{
$aSize = utils::GetImageSize($oImage->GetData());
if (is_array($aSize) && $aSize[0] > 0 && $aSize[1] > 0)
{
$oImage = utils::ResizeImageToFit(
$oImage,
$aSize[0],
$aSize[1],
$oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height')
);
}
else
{
IssueLog::Warning($sClass . ':' . $this->GetKey() . '/' . $sAttCode . ': Image could not be resized. Mimetype: ' . $oImage->GetMimeType() . ', filename: ' . $oImage->GetFileName());
}
$oImage = $oImage->ResizeImageToFit(
$oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height'),
$aDimensions
);
if (is_null($aDimensions)) {
IssueLog::Warning($sClass . ':' . $this->GetKey() . '/' . $sAttCode . ': Image could not be resized. Mimetype: ' . $oImage->GetMimeType() . ', filename: ' . $oImage->GetFileName());
}
$aOtherData = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
if (is_array($aOtherData))
@@ -4575,28 +4566,6 @@ HTML;
InlineImage::FinalizeInlineImages($this);
}
/**
* @deprecated 3.1.1 3.2.0 N°6966 We will have only one DBClone method in the future
*/
protected function DBCloneTracked_Internal($newKey = null)
{
/** @var cmdbAbstractObject $oNewObj */
$oNewObj = MetaModel::GetObject(get_class($this), parent::DBCloneTracked_Internal($newKey));
// Invoke extensions after insertion (the object must exist, have an id, etc.)
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBInsert()");
$oKPI = new ExecutionKPI();
$oExtensionInstance->OnDBInsert($oNewObj, self::GetCurrentChange());
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBInsert');
}
return $oNewObj;
}
public function DBUpdate()
{
$this->LogCRUDEnter(__METHOD__);
@@ -4690,25 +4659,6 @@ HTML;
parent::PostDeleteActions();
}
/**
* @deprecated 3.1.1 3.2.0 N°6967 We will have only one DBDelete method in the future
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
// Invoke extensions before the deletion (the deletion will do some cleanup and we might loose some information
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBDelete()");
$oKPI = new ExecutionKPI();
$oExtensionInstance->OnDBDelete($this, self::GetCurrentChange());
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBDelete');
}
return parent::DBDeleteTracked_Internal($oDeletionPlan);
}
public function IsModified()
{
if (parent::IsModified())
@@ -4860,110 +4810,6 @@ HTML;
}
}
/**
* Special display where the case log uses the whole "screen" at the bottom of the "Properties" tab
*
* @param WebPage $oPage
* @param string $sAttCode
* @param string $sComment
* @param string $sPrefix
* @param bool $bEditMode
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws \OQLException
* @throws \Exception
* @deprecated 3.0.0, will be removed in 3.1.0
*/
public function DisplayCaseLog(WebPage $oPage, $sAttCode, $sComment = '', $sPrefix = '', $bEditMode = false)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
$oPage->SetCurrentTab('UI:PropertiesTab');
$sClass = get_class($this);
if ($this->IsNew()) {
$iFlags = $this->GetInitialStateAttributeFlags($sAttCode);
} else {
$iFlags = $this->GetAttributeFlags($sAttCode);
}
if ($iFlags & OPT_ATT_HIDDEN) {
// The case log is hidden do nothing
} else
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
$sAttDefClass = get_class($oAttDef);
$sAttLabel = $oAttDef->GetLabel();
$sAttMetaDataLabel = utils::HtmlEntities($sAttLabel);
$sAttMetaDataFlagHidden = (($iFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN) ? 'true' : 'false';
$sAttMetaDataFlagReadOnly = (($iFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY) ? 'true' : 'false';
$sAttMetaDataFlagMandatory = (($iFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) ? 'true' : 'false';
$sAttMetaDataFlagMustChange = (($iFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE) ? 'true' : 'false';
$sAttMetaDataFlagMustPrompt = (($iFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT) ? 'true' : 'false';
$sAttMetaDataFlagSlave = (($iFlags & OPT_ATT_SLAVE) === OPT_ATT_SLAVE) ? 'true' : 'false';
$sInputId = $this->m_iFormId.'_'.$sAttCode;
if ((!$bEditMode) || ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE)))
{
// Check if the attribute is not read-only because of a synchro...
if ($iFlags & OPT_ATT_SLAVE)
{
$aReasons = array();
$sTip = '';
foreach($aReasons as $aRow) {
$sDescription = utils::EscapeHtml($aRow['description']);
$sDescription = str_replace(array("\r\n", "\n"), "<br/>", $sDescription);
$sTip .= "<div class=\"synchro-source\">";
$sTip .= "<div class=\"synchro-source-title\">Synchronized with {$aRow['name']}</div>";
$sTip .= "<div class=\"synchro-source-description\">$sDescription</div>";
}
$sTip = addslashes($sTip);
$oPage->add_ready_script("$('#synchro_$sInputId').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
// Attribute is read-only
$sHTMLValue = $this->GetAsHTML($sAttCode);
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.utils::EscapeHtml($this->GetEditValue($sAttCode)).'"/>';
$aFieldsMap[$sAttCode] = $sInputId;
}
else
{
$sValue = $this->Get($sAttCode);
$sDisplayValue = $this->GetEditValue($sAttCode);
$aArgs = array('this' => $this, 'formPrefix' => $sPrefix);
$sCommentAsHtml = ($sComment != '') ? '<span>'.$sComment.'</span><br/>' : '';
$sFieldAsHtml = self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs);
$sHTMLValue = <<<HTML
<div class="field_data">
<div class="field_value">
$sCommentAsHtml
$sFieldAsHtml
</div>
</div>
HTML;
$aFieldsMap[$sAttCode] = $sInputId;
}
$oPage->add(<<<HTML
<fieldset>
<legend>{$sAttLabel}</legend>
<div class="field_container field_large" data-attribute-code="{$sAttCode}" data-attribute-type="{$sAttDefClass}" data-attribute-label="{$sAttMetaDataLabel}"
data-attribute-flag-hidden="{$sAttMetaDataFlagHidden}" data-attribute-flag-read-only="{$sAttMetaDataFlagReadOnly}" data-attribute-flag-mandatory="{$sAttMetaDataFlagMandatory}"
data-attribute-flag-must-change="{$sAttMetaDataFlagMustChange}" data-attribute-flag-must-prompt="{$sAttMetaDataFlagMustPrompt}" data-attribute-flag-slave="{$sAttMetaDataFlagSlave}">
{$sHTMLValue}
</div>
</fieldset>
HTML
);
}
}
/**
* Special display where the case log uses the whole "screen" at the bottom of the "Properties" tab
*
@@ -5207,7 +5053,7 @@ HTML
$aKeys = array_keys($aValues[$sAttCode]);
$currValue = $aKeys[0]; // The only value is the first key
if ($oAttDef->GetEditClass() == 'LinkedSet') {
$oOrmLinkSet = $oDummyObj->Get($sAttCode);
$oOrmLinkSet = $oDummyObj->Get($sAttCode);
LinkSetDataTransformer::StringToOrmLinkSet($aValues[$sAttCode][$currValue]['edit_value'], $oOrmLinkSet);
} else {
@@ -5261,7 +5107,7 @@ HTML
}
$oDummyObj->Set($sAttCode, $oTagSet);
} else if ($oAttDef->GetEditClass() == 'LinkedSet') {
$oOrmLinkSet = $oDummyObj->Get($sAttCode);
$oOrmLinkSet = $oDummyObj->Get($sAttCode);
foreach ($aMultiValues as $key => $sValue) {
LinkSetDataTransformer::StringToOrmLinkSet($sValue['edit_value'], $oOrmLinkSet);
}

View File

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

View File

@@ -296,21 +296,21 @@ abstract class Dashboard
public function FromParams($aParams)
{
$this->sLayoutClass = $aParams['layout_class'];
if (!is_subclass_of($this->sLayoutClass,DashboardLayout::class)) {
throw new InvalidParameterException('Invalid parameter layout_class "'.$aParams['layout_class'].'"');
}
$this->sTitle = $aParams['title'];
$this->bAutoReload = $aParams['auto_reload'] == 'true';
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']);
foreach($aParams['cells'] as $aCell)
{
foreach($aParams['cells'] as $aCell) {
$aCellDashlets = array();
foreach($aCell as $aDashletParams)
{
foreach($aCell as $aDashletParams) {
$sDashletClass = $aDashletParams['dashlet_class'];
$sId = $aDashletParams['dashlet_id'];
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sDashletClass($this->oMetaModel, $sId);
if (isset($aDashletParams['dashlet_type']))
{
if (isset($aDashletParams['dashlet_type'])) {
$oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
}
$oForm = $oNewDashlet->GetForm();

View File

@@ -1967,7 +1967,10 @@ class DashletHeaderStatic extends Dashlet
$sIcon = $this->aProperties['icon'];
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
$sIconPath = '';
if (Utils::IsNotNullOrEmptyString($sIcon)) {
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
}
return DashletFactory::MakeForDashletHeaderStatic($this->oModelReflection->DictString($sTitle), $sIconPath);
}
@@ -1981,6 +1984,7 @@ class DashletHeaderStatic extends Dashlet
$oForm->AddField($oField);
$oField = $this->oModelReflection->GetIconSelectionField('icon', Dict::S('UI:DashletHeaderStatic:Prop-Icon'), $this->aProperties['icon']);
$oField->AddAllowedValue(['value' => '', 'label' => Dict::S('UI:DashletIcon:None'), 'icon' => '']);
$oForm->AddField($oField);
}
@@ -2093,7 +2097,10 @@ class DashletHeaderDynamic extends Dashlet
$sGroupBy = $this->aProperties['group_by'];
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
$sIconPath = $oIconSelect->MakeFileUrl($sIcon);
$sIconPath = '';
if (Utils::IsNotNullOrEmptyString($sIcon)) {
$sIconPath = $oIconSelect->MakeFileUrl($sIcon);
}
$aValues = $this->GetValues();
if (count($aValues) > 0) {
@@ -2223,6 +2230,7 @@ class DashletHeaderDynamic extends Dashlet
$oForm->AddField($oField);
$oField = $this->oModelReflection->GetIconSelectionField('icon', Dict::S('UI:DashletHeaderDynamic:Prop-Icon'), $this->aProperties['icon']);
$oField->AddAllowedValue(['value' => '', 'label' => Dict::S('UI:DashletIcon:None'), 'icon' => '']);
$oForm->AddField($oField);
$oField = new DesignerTextField('subtitle', Dict::S('UI:DashletHeaderDynamic:Prop-Subtitle'), $this->aProperties['subtitle']);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
<classes>
<class id="AbstractResource" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -45,7 +45,7 @@
<properties>
<comment>/** Acknowledge welcome popup messages */</comment>
<abstract>false</abstract>
<category></category>
<category/>
<key_type>autoincrement</key_type>
<db_table>priv_welcome_popup_acknowledge</db_table>
</properties>
@@ -111,7 +111,6 @@
<menu id="UserManagement" xsi:type="TemplateMenuNode" _delta="define">
<rank>10</rank>
<parent>AdminTools</parent>
<template_file/>
</menu>
<menu id="UserAccountsMenu" xsi:type="OQLMenuNode" _delta="define">
<rank>11</rank>
@@ -141,7 +140,6 @@
<menu id="Queries" xsi:type="TemplateMenuNode" _delta="define">
<rank>30</rank>
<parent>AdminTools</parent>
<template_file/>
</menu>
<menu id="RunQueriesMenu" xsi:type="WebPageMenuNode" _delta="define">
<rank>31</rank>
@@ -188,7 +186,6 @@
<menu id="Integrations" xsi:type="TemplateMenuNode" _delta="define">
<rank>50</rank>
<parent>ConfigurationTools</parent>
<template_file/>
</menu>
<menu id="DataSources" xsi:type="OQLMenuNode" _delta="define">
<rank>20</rank>

View File

@@ -1,880 +0,0 @@
<?php
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
/**
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*
* @deprecated 3.0.0 use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable
*/
class DataTable
{
protected $iListId; // Unique ID inside the web page
/** @var string */
private $sDatatableContainerId;
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
protected $oSet; // The set of objects to display
protected $aClassAliases; // The aliases (alias => class) inside the set
protected $iNbObjects; // Total number of objects in the set
protected $bUseCustomSettings; // Whether or not the current display uses custom settings
protected $oDefaultSettings; // the default settings for displaying such a list
protected $bShowObsoleteData;
/**
* @param string $iListId Unique ID for this div/table in the page
* @param DBObjectSet $oSet The set of data to display
* @param array$aClassAliases The list of classes/aliases to be displayed in this set $sAlias => $sClassName
* @param string $sTableId A string (or null) identifying this table in order to persist its settings
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable');
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
$this->sDatatableContainerId = 'datatable_'.utils::GetSafeId($iListId);
$this->oSet = $oSet;
$this->aClassAliases = $aClassAliases;
$this->sTableId = $sTableId;
$this->iNbObjects = $oSet->Count();
$this->bUseCustomSettings = false;
$this->oDefaultSettings = null;
$this->bShowObsoleteData = $oSet->GetShowObsoleteData();
}
/**
* @param WebPage $oPage
* @param DataTableSettings $oSettings
* @param $bActionsMenu
* @param $sSelectMode
* @param $bViewLink
* @param $aExtraParams
*
* @return string
* @throws \CoreException
* @throws \MySQLException
*/
public function Display(WebPage $oPage, DataTableSettings $oSettings, $bActionsMenu, $sSelectMode, $bViewLink, $aExtraParams)
{
$this->oDefaultSettings = $oSettings;
// Identified tables can have their own specific settings
$oCustomSettings = DataTableSettings::GetTableSettings($this->aClassAliases, $this->sTableId);
if ($oCustomSettings != null)
{
// Custom settings overload the default ones
$this->bUseCustomSettings = true;
if ($this->oDefaultSettings->iDefaultPageSize == 0)
{
$oCustomSettings->iDefaultPageSize = 0;
}
}
else
{
$oCustomSettings = $oSettings;
}
if ($oCustomSettings->iDefaultPageSize > 0)
{
$this->oSet->SetLimit($oCustomSettings->iDefaultPageSize);
}
$this->oSet->SetOrderBy($oCustomSettings->GetSortOrder());
// Load only the requested columns
$aColumnsToLoad = array();
foreach($oCustomSettings->aColumns as $sAlias => $aColumnsInfo)
{
foreach($aColumnsInfo as $sAttCode => $aData)
{
if ($sAttCode != '_key_')
{
if ($aData['checked'])
{
$aColumnsToLoad[$sAlias][] = $sAttCode;
}
else
{
// See if this column is a must to load
$sClass = $this->aClassAliases[$sAlias];
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->AlwaysLoadInTables()) {
$aColumnsToLoad[$sAlias][] = $sAttCode;
}
}
}
}
}
$this->oSet->OptimizeColumnLoad($aColumnsToLoad);
$bToolkitMenu = true;
if (isset($aExtraParams['toolkit_menu']))
{
$bToolkitMenu = (bool) $aExtraParams['toolkit_menu'];
}
if (UserRights::IsPortalUser())
{
// Portal users have a limited access to data, for now they can only see what's configured for them
$bToolkitMenu = false;
}
return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams);
}
/**
* @param WebPage $oPage
* @param $iPageSize
* @param $iDefaultPageSize
* @param $iPageIndex
* @param $aColumns
* @param $bActionsMenu
* @param $bToolkitMenu
* @param $sSelectMode
* @param $bViewLink
* @param $aExtraParams
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function GetAsHTML(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex, $aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams)
{
$sObjectsCount = $this->GetObjectCount($oPage, $sSelectMode);
$sPager = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
$sActionsMenu = '';
$sToolkitMenu = '';
if ($bActionsMenu) {
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
}
// if ($bToolkitMenu)
// {
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
// }
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
$sHtml = "<table id=\"{$this->sDatatableContainerId}\" class=\"datatable\">";
$sHtml .= "<tr><td>";
$sHtml .= "<table style=\"width:100%;\">";
$sHtml .= "<tr><td class=\"pagination_container\">$sObjectsCount</td><td class=\"menucontainer\">$sToolkitMenu $sActionsMenu</td></tr>";
$sHtml .= "<tr>$sPager</tr>";
$sHtml .= "</table>";
$sHtml .= "</td></tr>";
$sHtml .= "<tr><td class=\"datacontents\">$sDataTable</td></tr>";
$sHtml .= "</table>\n";
$oPage->add_at_the_end($sConfigDlg);
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
$aOptions = array(
'sPersistentId' => '',
'sFilter' => $this->oSet->GetFilter()->serialize(),
'oColumns' => $aColumns,
'sSelectMode' => $sSelectMode,
'sViewLink' => ($bViewLink ? 'true' : 'false'),
'iNbObjects' => $this->iNbObjects,
'iDefaultPageSize' => $iDefaultPageSize,
'iPageSize' => $iPageSize,
'iPageIndex' => $iPageIndex,
'oClassAliases' => $this->aClassAliases,
'sTableId' => $this->sTableId,
'oExtraParams' => $aExtraParams,
'sRenderUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
'oRenderParameters' => array('str' => ''), // Forces JSON to encode this as a object...
'oDefaultSettings' => array('str' => ''), // Forces JSON to encode this as a object...
'oLabels' => array('moveup' => Dict::S('UI:Button:MoveUp'), 'movedown' => Dict::S('UI:Button:MoveDown')),
);
if($this->oDefaultSettings != null)
{
$aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings);
}
$sJSOptions = json_encode($aOptions);
$oPage->add_ready_script("$('#{$this->sDatatableContainerId}').datatable($sJSOptions);");
return $sHtml;
}
/**
* When refreshing the body of a paginated table, get the rows of the table (inside the TBODY)
* return string The HTML rows to insert inside the <tbody> node
*/
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
{
if ($iPageSize < 1)
{
$iPageSize = -1; // convention: no pagination
}
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sHtml = '';
foreach($aValues as $aRow)
{
$sHtml .= $oPage->GetTableRow($aRow, $aAttribs);
}
return $sHtml;
}
/**
* @param WebPage $oPage
* @param $sSelectMode
*
* @return string
*/
protected function GetObjectCount(WebPage $oPage, $sSelectMode)
{
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
{
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderSelection', '<span id="total">'.$this->iNbObjects.'</span>', '<span class="selectedCount">0</span>').'</div>';
}
else
{
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderNoSelection', '<span id="total">'.$this->iNbObjects.'</span>').'</div>';
}
return $sHtml;
}
/**
* @param WebPage $oPage
* @param $iPageSize
* @param $iDefaultPageSize
* @param $iPageIndex
*
* @return string
*/
protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex)
{
$sHtml = '';
if ($iPageSize < 1) // Display all
{
$sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI
// WARNING: mPDF does not take the "display" style into account
// when applied to a <td> or a <table> tag, so make sure you apply this to a div
}
else
{
$sPagerStyle = '';
}
$sCombo = '<select class="pagesize">';
if($iPageSize < 1)
{
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
}
else
{
for($iPage = 1; $iPage < 5; $iPage++)
{
$iNbItems = $iPage * $iDefaultPageSize;
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
}
$sCombo .= "<option value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
}
$sCombo .= '</select>';
$sPages = Dict::S('UI:Pagination:PagesLabel');
$sPageSizeCombo = Dict::Format('UI:Pagination:PageSize', $sCombo);
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iNbPages == 1)
{
// No need to display the pager
$sPagerStyle = 'style="display:none"';
}
$aPagesToDisplay = array();
for($idx = 0; $idx <= min(4, $iNbPages-1); $idx++)
{
if ($idx == 0)
{
$aPagesToDisplay[$idx] = '<span page="0" class="curr_page">1</span>';
}
else
{
$aPagesToDisplay[$idx] = "<span id=\"gotopage_$idx\" class=\"gotopage\" page=\"$idx\">".(1+$idx)."</span>";
}
}
$iLastPageIdx = $iNbPages - 1;
if (!isset($aPagesToDisplay[$iLastPageIdx]))
{
unset($aPagesToDisplay[$idx - 1]); // remove the last page added to make room for the very last page
$aPagesToDisplay[$iLastPageIdx] = "<span id=\"gotopage_$iLastPageIdx\" class=\"gotopage\" page=\"$iLastPageIdx\">... $iNbPages</span>";
}
$sPagesLinks = implode('', $aPagesToDisplay);
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
$sHtml =
<<<EOF
<td colspan="2">
<div $sPagerStyle>
<table id="pager{$this->iListId}" class="pager"><tr>
<td>$sPages</td>
<td><img src="{$sAppRootUrl}images/first.png" class="first"/>AAAA</td>
<td><img src="{$sAppRootUrl}images/prev.png" class="prev"/></td>
<td><span id="index">$sPagesLinks</span></td>
<td><img src="{$sAppRootUrl}images/next.png" class="next"/></td>
<td><img src="{$sAppRootUrl}images/last.png" class="last"/></td>
<td>$sPageSizeCombo</td>
<td><span id="loading">&nbsp;</span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
</td>
</tr>
</table>
</div>
</td>
EOF;
return $sHtml;
}
/**
* @param WebPage $oPage
* @param $aExtraParams
*
* @return string
* @throws \ApplicationException
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \ReflectionException
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
{
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
return ConsoleBlockRenderer::RenderBlockTemplateInPage($oPage, $oBlock);
}
/**
* @param WebPage $oPage
* @param $aExtraParams
*
* @return string
* @throws \Exception
*/
protected function GetToolkitMenu(WebPage $oPage, $aExtraParams)
{
if (!$oPage->IsPrintableVersion())
{
$sMenuTitle = Dict::S('UI:ConfigureThisList');
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
$aActions = array(
$oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(),
);
$this->oSet->Rewind();
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions, $this->sTableId, $this->iListId);
$this->oSet->Rewind();
$sHtml .= $oPage->RenderPopupMenuItems($aActions);
}
else
{
$sHtml = '';
}
return $sHtml;
}
/**
* @param WebPage $oPage
* @param $aColumns
* @param $bViewLink
* @param $iDefaultPageSize
*
* @return string
*/
protected function GetTableConfigDlg(WebPage $oPage, $aColumns, $bViewLink, $iDefaultPageSize)
{
$sHtml = "<div id=\"datatable_dlg_{$this->iListId}\" style=\"display: none;\">";
$sHtml .= "<form onsubmit=\"return false\">";
$sChecked = ($this->bUseCustomSettings) ? '' : 'checked';
$sHtml .= "<p><input id=\"dtbl_dlg_settings_{$this->iListId}\" type=\"radio\" name=\"settings\" $sChecked value=\"defaults\"><label for=\"dtbl_dlg_settings_{$this->iListId}\">&nbsp;".Dict::S('UI:UseDefaultSettings').'</label></p>';
$sHtml .= "<fieldset>";
$sChecked = ($this->bUseCustomSettings) ? 'checked': '';
$sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_specific_{$this->iListId}\" type=\"radio\" class=\"specific_settings\" name=\"settings\" $sChecked value=\"specific\"><label for=\"dtbl_dlg_specific_{$this->iListId}\">&nbsp;".Dict::S('UI:UseSpecificSettings')."</label></legend>";
$sHtml .= Dict::S('UI:ColumnsAndSortOrder').'<br/><ul class="sortable_field_list" id="sfl_'.$this->iListId.'"></ul>';
$sHtml .= '<p>'.Dict::Format('UI:Display_X_ItemsPerPage', '<input type="text" size="4" name="page_size" value="'.$iDefaultPageSize.'">').'</p>';
$sHtml .= "</fieldset>";
$sHtml .= "<fieldset>";
$sSaveChecked = ($this->sTableId != null) ? 'checked' : '';
$sCustomDisabled = ($this->sTableId == null) ? 'disabled="disabled" stay-disabled="true" ' : '';
$sCustomChecked = ($this->sTableId != null) ? 'checked' : '';
$sGenericChecked = ($this->sTableId == null) ? 'checked' : '';
$sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_save_{$this->iListId}\" type=\"checkbox\" $sSaveChecked name=\"save_settings\"><label for=\"dtbl_dlg_save_{$this->iListId}\">&nbsp;".Dict::S('UI:UseSavetheSettings')."</label></legend>";
$sHtml .= "<p><input id=\"dtbl_dlg_this_list_{$this->iListId}\" type=\"radio\" name=\"scope\" $sCustomChecked $sCustomDisabled value=\"this_list\"><label for=\"dtbl_dlg_this_list_{$this->iListId}\">&nbsp;".Dict::S('UI:OnlyForThisList').'</label>&nbsp;&nbsp;&nbsp;&nbsp;';
$sHtml .= "<input id=\"dtbl_dlg_all_{$this->iListId}\" type=\"radio\" name=\"scope\" $sGenericChecked value=\"defaults\"><label for=\"dtbl_dlg_all_{$this->iListId}\">&nbsp;".Dict::S('UI:ForAllLists').'</label></p>';
$sHtml .= "</fieldset>";
$sHtml .= '<table style="width:100%"><tr><td style="text-align:center;">';
$sHtml .= '<button type="button" onclick="$(\'#'.$this->sDatatableContainerId.'\').datatable(\'onDlgCancel\'); $(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\')">'.Dict::S('UI:Button:Cancel').'</button>';
$sHtml .= '</td><td style="text-align:center;">';
$sHtml .= '<button type="submit" onclick="$(\'#'.$this->sDatatableContainerId.'\').datatable(\'onDlgOk\');$(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\');">'.Dict::S('UI:Button:Ok').'</button>';
$sHtml .= '</td></tr></table>';
$sHtml .= "</form>";
$sHtml .= "</div>";
$sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle'));
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });");
return $sHtml;
}
/**
* @param $oSetting
*
* @return array
*/
public function GetAsHash($oSetting)
{
$aSettings = array('iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns);
return $aSettings;
}
/**
* @param array $aColumns
* @param string $sSelectMode
* @param bool $bViewLink
*
* @return array
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \Exception
*/
protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
{
$aAttribs = array();
if ($sSelectMode == 'multiple')
{
$aAttribs['form::select'] = array(
'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>",
'description' => Dict::S('UI:SelectAllToggle+'),
'metadata' => array(),
);
}
else if ($sSelectMode == 'single')
{
$aAttribs['form::select'] = array('label' => '', 'description' => '', 'metadata' => array());
}
foreach($this->aClassAliases as $sAlias => $sClassName)
{
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$sAttLabel = MetaModel::GetName($sClassName);
$aAttribs['key_'.$sAlias] = array(
'label' => $sAttLabel,
'description' => '',
'metadata' => array(
'object_class' => $sClassName,
'attribute_label' => $sAttLabel,
),
);
}
else
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
$sAttDefClass = get_class($oAttDef);
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
$aAttribs[$sAttCode.'_'.$sAlias] = array(
'label' => $sAttLabel,
'description' => $oAttDef->GetOrderByHint(),
'metadata' => array(
'object_class' => $sClassName,
'attribute_code' => $sAttCode,
'attribute_type' => $sAttDefClass,
'attribute_label' => $sAttLabel,
),
);
}
}
}
}
return $aAttribs;
}
/**
* @param $aColumns
* @param $sSelectMode
* @param $iPageSize
* @param $bViewLink
* @param $aExtraParams
*
* @return array
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \Exception
*/
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{
$bLocalize = true;
if (isset($aExtraParams['localize_values']))
{
$bLocalize = (bool) $aExtraParams['localize_values'];
}
$aValues = array();
$aAttDefsCache = array();
$this->oSet->Seek(0);
$iMaxObjects = $iPageSize;
while (($aObjects = $this->oSet->FetchAssoc()) && ($iMaxObjects != 0))
{
$bFirstObject = true;
$aRow = array();
foreach($this->aClassAliases as $sAlias => $sClassName)
{
if (is_object($aObjects[$sAlias]))
{
$sHilightClass = MetaModel::GetHilightClass($sClassName, $aObjects[$sAlias]);
if ($sHilightClass != '')
{
$aRow['@class'] = $sHilightClass;
}
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject)
{
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]))
{
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
}
else
{
$sDisabled = '';
}
if ($sSelectMode == 'single')
{
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
else
{
$aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
}
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = array(
'value_raw' => $aObjects[$sAlias]->GetKey(),
'value_html' => $aObjects[$sAlias]->GetHyperLink(),
);
}
else
{
// Prepare att. def. classes cache to avoid retrieving AttDef for each row
if(!isset($aAttDefsCache[$sClassName][$sAttCode]))
{
$aAttDefClassesCache[$sClassName][$sAttCode] = get_class(MetaModel::GetAttributeDef($sClassName, $sAttCode));
}
// Only retrieve raw (stored) value for simple fields
$bExcludeRawValue = false;
foreach (cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
{
if (is_a($aAttDefClassesCache[$sClassName][$sAttCode], $sAttDefClassToExclude, true))
{
$bExcludeRawValue = true;
break;
}
}
if($bExcludeRawValue)
{
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize);
}
else
{
$aRow[$sAttCode.'_'.$sAlias] = array(
'value_raw' => $aObjects[$sAlias]->Get($sAttCode),
'value_html' => $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize),
);
}
}
}
}
}
else
{
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = '';
}
else
{
$aRow[$sAttCode.'_'.$sAlias] = '';
}
}
}
}
$bFirstObject = false;
}
$aValues[] = $aRow;
$iMaxObjects--;
}
return $aValues;
}
/**
* @param WebPage $oPage
* @param $aColumns
* @param $sSelectMode
* @param $iPageSize
* @param $bViewLink
* @param $aExtraParams
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \Exception
*/
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iPageSize < 1)
{
$iPageSize = -1; // convention: no pagination
}
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sHtml = '<table class="listContainer object-list">';
foreach($this->oSet->GetFilter()->GetInternalParams() as $sName => $sValue)
{
$aExtraParams['query_params'][$sName] = $sValue;
}
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
$sHtml .= "<tr><td>";
$sHtml .= $oPage->GetTable($aAttribs, $aValues);
$sHtml .= '</td></tr>';
$sHtml .= '</table>';
$iCount = $this->iNbObjects;
$aArgs = $this->oSet->GetArgs();
$sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them
$sSelectModeJS = '';
$sHeaders = '';
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
{
$sSelectModeJS = $sSelectMode;
$sHeaders = 'headers: { 0: {sorter: false}},';
}
$sDisplayKey = ($bViewLink) ? 'true' : 'false';
// Protect against duplicate elements in the Zlist
$aUniqueOrderedList = array();
foreach($this->aClassAliases as $sAlias => $sClassName)
{
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
$aUniqueOrderedList[$sAttCode] = true;
}
}
}
$aUniqueOrderedList = array_keys($aUniqueOrderedList);
$sJSColumns = json_encode($aColumns);
$sJSClassAliases = json_encode($this->aClassAliases);
$sCssCount = isset($aExtraParams['cssCount']) ? ", cssCount: '{$aExtraParams['cssCount']}'" : '';
$this->oSet->ApplyParameters();
// Display the actual sort order of the table
$aRealSortOrder = $this->oSet->GetRealSortOrder();
$aDefaultSort = array();
$iColOffset = 0;
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
{
$iColOffset += 1;
}
if ($bViewLink)
{
// $iColOffset += 1;
}
foreach($aRealSortOrder as $sColCode => $bAscending)
{
$iPos = array_search($sColCode, $aUniqueOrderedList);
if ($iPos !== false)
{
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]";
}
else if (($iPos = array_search(preg_replace('/_friendlyname$/', '', $sColCode), $aUniqueOrderedList)) !== false)
{
// if sorted on the friendly name of an external key, then consider it sorted on the column that shows the links
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]";
}
else if($sColCode == 'friendlyname' && $bViewLink)
{
$aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]";
}
}
$sFakeSortList = '';
if (count($aDefaultSort) > 0)
{
$sFakeSortList = '['.implode(',', $aDefaultSort).']';
}
$sOQL = addslashes($this->oSet->GetFilter()->serialize());
$oPage->add_ready_script(
<<<JS
var oTable = $('#{$this->sDatatableContainerId} table.listResults');
oTable.tableHover();
oTable
.tablesorter({ $sHeaders widgets: ['myZebra', 'truncatedList']})
.tablesorterPager({
container: $('#pager{$this->iListId}'),
totalRows:$iCount,
size: $iPageSize,
filter: '$sOQL',
extra_params: '$sExtraParams',
select_mode: '$sSelectModeJS',
displayKey: $sDisplayKey,
table_id: '{$this->sDatatableContainerId}',
columns: $sJSColumns,
class_aliases: $sJSClassAliases $sCssCount
});
JS
);
if ($sFakeSortList != '')
{
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
}
return $sHtml;
}
/**
* @param WebPage $oPage
* @param $iDefaultPageSize
* @param $iStart
*/
public function UpdatePager(WebPage $oPage, $iDefaultPageSize, $iStart)
{
$iPageSize = $iDefaultPageSize;
$iPageIndex = 0;
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
if ($iDefaultPageSize < 1)
{
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().hide()");
}
else
{
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().show()");
}
}
}
/**
* Simplified version of the data table with less "decoration" (and no paging)
* which is optimized for printing
*/
class PrintableDataTable extends DataTable
{
/**
* @param WebPage $oPage
* @param $iPageSize
* @param $iDefaultPageSize
* @param $iPageIndex
* @param $aColumns
* @param $bActionsMenu
* @param $bToolkitMenu
* @param $sSelectMode
* @param $bViewLink
* @param $aExtraParams
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public function GetAsHTML(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex, $aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams)
{
return $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, -1, $bViewLink, $aExtraParams);
}
/**
* @param WebPage $oPage
* @param $aColumns
* @param $sSelectMode
* @param $iPageSize
* @param $bViewLink
* @param $aExtraParams
*
* @return string
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
if ($iPageSize < 1)
{
$iPageSize = -1; // convention: no pagination
}
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
$sHtml = $oPage->GetTable($aAttribs, $aValues);
return $sHtml;
}
}

View File

@@ -263,6 +263,8 @@ class DisplayBlock
/** param for export.php */
'refresh_action',
/**to add refresh button in datatable*/
'object_count',
/** int number of objects in list */
], DataTableUIBlockFactory::GetAllowedParams()),
static::ENUM_STYLE_LIST_SEARCH => array_merge([
'update_history',
@@ -1863,7 +1865,11 @@ class MenuBlock extends DisplayBlock
$aSelectedClasses = $this->GetFilter()->GetSelectedClasses();
$bIsForLinkset = isset($aExtraParams['target_attr']);
$oSet = new CMDBObjectSet($this->GetFilter());
$iSetCount = $oSet->Count();
if(isset($aExtraParams['object_count'])){
$iSetCount = $aExtraParams['object_count'];
} else {
$iSetCount = $oSet->Count();
}
/** @var string $sRefreshAction JS snippet to run when clicking on the refresh button of the menu */
$sRefreshAction = $aExtraParams['refresh_action'] ?? '';
$bIsCreationInModal = isset($aExtraParams['creation_in_modal']) && $aExtraParams['creation_in_modal'] === true;
@@ -2218,6 +2224,11 @@ class MenuBlock extends DisplayBlock
$aFavoriteRegularActions[$key] = $aRegularActions[$key];
unset($aRegularActions[$key]);
}
// Toolkit actions
if (isset($aToolkitActions[$key])) {
$aFavoriteRegularActions[$key] = $aToolkitActions[$key];
unset($aToolkitActions[$key]);
}
// Transitions
if (isset($aTransitionActions[$key])) {
@@ -2307,7 +2318,27 @@ class MenuBlock extends DisplayBlock
break;
case 'UI:Menu:EMail':
$sIconClass = 'fas fa-share-alt';
$sIconClass = 'far fa-envelope fa-lg';
$sLabel = '';
break;
case 'UI:Menu:OpenOQL':
$sIconClass = 'fas fa-play fa-sm';
$sLabel = '';
break;
case 'UI:Menu:ExportXLSX':
$sIconClass = 'far fa-file-excel fa-lg';
$sLabel = '';
break;
case 'UI:Menu:CSVExport':
$sIconClass = 'fas fa-file-csv fa-lg';
$sLabel = '';
break;
case 'UI:Menu:PrintableVersion':
$sIconClass = 'fas fa-print';
$sLabel = '';
break;
case 'UI:Menu:ExportPDF':
$sIconClass = 'fas fa-file-pdf fa-lg';
$sLabel = '';
break;
@@ -2319,7 +2350,12 @@ class MenuBlock extends DisplayBlock
}
$sTarget = isset($aAction['target']) ? $aAction['target'] : '';
$oActionButton = ButtonUIBlockFactory::MakeLinkNeutral($sUrl, $sLabel, $sIconClass, $sTarget, utils::Sanitize($sActionId, '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER));
if (!empty($aAction['onclick'])) {
$oActionButton = ButtonUIBlockFactory::MakeIconAction($sIconClass, $aAction['label'], $aAction['label'], $sLabel,false); //utils::Sanitize($sActionId.md5($aAction['onclick']), '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER))
$oActionButton->SetOnClickJsCode($aAction['onclick']);
} else {
$oActionButton = ButtonUIBlockFactory::MakeLinkNeutral($sUrl, $sLabel, $sIconClass, $sTarget, utils::Sanitize($sActionId, '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER));
}
// ResourceId should not be sanitized
$oActionButton->AddDataAttribute('resource-id', $sActionId);
$oActionButton->AddCSSClasses(['ibo-action-button', 'ibo-regular-action-button']);

View File

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

View File

@@ -303,7 +303,7 @@ class ExcelExporter
{
if ($this->sOutputFilePath == null)
{
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.xlsx';
}
else
{
@@ -313,14 +313,14 @@ class ExcelExporter
public static function GetExcelFileFromToken($sToken)
{
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
return @file_get_contents(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
}
public static function CleanupFromToken($sToken)
{
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.status');
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.data');
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
}
public function Cleanup()
@@ -334,7 +334,7 @@ class ExcelExporter
*/
public static function CleanupOldFiles()
{
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
$aFiles = glob(utils::GetDataPath().'bulk_export/*.*');
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
if($iDelay > 0)
@@ -416,14 +416,14 @@ class ExcelExporter
protected function CheckDataDir()
{
if(!is_dir(APPROOT."data/bulk_export"))
if(!is_dir(utils::GetDataPath()."bulk_export"))
{
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
@mkdir(utils::GetDataPath()."bulk_export", 0777, true /* recursive */);
clearstatcache();
}
if (!is_writable(APPROOT."data/bulk_export"))
if (!is_writable(utils::GetDataPath()."bulk_export"))
{
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
throw new Exception('Data directory "'.utils::GetDataPath().'bulk_export" could not be written.');
}
}
@@ -433,12 +433,12 @@ class ExcelExporter
{
$sToken = $this->sToken;
}
return APPROOT."data/bulk_export/$sToken.status";
return utils::GetDataPath()."bulk_export/$sToken.status";
}
protected function GetDataFile()
{
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.data';
}
protected function GetNewToken()

View File

@@ -363,7 +363,7 @@ $('#$sDialogId').dialog({
buttons: [
{ text: "$sOkButtonLabel", click: function() {
var oForm = $(this).closest('.ui-dialog').find('form');
oForm.submit();
oForm.trigger('submit');
if (AnimateDlgButtons)
{
sFormId = oForm.attr('id');
@@ -1501,6 +1501,11 @@ class DesignerIconSelectionField extends DesignerFormField
$this->aAllowedValues = $aAllowedValues;
}
public function AddAllowedValue($aValue)
{
// Add a null value to the list of allowed values
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues);
}
public function EnableUpload($sIconUploadUrl)
{
$this->sUploadUrl = $sIconUploadUrl;

View File

@@ -36,29 +36,30 @@ class InputOutputTask extends cmdbAbstractObject
{
$aParams = array
(
"category" => "application",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_iotask",
"db_key_field" => "id",
"category" => "application",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_iotask",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("category", array("allowed_values"=>new ValueSetEnum('Input, Ouput'), "sql"=>"category", "default_value"=>"Input", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("allowed_values"=>new ValueSetEnum('File, Database, Web Service'), "sql"=>"source_type", "default_value"=>"File", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype", array("allowed_values"=>new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql"=>"source_subtype", "default_value"=>"CSV", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("source_path", array("allowed_values"=>null, "sql"=>"source_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeClass("objects_class", array("class_category"=>"", "more_values"=>"", "sql"=>"objects_class", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"test_mode", "default_value"=>'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"verbose_mode", "default_value" => 'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("options", array("allowed_values"=>new ValueSetEnum('Full, Update Only, Creation Only'), "sql"=>"options", "default_value"=> 'Full', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("category", array("allowed_values" => new ValueSetEnum('Input, Ouput'), "sql" => "category", "default_value" => "Input", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("allowed_values" => new ValueSetEnum('File, Database, Web Service'), "sql" => "source_type", "default_value" => "File", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype",
array("allowed_values" => new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql" => "source_subtype", "default_value" => "CSV", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("source_path", array("allowed_values" => null, "sql" => "source_path", "default_value" => "", "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeClass("objects_class", array("class_category" => "", "more_values" => "", "sql" => "objects_class", "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "class_exclusion_list" => null)));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "test_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("allowed_values" => new ValueSetEnum('Yes,No'), "sql" => "verbose_mode", "default_value" => 'No', "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("options", array("allowed_values" => new ValueSetEnum('Full, Update Only, Creation Only'), "sql" => "options", "default_value" => 'Full', "is_null_allowed" => true, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path' , 'options', 'test_mode', 'verbose_mode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path', 'options', 'test_mode', 'verbose_mode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the std search form

View File

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

View File

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

View File

@@ -91,15 +91,6 @@ function _MaintenanceJsonMessage($sTitle, $sMessage)
$oP->AddData($aMessage);
$oP->Output();
} else {
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
if (class_exists('ajax_page')) {
$oP = new ajax_page($sTitle);
$oP->add_header('Access-Control-Allow-Origin: *');
$oP->SetContentType('application/json');
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
$oP->Output();
} else {
_MaintenanceTextMessage($sMessage);
}
_MaintenanceTextMessage($sMessage);
}
}

View File

@@ -10,7 +10,6 @@ use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/application/template.class.inc.php');
require_once(APPROOT."/application/user.dashboard.class.inc.php");
@@ -999,15 +998,11 @@ class MenuGroup extends MenuNode
*/
class TemplateMenuNode extends MenuNode
{
/**
* @var string
*/
protected $sTemplateFile;
/**
* Create a menu item based on a custom template and inserts it into the application's main menu
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
* @param string $sTemplateFile Path (or URL) to the file that will be used as a template for displaying the page's content
* @param string $sTemplateFile unused deprecated
* @param integer $iParentIndex ID of the parent menu
* @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
* @param string $sEnableClass Name of class of object
@@ -1018,17 +1013,6 @@ class TemplateMenuNode extends MenuNode
public function __construct($sMenuId, $sTemplateFile, $iParentIndex, $fRank = 0.0, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
{
parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
$this->sTemplateFile = $sTemplateFile;
$this->aReflectionProperties['template_file'] = $sTemplateFile;
}
/**
* @inheritDoc
*/
public function GetHyperlink($aExtraParams)
{
if ($this->sTemplateFile == '') return '';
return parent::GetHyperlink($aExtraParams);
}
/**
@@ -1037,18 +1021,7 @@ class TemplateMenuNode extends MenuNode
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$sTemplate = @file_get_contents($this->sTemplateFile);
if ($sTemplate !== false)
{
$aExtraParams['table_id'] = 'Menu_'.$this->GetMenuId();
$oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, $aExtraParams);
}
else
{
$oPage->p("Error: failed to load template file: '{$this->sTemplateFile}'"); // No need to translate ?
}
//DO NOTHING this type of menu is only used for title not clickable
}
}

View File

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

View File

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

View File

@@ -221,17 +221,10 @@ class QueryOQL extends Query
{
try{
// retrieve attributes
$sFields = trim($this->Get('fields'));
$sOql = $this->Get('oql');
// construct base url depending on version
$bExportV1Recommended = ($sFields == '');
if ($bExportV1Recommended) {
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
}
else{
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
}
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
// search object from OQL
$oSearch = DBObjectSearch::FromOQL($sOql);
@@ -256,22 +249,9 @@ class QueryOQL extends Query
$oPage->add_script("$('[name=\"attr_oql\"]').addClass('ibo-query-oql ibo-is-code'); $('[data-attribute-code=\"oql\"]').addClass('ibo-query-oql ibo-is-code');");
if (!$bEditMode) {
$sFields = trim($this->Get('fields'));
$bExportV1Recommended = ($sFields == '');
if ($bExportV1Recommended) {
$oFieldAttDef = MetaModel::GetAttributeDef('QueryOQL', 'fields');
$oAlert = AlertUIBlockFactory::MakeForFailure()
->SetIsClosable(false)
->SetIsCollapsible(false);
$oAlert->AddCSSClass('mb-5');
$oAlert->AddSubBlock(new Html(Dict::Format('UI:Query:UrlV1', '')));
$oPage->AddSubBlock($oAlert);
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
} else {
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
}
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
$sOql = $this->Get('oql');
$sMessage = null;
try {
$oSearch = DBObjectSearch::FromOQL($sOql);
$aParameters = $oSearch->GetQueryParams();

View File

@@ -1,427 +0,0 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'/application/displayblock.class.inc.php');
/**
* This class manages the special template format used internally to build the iTop web pages
*
* @deprecated 3.0.0
*/
class DisplayTemplate
{
protected $m_sTemplate;
protected $m_aTags;
static protected $iBlockCount = 0;
public function __construct($sTemplate)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
$this->m_aTags = array(
'itopblock',
'itopcheck',
'itoptabs',
'itoptab',
'itoptoggle',
'itopstring',
'sqlblock',
);
$this->m_sTemplate = $sTemplate;
}
public function Render(WebPage $oPage, $aParams = array())
{
$this->m_sTemplate = MetaModel::ApplyParams($this->m_sTemplate, $aParams);
$iStart = 0;
$iEnd = strlen($this->m_sTemplate);
$iCount = 0;
$iBeforeTagPos = $iStart;
$iAfterTagPos = $iStart;
while($sTag = $this->GetNextTag($iStart, $iEnd))
{
$sContent = $this->GetTagContent($sTag, $iStart, $iEnd);
$iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
$sOuterTag = substr($this->m_sTemplate, $iStart, $iAfterTagPos - $iStart);
$oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos));
if ($sTag == DisplayBlock::TAG_BLOCK)
{
try
{
$oBlock = DisplayBlock::FromTemplate($sOuterTag);
if (is_object($oBlock))
{
$oBlock->Display($oPage, 'block_'.self::$iBlockCount, $aParams);
}
}
catch(OQLException $e)
{
$oPage->p('Error in template (please contact your administrator) - Invalid query<!--'.$sOuterTag.'-->');
}
catch(Exception $e)
{
$oPage->p('Error in template (please contact your administrator)<!--'.$e->getMessage().'--><!--'.$sOuterTag.'-->');
}
self::$iBlockCount++;
}
else
{
$aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd);
//$oPage->p("Tag: $sTag - ($iStart, $iEnd)");
$this->RenderTag($oPage, $sTag, $aAttributes, $sContent);
}
$iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
$iBeforeTagPos = $iAfterTagPos;
$iStart = $iEnd;
$iEnd = strlen($this->m_sTemplate);
$iCount++;
}
$oPage->add(substr($this->m_sTemplate, $iAfterTagPos));
}
public function GetNextTag(&$iStartPos, &$iEndPos)
{
$iChunkStartPos = $iStartPos;
$sNextTag = null;
$iStartPos = $iEndPos;
foreach($this->m_aTags as $sTag)
{
// Search for the opening tag
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos);
if ($iOpeningPos === false)
{
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos);
}
if ($iOpeningPos !== false)
{
$iClosingPos = stripos($this->m_sTemplate, '</'.$sTag.'>', $iOpeningPos);
}
if ( ($iOpeningPos !== false) && ($iClosingPos !== false))
{
if ($iOpeningPos < $iStartPos)
{
// This is the next tag
$iStartPos = $iOpeningPos;
$iEndPos = $iClosingPos;
$sNextTag = $sTag;
}
}
}
return $sNextTag;
}
public function GetTagContent($sTag, $iStartPos, $iEndPos)
{
$sContent = "";
$iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket
if ($iContentStart !== false)
{
$sContent = substr($this->m_sTemplate, 1+$iContentStart, $iEndPos - $iContentStart - 1);
}
return $sContent;
}
public function GetTagAttributes($sTag, $iStartPos, $iEndPos)
{
$aAttr = array();
$iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space
$iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket
if ( ($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart))
{
$sAttributes = substr($this->m_sTemplate, 1+$iAttrStart, $iAttrEnd - $iAttrStart - 1);
$aAttributes = explode(' ', $sAttributes);
foreach($aAttributes as $sAttr)
{
if ( preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches) )
{
$aAttr[strtolower($aMatches[1])] = $aMatches[2];
}
}
}
return $aAttr;
}
protected function RenderTag($oPage, $sTag, $aAttributes, $sContent)
{
static $iTabContainerCount = 0;
switch($sTag)
{
case 'itoptabs':
$oPage->AddTabContainer('Tabs_'.$iTabContainerCount);
$oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount);
$iTabContainerCount++;
//$oPage->p('Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
$oPage->SetCurrentTabContainer('');
break;
case 'itopcheck':
$sClassName = $aAttributes['class'];
if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ))
{
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
}
else
{
// Leave a trace for those who'd like to understand why nothing is displayed
$oPage->add("<!-- class $sClassName does not exist, skipping some part of the template -->\n");
}
break;
case 'itoptab':
$oPage->SetCurrentTab($aAttributes['name'], str_replace('_', ' ', $aAttributes['name']));
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oPage->SetCurrentTab('');
break;
case 'itoptoggle':
$sName = isset($aAttributes['name']) ? $aAttributes['name'] : 'Tagada';
$bOpen = isset($aAttributes['open']) ? $aAttributes['open'] : true;
$oPage->StartCollapsibleSection(Dict::S($sName), $bOpen);
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
$oPage->EndCollapsibleSection();
break;
case 'itopstring':
$oPage->add(Dict::S($sContent));
break;
case 'sqlblock':
$oBlock = SqlBlock::FromTemplate($sContent);
$oBlock->RenderContent($oPage);
break;
case 'itopblock': // No longer used, handled by DisplayBlock::FromTemplate see above
$oPage->add("<!-- Application Error: should be handled by DisplayBlock::FromTemplate -->");
break;
default:
// Unknown tag, just ignore it or now -- output an HTML comment
$oPage->add("<!-- unsupported tag: $sTag -->");
}
}
/**
* Unit test
*/
static public function UnitTest()
{
require_once(APPROOT.'/application/startup.inc.php');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1>
</div>
<img src="'.$sAppRootUrl.'images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itoptabs>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Contact AS c JOIN lnkContactToCI AS l ON l.contact_id = c.id WHERE l.ci_id = $id$</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Document AS d JOIN lnkDocumentToCI as l ON l.document_id = d.id WHERE l.ci_id = $id$)</itopblock>
</itoptab>
</itoptabs>';
$oPage = new iTopWebPage('Unit Test');
//$oPage->add("Template content: <pre>".htmlentities($sTemplate, ENT_QUOTES, 'UTF-8')."</pre>\n");
$oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, array('class'=>'Network device','pkey'=> 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3));
$oPage->output();
}
}
/**
* Special type of template for displaying the details of an object
* On top of the defaut 'blocks' managed by the parent class, the following placeholders
* are available in such a template:
* $attribute_code$ An attribute of the object (in edit mode this is the input for the attribute)
* $attribute_code->label()$ The label of an attribute
* $PlugIn:plugInClass->properties()$ The ouput of OnDisplayProperties of the specified plugInClass
*/
class ObjectDetailsTemplate extends DisplayTemplate
{
public function __construct($sTemplate, $oObj, $sFormPrefix = '')
{
parent::__construct($sTemplate);
$this->m_oObj = $oObj;
$this->m_sPrefix = $sFormPrefix;
}
public function Render(WebPage $oPage, $aParams = array(), $bEditMode = false)
{
$sStateAttCode = MetaModel :: GetStateAttributeCode(get_class($this->m_oObj));
$aTemplateFields = array();
preg_match_all('/\\$this->([a-z0-9_]+)\\$/', $this->m_sTemplate, $aMatches);
foreach ($aMatches[1] as $sAttCode)
{
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode;
}
else
{
$aParams['this->'.$sAttCode] = "<!--Unknown attribute: $sAttCode-->";
}
}
preg_match_all('/\\$this->field\\(([a-z0-9_]+)\\)\\$/', $this->m_sTemplate, $aMatches);
foreach ($aMatches[1] as $sAttCode)
{
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode;
}
else
{
$aParams['this->field('.$sAttCode.')'] = "<!--Unknown attribute: $sAttCode-->";
}
}
$aFieldsComments = (isset($aParams['fieldsComments'])) ? $aParams['fieldsComments'] : array();
$aFieldsMap = array();
$sClass = get_class($this->m_oObj);
// Renders the fields used in the template
foreach(MetaModel::ListAttributeDefs(get_class($this->m_oObj)) as $sAttCode => $oAttDef)
{
$aParams['this->label('.$sAttCode.')'] = $oAttDef->GetLabel();
$aParams['this->comments('.$sAttCode.')'] = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '';
$iInputId = '2_'.$sAttCode; // TODO: generate a real/unique prefix...
if (in_array($sAttCode, $aTemplateFields))
{
if ($this->m_oObj->IsNew())
{
$iFlags = $this->m_oObj->GetInitialStateAttributeFlags($sAttCode);
}
else
{
$iFlags = $this->m_oObj->GetAttributeFlags($sAttCode);
}
if (($iFlags & OPT_ATT_MANDATORY) && $this->m_oObj->IsNew())
{
$iFlags = $iFlags & ~OPT_ATT_READONLY; // Mandatory fields cannot be read-only when creating an object
}
if ((!$oAttDef->IsWritable()) || ($sStateAttCode == $sAttCode))
{
$iFlags = $iFlags | OPT_ATT_READONLY;
}
if ($iFlags & OPT_ATT_HIDDEN)
{
$aParams['this->label('.$sAttCode.')'] = '';
$aParams['this->field('.$sAttCode.')'] = '';
$aParams['this->comments('.$sAttCode.')'] = '';
$aParams['this->'.$sAttCode] = '';
}
else
{
if ($bEditMode && ($iFlags & (OPT_ATT_READONLY|OPT_ATT_SLAVE)))
{
// Check if the attribute is not read-only because of a synchro...
$aReasons = array();
$sSynchroIcon = '';
if ($iFlags & OPT_ATT_SLAVE)
{
$iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sAppRooturl = utils::GetAbsoluteUrlAppRoot();
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = '';
foreach($aReasons as $aRow)
{
$sDescription = utils::EscapeHtml($aRow['description']);
$sDescription = str_replace(array("\r\n", "\n"), "<br/>", $sDescription);
$sTip .= "<div class='synchro-source'>";
$sTip .= "<div class='synchro-source-title'>Synchronized with {$aRow['name']}</div>";
$sTip .= "<div class='synchro-source-description'>$sDescription</div>";
}
$oPage->add_ready_script("$('#synchro_$iInputId').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
// Attribute is read-only
$sHTMLValue = "<span id=\"field_{$iInputId}\">".$this->m_oObj->GetAsHTML($sAttCode);
$sHTMLValue .= '<input type="hidden" id="'.$iInputId.'" name="attr_'.$sAttCode.'" value="'.utils::EscapeHtml($this->m_oObj->Get($sAttCode)).'"/></span>';
$aFieldsMap[$sAttCode] = $iInputId;
$aParams['this->comments('.$sAttCode.')'] = $sSynchroIcon;
}
if ($bEditMode && !($iFlags & OPT_ATT_READONLY)) //TODO: check the data synchro status...
{
$aParams['this->field('.$sAttCode.')'] = "<span id=\"field_{$iInputId}\">".$this->m_oObj->GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,
$this->m_oObj->Get($sAttCode),
$this->m_oObj->GetEditValue($sAttCode),
$iInputId, // InputID
'',
$iFlags,
array('this' => $this->m_oObj) // aArgs
).'</span>';
$aFieldsMap[$sAttCode] = $iInputId;
}
else
{
$aParams['this->field('.$sAttCode.')'] = $this->m_oObj->GetAsHTML($sAttCode);
}
$aParams['this->'.$sAttCode] = "<table class=\"field\"><tr><td class=\"label\">".$aParams['this->label('.$sAttCode.')'].":</td><td>".$aParams['this->field('.$sAttCode.')']."</td><td>".$aParams['this->comments('.$sAttCode.')']."</td></tr></table>";
}
}
}
// Renders the PlugIns used in the template
preg_match_all('/\\$PlugIn:([A-Za-z0-9_]+)->properties\\(\\)\\$/', $this->m_sTemplate, $aMatches);
$aPlugInProperties = $aMatches[1];
foreach($aPlugInProperties as $sPlugInClass)
{
/** @var \iApplicationUIExtension $oInstance */
$oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass);
if ($oInstance != null) // Safety check...
{
$offset = $oPage->start_capture();
$oInstance->OnDisplayProperties($this->m_oObj, $oPage, $bEditMode);
$sContent = $oPage->end_capture($offset);
$aParams["PlugIn:{$sPlugInClass}->properties()"]= $sContent;
}
else
{
$aParams["PlugIn:{$sPlugInClass}->properties()"]= "Missing PlugIn: $sPlugInClass";
}
}
$offset = $oPage->start_capture();
parent::Render($oPage, $aParams);
$sContent = $oPage->end_capture($offset);
// Remove empty table rows in case some attributes are hidden...
$sContent = preg_replace('/<tr[^>]*>\s*(<td[^>]*>\s*<\\/td>)+\s*<\\/tr>/im', '', $sContent);
$oPage->add($sContent);
return $aFieldsMap;
}
}
//DisplayTemplate::UnitTest();
?>

View File

@@ -55,18 +55,6 @@ class ThemeHandler
];
}
/**
* Return the ID of the theme currently defined in the config. file
*
* @deprecated 3.0.0, will be removed in 3.1, see N°3898
* @return string
*/
public static function GetCurrentThemeId()
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
static::GetCurrentUserThemeId();
}
/**
* @return string ID of the theme currently defined in the config. file, which applies to all users by default. If non defined, fallback on the default one.
* @since 3.0.0

View File

@@ -228,7 +228,7 @@ class privUITransactionFile
*/
public static function GetNewTransactionId()
{
if (!is_dir(APPROOT.'data/transactions'))
if (!is_dir(utils::GetDataPath().'transactions'))
{
if (!is_writable(APPROOT.'data'))
{
@@ -236,22 +236,22 @@ class privUITransactionFile
}
// condition avoids race condition N°2345
// See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition
if (!mkdir($concurrentDirectory = APPROOT.'data/transactions') && !is_dir($concurrentDirectory))
if (!mkdir($concurrentDirectory = utils::GetDataPath().'transactions') && !is_dir($concurrentDirectory))
{
throw new Exception('Failed to create the directory "'.APPROOT.'data/transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
throw new Exception('Failed to create the directory "'.utils::GetDataPath().'transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
}
}
if (!is_writable(APPROOT.'data/transactions'))
if (!is_writable(utils::GetDataPath().'transactions'))
{
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
throw new Exception('The directory "'.utils::GetDataPath().'transactions" must be writable to the application.');
}
$iCurrentUserId = static::GetCurrentUserId();
self::CleanupOldTransactions();
$sTransactionIdFullPath = tempnam(APPROOT.'data/transactions', static::GetUserPrefix());
$sTransactionIdFullPath = tempnam(utils::GetDataPath().'transactions', static::GetUserPrefix());
file_put_contents($sTransactionIdFullPath, $iCurrentUserId, LOCK_EX);
$sTransactionIdFileName = basename($sTransactionIdFullPath);
@@ -274,8 +274,8 @@ class privUITransactionFile
*/
public static function IsTransactionValid($id, $bRemoveTransaction = true)
{
// Constraint the transaction file within APPROOT.'data/transactions'
$sTransactionDir = realpath(APPROOT.'data/transactions');
// Constraint the transaction file within utils::GetDataPath().'transactions'
$sTransactionDir = realpath(utils::GetDataPath().'transactions');
$sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir);
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath)))
{
@@ -348,7 +348,7 @@ class privUITransactionFile
clearstatcache();
$iLimit = time() - 24*3600;
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : APPROOT.'data/transactions/*';
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : utils::GetDataPath().'transactions/*';
$aTransactions = glob($sPattern);
foreach($aTransactions as $sFileName)
{
@@ -368,7 +368,7 @@ class privUITransactionFile
{
clearstatcache();
$aResult = array();
$aTransactions = glob(APPROOT.'data/transactions/'.self::GetUserPrefix().'*');
$aTransactions = glob(utils::GetDataPath().'transactions/'.self::GetUserPrefix().'*');
foreach($aTransactions as $sFileName)
{
$aResult[] = date('Y-m-d H:i:s', filemtime($sFileName)).' - '.basename($sFileName);

View File

@@ -1,127 +0,0 @@
<?php
namespace Combodo\iTop;
use AttributeDate;
use AttributeDateTime;
use DeprecatedCallsLog;
use Dict;
use Exception;
use MetaModel;
use Twig\Environment;
use Twig\TwigFilter;
use Twig\TwigFunction;
use utils;
DeprecatedCallsLog::NotifyDeprecatedFile('instead use sources/Application/TwigBase/Twig/Extension.php, which is loaded by the autoloader');
/**
* Class TwigExtension
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @package Combodo\iTop
* @deprecated 3.1.0 N°4034
*/
class TwigExtension
{
/**
* Registers Twig extensions such as filters or functions.
* It allows us to access some stuff directly in twig.
*
* @param Environment $oTwigEnv
*/
public static function RegisterTwigExtensions(Environment &$oTwigEnv)
{
// Filter to translate a string via the Dict::S function
// Usage in twig: {{ 'String:ToTranslate'|dict_s }}
$oTwigEnv->addFilter(new TwigFilter('dict_s',
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
})
);
// Filter to format a string via the Dict::Format function
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
$oTwigEnv->addFilter(new TwigFilter('dict_format',
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
})
);
// Filter to format output
// example a DateTime is converted to user format
// Usage in twig: {{ 'String:ToFormat'|output_format }}
$oTwigEnv->addFilter(new TwigFilter('date_format',
function ($sDate) {
try {
if (preg_match('@^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$@', trim($sDate))) {
return AttributeDateTime::GetFormat()->Format($sDate);
}
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate))) {
return AttributeDate::GetFormat()->Format($sDate);
}
}
catch (Exception $e)
{
}
return $sDate;
})
);
// Filter to format output
// example a DateTime is converted to user format
// Usage in twig: {{ 'String:ToFormat'|output_format }}
$oTwigEnv->addFilter(new TwigFilter('size_format',
function ($sSize) {
return utils::BytesToFriendlyFormat($sSize);
})
);
// Filter to enable base64 encode/decode
// Usage in twig: {{ 'String to encode'|base64_encode }}
$oTwigEnv->addFilter(new TwigFilter('base64_encode', 'base64_encode'));
$oTwigEnv->addFilter(new TwigFilter('base64_decode', 'base64_decode'));
// Filter to enable json decode (encode already exists)
// Usage in twig: {{ aSomeArray|json_decode }}
$oTwigEnv->addFilter(new TwigFilter('json_decode', function ($sJsonString, $bAssoc = false) {
return json_decode($sJsonString, $bAssoc);
})
);
// Filter to add itopversion to an url
$oTwigEnv->addFilter(new TwigFilter('add_itop_version', function ($sUrl) {
$sUrl = utils::AddParameterToUrl($sUrl, 'itopversion', ITOP_VERSION);
return $sUrl;
}));
// Filter to add a module's version to an url
$oTwigEnv->addFilter(new TwigFilter('add_module_version', function ($sUrl, $sModuleName) {
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
$sUrl = utils::AddParameterToUrl($sUrl, 'moduleversion', $sModuleVersion);
return $sUrl;
}));
// Function to check our current environment
// Usage in twig: {% if is_development_environment() %}
$oTwigEnv->addFunction(new TwigFunction('is_development_environment', function () {
return utils::IsDevelopmentEnvironment();
}));
// Function to get the URL of a static page in a module
// Usage in twig: {{ get_static_page_module_url('itop-my-module', 'path-to-my-page') }}
$oTwigEnv->addFunction(new TwigFunction('get_static_page_module_url', function ($sModuleName, $sPage) {
return utils::GetAbsoluteUrlModulesRoot().$sModuleName.'/'.$sPage;
}));
// Function to get the URL of a php page in a module
// Usage in twig: {{ get_page_module_url('itop-my-module', 'path-to-my-my-page.php') }}
$oTwigEnv->addFunction(new TwigFunction('get_page_module_url', function ($sModuleName, $sPage) {
return utils::GetAbsoluteUrlModulePage($sModuleName, $sPage);
}));
}
}

View File

@@ -1570,9 +1570,6 @@ class utils
$oContainerBlock->AddJsFileRelPath('js/tabularfieldsselector.js');
$oContainerBlock->AddJsFileRelPath('js/jquery.dragtable.js');
$oContainerBlock->AddCssFileRelPath('css/dragtable.css');
$oContainerBlock->AddJsFileRelPath('js/tabularfieldsselector.js');
$oContainerBlock->AddJsFileRelPath('js/jquery.dragtable.js');
$oContainerBlock->AddCssFileRelPath('css/dragtable.css');
$aResult = array(
new SeparatorPopupMenuItem(),
@@ -2315,97 +2312,6 @@ SQL;
return @getimagesizefromstring($sImageData);
}
/**
* Resize an image attachment so that it fits in the given dimensions
* @param ormDocument $oImage The original image stored as an ormDocument
* @param int $iWidth Image's original width
* @param int $iHeight Image's original height
* @param int $iMaxImageWidth Maximum width for the resized image
* @param int $iMaxImageHeight Maximum height for the resized image
* @return ormDocument The resampled image
*/
public static function ResizeImageToFit(ormDocument $oImage, $iWidth, $iHeight, $iMaxImageWidth, $iMaxImageHeight)
{
// If image size smaller than maximums, we do nothing
if (($iWidth <= $iMaxImageWidth) && ($iHeight <= $iMaxImageHeight))
{
return $oImage;
}
// If gd extension is not loaded, we put a warning in the log and return the image as is
if (extension_loaded('gd') === false)
{
IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. It will remain as ' . $iWidth . 'x' . $iHeight . ' instead of ' . $iMaxImageWidth . 'x' . $iMaxImageHeight);
return $oImage;
}
switch($oImage->GetMimeType())
{
case 'image/gif':
case 'image/jpeg':
case 'image/png':
$img = @imagecreatefromstring($oImage->GetData());
break;
default:
// Unsupported image type, return the image as-is
//throw new Exception("Unsupported image type: '".$oImage->GetMimeType()."'. Cannot resize the image, original image will be used.");
return $oImage;
}
if ($img === false)
{
//throw new Exception("Warning: corrupted image: '".$oImage->GetFileName()." / ".$oImage->GetMimeType()."'. Cannot resize the image, original image will be used.");
return $oImage;
}
else
{
// Let's scale the image, preserving the transparency for GIFs and PNGs
$fScale = min($iMaxImageWidth / $iWidth, $iMaxImageHeight / $iHeight);
$iNewWidth = $iWidth * $fScale;
$iNewHeight = $iHeight * $fScale;
$new = imagecreatetruecolor($iNewWidth, $iNewHeight);
// Preserve transparency
if(($oImage->GetMimeType() == "image/gif") || ($oImage->GetMimeType() == "image/png"))
{
imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
imagealphablending($new, false);
imagesavealpha($new, true);
}
imagecopyresampled($new, $img, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iWidth, $iHeight);
ob_start();
switch ($oImage->GetMimeType())
{
case 'image/gif':
imagegif($new); // send image to output buffer
break;
case 'image/jpeg':
imagejpeg($new, null, 80); // null = send image to output buffer, 80 = good quality
break;
case 'image/png':
imagepng($new, null, 5); // null = send image to output buffer, 5 = medium compression
break;
}
$oResampledImage = new ormDocument(ob_get_contents(), $oImage->GetMimeType(), $oImage->GetFileName());
@ob_end_clean();
imagedestroy($img);
imagedestroy($new);
return $oResampledImage;
}
}
/**
* Create a 128 bit UUID in the format: {########-####-####-####-############}
*
@@ -2896,21 +2802,6 @@ TXT
return static::$iNextId++;
}
/**
* @param string $sInterface
* @param string $sClassNameFilter
* @param array $aExcludedPath Reg. exp. of the paths to exclude. Note that backslashes (typically for Windows env.) need to be 4 backslashes, 2 for the escaping backslash, 2 for the actual backslash 😅
*
* @return array classes are returned in the same order as the module dependency tree, so core classes on top
* @since 3.0.0
* @deprecated 3.2.0 Use {@see InterfaceDiscovery::FindItopClasses()} instead
*/
public static function GetClassesForInterface(string $sInterface, string $sClassNameFilter = '', $aExcludedPath = []): array
{
$oInterfaceDiscoveryService = InterfaceDiscovery::GetInstance();
return $oInterfaceDiscoveryService->FindItopClasses($sInterface);
}
/**
* @return array All keyboard shortcuts config as an array
* @throws \CoreException

View File

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

View File

@@ -350,22 +350,6 @@ class WizardHelper
return $this->m_aData['m_bReturnNotEditableFields'] ?? false;
}
/**
* @return string JS code to be executed for fields update
* @since 3.0.0 N°3198
* @deprecated 3.0.3-2 3.0.4 3.1.1 3.2.0 Use {@see \WizardHelper::AddJsForUpdateFields()} instead
*/
public function GetJsForUpdateFields()
{
$sWizardHelperJsVar = (!is_null($this->m_aData['m_sWizHelperJsVarName'])) ? utils::Sanitize($this->m_aData['m_sWizHelperJsVarName'], '', utils::ENUM_SANITIZATION_FILTER_PARAMETER) : 'oWizardHelper'.$this->GetFormPrefix();
$sWizardHelperJson = $this->ToJSON();
return <<<JS
{$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson};
{$sWizardHelperJsVar}.UpdateFields();
JS;
}
/**
* Add necessary JS snippets (to the page) to be executed for fields update
*

View File

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

View File

@@ -11,7 +11,7 @@ define('APPCONF', APPROOT.'conf/');
*
* @see ITOP_CORE_VERSION to get full iTop core version
*/
define('ITOP_DESIGN_LATEST_VERSION', '3.2');
define('ITOP_DESIGN_LATEST_VERSION', '3.3');
/**
* Constant containing the iTop core version, whatever application was built
@@ -23,7 +23,7 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.2');
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '3.2.1');
define('ITOP_CORE_VERSION', '3.3.0');
/**
* @var string

View File

@@ -18,7 +18,7 @@
"laminas/laminas-mail": "^2.11",
"laminas/laminas-servicemanager": "^3.5",
"league/oauth2-google": "^4.0.1",
"nikic/php-parser": "^4.14.0",
"nikic/php-parser": "~5.6.0",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "^7.2.0",
"psr/log": "^3.0.0",
@@ -72,7 +72,6 @@
"sources"
],
"exclude-from-classmap": [
"application/twigextension.class.inc.php",
"core/oql/build/PHP/",
"core/apc-emulation.php",
"application/startup.inc.php",

748
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,937 +0,0 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Service\Notification\NotificationsRepository;
use Combodo\iTop\Service\Notification\NotificationsService;
use Combodo\iTop\Service\Router\Router;
/**
* Persistent classes (internal): user defined actions
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/asynctask.class.inc.php');
require_once(APPROOT.'/core/email.class.inc.php');
/**
* A user defined action, to customize the application
*
* @package iTopORM
*/
abstract class Action extends cmdbAbstractObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
(
"category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "name",
"complementary_name_attcode" => ['finalclass', 'description'],
"state_attcode" => "status",
"reconc_keys" => ['name'],
"db_table" => "priv_action",
"db_key_field" => "id",
"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'),
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values" => null, "sql" => "name", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array(
"allowed_values" => new ValueSetEnum(array('test' => 'Being tested', 'enabled' => 'In production', 'disabled' => 'Inactive')),
"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),
'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),
'disabled' => new ormStyle('ibo-dm-enum--Action-status-disabled', 'ibo-dm-enum-alt--Action-status-disabled', 'var(--ibo-dm-enum--Action-status-disabled--main-color)', 'var(--ibo-dm-enum--Action-status-disabled--complementary-color)', null, null),
],
"display_style" => 'list',
"sql" => "status",
"default_value" => "test",
"is_null_allowed" => false,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list",
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')));
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())));
// Display lists
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status'));
// Search criteria
// - Default criteria of the search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status'));
}
/**
* Encapsulate the execution of the action and handle failure & logging
*
* @param \Trigger $oTrigger
* @param array $aContextArgs
*
* @return mixed
*/
abstract public function DoExecute($oTrigger, $aContextArgs);
/**
* @return bool
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function IsActive()
{
switch($this->Get('status'))
{
case 'enabled':
case 'test':
return true;
default:
return false;
}
}
/**
* Return true if the current action status is set on "test"
*
* @return bool
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function IsBeingTested()
{
switch($this->Get('status'))
{
case 'test':
return true;
default:
return false;
}
}
/**
* @inheritDoc
* @since 3.0.0
*/
public function AfterInsert()
{
parent::AfterInsert();
$this->DoCheckIfHasTrigger();
}
/**
* @inheritDoc
* @since 3.0.0
*/
public function AfterUpdate()
{
parent::AfterUpdate();
$this->DoCheckIfHasTrigger();
}
/**
* Check if the Action has at least 1 trigger linked. Otherwise, it adds a warning.
* @return void
* @since 3.0.0
*/
protected function DoCheckIfHasTrigger()
{
$oTriggersSet = $this->Get('trigger_list');
if ($oTriggersSet->Count() === 0) {
$this->m_aCheckWarnings[] = Dict::S('Action:WarningNoTriggerLinked');
}
}
/**
* @since 3.2.0 N°5472 method creation
*/
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
parent::DisplayBareRelations($oPage, false);
if ($oPage instanceof iTopWebPage && !$this->IsNew()) {
$this->GenerateLastExecutionsTab($oPage, $bEditMode);
}
}
/**
* @since 3.2.0 N°5472 method creation
*/
protected function GenerateLastExecutionsTab(iTopWebPage $oPage, $bEditMode)
{
$oRouter = Router::GetInstance();
$sActionLastExecutionsPageUrl = $oRouter->GenerateUrl('notifications.action.last_executions_tab', ['action_id' => $this->GetKey()]);
$oPage->AddAjaxTab('action_errors', $sActionLastExecutionsPageUrl, false, Dict::S('Action:last_executions_tab'));
}
/**
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
* @throws \ApplicationException
* @throws \ArchivedObjectException
* @throws \ConfigException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \InvalidConfigParamException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \ReflectionException
* @since 3.2.0 N°5472 method creation
*/
public function GetLastExecutionsTabContent(WebPage $oPage): void
{
$oConfig = utils::GetConfig();
$sLastExecutionDaysConfigParamName = 'notifications.last_executions_days';
$iLastExecutionDays = $oConfig->Get($sLastExecutionDaysConfigParamName);
if ($iLastExecutionDays < 0) {
throw new InvalidConfigParamException("Invalid value for {$sLastExecutionDaysConfigParamName} config parameter. Param desc: " . $oConfig->GetDescription($sLastExecutionDaysConfigParamName));
}
$sActionQueryOql = 'SELECT EventNotification WHERE action_id = :action_id';
$aActionQueryParams = ['action_id' => $this->GetKey()];
if ($iLastExecutionDays > 0) {
$sActionQueryOql .= ' AND date > DATE_SUB(NOW(), INTERVAL :days DAY)';
$aActionQueryParams['days'] = $iLastExecutionDays;
$sActionQueryLimit = Dict::Format('Action:last_executions_tab_limit_days', $iLastExecutionDays);
} else {
$sActionQueryLimit = Dict::S('Action:last_executions_tab_limit_none');
}
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle]);
$oPage->AddUiBlock($oExecutionsListBlock);
}
/**
* Will be overloaded by the children classes to return the value of their global asynchronous setting (eg. `email_asynchronous` for `\ActionEmail`, `prefer_asynchronous` for `\ActionWebhook`, ...)
*
* @return bool true if the global setting for this kind of action if to be executed asynchronously, false otherwise.
* @since 3.2.0
*/
public static function GetAsynchronousGlobalSetting(): bool
{
return false;
}
/**
* @return bool true if that action instance should be executed asynchronously, otherwise false
* @throws \ArchivedObjectException
* @throws \CoreException
* @since 3.2.0
*/
public function IsAsynchronous(): bool
{
$sAsynchronous = $this->Get('asynchronous');
if ($sAsynchronous === 'use_global_setting') {
return static::GetAsynchronousGlobalSetting();
}
return $sAsynchronous === 'yes';
}
}
/**
* A notification
*
* @package iTopORM
*/
abstract class ActionNotification extends Action
{
/**
* @inheritDoc
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
(
"category" => "grant_by_profile,core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "name",
"complementary_name_attcode" => ['finalclass', 'description'],
"state_attcode" => "",
"reconc_keys" => ['name'],
"db_table" => "priv_action_notification",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'description', 'status'));
MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql"=>"language", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Search criteria
// - Criteria of the std search form
// MetaModel::Init_SetZListItems('standard_search', array('name'));
// - Default criteria of the search form
// MetaModel::Init_SetZListItems('default_search', array('name'));
}
/**
* @param $sLanguage
* @param $sLanguageCode
*
* @return array [$sPreviousLanguage, $aPreviousPluginProperties]
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @since 3.2.0
*/
public function SetNotificationLanguage($sLanguage = null, $sLanguageCode = null){
$sPreviousLanguage = Dict::GetUserLanguage();
$aPreviousPluginProperties = ApplicationContext::GetPluginProperties('QueryLocalizerPlugin');
$sLanguage = $sLanguage ?? $this->Get('language');
$sLanguageCode = $sLanguageCode ?? $sLanguage;
if (!utils::IsNullOrEmptyString($sLanguage)) {
// If a language is specified for this action, force this language
// when rendering all placeholders inside this message
Dict::SetUserLanguage($sLanguage);
AttributeDateTime::LoadFormatFromConfig();
ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', $sLanguageCode);
}
return [$sPreviousLanguage, $aPreviousPluginProperties];
}
}
/**
* An email notification
*
* @package iTopORM
*/
class ActionEmail extends ActionNotification
{
/**
* @var string
* @since 3.0.1
*/
const ENUM_HEADER_NAME_MESSAGE_ID = 'Message-ID';
/**
* @var string
* @since 3.0.1
*/
const ENUM_HEADER_NAME_REFERENCES = 'References';
/**
* @var string
* @since 3.1.0
*/
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
* @var string
* @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>';
/**
* 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
*/
const FIELD_HIGHLIGHT = '<span style="background-color:#6800ff;color:#fff;font-size:smaller;font-family:Courier New, sans-serif;padding:2px;">\\$$1\\$</span>';
/**
* @inheritDoc
*/
public static function Init()
{
$aParams = array
(
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array('name'),
"db_table" => "priv_action_email",
"db_key_field" => "id",
"db_finalclass_field" => "",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-mailing.svg'),
);
MetaModel::Init_Params($aParams);
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 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())));
// Display lists
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array(
'col:col1' => array(
'fieldset:ActionEmail:main' => array(
0 => 'name',
1 => 'description',
2 => 'status',
3 => 'language',
4 => 'html_template',
5 => 'subject',
6 => 'body',
// 5 => 'importance', not handled when sending the mail, better hide it then
),
'fieldset:ActionEmail:trigger' => array(
0 => 'trigger_list',
1 => 'asynchronous'
),
),
'col:col2' => array(
'fieldset:ActionEmail:recipients' => array(
0 => 'from',
1 => 'from_label',
2 => 'reply_to',
3 => 'reply_to_label',
4 => 'test_recipient',
5 => 'ignore_notify',
6 => 'to',
7 => 'cc',
8 => 'bcc',
),
),
));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('status', 'to', 'subject', 'language'));
// Search criteria
// - Standard criteria of the search
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'status', 'subject', 'language'));
// - Default criteria for the search
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status', 'subject', 'language'));
}
// count the recipients found
protected $m_iRecipients;
// Errors management : not that simple because we need that function to be
// executed in the background, while making sure that any issue would be reported clearly
protected $m_aMailErrors; //array of strings explaining the issue
/**
* Return the list of emails as a string, or a detailed error description
*
* @param string $sRecipAttCode
* @param array $aArgs
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
protected function FindRecipients($sRecipAttCode, $aArgs)
{
$oTrigger = $aArgs['trigger->object()'] ?? null;
$sOQL = $this->Get($sRecipAttCode);
if (utils::IsNullOrEmptyString($sOQL)) return '';
try
{
$oSearch = DBObjectSearch::FromOQL($sOQL);
if ($this->Get('ignore_notify') === 'no') {
// In theory, it is possible to notify *any* kind of object,
// as long as there is an email attribute in the class
// So let's not assume that the selected class is a Person
$sFirstSelectedClass = $oSearch->GetClass();
if (MetaModel::IsValidAttCode($sFirstSelectedClass, 'notify')) {
$oSearch->AddCondition('notify', 'yes');
}
}
$oSearch->AllowAllData();
}
catch (OQLException $e)
{
$this->m_aMailErrors[] = "query syntax error for recipient '$sRecipAttCode'";
return $e->getMessage();
}
$sClass = $oSearch->GetClass();
// Determine the email attribute (the first one will be our choice)
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if ($oAttDef instanceof AttributeEmailAddress)
{
$sEmailAttCode = $sAttCode;
// we've got one, exit the loop
break;
}
}
if (!isset($sEmailAttCode))
{
$this->m_aMailErrors[] = "wrong target for recipient '$sRecipAttCode'";
return "The objects of the class '$sClass' do not have any email attribute";
}
if($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
$aArgs['trigger_id'] = $oTrigger->GetKey();
$aArgs['action_id'] = $this->GetKey();
$sSubscribedContactsOQL = NotificationsRepository::GetInstance()->GetSearchOQLContactUnsubscribedByTriggerAndAction();
$sSubscribedContactsOQL->ApplyParameters($aArgs);
$sAlias = $oSearch->GetClassAlias();
$oSearch->AddConditionExpression(Expression::FromOQL("`$sAlias`.id NOT IN ($sSubscribedContactsOQL)"));
}
$oSet = new DBObjectSet($oSearch, array() /* order */, $aArgs);
$aRecipients = array();
while ($oObj = $oSet->Fetch())
{
$sAddress = trim($oObj->Get($sEmailAttCode));
if (utils::IsNotNullOrEmptyString($sAddress))
{
$aRecipients[] = $sAddress;
$this->m_iRecipients++;
}
if ($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oObj);
}
}
return implode(', ', $aRecipients);
}
/**
* @inheritDoc
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
*/
public function DoExecute($oTrigger, $aContextArgs)
{
if (MetaModel::IsLogEnabledNotification())
{
$oLog = new EventNotificationEmail();
if ($this->IsBeingTested())
{
$oLog->Set('message', 'TEST - Notification sent ('.$this->Get('test_recipient').')');
}
else
{
$oLog->Set('message', 'Notification pending');
}
$oLog->Set('userinfo', UserRights::GetUser());
$oLog->Set('trigger_id', $oTrigger->GetKey());
$oLog->Set('action_id', $this->GetKey());
$oLog->Set('object_id', $aContextArgs['this->object()']->GetKey());
// Must be inserted now so that it gets a valid id that will make the link
// between an eventual asynchronous task (queued) and the log
$oLog->DBInsertNoReload();
}
else
{
$oLog = null;
}
try
{
$sRes = $this->_DoExecute($oTrigger, $aContextArgs, $oLog);
if ($this->IsBeingTested())
{
$sPrefix = 'TEST ('.$this->Get('test_recipient').') - ';
}
else
{
$sPrefix = '';
}
if ($oLog)
{
$oLog->Set('message', $sPrefix . $sRes);
$oLog->DBUpdate();
}
}
catch (Exception $e)
{
if ($oLog)
{
$oLog->Set('message', 'Error: '.$e->getMessage());
try
{
$oLog->DBUpdate();
}
catch (Exception $eSecondTryUpdate)
{
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->DBUpdate();
}
}
}
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
* @param \EventNotification $oLog
*
* @return string
* @throws \CoreException
* @throws \Exception
*/
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
{
$sStyles = file_get_contents(APPROOT . utils::GetCSSFromSASS("css/email.scss"));
$sStyles .= MetaModel::GetConfig()->Get('email_css');
$oEmail = new EMail();
$aEmailContent = $this->PrepareMessageContent($aContextArgs, $oLog);
$oEmail->SetSubject($aEmailContent['subject']);
$oEmail->SetBody($aEmailContent['body'], 'text/html', $sStyles);
$oEmail->SetRecipientTO($aEmailContent['to']);
$oEmail->SetRecipientCC($aEmailContent['cc']);
$oEmail->SetRecipientBCC($aEmailContent['bcc']);
$oEmail->SetRecipientFrom($aEmailContent['from'], $aEmailContent['from_label']);
$oEmail->SetRecipientReplyTo($aEmailContent['reply_to'], $aEmailContent['reply_to_label']);
$oEmail->SetReferences($aEmailContent['references']);
$oEmail->SetMessageId($aEmailContent['message_id']);
$oEmail->SetInReplyTo($aEmailContent['in_reply_to']);
foreach($aEmailContent['attachments'] as $aAttachment) {
$oEmail->AddAttachment($aAttachment['data'], $aAttachment['filename'], $aAttachment['mime_type']);
}
if (empty($this->m_aMailErrors))
{
if ($this->m_iRecipients == 0)
{
return 'No recipient';
}
else
{
$aErrors = [];
$iRes = $oEmail->Send($aErrors, $this->IsAsynchronous() ? Email::ENUM_SEND_FORCE_ASYNCHRONOUS : Email::ENUM_SEND_FORCE_SYNCHRONOUS, $oLog);
switch ($iRes)
{
case EMAIL_SEND_OK:
return "Sent";
case EMAIL_SEND_PENDING:
return "Pending";
case EMAIL_SEND_ERROR:
return "Errors: ".implode(', ', $aErrors);
}
}
} else {
if (is_array($this->m_aMailErrors) && count($this->m_aMailErrors) > 0) {
$sError = implode(', ', $this->m_aMailErrors);
} else {
$sError = 'Unknown reason';
}
return 'Notification was not sent: '.$sError;
}
}
/**
* @param array $aContextArgs
* @param \EventNotification $oLog
*
* @return array
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \DictExceptionMissingString
* @throws \DictExceptionUnknownLanguage
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @since 3.1.0 N°918
*/
protected function PrepareMessageContent($aContextArgs, &$oLog): array
{
$aMessageContent = [
'to' => '',
'cc' => '',
'bcc' => '',
'from' => '',
'from_label' => '',
'reply_to' => '',
'reply_to_label' => '',
'subject' => '',
'body' => '',
'references' => '',
'message_id' => '',
'in_reply_to' => '',
'attachments' => [],
];
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();
[$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage();
try
{
$this->m_iRecipients = 0;
$this->m_aMailErrors = array();
// Determine recipients
//
$aMessageContent['to'] = $this->FindRecipients('to', $aContextArgs);
$aMessageContent['cc'] = $this->FindRecipients('cc', $aContextArgs);
$aMessageContent['bcc'] = $this->FindRecipients('bcc', $aContextArgs);
$aMessageContent['from'] = MetaModel::ApplyParams($this->Get('from'), $aContextArgs);
$aMessageContent['from_label'] = MetaModel::ApplyParams($this->Get('from_label'), $aContextArgs);
$aMessageContent['reply_to'] = MetaModel::ApplyParams($this->Get('reply_to'), $aContextArgs);
$aMessageContent['reply_to_label'] = MetaModel::ApplyParams($this->Get('reply_to_label'), $aContextArgs);
$aMessageContent['subject'] = MetaModel::ApplyParams($this->Get('subject'), $aContextArgs);
$sBody = $this->BuildMessageBody(false);
$aMessageContent['body'] = MetaModel::ApplyParams($sBody, $aContextArgs);
$oObj = $aContextArgs['this->object()'];
$aMessageContent['message_id'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_MESSAGE_ID);
$aMessageContent['references'] = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_REFERENCES);
}
catch (Exception $e) {
/** @noinspection PhpUnhandledExceptionInspection */
throw $e;
}
finally {
ApplicationContext::SetUrlMakerClass($sPreviousUrlMaker);
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
}
if (!is_null($oLog)) {
// Note: we have to secure this because those values are calculated
// inside the try statement, and we would like to keep track of as
// many data as we could while some variables may still be undefined
if (isset($aMessageContent['to'])) {
$oLog->Set('to', $aMessageContent['to']);
}
if (isset($aMessageContent['cc'])) {
$oLog->Set('cc', $aMessageContent['cc']);
}
if (isset($aMessageContent['bcc'])) {
$oLog->Set('bcc', $aMessageContent['bcc']);
}
if (isset($aMessageContent['from'])) {
$oLog->Set('from', $aMessageContent['from']);
}
if (isset($aMessageContent['subject'])) {
$oLog->Set('subject', $aMessageContent['subject']);
}
if (isset($aMessageContent['body'])) {
$oLog->Set('body', HTMLSanitizer::Sanitize($aMessageContent['body']));
}
}
if ($this->IsBeingTested()) {
$sTestBody = $aMessageContent['body'];
$sTestBody .= "<div style=\"border: dashed;\">\n";
$sTestBody .= "<h1>Testing email notification ".$this->GetHyperlink()."</h1>\n";
$sTestBody .= "<p>The email should be sent with the following properties\n";
$sTestBody .= "<ul>\n";
$sTestBody .= "<li>TO: {$aMessageContent['to']}</li>\n";
$sTestBody .= "<li>CC: {$aMessageContent['cc']}</li>\n";
$sTestBody .= "<li>BCC: {$aMessageContent['bcc']}</li>\n";
$sTestBody .= empty($aMessageContent['from_label']) ? "<li>From: {$aMessageContent['from']}</li>\n" : "<li>From: {$aMessageContent['from_label']} &lt;{$aMessageContent['from']}&gt;</li>\n";
$sTestBody .= empty($aMessageContent['reply_to_label']) ? "<li>Reply-To: {$aMessageContent['reply_to']}</li>\n" : "<li>Reply-To: {$aMessageContent['reply_to_label']} &lt;{$aMessageContent['reply_to']}&gt;</li>\n";
$sTestBody .= "<li>References: {$aMessageContent['references']}</li>\n";
$sTestBody .= "</ul>\n";
$sTestBody .= "</p>\n";
$sTestBody .= "</div>\n";
$aMessageContent['subject'] = 'TEST['.$aMessageContent['subject'].']';
$aMessageContent['body'] = $sTestBody;
$aMessageContent['to'] = $this->Get('test_recipient');
// N°6677 Ensure emails in test are never sent to cc'd and bcc'd addresses
$aMessageContent['cc'] = '';
$aMessageContent['bcc'] = '';
}
// 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'];
if (isset($aContextArgs['attachments']))
{
$aAttachmentReport = array();
/** @var \ormDocument $oDocument */
foreach($aContextArgs['attachments'] as $oDocument)
{
$aMessageContent['attachments'][] = ['data' => $oDocument->GetData(), 'filename' => $oDocument->GetFileName(), 'mime_type' => $oDocument->GetMimeType()];
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData() ?? ''));
}
$oLog->Set('attachments', $aAttachmentReport);
}
return $aMessageContent;
}
/**
* @param \DBObject $oObject
* @param string $sHeaderName {@see \ActionEmail::ENUM_HEADER_NAME_REFERENCES}, {@see \ActionEmail::ENUM_HEADER_NAME_MESSAGE_ID}
*
* @return string The formatted identifier for $sHeaderName based on $oObject
* @throws \Exception
* @since 3.1.0 N°4849
*/
protected function GenerateIdentifierForHeaders(DBObject $oObject, string $sHeaderName): string
{
$sObjClass = get_class($oObject);
$sObjId = $oObject->GetKey();
$sAppName = utils::Sanitize(ITOP_APPLICATION_SHORT, '', utils::ENUM_SANITIZATION_FILTER_VARIABLE_NAME);
switch ($sHeaderName) {
case static::ENUM_HEADER_NAME_MESSAGE_ID:
case static::ENUM_HEADER_NAME_REFERENCES:
// Prefix
$sPrefix = sprintf('%s_%s_%d', $sAppName, $sObjClass, $sObjId);
if ($sHeaderName === static::ENUM_HEADER_NAME_MESSAGE_ID) {
$sPrefix .= sprintf('_%F', microtime(true /* get as float*/));
}
// Suffix
$sSuffix = sprintf('@%s.openitop.org', MetaModel::GetEnvironmentId());
// Identifier
$sIdentifier = $sPrefix.$sSuffix;
if ($sHeaderName === static::ENUM_HEADER_NAME_REFERENCES) {
$sIdentifier = "<$sIdentifier>";
}
return $sIdentifier;
}
// Requested header name invalid
$sErrorMessage = sprintf('%s: Could not generate identifier for header "%s", only %s are supported', static::class, $sHeaderName, implode(' / ', [static::ENUM_HEADER_NAME_MESSAGE_ID, static::ENUM_HEADER_NAME_REFERENCES]));
IssueLog::Error($sErrorMessage, LogChannels::NOTIFICATIONS, [
'Object' => $sObjClass.'::'.$sObjId.' ('.$oObject->GetRawName().')',
'Action' => get_class($this).'::'.$this->GetKey().' ('.$this->GetRawName().')',
]);
throw new Exception($sErrorMessage);
}
/**
* Compose the body of the message from the 'body' attribute and the HTML template (if any)
* @since 3.1.0 N°4849
* @param bool $bHighlightPlaceholders If true add some extra HTML around placeholders to highlight them
* @return string
*/
protected function BuildMessageBody(bool $bHighlightPlaceholders = false): string
{
// Wrap content with a specific class in order to apply styles of HTML fields through the emogrifier (see `css/email.scss`)
$sBody = <<<HTML
<div class="email-is-html-content">
{$this->Get('body')}
</div>
HTML;
/** @var ormDocument $oHtmlTemplate */
$oHtmlTemplate = $this->Get('html_template');
if ($oHtmlTemplate && !$oHtmlTemplate->IsEmpty()) {
$sHtmlTemplate = $oHtmlTemplate->GetData();
if (false !== mb_strpos($sHtmlTemplate, static::TEMPLATE_BODY_CONTENT)) {
if ($bHighlightPlaceholders) {
// Highlight the $content$ block
$sBody = sprintf(static::CONTENT_HIGHLIGHT, $sBody);
}
$sBody = str_replace(static::TEMPLATE_BODY_CONTENT, $sBody, $oHtmlTemplate->GetData()); // str_replace is ok as long as both strings are well-formed UTF-8
} else {
$sBody = $oHtmlTemplate->GetData();
}
}
if($bHighlightPlaceholders) {
// Highlight all placeholders
$sBody = preg_replace('/\\$([^$]+)\\$/', static::FIELD_HIGHLIGHT, $sBody);
}
return $sBody;
}
/**
* @since 3.1.0 N°4849
* @inheritDoc
* @see cmdbAbstractObject::DisplayBareRelations()
*/
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
parent::DisplayBareRelations($oPage, false);
if (!$bEditMode) {
$oPage->SetCurrentTab('action_email__preview', Dict::S('ActionEmail:preview_tab'), Dict::S('ActionEmail:preview_tab+'));
$sBody = $this->BuildMessageBody(true);
TwigHelper::RenderIntoPage($oPage, APPROOT.'/', 'templates/datamodel/ActionEmail/email-notification-preview', ['iframe_content' => $sBody]);
}
}
/**
* @since 3.1.0
* @inheritDoc
* @see cmdbAbstractObject::DoCheckToWrite()
*/
public function DoCheckToWrite()
{
parent::DoCheckToWrite();
$oHtmlTemplate = $this->Get('html_template');
if ($oHtmlTemplate && !$oHtmlTemplate->IsEmpty()) {
if (false === mb_strpos($oHtmlTemplate->GetData(), static::TEMPLATE_BODY_CONTENT)) {
$this->m_aCheckWarnings[] = Dict::Format('ActionEmail:content_placeholder_missing', static::TEMPLATE_BODY_CONTENT, Dict::S('Class:ActionEmail/Attribute:body'));
}
}
}
/**
* @inheritDoc
* @since 3.2.0
*/
public static function GetAsynchronousGlobalSetting(): bool
{
return utils::GetConfig()->Get('email_asynchronous');
}
}

View File

@@ -1,544 +0,0 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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\Service\Notification\Event\EventNotificationNewsroomService;
/**
* Persistent classes (internal): user defined actions
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ExecAsyncTask implements iBackgroundProcess
{
public function GetPeriodicity()
{
return 2; // seconds
}
public function Process($iTimeLimit)
{
$sNow = date(AttributeDateTime::GetSQLFormat());
// Criteria: planned, and expected to occur... ASAP or in the past
$sOQL = "SELECT AsyncTask WHERE (status = 'planned') AND (ISNULL(planned) OR (planned < '$sNow'))";
$iProcessed = 0;
while (time() < $iTimeLimit)
{
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array(), null, 1 /* limit count */);
$oTask = $oSet->Fetch();
if (is_null($oTask))
{
// Nothing to be done
break;
}
$iProcessed++;
if ($oTask->Process())
{
$oTask->DBDelete();
}
}
return "processed $iProcessed tasks";
}
}
/**
* A
*
* @package iTopORM
*/
abstract class AsyncTask extends DBObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => array('created'),
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_async_task",
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
);
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
// 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 AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
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("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
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 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("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 AttributeString("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("last_attempt", array("allowed_values"=>null, "sql"=>"last_attempt", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
}
/**
* Every is fine
*/
const OK = 0;
/**
* The task no longer exists
*/
const DELETED = 1;
/**
* The task is already being executed
*/
const ALREADY_RUNNING = 2;
/**
* The current process requests the ownership on the task.
* In case the task can be accessed concurrently, this function can be overloaded to add a critical section.
* The function must not block the caller if another process is already owning the task
*
* @return integer A code among OK/DELETED/ALREADY_RUNNING.
*/
public function MarkAsRunning()
{
try
{
if ($this->Get('status') == 'running')
{
return self::ALREADY_RUNNING;
}
else
{
$this->Set('status', 'running');
$this->Set('started', time());
$this->DBUpdate();
return self::OK;
}
}
catch(Exception $e)
{
// 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.');
if ($this->Get('event_id') != 0)
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
$oEventLog->DBUpdate();
}
$this->DBDelete();
return self::DELETED;
}
}
public function GetRetryDelay($iErrorCode = null)
{
$iRetryDelay = 600;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
$iRetryDelay = $aConfig['retry_delay'] ?? $iRetryDelay;
}
return $iRetryDelay;
}
public function GetMaxRetries($iErrorCode = null)
{
$iMaxRetries = 0;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
$iMaxRetries = $aConfig['max_retries'] ?? $iMaxRetries;
}
return $iMaxRetries;
}
public function IsRetryDelayExponential()
{
$bExponential = false;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
$bExponential = (bool) ($aConfig['exponential_delay'] ?? $bExponential);
}
return $bExponential;
}
public static function CheckRetryConfig(Config $oConfig, $sAsyncTaskClass)
{
$aMessages = [];
$aRetries = $oConfig->Get('async_task_retries');
if (is_array($aRetries) && array_key_exists($sAsyncTaskClass, $aRetries))
{
$aValidKeys = array("retry_delay", "max_retries", "exponential_delay");
$aConfig = $aRetries[$sAsyncTaskClass];
if (!is_array($aConfig))
{
$aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_Keys', $sAsyncTaskClass, implode(', ', $aValidKeys));
}
else
{
foreach($aConfig as $key => $value)
{
if (!in_array($key, $aValidKeys))
{
$aMessages[] = Dict::Format('Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys', $sAsyncTaskClass, $key, implode(', ', $aValidKeys));
}
}
}
}
return $aMessages;
}
/**
* Compute the delay to wait for the "next retry", based on the given parameters
* @param bool $bIsExponential
* @param int $iRetryDelay
* @param int $iMaxRetries
* @param int $iRemainingRetries
* @return int
*/
public static function GetNextRetryDelay($bIsExponential, $iRetryDelay, $iMaxRetries, $iRemainingRetries)
{
if ($bIsExponential)
{
$iExponent = $iMaxRetries - $iRemainingRetries;
if ($iExponent < 0) $iExponent = 0; // Safety net in case on configuration change in the middle of retries
return $iRetryDelay * (2 ** $iExponent);
}
else
{
return $iRetryDelay;
}
}
/**
* Override to notify people that a task cannot be performed
*/
protected function OnDefinitiveFailure()
{
}
protected function OnInsert()
{
$this->Set('created', time());
}
/**
* @return boolean True if the task record can be deleted
*/
public function Process()
{
// By default: consider that the task is not completed
$bRet = false;
// Attempt to take the ownership
$iStatus = $this->MarkAsRunning();
if ($iStatus == self::OK)
{
try
{
$sStatus = $this->DoProcess();
if ($this->Get('event_id') != 0)
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', $sStatus);
$oEventLog->DBUpdate();
}
$bRet = true;
} catch (Exception $e)
{
$this->HandleError($e->getMessage(), $e->getCode());
}
}
else
{
// Already done or being handled by another process... skip...
$bRet = false;
}
return $bRet;
}
/**
* Overridable to extend the behavior in case of error (logging)
*/
protected function HandleError($sErrorMessage, $iErrorCode)
{
if ($this->Get('last_attempt') == '')
{
// First attempt
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
}
$this->SetTrim('last_error', $sErrorMessage);
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
$this->Set('last_attempt', time());
$iRemaining = $this->Get('remaining_retries');
if ($iRemaining > 0)
{
$iRetryDelay = $this->GetRetryDelay($iErrorCode);
$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');
if ($this->Get('event_id') != 0)
{
$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");
try
{
$oEventLog->DBUpdate();
}
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->DBUpdate();
}
}
$this->Set('remaining_retries', $iRemaining - 1);
$this->Set('status', 'planned');
$this->Set('started', null);
$this->Set('planned', time() + $iNextRetryDelay);
}
else
{
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage);
if ($this->Get('event_id') != 0)
{
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
$oEventLog->Set('message', "$sErrorMessage\nFailed to process async task.");
try
{
$oEventLog->DBUpdate();
}
catch (Exception $e)
{
$oEventLog->Set('message', 'Failed to process async task, more details in the log');
$oEventLog->DBUpdate();
}
}
$this->Set('status', 'error');
$this->Set('started', null);
$this->Set('planned', null);
$this->OnDefinitiveFailure();
}
$this->DBUpdate();
}
/**
* Throws an exception (message and code)
*
* @return string
*/
abstract public function DoProcess();
/**
* Describes the error codes that DoProcess can return by the mean of exceptions
*/
static public function EnumErrorCodes()
{
return array();
}
}
/**
* An email notification
*
* @package iTopORM
*/
class AsyncSendEmail extends AsyncTask
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "created",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_async_send_email",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
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 AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// 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('list', array('name', 'status', 'to', 'subject')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
static public function AddToQueue(EMail $oEMail, $oLog)
{
$oNew = MetaModel::NewObject(__class__);
if ($oLog)
{
$oNew->Set('event_id', $oLog->GetKey());
}
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
$oNew->Set('subject', $oEMail->GetSubject());
$oNew->Set('version', 2);
$sMessage = $oEMail->SerializeV2();
$oNew->Set('message', $sMessage);
$oNew->DBInsert();
}
/**
* @inheritDoc
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function DoProcess()
{
$sMessage = $this->Get('message');
$iVersion = (int) $this->Get('version');
switch($iVersion)
{
case Email::FORMAT_V2:
$oEMail = Email::UnSerializeV2($sMessage);
break;
case Email::ORIGINAL_FORMAT:
$oEMail = unserialize($sMessage);
break;
default:
return 'Unknown version of the serialization format: '.$iVersion;
}
$iRes = $oEMail->Send($aIssues, true /* force synchro !!!!! */);
switch ($iRes)
{
case EMAIL_SEND_OK:
return "Sent";
case EMAIL_SEND_PENDING:
return "Bug - the email should be sent in synchronous mode";
case EMAIL_SEND_ERROR:
if (is_array($aIssues)) {
$sMessage = "Sending eMail failed: ".implode(', ', $aIssues);
} else {
$sMessage = "Sending eMail failed.";
}
throw new Exception($sMessage);
}
return '';
}
}
/**
* An async notification to be sent to iTop users through the newsroom
* @since 3.2.0
*/
class AsyncSendNewsroom extends AsyncTask {
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "created",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_async_send_newsroom",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
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 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("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 AttributeText("title", array("allowed_values"=>null, "sql"=>"title", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
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 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 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 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 AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>'NOW()', "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
}
/**
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public static function AddToQueue(int $iActionId, int $iTriggerId, array $aRecipients, string $sMessage, string $sTitle, string $sUrl, int $iObjectId, ?string $sObjectClass): void
{
$oNew = new static();
$oNew->Set('action_id', $iActionId);
$oNew->Set('trigger_id', $iTriggerId);
$oNew->Set('recipients', json_encode($aRecipients));
$oNew->Set('message', $sMessage);
$oNew->Set('title', $sTitle);
$oNew->Set('url', $sUrl);
$oNew->Set('object_id', $iObjectId);
$oNew->Set('object_class', $sObjectClass);
$oNew->SetCurrentDate('date');
$oNew->DBInsert();
}
/**
* @inheritDoc
*/
public function DoProcess()
{
$oAction = MetaModel::GetObject('Action', $this->Get('action_id'));
$iTriggerId = $this->Get('trigger_id');
$aRecipients = json_decode($this->Get('recipients'));
$sMessage = $this->Get('message');
$sTitle = $this->Get('title');
$sUrl = $this->Get('url');
$iObjectId = $this->Get('object_id');
$sObjectClass = $this->Get('object_class');
$sDate = $this->Get('date');
foreach ($aRecipients as $iRecipientId)
{
$oEvent = EventNotificationNewsroomService::MakeEventFromAction($oAction, $iRecipientId, $iTriggerId, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass, $sDate);
$oEvent->DBInsertNoReload();
}
return "Sent";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,17 +26,54 @@ MetaModel::IncludeModule('application/query.class.inc.php');
MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php');
MetaModel::IncludeModule('core/event.class.inc.php');
MetaModel::IncludeModule('core/action.class.inc.php');
MetaModel::IncludeModule('core/trigger.class.inc.php');
MetaModel::IncludeModule('core/bulkexport.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/Event.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventNotification.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventNotificationEmail.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventIssue.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventWebService.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventRestService.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventLoginUsage.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/Event/EventOnObject.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/AsyncTask/ExecAsyncTask.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncTask.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncSendEmail.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/AsyncTask/ExecAsyncTask.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncSendNewsroom.php');
MetaModel::IncludeModule(APPROOT.'/core/email.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/Action.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/ActionNotification.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/ActionEmail.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/lnkTriggerAction.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/Trigger.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnAttributeBlobDownload.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnObject.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnObjectCreate.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnObjectDelete.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnObjectMention.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnObjectUpdate.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnPortalUpdate.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnStateChange.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnStateEnter.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnStateLeave.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/DataModel/TriggerAndAction/TriggerOnThresholdReached.php');
//MetaModel::IncludeModule('core/bulkexport.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/BulkExport/BulkExport.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/BulkExport/BulkExportException.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/BulkExport/BulkExportMissingParameterException.php');
MetaModel::IncludeModule(APPROOT.'/sources/Application/BulkExport/BulkExportResultGC.php');
MetaModel::IncludeModule('core/ownershiplock.class.inc.php');
MetaModel::IncludeModule('core/tagsetfield.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/TagSetFieldData.php');
MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php');
MetaModel::IncludeModule('core/backgroundtask.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/BackgroundTask.php');
MetaModel::IncludeModule('core/inlineimage.class.inc.php');
MetaModel::IncludeModule('core/counter.class.inc.php');
MetaModel::IncludeModule('core/TemporaryObjectDescriptor.php');
//MetaModel::IncludeModule('core/counter.class.inc.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/KeyValueStore.php');
MetaModel::IncludeModule(APPROOT.'/sources/Core/DataModel/TemporaryObjectDescriptor.php');
MetaModel::IncludeModule('webservices/webservices.basic.php');

File diff suppressed because it is too large Load Diff

View File

@@ -1,514 +0,0 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\WebPage\Page;
use Combodo\iTop\Application\WebPage\WebPage;
define('EXPORTER_DEFAULT_CHUNK_SIZE', 1000);
class BulkExportException extends Exception
{
protected $sLocalizedMessage;
public function __construct($message, $sLocalizedMessage, $code = 0, $previous = null)
{
parent::__construct($message, $code, $previous);
$this->sLocalizedMessage = $sLocalizedMessage;
}
public function GetLocalizedMessage()
{
return $this->sLocalizedMessage;
}
}
class BulkExportMissingParameterException extends BulkExportException
{
public function __construct($sFieldCode)
{
parent::__construct('Missing parameter: '.$sFieldCode, Dict::Format('Core:BulkExport:MissingParameter_Param', $sFieldCode));
}
}
/**
* Class BulkExport
*
* @copyright Copyright (C) 2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class BulkExportResult extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => 'core/cmdb',
"key_type" => 'autoincrement',
"name_attcode" => array('created'),
"state_attcode" => '',
"reconc_keys" => array(),
"db_table" => 'priv_bulk_export_result',
"db_key_field" => 'id',
"db_finalclass_field" => '',
"display_template" => '',
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("user_id", array("allowed_values"=>null, "sql"=>"user_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("chunk_size", array("allowed_values"=>null, "sql"=>"chunk_size", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("format", array("allowed_values"=>null, "sql"=>"format", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("temp_file_path", array("allowed_values"=>null, "sql"=>"temp_file_path", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("search", array("allowed_values"=>null, "sql"=>"search", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("status_info", array("allowed_values"=>null, "sql"=>"status_info", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("localize_output", array("allowed_values"=>null, "sql"=>"localize_output", "default_value"=>true, "is_null_allowed"=>true, "depends_on"=>array())));
}
/**
* @throws CoreUnexpectedValue
* @throws Exception
*/
public function ComputeValues()
{
$this->Set('user_id', UserRights::GetUserId());
}
}
/**
* Garbage collector for cleaning "old" export results from the database and the disk.
* This background process runs once per day and deletes the results of all exports which
* are older than one day.
*/
class BulkExportResultGC implements iBackgroundProcess
{
public function GetPeriodicity()
{
return 24*3600; // seconds
}
public function Process($iTimeLimit)
{
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time() - 24*3600); // Every BulkExportResult older than one day will be deleted
$sOQL = "SELECT BulkExportResult WHERE created < '$sDateLimit'";
$iProcessed = 0;
while (time() < $iTimeLimit)
{
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array('BulkExportResult' => array('temp_file_path')));
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
// Nothing to be done
break;
}
$iProcessed++;
@unlink($oResult->Get('temp_file_path'));
utils::PushArchiveMode(false);
$oResult->DBDelete();
utils::PopArchiveMode();
}
return "Cleaned $iProcessed old export results(s).";
}
}
/**
* Class BulkExport
*
* @copyright Copyright (C) 2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class BulkExport
{
protected $oSearch;
protected $iChunkSize;
protected $sFormatCode;
protected $aStatusInfo;
protected $oBulkExportResult;
protected $sTmpFile;
protected $bLocalizeOutput;
public function __construct()
{
$this->oSearch = null;
$this->iChunkSize = 0;
$this->sFormatCode = null;
$this->aStatusInfo = [
'show_obsolete_data' => utils::ShowObsoleteData(),
];
$this->oBulkExportResult = null;
$this->sTmpFile = '';
$this->bLocalizeOutput = false;
}
/**
* Find the first class capable of exporting the data in the given format
*
* @param string $sFormatCode The lowercase format (e.g. html, csv, spreadsheet, xlsx, xml, json, pdf...)
* @param DBSearch $oSearch The search/filter defining the set of objects to export or null when listing the supported formats
*
* @return BulkExport|null
* @throws ReflectionException
*/
static public function FindExporter($sFormatCode, $oSearch = null)
{
foreach(get_declared_classes() as $sPHPClass)
{
$oRefClass = new ReflectionClass($sPHPClass);
if ($oRefClass->isSubclassOf('BulkExport') && !$oRefClass->isAbstract())
{
/** @var BulkExport $oBulkExporter */
$oBulkExporter = new $sPHPClass();
if ($oBulkExporter->IsFormatSupported($sFormatCode, $oSearch))
{
if ($oSearch)
{
$oBulkExporter->SetObjectList($oSearch);
}
return $oBulkExporter;
}
}
}
return null;
}
/**
* Find the exporter corresponding to the given persistent token
*
* @param int $iPersistentToken The identifier of the BulkExportResult object storing the information
*
* @return BulkExport|null
* @throws ArchivedObjectException
* @throws CoreException
* @throws ReflectionException
*/
static public function FindExporterFromToken($iPersistentToken = null)
{
$oBulkExporter = null;
$oInfo = MetaModel::GetObject('BulkExportResult', $iPersistentToken, false);
if ($oInfo && ($oInfo->Get('user_id') == UserRights::GetUserId()))
{
$sFormatCode = $oInfo->Get('format');
$aStatusInfo = json_decode($oInfo->Get('status_info'),true);
$oSearch = DBObjectSearch::unserialize($oInfo->Get('search'));
$oSearch->SetShowObsoleteData($aStatusInfo['show_obsolete_data']);
$oBulkExporter = self::FindExporter($sFormatCode, $oSearch);
if ($oBulkExporter)
{
$oBulkExporter->SetFormat($sFormatCode);
$oBulkExporter->SetObjectList($oSearch);
$oBulkExporter->SetChunkSize($oInfo->Get('chunk_size'));
$oBulkExporter->SetStatusInfo($aStatusInfo);
$oBulkExporter->SetLocalizeOutput($oInfo->Get('localize_output'));
$oBulkExporter->sTmpFile = $oInfo->Get('temp_file_path');
$oBulkExporter->oBulkExportResult = $oInfo;
}
}
return $oBulkExporter;
}
/**
* @param $data
* @throws Exception
*/
public function AppendToTmpFile($data)
{
if ($this->sTmpFile == '')
{
$this->sTmpFile = $this->MakeTmpFile($this->GetFileExtension());
}
$hFile = fopen($this->sTmpFile, 'ab');
if ($hFile !== false)
{
fwrite($hFile, $data);
fclose($hFile);
}
}
public function GetTmpFilePath()
{
return $this->sTmpFile;
}
/**
* Lists all possible export formats. The output is a hash array in the form: 'format_code' => 'localized format label'
* @return array :string
*/
static public function FindSupportedFormats()
{
$aSupportedFormats = array();
foreach(get_declared_classes() as $sPHPClass)
{
$oRefClass = new ReflectionClass($sPHPClass);
if ($oRefClass->isSubClassOf('BulkExport') && !$oRefClass->isAbstract())
{
$oBulkExporter = new $sPHPClass;
$aFormats = $oBulkExporter->GetSupportedFormats();
$aSupportedFormats = array_merge($aSupportedFormats, $aFormats);
}
}
return $aSupportedFormats;
}
/**
* (non-PHPdoc)
* @see iBulkExport::SetChunkSize()
*/
public function SetChunkSize($iChunkSize)
{
$this->iChunkSize = $iChunkSize;
}
/**
* @param $bLocalizeOutput
*/
public function SetLocalizeOutput($bLocalizeOutput)
{
$this->bLocalizeOutput = $bLocalizeOutput;
}
/**
* (non-PHPdoc)
* @see iBulkExport::SetObjectList()
*/
public function SetObjectList(DBSearch $oSearch)
{
$oSearch->SetShowObsoleteData($this->aStatusInfo['show_obsolete_data']);
$this->oSearch = $oSearch;
}
public function SetFormat($sFormatCode)
{
$this->sFormatCode = $sFormatCode;
}
/**
* (non-PHPdoc)
* @see iBulkExport::IsFormatSupported()
*/
public function IsFormatSupported($sFormatCode, $oSearch = null)
{
return array_key_exists($sFormatCode, $this->GetSupportedFormats());
}
/**
* (non-PHPdoc)
* @see iBulkExport::GetSupportedFormats()
*/
public function GetSupportedFormats()
{
return array(); // return array('csv' => Dict::S('UI:ExportFormatCSV'));
}
public function SetHttpHeaders(WebPage $oPage)
{
}
/**
* @return string
*/
public function GetHeader()
{
return '';
}
abstract public function GetNextChunk(&$aStatus);
/**
* @return string
*/
public function GetFooter()
{
return '';
}
public function SaveState()
{
if ($this->oBulkExportResult === null)
{
$this->oBulkExportResult = new BulkExportResult();
$this->oBulkExportResult->Set('format', $this->sFormatCode);
$this->oBulkExportResult->Set('search', $this->oSearch->serialize());
$this->oBulkExportResult->Set('chunk_size', $this->iChunkSize);
$this->oBulkExportResult->Set('localize_output', $this->bLocalizeOutput);
}
$this->oBulkExportResult->Set('status_info', json_encode($this->GetStatusInfo()));
$this->oBulkExportResult->Set('temp_file_path', $this->sTmpFile);
utils::PushArchiveMode(false);
$ret = $this->oBulkExportResult->DBWrite();
utils::PopArchiveMode();
return $ret;
}
public function Cleanup()
{
if (($this->oBulkExportResult && (!$this->oBulkExportResult->IsNew())))
{
$sFilename = $this->oBulkExportResult->Get('temp_file_path');
if ($sFilename != '')
{
@unlink($sFilename);
}
utils::PushArchiveMode(false);
$this->oBulkExportResult->DBDelete();
utils::PopArchiveMode();
}
}
public function EnumFormParts()
{
return array();
}
/**
* @deprecated 3.0.0 use GetFormPart instead
*/
public function DisplayFormPart(WebPage $oP, $sPartId)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use GetFormPart instead');
$oP->AddSubBlock($this->GetFormPart($oP, $sPartId));
}
/**
* @param WebPage $oP
* @param $sPartId
*
* @return UIContentBlock
*/
public function GetFormPart(WebPage $oP, $sPartId)
{
}
public function DisplayUsage(Page $oP)
{
}
public function ReadParameters()
{
$this->bLocalizeOutput = !((bool)utils::ReadParam('no_localize', 0, true, 'integer'));
}
public function GetResultAsHtml()
{
}
public function GetRawResult()
{
}
/**
* @return string
*/
public function GetMimeType()
{
return '';
}
/**
* @return string
*/
public function GetFileExtension()
{
return '';
}
public function GetCharacterSet()
{
return 'UTF-8';
}
public function GetStatistics()
{
}
public function SetFields($sFields)
{
}
public function GetDownloadFileName()
{
return Dict::Format('Core:BulkExportOf_Class', MetaModel::GetName($this->oSearch->GetClass())).'.'.$this->GetFileExtension();
}
public function SetStatusInfo($aStatusInfo)
{
$this->aStatusInfo = $aStatusInfo;
}
public function GetStatusInfo()
{
return $this->aStatusInfo;
}
/**
* @param $sExtension
* @return string
* @throws Exception
*/
protected function MakeTmpFile($sExtension)
{
if(!is_dir(APPROOT."data/bulk_export"))
{
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
clearstatcache();
}
if (!is_writable(APPROOT."data/bulk_export"))
{
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
}
$iNum = rand();
do
{
$iNum++;
$sToken = sprintf("%08x", $iNum);
$sFileName = APPROOT."data/bulk_export/$sToken.".$sExtension;
$hFile = @fopen($sFileName, 'x');
}
while($hFile === false);
fclose($hFile);
return $sFileName;
}
}
// The built-in exports
require_once(APPROOT.'core/tabularbulkexport.class.inc.php');
require_once(APPROOT.'core/htmlbulkexport.class.inc.php');
if (extension_loaded('gd'))
{
// PDF export - via TCPDF - requires GD
require_once(APPROOT.'core/pdfbulkexport.class.inc.php');
}
require_once(APPROOT.'core/csvbulkexport.class.inc.php');
require_once(APPROOT.'core/excelbulkexport.class.inc.php');
require_once(APPROOT.'core/spreadsheetbulkexport.class.inc.php');
require_once(APPROOT.'core/xmlbulkexport.class.inc.php');

File diff suppressed because it is too large Load Diff

View File

@@ -39,11 +39,16 @@ require_once('kpi.class.inc.php');
require_once('dict.class.inc.php');
require_once('attributedef.class.inc.php');
require_once('filterdef.class.inc.php');
require_once('stimulus.class.inc.php');
require_once('valuesetdef.class.inc.php');
require_once('MyHelpers.class.inc.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetDefinition.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetObjects.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetEnum.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetEnumPadded.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetRange.php');
require_once(APPROOT.'/sources/Core/ValueSetDefinition/ValueSetEnumClasses.php');
require_once('oql/expression.class.inc.php');
require_once('oql/oqlquery.class.inc.php');
require_once('oql/oqlexception.class.inc.php');
@@ -60,12 +65,41 @@ require_once('dbobject.class.php');
require_once('dbobjectset.class.php');
require_once('backgroundprocess.inc.php');
require_once('asynctask.class.inc.php');
require_once('dbproperty.class.inc.php');
//require_once('asynctask.class.inc.php');
require_once(APPROOT.'/sources/Core/DataModel/AsyncTask/ExecAsyncTask.php');
require_once(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncTask.php');
require_once(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncSendEmail.php');
require_once(APPROOT.'/sources/Core/DataModel/AsyncTask/ExecAsyncTask.php');
require_once(APPROOT.'/sources/Core/DataModel/AsyncTask/AsyncSendNewsroom.php');
require_once(APPROOT.'/sources/Core/DataModel/DBProperty.php');
// db change tracking data model
require_once('cmdbchange.class.inc.php');
require_once('cmdbchangeop.class.inc.php');
//require_once('cmdbchangeop.class.inc.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/iCMDBChangeOp.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOp.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpCreate.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpDelete.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpPlugin.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttribute.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeBlob.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeCaseLog.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeCustomFields.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeEncrypted.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeHTML.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeLinks.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeLinksAddRemove.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeLinksTune.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeLongText.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeOneWayPassword.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeScalar.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeTagSet.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeText.php');
require_once(APPROOT.'/sources/Core/DataModel/CMDBChange/CMDBChangeOpSetAttributeURL.php');
// customization data model
// Romain: temporary moved into application.inc.php (see explanations there)
@@ -78,7 +112,7 @@ require_once('cmdbchangeop.class.inc.php');
require_once('templatestring.class.inc.php');
require_once('csvparser.class.inc.php');
require_once('bulkchange.class.inc.php');
//require_once('bulkchange.class.inc.php');
/**
* A persistent object, which changes are accurately recorded
@@ -397,60 +431,7 @@ abstract class CMDBObject extends DBObject
}
}
/**
* Helper to ultimately check user rights before writing (Insert, Update or Delete)
* The check should never fail, because the UI should prevent from such a usage
* Anyhow, if the user has found a workaround... the security gets enforced here
*
* @deprecated 3.0.0 N°2591 will be removed in 3.1.0
*
* @param bool $bSkipStrongSecurity
* @param int $iActionCode
*
* @throws \SecurityException
*/
protected function CheckUserRights($bSkipStrongSecurity, $iActionCode)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
if (is_null($bSkipStrongSecurity)) {
// This is temporary
// We have implemented this safety net right before releasing iTop 1.0
// and we decided that it was too risky to activate it
// Anyhow, users willing to have a very strong security could set
// skip_strong_security = 0, in the config file
$bSkipStrongSecurity = MetaModel::GetConfig()->Get('skip_strong_security');
}
if (!$bSkipStrongSecurity)
{
$sClass = get_class($this);
$oSet = DBObjectSet::FromObject($this);
if (!UserRights::IsActionAllowed($sClass, $iActionCode, $oSet))
{
// Intrusion detected
throw new SecurityException('You are not allowed to modify objects of class: '.$sClass);
}
}
}
public function DBClone($newKey = null)
{
return $this->DBCloneTracked_Internal();
}
/**
* @deprecated 3.1.0 N°5232 N°6966 simply use {@see DBObject::DBClone()} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*/
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
{
self::SetCurrentChange($oChange);
$this->DBCloneTracked_Internal($newKey);
}
/**
* @deprecated 3.1.1 3.2.0 N°6966 We will have only one DBClone method in the future
*/
protected function DBCloneTracked_Internal($newKey = null)
{
$newKey = parent::DBClone($newKey);
$oClone = MetaModel::GetObject(get_class($this), $newKey);
@@ -479,16 +460,6 @@ abstract class CMDBObject extends DBObject
return $oDeletionPlan;
}
/**
* @deprecated 3.1.1 3.2.0 N°6967 We will have only one DBDelete method in the future
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
$ret = parent::DBDelete($oDeletionPlan);
return $ret;
}
public function DBArchive()
{
// Note: do the job anyway, so as to repair any DB discrepancy

View File

@@ -226,27 +226,23 @@ class CMDBSource
*/
public static function InitServerAndPort($sDbHost, &$sServer, &$iPort)
{
$aConnectInfo = explode(':', $sDbHost);
if ($sDbHost != null) {
$aConnectInfo = explode(':', $sDbHost);
$bUsePersistentConnection = false;
if (strcasecmp($aConnectInfo[0], 'p') === 0)
{
$bUsePersistentConnection = true;
$sServer = $aConnectInfo[0].':'.$aConnectInfo[1];
}
else
{
$sServer = $aConnectInfo[0];
}
$bUsePersistentConnection = false;
if (strcasecmp($aConnectInfo[0], 'p') === 0) {
$bUsePersistentConnection = true;
$sServer = $aConnectInfo[0].':'.$aConnectInfo[1];
} else {
$sServer = $aConnectInfo[0];
}
$iConnectInfoCount = count($aConnectInfo);
if ($bUsePersistentConnection && ($iConnectInfoCount == 3))
{
$iPort = (int)($aConnectInfo[2]);
}
else if (!$bUsePersistentConnection && ($iConnectInfoCount == 2))
{
$iPort = (int)($aConnectInfo[1]);
$iConnectInfoCount = count($aConnectInfo);
if ($bUsePersistentConnection && ($iConnectInfoCount == 3)) {
$iPort = (int)($aConnectInfo[2]);
} else if (!$bUsePersistentConnection && ($iConnectInfoCount == 2)) {
$iPort = (int)($aConnectInfo[1]);
}
}
}

View File

@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
*
* @see ITOP_CORE_VERSION to get iTop core version
*/
define('ITOP_VERSION', '3.2.0-dev');
define('ITOP_VERSION', '3.3.0-dev');
define('ITOP_VERSION_NAME', 'Fullmoon');
define('ITOP_REVISION', 'svn');
@@ -49,7 +49,13 @@ define('ACCESS_READONLY', 0);
*/
require_once('attributedef.class.inc.php'); // For the defines
require_once('simplecrypt.class.inc.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/CryptEngine.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCrypt.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCryptMcryptEngine.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCryptOpenSSLEngine.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCryptOpenSSLMcryptCompatibilityEngine.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCryptSimpleEngine.php');
require_once(APPROOT.'/sources/Application/SimpleCrypt/SimpleCryptSodiumEngine.php');
// was utf8 but it only supports BMP chars (https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)
// so we switched to utf8mb4 in iTop 2.5, adding dependency to MySQL 5.5.3
@@ -308,15 +314,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
// Deprecated in 3.0.0 N°2591 Will be removed in 3.1
'skip_strong_security' => [
'type' => 'bool',
'description' => 'Disable strong security - TEMPORARY: this flag should be removed when we are more confident in the recent change in security',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'query_optimization_enabled' => [
'type' => 'bool',
'description' => 'The queries are optimized based on the assumption that the DB integrity has been preserved. By disabling the optimization one can ensure that the fetched data is clean... but this can be really slower or not usable at all (some queries will exceed the allowed number of joins in MySQL: 61!)',
@@ -1444,6 +1441,14 @@ class Config
'quick_create.max_history_results' => [
'type' => 'integer',
'description' => 'Max. number of elements in the history',
'default' => 5,
'value' => 5,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'quick_create.max_popular_results' => [
'type' => 'integer',
'description' => 'Max. number of elements in the popular classes section',
'default' => 10,
'value' => 10,
'source_of_value' => '',
@@ -1803,6 +1808,13 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'http.request.user_agent' => [
'type' => 'string',
'description' => 'HTTP request user agent, use this to set a custom agent on external requests.',
'default' => ITOP_APPLICATION.'/'.ITOP_VERSION,
'source_of_value' => '',
'show_in_conf_sample' => false,
]
];
public function IsProperty($sPropCode)
@@ -2011,10 +2023,7 @@ class Config
$bLoadConfig = false;
}
$this->m_aAddons = array(
// Default AddOn, always present can be moved to an official iTop Module later if needed
'user rights' => 'addons/userrights/userrightsprofile.class.inc.php',
);
$this->m_aAddons = [];
foreach ($this->m_aSettings as $sPropCode => $aSettingInfo)
{
@@ -2142,19 +2151,13 @@ class Config
array('file' => $sConfigFile, 'expected' => '$MySettings'));
}
if (!array_key_exists('addons', $MyModules))
{
throw new ConfigException('Missing item in configuration file',
array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']'));
}
if (!array_key_exists('user rights', $MyModules['addons']))
if (!array_key_exists('addons', $MyModules) || !array_key_exists('user rights', $MyModules['addons']))
{
// Add one, by default
$MyModules['addons']['user rights'] = '/addons/userrights/userrightsnull.class.inc.php';
$MyModules['addons']['user rights'] = 'addons/userrights/userrightsprofile.class.inc.php';
$this->m_aAddons = $MyModules['addons'];
}
$this->m_aAddons = $MyModules['addons'];
foreach ($MySettings as $sPropCode => $rawvalue)
{
if ($this->IsProperty($sPropCode))
@@ -2260,7 +2263,11 @@ class Config
public function GetAddons()
{
return $this->m_aAddons;
if (array_key_exists("user rights", $this->m_aAddons)) {
return $this->m_aAddons;
} else {
return array_merge($this->m_aAddons,['user rights' => 'addons/userrights/userrightsprofile.class.inc.php']);
}
}
public function SetAddons($aAddons)
@@ -2696,15 +2703,6 @@ class Config
{
fwrite($hFile, "\t'addons' => {$aParserValue['value']},\n");
}
else
{
fwrite($hFile, "\t'addons' => array (\n");
foreach ($this->m_aAddons as $sKey => $sFile)
{
fwrite($hFile, "\t\t'$sKey' => '$sFile',\n");
}
fwrite($hFile, "\t),\n");
}
fwrite($hFile, ");\n");
fwrite($hFile, '?'.'>'); // Avoid perturbing the syntax highlighting !

View File

@@ -1,11 +0,0 @@
<?php
/**
* This file is only here for compatibility reasons.
* It will be removed in future iTop versions (N°6533)
*
* @deprecated 3.0.0 N°3663 Exception classes were moved to `/application/exceptions`, use autoloader instead of require !
*/
require_once __DIR__ . '/../approot.inc.php';
DeprecatedCallsLog::NotifyDeprecatedFile('Classes were moved to /application/exceptions and can be used directly with the autoloader');

View File

@@ -1,251 +0,0 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
/**
* Class ItopCounter
*
*/
final class ItopCounter
{
/**
* Key based counter.
* The counter is protected against concurrency script.
*
* @param $sCounterName
* @param null|callable $oNewObjectValueProvider optional callable that must return an integer. Used when no key is found
*
* @return int the counter starting at
* * `0` when no $oNewObjectValueProvider is given (or null)
* * `$oNewObjectValueProvider() + 1` otherwise
*
* @throws \CoreException
* @throws \MySQLException
* @throws \Exception
*/
public static function Inc($sCounterName, $oNewObjectValueProvider = null)
{
$sSelfClassName = self::class;
$sMutexKeyName = "{$sSelfClassName}-{$sCounterName}";
$oiTopMutex = new iTopMutex($sMutexKeyName);
$oiTopMutex->Lock();
$bIsInsideTransaction = CMDBSource::IsInsideTransaction();
if ($bIsInsideTransaction)
{
// # Transaction isolation hack:
// 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.
// Either way, the lock is not long enought, and there would be duplicate ref.
//
// SELECT ... FOR UPDATE would have also worked but with the cost of extra long lock (until the commit),
// 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!
$hDBLink = self::InitMySQLSession();
}
else
{
$hDBLink = CMDBSource::GetMysqli();
}
try
{
$oFilter = DBObjectSearch::FromOQL('SELECT KeyValueStore WHERE key_name=:key_name AND namespace=:namespace', array(
'key_name' => $sCounterName,
'namespace' => $sSelfClassName,
));
$oAttDef = MetaModel::GetAttributeDef(KeyValueStore::class, 'value');
$aAttToLoad = array(KeyValueStore::class => array('value' => $oAttDef));
$sSql = $oFilter->MakeSelectQuery(array(), array(), $aAttToLoad);
$hResult = mysqli_query($hDBLink, $sSql);
$aCounter = mysqli_fetch_array($hResult, MYSQLI_NUM);
mysqli_free_result($hResult);
//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(
'key_name' => $sCounterName,
'namespace' => $sSelfClassName,
));
if (is_null($aCounter))
{
if (null != $oNewObjectValueProvider)
{
$iComputedValue = $oNewObjectValueProvider();
}
else
{
$iComputedValue = 0;
}
$iCurrentValue = $iComputedValue + 1;
$aQueryParams = array(
'key_name' => $sCounterName,
'value' => "$iCurrentValue",
'namespace' => $sSelfClassName,
);
$sSql = $oFilter->MakeInsertQuery($aQueryParams);
}
else
{
$iCurrentValue = (int) $aCounter[1];
$iCurrentValue++;
$aQueryParams = array(
'value' => "$iCurrentValue",
);
$sSql = $oFilter->MakeUpdateQuery($aQueryParams);
}
$hResult = mysqli_query($hDBLink, $sSql);
}
catch(Exception $e)
{
IssueLog::Error($e->getMessage());
throw $e;
}
finally
{
if ($bIsInsideTransaction)
{
mysqli_close($hDBLink);
}
$oiTopMutex->Unlock();
}
return $iCurrentValue;
}
/**
* handle a counter for the root class of given $sLeafClass.
* If no counter exist initialize it with the `max(id) + 1`
*
*
*
* @param $sLeafClass
*
* @return int
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreOqlMultipleResultsForbiddenException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
*/
public static function IncClass($sLeafClass)
{
$sRootClass = MetaModel::GetRootClass($sLeafClass);
$oNewObjectCallback = function() use ($sRootClass)
{
$sRootTable = MetaModel::DBGetTable($sRootClass);
$sIdField = MetaModel::DBGetKey($sRootClass);
return CMDBSource::QueryToScalar("SELECT max(`$sIdField`) FROM `$sRootTable`");
};
return self::Inc($sRootClass, $oNewObjectCallback);
}
/**
* @return \mysqli
* @throws \ConfigException
* @throws \CoreException
* @throws \MySQLException
*/
private static function InitMySQLSession()
{
$oConfig = utils::GetConfig();
$sDBHost = $oConfig->Get('db_host');
$sDBUser = $oConfig->Get('db_user');
$sDBPwd = $oConfig->Get('db_pwd');
$sDBName = $oConfig->Get('db_name');
$bDBTlsEnabled = $oConfig->Get('db_tls.enabled');
$sDBTlsCA = $oConfig->Get('db_tls.ca');
$hDBLink = CMDBSource::GetMysqliInstance($sDBHost, $sDBUser, $sDBPwd, $sDBName, $bDBTlsEnabled, $sDBTlsCA, false);
if (!$hDBLink)
{
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;
}
}
/**
* Persistent classes for a CMDB
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
class KeyValueStore extends DBObject
{
public static function Init()
{
$aParams = array(
'category' => '',
'key_type' => 'autoincrement',
'name_attcode' => array('key_name'),
'state_attcode' => '',
'reconc_keys' => array(''),
'db_table' => 'key_value_store',
'db_key_field' => 'id',
'db_finalclass_field' => '',
'indexes' => array (
array (
0 => 'key_name',
1 => 'namespace',
),
),);
MetaModel::Init_Params($aParams);
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("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("value", array("allowed_values"=>null, "sql"=>'value', "default_value"=>'0', "is_null_allowed"=>false, "depends_on"=>array(), "always_load_in_tables"=>false)));
MetaModel::Init_SetZListItems('details', array (
0 => 'key_name',
1 => 'value',
2 => 'namespace',
));
MetaModel::Init_SetZListItems('standard_search', array (
0 => 'key_name',
1 => 'value',
2 => 'namespace',
));
MetaModel::Init_SetZListItems('list', array (
0 => 'key_name',
1 => 'value',
2 => 'namespace',
));
;
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
<classes>
<class id="lnkActionNotificationToContact" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -99,7 +99,7 @@
</presentation>
<methods/>
</class>
<class id="ActionNewsroom" _delta="define">
<class id="ActionNewsroom" _delta="define">
<php_parent>
<name>ActionNotification</name>
</php_parent>
@@ -148,7 +148,7 @@
<display_max_height>96</display_max_height>
<storage_max_width>256</storage_max_width>
<storage_max_height>256</storage_max_height>
<default_image />
<default_image/>
</field>
<field id="priority" xsi:type="AttributeEnum">
<sql>priority</sql>
@@ -183,7 +183,7 @@
</field>
<field id="url" xsi:type="AttributeString">
<sql>url</sql>
<default_value>$this->url()$</default_value>
<default_value>$this-&gt;url()$</default_value>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
@@ -355,21 +355,37 @@
}
}
if ($bIsAsync === true) {
AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
} else {
foreach ($aRecipientsIds as $iRecipientId) {
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
$oEvent->DBInsertNoReload();
}
}
try {
if ($bIsAsync === true) {
AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
} else {
foreach ($aRecipientsIds as $iRecipientId) {
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
$oEvent->DBInsertNoReload();
}
}
} catch (CoreCannotSaveObjectException $e) {
ExceptionLog::LogException($e);
foreach($aRecipientsIds as $iRecipientId) {
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this,
$iRecipientId,
$oTrigger->GetKey(),
Dict::S('Core:EventNotificationNewsroom:ErrorOnDBInsert'),
Dict::S('Core:EventNotificationNewsroom:ErrorNotificationNotSent'),
$sUrl,
$iObjectId,
$sObjectClass
);
$oEvent->DBInsertNoReload();
}
}
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
}
]]></code>
</method>
<method id="GetAsynchronousGlobalSetting">
<comment></comment>
<comment/>
<static>true</static>
<access>public</access>
<code><![CDATA[
@@ -381,7 +397,7 @@
</method>
</methods>
</class>
<class id="EventNotificationNewsroom" _delta="define">
<class id="EventNotificationNewsroom" _delta="define">
<php_parent>
<name>EventNotification</name>
</php_parent>
@@ -405,7 +421,7 @@
</reconciliation>
<order>
<columns>
<column id="date" ascending="false" />
<column id="date" ascending="false"/>
</columns>
</order>
</properties>
@@ -419,7 +435,7 @@
<sql>icon</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
<default_image />
<default_image/>
</field>
<field id="priority" xsi:type="AttributeEnum">
<sql>priority</sql>
@@ -501,14 +517,14 @@
</items>
</details>
<summary>
<items>
<item id="date">
<rank>10</rank>
</item>
<item id="message">
<rank>20</rank>
</item>
</items>
<items>
<item id="date">
<rank>10</rank>
</item>
<item id="message">
<rank>20</rank>
</item>
</items>
</summary>
<list>
<items>
@@ -1008,6 +1024,12 @@
<type>string</type>
<default/>
</property>
<property id="class_exclusion_list">
<php_param>class_exclusion_list</php_param>
<mandatory>false</mandatory>
<type>string</type>
<default/>
</property>
<property id="min_up">
<php_param>min_up</php_param>
<mandatory>true</mandatory>

View File

@@ -1748,9 +1748,9 @@ abstract class DBObject implements iDisplay
* @throws \CoreException
* @since 3.0.0 N°4106 Method should not be overloaded anymore for performances reasons. It will be set final in 3.1.0 (N°4107)
* @since 3.0.0 N°580 New $sType parameter
*
* @since 3.3.0 N°4107 Should never be overriden
*/
public function GetName($sType = FriendlyNameType::SHORT)
public final function GetName($sType = FriendlyNameType::SHORT)
{
return utils::EscapeHtml($this->GetRawName($sType));
}

View File

@@ -417,8 +417,17 @@ class DBObjectSearch extends DBSearch
*/
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSearchString = false)
{
MyHelpers::CheckKeyInArray('filter code in class: '.$this->GetClass(), $sFilterCode, MetaModel::GetFilterAttribList($this->GetClass()));
if (MetaModel::IsValidFilterCode($this->GetClass(),$sFilterCode) == false){
/* $sArrayDesc = if (count($aData) == 0)
{
$sArrayDesc = "{}";
}
else
{
$sArrayDesc = "{".implode(", ", $aData)."}";
}*/
throw new CoreException("Wrong value for '".$this->GetClass()."', found '$sFilterCode'");// while expecting a value in $sArrayDesc");
}
$oField = new FieldExpression($sFilterCode, $this->GetClassAlias());
if (empty($sOpCode)) {
if ($sFilterCode == 'id') {
@@ -1364,44 +1373,41 @@ class DBObjectSearch extends DBSearch
$this->m_aParams[$sKey] = $value;
}
public function GetQueryParams($bExcludeMagicParams = true)
public function GetQueryParams()
{
$aParams = array();
$this->m_oSearchCondition->RenderExpression(false, $aParams, true);
if ($bExcludeMagicParams)
{
$aRet = array();
$aRet = array();
// Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams($bExclude magic params)
$aNakedMagicArguments = array();
foreach (MetaModel::PrepareQueryArguments(array(),array(), $this->GetExpectedArguments()) as $sArgName => $value)
// Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams()
$aNakedMagicArguments = array();
foreach (MetaModel::PrepareQueryArguments(array(),array(), $this->GetExpectedArguments()) as $sArgName => $value)
{
$iPos = strpos($sArgName, '->object()');
if ($iPos === false)
{
$iPos = strpos($sArgName, '->object()');
if ($iPos === false)
{
$aNakedMagicArguments[$sArgName] = $value;
}
else
{
$aNakedMagicArguments[substr($sArgName, 0, $iPos)] = true;
}
$aNakedMagicArguments[$sArgName] = $value;
}
foreach ($aParams as $sParam => $foo)
else
{
$iPos = strpos($sParam, '->');
if ($iPos === false)
{
$sRefName = $sParam;
}
else
{
$sRefName = substr($sParam, 0, $iPos);
}
if (!array_key_exists($sRefName, $aNakedMagicArguments))
{
$aRet[$sParam] = $foo;
}
$aNakedMagicArguments[substr($sArgName, 0, $iPos)] = true;
}
}
foreach ($aParams as $sParam => $foo)
{
$iPos = strpos($sParam, '->');
if ($iPos === false)
{
$sRefName = $sParam;
}
else
{
$sRefName = substr($sParam, 0, $iPos);
}
if (!array_key_exists($sRefName, $aNakedMagicArguments))
{
$aRet[$sParam] = $foo;
}
}

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