Compare commits

...

1197 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
c63e01e27b N°8552 - Aggregate brick, Search Brick and new look issue 2025-07-23 16:36:01 +02:00
Benjamin Dalsass
8580cb70a4 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-16 16:46:42 +02:00
Benjamin Dalsass
1438006861 N°8419 - Improve Setup process by avoiding the update of the attachment table when contact_id is already set 2025-07-16 16:41:50 +02:00
Stephen Abello
700470dd29 N°8219 - Allow to reset user cache 2025-07-11 10:28:24 +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
bdalsass
497fc4978a N°8340 - CKEditor is slow with large texts 2025-07-10 10:20:23 +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
6826ab509d N°6925 - Add a dedicated dict entry for "View the OQL query" 2025-07-09 17:10:07 +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
bdalsass
41194ce9ab N°8365 - Portal: impact analysis and silo, Ticket cannot be created due to CI not visible 2025-07-09 07:38:07 +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
Anne-Catherine
0e5bece5b6 N°8347 - Bad display of special characters on the portal CheckToWrite message (#712) 2025-07-08 11:16:11 +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
jf-cbd
e987ea72bc Fix broken URI 2025-07-07 16:01:57 +02:00
bdalsass
a7877dc6a6 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-07 14:04:18 +02:00
bdalsass
c8371f1c19 N°8395 - php8.1 compatibility in class extended Exception 2025-07-07 14:03:29 +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
740f83f43e N°8395 - php8.1 compatibility in class extended Exception 2025-07-03 13:39:39 +02:00
bdalsass
d2d422afcf Merge remote-tracking branch 'origin/support/3.2' into develop 2025-07-01 16:11:20 +02:00
bdalsass
14791bf6b4 N°8148 - CAS problem when sending a link ending in &
- ApplicationContextTest mocking service
2025-07-01 15:57:45 +02:00
Benjamin Dalsass
062d543b26 N°8148 - CAS problem when sending a link ending in & (#722)
N°8148 - CAS problem when sending a link ending in &
2025-06-30 14:19:33 +02:00
bdalsass
278ac66637 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-06-30 10:08:47 +02:00
bdalsass
8cece0f0fd N°8395 - php8.1 compatibility in class extended Exception 2025-06-30 10:01:00 +02:00
odain
87db141c3c Merge branch 'support/3.2' into develop 2025-06-19 11:32:58 +02:00
odain
18871566d2 N°8286 - fix call to CompleteSessionData in case of no proper session content 2025-06-19 11:29:48 +02:00
odain
b565b700a9 Merge branch 'feature/7398-sessiontracker-extensibility' into support/3.2 2025-06-19 10:39:35 +02:00
odain
3846087dc1 N°7398 - regenerate autoload 2025-06-19 10:39:09 +02:00
odain
4f96246cbe N°7398-log level with invalid json 2025-06-19 10:38:01 +02:00
odain
ddd3dcdaf2 N°8286 - Be able to add additional data in iTop session files via custom classes 2025-06-19 10:38:01 +02:00
odain
82ad9d4317 N°7398 - be able to add custom data in session files generated by SessionHandler 2025-06-19 10:38:00 +02:00
Anne-Cath
6dc48ad36d N°8351 - [Export Impact Analysis] Field to display for the CSV export - Add the friendlyname to each list 2025-06-17 10:22:53 +02:00
jf-cbd
f062f994f0 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-06-16 17:01:49 +02:00
Björn Rudner
84476a869f 🎨 remove outdated or duplicated elemets (#726) 2025-06-16 16:25:22 +02:00
jf-cbd
684f829581 Merge commit from fork 2025-06-16 15:06:45 +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
Björn Rudner
d1e6334629 N°8456 - 🐛 add missing element attributes (#725) 2025-06-13 16:50:56 +02:00
Eric Espie
047ba8c6c7 Better KPI log performances 2025-06-13 15:31:30 +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
v-dumas
f609010d7f Fix typo in SynchroLog class name 2025-06-11 17:49:28 +02:00
v-dumas
9330b5ec9a N°8377 - Fix confusing duplicated stimulus label on Change 2025-06-11 17:42:04 +02:00
v-dumas
18b85d4080 N°8377 - Missing rights on change ITIL for SuperUser 2025-06-11 17:41:01 +02:00
v-dumas
7214e5b43a Fix typo in SynchroLog class name 2025-06-11 17:14:15 +02:00
v-dumas
3689a83953 N°2583 - Control rights per class (bulk read on business, bulk write on others) 2025-06-11 17:13:25 +02:00
v-dumas
a715ce1292 Fix typo in SynchroLog class name 2025-06-11 17:11:43 +02:00
v-dumas
17d85fbb3f N°2583 - Advanced mode on CSV import add technical classes and class codes 2025-06-11 16:50:38 +02:00
v-dumas
5e59aff74f N°2583 - Filter Universal Search based on user rights 2025-06-11 16:48:28 +02:00
v-dumas
9e1e81ccc1 N°2583 - Audit, User, Query classes available for universal Search without the "Administrator" profile 2025-06-11 11:17:27 +02:00
v-dumas
c57c8d2af3 N°8406 - Fix FR translations 2025-06-11 10:16:50 +02:00
bdalsass
8a436f9760 N°8251 - Deprecated function when bulk assign
- Deprecated on strlen
2025-06-06 15:26:05 +02:00
bdalsass
2e77713772 N°8399 - Portal: unnecessary screen is displayed during a transition with no field to display 2025-06-06 15:04:21 +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
bdalsass
975c554e91 N°8251 - Deprecated function when bulk assign 2025-06-06 09:02:29 +02:00
bdalsass
ac6f642052 N°8232 - CKEditor: Unexpected lines repeatedly added after blocks 2025-06-06 08:54:23 +02:00
bdalsass
cf9ab2a83c N°8436 - CreateBrick fails when used with an abstract class 2025-06-04 16:22:41 +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
bdalsass
3ff3dcba54 N°8308 - Broken URL in sending mail 2025-06-02 17:15:51 +02:00
jf-cbd
657fc912bf N°8198 - ModuleInstallation now extends DBObject + better exception message 2025-06-02 16:09:29 +02:00
Stephen Abello
a0f4c62bcc Fix browse brick items color not being overloadable 2025-05-28 16:35:12 +02:00
Anne-Catherine
5ae5221f6f N°6925 - Enable on any search result edition of OQL (#711) 2025-05-28 10:59:50 +02:00
jf-cbd
b15ca2fbc9 N°8260 - Change format of REST logs when they are close to the SQL field size limit 2025-05-27 10:41:05 +02:00
Stephen Abello
cb382eab4e Fix CI following dict behavior change 2025-05-26 16:23:38 +02:00
Stephen Abello
9723cde24c N°7960 - Add a wrapper to vsprintf to handle argument number disparities (#717) 2025-05-26 15:41:25 +02:00
Stephen Abello
7ae49e2cf4 N°8076 - Fix cancel and close buttons in a modal blocking all buttons for the underlying object 2025-05-26 11:25:08 +02:00
v-dumas
cb13a7a5b4 N°2583 - Audit, User, Query classes can be Import with bulk_modify right 2025-05-23 17:37:47 +02:00
bdalsass
cd4e2608ee Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-23 10:19:16 +02:00
bdalsass
9618e47045 N°8201 - [CVE_Request]_Cross-Site-Script Reflected(XSS Reflected at the name="attr_installed" (Low or Medium) 2025-05-23 10:16:22 +02:00
bdalsass
d84506ea9e Merge remote-tracking branch 'origin/support/2.7' into support/3.2
# Conflicts:
#	pages/UI.php
2025-05-23 10:14:50 +02:00
bdalsass
13239c2751 N°8201 - [CVE_Request]_Cross-Site-Script Reflected(XSS Reflected at the name="attr_installed" (Low or Medium) 2025-05-23 10:06:01 +02:00
bdalsass
d6c9a6d318 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-23 09:14:26 +02:00
bdalsass
8b30e36dd1 N°8168 - Stored XSS in portals lnk 2025-05-23 08:52:18 +02:00
bdalsass
80b290ab88 Merge remote-tracking branch 'origin/support/2.7' into support/3.2
# Conflicts:
#	sources/renderer/bootstrap/fieldrenderer/bslinkedsetfieldrenderer.class.inc.php
2025-05-23 08:49:52 +02:00
bdalsass
81b20ee583 N°8168 - Stored XSS in portals lnk 2025-05-23 08:42:56 +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
Stephen Abello
a5545b0084 N°8205 - Security hardening 2025-05-20 09:48:00 +02:00
Stephen Abello
d72e861dfe N°8315 - Security hardening 2025-05-19 14:51:12 +02:00
Stephen Abello
92385273ff N°8315 - Security hardening 2025-05-19 14:45:24 +02:00
bdalsass
61c25f85e7 N°8313 - edit dashboard (fix broken test 3.2) 2025-05-19 13:12:02 +02:00
bdalsass
20a7a945fc Merge remote-tracking branch 'origin/support/3.2' into develop 2025-05-16 14:36:36 +02:00
bdalsass
b1cf2ec137 N°8313 - edit dashboard (fix broken test 3.2) 2025-05-16 14:35:39 +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
bdalsass
7549ded51d Merge remote-tracking branch 'origin/support/2.7' into support/3.2
# Conflicts:
#	application/dashboard.class.inc.php
#	setup/setuputils.class.inc.php
#	tests/php-unit-tests/unitary-tests/application/utilsTest.php
2025-05-16 14:19:00 +02:00
bdalsass
38683c20b1 N°8313 - edit dashboard (fix broken test) 2025-05-16 14:05:55 +02:00
bdalsass
81791dd253 N°8313 - edit dashboard 2025-05-16 14:05:55 +02:00
bdalsass
e77e0eec9f N°8355 - render_dashboard 2025-05-16 14:05:55 +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
jf-cbd
f5ddbbbe0e Rollback typing parameter 2025-05-13 16:59:43 +02:00
jf-cbd
6811a82e1a Merge remote-tracking branch 'origin/support/2.7' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-backup/status.php
#	setup/setuputils.class.inc.php
2025-05-13 16:40:11 +02:00
jf-cbd
960133c0df N°8379 - fix backup issue 2025-05-13 16:27:59 +02:00
jf-cbd
544c4ae888 N°8379 - fix backup issue 2025-05-13 16:05:39 +02:00
Stephen Abello
6bd11fb9bf N°8361 - Make vertical the default value for portal's menu 2025-05-06 10:43:34 +02:00
jbostoen
9ee18c2f36 Add helper method to create an ObjectResult from a DBObject. (#706)
Author: Jeffrey Bostoen <support@jeffreybostoen.be>
2025-04-25 14:46:33 +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
jf-cbd
43a10e6944 Revert "N°8259 - Problem with GetMaxSize on AttributeText"
This reverts commit 29c75f626b.
2025-04-22 09:37:54 +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
Stephen Abello
bf8269fee1 N°8293 - Make multiple modal in portal correctly stack the backdrops 2025-03-26 09:26:04 +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
c99995563e Merge remote-tracking branch 'origin/support/3.2.1' into support/3.2
# Conflicts:
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
2025-03-24 11:31:25 +01:00
jf-cbd
7af1cdebfa Workaround for N°4459 doesn't work on 3.2 2025-03-24 11:21:41 +01:00
jf-cbd
a9fb5cd182 N°7870 - Tests: access the symfony service container to instantiate services 2025-03-24 11:02:34 +01:00
jf-cbd
9010504902 Fix tests 2025-03-24 10:53:18 +01:00
jf-cbd
2625b1ab54 Update tests for 3.1 2025-03-24 10:52:47 +01:00
Molkobain
b967338c48 🐛 N°8278 - Avoid autoloaders class name conflict by ensuring all existing have a unique name (#704)
* 🐛 Avoid autoloaders class name conflict by ensuring all existing have a unique name

* 🐛 Redump itop-attachments autoloaders for correct suffix
2025-03-24 10:15:09 +01:00
jf-cbd
10fbea5f4d Fix merge conflict 2025-03-24 10:09:33 +01:00
jf-cbd
e49b8fc480 Merge remote-tracking branch 'origin/support/2.7' into support/3.2.1
# Conflicts:
#	core/restservices.class.inc.php
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
2025-03-24 10:07:36 +01:00
jf-cbd
4a415fdb59 N°8215 - When PHP warning are enabled, Global Request doesn't work 2025-03-21 14:44:18 +01:00
jf-cbd
5232694c04 N°8281 - Unable to click search button in multiple request template 2025-03-21 11:20:37 +01:00
Eric Espie
2a87d0aa15 N°8242 - When editing a dashboard the parameters do not refresh as expected 2025-03-18 17:40:10 +01:00
Anne-Cath
a103c458cb N°8272 - Portal : Unable to save a date in French format - rollback removed code for N°7145 2025-03-18 16:58:50 +01:00
jf-cbd
fe913524fd Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-13 16:04:19 +01:00
Tommaso Rossi
9a895a7fbd 🐛 N°8115 - Unattended Install: unable to connect to MySQL with TLS (#694)
🐛 Support TLS connections to MySQL in unattended-install process
2025-03-13 15:59:04 +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
f5011bb200 N°8260 - Change format of REST logs when they are close to the SQL field size limit 2025-03-13 15:39:00 +01:00
jf-cbd
29c75f626b N°8259 - Problem with GetMaxSize on AttributeText 2025-03-13 15:29:00 +01:00
jf-cbd
4b86639d71 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-12 11:55:15 +01:00
jf-cbd
0562563cbb Dump autoloader 2025-03-12 11:51:59 +01:00
jf-cbd
40068bd913 Merge remote-tracking branch 'origin/support/2.7' into support/3.2
# Conflicts:
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
2025-03-12 11:47:33 +01:00
jf-cbd
874a5fd2ce Dump autoloader 2025-03-12 11:36:06 +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
1ec139782e Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-03-06 16:24:40 +01:00
jf-cbd
056dce4d78 Merge remote-tracking branch 'origin/support/2.7' into support/3.1
# Conflicts:
#	webservices/rest.php
2025-03-06 16:12:15 +01:00
jf-cbd
063bb9680e N°8231 - Better variable fallback 2025-03-06 16:09:51 +01:00
jf-cbd
25e8ec38d6 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-03-06 15:31:19 +01:00
jf-cbd
9b1395db03 Workaround for N°4459 doesn't work on 3.2 2025-03-06 15:23:38 +01:00
jf-cbd
8fd9eb6a84 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-03-06 14:58:24 +01:00
jf-cbd
1142bf327c Fix tests 2025-03-06 14:54:18 +01:00
jf-cbd
278496eaf6 Update tests for 3.1 2025-03-06 14:40:39 +01:00
jf-cbd
77ba0b398f Fix merge conflict 2025-03-06 12:11:20 +01:00
jf-cbd
04ca7bf603 Merge remote-tracking branch 'origin/support/2.7' into support/3.1
# Conflicts:
#	core/restservices.class.inc.php
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
#	tests/php-unit-tests/unitary-tests/core/Delta/delta_test_sanitize_output.xml
#	tests/php-unit-tests/unitary-tests/core/RestServicesSanitizeOutputTest.php
#	tests/php-unit-tests/unitary-tests/core/RestServicesTest.php
#	webservices/rest.php
2025-03-06 12:10:00 +01:00
jf-cbd
8f8ac46f55 N°8215 - When PHP warning are enabled, Global Request doesn't work 2025-03-06 11:59:08 +01:00
denis.flaven@combodo.com
07b904ee1b N°8231 - making rest api logs more readable 2025-03-06 11:59:08 +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
Eric Espie
5aee7f4722 N°8242 - When editing a dashboard the parameters do not refresh as expected 2025-03-05 11:02:19 +01:00
Eric Espie
292701b71c N°8242 - When editing a dashboard the parameters do not refresh as expected 2025-03-04 16:51:58 +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
533b57ab99 Merge branch 'support/3.1' into support/3.2 2025-03-03 17:07:24 +01:00
jf-cbd
be8d348b25 N°8231 - Update tests 2025-03-03 16:49:27 +01:00
jf-cbd
6c7a98fe3d Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-03-03 16:38:32 +01:00
denis.flaven@combodo.com
ec2203229b N°8231 - making rest api log more readable 2025-03-03 16:23:25 +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
2f699d355a Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-03-03 14:37:57 +01:00
jf-cbd
da4457f5b4 Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-03-03 14:36:50 +01:00
denis.flaven@combodo.com
97848cea4f N°8231 - making rest api log more readable 2025-03-03 11:38:52 +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
2ccd883c9a 👥 Update contributor list 2025-02-25 11:38:54 +01:00
jf-cbd
eabd68ff77 👥 Update contributor list 2025-02-25 11:38:14 +01:00
jf-cbd
d982652228 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-02-25 09:22:04 +01:00
jf-cbd
2b493787b1 Update itop-version-history.md with 2.7.12, 3.1.3 and 3.2.1 2025-02-25 09:19:47 +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
d74c850621 N°7870 - Tests: access the symfony service container to instantiate services 2025-02-21 15:28:38 +01:00
jf-cbd
4e575e17a3 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-02-21 13:23:57 +01:00
jf-cbd
94d6eca0c1 N°8215 - When PHP warning are enabled, Global Request doesn't work 2025-02-21 13:20:27 +01:00
jf-cbd
355da8ec0a Merge remote-tracking branch 'origin/support/2.7' into support/3.1
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
2025-02-21 13:18:19 +01:00
jf-cbd
5f006c45db N°8215 - When PHP warning are enabled, Global Request doesn't work 2025-02-21 13:16:07 +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
Eric Espie
a9bc4973b4 N°8139 - Fix ApplyStimulus during post update 2025-02-07 17:24:43 +01:00
Timothee
e93d909a38 🌐 Dictionaries update 2025-02-07 15:36:58 +01:00
jf-cbd
534b087a2c N°8163 - Increase page redirection timeout on logout 2025-02-07 14:36:01 +01:00
Eric Espie
14346e0895 N°8139 - Avoid double writing in lifecycle action 2025-02-07 11:10:14 +01:00
Eric Espie
6985e366c2 N°8139 - Avoid double writing in lifecycle action 2025-02-07 10:58:13 +01:00
denis.flaven@combodo.com
e85ec6bb47 Merge branch 'support/3.2' into develop 2025-02-07 10:36:32 +01:00
denis.flaven@combodo.com
cf57549370 Merge branch 'support/3.1' into support/3.2 2025-02-07 10:29:24 +01:00
denis.flaven@combodo.com
46aaeb4301 Merge branch 'support/2.7' into support/3.1 2025-02-07 10:24:18 +01:00
Eric Espie
7ddc593869 🔊 enhance crud logs 2025-02-07 10:14:39 +01:00
denis.flaven@combodo.com
affed69999 Version number bump. 2025-02-07 10:09:48 +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
jf-cbd
695f357054 N°8170 - Issue with Ckeditor and precanned reply
N°8152 - CKEditor : Style and list button are the same
2025-02-06 17:11:53 +01:00
Eric Espie
0088580798 Better specific delta detection for tests 2025-02-05 17:40:57 +01:00
Ben
92d49c6c47 Adding new modules 2025-02-04 11:56:57 +01:00
Ben
f6298370a7 Adding new modules 2025-02-04 11:56:32 +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
jf-cbd
bd6ccc55f8 N°8150 - Better picture checking 2025-02-04 10:49:54 +01:00
XGUI
3a497524dc N°8129 - Fix unexpected identifier self 2025-02-04 10:48:28 +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
denis.flaven@combodo.com
4c1da328ce Merge support/3.1 into support/3.2 2025-01-31 17:20:33 +01:00
denis.flaven@combodo.com
64a216e0f6 Merge branch 'support/2.7' into support/3.1 2025-01-31 17:13:09 +01:00
denis.flaven@combodo.com
d5754fc568 N°8135 - Bump datamodel version. 2025-01-31 17:04:56 +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
5851b2e1ff N°8129 - Fix missing namespace backslash 2025-01-30 15:06:00 +01:00
XGUI
803ebfbe33 N°8129 - Dont crash if date/time default value has a bad format 2025-01-30 14:14:31 +01:00
odain
d12c8a183c N°8143 - Setup page in error in support.combodo.com 2025-01-30 11:16:07 +01:00
Anne-Cath
7bbd4b4726 N°8144 - Issue using Organization filtering box 2025-01-30 10:10:36 +01:00
odain
c8754725b0 N°8143 - Setup page in error in support.combodo.com 2025-01-29 16:42:43 +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
a3c911e93e N°8139 - Avoid double writing in lifecycle action 2025-01-29 09:32:21 +01:00
Eric Espie
72e0750c1b Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-28 11:13:05 +01:00
Eric Espie
38e0fb27f1 N°8131 - Issue on DBlinkchange event when object is deleted 2025-01-28 11:12:11 +01:00
Eric Espie
4b4197d910 N°8131 - Issue on DBlinkchange event when object is deleted 2025-01-28 11:09:31 +01:00
jf-cbd
ac8004561b Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-28 10:53:15 +01:00
jf-cbd
c5189b7d33 N°8134 - Fix import after merge 2025-01-28 10:52:29 +01:00
jf-cbd
b0288bc08e Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php
2025-01-28 10:44:35 +01:00
Eric Espie
52097f5e12 N°8131 - Issue on DBlinkchange event when object is deleted 2025-01-28 10:33:11 +01:00
jf-cbd
ccb1ca9d79 Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-01-28 10:32:18 +01:00
jf-cbd
44290db312 N°8134 - Portal user profile is broken, regression from 7776 2025-01-28 10:23:44 +01:00
Eric Espie
65e49e2139 N°8139 - Avoid double writing in lifecycle action 2025-01-27 17:34:46 +01:00
Eric Espie
b1bf89807d Add CRUD logs 2025-01-27 15:06:11 +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
39c59f46fd Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-01-24 14:35:48 +01:00
Eric Espie
025af923ea N°8131 - Issue on DBlinkchange event when object is delete 2025-01-24 14:23:50 +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
c2aecad9d2 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-01-24 12:06:49 +01:00
v-dumas
986e900a99 N°7145 - Inline & Attachment add default expire for MailToTicket 2025-01-24 12:03:16 +01:00
Eric Espie
858b12abaa N°8131 - Issue on DBlinkchange event when object is delete 2025-01-24 11:59:51 +01:00
Stephen Abello
bd93879ac4 Add yellow and purple SCSS variables 2025-01-23 11:27:36 +01:00
Timmy38
133a4a8533 N°8113 Fix global organization filter (#699) 2025-01-23 10:04:02 +01:00
Eric Espie
51bb0add8e Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-22 17:11:13 +01:00
Eric Espie
1163a20cdd Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	application/cmdbabstract.class.inc.php
2025-01-22 16:44:12 +01:00
Eric Espie
a7bc4bd411 Add new measure points for KPI logger 2025-01-22 16:34:31 +01:00
Benjamin Dalsass
6f3fddf9bf N°8122 - View or edit an object in portal in a new tab no more possible 2025-01-22 14:15:23 +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
470f145747 N°6284 - fix regex 2025-01-21 17:41:53 +01:00
Timmy38
2852d8ce49 N°7662 Allowing indentation and de-indentation (#698) 2025-01-21 17:12:43 +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
7e9a95fe93 Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php
2025-01-21 16:55:04 +01:00
jf-cbd
a07f66c061 Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-01-21 16:48:33 +01:00
jf-cbd
c49ceae75e Fix HandleForm call 2025-01-21 16:46:15 +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
80244e2797 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-01-21 13:48:12 +01:00
jf-cbd
4da975cb64 Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-01-21 12:15:06 +01:00
jf-cbd
8980f627e9 Fix format 2025-01-21 12:09:06 +01:00
jf-cbd
5ce1788d4a N°7776 remove twig from ajax calls, 3.2 edition 2025-01-20 16:34:46 +01:00
jf-cbd
38fe31c9fc Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
2025-01-20 16:33:35 +01:00
jf-cbd
ec61b52238 N°7776 remove twig from ajax calls, 3.1 edition 2025-01-20 16:02:26 +01:00
jf-cbd
072596a53b Merge remote-tracking branch 'origin/support/2.7' into support/3.1
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
2025-01-20 15:53:34 +01:00
jf-cbd
160bfd714b N°7776 remove twig from ajax calls 2025-01-20 15:41:22 +01:00
Eric Espie
3b51124f1c N°7927 - No context tag available on designer MTP 2025-01-17 10:06:20 +01:00
jf-cbd
e7b87128b1 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-16 17:18:02 +01:00
jf-cbd
19fa836758 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2025-01-16 17:16:31 +01:00
jf-cbd
1c5cb1547f Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2025-01-16 17:15:12 +01:00
jf-cbd
8d58372074 Update unattended installation script documentation 2025-01-16 17:13:26 +01:00
Eric Espie
e98c6637ac N°8108 - EVENT_DB_AFTER_WRITE: $oEventData->Get('changes') missing previous values 2025-01-16 09:31:12 +01:00
odain
7d2a9d0bfc N°8066 - Polishing Webhook Oauth 2025-01-15 17:26:12 +01:00
odain
762d1162ca N°8066 - Polishing Webhook Oauth 2025-01-15 16:59:51 +01:00
odain
d0bdde30ad Merge branch 'support/3.2' into develop 2025-01-14 08:34:41 +01:00
odain
95dbe4c859 N°7873 - ci fix remove useless require_once 2025-01-14 07:52:07 +01:00
Benjamin Dalsass
3fe8b6c696 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-13 15:01:55 +01:00
Benjamin Dalsass
ec6adee9c1 Remove useless require_once and replace it with inheritance 2025-01-13 14:32:06 +01:00
Benjamin Dalsass
baa8bba926 N°8031 - Make all portal bricks use custom templates for all templates
add missing templates
2025-01-13 12:50:58 +01:00
v-dumas
8dc5411717 N°7906 - User Preference: friendlyname, list, search criteria and reconciliation 2025-01-13 12:08:14 +01:00
Tommaso Rossi
6539687f16 🌐 Italian translation enhancements (#697) 2025-01-13 12:07:33 +01:00
Benjamin Dalsass
f1d448fd78 N°8031 - Make all portal bricks use custom templates for all templates
add missing templates
2025-01-13 11:53:44 +01:00
odain
a4490e2b5f N°7873 - Portal: Brick visible despite XML security tag allowed profiles 2025-01-13 11:06:27 +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
odain
efb7831a5a N°7111 - False link at the end of the setup 2025-01-13 08:30:23 +01:00
Benjamin Dalsass
9fadbb5eb1 N°8031 - Make all portal bricks use custom templates for all templates (#696)
Service implementation
2025-01-13 08:04:49 +01:00
Romain Quetiez
93dba0644d N°5791 - Handle NOT IN and NOT LIKE too 2025-01-10 16:21:12 +01:00
XGUI
ec324bb28e N°7746 - Caselog edition button active even if the user has a read-only access to the object 2025-01-10 11:12:03 +01:00
Eric Espie
dc8f521b12 N°7145 - UI - Init Value DateTime and Date with Day Time (Add default values on mandatory dates) 2025-01-09 11:56:55 +01:00
Eric Espie
bf6277fcd2 N°7145 - UI - Init Value DateTime and Date with Day Time (support raw date values) 2025-01-09 11:22:28 +01:00
Eric Espie
886db5d6ad N°7145 - UI - Init Value DateTime and Date with Day Time (use OQL syntax for default value) 2025-01-09 10:49:35 +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
Eric Espie
0e8ddf990c N°7145 - UI - Init Value DateTime and Date with Day Time (Fix Event class) 2025-01-07 13:21:13 +01:00
Eric Espie
346a8eadec N°5791 - Obsolescence condition containing IN makes object creation fail 2025-01-07 11:29:33 +01:00
Eric Espie
6948c594c2 N°7145 - UI - Init Value DateTime and Date with Day Time 2025-01-07 10:18:23 +01:00
Eric Espie
301a7a92a0 N°7145 - UI - Init Value DateTime and Date with Day Time 2025-01-06 16:52:32 +01:00
Eric Espie
73bb80ebea N°7206 - Force DBUpdate() when a transition is asked, and it leads to the same state 2025-01-06 11:31:36 +01:00
Timmy38
1e674d7bdc N°7383 Show data table even when there is no data after filtering (#695) 2025-01-06 11:06:18 +01:00
v-dumas
1225ee1e78 improve test 2025-01-03 17:18:24 +01:00
v-dumas
a91de9fb36 Add helpers for stopwatches manipulation 2025-01-03 17:04:41 +01:00
v-dumas
71b3a415a6 N°7206 - Add tests 2025-01-03 16:17:51 +01:00
Romain Quetiez
b97c7433c8 🎨 N°7633 Cosmetics on unit tests 2025-01-03 11:57:51 +01:00
jf-cbd
5a59d16c99 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-01-02 09:34:32 +01:00
jf-cbd
11fc958a7b 🐛 N°6284 - Add data-object-key 2024-12-31 15:01:36 +01:00
odain
a63a3d3d9c Merge branch 'support/3.2' into develop 2024-12-27 11:14:21 +01:00
odain
a151e40b75 Merge branch 'support/3.1' into support/3.2 2024-12-27 11:13:50 +01:00
odain
5780f26817 N°7810: fix merge 2024-12-27 11:13:31 +01:00
odain
ed6e4f612a Merge branch 'support/3.2' into develop 2024-12-27 09:24:49 +01:00
odain
9a690861a3 Merge branch 'support/3.1' into support/3.2 2024-12-27 09:24:33 +01:00
odain
343f3286b8 Merge branch 'support/2.7' into support/3.1 2024-12-27 09:08:47 +01:00
Eric Espie
37fc1a5723 N°7810 - security hardening 2024-12-27 09:04:28 +01:00
Eric Espie
16279233e0 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-26 14:54:14 +01:00
Eric Espie
7a09b3effc 🐛 Don't display create mailbox if the corresponding class does not exist 2024-12-24 15:05:48 +01:00
Romain Quetiez
4f6d514694 N°8001 - Refactoring: instantiation of an ormDocument moved to... ormDocument 2024-12-20 10:36:25 +01:00
Stephen Abello
07964cc404 Merge branch 'support/3.2' into develop 2024-12-20 10:16:11 +01:00
Stephen Abello
8f8b65a71d N°8031 - Add robustness if portal configuration doesn't go through 2024-12-20 10:15:22 +01:00
Timothee
49e72e83fe N°6282 Fix XSS vulnerability in wsdl 2024-12-19 15:34:43 +01:00
Stephen Abello
ea5473ad77 Merge branch 'support/3.2' into develop 2024-12-19 15:16:51 +01:00
Stephen Abello
f0685e33e1 N°8031 - Add robustness and fix SF parameter binding being ambiguous in extensions bricks 2024-12-19 15:14:46 +01:00
Tommaso Rossi
2a888cf5af 🌐 Update IT IT dictionaries (#693) 2024-12-19 14:13:13 +01:00
Timmy38
42f391472b N°6282 Fix XSS vulnerability in soap (#690)
* N°6282 Fix XSS vulnerability in soap
2024-12-19 11:39:00 +01:00
Eric Espie
30ef2735b6 N°8001 - TriggerOnObjectMention : load of the icon failed 2024-12-18 16:03:39 +01:00
Stephen Abello
548131482a Merge branch 'support/3.2' into develop 2024-12-18 11:10:43 +01:00
Stephen Abello
bbff0b72d3 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:09:39 +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
2dffab9ca0 🌐 Update ZH CN dictionaries 2024-12-18 10:39:25 +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
1cbfa4f1b1 🌐 Update ZH CN dictionaries 2024-12-18 10:11:52 +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
odain-cbd
5f85757630 N°7633 - Reloads the same user multiple times if it no longer exists (#692)
* N°7633 - Reloads the same user multiple times if it no longer exists

* Update core/userrights.class.inc.php

good catch

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

* Update core/userrights.class.inc.php

good catch (again)

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

* Update core/userrights.class.inc.php

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

* PR feedbacks from Romain

* ci: rename user logins

---------

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2024-12-17 17:27:49 +01:00
jf-cbd
90f58721b1 🌐 Update ZH CN dictionaries 2024-12-17 17:21:55 +01:00
v-dumas
56d3ac668c N°8047 - SuperUser profile moved under iTop Community 3.2.1 2024-12-17 16:31:59 +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
0a3b02bf45 🌐 Update ZH CN dictionaries 2024-12-16 18:30:22 +01:00
jf-cbd
74ebbc5fa4 🌐 Update ZH CN dictionaries 2024-12-16 18:19:17 +01:00
Eric Espie
a762b6a2bb Fix failing directory removal 2024-12-16 17:04:33 +01:00
Eric Espie
32ef639ce1 N°7803 - MTP from itophub/designer failing in itop 3.2.0 2024-12-16 16:44:59 +01:00
Purple Grape
8647a76dbf 🌐 Translations - improved translation for zh cn 20241108 (#679)
* improved translation for zh cn
2024-12-16 11:39:26 +01:00
jf-cbd
96414dcc98 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-16 11:07:32 +01:00
jf-cbd
47cd8bce31 Security hardening 2024-12-16 11:05:16 +01:00
jf-cbd
86c677b2ca Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/src/Controller/ObjectController.php
2024-12-16 11:02:37 +01:00
Eric Espie
960129316d N°8050 - Fix regression due to directories filter changes 2024-12-16 10:56:06 +01:00
jf-cbd
1fa50f695d Security hardening 2024-12-16 10:47:06 +01:00
Anne-Cath
6ab19d29b9 fix tests in all iTop configurations 2024-12-16 10:38:44 +01:00
jf-cbd
692cf4f635 Merge branch 'support/2.7' into support/3.1 2024-12-16 10:27:00 +01:00
jf-cbd
95aa444ee6 Security hardening 2024-12-13 16:48:13 +01:00
jf-cbd
f5de808c7c Security hardening (#685)
* security hardening
2024-12-13 15:09:18 +01:00
Eric Espie
5c5c5d769f Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-13 10:17:40 +01:00
Eric Espie
fc388313d7 N°8050 - Problems with interface discovery from itop 2024-12-13 10:14:17 +01:00
odain
d544ee5498 N°7750 - ci enhance test 2024-12-13 09:35:35 +01:00
Anne-Cath
ecce0a3376 fix tests 2024-12-13 09:20:19 +01:00
odain
ce187550f6 N°7750 - Fix display regression 2024-12-12 12:21:57 +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
5d15a08824 🥅 Fast setup error display 2024-12-12 09:55:16 +01:00
Eric Espie
0fd2cf85a2 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-12-12 08:44:38 +01:00
odain
8135316119 N°7750 - Bug with OQL set as Shortcut 2024-12-11 16:05:15 +01:00
Eric Espie
868c0ae836 N°7997 - Sharing Base incompatible with iTop >= 3.1 (code review) 2024-12-11 15:51:36 +01:00
Eric Espie
d03d4fce5f N°7997 - Sharing Base incompatible with iTop >= 3.1 2024-12-11 13:35:15 +01:00
Eric Espie
aa55c2b30f N°7997 - Sharing Base incompatible with iTop >= 3.1 2024-12-11 13:28:37 +01:00
Eric Espie
9d3b46b919 🥅 Fast setup error display 2024-12-11 11:40:03 +01:00
Eric Espie
01b4dbba71 🥅 Fast setup error display 2024-12-11 11:20:32 +01:00
Eric Espie
72ac4096c1 N°7854 - ⬆️ Bump twig version 2024-12-10 17:08:48 +01:00
Eric Espie
19559b08a7 N°7854 - ⬆️ Bump twig version 2024-12-10 10:52:30 +01:00
Eric Espie
346564ca0e N°7854 - ⬆️ Bump twig version 2024-12-10 10:11:28 +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
Eric Espie
1bf53bae2a N°7871 - unable to migrate to itop3.2 if a trigger on object mention without "mentioned filter" exists 2024-12-09 17:05:07 +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
Eric Espie
29ce042916 N°7867 - Issue with MTP offline (reset cache in metamodel) 2024-12-09 10:38:50 +01:00
odain
83539d6d4c N°7446 - Make ItopCustomDatamodelTestCase work with modules in production-modules 2024-12-05 11:29:05 +01:00
Eric Espie
e6a7b926f6 N°7852 - Issue on Class groups definition when checking EventNotification class 2024-12-05 11:14:19 +01:00
Eric Espie
b30e053236 N°8020 - Bugs MFA and designer incompatibility 2024-12-03 16:42:27 +01:00
Stephen Abello
ecfc26f1ec Merge branch 'support/3.2' into develop 2024-12-03 10:47:42 +01:00
Stephen Abello
afd96a0f49 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:44:37 +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
Eric Espie
a77765ec7b N°8019 - Enrich event with transition information 2024-12-03 10:28:13 +01:00
jf-cbd
64b4b03ea9 Security hardening 2024-12-03 10:26:11 +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
a797878b17 Security hardening 2024-12-03 09:54:31 +01:00
jf-cbd
a1860c82fb Merge branch 'support/3.2' into develop 2024-12-02 17:47:10 +01:00
jf-cbd
1fa0f7bdd9 N°8007 - Security hardening 2024-12-02 17:45:39 +01:00
Eric Espie
f718b4173d N°7206 - TriggerOnStateEnter not called when using reassign transition (after review) 2024-12-02 17:28:15 +01:00
Eric Espie
e057c0f081 N°7777 - Click on tab "Last executions" during action creation crashs the form 2024-12-02 17:12:32 +01:00
Eric Espie
5a49fc7654 N°7206 - TriggerOnStateEnter not called when using reassign transition 2024-12-02 14:49:28 +01:00
Stephen Abello
6fca659c9d Fix portal not being able to use $common-* SCSS variables when recompiling stylesheets 2024-12-02 14:06:53 +01:00
Stephen Abello
eacd08f31e Fix SCSS comments type 2024-12-02 14:03:39 +01:00
jf-cbd
d47d65df10 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-29 16:49:57 +01:00
jf-cbd
5f7d8f6cc0 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-11-29 16:43:13 +01:00
jf-cbd
cbb4281a37 N°7980 - security hardening 2024-11-29 16:40:34 +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
d7a8d335d5 N°7446 - Fix in CI environment when class already loaded 2024-11-29 12:22:38 +01:00
odain
a65dd1c27c Merge branch 'support/3.2' into develop 2024-11-29 12:09:08 +01:00
odain
bd1d447677 N°7446 - Fix in CI environment 2024-11-29 12:08:16 +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
Eric Espie
bb405d5173 N°7429 - Create an MFA extension for iTop - Add support for AttributeClassSet 2024-11-27 14:57:51 +01:00
Benjamin Dalsass
fcfdac2844 Merge remote-tracking branch 'origin/support/3.2' into develop 2024-11-27 09:56:35 +01:00
Benjamin Dalsass
4723fc885c Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	application/dashboard.class.inc.php
2024-11-27 09:55:15 +01:00
Benjamin Dalsass
06dcae1dd1 Merge remote-tracking branch 'origin/support/2.7' into support/3.1 2024-11-27 09:50:57 +01:00
Benjamin Dalsass
e03033ce52 N°7219 - Fatal error following dashboard modification when dashboard title contains an é 2024-11-27 09:40:22 +01:00
Timothee
19eae916f0 N°7792 Do not initialize CAS if already started 2024-11-22 09:59:41 +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
Lars Kaltefleiter
596e26a96f 🌐 N°7932 Translations - British English (#677)
* Translation into EN GB
2024-11-18 14:38:53 +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
Eric Espie
ef42a49009 Allow extensions to add extra datamodel for tests 2024-11-14 09:27:57 +01:00
Romain Quetiez
51e5f1e7de N°7962 Suppress warnings emitted by the parser/lexer generators and the runtime OQL lexer, with PHP 8.1+ 2024-11-13 15:28:29 +01:00
Timothee
9cffd17e19 N°7704 Fix missing namespace for constant EVENT_DOWNLOAD_DOCUMENT 2024-11-13 14:39:23 +01:00
Benjamin Dalsass
d95e7168aa Merge branch 'support/3.2' into develop 2024-11-13 13:32:53 +01:00
Benjamin Dalsass
e9f16935b6 N°6613 - Fix user picture pushing invalid data 2024-11-13 13:20:27 +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
3100 changed files with 198484 additions and 175279 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

@@ -93,6 +93,12 @@ gitGraph
checkout support/3.2
commit id: "2024-06-25" tag: "3.2.0-beta1" type: REVERSE
commit id: "2024-08-07" tag: "3.2.0"
checkout support/2.7
commit id: "2025-02-25" tag: "2.7.12"
checkout support/3.1
commit id: "2025-02-25 " tag: "3.1.3"
checkout support/3.2
commit id: "2025-02-25 " tag: "3.2.1"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

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,5 +1,9 @@
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
<img src="https://www.combodo.com/logos/logo-itop-baseline.svg" width=350>
<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">
<img src="/images/logos/logo-itop-baseline-light.svg" width="350" alt="Logo iTop with baseline" />
</picture>
</a></p>
@@ -76,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
@@ -88,33 +94,44 @@ 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
- Roháč, Richard (a.k.a [@RohacRichard](https://github.com/RohacRichard))
- Rosenke, Stephan
- Rossi, Tommaso (a.k.a [@tomrss](https://www.github.com/tomrss))
- Rudner, Björn (a.k.a [@rudnerbjoern](https://github.com/rudnerbjoern))
- Šafránek, Jaroslav (a.k.a [jkcinik](https://sourceforge.net/u/jkcinik/profile/) on SourceForge)
- 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
@@ -135,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');
?>

View File

@@ -825,49 +825,38 @@ class UserRightsProfile extends UserRightsAddOnAPI
{
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
// We have to answer NO for objects shared for reading purposes
if (self::HasSharing())
{
$aClassProps = SharedObject::GetSharedClassProperties($sClass);
if ($aClassProps)
{
// This class is shared, GetSelectFilter may allow some objects for read only
// But currently we are checking wether the objects might be written...
// Let's exclude the objects based on the relevant criteria
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
// This class is shared, GetSelectFilter may allow some objects for read only
// But currently we are checking whether the objects might be written...
// Let's exclude the objects based on the relevant criteria
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
if (!is_null($sOrgAttCode))
{
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0)
{
$iCountNO = 0;
$iCountYES = 0;
$oInstanceSet->Rewind();
while($oObject = $oInstanceSet->Fetch())
{
$iOrg = $oObject->Get($sOrgAttCode);
if (in_array($iOrg, $aUserOrgs))
{
$iCountYES++;
}
else
{
$iCountNO++;
}
}
if ($iCountNO == 0)
{
$iPermission = UR_ALLOWED_YES;
}
elseif ($iCountYES == 0)
{
$iPermission = UR_ALLOWED_NO;
}
else
{
$iPermission = UR_ALLOWED_DEPENDS;
// Use $oInstanceSet only if sClass is the main class
if (!is_a($oInstanceSet->GetClass(), $sClass, true)) {
/** @var \DBObjectSet $oInstanceSet */
throw new CoreException(__FUNCTION__.': Expecting object set to be of class '.$sClass.' but it is of class '.$oInstanceSet->GetClass(), ['OQL_Query' => $oInstanceSet->GetFilter()->ToOQL(), 'classes' => $oInstanceSet->GetSelectedClasses()]);
}
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
if (!is_null($sOrgAttCode)) {
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0) {
$iCountNO = 0;
$iCountYES = 0;
$oInstanceSet->Rewind();
while ($oObject = $oInstanceSet->Fetch()) {
$iOrg = $oObject->Get($sOrgAttCode);
if (in_array($iOrg, $aUserOrgs)) {
$iCountYES++;
} else {
$iCountNO++;
}
}
if ($iCountNO == 0) {
$iPermission = UR_ALLOWED_YES;
} elseif ($iCountYES == 0) {
$iPermission = UR_ALLOWED_NO;
} else {
$iPermission = UR_ALLOWED_DEPENDS;
}
}
}
}
@@ -982,4 +971,3 @@ class UserRightsProfile extends UserRightsAddOnAPI
UserRights::SelectModule('UserRightsProfile');
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -195,16 +195,31 @@ class ApplicationContext
/**
* Returns the context as string with the format name1=value1&name2=value2....
* @return string The context as a string to be appended to an href property
*
*/
public function GetForLink()
public function GetForLink(bool $bWithLeadingAmpersand = false)
{
// If there are no parameters, return an empty string
if(empty($this->aValues)){
return '';
}
// Build the query string with ampersand separated parameters
$aParams = array();
foreach($this->aValues as $sName => $sValue)
{
$aParams[] = "c[$sName]".'='.urlencode($sValue);
}
return implode("&", $aParams);
$sReturnValue = implode('&', $aParams);
// add the leading ampersand if requested
if($bWithLeadingAmpersand){
$sReturnValue = '&' . $sReturnValue;
}
return $sReturnValue;
}
/**
* @since 3.0.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
* Returns the params as c[menu]:..., c[org_id]:....
@@ -382,7 +397,7 @@ class ApplicationContext
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey);
if (utils::StrLen($sUrl) > 0) {
if ($bWithNavigationContext) {
return $sUrl."&".$oAppContext->GetForLink();
return $sUrl.$oAppContext->GetForLink(true);
} else {
return $sUrl;
}

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

@@ -311,7 +311,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
$sParams .= $sName.'='.urlencode($value).'&'; // Always add a trailing &
}
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/'.$oObj->GetUIPage().'?'.$sParams.'class='.get_class($oObj).'&id='.$oObj->getKey().'&'.$oAppContext->GetForLink().'&a=1';
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/'.$oObj->GetUIPage().'?'.$sParams.'class='.get_class($oObj).'&id='.$oObj->getKey().$oAppContext->GetForLink(true).'&a=1';
$oPage->add_early_script(<<<JS
if (!sessionStorage.getItem('$sSessionStorageKey'))
{
@@ -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();
@@ -1113,8 +1113,10 @@ HTML
}
// Note: DisplayBareHeader is called before adding $oObjectDetails to the page, so it can inject HTML before it through $oPage.
/** @var iTopWebPage $oPage */
/** @var \iTopWebPage $oPage */
$oKPI = new ExecutionKPI();
$aHeadersBlocks = $this->DisplayBareHeader($oPage, $bEditMode);
$oKPI->ComputeStatsForExtension($this, 'DisplayBareHeader');
if (false === empty($aHeadersBlocks['subtitle'])) {
$oObjectDetails->AddSubTitleBlocks($aHeadersBlocks['subtitle']);
}
@@ -1127,8 +1129,12 @@ HTML
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, '', $oObjectDetails);
$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
$oPage->SetCurrentTab('UI:PropertiesTab');
$oKPI = new ExecutionKPI();
$this->DisplayBareProperties($oPage, $bEditMode);
$oKPI->ComputeStatsForExtension($this, 'DisplayBareProperties');
$oKPI = new ExecutionKPI();
$this->DisplayBareRelations($oPage, $bEditMode);
$oKPI->ComputeStatsForExtension($this, 'DisplayBareRelations');
// Note: Adding the JS snippet which enables the image upload should have been done directly by the ActivityPanel which would have kept the independance principle
@@ -1331,7 +1337,7 @@ HTML
}
}
}
$aHeader['friendlyname'] = ['label' => MetaModel::GetName($sClassName)];
foreach ($aList[$sAlias] as $sAttCodeEx => $oAttDef) {
$sColLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx) : $sAttCodeEx;
@@ -1352,6 +1358,7 @@ HTML
$aRow = [];
foreach ($aAuthorizedClasses as $sAlias => $sClassName) {
$oObj = $aObjects[$sAlias];
$aRow["friendlyname"] = $oObj->Get('friendlyname');
foreach ($aList[$sAlias] as $sAttCodeEx => $oAttDef) {
if (is_null($oObj)) {
$aRow[$oAttDef->GetCode()] = '';
@@ -2924,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
@@ -3065,7 +3072,7 @@ JS
$oPage->add($oAppContext->GetForForm());
// Hook the cancel button via jQuery so that it can be unhooked easily as well if needed
$sDefaultUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search_form&class='.$sClass.'&'.$oAppContext->GetForLink();
$sDefaultUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search_form&class='.$sClass.$oAppContext->GetForLink(true);
$sCancelButtonOnClickScript = "let fOnClick{$this->m_iFormId}CancelButton = ";
if(isset($aExtraParams['js_handlers']['cancel_button_on_click'])){
@@ -3073,7 +3080,7 @@ JS
} else {
$sCancelButtonOnClickScript .= "function() { BackToDetails('$sClass', $iKey, '$sDefaultUrl', $sJSToken)};";
}
$sCancelButtonOnClickScript .= "$('#form_{$this->m_iFormId} button.cancel').on('click', fOnClick{$this->m_iFormId}CancelButton);";
$sCancelButtonOnClickScript .= "$('#form_{$this->m_iFormId} button.cancel').on('click.navigation.itop', fOnClick{$this->m_iFormId}CancelButton);";
$oPage->add_ready_script($sCancelButtonOnClickScript);
$iFieldsCount = count($aFieldsMap);
@@ -3439,8 +3446,18 @@ EOF
}
$sInputType = '';
$sInputId = 'att_'.$iFieldIndex;
$value = $this->Get($sAttCode);
$sDisplayValue = $this->GetEditValue($sAttCode);
if ($oAttDef instanceof AttributeDateTime && !$oAttDef->IsNullAllowed() && $value === $oAttDef->GetNullValue()) {
$value = $oAttDef->GetDefaultValue($this);
if ($value !== $oAttDef->GetNullValue()) {
// Set default date
$this->Set($sAttCode, $value);
$sDisplayValue = $this->GetEditValue($sAttCode);
}
}
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,
$this->Get($sAttCode), $this->GetEditValue($sAttCode), $sInputId, '', $iExpectCode,
$value, $sDisplayValue, $sInputId, '', $iExpectCode,
$aArgs, true, $sInputType);
$aAttrib = array(
'label' => '<span>'.$oAttDef->GetLabel().'</span>',
@@ -3908,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;
}
@@ -4296,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))
@@ -4558,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__);
@@ -4673,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())
@@ -4843,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
*
@@ -5190,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 {
@@ -5244,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);
}
@@ -5923,14 +5786,14 @@ JS
*
* @since 3.1.0
*/
final protected function FireEventCheckToWrite(): void
final protected function FireEventCheckToWrite(?string $sStimulusBeingApplied): void
{
$this->FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => $this->IsNew()]);
$this->FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
}
final protected function FireEventBeforeWrite()
final protected function FireEventBeforeWrite(?string $sStimulusBeingApplied)
{
$this->FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => $this->IsNew()]);
$this->FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
}
/**
@@ -5942,11 +5805,11 @@ JS
* @throws \CoreException
* @since 3.1.0
*/
final protected function FireEventAfterWrite(array $aChanges, bool $bIsNew): void
final protected function FireEventAfterWrite(array $aChanges, bool $bIsNew, ?string $sStimulusBeingApplied): void
{
$this->NotifyAttachedObjectsOnLinkClassModification();
$this->RemoveObjectAwaitingEventDbLinksChanged(get_class($this), $this->GetKey());
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges]);
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied]);
}
//////////////
@@ -6087,7 +5950,9 @@ JS
// We want to avoid launching the listener twice, first here, and secondly after saving the Ticket in the listener
// By disabling the event to be fired, we can remove the current object from the attribute !
$oObject = MetaModel::GetObject($sClass, $sId, false);
self::FireEventDbLinksChangedForObject($oObject);
if (!is_null($oObject)) {
self::FireEventDbLinksChangedForObject($oObject);
}
self::RemoveObjectAwaitingEventDbLinksChanged($sClass, $sId);
}
@@ -6095,13 +5960,11 @@ JS
{
self::SetEventDBLinksChangedBlocked(true);
// N°6408 The object can have been deleted
if (!is_null($oObject)) {
$oObject->FireEvent(EVENT_DB_LINKS_CHANGED);
$oObject->FireEvent(EVENT_DB_LINKS_CHANGED);
// Update the object if needed
if (count($oObject->ListChanges()) !== 0) {
$oObject->DBUpdate();
}
// Update the object if needed
if (count($oObject->ListChanges()) !== 0) {
$oObject->DBUpdate();
}
cmdbAbstractObject::SetEventDBLinksChangedBlocked(false);
}
@@ -6179,9 +6042,9 @@ JS
* @inheritDoc
* @throws \CoreException
*/
final protected function FireEventComputeValues(): void
final protected function FireEventComputeValues(?string $sStimulusBeingApplied): void
{
$this->FireEvent(EVENT_DB_COMPUTE_VALUES);
$this->FireEvent(EVENT_DB_COMPUTE_VALUES, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
}
/**

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();
@@ -524,9 +524,7 @@ EOF
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
{
if (!array_key_exists('dashboard_div_id', $aExtraParams)) {
$aExtraParams['dashboard_div_id'] = utils::Sanitize($this->GetId(), '', 'element_identifier');
}
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
/** @var \DashboardLayoutMultiCol $oLayout */
$oLayout = new $this->sLayoutClass();
@@ -1052,7 +1050,7 @@ EOF
$sSelectorHtml .= '</div>';
$sFile = addslashes($this->GetDefinitionFile());
$sReloadURL = $this->GetReloadURL();
$sReloadURL = json_encode($this->GetReloadURL());
$bFromDashboardPage = isset($aAjaxParams['from_dashboard_page']) ? isset($aAjaxParams['from_dashboard_page']) : false;
if ($bFromDashboardPage) {
@@ -1141,7 +1139,6 @@ JS
->AddCSSClass('ibo-action-button');
$oToolbar->AddSubBlock($oActionButton);
$aActions = array();
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
$sJSExtraParams = json_encode($aExtraParams);
@@ -1166,7 +1163,7 @@ JS
$oToolbar->AddSubBlock($oActionButton)
->AddSubBlock($oActionsMenu);
$sReloadURL = $this->GetReloadURL();
$sReloadURL = json_encode($this->GetReloadURL());
$oPage->add_script(
<<<EOF
function EditDashboard(sId, sDashboardFile, aExtraParams)
@@ -1266,15 +1263,14 @@ EOF
$sOkButtonLabel = Dict::S('UI:Button:Save');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$sId = utils::HtmlEntities($this->sId);
$sLayoutClass = utils::HtmlEntities($this->sLayoutClass);
$sId = json_encode($this->sId);
$sLayoutClass = json_encode($this->sLayoutClass);
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sTitle = utils::HtmlEntities($this->sTitle);
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
$sFileForJS = json_encode($this->GetDefinitionFile());
$sTitle = json_encode($this->sTitle);
$sFile = json_encode($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sReloadURL = $this->GetReloadURL();
$sReloadURL = json_encode($this->GetReloadURL());
$sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage'));
$sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage'));
@@ -1328,15 +1324,15 @@ $('#dashboard_editor').dialog({
});
$('#dashboard_editor .ui-layout-center').runtimedashboard({
dashboard_id: '$sId',
layout_class: '$sLayoutClass',
title: '$sTitle',
dashboard_id: $sId,
layout_class: $sLayoutClass,
title: $sTitle,
auto_reload: $sAutoReload,
auto_reload_sec: $sAutoReloadSec,
submit_to: '$sUrl',
submit_parameters: {operation: 'save_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
submit_parameters: {operation: 'save_dashboard', file: $sFile, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl',
render_parameters: {operation: 'render_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_parameters: {operation: 'render_dashboard', file: $sFile, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
new_dashlet_parameters: {operation: 'new_dashlet'}
});

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) {
@@ -2138,7 +2145,7 @@ class DashletHeaderDynamic extends Dashlet
$oSet = new DBObjectSet($oFilter);
$iCount = $oSet->Count();
$oAppContext = new ApplicationContext();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search'.$oAppContext->GetForLink(true).'&filter='.rawurlencode($oFilter->serialize());
$oSubTitle->AddHtml('<a class="summary" href="'.$sHyperlink.'">'.Dict::Format(str_replace('_', ':', $sSubtitle), $iCount).'</a>');
return $oPanel;
@@ -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>
@@ -238,6 +235,10 @@ The object can be modified.]]></description>
<description>Creation flag</description>
<type>boolean</type>
</event_datum>
<event_datum id="stimulus_applied">
<description>Life cycle stimulus applied (null if not within a transition)</description>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
@@ -263,6 +264,10 @@ Call $this->AddCheckWarning($sWarningMessage) to display a warning.
<description>Creation flag</description>
<type>boolean</type>
</event_datum>
<event_datum id="stimulus_applied">
<description>Life cycle stimulus applied (null if not within a transition)</description>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
@@ -290,6 +295,10 @@ The modifications can be propagated to other objects.]]></description>
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
<type>array</type>
</event_datum>
<event_datum id="stimulus_applied">
<description>Life cycle stimulus applied (null if not within a transition)</description>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
@@ -420,6 +429,14 @@ The only action allowed is to deny transitions with $this->DenyTransition($sTran
<description>The object inserted</description>
<type>DBObject</type>
</event_datum>
<event_datum id="is_new">
<description>Creation flag</description>
<type>boolean</type>
</event_datum>
<event_datum id="stimulus_applied">
<description>Life cycle stimulus applied (null if not within a transition)</description>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>

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',
@@ -1124,7 +1126,7 @@ JS
$oSingleGroupByValueFilter->SetShowObsoleteData($this->m_bShowObsoleteData);
}
$sHyperlink = utils::GetAbsoluteUrlAppRoot()
.'pages/UI.php?operation=search&'.$oAppContext->GetForLink()
.'pages/UI.php?operation=search'.$oAppContext->GetForLink(true)
.'&filter='.rawurlencode($oSingleGroupByValueFilter->serialize());
$aCounts[$sStateValue] = ['link' => $sHyperlink, 'label' => $aCounts[$sStateValue]];
}
@@ -1232,7 +1234,7 @@ JS
$iCount = $this->m_oSet->Count();
$sClassLabel = MetaModel::GetName($sClass);
$sClassIconUrl = MetaModel::GetClassIcon($sClass, false);
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search'.$oAppContext->GetForLink(true).'&filter='.rawurlencode($this->m_oFilter->serialize());
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
$aRefreshParams = [
@@ -1241,7 +1243,7 @@ JS
];
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
$sCreateActionUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class='.$sClass.'&'.$oAppContext->GetForLink();
$sCreateActionUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class='.$sClass.$oAppContext->GetForLink(true);
$sCreateActionLabel = Dict::Format('UI:Button:Create');
$oBlock = DashletFactory::MakeForDashletBadge($sClassIconUrl, $sHyperlink, $iCount, $sClassLabel, $sCreateActionUrl,
$sCreateActionLabel, $aRefreshParams);
@@ -1289,7 +1291,7 @@ JS
$aData = array();
$oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink();
$sParams = $oAppContext->GetForLink(true);
foreach ($aGroupBy as $iRow => $iCount) {
// Build the search for this subset
$oSubsetSearch = $this->m_oFilter->DeepClone();
@@ -1304,7 +1306,7 @@ JS
$aData[] = array(
'group' => $aLabels[$iRow],
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=$sFilter\">$iCount</a>"
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1$sParams&filter=$sFilter\">$iCount</a>"
); // TO DO: add the context information
}
$aAttribs = array(
@@ -1636,7 +1638,7 @@ JS
$sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '&params[group_by_expr]='.$aExtraParams['group_by_expr'] : '';
$sFilter = $this->m_oFilter->serialize(false, $aQueryParams);
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink();
$sContextParam = $oContext->GetForLink(true);
$sAggregationFunction = isset($aExtraParams['aggregation_function']) ? $aExtraParams['aggregation_function'] : '';
$sAggregationAttr = isset($aExtraParams['aggregation_attribute']) ? $aExtraParams['aggregation_attribute'] : '';
$sLimit = isset($aExtraParams['limit']) ? $aExtraParams['limit'] : '';
@@ -1644,7 +1646,7 @@ JS
$sOrderDirection = isset($aExtraParams['order_direction']) ? $aExtraParams['order_direction'] : '';
if (isset($aExtraParams['group_by_label'])) {
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sChartId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sChartId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam;
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sChartId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sChartId{$iChartCounter}&filter=".rawurlencode($sFilter).$sContextParam;
} else {
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[chart_type]=$sChartType&params[currentId]=$sChartId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sChartId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam;
}
@@ -1681,11 +1683,14 @@ JS
$oBlock = null;
$sJSURLs = '';
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink(true);
if (isset($aExtraParams['group_by'])) {
$this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql);
$aRes = CMDBSource::QueryToArray($sSql);
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink();
$iTotalCount = 0;
$aURLs = array();
@@ -1705,14 +1710,14 @@ JS
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($sValue));
$oSubsetSearch->AddConditionExpression($oCondition);
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".rawurlencode($oSubsetSearch->serialize()).'&'.$sContextParam;
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".rawurlencode($oSubsetSearch->serialize()).$sContextParam;
}
$sJSURLs = json_encode($aURLs);
}
if (isset($aExtraParams['group_by_label'])) {
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$aExtraParams[group_by]&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$aExtraParams[currentId]&params[order_direction]=$aExtraParams[order_direction]&params[order_by]=$aExtraParams[order_by]&params[limit]=$aExtraParams[limit]&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId&filter=".rawurlencode($this->m_oFilter->ToOQL()).'&'.$sContextParam;
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$aExtraParams[group_by]&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$aExtraParams[currentId]&params[order_direction]=$aExtraParams[order_direction]&params[order_by]=$aExtraParams[order_by]&params[limit]=$aExtraParams[limit]&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId&filter=".rawurlencode($this->m_oFilter->ToOQL()).$sContextParam;
} else {
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$aExtraParams[group_by]&params[chart_type]=$sChartType&params[currentId]=$aExtraParams[currentId]&params[order_direction]=$aExtraParams[order_direction]&params[order_by]=$aExtraParams[order_by]&params[limit]=$aExtraParams[limit]&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId&filter=".rawurlencode($this->m_oFilter->ToOQL()).'&'.$sContextParam;
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$aExtraParams[group_by]&params[chart_type]=$sChartType&params[currentId]=$aExtraParams[currentId]&params[order_direction]=$aExtraParams[order_direction]&params[order_by]=$aExtraParams[order_by]&params[limit]=$aExtraParams[limit]&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId&filter=".rawurlencode($this->m_oFilter->ToOQL()).$sContextParam;
}
switch ($sChartType) {
@@ -1785,7 +1790,7 @@ JS
$oBlock->sCsvFile = strtolower($this->m_oFilter->GetClass()).'.csv';
$oBlock->sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($oBlock->sCsvFile);
$oBlock->sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize()).'&format=csv';
$oBlock->sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search'.$oAppContext->GetForLink(true).'&filter='.rawurlencode($this->m_oFilter->serialize()).'&format=csv';
// Pass the parameters via POST, since expression may be very long
$aParamsToPost = array(
'expression' => $this->m_oFilter->ToOQL(true),
@@ -1860,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;
@@ -1885,10 +1894,7 @@ class MenuBlock extends DisplayBlock
&& (!isset($aExtraParams['menu']) || $aExtraParams['menu'] === "1" || $aExtraParams['menu'] === true)
) {
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
if (utils::IsNotNullOrEmptyString($sContext)) {
$sContext = '&'.$sContext;
}
$sContext = $oAppContext->GetForLink(true);
$sFilter = $this->GetFilter()->serialize();
@@ -2024,8 +2030,8 @@ class MenuBlock extends DisplayBlock
$sSelectedClassName = MetaModel::GetName($sSelectedClass);
// Check rights on class
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY, $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE, $sSelectedClass);
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE);
// Refine filter on selected class so bullk actions occur on the right class
$oSelectedClassFilter = $this->GetFilter()->DeepClone();
@@ -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']);
@@ -2578,11 +2614,8 @@ class MenuBlock extends DisplayBlock
$sUrl = "{$sRootUrl}pages/{$sUIPage}?{$sUrlParams}";
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
if (utils::IsNotNullOrEmptyString($sContext)) {
$sUrl .= '&'.$sContext;
}
$sContext = $oAppContext->GetForLink(true);
return $sUrl;
return $sUrl . $sContext;
}
}

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

@@ -63,14 +63,14 @@ class CoreCannotSaveObjectException extends CoreException
public function getTextMessage()
{
$sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = utils::HtmlEntities($sTitle);
$sContent = $sTitle;
if (count($this->aIssues) == 1) {
$sIssue = reset($this->aIssues);
$sContent .= utils::HtmlEntities($sIssue);
$sContent .= $sIssue;
} else {
foreach ($this->aIssues as $sError) {
$sContent .= " ".utils::HtmlEntities($sError).", ";
$sContent .= " " . $sError . ", ";
}
}

View File

@@ -67,7 +67,7 @@ class CoreException extends Exception
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
{
return $this->getMessage();
return utils::EscapeHtml($this->getMessage());
}
/**

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
}
}
@@ -1159,11 +1132,11 @@ class OQLMenuNode extends MenuNode
{
$sUsageId = utils::GetSafeId($sUsageId);
$oSearch = DBObjectSearch::FromOQL($sOql);
$sClass= $oSearch->GetClass();
$sClass= $oSearch->GetClass();
$sIcon = MetaModel::GetClassIcon($sClass, false);
if ($bSearchPane) {
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
$oBlock = new DisplayBlock($oSearch, DisplayBlock::ENUM_STYLE_SEARCH, false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0);
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>");
}

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

@@ -250,7 +250,7 @@ class UIExtKeyWidget
foreach ($aAdditionalField as $sAdditionalField) {
array_push($aArguments, $oObj->Get($sAdditionalField));
}
$aOption['additional_field'] = utils::HtmlEntities(vsprintf($sFormatAdditionalField, $aArguments));
$aOption['additional_field'] = utils::HtmlEntities(utils::VSprintf($sFormatAdditionalField, $aArguments));
}
if (!empty($sObjectImageAttCode)) {
// Try to retrieve image for contact

View File

@@ -249,9 +249,9 @@ class appUserPreferences extends DBObject
(
"category" => "gui",
"key_type" => "autoincrement",
"name_attcode" => "userid",
"name_attcode" => "login",
"state_attcode" => "",
"reconc_keys" => array("userid"),
"reconc_keys" => array("userid","login"),
"db_table" => "priv_app_preferences",
"db_key_field" => "id",
"db_finalclass_field" => "",
@@ -260,8 +260,10 @@ class appUserPreferences extends DBObject
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributePropertySet("preferences", array("allowed_values"=>null, "sql"=>"preferences", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_SetZListItems('list', array('preferences',));
MetaModel::Init_SetZListItems('default_search', array('userid'));
MetaModel::Init_AddAttribute(new AttributeExternalField("org_id", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "org_id")));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login")));
MetaModel::Init_SetZListItems('list', array('org_id','preferences'));
MetaModel::Init_SetZListItems('default_search', array('userid','login','org_id'));
}
/**

View File

@@ -180,6 +180,7 @@ class utils
*/
private static $sAbsoluteUrlAppRootCache = null;
protected static function LoadParamFile($sParamFile)
{
if (!file_exists($sParamFile)) {
@@ -418,11 +419,26 @@ class utils
* @since 2.7.7, 3.0.2, 3.1.0 N°4899 - new 'url' filter
* @since 2.7.10 N°6606 use the utils::ENUM_SANITIZATION_* const
* @since 2.7.10 N°6606 new case for ENUM_SANITIZATION_FILTER_PHP_CLASS
* @since 3.2.1-1 N°8242 Allow value to be an array for every filter
*
* @link https://www.php.net/manual/en/filter.filters.sanitize.php PHP sanitization filters
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
if (is_array($value))
{
$retValue = array();
foreach ($value as $key => $val)
{
$retValue[$key] = self::Sanitize_Internal($val, $sSanitizationFilter); // recursively check arrays
if ($retValue[$key] === false)
{
return false;
}
}
return $retValue;
}
switch ($sSanitizationFilter)
{
case static::ENUM_SANITIZATION_FILTER_INTEGER:
@@ -453,52 +469,36 @@ class utils
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
if (is_array($value))
switch ($sSanitizationFilter)
{
$retValue = array();
foreach ($value as $key => $val)
{
$retValue[$key] = self::Sanitize_Internal($val, $sSanitizationFilter); // recursively check arrays
if ($retValue[$key] === false)
{
$retValue = false;
break;
}
}
}
else
{
switch ($sSanitizationFilter)
{
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
// Same as parameter type but keep the dot character
// transaction_id, the dot is mostly for Windows servers when using file storage as the tokens are named *.tmp
// - See N°1835
// - Note: It must be included at the regexp beginning otherwise you'll get an invalid character error
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
// Same as parameter type but keep the dot character
// transaction_id, the dot is mostly for Windows servers when using file storage as the tokens are named *.tmp
// - See N°1835
// - Note: It must be included at the regexp beginning otherwise you'll get an invalid character error
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case static::ENUM_SANITIZATION_FILTER_ROUTE:
case static::ENUM_SANITIZATION_FILTER_OPERATION:
// - Routes should be of the "controller_namespace_code.controller_method_name" form
// - Operations should be allowed to be namespaced as well even though then don't have dedicated controller yet
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[\.A-Za-z0-9_-]*$/')));
break;
case static::ENUM_SANITIZATION_FILTER_ROUTE:
case static::ENUM_SANITIZATION_FILTER_OPERATION:
// - Routes should be of the "controller_namespace_code.controller_method_name" form
// - Operations should be allowed to be namespaced as well even though then don't have dedicated controller yet
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[\.A-Za-z0-9_-]*$/')));
break;
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
// Characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
// Characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
break;
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
break;
}
}
break;
@@ -521,8 +521,8 @@ class utils
// For URL
case static::ENUM_SANITIZATION_FILTER_URL:
// N°6350 - returns only valid URLs
$retValue = filter_var($value, FILTER_VALIDATE_URL);
$retValue = filter_var($value, FILTER_SANITIZE_URL);
$retValue = filter_var($retValue, FILTER_VALIDATE_URL);
break;
default:
@@ -1451,9 +1451,12 @@ class utils
* @return string A path to a folder into which any module can store cache data
* The corresponding folder is created or cleaned upon code compilation
*/
public static function GetCachePath()
public static function GetCachePath(string $sEnvironment = null): string
{
return static::GetDataPath().'cache-'.MetaModel::GetEnvironment().'/';
if (is_null($sEnvironment)) {
$sEnvironment = MetaModel::GetEnvironment();
}
return static::GetDataPath()."cache-$sEnvironment/";
}
/**
@@ -1513,12 +1516,12 @@ class utils
case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT:
/** @var \DBObjectSet $param */
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$sContext = $oAppContext->GetForLink(true);
$sDataTableId = is_null($sDataTableId) ? '' : $sDataTableId;
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage($param->GetFilter()->GetClass());
$sOQL = addslashes($param->GetFilter()->ToOQL(true));
$sFilter = urlencode($param->GetFilter()->serialize());
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".$sFilter."&{$sContext}";
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".$sFilter.$sContext;
$oContainerBlock->AddJsFileRelPath('js/tabularfieldsselector.js');
$oContainerBlock->AddJsFileRelPath('js/jquery.dragtable.js');
$oContainerBlock->AddCssFileRelPath('css/dragtable.css');
@@ -1552,6 +1555,10 @@ class utils
}
$aResult[] = new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL', '$sContext')");
$aResult[] = new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')");
if (ApplicationMenu::IsMenuIdEnabled('RunQueriesMenu')) {
$oMenuItemPlay = new JSPopupMenuItem('UI:Menu:OpenOQL', Dict::S('UI:Menu:OpenOQL'), "OpenOql('$sOQL')");
$aResult[] = $oMenuItemPlay;
}
break;
@@ -1563,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(),
@@ -1688,8 +1692,8 @@ class utils
$oAppContext = new ApplicationContext();
$sUrl = $sAppRootUrl
.'pages/UI.php?operation=search&'
.$oAppContext->GetForLink()
.'pages/UI.php?operation=search'
.$oAppContext->GetForLink(true)
.'&filter='.rawurlencode($oDataTableSearchFilter->serialize());
$sUrl .= '&aParams='.rawurlencode($sParams); // Not working... yet, cause not handled by UI.php
@@ -2072,6 +2076,127 @@ SQL;
);
}
/**
* Format a string using vsprintf with safety checks to avoid ValueError
*
* This method fills missing arguments with their original format specifiers,
* then calls vsprintf with the complete array.
*
* @param string $sFormat The format string
* @param array $aArgs The arguments to format
* @param bool $bLogErrors Whether to log errors (defaults to true)
*
* @return string The formatted string
* @since 3.2.2
*/
public static function VSprintf(string $sFormat, array $aArgs, bool $bLogErrors = true): string
{
// Extract all format specifiers
$sPattern = '/%(?:(?:[1-9][0-9]*)\$)?[-+\'0# ]*(?:[0-9]*|\*)?(?:\.(?:[0-9]*|\*))?(?:[hlL])?[diouxXeEfFgGcrs%]/';
preg_match_all($sPattern, $sFormat, $aMatches, PREG_OFFSET_CAPTURE);
// Process matches, keeping track of their positions and excluding escaped percent signs (%%)
$aSpecifierMatches = [];
foreach ($aMatches[0] as $sMatch) {
if ($sMatch[0] !== '%%') {
$aSpecifierMatches[] = $sMatch;
}
}
// Check for positional specifiers and build position map
$bHasPositional = false;
$iMaxPosition = 0;
$aPositions = [];
$aUniquePositions = [];
foreach ($aSpecifierMatches as $index => $match) {
$sSpec = $match[0];
if (preg_match('/^%([1-9][0-9]*)\$/', $sSpec, $posMatch)) {
$bHasPositional = true;
$iPosition = (int)$posMatch[1] - 1; // Convert to 0-based
$aPositions[$index] = $iPosition;
$aUniquePositions[$iPosition] = true;
$iMaxPosition = max($iMaxPosition, $iPosition + 1);
} else {
$aPositions[$index] = $index;
$aUniquePositions[$index] = true;
$iMaxPosition = max($iMaxPosition, $index + 1);
}
}
// Count unique positions, this tells us how many arguments we actually need
$iExpectedCount = count($aUniquePositions);
$iActualCount = count($aArgs);
// If we have enough arguments, just use vsprintf
if ($iActualCount >= $iExpectedCount) {
return vsprintf($sFormat, $aArgs);
}
// else log the error if needed
if ($bLogErrors) {
IssueLog::Warning("Format string requires $iExpectedCount arguments, but only $iActualCount provided. Format: '$sFormat'" );
}
// Create a replacement map
if ($bHasPositional) {
// For positional, we need to handle the exact positions
$aReplacements = array_fill(0, $iMaxPosition, null);
// Fill in the real arguments first
foreach ($aArgs as $index => $sValue) {
if ($index < $iMaxPosition) {
$aReplacements[$index] = $sValue;
}
}
// For null values in the replacement map, use the original specifier
foreach ($aSpecifierMatches as $index => $sMatch) {
$iPosition = $aPositions[$index];
if ($aReplacements[$iPosition] === null) {
// Use the original format specifier when we don't have an argument
$aReplacements[$iPosition] = $sMatch[0];
}
}
// Remove any remaining nulls (for positions that weren't referenced)
$aReplacements = array_filter($aReplacements, static function($val) { return $val !== null; });
} else {
// For non-positional, we need to map each position
$aReplacements = [];
$iUsed = 0;
// Create a map of what values to use for each position
$aPositionValues = [];
for ($i = 0; $i < $iMaxPosition; $i++) {
if (isset($aUniquePositions[$i])) {
if ($iUsed < $iActualCount) {
// We have an actual argument for this position
$aPositionValues[$i] = $aArgs[$iUsed++];
} else {
// Mark this position to use the original specifier
$aPositionValues[$i] = null;
}
}
}
// Build the replacements array preserving the original order
foreach ($aSpecifierMatches as $index => $sMatch) {
$iPosition = $aPositions[$index];
if (isset($aPositionValues[$iPosition])) {
$aReplacements[] = $aPositionValues[$iPosition];
} else {
// Use the original format specifier when we don't have an argument
$aReplacements[] = $sMatch[0];
// Mark this position as used, so if it appears again, it gets the same replacement
$aPositionValues[$iPosition] = $sMatch[0];
}
}
}
// Process the format string with our filled-in arguments
return vsprintf($sFormat, $aReplacements);
}
/**
* Convert a string containing some (valid) HTML markup to plain text
*
@@ -2187,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: {########-####-####-####-############}
*
@@ -2390,53 +2424,75 @@ SQL;
return $bRet;
}
/**
* @param $sPath
*
* @return false|\ormDocument
* @throws \Exception
*
* @deprecated 3.2.1 use utils::GetDocumentFromSelfURL instead
*/
public static function IsSelfURL($sPath)
{
return self::GetDocumentFromSelfURL($sPath);
}
/**
* Check if the given URL is a link to download a document/image on the CURRENT iTop
* In such a case we can read the content of the file directly in the database (if the users rights allow) and return the ormDocument
*
* @Since 3.2.1 a local URL is transformed into a local file to read
*
* @param string $sPath
* @return false|ormDocument
* @throws Exception
*/
public static function IsSelfURL($sPath)
public static function GetDocumentFromSelfURL(string $sPath)
{
$result = false;
$sPageUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.document.php';
if (substr($sPath, 0, strlen($sPageUrl)) == $sPageUrl)
{
if (utils::StartsWith($sPath, $sPageUrl)) {
// If the URL is an URL pointing to this instance of iTop, then
// extract the "query" part of the URL and analyze it
$sQuery = parse_url($sPath, PHP_URL_QUERY);
if ($sQuery !== null)
{
if ($sQuery !== null) {
$aParams = array();
foreach(explode('&', $sQuery) as $sChunk)
{
foreach (explode('&', $sQuery) as $sChunk) {
$aParts = explode('=', $sChunk ?? '');
if (count($aParts) != 2) continue;
if (count($aParts) != 2) {
continue;
}
$aParams[$aParts[0]] = urldecode($aParts[1]);
}
$result = array_key_exists('operation', $aParams) && array_key_exists('class', $aParams) && array_key_exists('id', $aParams) && array_key_exists('field', $aParams) && ($aParams['operation'] == 'download_document');
if ($result)
{
if ($result) {
// This is a 'download_document' operation, let's retrieve the document directly from the database
$sClass = $aParams['class'];
$iKey = $aParams['id'];
$sAttCode = $aParams['field'];
$oObj = MetaModel::GetObject($sClass, $iKey, false /* must exist */); // Users rights apply here !!
if ($oObj)
{
if ($oObj) {
/**
* @var ormDocument $result
*/
$result = clone $oObj->Get($sAttCode);
return $result;
return clone $oObj->Get($sAttCode);
}
}
}
throw new Exception('Invalid URL. This iTop URL is not pointing to a valid Document/Image.');
}
return $result;
if (utils::StartsWith($sPath, utils::GetAbsoluteUrlAppRoot())) {
$sFilePath = utils::LocalPath(APPROOT.substr($sPath, strlen(utils::GetAbsoluteUrlAppRoot())));
if (false === $sFilePath) {
return false;
}
$sFilePath = APPROOT.$sFilePath;
return ormDocument::FromFile($sFilePath);
}
return false;
}
/**
@@ -2444,68 +2500,28 @@ SQL;
* - an URL pointing to a blob (image/document) on the current iTop server
* - an http(s) URL
* - the local file system (but only if you are an administrator)
* @param string $sPath
*
* @param string|null $sPath
* @return ormDocument|null
* @throws Exception
*/
public static function FileGetContentsAndMIMEType($sPath)
{
$oUploadedDoc = null;
$aKnownExtensions = array(
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'dot' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'vsd' => 'application/x-visio',
'vdx' => 'application/visio.drawing',
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'zip' => 'application/zip',
'txt' => 'text/plain',
'htm' => 'text/html',
'html' => 'text/html',
'exe' => 'application/octet-stream',
);
$sData = null;
$sMimeType = 'text/plain'; // Default MIME Type: treat the file as a bunch a characters...
$sFileName = 'uploaded-file'; // Default name for downloaded-files
$sExtension = '.txt'; // Default file extension in case we don't know the MIME Type
if(empty($sPath))
{
if (utils::IsNullOrEmptyString($sPath)) {
// Empty path (NULL or '') means that there is no input, making an empty document.
$oUploadedDoc = new ormDocument('', '', '');
return new ormDocument('', '', '');
}
elseif (static::IsURL($sPath))
{
if ($oUploadedDoc = static::IsSelfURL($sPath))
{
// Nothing more to do, we've got it !!
if (static::IsURL($sPath)) {
$oUploadedDoc = static::GetDocumentFromSelfURL($sPath);
if ($oUploadedDoc) {
return $oUploadedDoc;
}
else
{
// Remote file, let's use the HTTP headers to find the MIME Type
$sData = @file_get_contents($sPath);
if ($sData === false)
{
IssueLog::Error(<<<TXT
// Remote file, let's use the HTTP headers to find the MIME Type
$sData = @file_get_contents($sPath);
if ($sData === false) {
IssueLog::Error(<<<TXT
Failed to load the file from URL. This can happen for multiple reasons:
- Invalid URL
- URL using HTTPS with an untrusted certificate on the remote server
@@ -2514,54 +2530,40 @@ TXT
, LogChannels::CORE, [
'URL' => $sPath,
]);
throw new Exception("Failed to load the file from the URL '$sPath'.");
}
else
{
if (isset($http_response_header))
{
$aHeaders = static::ParseHeaders($http_response_header);
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
// Compute the file extension from the MIME Type
foreach ($aKnownExtensions as $sExtValue => $sMime) {
if ($sMime === $sMimeType) {
$sExtension = '.'.$sExtValue;
break;
}
}
}
$sPathName = pathinfo($sPath, PATHINFO_FILENAME);
if (utils::IsNotNullOrEmptyString($sPathName)) {
$sFileName = $sPathName;
}
$sFileName .= $sExtension;
}
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
throw new Exception("Failed to load the file from the URL '$sPath'.");
}
}
else if (UserRights::IsAdministrator())
{
// Only administrators are allowed to read local files
$sData = @file_get_contents($sPath);
if ($sData === false)
{
throw new Exception("Failed to load the file '$sPath'. The file does not exist or the current process is not allowed to access it.");
}
$sExtension = strtolower(pathinfo($sPath, PATHINFO_EXTENSION));
$sFileName = basename($sPath);
if (array_key_exists($sExtension, $aKnownExtensions))
{
$sMimeType = $aKnownExtensions[$sExtension];
$sMimeType = 'text/plain'; // Default MIME Type: treat the file as a bunch a characters...
$sFileName = 'uploaded-file'; // Default name for downloaded-files
$sExtension = '.txt'; // Default file extension in case we don't know the MIME Type
if (isset($http_response_header)) {
$aHeaders = static::ParseHeaders($http_response_header);
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
// Compute the file extension from the MIME Type
foreach (ormDocument::GetKnownExtensions() as $sExtValue => $sMime) {
if ($sMime === $sMimeType) {
$sExtension = '.'.$sExtValue;
break;
}
}
}
else if (extension_loaded('fileinfo'))
{
$finfo = new finfo(FILEINFO_MIME);
$sMimeType = $finfo->file($sPath);
$sPathName = pathinfo($sPath, PATHINFO_FILENAME);
if (utils::IsNotNullOrEmptyString($sPathName)) {
$sFileName = $sPathName;
}
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
$sFileName .= $sExtension;
return new ormDocument($sData, $sMimeType, $sFileName);
}
return $oUploadedDoc;
// Local file
if (UserRights::IsAdministrator()) {
// Only administrators are allowed to read local files
return ormDocument::FromFile($sPath);
}
return null;
}
protected static function ParseHeaders($aHeaders)
@@ -2800,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
@@ -3132,30 +3119,13 @@ TXT
* @throws \Exception
* @since 3.0.0
*/
public static function GetMentionedObjectsFromText(string $sText, string $sFormat = self::ENUM_TEXT_FORMAT_HTML): array
public static function GetMentionedObjectsFromText(string $sText): array
{
// First transform text so it can be parsed
switch ($sFormat) {
case static::ENUM_TEXT_FORMAT_HTML:
$sText = static::HtmlToText($sText);
break;
default:
// Don't transform it
break;
}
// Then parse text to find objects
$aMentionedObjects = array();
$aMentionMatches = array();
// Note: As the sanitizer (or CKEditor autocomplete plugin? 🤔) removes data-* attributes from the hyperlink,
// - we can't use the following (simpler) regexp that only checks data attributes on hyperlinks, which would have worked for hyperlinks pointing to any GUIs: '/<a\s*([^>]*)data-object-class="([^"]*)"\s*data-object-id="([^"]*)">/i'
// - instead we use a regexp to match the following pattern '[Some object label](<APP_ROOT_URL>...&class=<OBJECT_CLASS>&id=<OBJECT_ID>...)' which only works for the backoffice
// If we change the sanitizer, we might want to switch to the other regexp as it's universal and easier to read
$sAppRootUrlForRegExp = addcslashes(utils::GetAbsoluteUrlAppRoot(), '/&');
preg_match_all("/\[([^\]]*)\]\({$sAppRootUrlForRegExp}[^\)]*\&class=([^\)\&]*)\&id=([\d]*)[^\)]*\)/i", $sText, $aMentionMatches);
$aMentionedObjects = [];
$aMentionMatches = [];
$sText = html_entity_decode($sText);
preg_match_all('/<a\s*([^>]*)data-object-class="([^"]*)"\s.*data-object-key="([^"]*)"/Ui', $sText, $aMentionMatches);
foreach ($aMentionMatches[0] as $iMatchIdx => $sCompleteMatch) {
$sMatchedClass = $aMentionMatches[2][$iMatchIdx];
$sMatchedId = $aMentionMatches[3][$iMatchIdx];

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.0');
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",

720
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->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"=>"", "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"=>null, "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 = null, $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"=>"", "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');

View File

@@ -33,7 +33,7 @@ class CMDBChange extends DBObject
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"User", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum(implode(',', [CMDBChangeOrigin::INTERACTIVE, CMDBChangeOrigin::CSV_INTERACTIVE, CMDBChangeOrigin::CSV_IMPORT, CMDBChangeOrigin::WEBSERVICE_SOAP, CMDBChangeOrigin::WEBSERVICE_REST, CMDBChangeOrigin::SYNCHRO_DATA_SOURCE, CMDBChangeOrigin::EMAIL_PROCESSING, CMDBChangeOrigin::CUSTOM_EXTENSION])), "sql"=>"origin", "default_value"=>CMDBChangeOrigin::INTERACTIVE, "is_null_allowed"=>true, "depends_on"=>array())));

File diff suppressed because it is too large Load Diff

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