Compare commits

...

653 Commits

Author SHA1 Message Date
denis.flaven@combodo.com
9400b697eb N°5620 Also hide the favorite orgs in preferences 2022-12-19 15:55:52 +01:00
odain
e1807f598f N°5620-fix ci 2022-11-22 13:46:33 +01:00
Molkobain
02e63fff64 Add PHPDoc 2022-11-22 13:28:02 +01:00
odain
c8fade6013 5620-simplify test to avoid regression in other test sections linked to MetaModel use 2022-11-22 07:42:03 +01:00
odain
ad052dd861 N°5620-renaming IsOrgMenuFilterAllowed<-IsSiloSelectionEnabled and made public 2022-11-22 07:31:12 +01:00
odain
a5ea868609 fix test 2022-11-21 10:41:03 +01:00
odain
0b03b3ef4d N°5620 - conf param renaming + backward compatibility test 2022-11-21 09:56:56 +01:00
odain
174cace20a N°5620 - remove debug log 2022-11-15 09:55:12 +01:00
odain
e3f5dbfc80 N°5620 - Hide the organization filter with a conf parameter 2022-11-15 09:49:36 +01:00
odain
c6e4466c53 ci: fix ItopDataTestCase CreateUser contactid unset 2022-10-26 14:03:11 +02:00
odain
6638eb4adc ci: adapt impersonate test to any friendlyname output 2022-10-26 09:50:56 +02:00
odain
eb40968e34 ci: add CreateContactlessUser method in test framework 2022-10-25 09:26:57 +02:00
odain-cbd
766c9f0e7e N°5305 - CSV import ergonomy PR (#332)
Reworked UI feedbacks on following attributes:
- enum
- date
- external key
2022-09-20 16:00:33 +02:00
Eric Espie
2a064fd97d N°5394 - use session for the FSM 2022-09-12 10:56:25 +02:00
Eric Espie
ca3c0cb163 N°5510 - Exception "$amount: Expected 5% to be within 0% and 1%" when compiling a theme 2022-09-09 09:20:52 +02:00
Eric Espie
44c0e236b0 N°5509 - User Provisioning Issue 2022-09-08 09:58:29 +02:00
Eric Espie
6190429f51 N°5394 - Rework session start 2022-09-01 16:08:16 +02:00
Molkobain
6e3ff0e429 Update iTop version to 3.0.2 2022-08-29 09:40:47 +02:00
Stephen Abello
14facb4d6c N°5462 Add a setup check to verify if directory-level configuration files (.htaccess and web.config) are used by the server 2022-08-24 16:44:11 +02:00
odain
f923ac879f ci: tag some tests with addition annotations to ease exclusion/inclusion mechanism 2022-08-24 12:07:04 +02:00
odain
0b46ab9e48 ci: add phpunit defaultProfiles annotation + tag some tests with addition annotations to ease exclusion/inclusion mechanism 2022-08-24 11:02:11 +02:00
Molkobain
bdf11e32a7 N°5318 - Security hardening 2022-08-24 10:47:40 +02:00
Molkobain
1441b8a1d2 N°5318 - Fix bad merge of the coreexception.class.inc.php file 2022-08-23 10:01:51 +02:00
Stephen Abello
b1bc2cec1b N°5138 Fix tooltips flickering in bulk modify when it contains hyperlinks 2022-08-22 16:59:24 +02:00
Molkobain
e280f99996 N°5437 - PHP 8.0: Fix deprecated PHP notice in TWIG lib 2022-08-22 16:43:38 +02:00
Molkobain
c5d5379c49 N°5408 - Mentions: Fix empty results for class with no image attribute 2022-08-16 14:21:28 +02:00
Molkobain
83b2096d2d N°5407 - Mentions: Fix RegExp wildcard not usable as marker 2022-08-16 13:43:51 +02:00
Molkobain
c8cb64db24 N°4739 - Remove precompiled themes unit test as they are no longer used since the introduction of DM classes style SCSS 2022-08-16 11:48:38 +02:00
Molkobain
f70073cf3e N°3979 - Fix typo 2022-08-16 09:31:56 +02:00
Molkobain
fc9ac1b441 N°4739 - Add semantic on state for user classes
* Add new section in the backoffice SCSS structure for PHP classes of the DM that are in the core (not a module) and can't be styled via XML.
2022-08-14 21:35:56 +02:00
Anne-Catherine
47becb3be8 N°5024 - Missing result in search widget for external key (#327)
* N°5024 - Missing result in search widget for external key
2022-08-12 18:23:29 +02:00
acognet
7320005c08 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/cmdbabstract.class.inc.php
#	core/coreexception.class.inc.php
#	core/dbobject.class.php
2022-08-12 18:13:42 +02:00
Anne-Catherine
d7e5705520 N°5318 - Fix DBObject::CheckValue() messages being HTML encoded when not necessary (#326)
* Rollback N°4898 - Security fix

* N°5318 - security fix
2022-08-12 17:50:14 +02:00
Anne-Catherine
bacdd63dd4 N°3979 - Handle initial values on dependent fields (#325)
N°3979 - Handle initial values on dependent fields
2022-08-12 17:48:53 +02:00
Molkobain
b91ab8940e N°4918 - Fix "other tabs" menu displayed behind some elements 2022-08-12 14:59:06 +02:00
Stephen Abello
9bf65da420 Merge branch 'support/2.7' into support/3.0 2022-08-12 11:35:47 +02:00
Stephen Abello
35a8b501c9 N°5393 Security hardening 2022-08-12 11:33:55 +02:00
Molkobain
8e7aef17c6 N°4903 - Fix dynamic "app_root_url" conf. param. not used properly for the app. icon 2022-08-12 11:11:55 +02:00
Molkobain
24f2416427 Navigation menu: Fix duplicated conf. property code usage 2022-08-12 11:11:55 +02:00
Eric Espie
cc6cf79835 N°5389 - Email Notification templates with AttributeLinkedSetIndirect failed 2022-08-12 10:37:43 +02:00
Stephen Abello
f10e9c2d64 N°5393 Security hardening 2022-08-12 09:54:35 +02:00
Stephen Abello
bd97d9c7ca Replace OAuth object subtitle icon with a solid icon for more harmony 2022-08-12 09:53:24 +02:00
Stephen Abello
94b9fda354 Remove OAuth object subtitle tooltip as it's always empty 2022-08-12 09:53:24 +02:00
Eric Espie
7a7498537f N°5135 - Impersonate: history of changes versus log entries - Fix typo 2022-08-11 17:17:29 +02:00
acognet
b6e22e47ca N°4910 - Adding a regexp on an existing field with value not complient, block the object modification 2022-08-11 16:43:36 +02:00
jbostoen
d17e399a5f 🌐 N°5397 - Updated Dutch translations (#262)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@me.com>
2022-08-11 14:07:51 +02:00
Molkobain
48742f334f N°5198 - Add comment to clarify usage of array_replace 2022-08-11 11:38:53 +02:00
odain-cbd
ec01ab73aa N°5135 - Impersonate: history of changes versus log entries (#290)
* N°5135 - Impersonate: history of changes versus log entries

* N°5135 - enrich impersonated changelog userinfo with its previous value when overrided by an extension (ie approvalbase)

* N°5135 - indicate impersonation inside changelogs in both caselogs and activity

* N°5135 - Impersonate: history of changes versus log entries add specific username for caselogs

Co-authored-by: Eric Espie <eric.espie@combodo.com>
2022-08-11 11:12:07 +02:00
acognet
931bafe380 N°5198 - Inconsistent behavior in selection of combobox with more than 150 results 2022-08-10 17:49:40 +02:00
Stephen Abello
5164976b76 N°5050 * Revert changes made in 3b83d3f2 in english dictionary 🤦
* Move it to Spanish dictionary
2022-08-10 15:38:42 +02:00
Eric Espie
5854eefcce N°5395 - Errors from OAuth servers for email are not well handled (use 3.0 constants) 2022-08-10 15:27:25 +02:00
Molkobain
5845972941 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-08-10 15:14:27 +02:00
Eric Espie
7f7538ed58 N°5395 - Errors from OAuth servers for email are not well handled 2022-08-10 14:59:32 +02:00
Eric Espie
8fa616f440 N°5395 - Errors from OAuth servers for email are not well handled 2022-08-10 14:57:26 +02:00
Molkobain
62aaaabd7e Update visual test comment 2022-08-10 14:53:42 +02:00
Stephen Abello
b3750e46cf Stylize datatables before widget is loaded in order to avoid flickering 2022-08-10 14:07:39 +02:00
Stephen Abello
b43b2e9741 Remove padding between Dashlet/Preferences datatables and their parent panel 2022-08-10 14:07:38 +02:00
Stephen Abello
77e9eaba00 Add highlighted rows to RenderAllUiBlocks 2022-08-10 14:07:38 +02:00
Stephen Abello
3d593faad8 Fix datatables semantic colors not using sematinc variables 2022-08-10 14:07:38 +02:00
Stephen Abello
118622493f N°5050 Revert entry deleted in 3b83d3f2 2022-08-10 14:07:38 +02:00
Molkobain
e44523e623 N°5343 - Avoid crash when 1 level menu group is not actually a MenuGroup (#312) 2022-08-09 17:45:31 +02:00
Eric Espié
69749a5cbe N°5375 - XML custo on Semantic field with hierarchy, breaks at compilation (#323) 2022-08-09 17:37:01 +02:00
Molkobain
43b49034df Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-08-09 17:33:18 +02:00
Molkobain
5829e698da Fix typo 2022-08-09 17:19:21 +02:00
Eric Espié
d2041c0334 N°5009 - Invalid XML for class Attachment (icon node) (#324)
N°5009 - Invalid XML for class Attachment (icon node)
2022-08-09 16:55:50 +02:00
Stephen Abello
f9487e55d5 N°5088 Fix audit displaying only 10 rules per category 2022-08-09 15:34:46 +02:00
Stephen Abello
b8ecb68ad7 N°5192 Make highlighted row more visible by adding a border to the first cell 2022-08-09 14:27:09 +02:00
Stephen Abello
3b83d3f209 N°5050 Update Spanish translations (thanks to Miguel Turrubiates!) 2022-08-09 14:27:09 +02:00
Eric Espie
029e6114ad N°4715 - Remove deprecated legacy SQL build 2022-08-09 10:41:46 +02:00
Eric Espié
de5fee8876 N°4792 - memory limit is reached when an AttributeExternalKey is pointing to a class with an AttributeBlob (#322)
N°4792 - memory limit is reached when an AttributeExternalKey is poin…
2022-08-09 09:17:15 +02:00
Molkobain
80fa4ec71f Code format 2022-08-08 16:30:46 +02:00
Stephen Abello
b1432ef1c6 N°4927 Fix date picker widget initialized visible 2022-08-08 15:07:02 +02:00
Stephen Abello
0599341515 N°4975 Security hardening 2022-08-08 15:07:02 +02:00
Stephen Abello
8e840d4529 N°5138 N°4425 Fix not being able to click on hyperlinks in tooltips 2022-08-08 15:07:01 +02:00
Stephen Abello
b4880beb5b N°5192 Fix HILIGHT_CLASS_OK not displaying green rows since iTop 3.0 2022-08-08 15:07:01 +02:00
Molkobain
c6b88c4db0 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/dbobject.class.php
2022-08-08 11:57:12 +02:00
Molkobain
df347b90e5 N°5383 - Declare DBObject::EnumTransitions() as "overwritable hook" 2022-08-08 11:53:46 +02:00
Molkobain
47683f3bd4 N°5033 - Add model file to 'itop-bridge-virtualization-storage' module to avoid compilation crash when lnkVirtualDeviceToVolume class is removed 2022-08-08 08:58:34 +02:00
acognet
b704e0d131 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-08-04 16:38:47 +02:00
acognet
bb861aa262 N°3024 - Archiving Service Families (or any class with no child) with combodo-archive-manual 2022-08-04 16:26:21 +02:00
acognet
f9ac07830e Fix translation 2022-08-04 16:26:01 +02:00
Stephen Abello
1ab35c68c8 Fix typo in datetime input autocomplete attribute 2022-08-03 14:47:01 +02:00
Molkobain
f1acc956f4 N°4517 - PHP 8.1: Fix return type for class implementing IteratorAggregate 2022-08-03 10:33:24 +02:00
Molkobain
a2973f6f28 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	js/wizardhelper.js
2022-07-29 15:25:13 +02:00
Molkobain
614a586b4c N°3129 - PHP 8.0: Fix unit test for which the tested error message as changed 2022-07-29 11:08:32 +02:00
Pierre Goiffon
0f4c7ac90f N°5129 Prevent "fieldForm is null" JS error when updating dependant field
For example when changing Server.location, 3 JS errors are thrown in the console :/
2022-07-29 10:12:37 +02:00
Molkobain
77aa154388 Convert line endings to LF on misaligned text files 2022-07-28 10:02:18 +02:00
Molkobain
414e1542d0 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/authent-external/ja.dict.authent-external.php
#	datamodels/2.x/authent-local/da.dict.authent-local.php
#	datamodels/2.x/authent-local/ja.dict.authent-local.php
2022-07-28 10:00:32 +02:00
Molkobain
0687f9a0a9 Convert line endings to LF on misaligned text files 2022-07-28 09:58:04 +02:00
Molkobain
6e75ab2889 Add .gitattributes to enforce line endings
More info: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
2022-07-28 09:44:42 +02:00
Molkobain
a80cfb6b05 N°5302 - Code cleanup 2022-07-26 22:18:21 +02:00
Molkobain
6ee67a2a36 N°5108 - Fix variable name 2022-07-26 22:11:38 +02:00
Molkobain
a11bbd667a Fix typos 2022-07-26 20:09:37 +02:00
Pierre Goiffon
7268cf7311 👥 Add @nv35 to contributors list! 🙌
See #183
2022-07-26 17:21:19 +02:00
Molkobain
6cda9e001f Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-07-20 17:48:47 +02:00
Molkobain
b90d29d448 🔧 Add IntelliLang.xml file to provide PHP synthax highlighting in DM XML files 2022-07-20 17:48:01 +02:00
Molkobain
808092acdd N°5311 - Update deprecation comment to match PHP deprecations convention 2022-07-18 16:05:41 +02:00
Molkobain
b9c716a247 N°5102 - Convert line separators 2022-07-18 15:58:11 +02:00
Molkobain
bf7b2e1e7e Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-07-18 14:15:50 +02:00
Molkobain
1f78bf4119 N°5287 - Fix license in composer.json 2022-07-18 13:52:40 +02:00
Molkobain
28df2dad60 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	js/wizardhelper.js
2022-07-13 17:11:04 +02:00
Molkobain
5d25e77189 Code format 2022-07-13 17:03:01 +02:00
Molkobain
d9dabf25da PHPDoc 2022-07-13 17:03:01 +02:00
Molkobain
73af605892 Fix typo in dictionaries 2022-07-13 17:03:00 +02:00
Molkobain
a71d8a660f N°5311 - Deprecate old backoffice stylesheets 2022-07-12 11:20:48 +02:00
Eric Espie
03b56b2941 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 : wrong positioning of module_parameters for portal 2022-07-11 16:26:41 +02:00
Eric Espie
01ee91d003 N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
* migration to iTop 3.0
2022-07-11 15:20:47 +02:00
Benjamin Dalsass
f70f95c119 Update community licence 2.7.7 (script from git bash, not php execution) 2022-07-11 15:20:36 +02:00
Eric Espie
badc5ff3ec Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-07-11 15:20:29 +02:00
Eric Espie
8dbdcdcb25 autoloader updated 2022-07-11 14:18:44 +02:00
Eric Espie
13533a2fa9 ⬆️ libs upgrade 2022-07-11 14:18:20 +02:00
Eric Espie
e4343ded01 autoloader updated 2022-07-11 09:24:24 +02:00
Eric Espie
e105cc6d44 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.lock
#	core/log.class.inc.php
#	datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml
#	lib/composer/autoload_real.php
#	setup/licenses/community-licenses.xml
#	setup/setuputils.class.inc.php
2022-07-11 09:23:18 +02:00
Benjamin Dalsass
53c50cf6fc Update community licence 2.7.7 2022-07-11 08:24:20 +02:00
Vincent Dumas
f19d1472c5 N°5102 - OAuth - replace double quote char EN
Use a special double quote characters so it is correctly handled in HTML
2022-07-08 13:44:00 +02:00
Vincent Dumas
eef00502cd N°5102 - OAuth - remove unsupported quote FR 2022-07-08 13:38:37 +02:00
Molkobain
0b1caac195 N°4867 - Restore datamodel node to avoid minor version migration crash
Will be properly removed in 3.1.0
2022-07-08 13:22:27 +02:00
Vincent Dumas
e900a44d47 N°5102 - OAuth client - FR tooltips 2022-07-08 12:22:52 +02:00
Vincent Dumas
a3de9fa898 N°5102 - OAuth client - Add EN tooltips 2022-07-08 12:06:47 +02:00
Eric Espie
aa8de912fd Merge branch 'support/3.0.1' into support/3.0 2022-07-08 11:01:02 +02:00
Eric Espie
f8648e2929 N°5267 - Error on class view when datamodel encoding is not UTF-8 - add logs to ease finding the model load errors 2022-07-08 10:59:21 +02:00
bdalsass
33054d306d N°5302 - Replace deprecated php strlen usages (#308) 2022-07-08 10:27:52 +02:00
bdalsass
8b0154cc62 N°5168 - Access to unauthorized contact information on Portal (#305)
GlobalRequestMgmt issue
2022-07-08 09:51:20 +02:00
Eric Espie
1a225bf55b N°5102 - Allow to send emails using GSuite SMTP and OAuth - Access rights 2022-07-07 17:57:24 +02:00
Eric Espie
24d19cd8d6 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Add a flag to select OAuth client for SMTP usage 2022-07-07 16:34:19 +02:00
Eric Espie
c25a4a7346 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Access rights 2022-07-07 14:17:09 +02:00
Stephen Abello
65c6e99a3f Fix typo/useless comment 2022-07-07 09:16:11 +02:00
Stephen Abello
8e85058495 Fix SCSS comment type 2022-07-07 09:15:20 +02:00
Eric Espie
20fb7b241f N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 17:23:44 +02:00
Eric Espie
a0553e1195 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 17:10:59 +02:00
Eric Espie
f40141072a N°5102 - Allow to send emails using GSuite SMTP and OAuth - Fix errors on vendor name 2022-07-06 14:10:01 +02:00
Eric Espie
c759856a61 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 10:10:42 +02:00
Pierre Goiffon
237b181eec 💡 Fix \SetupUtils::GetTmpDir PHPDoc 2022-07-05 18:09:59 +02:00
Eric Espie
48957fd2f0 N°5102 - Allow to send emails using GSuite SMTP and OAuth - refactor scopes 2022-07-05 17:54:43 +02:00
Pierre Goiffon
8a99c37200 N°5287 Fix composer.json errors
See https://getcomposer.org/doc/03-cli.md#validate
2022-07-05 15:08:29 +02:00
Eric Espie
d388c3fd3d N°5102 - Allow to send emails using GSuite SMTP and OAuth - Limit error size 2022-07-04 16:48:56 +02:00
Stephen Abello
9fd2b7f4da N°5071 Fix objects popup shrinking when scrolling 2022-07-04 16:41:10 +02:00
Stephen Abello
b43e6d7af3 N°5071 Fix properties tab on objects popup hiding in "..." overflowing button 2022-07-04 16:39:02 +02:00
Eric Espie
1b8e48539d N°5102 - Allow to send emails using GSuite SMTP and OAuth - Add comment in configuration 2022-07-01 14:32:44 +02:00
Eric Espie
104beff158 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Fix log 2022-06-29 15:09:17 +02:00
Pierre Goiffon
4712569a36 📝 CONTRIBUTING : fix GitMoji link 2022-06-29 10:56:21 +02:00
Pierre Goiffon
779ac0e4d9 Dump autoloader 2022-06-28 15:19:08 +02:00
Pierre Goiffon
4a20a6e525 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.lock
#	lib/composer/autoload_files.php
#	lib/composer/autoload_real.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.json
#	lib/composer/installed.php
2022-06-28 15:16:41 +02:00
Pierre Goiffon
2392f4a902 🔒 Update guzzlehttp/guzzle 2022-06-28 15:13:04 +02:00
Benjamin Dalsass
cb1203fde9 Merge 2.7 into Support 3.0 : Update oauth composer 2022-06-28 15:09:19 +02:00
Pierre Goiffon
1135896b3d Composer dump autoloader 2022-06-28 12:05:47 +02:00
acognet
39cd933ebb N°5108 - Update embedded libs for PHP 8.0 (3.0 branch) 2022-06-28 12:03:01 +02:00
Pierre Goiffon
2fcc386e1e Fix compilation error on OAuthClient.status
XML file version was update but structure wasn't aligned with the new XML version (AttributeEnum structure)
2022-06-28 11:55:03 +02:00
acognet
682f20bbba N°5108 - Update embedded libs for PHP 8.0 (3.0 branch) 2022-06-28 11:24:47 +02:00
Pierre Goiffon
74f7775332 Restore images/icons/*
Were removed by the merge in f0b94dd0
2022-06-28 11:02:56 +02:00
Eric Espie
a0f28a9098 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-28 10:47:20 +02:00
acognet
93a69cbc49 N°5108 - Update embedded libs for PHP 8.0 (3.0 branch) 2022-06-27 23:38:58 +02:00
Benjamin Dalsass
15b9ea45a0 Merge 2.7 into Support 3.0 : Upgrade oauth module version to 3.0.1 2022-06-27 09:31:49 +02:00
Benjamin Dalsass
1b76e96720 Merge 2.7 into Support 3.0 : Update autoload 2022-06-27 08:18:49 +02:00
Benjamin Dalsass
f0b94dd0f7 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/config.class.inc.php
#	datamodels/2.x/installation.xml
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-adjust.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-administrative-tools.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-application-window.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-apps-tab.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-archive-folder.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-audit.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-automatic.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-bandage.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-book-error.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-calendar.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-cassette.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-change-approved.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-change-emergency.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-change-normal.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-change-routine.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-change.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-checkmark.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-cloud-file.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-conflict.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-contract.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-customer.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-database-custom.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-database.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-delete.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-department.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-desktop.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-discussion-forum.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-documents.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-electrical.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-electricity.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-electronics.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-enclosure-for-servers.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-export-csv.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-faq.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-farm.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-file.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-globe-cable.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-globe-fiber.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-globe-wire.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-hdd.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-hierarchy.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-hypervisor.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-import-csv.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-important-book.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-in-transit.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-laptop.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-licence.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-map-as-drive.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-map-marker.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-mobile.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-music-robot.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-nas.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-network.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-new-item.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-note.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-office-phone.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-old-vmware-logo.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-organization.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-person-female.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-phone.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-plug-socket.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-power-plant.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-print.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-process-improvement.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-puzzle.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-rack.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-server-custom.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-server-storage.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-server.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-service.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-services.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-smartphone-tablet.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-software-instance.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-software-license.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-software-other.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-software.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-solve.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-stack.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-switch-san.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-switch.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-tape-library.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-tasklist.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-team.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-telephone.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-time-limit.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-virtual-machine.svg
#	datamodels/2.x/itop-oauth-client/assets/img/icons8-web.svg
#	datamodels/2.x/itop-welcome-itil/datamodel.itop-welcome-itil.xml
#	dictionaries/cs.dictionary.itop.ui.php
#	dictionaries/da.dictionary.itop.ui.php
#	dictionaries/de.dictionary.itop.ui.php
#	dictionaries/en.dictionary.itop.ui.php
#	dictionaries/es_cr.dictionary.itop.ui.php
#	dictionaries/fr.dictionary.itop.ui.php
#	dictionaries/hu.dictionary.itop.ui.php
#	dictionaries/it.dictionary.itop.ui.php
#	dictionaries/ja.dictionary.itop.ui.php
#	dictionaries/nl.dictionary.itop.ui.php
#	dictionaries/pt_br.dictionary.itop.ui.php
#	dictionaries/ru.dictionary.itop.ui.php
#	dictionaries/sk.dictionary.itop.ui.php
#	dictionaries/tr.dictionary.itop.ui.php
#	dictionaries/zh_cn.dictionary.itop.ui.php
#	js/wizardhelper.js
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_real.php
#	lib/composer/autoload_static.php
#	templates/pages/backoffice/oauth/Wizard.html.twig
2022-06-27 08:11:28 +02:00
Eric Espie
6df622e8ed N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-23 14:05:17 +02:00
Eric Espie
54eb9d081b N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-23 12:20:53 +02:00
Eric Espie
9f60f27636 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-22 16:41:45 +02:00
Eric Espie
ba59643f52 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:47:46 +02:00
Eric Espie
01c02a75a8 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:40:43 +02:00
Eric Espie
f5b3e5f341 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:10:34 +02:00
Eric Espie
9b825cb529 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:05:58 +02:00
Eric Espie
3f326f0913 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:05:58 +02:00
acognet
ec86bd246a N°5129 - Unwanted popup during a transition with an AttributeExternalField 2022-06-21 15:24:25 +02:00
Eric Espie
aa90d5b6ab N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 13:51:08 +02:00
Pierre Goiffon
d6798470e7 💡 N°5248 \cmdbAbstractObject::DisplayBareHeader phpdoc v3 2022-06-21 12:15:04 +02:00
Pierre Goiffon
073388436b 💡 N°5248 \cmdbAbstractObject::DisplayBareHeader phpdoc v2 2022-06-21 10:21:10 +02:00
Pierre Goiffon
84d1be07cd 💡 N°5248 Document method signature change in \cmdbAbstractObject::DisplayBareHeader 2022-06-20 15:38:51 +02:00
Pierre Goiffon
26747b8c7e Merge remote-tracking branch 'origin/support/3.0.1' into support/3.0 2022-06-17 10:50:18 +02:00
Benjamin Dalsass
d0b8c560f6 N°5037 - Setup: Add disclaimer about collected data
3.0 look and feel adaptation
2022-06-17 09:50:36 +02:00
Benjamin Dalsass
4d180eb303 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.lock
#	js/wizardhelper.js
#	lib/composer/autoload_real.php
#	lib/composer/installed.json
#	lib/composer/installed.php
#	lib/guzzlehttp/guzzle/CHANGELOG.md
#	setup/wizardsteps.class.inc.php
2022-06-17 09:25:57 +02:00
acognet
53d2129bd1 N°5129 - Unwanted popup during a transition with an AttributeExternalField 2022-06-16 17:58:19 +02:00
Eric Espie
d21b577dd7 N°5229 - Caselog inline image lost after migration to 3.0 - missing calls to InlineImage::FixUrls() 2022-06-14 17:40:21 +02:00
Benjamin Dalsass
00e8c11ec2 N°5037 - Setup: Add disclaimer about collected data
change ui organization
2022-06-14 17:18:34 +02:00
Benjamin Dalsass
617b6b991f N°5037 - Setup: Add disclaimer about collected data
flip modules array
2022-06-14 14:33:35 +02:00
Benjamin Dalsass
b3ea1050eb N°5037 - Setup: Add disclaimer about collected data 2022-06-14 12:40:36 +02:00
Benjamin Dalsass
ca98066d68 N°5037 - Setup: Add disclaimer about collected data 2022-06-14 10:54:25 +02:00
Pierre Goiffon
352f7c8675 Update guzzlehttp/guzzle 2022-06-14 09:47:13 +02:00
Eric Espie
df5d514c28 N°4642 - Core Update : limit the usage of this function to minor version - fix error message (revert) 2022-06-13 15:59:25 +02:00
Eric Espie
16663797b2 N°4642 - Core Update : limit the usage of this function to minor version - fix error message 2022-06-13 15:51:36 +02:00
Eric Espie
4099376472 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Defer the deletion (expunge) to the end of connection 2022-06-09 11:40:13 +02:00
Pierre Goiffon
fb64fbab0b Fix syntax error in Darkmoon theme 2022-06-08 18:10:03 +02:00
Eric Espie
6e4fb5888c N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
* migration to iTop 3.0
2022-06-08 15:47:52 +02:00
Eric Espie
c94c727058 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * migration to iTop 3.0
2022-06-08 15:46:29 +02:00
Eric Espie
6d3118d9e9 N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth (fix config error message) 2022-06-08 13:24:29 +02:00
Benjamin Dalsass
a0c78a94c6 Merge remote-tracking branch 'origin/support/3.0' into support/3.0
# Conflicts:
#	core/log.class.inc.php
2022-06-08 13:05:50 +02:00
Benjamin Dalsass
f014ebfeb1 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/log.class.inc.php
#	setup/modelfactory.class.inc.php
2022-06-08 13:04:50 +02:00
Benjamin Dalsass
220b384479 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/log.class.inc.php
#	setup/modelfactory.class.inc.php
2022-06-08 12:38:41 +02:00
odain
4c585614cd ease testing: CreateTestOrganization returns org object 2022-06-08 11:07:31 +02:00
Eric Espie
9674378c56 N°5211 - Core update not working with auto-selected modules (comments) 2022-06-08 10:36:55 +02:00
Eric Espie
9e314ba77b N°5211 - Core update not working with auto-selected modules 2022-06-08 10:24:03 +02:00
Eric Espie
cdd7dcdc5c N°5211 - Core update not working with auto-selected modules 2022-06-08 10:12:19 +02:00
Benjamin Dalsass
34bed5ec4f N°5215 - Portal insufficient access control for ajax search form 2022-06-07 11:14:43 +02:00
Pierre Goiffon
3ea82e37d5 N°4635 Report \LogChannels::NOTIFICATIONS 2022-06-03 18:00:29 +02:00
Pierre Goiffon
596c62aec8 💡 N°4867 Add bug reference in phpdoc 2022-06-03 09:54:29 +02:00
Benjamin Dalsass
834084a3e2 Correct dictionary entry 2022-06-02 17:15:10 +02:00
Benjamin Dalsass
0819b9baba Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.json
#	composer.lock
#	core/config.class.inc.php
#	core/dbobject.class.php
#	core/email.class.inc.php
#	datamodels/2.x/itop-core-update/dictionaries/hu.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/it.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/ja.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/nl.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/ru.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/sk.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/tr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/zh_cn.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/pt_br.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/view/ConfirmUpdate.html.twig
#	datamodels/2.x/itop-portal-base/portal/src/Twig/AppExtension.php
#	datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml
#	datamodels/2.x/itop-welcome-itil/datamodel.itop-welcome-itil.xml
#	dictionaries/cs.dictionary.itop.core.php
#	dictionaries/cs.dictionary.itop.ui.php
#	dictionaries/da.dictionary.itop.core.php
#	dictionaries/da.dictionary.itop.ui.php
#	dictionaries/de.dictionary.itop.core.php
#	dictionaries/de.dictionary.itop.ui.php
#	dictionaries/en.dictionary.itop.ui.php
#	dictionaries/es_cr.dictionary.itop.core.php
#	dictionaries/es_cr.dictionary.itop.ui.php
#	dictionaries/fr.dictionary.itop.core.php
#	dictionaries/fr.dictionary.itop.ui.php
#	dictionaries/hu.dictionary.itop.core.php
#	dictionaries/hu.dictionary.itop.ui.php
#	dictionaries/it.dictionary.itop.core.php
#	dictionaries/it.dictionary.itop.ui.php
#	dictionaries/ja.dictionary.itop.core.php
#	dictionaries/ja.dictionary.itop.ui.php
#	dictionaries/nl.dictionary.itop.core.php
#	dictionaries/nl.dictionary.itop.ui.php
#	dictionaries/pt_br.dictionary.itop.core.php
#	dictionaries/pt_br.dictionary.itop.ui.php
#	dictionaries/ru.dictionary.itop.core.php
#	dictionaries/ru.dictionary.itop.ui.php
#	dictionaries/sk.dictionary.itop.core.php
#	dictionaries/sk.dictionary.itop.ui.php
#	dictionaries/tr.dictionary.itop.core.php
#	dictionaries/tr.dictionary.itop.ui.php
#	dictionaries/zh_cn.dictionary.itop.core.php
#	dictionaries/zh_cn.dictionary.itop.ui.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_real.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.json
#	lib/composer/installed.php
#	sources/application/TwigBase/Controller/Controller.php
#	sources/application/TwigBase/Twig/TwigHelper.php
2022-06-02 16:30:48 +02:00
acognet
265415030e N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Add comment 2022-06-02 12:35:42 +02:00
Eric Espie
3d26f28f9b N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
* Add icons to wizard
2022-06-01 11:44:02 +02:00
Eric Espie
0abec767e3 Dictionaries 2022-06-01 10:45:53 +02:00
Benjamin Dalsass
9fd10bd73e N°5168 - Security hardening 2022-05-31 16:28:02 +02:00
acognet
95dafc87c0 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Add tests 2022-05-30 15:10:50 +02:00
acognet
fe1790793e N°4898 - security hardening 2022-05-30 15:10:49 +02:00
Eric Espie
ddb95dc64e Removed laminas service manager test folder 2022-05-27 09:32:16 +02:00
Eric Espie
f6f9ee26e1 Removed laminas service manager test folder 2022-05-27 09:29:00 +02:00
Eric Espie
21faa92904 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-27 09:06:28 +02:00
Eric Espie
622f40c06c N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
 * Fix legacy mailboxes compatibility
2022-05-25 08:21:16 +02:00
acognet
964134cb60 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Remove useless code 2022-05-24 18:20:18 +02:00
Pierre Goiffon
f0d1c3ac60 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/utils.inc.php
#	core/htmlsanitizer.class.inc.php
#	datamodels/2.x/itop-portal-base/portal/src/Twig/AppExtension.php
#	pages/UI.php
#	test/OQL/DataLocalizerTest.php
#	test/OQL/OQLToSQLAllClassesTest.php
#	test/OQL/OQLToSQLGroupByTest.php
#	test/OQL/OQLToSQLNestedSelectTest.php
#	test/OQL/OQLToSQLTest.php
#	test/application/UtilsTest.php
2022-05-24 11:13:28 +02:00
acognet
72f498a63b N°5168 - Fix error message "Call to a member function GetKey() on null" 2022-05-24 10:50:56 +02:00
Pierre Goiffon
f9a1f68295 N°4655 Remove OQL tests
Were only here to check legacy OQL engine, but since 2.7.0 we fixed couple of bugs in the current OQL engine : we can't keep same functionalities in both engines :/.

Plus now we are working on 2.7.7 and we're not aware of any use of this legacy engine...

Note that it will be deprecated (N°3141) and removed (N°4715) very soon.
2022-05-24 10:38:59 +02:00
Pierre Goiffon
9b67b0b9d5 Same options in phpunit config files 2022-05-23 14:53:13 +02:00
acognet
f798ef1d76 N°4538 - Dashlet Groupby on ExternalKey with special character, bad display - remove useless test 2022-05-23 14:21:03 +02:00
Eric Espie
754946bf62 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
 * Fix legacy mailboxes compatibility
2022-05-23 12:09:40 +02:00
Eric Espie
a6580e3cd8 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-23 10:56:32 +02:00
Pierre Goiffon
da6621f2ff Fix include warning in unittestautoload.php on Windows 2022-05-23 09:53:30 +02:00
Molkobain
f2d42a7e56 N°5002 - Simplify code 2022-05-20 18:41:39 +02:00
Benjamin Dalsass
d01e4b4a85 N°5168 - Security hardening 2022-05-20 16:08:25 +02:00
Pierre Goiffon
f57d1f1de3 Fix PHPunit errors with InlineImageMock.php and UtilsTest
HTMLDOMSanitizerTest : fix "Fatal error: Cannot declare class InlineImage, because the name is already in use in /var/www/html/iTop/test/core/sanitizer/InlineImageMock.php"
We are now injecting the class to mock, instead of declaring another class with the same name (was working before but why ?!???)

\UtilsTest::testSanitizer : no more testing the "class" filter, because it is a simple indirection, and we need to load datamodel which is causing multiple problems (see the comment in the test method dataprovider)
2022-05-20 10:48:05 +02:00
Eric Espie
a3f122184c N°4642 - Core Update : limit the usage of this function - revert due to N°4666 fix 2022-05-20 10:20:47 +02:00
acognet
16fcddc249 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal (regression of N°4384 ) 2022-05-20 09:52:25 +02:00
Eric Espie
2a9c9be36a N°4666 - Core Update : handle modules 2022-05-20 09:42:14 +02:00
Molkobain
227814e6c3 N°4517 - PHP 8.1: Fix missing use statement 2022-05-20 09:35:23 +02:00
Eric Espie
ca3aae23a1 N°4666 - Core Update : handle modules 2022-05-20 09:33:41 +02:00
bdalsass
4dd384e418 N°4872 - Create a ticket in resolved statut Inlineimage disappear (#294) 2022-05-20 09:26:06 +02:00
Molkobain
80e7313b24 PHPDoc 2022-05-19 17:40:14 +02:00
Eric Espie
183c3c1baf N°4666 - Core Update : handle modules 2022-05-19 16:30:06 +02:00
Eric Espie
160c52fe81 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-19 14:49:48 +02:00
Benjamin Dalsass
5f0a820b4a N°4899 - add sanitizer url since annotation and tests for sanitizer function 2022-05-19 08:36:42 +02:00
Molkobain
60aaa01e2e N°4517 - PHP 8.1: Replace strlen() usages with utils::StrLen() for compatibility 2022-05-18 19:59:20 +02:00
Molkobain
d3fb08ba81 PHP 8.1: Replace strlen() usages with utils::StrLen() for compatibility 2022-05-18 18:32:48 +02:00
Benjamin Dalsass
03ef4246bf N°4899 - add sanitizer url since annotation and tests for sanitizer function 2022-05-18 12:03:07 +02:00
Benjamin Dalsass
5574eabfed N°4899 Adjust url sanitizer for 3.0 compliance 2022-05-18 10:49:23 +02:00
Benjamin Dalsass
87f606f768 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/dashlet.class.inc.php
#	pages/ajax.render.php
#	pages/csvimport.php
#	test/phpunit.xml.dist
2022-05-18 10:38:50 +02:00
Pierre Goiffon
534e7cf59d N°4655 New nightly PHPUnit file containing OQL tests
Those tests were removed in 72af2b7c as they took too much time to run.
We are re-enabling them but only for nightly builds !
2022-05-18 09:35:13 +02:00
Eric Espie
e1645f6903 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * Config messages
 * Fix unit tests
2022-05-18 08:41:58 +02:00
Benjamin Dalsass
61a2d200b4 N°4900 - Stored XSS in dashlets failed OQL query 2022-05-18 08:10:01 +02:00
Benjamin Dalsass
3d6bbe4029 Revert "N°4900 - Stored XSS in dashlets failed OQL query"
This reverts commit 562dd8fc21.
2022-05-18 08:05:19 +02:00
Thomas Casteleyn
3d04cf1cd6 🌐 Improve DBObject::CheckValue and CheckConsistency error messages (#288)
Now contains attribute code and value
2022-05-17 17:01:41 +02:00
Eric Espie
44eda676a3 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 16:56:43 +02:00
Molkobain
eac6f07823 N°4985 - PHP 8.0: Fix optional parameter before mandatory parameter
* Method is always (once) called with the value defined in iTop
  * No Combodo extension call the method
  * No customization in the ITSM Designer (snippets / extensions) call the method
  * Calling method with only the first parameter would crash anyway
2022-05-17 16:51:50 +02:00
Pierre Goiffon
424e2a5745 💡 Fix PHPDoc for \DBObject::CheckConsistency 2022-05-17 15:52:43 +02:00
Molkobain
46713236c4 PHPDoc - Add corresponding link thanks to @pirGoif 2022-05-17 15:34:58 +02:00
Molkobain
0ef4fee0b4 N°4985 - PHP 8.0: Fix usort callback return type 2022-05-17 15:28:04 +02:00
Eric Espie
1d45eff9b0 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 10:11:15 +02:00
Benjamin Dalsass
8e97279401 N°4899 - Reflected XSS on revert_dashboard operation 2022-05-17 09:27:06 +02:00
Eric Espie
932ef780fd N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 09:06:49 +02:00
Benjamin Dalsass
59424c3126 N°4976 - CSRF in import page 2022-05-17 09:02:06 +02:00
Benjamin Dalsass
562dd8fc21 N°4900 - Stored XSS in dashlets failed OQL query 2022-05-17 08:20:26 +02:00
Vladimir Kunin
f3e601e340 🐛 N°4834 - Fix mentions working only with latin alphabet (no dash, no cyrillic, no asian, ...) (#274)
* 🐛 Add the 'pattern' parameter with the unicode Cyrillic block regex to the CKEditor mentions config.

* Revert "🐛 Add the 'pattern' parameter with the unicode Cyrillic block regex to the CKEditor mentions config."

This reverts commit 1f5ac000b6.

* 🐛 Rewrite the CKEditor Mentions plugin regexp to make it suitable for all Unicode alphabets.
2022-05-16 20:06:30 +02:00
Molkobain
cf745554fb N°4985 - PHP 8.0: Fix strlen() test condition that needs to be more strict 2022-05-16 18:04:29 +02:00
Molkobain
e909eac98e N°4985 - PHP 8.0: Fix is_callable() first param syntax in ObjectFormManager 2022-05-16 17:44:34 +02:00
Molkobain
5e42efc3ec N°4985 - PHP 8.0: Fix usort callback return type in portal's lists initialization 2022-05-16 17:44:33 +02:00
Molkobain
ff58fb8617 N°5172 - Add internal helpers to keep usage of null value in native PHP methods: strlen() => utils::StrLen() 2022-05-16 16:15:18 +02:00
Pierre Goiffon
98b24dff36 Merge remote-tracking branch 'origin/support/3.0.1' into support/3.0 2022-05-16 15:28:10 +02:00
Pierre Goiffon
ed9197e6ef N°4224 Fix failed Jenkins build due to "Function ReflectionType::__toString() is deprecated"
E_DEPRECATED were previously hidden on the whole test infra.
But after PHPUnit update (N°3091) we restored them.

On legacy builds we are still using PHPUnit 6 and mocks which are generating such notices. So we are now hiding them only where necessary !
2022-05-16 15:16:03 +02:00
Eric Espie
eb1d56f439 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-16 14:51:12 +02:00
Eric Espie
644e1ac4f6 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 16:27:56 +02:00
Stephen Abello
4c88dbd9ac N°2504 N°3169 N°5102 Add libraries 2022-05-13 14:39:19 +02:00
Stephen Abello
11d2e62e67 N°2504 N°3169 N°5102 Correctly disable authentication button for 2.7 2022-05-13 14:38:55 +02:00
Stephen Abello
58b27a9daa N°2504 N°3169 N°5102 Handle result display 2022-05-13 14:28:38 +02:00
Stephen Abello
caf939bf58 N°2504 N°3169 N°5102 Add dictionaries 2022-05-13 14:06:11 +02:00
Eric Espie
8c217fdac9 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 12:07:27 +02:00
Eric Espie
6b80bbeaa2 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 11:45:42 +02:00
Eric Espie
134736dce5 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 11:37:09 +02:00
Stephen Abello
4b870bcf1e N°2504 N°3169 N°5102 Add js template 2022-05-12 17:38:38 +02:00
acognet
2165bfe8c2 Fix "undefined offset" error during "Anonymize" action 2022-05-12 14:45:18 +02:00
Eric Espie
dd8a4a0082 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
2022-05-12 14:40:55 +02:00
Molkobain
c1f335fedb Merge remote-tracking branch 'origin/support/3.0.1' into support/3.0 2022-05-11 18:10:46 +02:00
Molkobain
22a4a2fc5e Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	setup/wizardsteps.class.inc.php
2022-05-11 17:50:00 +02:00
acognet
6946bb54ed Revert "Fix "undefined offset" error during "Anonymize" action"
This reverts commit b4e623d1
2022-05-11 12:38:23 +02:00
acognet
b4e623d175 Fix "undefined offset" error during "Anonymize" action 2022-05-11 10:18:58 +02:00
acognet
f4e04477db Fix "undefined offset" error during "Anonymize" action 2022-05-09 16:08:33 +02:00
Molkobain
c2607c4223 N°5035 - Setup: Remove tracking image at the end of the setup 2022-05-09 13:55:06 +02:00
Molkobain
66953be67d N°5060 - Activity panel: Increase "max_history_length" conf. parameter from 50 to 200 2022-05-09 13:14:09 +02:00
Molkobain
ce355e311c N°5060 - Activity panel: Show "load more entries" buttons no matter the filters 2022-05-09 13:14:08 +02:00
Pierre Goiffon
bab14e1489 N°4224 remove workarounds for DEPRECATED notices generated by mock
We shouldn't have the problem anymore with PHPUnit 8.5 !
2022-05-05 15:43:59 +02:00
Anne-Catherine
65a0aa7abb Update README.md 2022-05-04 10:48:33 +02:00
Anne-Catherine
261a44764d Update README.md
Change logo
2022-05-04 10:40:37 +02:00
Pierre Goiffon
b3ef9333af 💡 Added since annotation to \LogAPI::IsLogLevelEnabled 2022-05-03 17:18:07 +02:00
Pierre Goiffon
1fb0911710 🔧 N°3091 postbuild PHPunit XML : change html_errors PHP setting 2022-05-03 10:53:32 +02:00
Pierre Goiffon
867cc6ce7e Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-05-03 10:52:01 +02:00
Pierre Goiffon
b348e0ff27 🔧 N°3091 PHPunit XML : change html_errors PHP setting
We are outputting to console, and will get results in Jenkins or terminal, so no HTML please :o)
2022-05-03 10:51:48 +02:00
Pierre Goiffon
4646a05c7a N°4824 Update consumers after swiftmailer/swiftmailer
Multiple things to do as there were some changes in 6.0
Reference : https://github.com/swiftmailer/swiftmailer/blob/master/CHANGES#L107

* Fix "Call to undefined method Swift_Message::newInstance()" exception in notifications
* Fix removed Swift_MailTransport
2022-05-03 09:35:48 +02:00
Pierre Goiffon
84e35e27b8 N°5143 Fix FunctionExpression for DATE_FORMAT and formats %j, %k and %l 2022-05-02 18:59:10 +02:00
Pierre Goiffon
c5527c106c 🔧 N°3091 PHPunit XML : set columns 2022-05-02 15:33:39 +02:00
Pierre Goiffon
5eac1b8730 🔧 N°3091 PHPunit XML : fix correct PHP INI settings
see https://phpunit.readthedocs.io/en/8.5/configuration.html#the-php-element
2022-05-02 15:25:59 +02:00
Pierre Goiffon
603934bac1 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.lock
#	lib/composer/installed.php
2022-05-02 09:43:33 +02:00
Pierre Goiffon
0de15d040f ⬇️ N°4824 rollback scssphp/scssphp update (won't be done in this branch !) 2022-05-02 09:15:48 +02:00
Pierre Goiffon
41d032eee6 N°4284 Update BackOffice JQuery UI SCSS to remove SCSSPHP warnings 2022-05-02 08:48:28 +02:00
Pierre Goiffon
c4ae94fd4c Update denied test dirs 2022-04-29 17:15:50 +02:00
Pierre Goiffon
afaf72573b N°4284 remove unused dependencies 2022-04-29 17:13:58 +02:00
Pierre Goiffon
ddd41d2ba7 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.json
#	composer.lock
#	core/email.class.inc.php
#	css/ui-lightness/jqueryui.scss
#	lib/bin/php-parse
#	lib/bin/php-parse.bat
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.json
#	lib/composer/installed.php
#	lib/composer/platform_check.php
#	lib/nikic/php-parser/grammar/php7.y
#	lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php
#	lib/nikic/php-parser/lib/PhpParser/Builder/Param.php
#	lib/nikic/php-parser/lib/PhpParser/Builder/Property.php
#	lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php
#	lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php
#	lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php
#	lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php
#	lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Param.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php
#	lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php
#	lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php
#	lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php
#	lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php
#	lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php
#	lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php
#	test/core/ConfigValidator/iTopConfigAstValidatorTest.php
2022-04-29 16:18:08 +02:00
Pierre Goiffon
1e8818984e 📄 N°4284 Update licenses 2022-04-29 15:53:03 +02:00
Pierre Goiffon
a023f73509 N°4284 Update jquery UI SCSS to remove SCSSPHP warnings
Replace "Alpha(..." with "alpha(..."

Example of warning at compilation with SCSSPHP :

DEPRECATION WARNING: Calling built-in functions with a non-standard name is deprecated since Scssphp 1.8.0 and will not work anymore in 2.0 (they will be treated as CSS function calls instead).
Use "alpha" instead of "Alpha".
         on line 55 of /var/www/html/iTop/css/../css/ui-lightness/jqueryui.scss
2022-04-29 15:39:26 +02:00
Pierre Goiffon
6f0e1a7f47 N°4824 Update consumers after swiftmailer/swiftmailer update
Also remove new Doctrine test dir (iTopComposerTest feedback)
2022-04-29 15:24:56 +02:00
Pierre Goiffon
0ef9bb1a47 ⬆️ N°4824 Composer libs : update swiftmailer/swiftmailer 2022-04-29 15:24:56 +02:00
Pierre Goiffon
71ceedc4bb 🔨 N°4284 Detect new test dirs on composer update 2022-04-29 15:24:56 +02:00
Pierre Goiffon
73c3c1249f ⬆️ N°4824 Composer libs : update scssphp/scssphp 2022-04-29 15:24:56 +02:00
Pierre Goiffon
88a10dba28 N°4824 Update consumers after pelago/emogrifier update 2022-04-29 15:24:56 +02:00
Pierre Goiffon
001e222f67 ⬆️ N°4824 Composer libs : update pelago/emogrifier 2022-04-29 15:24:56 +02:00
Pierre Goiffon
af8bcdc242 ⬆️ N°4824 Composer libs : update pear/archive_tar 2022-04-29 15:24:56 +02:00
Pierre Goiffon
f4c7afc148 N°4824 Update consumers & tests after nikic/php-parser update
Was done in 3.0.0 with N°3867
(cherry picked from commit cd1ba097cb)
(cherry picked from commit 5b42f67a99)
(cherry picked from commit 2d98ca2318)
(cherry picked from commit ddc5bbd1bb)
2022-04-29 15:24:56 +02:00
Pierre Goiffon
b19c73a36e ⬆️ N°4284 Composer libs : update nikic/php-parser
Was done in 3.0.0 with N°3867
2022-04-29 15:24:55 +02:00
Pierre Goiffon
5fe0d0b94f ⬆️ N°4284 Composer libs : update combodo/tcpdf 2022-04-29 15:18:41 +02:00
Pierre Goiffon
f8d435d5f3 N°4284 Composer libs : refresh symfony 2022-04-29 15:18:41 +02:00
Pierre Goiffon
f15ef36fd1 N°4284 Composer libs : remove symfony/polyfill-php70
Though it is still downloaded because asked by symfony framework, but as we don't need it in our code no need to specify it here !
2022-04-29 15:18:41 +02:00
Pierre Goiffon
64b25c4daa 📌 N°4284 Composer libs : fix twig/twig to ~1.42.5
Without specifying explicitly the Twig version, since the update of require php from 5.6 to 7.0 we are getting Twig 2.12.5 !
We don't want Twig 2 as this version changes the macro scope and causes massive changes in our code... This update will be done later in other branches.
2022-04-29 15:15:32 +02:00
Pierre Goiffon
e81587470d N°3091 Fix ExpressionEvaluateTest::testEveryTimeFormat
Might need a real fix sometime !!
2022-04-22 17:06:03 +02:00
Pierre Goiffon
fc6df1063c N°4660 restore old phpunit testsuites order
Was causing error in DataSynchroTest::testDataSynchroByHttp
2022-04-22 16:29:01 +02:00
Pierre Goiffon
5a37bc338a N°3091 Update PHPUnit to 8.5 : fix setUp and teardDown methods signatures on support/3.0 new tests 2022-04-22 16:04:54 +02:00
Pierre Goiffon
f4a027b474 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	composer.json
#	core/cmdbchangeop.class.inc.php
#	core/cmdbobject.class.inc.php
#	css/light-grey.scss
#	setup/setuputils.class.inc.php
#	test/ItopTestCase.php
#	test/core/ConfigTest.php
#	test/core/LogAPITest.php
#	test/core/UserRightsTest.php
#	test/core/dictApcuTest.php
#	test/core/dictTest.php
#	test/core/iTopConfigParserTest.php
#	test/core/ormLinkSetTest.php
#	test/phpunit.xml.dist
#	test/postbuild_integration.xml.dist
#	test/setup/SetupUtilsTest.php
#	test/status/StatusIncTest.php
#	webservices/cron.php
2022-04-22 15:26:18 +02:00
Pierre Goiffon
d0ba0d193b N°3091 iTopComposerTest : change deprecated PHPUnit method call 2022-04-22 14:42:12 +02:00
Pierre Goiffon
8e6e2432d3 Extensibility : iPortalUIExtension and AbstractPortalUIExtension aren't experimental anymore 2022-04-21 17:29:40 +02:00
Molkobain
83ec19dfca Remove duplicated lines in .gitignore 2022-04-21 14:26:56 +02:00
Pierre Goiffon
6e619f2c35 Fix \iTopConfigParserTest::testConfigWriteToFile_FromScratchInstallation throwing error 2022-04-21 12:02:35 +02:00
Pierre Goiffon
163ba41e8d N°3091 Update PHPUnit to 8.5 : remove doesNotPerformAssertions annotation
Modified tests :
- iTopConfigParsertest
- DBSearchIntersectTest::testIntersectOptimization

As expected this isn't working with PHPUnit 8.5
Why does it worked with previous PHPUnit 6 version ? Maybe this annotation wasn't handled yet ? The corresponding PHPUnit doc isn't available anymore...

Annotations doc for PHP 8.5 : https://phpunit.readthedocs.io/en/8.5/annotations.html#doesnotperformassertions
2022-04-21 12:02:35 +02:00
Pierre Goiffon
ec143c43db N°3091 Update PHPUnit to 8.5 : fix setUp and teardDown methods signatures
"Return type declaration must be compatible with parent"
See https://phpunit.de/announcements/phpunit-8.html "Return Type of Template Methods"
2022-04-21 12:02:35 +02:00
Pierre Goiffon
cacf0004a5 🙈 N°3091 Update PHPUnit to 8.5 : add PHPunit cache file to ignore
We don't want to disable the feature, nor we want this file to be versionned
https://phpunit.readthedocs.io/en/8.5/configuration.html#the-cacheresult-attribute
2022-04-21 12:02:35 +02:00
Pierre Goiffon
cb39541e2a N°3091 Update PHPUnit to 8.5 : composer and base files
Autoload wasn't working anymore, easy to see : just launch `php unittestautoload.php` (or see fatal errors when launching tests with your IDE)
2022-04-21 10:47:30 +02:00
Pierre Goiffon
b9ddadeb44 N°5109 update PHP requirements from 5.6 to 7.0
No embedded libs supports all versions from PHP 5.6 to 8.0 included :/
7.0.8 is required for our Symfony version (updated with N°4770)
2022-04-20 17:29:20 +02:00
Benjamin Dalsass
dabd2a3f4d N°5101 - Setup error when semantic field attribute code is not defined in current class 2022-04-20 14:32:03 +02:00
Pierre Goiffon
11e811cc4b N°3717 Improve iTop object history API (#192)
This fixes a major flaw in the history API that was causing "phantom" CMDBChange records (without any CMDBChangeOp attached). That was happening especially in iProcess impl.
For example this lead to the creation of the combodo-cmdbchange-cleaner module in the Mail To Ticket extension.

The modifications in detail : 
- We can now pass a non persisted CMDBChange instance to \CMDBObject::SetCurrentChange
- No persistence done in \CMDBObject::CreateChange anymore
- Persistence of the attached CMDChange will be done if necessary in CMDBChangeOp::OnInsert
- New CMDBObject::SetCurrentChangeFromParams helper method to ease resetting the current change
2022-04-19 17:13:18 +02:00
Pierre Goiffon
e422adb0d0 N°4998 Fix CSS for AttributeDuration in transition form (#281) 2022-04-19 12:25:15 +02:00
Molkobain
b03e28efb9 N°4966 - Code cleanup 2022-04-19 12:13:14 +02:00
Pierre Goiffon
7b3d859522 N°5027 AttributeUrl handle anchors starting with digits 2022-04-19 10:57:47 +02:00
Pierre Goiffon
e02d9f3f0e 💡 N°5090 Improve phpdoc using list array shape 2022-04-15 17:43:20 +02:00
Pierre Goiffon
e831d66b76 N°5090 Setup : improve missing dependencies message (#280)
The setup now relies on the new method MissingDependencyException::getHtmlDesc to get the message to display
MissingDependencyException is also now a CoreException child.

Note that previous behavior (MissingDependencyException instantiator setting message) is kept, as some consumer still do $e->getMessage() (like unattended install)
2022-04-15 17:30:05 +02:00
acognet
6fa2d47780 N°4538 - Dashlet Groupby on ExternalKey with special character, bad display 2022-04-15 10:03:04 +02:00
acognet
e691454339 N°5002 - memory leak after object creation in popup 2022-04-15 10:00:08 +02:00
acognet
079b406f18 N°4966 - No more custom dashboard switch 2022-04-15 09:54:41 +02:00
Timothee
dbe02a42c2 N°4888 New url() placeholder 2022-04-14 12:05:41 +02:00
Molkobain
94365ea40e Update contributors stickers image to 2022! 🚀 2022-04-13 16:05:00 +02:00
Molkobain
2716f9d24c Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/config.class.inc.php
2022-04-08 13:30:42 +02:00
Stephen Abello
bac2918ceb N°5028 Revert default logos by png ones 2022-04-08 09:46:26 +02:00
Pierre Goiffon
92997e3e57 💡 N°2498 add @since 2022-04-08 08:54:07 +02:00
Stephen Abello
604837c770 N°5028 Fix updated default logo in error webpages 2022-04-07 16:46:39 +02:00
Molkobain
f32c283c9c N°4759 - Navigation menu: Fix menu groups icons glitch when switching between collapsed / expanded mode 2022-04-07 16:02:06 +02:00
Stephen Abello
27d06a712b N°5028 Update setup favicon to default one 2022-04-07 15:01:07 +02:00
Stephen Abello
b15050487c N°5028 Fix updated default logo in unauthenticated webpages 2022-04-07 14:59:48 +02:00
Stephen Abello
46f232d561 N°4759 Harmonize top and bottom space around branding logo 2022-04-07 11:04:24 +02:00
Stephen Abello
63976df2e1 N°5028 Update iTop and Combodo logos to new ones 2022-04-07 11:03:32 +02:00
Molkobain
3514e21772 Revert precompiled themes update 2022-04-04 10:54:11 +02:00
Molkobain
3463b1715a N°4674 - CKEditor: Fix space indentation in code blocks 2022-04-04 10:21:52 +02:00
Pierre Goiffon
631b38a160 N°5003 Change cron_max_execution_time config param help text 2022-03-25 15:56:11 +01:00
Eric Espie
0287500feb N°4999 - Wrong object save order in activity panel 2022-03-25 09:31:16 +01:00
Molkobain
e4cbaf7096 Typo 2022-03-23 10:23:35 +01:00
Molkobain
73c6b4be20 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	test/core/DBObjectTest.php
2022-03-23 09:44:13 +01:00
Molkobain
fde2103659 👥 Add link to contributors' GitHub profile 2022-03-23 09:42:31 +01:00
Molkobain
24500216f6 👥 Add @ChristianBeer to contributors list! 🙌 2022-03-23 09:41:24 +01:00
acognet
2039b872d3 N°4977 - Wrong result in search on a Service subcategory for Service provider 2022-03-22 17:06:05 +01:00
Molkobain
b368c593e5 N°4462 - Improve message to explicitly say next "major" release 2022-03-22 12:25:52 +01:00
Stephen Abello
c9c731a2a5 N°3541 Split button and button-group js in 2 different files 2022-03-22 10:16:17 +01:00
acognet
8204723b5b N°4667 - Remove call to tooltip function - change type of preview (fix seen with Guillaume) 2022-03-21 15:14:30 +01:00
acognet
f93218a80f N°4479 - Impact analysis : Display and apply filter before display impact analysis graphical - fix var name 2022-03-21 11:11:47 +01:00
Molkobain
4f5a9c898c N°4462 - Set next min. PHP version for iTop 3.1
Note: This might change to PHP 7.2 this summer depending on RedHat 9.0 release date / plans
2022-03-21 09:51:23 +01:00
Eric Espie
7ce5712b71 N°4967 - 'Previous Values For Updated Attributes' not updated if DBUpdate is called without modifying the object 2022-03-21 08:43:03 +01:00
acognet
90b41e0b81 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/displayablegraph.class.inc.php
#	pages/UI.php
2022-03-18 15:51:45 +01:00
Pierre Goiffon
9d2c89f118 N°4959 Fix graph dashlet not refreshed
Previous fix in e4501389 was incomplete, cause passing empty as id isn't handled in called method.
2022-03-18 15:16:52 +01:00
acognet
61137a6f65 N°4479 - Impact analysis : Display and apply filter before display impact analysis graphical - Fix dictionnary 2022-03-18 11:02:04 +01:00
acognet
a26c8fbd48 N°4971 - "Please specify a value" does not disappear after selecting the value via the popup 2022-03-17 17:39:31 +01:00
Pierre Goiffon
0080a2e733 💡 N°3129 Fix phpdoc
Method was renamed in 45b5c39a but I forgot to update the PHPDoc
2022-03-17 15:36:39 +01:00
acognet
992ee3a74b N°4667 - Remove call to tooltip function - tooltip on attachment in portal 2022-03-17 12:53:03 +01:00
acognet
e45013891c N°4959 - Chart update fails in dashboard 2022-03-16 11:05:50 +01:00
acognet
ea043960ff Rename the map file. We are using the min version 2022-03-15 11:23:57 +01:00
acognet
d0f83046cd Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/itop-files-information/dictionaries/pt_br.dict.itop-files-information.php
#	datamodels/2.x/itop-files-information/dictionaries/zh_cn.dict.itop-files-information.php
2022-03-15 10:56:01 +01:00
acognet
7f4fddb378 N°4644 - Core update : confusing warning message when integrity of iTop std files is modified - fix default translation 2022-03-15 10:52:19 +01:00
Stephen Abello
9cd076131f N°3541 Add event listener to enable/disable loading state for buttons group block 2022-03-14 15:32:42 +01:00
acognet
a71cb97db3 N°4644 - Core update : confusing warning message when integrity of iTop std files is modified - fix comment 2022-03-14 15:30:35 +01:00
acognet
0c80a4e430 N°4644 - Core update : confusing warning message when integrity of iTop std files is modified - merge from 2.7.0 2022-03-14 15:28:47 +01:00
acognet
779211e638 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/itop-core-update/dictionaries/cs.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/da.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/de.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/en.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/es_cr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/fr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/hu.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/it.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/ja.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/nl.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/ru.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/sk.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/tr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/dictionaries/zh_cn.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/pt_br.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/view/SelectUpdateFile.html.twig
#	datamodels/2.x/itop-datacenter-mgmt/dictionaries/pl.dict.itop-datacenter-mgmt.php
#	datamodels/2.x/itop-endusers-devices/dictionaries/pl.dict.itop-endusers-devices.php
#	datamodels/2.x/itop-files-information/src/Service/FilesIntegrity.php
2022-03-14 15:17:28 +01:00
acognet
4c99f497cc N°4644 - Core update : confusing warning message when integrity of iTop std files is modified - List all modified files 2022-03-14 14:45:07 +01:00
Stephen Abello
d1e2be97d2 Typo in cron_task_max_execution_time description 2022-03-14 11:46:27 +01:00
Stephen Abello
93c6cfffda N°4931 Fix background tasks max duration being set to 3 times its periodicity 2022-03-14 09:35:46 +01:00
Molkobain
b50ba0ad49 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-03-13 20:36:49 +01:00
Molkobain
0205cdf713 N°4791 - Portal: Fix "Twig not allowed" error when transition form has no editable field (auto redirect)
Regression from b6fac4b4
2022-03-13 18:15:49 +01:00
Molkobain
39fc59a8b2 Code cleanup 2022-03-13 17:55:04 +01:00
Molkobain
107c9adf60 N°4791 - Expand usage of ObjectFormHandlerHelper::ENUM_MODE_XXX constants for better robustness / comprehension 2022-03-13 17:29:55 +01:00
Molkobain
143c30b099 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/itop-core-update/cs.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/da.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/de.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/en.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/es_cr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/hu.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/it.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/ja.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/nl.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/pt_br.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/ru.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/sk.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/src/Service/CoreUpdater.php
#	datamodels/2.x/itop-core-update/tr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/view/ConfirmUpdate.html.twig
#	datamodels/2.x/itop-core-update/zh_cn.dict.itop-core-update.php
2022-03-11 18:03:21 +01:00
Molkobain
d29880b1b8 Update PHPDoc 2022-03-11 17:52:10 +01:00
acognet
3edfc2016d Fix typo 2022-03-11 15:41:12 +01:00
Molkobain
5f80be75ed N°4938 - Fix remaining broken AJAX endpoints in ajax.render.php 2022-03-11 10:47:05 +01:00
Molkobain
0d4796ae2b N°4938 - Fix background calls broken by lazy JS dictionaries loads 2022-03-11 09:34:27 +01:00
acognet
2d156bd77b N°4642 - Core Update : limit the usage of this function - disable if new modules found 2022-03-10 16:47:21 +01:00
Pierre Goiffon
5908ec5197 N°4515 AttributeURLTest : add SF forum url 2022-03-10 16:42:43 +01:00
acognet
d122dbfdd6 N°4642 - Core Update : limit the usage of this function - disable if new modules found 2022-03-10 16:06:37 +01:00
acognet
46d58e6512 N°4642 - Core Update : limit the usage of this function - disable if new modules found 2022-03-10 15:24:29 +01:00
Christian Beer
6cf781da33 🌐 Improve German translation (#277)
Many thanks @ChristianBeer for this great contribution, and @larhip for the validation !
2022-03-10 14:16:59 +01:00
Molkobain
0f2cbaf186 N°4849 - Enable notification emails grouping in threads in email clients (#275)
N°4849 - Enable notification emails grouping in threads in email clients (#275)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2022-03-10 09:31:29 +01:00
Molkobain
7ddb47dc83 N°4312 - Activity panel: Fix JS error on object without tabs (typically DBObject instead of cmdbAbstractObject)
Regression from b9c5f2c523
2022-03-09 20:06:19 +01:00
Molkobain
304e379c01 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/itop-core-update/cs.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/da.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/de.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/en.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/es_cr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/hu.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/it.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/ja.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/nl.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/pt_br.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/ru.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/sk.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/tr.dict.itop-core-update.php
#	datamodels/2.x/itop-core-update/view/SelectUpdateFile.html.twig
#	datamodels/2.x/itop-core-update/view/SelectUpdateFile.ready.js.twig
#	datamodels/2.x/itop-core-update/zh_cn.dict.itop-core-update.php
2022-03-09 18:31:34 +01:00
Molkobain
93a138606f N°4664 - Core Update : block zip file upload until instance declared OK 2022-03-09 18:21:08 +01:00
Molkobain
70074ee1cb N°4644 - Core update: Update translations with missing entry 2022-03-09 17:31:22 +01:00
Molkobain
d28ccb264f N°4644 - Core update : confusing warning message when integrity of iTop std files is modified
(cherry picked from commit 69a0bd0c34)
2022-03-09 17:28:38 +01:00
Thomas Casteleyn
9f95d45f51 Fix check on when to load JS dicts 2022-03-08 18:42:55 +01:00
odain-cbd
8ab38854a8 N°4920 - Fix "undefined index" notice in user rights (#271) 2022-03-08 18:21:40 +01:00
acognet
bceb570d84 N°4874 - Auto Refresh of attribute Dasboard 2022-03-08 15:31:41 +01:00
acognet
138fa569f2 N°4642 - Core Update : limit the usage of this function to minor version 2022-03-08 14:56:15 +01:00
Molkobain
1f65ab5a92 N°4642 - Improve conventions
* Rename SCSS variables
  * Optimize SCSS rules
2022-03-07 17:05:29 +01:00
Molkobain
7cfac7300b N°4642 - Fix typo in SCSS variables 2022-03-07 16:31:43 +01:00
Molkobain
ede720c9b9 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2022-03-07 12:52:09 +01:00
Molkobain
684efee5d2 N°4664 - Code format 2022-03-07 12:49:27 +01:00
acognet
e347989dcb N°4664 - Core Update : block zip file upload until instance declared OK 2022-03-07 12:05:54 +01:00
acognet
e1051e7a47 N°4654 - Missing licence Information in About iTop for non admin users - add since 3.0.1 2022-03-07 11:35:18 +01:00
Molkobain
7e8eb26866 N°4654 - Change block ID to match conventions 2022-03-07 09:50:07 +01:00
Molkobain
6775a3e928 Code cleanup 2022-03-07 09:47:54 +01:00
Molkobain
faa38155e5 N°4911 - Mentions: Fix DBObject::Reload() for classes with an image attribute 2022-03-06 22:44:13 +01:00
Molkobain
558bbc3357 Revert "N°4911 - Mentions: Fix Person picture not displayed if marker configured on parent class (Contact)"
This reverts commit 106127e6b7.

As the image attribute can be different depending on the object finalclass, it cannot be added in the DBObjectSet::OptimizeColumnLoad(), which means that retrieving it within the loop might lead to a complete DBObject::Reload() of the object which can have a real impact on performances depending on the objects.
2022-03-06 22:44:13 +01:00
Molkobain
cd7f9e478f N°4913 - Avoid object initials to overflow in medallions 2022-03-06 22:44:12 +01:00
Molkobain
e3586cff65 Unit tests: Add unit cyrillic alphabet test case for utils::ToAcronym() 2022-03-06 16:31:48 +01:00
Molkobain
106127e6b7 N°4911 - Mentions: Fix Person picture not displayed if marker configured on parent class (Contact) 2022-03-06 12:49:11 +01:00
Molkobain
2299983db3 N°4741 - Factorize activation of on mention triggers 2022-03-06 11:54:39 +01:00
acognet
2fab7de34b N°4806 - UI:WelcomeMenu:Text contains empty string 2022-03-04 10:36:28 +01:00
acognet
c0ab79971c N°4654 - Missing licence Information in About iTop for non admin users - nicer loading icon 2022-03-04 10:36:27 +01:00
Molkobain
03ed9c9deb N°4905 - Fix usage of ITOP_APPLICATION constant in dictionaries 2022-03-04 10:31:01 +01:00
acognet
7152277760 N°4642 - Core Update : limit the usage of this function to minor version or disable the functionality ? 2022-03-03 22:02:35 +01:00
acognet
14d05da9f6 N°4664 - Core Update : block zip file upload until instance declared OK 2022-03-03 22:00:15 +01:00
acognet
69a0bd0c34 N°4644 - Core update : confusing warning message when integrity of iTop std files is modified 2022-03-03 21:59:04 +01:00
acognet
c09cee994a N°2884 - Core update : Database version not updated - remove definitively lines with $sDataModelVersion 2022-03-03 16:17:16 +01:00
acognet
50ee0b3eed N°4654 - Missing licence Information in About iTop for non admin users 2022-03-03 16:16:45 +01:00
Molkobain
84169a864c N°4856 - Update PHPDoc 2022-03-03 15:50:28 +01:00
acognet
9f27cf2b84 N°4525 - bad source for extensions in system information and about iTop with iTop Pr 2022-03-03 15:14:28 +01:00
Pierre Goiffon
f78986009f Improve messages of iTopModuleXmlInstallationChecklistTest::testAllModuleAreIncludedInInstallationXml 2022-03-03 10:46:06 +01:00
Eric Espie
4fdbec72d4 N°4569 - dictionaries 2022-03-03 10:00:25 +01:00
Eric Espie
94d31827e7 N°4569 - Fix tests 2022-03-02 17:54:27 +01:00
Eric Espie
45a8eb93e7 N°4569 - Add itop-themes-compat 2022-03-02 17:14:08 +01:00
Eric Espie
6ac3539373 N°4569 - Revert meta save of deleted nodes 2022-03-02 17:08:45 +01:00
Stephen Abello
a5d8425fe7 N°4741 Fix On mention trigger not working on object creation 2022-03-02 16:13:00 +01:00
Stephen Abello
3608c6b8ab N°4582 Prevent selectize behavior introduced by 2e08cff from displaying unescaped characters 2022-03-02 16:12:59 +01:00
Pierre Goiffon
2b1e583dc7 💡 N°4854 Document compiler behavior change for model.*.php files 2022-03-02 10:06:59 +01:00
Pierre Goiffon
3081aa473a Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	setup/runtimeenv.class.inc.php
2022-03-02 09:49:59 +01:00
Pierre Goiffon
809ea2eb49 💡 N°4854 Add phpdoc to utils::*Module* methods 2022-03-02 09:42:09 +01:00
acognet
2f98a3e7ac N°2884 - Core update : Database version not updated - prevent multi click on button "About iTop" 2022-03-01 17:04:37 +01:00
acognet
c737fc46ff N°2884 - Core update : Database version not updated 2022-02-28 15:21:44 +01:00
Stephen Abello
619c0d34e8 N°4764 Fix unit test 2022-02-28 14:59:56 +01:00
acognet
bdc7ed6f8e N°4057 - Custom Translation for Custom Tab is not inherited by instanciable Classes 2022-02-28 12:09:38 +01:00
Eric Espie
d9819d9c2a N°4784 - CAS authentication issue with iTop 3.0
* Fix regression when setting cas as first login mode
2022-02-28 11:55:45 +01:00
Eric Espie
f24f8a2f34 N°4569 - Fix restoring deleted nodes when parent is not present 2022-02-28 10:54:59 +01:00
Stephen Abello
3890b1a020 N°4764 Remove iTop version from webservices/status.php 2022-02-25 10:08:43 +01:00
Stephen Abello
2e08cff9ee N°4582 Align backspace behavior in selectize widgets with jQuery autocomplete one 2022-02-25 09:40:02 +01:00
Pierre Goiffon
968a0e5f3a Add check to prevent setup crash when creating config
Cherry-pick of 09b12bd0
This will prevent also a warning when running on PHP 8.0 (N°3129)
2022-02-24 15:39:20 +01:00
Molkobain
4694e8152e N°4809 - Remove iTopOwnershipToken class from CSV import list 2022-02-22 11:42:28 +01:00
Pierre Goiffon
4b731dd336 N°4836 Better fix by adding AjaxPage::SetOutputDataOnly() 2022-02-22 10:23:15 +01:00
Stephen Abello
5e0c7c211b N°4460 Fix run-query highlight color on error for Full Moon and Darkmoon 2022-02-22 10:13:36 +01:00
Pierre Goiffon
815870fe6b Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/cmdbabstract.class.inc.php
#	dictionaries/cs.dictionary.itop.model.php
#	dictionaries/da.dictionary.itop.model.php
#	dictionaries/de.dictionary.itop.model.php
#	dictionaries/es_cr.dictionary.itop.model.php
#	dictionaries/fr.dictionary.itop.model.php
#	dictionaries/hu.dictionary.itop.model.php
#	dictionaries/it.dictionary.itop.model.php
#	dictionaries/ja.dictionary.itop.model.php
#	dictionaries/pl.dictionary.itop.model.php
#	dictionaries/pt_br.dictionary.itop.model.php
#	dictionaries/tr.dictionary.itop.model.php
#	dictionaries/zh_cn.dictionary.itop.model.php
2022-02-22 09:36:06 +01:00
Pierre Goiffon
33ceab86fb N°4836 Fix dashlet editor when iBackofficeDictEntriesExtension impl exists 2022-02-21 16:52:31 +01:00
Molkobain
fe1bf3bfc1 PHPDoc 2022-02-19 17:18:42 +01:00
acognet
3727223db3 Fix comment 2022-02-18 18:05:36 +01:00
Stephen Abello
5b96d9f778 N°4769 Fix badly escaped run query suggestions containing multiple lines 2022-02-18 10:17:14 +01:00
Stephen Abello
162b15236d N°4783 Fix tabs headers hiding on Chrome with zoom-in/out 2022-02-18 09:17:55 +01:00
acognet
83e98ef2b8 N°4284 - Object modification: Attribute value lost if not allowed to be seen 2022-02-17 17:06:06 +01:00
Stephen Abello
d783954d13 N°4671 Fix dark moon extra tabs color 2022-02-17 14:48:35 +01:00
Molkobain
7207dc657c N°4662 - Add comment to all concerned templates 2022-02-17 14:13:41 +01:00
Stephen Abello
f1cce8e430 N°4582 Nicer focus indicator for extkey selectize inputs 2022-02-16 15:35:11 +01:00
Molkobain
3da49e6603 N°4814 - Improve image attribute placeholder when no default image 2022-02-16 11:45:18 +01:00
Pierre Goiffon
5048421bfa 🔥 N°4815 Remove .model files in /dictionaries
They were added with 3fb0c768 in 2.5.2, probably by mistake as they :
* exists only for certain languages and not for english
* only contain comments
2022-02-16 10:17:42 +01:00
Stephen Abello
b9c5f2c523 N°4312 Keep selected activity panel tab active when refreshing or modifying an object 2022-02-15 15:45:41 +01:00
acognet
ec75195a2f N°4662 - Portal: Fix broken display of the services catalogue when installing Service Provider + Sample Data
(cherry picked from commit f9e8bf88c8)
2022-02-15 14:08:44 +01:00
Stephen Abello
e971d628dd N°4565 Add a message indicator to caselog tabs toggler 2022-02-15 10:21:09 +01:00
acognet
bbd50ba73b N°4438 - Disable (temporarly) copy of precompiled stylesheets after setup 2022-02-15 09:59:47 +01:00
acognet
ba71c1bcd5 N°4747 - Broken XLSX Templates created 2022-02-15 09:59:47 +01:00
acognet
16be8fd3d3 N°4777 - UserRequest: selecting organisation through hierarchy tree 2022-02-15 09:59:47 +01:00
acognet
cacae0a2b3 N°4591 - Space trimed when filling html attribute or log attribute with object-copier 2022-02-15 09:59:47 +01:00
Pierre Goiffon
b1ed15f31c N°4787 Remove useless "+" dict entries
Emptied "+" entries when their value is the same as its counterpart
2022-02-14 16:33:10 +01:00
acognet
788caf9c50 N°4284 - Object modification: Attribute value lost if not allowed to be seen 2022-02-14 12:26:16 +01:00
Eric Espie
1728dcc40c N°4784 - CAS authentication issue with iTop 3.0
* Moved session closing after the login
2022-02-14 09:31:52 +01:00
acognet
35165568af N°4057 - Custom Translation for Custom Tab is not inherited by instanciable Classes 2022-02-14 09:10:18 +01:00
Pierre Goiffon
cb5554ddb1 N°4714 Fix setup crashing with "Call to undefined method utils::GetCoreVersionWikiSyntax()" 2022-02-14 08:49:46 +01:00
Pierre Goiffon
6a5840ed82 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	lib/composer/installed.php
#	setup/licenses/community-licenses.xml
#	setup/setuputils.class.inc.php
#	sources/application/TwigBase/Controller/Controller.php
2022-02-14 08:41:33 +01:00
Molkobain
4a67819f87 N°4714 - Revert rename of utils::GetItopVersionWikiSyntax as it is used in cached packages in the ITSM Designer 2022-02-11 20:00:39 +01:00
Pierre Goiffon
81c39c35cd N°4771 Fix lib test dir detection
Thanks to @Molkobain and @Hipska for their review in dfaa9733
2022-02-11 18:15:56 +01:00
Pierre Goiffon
4caf52f1ae 🔥 N°4781 Remove SetupUtils::Log 2022-02-11 16:48:24 +01:00
Pierre Goiffon
0c5b845c8a 📄 N°4770 Update license file 2022-02-11 16:23:54 +01:00
Pierre Goiffon
cdfdb1f2ca 🔧 N°4770 composer.json version constraint
Will help Dependabot !
2022-02-11 16:23:54 +01:00
Pierre Goiffon
f29a8792af ⬆️ N°4770 Update to latest Symfony 3.4 2022-02-11 16:23:03 +01:00
Pierre Goiffon
b494ff2ce6 N°4488 Remove cmdbAbstractObject methods used in export.php from API methods and add comment in export.php
`@deprecated` was added in 03e9bcd4 but as none of those will be removed in a near future, we are using `@internal`instead !
2022-02-11 16:15:35 +01:00
Molkobain
a65c55fc48 iTopWebPage: Add CSS classes in addition to HTML IDs in template
This ease mocking several pages in a single one when IDs are removed
2022-02-11 15:51:52 +01:00
Molkobain
01b94f42fe Fix object's actions menu cannot be open (regression from 0d26211d) 2022-02-11 15:00:44 +01:00
odain
df1e19dc43 enhance ItopDataTestCase->CreateUser to avoid be able to avoid hardcoded contact_id 2022-02-11 14:10:02 +01:00
Thomas Casteleyn
cbef9bb267 Allow binary data to be imported/synchronised with the synchro_import.php 2022-02-11 12:16:09 +01:00
Pierre Goiffon
9ad341f73a N°4771 Fix .make/composer/rmDeniedTestDir.php Throwing errors when dir in denied list not existing on disk 2022-02-10 15:12:31 +01:00
acognet
03e9bcd47a N°4488 - deprecate cmdbAbstractObject::GetSetAsHTMLSpreadsheet() used only by the old export.php 2022-02-10 15:04:59 +01:00
acognet
55effea0a3 N°4513 - User Portal can apply transition on on an objetc not in his scope 2022-02-10 14:01:21 +01:00
Pierre Goiffon
dfaa973359 N°4771 improve iTopComposerTest
- debug testListDeniedTestDir not working well on Windows
- update error message for testAllDirCovered
2022-02-10 12:54:09 +01:00
Pierre Goiffon
2e45b20fc4 N°4771 Fix .make/composer/rmDeniedTestDir.php doing nothing on Windows
Note that a .gitignore entry was added in dbc3da7b but it isn't necessary if rmDeniedTestDir work as expected !
2022-02-10 12:45:52 +01:00
Pierre Goiffon
e89090f0ec N°4771 Update lib test dirs list : reordered for readability / easier maintenance 2022-02-10 12:08:18 +01:00
Molkobain
c9d02826a0 Code cleanup (indentation and PHPDoc) 2022-02-09 19:28:21 +01:00
Pierre Goiffon
47db04bcb7 💡 N°4760 Add complement in phpdoc 2022-02-09 11:48:17 +01:00
Pierre Goiffon
a49c451ae4 💡 N°4760 Fix wrong phpdoc 2022-02-09 11:43:42 +01:00
Pierre Goiffon
25c3704990 N°4761 Fix license.xml content not displayed in setup with multi modules extensions (#261)
For example :
module "mymodule" is in extension "myextension"
On the file system the `license.xml` file will be in `/extensions/myextension/mymodule/license.mymodule.xml`
This form wasn't working in the setup but well displayed in the about box.

When \SetupUtils::GetLicenses was called in the setup it was searching with a GLOB pattern only in one level subfolders. Now we are searching 2 levels.
When called from the console, it is only searching in env-*, where everything is on one level.
2022-02-08 17:28:47 +01:00
Pierre Goiffon
3000659e86 🎨 Change disable breadcrumb method name to clarify usage
Thanks @eespie for the review !
2022-02-08 17:04:11 +01:00
Pierre Goiffon
ce36c00b83 Remove now useless default values
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2022-02-08 17:04:11 +01:00
Pierre Goiffon
2a3e6384d9 ♻️ After dev team code review 2022-02-08 17:04:11 +01:00
Pierre Goiffon
dd7e73e413 🎨 Simpler code
Thanks Hipska !
2022-02-08 17:04:11 +01:00
Pierre Goiffon
1709082e39 Controller::CreatePage : default values for sUrl and sIcon 2022-02-08 17:04:11 +01:00
Pierre Goiffon
41f6e85673 Controller::CreatePage : use @list() intead of 3 lines with count() tests
Thanks Hipska !

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2022-02-08 17:04:11 +01:00
Pierre Goiffon
3ef3166bd5 Add new methods to override in order to control breadcrumb in Controller children classes 2022-02-08 17:04:11 +01:00
Pierre Goiffon
0d26211dbe Fix error in object details : "Too few arguments to function MenuBlock::GetRenderContent()" 2022-02-08 15:16:57 +01:00
Pierre Goiffon
3b99006159 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	test/integration/iTopModulesPhpVersionChecklistTest.php
2022-02-08 14:49:08 +01:00
Pierre Goiffon
299ad7e753 N°4714 Fix \utils::GetCoreVersionWikiSyntax throwing Exception when 2nd version digit is "0" (for example in 3.0.1) 2022-02-08 14:48:02 +01:00
Pierre Goiffon
94a2421186 N°4714 Fix iTopModulesPhpVersionIntegrationTest
Was still testing removed utils::GetItopMinorVersion()
And also wrong merge done in testITopModulesPhpVersion()
2022-02-08 14:30:06 +01:00
Pierre Goiffon
923c3a27a3 Prepare 3.0.1 version 2022-02-08 14:28:27 +01:00
Pierre Goiffon
c1a1186bf7 N°4714 Fix setup crashing with "Call to undefined method utils::GetItopVersionWikiSyntax()"
Regression caused by merge b3605146
2022-02-08 13:55:20 +01:00
Pierre Goiffon
b360514646 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/displayblock.class.inc.php
#	application/ui.extkeywidget.class.inc.php
#	application/utils.inc.php
#	approot.inc.php
#	core/config.class.inc.php
#	css/css-variables.scss
#	datamodels/2.x/authent-cas/module.authent-cas.php
#	datamodels/2.x/authent-external/module.authent-external.php
#	datamodels/2.x/authent-ldap/module.authent-ldap.php
#	datamodels/2.x/authent-local/module.authent-local.php
#	datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/module.itop-attachments.php
#	datamodels/2.x/itop-backup/module.itop-backup.php
#	datamodels/2.x/itop-bridge-virtualization-storage/module.itop-bridge-virtualization-storage.php
#	datamodels/2.x/itop-change-mgmt-itil/module.itop-change-mgmt-itil.php
#	datamodels/2.x/itop-change-mgmt/module.itop-change-mgmt.php
#	datamodels/2.x/itop-config-mgmt/module.itop-config-mgmt.php
#	datamodels/2.x/itop-config/module.itop-config.php
#	datamodels/2.x/itop-core-update/module.itop-core-update.php
#	datamodels/2.x/itop-datacenter-mgmt/module.itop-datacenter-mgmt.php
#	datamodels/2.x/itop-endusers-devices/module.itop-endusers-devices.php
#	datamodels/2.x/itop-files-information/module.itop-files-information.php
#	datamodels/2.x/itop-full-itil/module.itop-full-itil.php
#	datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
#	datamodels/2.x/itop-incident-mgmt-itil/module.itop-incident-mgmt-itil.php
#	datamodels/2.x/itop-knownerror-mgmt/module.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-portal-base/module.itop-portal-base.php
#	datamodels/2.x/itop-portal/module.itop-portal.php
#	datamodels/2.x/itop-problem-mgmt/module.itop-problem-mgmt.php
#	datamodels/2.x/itop-profiles-itil/module.itop-profiles-itil.php
#	datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php
#	datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php
#	datamodels/2.x/itop-service-mgmt-provider/module.itop-service-mgmt-provider.php
#	datamodels/2.x/itop-service-mgmt/module.itop-service-mgmt.php
#	datamodels/2.x/itop-sla-computation/module.itop-sla-computation.php
#	datamodels/2.x/itop-storage-mgmt/module.itop-storage-mgmt.php
#	datamodels/2.x/itop-tickets/module.itop-tickets.php
#	datamodels/2.x/itop-virtualization-mgmt/module.itop-virtualization-mgmt.php
#	datamodels/2.x/itop-welcome-itil/module.itop-welcome-itil.php
#	datamodels/2.x/version.xml
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.php
#	setup/modelfactory.class.inc.php
#	setup/setuputils.class.inc.php
#	test/integration/iTopModulesPhpVersionChecklistTest.php
2022-02-08 13:18:50 +01:00
acognet
541794ca9c N°4482 - Polishing : Export page 2022-02-07 16:45:25 +01:00
acognet
5fbcae1f55 N°4576 - issue with search date widget 2022-02-07 16:44:13 +01:00
Eric Espie
0f6e0e5085 Allow file name to be set with parameters 2022-02-07 15:02:47 +01:00
Stephen Abello
3541a9e1db N°3541 Add event listener to enable/disable loading state for buttons block 2022-02-07 14:54:23 +01:00
Stephen Abello
1f95a4ee21 N°3541 Add loading state design to buttons block 2022-02-07 14:54:23 +01:00
Molkobain
af5a0d5006 N°4751 - Fix crash when disabling newsroom in configuration 2022-02-04 22:58:48 +01:00
acognet
84280a3b5f N°4530 - Bug with OQL and profiles. 2022-02-04 16:21:53 +01:00
Molkobain
e3bce622e5 Dashboard: Add "input" event to properties listeners for real-time updates 2022-02-02 21:29:35 +01:00
Molkobain
ef9392a8d5 Fix icon selection misalignment in edition 2022-02-02 21:10:34 +01:00
Molkobain
15087ab848 N°592 - Fix ModelFactory::GetField() always failing as $aLoadedClasses is never filled 2022-02-02 19:06:38 +01:00
Molkobain
7bb7445c91 N°4482 - Small refacto
- SCSS partial rule should target only the concerned elements
- Improve PHPDoc
2022-02-02 16:47:15 +01:00
Molkobain
6a4ce3c3b1 Fix regression from c3a2713bb 2022-02-02 10:54:01 +01:00
Stephen Abello
7df27de5c1 N°4674 Fix code highlighter calls 2022-02-02 10:35:50 +01:00
Pierre Goiffon
b4fc647845 N°4714 Rename \utils::GetItopVersionWikiSyntax to GetCoreVersionWikiSyntax
Will avoid confusion between core or product version !
2022-02-01 15:40:43 +01:00
Pierre Goiffon
de053eed72 N°4714 Update iTopXmlVersionIntegrationTest::testItopXmlVersion to use new constant 2022-02-01 15:27:57 +01:00
Pierre Goiffon
17612f88d3 N°4714 utils version method refactoring
- removes utils::GetItopPatchVersion and GetItopMinorVersion : unused and badly named :/
- GetItopVersionWikiSyntax now uses core version constant
- iTopModulesPhpVersionIntegrationTest::testiTopModulesPhpVersion now uses ITOP_CORE_VERSION constant
2022-02-01 15:24:56 +01:00
Pierre Goiffon
e14845728c Prepare 2.7.7 2022-02-01 15:19:10 +01:00
Pierre Goiffon
4e80fc0f76 N°4624 Remove processIsolation flag from postBuild tests
Was done in standard test suite (test/phpunit.xml.dist) with 6bf25f90
2022-02-01 14:50:33 +01:00
Pierre Goiffon
fcfcf85e0d N°4714 fix constant version usages in utils methods 2022-02-01 11:39:57 +01:00
Pierre Goiffon
f0715baf7d N°4714 move constant from core/config.class.inc.php to approot.inc.php
see N°4406
2022-02-01 11:39:35 +01:00
Molkobain
2733e7966f N°4731 - Restore "data-value-raw" HTML metadata on attributes in object details 2022-01-31 20:03:02 +01:00
Eric Espie
52327d1086 Migrate default theme test-red 2022-01-31 17:50:54 +01:00
Eric Espie
81cf3df5e2 Migrate default theme test-red 2022-01-31 17:35:26 +01:00
Pierre Goiffon
45b5c39af7 N°3129 PHP 8.0 compat : code review modifications
Many thanks @Molkobain & @Hipska !
2022-01-31 16:41:35 +01:00
Eric Espie
4463e91d85 N°4569 - Fix unit tests 2022-01-31 16:41:01 +01:00
Eric Espie
ce87bf9e23 N°4569 - Fix bad alteration on trashed nodes 2022-01-31 16:23:01 +01:00
Pierre Goiffon
dbc3da7bc3 N°3129 Remove twig-bundle Test dir
Thanks to iTopComposerTest::testNoDeniedDirIsPresentForNow :o)
2022-01-28 17:25:55 +01:00
Pierre Goiffon
ebc9fa684a N°3129 PHP 8.0 compat: Fix "Private methods cannot be final as they are never overridden by other classes"
Was breaking setup ajax compilation
Fixed in:
* \SetupUtils::Log
* \MetaModel::SetUniquenessRuleRootClass
2022-01-28 17:01:07 +01:00
Pierre Goiffon
606bdc1909 N°3129 PHP 8.0 compat: Fix "Access level to MFElement::ReplaceWith() must be public (as in class DOMElement)" 2022-01-28 17:01:07 +01:00
Pierre Goiffon
7495fb9af4 N°3129 PHP 8.0 compat: Fix "Deprecated: Required parameter ... follows optional parameter ..." in Twig
Update symfony/twig-bundle from 3.4.36 to 3.4.47
2022-01-28 17:01:07 +01:00
Pierre Goiffon
75dbad7406 N°3129 PHP 8.0 compat: Fix "Deprecated: Required parameter ... follows optional parameter ..."
* \SQLObjectQuery::PrepareSingleTable
* \HistoryBlock::GetRenderContent
* \MenuBlock::GetRenderContent
* \UILinksWidgetDirect::DisplayAsBlock
* \UILinksWidgetDirect::Display
* \UILinksWidgetDirect::DisplayEditInPlace
* \UIExtKeyWidget::AutoComplete
* \UIExtKeyWidget::DisplayFromAttCode
2022-01-28 17:01:07 +01:00
acognet
c95064b76d N°4433 - Fix "date_format" TWIG filter not working for date without time 2022-01-28 14:52:44 +01:00
acognet
f0933eaf1e N°4446 - Attachments: deleted file re-appear 2022-01-28 10:34:53 +01:00
Eric Espie
b9ea7d4913 N°4569 - Fix collision between existing nodes and saved ones 2022-01-27 17:42:52 +01:00
Stephen Abello
9c75a705f3 N°4570 Harmonize inputs font size/weight 2022-01-27 16:31:33 +01:00
Pierre Goiffon
3381c085f4 💡 N°4714 fix phpdoc 2022-01-27 16:15:57 +01:00
acognet
b89d181125 N°4634 - Missing class icone in predefined search 2022-01-27 14:47:24 +01:00
Pierre Goiffon
c3a2713bba N°4725 Fix \DeprecatedCallsLog::NotifyDeprecatedFile doesn't catch ConfigException 2022-01-27 09:25:28 +01:00
Pierre Goiffon
99b73fe1ee 🐛 N°4714 Restore ITOP_VERSION_NAME constant
Was removed by mistake on merge (627c0070)
2022-01-27 08:57:19 +01:00
Stephen Abello
151f42ceef N°4626 Fix backup error message not showing 2022-01-26 16:14:41 +01:00
Pierre Goiffon
627c0070c1 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/config.class.inc.php
#	setup/itopdesignformat.class.inc.php
2022-01-26 16:07:34 +01:00
Eric Espie
3a56824cde N°4569 - Fix unit tests names 2022-01-26 16:02:07 +01:00
Pierre Goiffon
9b6f7d94f4 N°4714 Handle ITOP_CORE_VERSION update in .make/release/update-versions.php 2022-01-26 15:45:10 +01:00
Eric Espie
9a6d40e9db N°4569 - Fix unit tests 2022-01-26 15:30:03 +01:00
Pierre Goiffon
64e8aa5fee N°4714 New ITOP_CORE_VERSION constant
See following constants PHPDoc for information :
* core/config.class.inc.php ITOP_VERSION
* core/config.class.inc.php ITOP_CORE_VERSION
* setup/itopdesignformat.class.inc.php ITOP_DESIGN_LATEST_VERSION
2022-01-26 15:19:29 +01:00
Eric Espie
a839b1c4ae N°4569 - Fix unit tests 2022-01-26 15:14:42 +01:00
Eric Espie
b58df7150f N°4634 - Fix typo 2022-01-26 14:43:30 +01:00
Eric Espie
1cd230a543 N°4569 - Fix module XML migration during setup (fix _delta and list ids) 2022-01-26 14:39:47 +01:00
Eric Espie
fc47e031b6 N°4569 - Fix module XML migration during setup 2022-01-26 14:03:44 +01:00
Pierre Goiffon
477128ad53 💡 N°4023 More phpdoc on \DBObjectSearch::AddCondition 2022-01-26 13:58:49 +01:00
acognet
3b4ba2aafd N°4634 - Missing class icone in predefined search 2022-01-26 12:51:39 +01:00
acognet
70f67068f4 N°4553 - Fix label size for "Greater/equals" in search for numeric attributes 2022-01-26 11:07:41 +01:00
acognet
4fec344799 N°4550 - Fix scroll bar in search for date attribute 2022-01-26 11:05:38 +01:00
Molkobain
cc5f7608e3 N°3861 - Dictionaries: Replace usages of hardcoded "iTop" string by ITOP_APPLICATION_SHORT constant 2022-01-26 10:28:47 +01:00
Eric Espie
468de06fe1 N°4569 - Fix deletion of light-grey theme for iTop 2.7 and older 2022-01-26 10:00:48 +01:00
acognet
aa20289dfe N°4576 - issue with search date widget 2022-01-25 17:14:33 +01:00
acognet
4449fdbbc5 N°4311 - Bubble caselog : differences between console and portal for Agent Name 2022-01-25 15:35:52 +01:00
Stephen Abello
04a690caff N°4696 Improve spacing between a fieldset and a field 2022-01-25 15:26:13 +01:00
Molkobain
0156eb0dda Activity panel: Fix missing space in HTML markup 2022-01-25 13:29:43 +01:00
acognet
e8448332f4 N°4529 - Object list: Count in header not updated when refreshing through the icon 2022-01-25 10:24:44 +01:00
acognet
e8e6ceb29e N°4529 - Object list: Count in header not updated when refreshing through the icon 2022-01-25 08:56:43 +01:00
Molkobain
1f42f897d8 N°4667 - Remove call to tooltip function 2022-01-25 08:55:49 +01:00
Pierre Goiffon
aa66bec783 💡 Add comment for the timezone config parameter 2022-01-24 15:54:42 +01:00
Pierre Goiffon
1da52a8517 Revert "dbtools report.php : compatibility with CLI + symlinks"
Woops pushed by mistake, sorry :/

This reverts commit cbd2181862.
2022-01-24 14:22:01 +01:00
Pierre Goiffon
cbd2181862 dbtools report.php : compatibility with CLI + symlinks 2022-01-24 14:16:41 +01:00
Molkobain
102528195b Fix typo, thanks to @jbostoen 2022-01-23 16:10:42 +01:00
Molkobain
7def094291 N°4705 - Fix newsroom messages not formatted correctly 2022-01-23 15:52:16 +01:00
acognet
ffb3edced5 N°4668 - Remove all deprecated function from iTopExtensions - ajax_page 2022-01-21 15:20:25 +01:00
acognet
17e8c53236 demove deprecated functions : replace ajax_page by AjaxPage 2022-01-21 11:52:02 +01:00
acognet
910638d93f N°4667 - Remove call to tooltip function 2022-01-21 11:51:59 +01:00
acognet
d005ff0099 Remove deprecated functions : replace ormLinkSet::AddObject by ormLinkSet::AddItem 2022-01-21 11:51:57 +01:00
acognet
4fdf8803a5 Remove deprecied function $oField->Render replaced by $oField->RenderExpression() 2022-01-21 11:51:56 +01:00
acognet
06af788480 N°4622 - Advanced search: Fix dictionaries being retrieved by XHR calls 2022-01-21 11:51:54 +01:00
Molkobain
7aa1719514 N°4701 - Fix meta-enums labels being double encoded when displayed 2022-01-21 11:12:53 +01:00
Pierre Goiffon
81c0951c2a N°4694 Fix ServiceSubcategory icon path in datamodel.itop-service-mgmt-provider.xml
Many thanks to hong on SourceForge (https://sourceforge.net/p/itop/tickets/2018/)
2022-01-19 09:27:14 +01:00
Molkobain
89ecdeb13b Code cleanup: Add missing quotes in selector 2022-01-17 19:03:05 +01:00
Pierre Goiffon
c6211cde09 Revert REST API init objects array (#231)
We didn't anticipated this was causing the REST API response to be changed for all consumers :
- before PR `"objects":null`
- after `"objects":[]`

We don't want that :/

We will instead fix collector-base (object of another PR, see #231)

This reverts commit 7243da3576.
This reverts commit 0940741568.
2022-01-17 18:38:33 +01:00
acognet
739001eca4 Fix PHP comments 2022-01-17 09:18:36 +01:00
Pierre Goiffon
7243da3576 💚 Fix RestTest
When no objects to return, since #231 we are now getting `[]` instead of `null`
2022-01-17 08:24:10 +01:00
acognet
c9d547030f Fix Get filter in DoAddObject 2022-01-14 15:34:24 +01:00
acognet
4923ac7015 N°4482 - Polishing : Export page 2022-01-14 11:52:55 +01:00
acognet
c1c264d6d8 Fix Get filter in DoAddObject 2022-01-14 11:03:19 +01:00
Thomas Casteleyn
0940741568 RestResultWithObjects : properly init objects array (#231) 2022-01-14 11:01:00 +01:00
annProg
041a938fc0 🐛 fix notice log when upload svg image 2022-01-14 10:24:37 +01:00
Stephen Abello
839048fab2 Merge branch 'support/2.7' into support/3.0 2022-01-14 10:22:48 +01:00
Stephen Abello
4180a41f27 N°4652 Better error message when XML node define fails from delta (#256)
N°4652 Add more details when trying to define an already existing XML node
Co-authored-by: Molkobain <guillaume.lajarige@combodo.com>
Co-authored-by: Pierre Goiffon <pierre.goiffon@combodo.com>
2022-01-14 10:20:46 +01:00
Stephen Abello
8ada56fc53 N°4652 Better error message when XML node define fails from delta (#256)
N°4652 Add more details when trying to define an already existing XML node
Co-authored-by: Molkobain <guillaume.lajarige@combodo.com>
Co-authored-by: Pierre Goiffon <pierre.goiffon@combodo.com>
2022-01-14 10:18:02 +01:00
Pierre Goiffon
6c5ca614e0 🔧 phpunit.xml restoring old style
Not enough time to work on this right now :(
Will be done with N°4660
2022-01-13 14:14:59 +01:00
Pierre Goiffon
4ddee0b624 🔧 phpunit.xml setup at the end
\Combodo\iTop\Test\UnitTest\Synchro\DataSynchroTest::RunDataSynchroTest was generating a ConfigException (file exists but cannot be read)
2022-01-13 13:50:39 +01:00
Pierre Goiffon
135ddbf37d Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	test/phpunit.xml.dist
2022-01-13 13:36:09 +01:00
Pierre Goiffon
a43adcd202 🔧 phpunit.xml comment OQL better
Was executing on Jenkins :(
2022-01-13 13:11:26 +01:00
Pierre Goiffon
e8e170fb06 🔧 phpunit.xml reorder testSuites again 2022-01-13 13:05:42 +01:00
Pierre Goiffon
5ac5d649aa 🔧 Try again : reorder test suites for better readability
Jenkins should now be fixed
2022-01-13 12:15:12 +01:00
acognet
ec0c98bb0f N°4482 - Polishing : Export page 2022-01-13 10:52:18 +01:00
Pierre Goiffon
decb802df4 Revert "🔧 Reorder test suites for better readability"
This reverts commit cacc3a3085.
2022-01-13 09:48:07 +01:00
Pierre Goiffon
cacc3a3085 🔧 Reorder test suites for better readability 2022-01-13 09:42:21 +01:00
Pierre Goiffon
0fd2ea6a47 🎨 phpunit.xml code formatting 2022-01-13 09:42:21 +01:00
Molkobain
ab7e73ef9b Unit tests: Fix typo in tests suite name 2022-01-12 15:56:42 +01:00
Molkobain
31e7a5383c Unit tests: Activate tests that were never ran... 🥶 2022-01-12 15:31:40 +01:00
Molkobain
64afa07ff5 Unit tests: Fix themes compilation test 2022-01-12 15:14:05 +01:00
Molkobain
656bbfe46d Update precompiled themes 2022-01-12 15:13:39 +01:00
Pierre Goiffon
426f275c03 💡 Add additional phpdoc to \DBBackup::GetMysqlCliTlsOptions 2022-01-12 11:21:21 +01:00
Pierre Goiffon
b55ba2ac7f Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/cmdbsource.class.inc.php
#	core/log.class.inc.php
#	test/setup/iTopDesignFormat/iTopDesignFormatTest.php
2022-01-12 09:56:16 +01:00
Pierre Goiffon
693a861e7d ♻️ Refactor DBBackuptest
Split each test in a dedicated method
2022-01-12 09:42:57 +01:00
Pierre Goiffon
0ee6c60e94 Fix DBBackupTest (again :/)
Was working on Windows but not on Linux...
2022-01-12 09:12:04 +01:00
Pierre Goiffon
a663e9fded Fix DBBackupTest
DB connection dependency was added in a222ead4 (N°2336) in \DBBackup::GetMysqlCliTlsOptions but test wasn't updated accordingly :/^

The test wasn't ran on Jenkins until b11bf308, so we saw the regression only yesterday :(

This is now fixed ! 🥳
2022-01-12 09:00:26 +01:00
Pierre Goiffon
b3bf516b20 💡 Fix PHPDoc for \DBBackup::GetMysqlCliTlsOptions 2022-01-12 08:24:28 +01:00
Molkobain
c2408b74cd Unit tests: Fix invalid/duplicate class name 2022-01-11 18:13:13 +01:00
Pierre Goiffon
6855c2f83a N°4624 restore backupGlobals to default 2022-01-11 17:29:32 +01:00
Molkobain
b11bf30881 Unit tests: Activate tests that were never ran... 🥶
Note that testGetMysqlCliTlsOptions will fail
2022-01-11 15:49:21 +01:00
Molkobain
64736f1463 Fix unit test provider 2022-01-11 15:48:45 +01:00
Pierre Goiffon
930b224ca2 💡 N°4624 phpdoc for ItopDataTestCase 2022-01-11 15:36:40 +01:00
acognet
c87de1024d N°4479 - Impact analysis : Display and apply filter before display impact analysis graphical 2022-01-11 08:32:58 +01:00
acognet
24e6840a8b N°4647 - Dictionaries for Polish not up to date 2022-01-10 18:07:30 +01:00
acognet
06ed048983 N°4448 - Enabled x icon on Organisation filter box even if there is no change on filter 2022-01-10 17:53:26 +01:00
acognet
937313495d Fix checkbox in datatable. 2022-01-10 17:53:25 +01:00
Pierre Goiffon
9493e31a5d 💡 N°4558 Add PHPDoc to document that\LogChannels::CMDB_SOURCE constant was added in 3.0.0 2022-01-10 17:11:13 +01:00
Pierre Goiffon
92b61c7491 N°4558 Rename \LogChannels::CMDBSOURCE to CMDB_SOURCE to match existing constant in support/3.0 branch 2022-01-10 17:09:43 +01:00
Pierre Goiffon
3a4c4cd33d N°4624 Fix SessionTest 2022-01-10 16:50:02 +01:00
Pierre Goiffon
9aa399894c N°4624 Add processIsolation PHPUnit option to all tests implementing ItopDataTestCase 2022-01-10 16:41:26 +01:00
Pierre Goiffon
bde5dc825d 💡 Fix iTopModulesPhpVersionIntegrationTest phpdoc 2022-01-10 16:35:48 +01:00
Pierre Goiffon
8578d18e7f Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/cmdbsource.class.inc.php
#	core/config.class.inc.php
#	core/displayablegraph.class.inc.php
#	core/log.class.inc.php
#	datamodels/2.x/itop-config-mgmt/dictionaries/tr.dict.itop-config-mgmt.php
#	datamodels/2.x/itop-knownerror-mgmt/dictionaries/tr.dict.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-service-mgmt/dictionaries/tr.dict.itop-service-mgmt.php
#	datamodels/2.x/itop-tickets/tr.dict.itop-tickets.php
#	datamodels/2.x/itop-welcome-itil/tr.dict.itop-welcome-itil.php
#	dictionaries/tr.dictionary.itop.core.php
#	dictionaries/tr.dictionary.itop.ui.php
#	pages/UI.php
#	setup/itopdesignformat.class.inc.php
#	test/core/LogAPITest.php
#	test/integration/iTopModulesPhpVersionChecklistTest.php
#	test/postbuild_integration/SetupCssIntegrityChecklistTest.php
#	test/postbuild_integration/iTopModuleXmlInstallationChecklistTest.php
#	test/status/StatusTest.php
2022-01-10 16:15:00 +01:00
acognet
9b0e55210d N°4349 - Drop-down mandatory template field documented still required in modification 2022-01-10 15:08:41 +01:00
Pierre Goiffon
e530cbb4f2 N°4624 Restore processIsolation on tests which actually need it
Warning, one symptom was having the CI returning an empty phpunit.results.xml !!
2022-01-07 17:25:18 +01:00
Pierre Goiffon
ddb8378fe6 N°4624 align phpunit annotations
Remove processIsolation when not needed
When needed, make sure to have also their counterpart (preserveGlobalState and backupGlobals)
2022-01-07 15:20:34 +01:00
Pierre Goiffon
47db23d91c 💚 N°4624 Fix other tests after global processIsolation was disabled in 6bf25f90 2022-01-07 12:44:08 +01:00
Pierre Goiffon
fc1f701bf6 💚 N°4624 TransactionsTest : add process isolation
Was global before 6bf25f90
2022-01-07 12:34:09 +01:00
Pierre Goiffon
ece31855af :bulb N°4619 table-selectable-lines.js fix missing doc comment 2022-01-07 12:08:35 +01:00
Pierre Goiffon
d57ef77758 N°4619 table-selectable-lines.js : handles better all click types
* Set one click handler instead of two
* Remove the now useless test on input:radio in updateLines()
* If clicking in a cell that have one input:radio or input:checkbox, and isn't located in the first column :
  - click on the cell input
  - don't select the line
2022-01-07 12:04:33 +01:00
Stephen Abello
365c7bb89e N°4397 Update Turkish translations 2022-01-07 11:09:51 +01:00
Pierre Goiffon
bf2c4dee1b 💡 N°4619 Document table-selectable-lines.js 2022-01-07 09:05:02 +01:00
acognet
11b812b5fc N°4564 - Tooltip for switching from standard dashboard to custo dashboard not refreshed 2022-01-06 15:09:48 +01:00
Pierre Goiffon
b073e4385c 💡 Document versions constants (#255)
Clarify ITOP_VERSION and ITOP_DESIGN_LATEST_VERSION uses
2022-01-06 14:49:34 +01:00
acognet
c37c46a4a8 N°4619 - Strange colors on selected lines on a list 2022-01-06 14:47:05 +01:00
Pierre Goiffon
f592d94af3 iTopModuleXmlInstallationChecklistTest : fix phpdoc, remove process isolation annotation, remove inspection warnings 2022-01-04 18:00:23 +01:00
Pierre Goiffon
f9359431fe 💡 N°4558 Add PHPDoc 2022-01-03 12:21:55 +01:00
Pierre Goiffon
25e560fdaa N°4558 Fix possible PHP notice in \CMDBSource::StartTransaction 2021-12-31 16:34:19 +01:00
Pierre Goiffon
0ce805b192 \MFCompilerTest::testCompileThemes : fix calling protected method 2021-12-31 15:09:18 +01:00
Pierre Goiffon
6bf25f90bc Tests : remove global process isolation
Is done in ItopDataTestCase using annotation
Other tests (like the one extending ItopTestCase) won't use isolation anymore
2021-12-29 15:31:25 +01:00
Pierre Goiffon
30d36fca81 N°4515 Fix function header for \Config::GetDefault 2021-12-29 14:30:19 +01:00
Pierre Goiffon
ffd0bbb1a4 N°4515 Fix default validation pattern for AttributeURL (#249)
URL containing ":" in their path were rejected. This caused problems with some URL from Alfresco or Sharepoint...
The default regexp used by AttributeURL was updated to avoid this.
Warning, check your config to see if you have any custom regexp configured (`url_validation_pattern` config parameter) !

Also a test was added to document the default regexp.
2021-12-29 11:43:07 +01:00
acognet
3db20e8028 N°4479 - Impact analysis : Display and apply filter before display impact analysis graphical 2021-12-23 16:53:15 +01:00
acognet
ed12f98075 Fix warning PHP seen in N°3702 - Migrate module to new UIBlock system : Follow-up forms without authentication 2021-12-23 13:19:18 +01:00
acognet
19eef5bd72 N°4578 - Dict::CloneString replace entry if already exists 2021-12-23 13:19:18 +01:00
Pierre Goiffon
7b2bcd1055 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	css/css-variables.scss
#	datamodels/2.x/authent-cas/module.authent-cas.php
#	datamodels/2.x/authent-external/module.authent-external.php
#	datamodels/2.x/authent-ldap/module.authent-ldap.php
#	datamodels/2.x/authent-local/module.authent-local.php
#	datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/module.itop-attachments.php
#	datamodels/2.x/itop-backup/module.itop-backup.php
#	datamodels/2.x/itop-bridge-virtualization-storage/module.itop-bridge-virtualization-storage.php
#	datamodels/2.x/itop-change-mgmt-itil/module.itop-change-mgmt-itil.php
#	datamodels/2.x/itop-change-mgmt/module.itop-change-mgmt.php
#	datamodels/2.x/itop-config-mgmt/module.itop-config-mgmt.php
#	datamodels/2.x/itop-config/module.itop-config.php
#	datamodels/2.x/itop-core-update/module.itop-core-update.php
#	datamodels/2.x/itop-datacenter-mgmt/module.itop-datacenter-mgmt.php
#	datamodels/2.x/itop-endusers-devices/module.itop-endusers-devices.php
#	datamodels/2.x/itop-files-information/module.itop-files-information.php
#	datamodels/2.x/itop-full-itil/module.itop-full-itil.php
#	datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
#	datamodels/2.x/itop-incident-mgmt-itil/module.itop-incident-mgmt-itil.php
#	datamodels/2.x/itop-knownerror-mgmt/module.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-portal-base/module.itop-portal-base.php
#	datamodels/2.x/itop-portal/module.itop-portal.php
#	datamodels/2.x/itop-problem-mgmt/module.itop-problem-mgmt.php
#	datamodels/2.x/itop-profiles-itil/module.itop-profiles-itil.php
#	datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php
#	datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php
#	datamodels/2.x/itop-service-mgmt-provider/module.itop-service-mgmt-provider.php
#	datamodels/2.x/itop-service-mgmt/module.itop-service-mgmt.php
#	datamodels/2.x/itop-sla-computation/module.itop-sla-computation.php
#	datamodels/2.x/itop-storage-mgmt/module.itop-storage-mgmt.php
#	datamodels/2.x/itop-tickets/module.itop-tickets.php
#	datamodels/2.x/itop-virtualization-mgmt/module.itop-virtualization-mgmt.php
#	datamodels/2.x/itop-welcome-itil/module.itop-welcome-itil.php
#	datamodels/2.x/version.xml
2021-12-23 10:05:18 +01:00
Pierre Goiffon
108c1fcb2b iTopXmlVersionIntegrationTest : more details in test feedback 2021-12-23 09:56:12 +01:00
acognet
ced29dea8e Change iTop version to 3.0.1-dev 2021-12-22 16:03:58 +01:00
odain
20a07d61c6 N°4541 - no failure exit code captured when csv a import fails in CLI mode 2021-12-20 16:13:10 +01:00
Pierre Goiffon
b190d0e385 Prepare 2.7.6 version 2021-12-14 16:54:42 +01:00
2222 changed files with 177388 additions and 35187 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

48
.gitattributes vendored Normal file
View File

@@ -0,0 +1,48 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.bash text eol=lf
*.bat text eol=lf
*.cmd text eol=lf
*.css text eol=lf
*.scss text eol=lf
*.dist text eol=lf
.editorconfig text eol=lf
.env* text eol=lf
.gitignore text eol=lf
.htaccess text eol=lf
*.htm text eol=lf
*.html text eol=lf
*.ini text eol=lf
*.js text eol=lf
*.json text eol=lf
*.lock text eol=lf
*.md text eol=lf
*.php text eol=lf
*.php_cs text eol=lf
*.php8 text eol=lf
*.plex text eol=lf
*.sh text eol=lf
*.svg text eol=lf
*.ts text eol=lf
*.twig text eol=lf
*.txt text eol=lf
*.xml text eol=lf
*.xsd text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpeg binary
*.jpg binary
*.gif binary
*.ico binary
*.pdf binary
*.swf binary
*.zip binary
*.ttf binary
*.woff binary
*.woff2 binary

4
.gitignore vendored
View File

@@ -45,9 +45,13 @@ test/vendor/*
!/log/index.php
!/log/web.config
# PHPUnit cache file
/test/.phpunit.result.cache
# Jetbrains
/.idea/**
!/.idea/IntelliLang.xml
# doc. generation
/.doc/vendor

15
.idea/IntelliLang.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="LanguageInjectionConfiguration">
<injection language="InjectablePHP" injector-id="xml">
<display-name>iTop - Class method code</display-name>
<place><![CDATA[xmlTag().withLocalName(string().equalTo("code"))]]></place>
<xpath-condition>name(..) = 'method' and count(/itop_design) = 1</xpath-condition>
</injection>
<injection language="InjectablePHP" injector-id="xml">
<display-name>iTop - Snippet code</display-name>
<place><![CDATA[xmlTag().withLocalName(string().equalTo("snippet"))]]></place>
<xpath-condition>name(..) = 'snippets' and count(/itop_design) = 1</xpath-condition>
</injection>
</component>
</project>

View File

@@ -36,22 +36,38 @@ clearstatcache();
$oiTopComposer = new iTopComposer();
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
echo "\n";
foreach ($aDeniedButStillPresent as $sDir)
{
if (! preg_match('#[tT]ests?/?$#', $sDir))
if (false === iTopComposer::IsTestDir($sDir))
{
echo "\nfound INVALID denied test dir: '$sDir'\n";
echo "ERROR found INVALID denied test dir: '$sDir'\n";
throw new \Exception("$sDir must end with /Test/ or /test/");
}
try
{
SetupUtils::rrmdir($sDir);
echo "Remove denied test dir: '$sDir'\n";
}
catch (\Exception $e)
{
echo "\nFAILED to remove denied test dir: '$sDir'\n";
if (false === file_exists($sDir)) {
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
continue;
}
try {
SetupUtils::rrmdir($sDir);
echo "OK Remove denied test dir: '$sDir'\n";
}
catch (\Exception $e) {
echo "\nFAILED to remove denied test dir: '$sDir'\n";
}
}
$aAllowedAndDeniedDirs = array_merge(
$oiTopComposer->ListAllowedTestDir(),
$oiTopComposer->ListDeniedTestDir()
);
$aExistingDirs = $oiTopComposer->ListAllTestDir();
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
if (false === empty($aMissing)) {
echo "Some new tests dirs exists !\n"
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
.' List of dirs:'."\n".var_export($aMissing, true);
}

View File

@@ -26,6 +26,7 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php');
$aFilesUpdaters = array(
new iTopVersionFileUpdater(),
new DatamodelsModulesFiles(),
new ConstantFileUpdater('ITOP_CORE_VERSION', 'approot.inc.php'),
);
if (count($argv) === 1)

View File

@@ -69,6 +69,40 @@ abstract class AbstractSingleFileVersionUpdater extends FileVersionUpdater
}
}
/**
* @since 2.7.7 3.0.1 3.1.0 N°4714
*/
class ConstantFileUpdater extends AbstractSingleFileVersionUpdater {
/** @var string */
private $sConstantName;
/**
* @param $sConstantName constant to search, for example `ITOP_CORE_VERSION`
* @param $sFileToUpdate file containing constant definition
*/
public function __construct($sConstantName, $sFileToUpdate)
{
$this->sConstantName = $sConstantName;
parent::__construct($sFileToUpdate);
}
/**
* @inheritDoc
*/
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
{
$sConstantSearchPattern = <<<REGEXP
/define\('{$this->sConstantName}', ?'[^']+'\);/
REGEXP;
return preg_replace(
$sConstantSearchPattern,
"define('{$this->sConstantName}', '{$sVersionLabel}');",
$sFileContent
);
}
}
class iTopVersionFileUpdater extends AbstractSingleFileVersionUpdater
{
public function __construct()

View File

@@ -111,9 +111,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
Emoji examples :
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)).
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
Emoji examples :
* 🌐 `:globe_with_meridians:` for translations
* 🎨 `:art:` when improving the format/structure of the code
* ⚡️ `:zap:` when improving performance

View File

@@ -1,13 +1,11 @@
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
<img src="https://www.combodo.com/logos/logo-itop.svg">
<img src="https://www.combodo.com/logos/logo-itop-baseline.svg" width=350>
</a></p>
# iTop - ITSM & CMDB
iTop stands for *IT Operations Portal*.
It is a complete open source, ITIL, web based service management tool including a fully customizable CMDB, a helpdesk system and a document management tool.
iTop also offers mass import tools and web services to integrate with your IT
iTop stands for IT Operations Portal. It is a complete open source and web based IT service management platform including a fully customizable CMDB, a helpdesk system and a document management tool. It is ITIL compliant and easily customizable and extensible thanks to a high number of adds-on and web services to integrate with your IT.
iTop also offers mass import tools to help you being even more efficient.
## Features
- Fully configurable [Configuration Management (CMDB)][10]
@@ -78,18 +76,19 @@ We would like to give a special thank you 🤗 to the people from the community
- Alves, David
- Beck, Pedro
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
- Bilger, Jean-François
- Bostoen, Jeffrey (a.k.a @jbostoen)
- Bostoen, Jeffrey (a.k.a [@jbostoen](https://www.github.com/jbostoen))
- Cardoso, Anderson
- Cassaro, Bruno
- Casteleyn, Thomas (a.k.a @Hipska)
- Casteleyn, Thomas (a.k.a [@Hipska](https://www.github.com/Hipska))
- Castro, Randall Badilla
- Colantoni, Maria Laura
- Couronné, Guy
- Dvořák, Lukáš
- Goethals, Stefan
- Gumble, David
- Kaltefleiter, Lars (a.k.a @larhip)
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
- Khamit, Shamil
- Kincel, Martin
- Konečný, Kamil
@@ -98,12 +97,12 @@ We would like to give a special thank you 🤗 to the people from the community
- Lazcano, Federico
- Lucas, Jonathan
- Malik, Remie
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
- Raenker, Martin
- Rosenke, Stephan
- Seki, Shoji
- Shilov, Vladimir
- Stukalov, Ilya (a.k.a @ilya-stukalov)
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
- Tulio, Marco
- Turrubiates, Miguel
@@ -114,6 +113,7 @@ We would like to give a special thank you 🤗 to the people from the community
- DudekArtur
- Karkoff1212
- Laura
- nv35
- Purple Grape
- Schlobinux
- theBigOne

View File

@@ -10,7 +10,7 @@ define('PORTAL_PROFILE_NAME', 'Portal user');
class UserRightsBaseClassGUI extends cmdbAbstractObject
{
// Whenever something changes, reload the privileges
protected function AfterInsert()
{
UserRights::FlushPrivileges();
@@ -59,7 +59,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
}
protected static $m_aCacheProfiles = null;
public static function DoCreateProfile($sName, $sDescription)
{
if (is_null(self::$m_aCacheProfiles))
@@ -71,7 +71,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
{
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
}
}
}
$sCacheKey = $sName;
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
@@ -82,10 +82,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
$oNewObj->Set('name', $sName);
$oNewObj->Set('description', $sDescription);
$iId = $oNewObj->DBInsertNoReload();
self::$m_aCacheProfiles[$sCacheKey] = $iId;
self::$m_aCacheProfiles[$sCacheKey] = $iId;
return $iId;
}
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
{
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
@@ -102,7 +102,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
}
}
function DoShowGrantSumary($oPage)
{
if ($this->GetRawName() == "Administrator")
@@ -114,7 +114,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
// Note: for sure, we assume that the instance is derived from UserRightsProfile
$oUserRights = UserRights::GetModuleInstance();
$aDisplayData = array();
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
{
@@ -123,12 +123,12 @@ class URP_Profiles extends UserRightsBaseClassGUI
{
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
if ($bGrant === true)
{
{
$aStimuli[] = '<span title="'.$sStimulusCode.': '.htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8').'">'.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').'</span>';
}
}
$sStimuli = implode(', ', $aStimuli);
$aDisplayData[] = array(
'class' => MetaModel::GetName($sClass),
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
@@ -140,7 +140,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
'stimuli' => $sStimuli,
);
}
$aDisplayConfig = array();
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
@@ -198,7 +198,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
* @return integer Flags: the binary combination of the flags applicable to this attribute
*/
*/
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
{
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
@@ -404,7 +404,7 @@ class URP_UserOrg extends UserRightsBaseClassGUI
{
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
$oUser = UserRights::GetUserObject();
$oUser = UserRights::GetUserObject();
$oAddon = UserRights::GetModuleInstance();
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
if (count($aOrgs) > 0)
@@ -528,7 +528,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
$oSearch->AllowAllData();
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
$oSearch->AddConditionExpression($oCondition);
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
while ($oUserOrg = $oUserOrgSet->Fetch())
{
@@ -738,8 +738,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
// load and cache permissions for the current user on the given class
//
$iUser = $oUser->GetKey();
$aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
if (is_array($aTest)) return $aTest;
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])){
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
if (is_array($aTest)) return $aTest;
}
$sAction = self::$m_aActionCodes[$iActionCode];
@@ -905,8 +907,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
/**
* Find out which attribute is corresponding the the dimension 'owner org'
* returns null if no such attribute has been found (no filtering should occur)
*/
* returns null if no such attribute has been found (no filtering should occur)
*/
public static function GetOwnerOrganizationAttCode($sClass)
{
$sAttCode = null;

View File

@@ -1402,11 +1402,11 @@ interface iBackofficeDictEntriesPrefixesExtension
/**
* Implement this interface to add content to any enhanced portal page
*
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
*
* @api
* @package Extensibility
* @since 2.4.0
*
* @since 2.4.0 interface creation
* @since 2.7.0 change method signatures due to Silex to Symfony migration
*/
interface iPortalUIExtension
{
@@ -1479,7 +1479,11 @@ interface iPortalUIExtension
}
/**
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
*
* @api
* @package Extensibility
* @since 2.4.0
*/
abstract class AbstractPortalUIExtension implements iPortalUIExtension
{

View File

@@ -341,13 +341,17 @@ JS
}
/**
* Important: For compatibility reasons, this function still allows to manipulate the $oPage. In that case, markup will be put above the real header of the panel.
* To insert something IN the panel, we now need to add UIBlocks in either the "subtitle" or "toolbar" sections of the array that will be returned.
* @param \WebPage $oPage Warning, since 3.0.0 this parameter was kept for compatibility reason. You shouldn't write directly on the page!
* When writing to the page, markup will be put above the real header of the panel.
* To insert something IN the panel, we now need to add UIBlocks in either the "subtitle" or "toolbar" sections of the array that will be returned.
* @param bool $bEditMode Deprecated parameter in iTop 3.0.0, use {@see GetDisplayMode()} and ENUM_DISPLAY_MODE_* constants instead
*
* @param \WebPage $oPage
* @param bool $bEditMode Note that this parameter is no longer used in this method. Use {@see static::$sDisplayMode} instead
*
* @return array UIBlocks to be inserted in the "subtitle" and the "toolbar" sections of the ObjectDetails block. eg. ['subtitle' => [<BLOCK1>, <BLOCK2>], 'toolbar' => [<BLOCK3>]]
* @return array{
* subtitle: \Combodo\iTop\Application\UI\Base\UIBlock[],
* toolbar: \Combodo\iTop\Application\UI\Base\UIBlock[]
* }
* blocks to be inserted in the "subtitle" and the "toolbar" sections of the ObjectDetails block.
* eg. ['subtitle' => [<BLOCK1>, <BLOCK2>], 'toolbar' => [<BLOCK3>]]
*
* @throws \ApplicationException
* @throws \ArchivedObjectException
@@ -356,7 +360,10 @@ JS
* @throws \MySQLException
* @throws \OQLException
*
* @since 3.0.0 $bEditMode is deprecated and no longer used
* @since 3.0.0 $bEditMode is deprecated, see param documentation above
* @since 3.0.0 Changed signature: Method must return header content in an array (no more writing directly to the $oPage)
*
* @noinspection PhpUnusedParameterInspection
*/
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
{
@@ -391,7 +398,8 @@ JS
$oSingletonFilter = new DBObjectSearch(get_class($this));
$oSingletonFilter->AddCondition('id', $this->GetKey(), '=');
$oBlock = new MenuBlock($oSingletonFilter, 'details', false);
$oActionMenuBlock = $oBlock->GetRenderContent($oPage);
$sActionMenuId = utils::Sanitize(uniqid('', true), '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
$oActionMenuBlock = $oBlock->GetRenderContent($oPage, [], $sActionMenuId);
$aHeaderBlocks['toolbar'][$oActionMenuBlock->GetId()] = $oActionMenuBlock;
}
@@ -649,11 +657,17 @@ HTML
if ($oAttDef instanceof AttributeDashboard) {
if (!$this->IsNew()) {
$sHostContainerInEditionUrlParam = ($bEditMode) ? '&host_container_in_edition=true' : '';
$oPage->AddAjaxTab($oAttDef->GetLabel(),
utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=dashboard&class='.get_class($this).'&id='.$this->GetKey().'&attcode='.$oAttDef->GetCode().$sHostContainerInEditionUrlParam,
true,
$oPage->AddAjaxTab(
'Class:'.$sClass.'/Attribute:'.$sAttCode,
AjaxTab::ENUM_TAB_PLACEHOLDER_DASHBOARD);
utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=dashboard&class='
.get_class($this)
.'&id='.$this->GetKey()
.'&attcode='.$oAttDef->GetCode()
.$sHostContainerInEditionUrlParam,
true,
$oAttDef->GetLabel(),
AjaxTab::ENUM_TAB_PLACEHOLDER_DASHBOARD
);
// Add graphs dependencies
WebResourcesHelper::EnableC3JSToWebPage($oPage);
}
@@ -740,7 +754,7 @@ HTML
$oClassIcon = new MedallionIcon(MetaModel::GetClassIcon($sTargetClass, false));
$oClassIcon->SetDescription($oAttDef->GetDescription())->AddCSSClass('ibo-block-list--medallion');
$oPage->AddUiBlock($oClassIcon);
$sDisplayValue = ''; // not used
$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode,
$oAttDef, $oLinkSet, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
@@ -1739,6 +1753,9 @@ HTML
* @param array $aParams
*
* @throws \Exception
* only used in old and deprecated export.php
*
* @internal Only to be used by `/webservices/export.php` : this is a legacy method that produces wrong HTML (no TR on table body rows)
*/
public static function DisplaySetAsHTMLSpreadsheet(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array())
{
@@ -1759,6 +1776,8 @@ HTML
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \Exception
*
* @internal Only to be used by `/webservices/export.php` : this is a legacy method that produces wrong HTML (no TR on table body rows)
*/
public static function GetSetAsHTMLSpreadsheet(DBObjectSet $oSet, $aParams = array())
{
@@ -2147,7 +2166,7 @@ HTML;
$sDisplayValueForHtml = utils::EscapeHtml($sDisplayValue);
$sHTMLValue = <<<HTML
<div class="field_input_zone field_input_datetime ibo-input-wrapper ibo-input-datetime-wrapper" data-validation="untouched">
<input title="{$sHelpText}" class="datetime-pick ibo-input ibo-input-datetime" type="text" size="19" {$sPlaceholderValue} name="attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}" value="{$sDisplayValueForHtml}" id="{$iId}" autoomplete="off" />
<input title="{$sHelpText}" class="datetime-pick ibo-input ibo-input-datetime" type="text" size="19" {$sPlaceholderValue} name="attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}" value="{$sDisplayValueForHtml}" id="{$iId}" autocomplete="off" />
</div>{$sValidationSpan}{$sReloadSpan}
HTML;
break;
@@ -3945,7 +3964,7 @@ HTML;
}
elseif ($iFlags & OPT_ATT_SLAVE)
{
$aErrors[$sAttCode] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel());
$aErrors[$sAttCode] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel(), $sAttCode);
}
else
{
@@ -4231,13 +4250,20 @@ HTML;
if (!is_null($oImage->GetData()))
{
$aSize = utils::GetImageSize($oImage->GetData());
$oImage = utils::ResizeImageToFit(
$oImage,
$aSize[0],
$aSize[1],
$oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height')
);
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());
}
}
$aOtherData = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
if (is_array($aOtherData))
@@ -5095,7 +5121,7 @@ HTML
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass) || !MetaModel::HasLifecycle($sClass)) {
$sValueCheckbox = '<input type="checkbox" class="ibo-field--enable-bulk--checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
}
$aComments[$sAttCode] .= '<div class="multi_values ibo-field--enable-bulk ibo-pill ibo-is-failure" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true">'.$iCount.$sValueCheckbox.'</div>';
$aComments[$sAttCode] .= '<div class="multi_values ibo-field--enable-bulk ibo-pill ibo-is-failure" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true" data-tooltip-append-to="body">'.$iCount.$sValueCheckbox.'</div>';
}
$sReadyScript .= 'ToggleField('.(($iCount == 1) ? 'true' : 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
}
@@ -5213,11 +5239,14 @@ EOF
} else {
$sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped');
}
$sChecked = $bResult ? 'checked' : '';
$aErrorsToDisplay = array_map(function($sError) {
return utils::HtmlEntities($sError);
}, $aErrors);
$aRows[] = array(
'object' => $oObj->GetHyperlink(),
'status' => $sStatus,
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrors)).'</p>',
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrorsToDisplay)).'</p>',
);
if ($bResult && (!$bPreview)) {
$oObj->DBUpdate();
@@ -5226,7 +5255,7 @@ EOF
set_time_limit(intval($iPreviousTimeLimit));
$oTable = DataTableUIBlockFactory::MakeForForm('BulkModify', $aHeaders, $aRows);
$oTable->AddOption("bFullscreen", true);
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, '');
$oPanel->SetIcon($sClassIcon);
$oPanel->SetTitle($sHeaderTitle);
@@ -5432,13 +5461,13 @@ EOF
$oFailAlertBlock = AlertUIBlockFactory::MakeForDanger('', Dict::S('UI:Delete:SorryDeletionNotAllowed'));
$oFailAlertBlock->SetIsClosable(false);
$oP->AddUiBlock($oFailAlertBlock);
}
}
else {
$oWarningAlertBlock = AlertUIBlockFactory::MakeForWarning('', Dict::S('UI:Delete:PleaseDoTheManualOperations'));
$oWarningAlertBlock->SetIsClosable(false);
$oP->AddUiBlock($oWarningAlertBlock);
}
$oForm = FormUIBlockFactory::MakeStandard('');
$oP->AddSubBlock($oForm);
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('transaction_id', utils::ReadParam('transaction_id', '', false, 'transaction_id')));

View File

@@ -583,7 +583,7 @@ JS
$oPage->add('<div id="select_dashlet" class="ibo-dashboard--available-dashlets--list" data-role="ibo-dashboard--available-dashlets--list">');
$aAvailableDashlets = $this->GetAvailableDashlets();
foreach ($aAvailableDashlets as $sDashletClass => $aInfo) {
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="ibo-dashboard-editor--available-dashlet-icon dashlet_icon ui-widget-content ui-corner-all" data-role="ibo-dashboard-editor--available-dashlet-icon" id="dashlet_'.$sDashletClass.'" title="'.$aInfo['label'].'"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="ibo-dashboard-editor--available-dashlet-icon dashlet_icon ui-widget-content ui-corner-all" data-role="ibo-dashboard-editor--available-dashlet-icon" id="dashlet_'.$sDashletClass.'" data-tooltip-content="'.$aInfo['label'].'" title="'.$aInfo['label'].'"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
}
$oPage->add('</div>');
@@ -789,6 +789,7 @@ class RuntimeDashboard extends Dashboard
/**
* @inheritDoc
* @return bool $bIsNew
* @throws \Exception
*/
public function Save()
@@ -798,6 +799,7 @@ class RuntimeDashboard extends Dashboard
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
$bIsNew = false;
if ($oUDSet->Count() > 0)
{
// Assuming there is at most one couple {user, menu}!
@@ -811,10 +813,12 @@ class RuntimeDashboard extends Dashboard
$oUserDashboard->Set('user_id', UserRights::GetUserId());
$oUserDashboard->Set('menu_code', $this->sId);
$oUserDashboard->Set('contents', $sXml);
$bIsNew = true;
}
utils::PushArchiveMode(false);
$oUserDashboard->DBWrite();
utils::PopArchiveMode();
return $bIsNew;
}
/**
@@ -1066,11 +1070,11 @@ EOF
dashboard.html(data);
dashboard.unblock();
if ($('#ibo-dashboard-selector$sDivId input').prop("checked")) {
$('#ibo-dashboard-selector$sDivId').data('tooltip-content', '$sSwitchToStandard');
$('#ibo-dashboard-selector$sDivId').attr('data-tooltip-content', '$sSwitchToStandard');
} else {
$('#ibo-dashboard-selector$sDivId').data('tooltip-content', '$sSwitchToCustom');
$('#ibo-dashboard-selector$sDivId').attr('data-tooltip-content', '$sSwitchToCustom');
}
CombodoTooltip.InitAllNonInstantiatedTooltips($('#ibo-dashboard-selector$sDivId').parent());
CombodoTooltip.InitAllNonInstantiatedTooltips($('#ibo-dashboard-selector$sDivId').parent(), true);
}
);
}

View File

@@ -262,7 +262,7 @@ abstract class Dashlet
}
} catch (OqlException $e) {
$oDashletContainer->AddCSSClass("dashlet-content");
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
$oDashletContainer->AddHtml('<p>'.utils::HtmlEntities($e->GetUserFriendlyDescription()).'</p>');
} catch (Exception $e) {
$oDashletContainer->AddCSSClass("dashlet-content");
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');

View File

@@ -539,8 +539,10 @@ class DisplayBlock
* @throws DictExceptionMissingString
* @throws MySQLException
* @throws Exception
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 add type hinting to $aExtraParams
*/
public function GetRenderContent(WebPage $oPage, array $aExtraParams = [], string $sId = null)
public function GetRenderContent(WebPage $oPage, array $aExtraParams, string $sId)
{
$sHtml = '';
$oBlock = null;
@@ -853,7 +855,7 @@ JS
{
$oField = new FieldExpression($sFilterCode, $oFilter->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($condition)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
return $oNewCondition;
}
@@ -1052,6 +1054,11 @@ JS
$oBlock->AddSubBlock($oPill);
}
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
if(isset($aExtraParams['query_params']['this->object()'])){
$aExtraParams['query_params']['this->class'] = get_class($aExtraParams['query_params']['this->object()']);
$aExtraParams['query_params']['this->id'] = $aExtraParams['query_params']['this->object()']->GetKey();
unset($aExtraParams['query_params']['this->object()']);
}
$aRefreshParams = ['filter' => $this->m_oFilter->ToOQL(), "extra_params" => json_encode($aExtraParams)];
$oBlock->SetJSRefresh(
"$('#".$oBlock->GetId()."').block();
@@ -1200,6 +1207,7 @@ JS
$sTitle = Dict::Format($sFormat, $iTotalCount);
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
$oBlock->AddSubTitleBlock(new Html($sTitle));
$oBlock->AddCSSClass('ibo-datatable-panel');
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
$oBlock->SetIcon($aExtraParams["panel_icon"]);
}
@@ -1730,7 +1738,24 @@ class HistoryBlock extends DisplayBlock
$this->iLimitCount = $iCount;
}
public function GetRenderContent(WebPage $oPage, array $aExtraParams = [], string $sId = null)
/**
* @param \WebPage $oPage
* @param array $aExtraParams
* @param string $sId
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aExtraParams and add type hinting for PHP 8.0 compatibility
* (var is unused, and all calls were already made using a default value)
*/
public function GetRenderContent(WebPage $oPage, array $aExtraParams, string $sId)
{
$sHtml = '';
$bTruncated = false;
@@ -1871,11 +1896,10 @@ class MenuBlock extends DisplayBlock
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \ReflectionException
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value and add type hinting on $aExtraParams for PHP 8.0 compatibility
*/
public function GetRenderContent(WebPage $oPage, array $aExtraParams = [], string $sId = null)
public function GetRenderContent(WebPage $oPage, array $aExtraParams, string $sId)
{
$oRenderBlock = new UIContentBlock();

View File

@@ -44,15 +44,15 @@ class CoreCannotSaveObjectException extends CoreException
public function getHtmlMessage()
{
$sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = "<span><strong>{$sTitle}</strong></span>";
$sContent = "<span><strong>".utils::HtmlEntities($sTitle)."</strong></span>";
if (count($this->aIssues) == 1) {
$sIssue = reset($this->aIssues);
$sContent .= " <span>{$sIssue}</span>";
$sContent .= " <span>".utils::HtmlEntities($sIssue)."</span>";
} else {
$sContent .= '<ul>';
foreach ($this->aIssues as $sError) {
$sContent .= "<li>$sError</li>";
$sContent .= "<li>".utils::HtmlEntities($sError)."</li>";
}
$sContent .= '</ul>';
}

View File

@@ -1272,7 +1272,7 @@ class DesignerComboField extends DesignerFormField
$sChecked = $this->defaultValue ? 'checked' : '';
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
if ($this->IsSorted())
if ($this->IsSorted() )
{
asort($this->aAllowedValues);
}
@@ -1320,18 +1320,14 @@ class DesignerComboField extends DesignerFormField
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
}
}
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
{
if ($this->bMultipleSelection)
{
foreach ($this->aAllowedValues as $sKey => $sDisplayValue) {
if ($this->bMultipleSelection) {
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
}
else
{
} else {
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
}
// Quick and dirty: display the menu parents as a tree
$sHtmlValue = str_replace(' ', '&nbsp;', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
$sHtmlValue = str_replace(' ', '&nbsp;', $sDisplayValue);
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
}
$sHtml .= "</select></span>";

View File

@@ -62,6 +62,7 @@ class LoginBasic extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
Session::Set('auth_user', $sAuthUser);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -70,8 +71,7 @@ class LoginBasic extends AbstractLoginFSMExtension
{
if (Session::Get('login_mode') == 'basic')
{
list($sAuthUser) = $this->GetAuthUserAndPassword();
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}

View File

@@ -45,6 +45,7 @@ class LoginExternal extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
Session::Set('auth_user', $sAuthUser);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -53,8 +54,7 @@ class LoginExternal extends AbstractLoginFSMExtension
{
if (Session::Get('login_mode') == 'external')
{
$sAuthUser = $this->GetAuthUser();
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', Session::Get('login_mode'));
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'external', Session::Get('login_mode'));
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}

View File

@@ -71,6 +71,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
Session::Set('auth_user', $sAuthUser);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -82,17 +83,8 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
{
if (Session::Get('login_mode') == 'form')
{
if (Session::IsSet('auth_user'))
{
// If FSM reenter this state (example 2FA) then the auth_user is not resubmitted
$sAuthUser = Session::Get('auth_user');
}
else
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
}
// Store 'auth_user' in session for further use
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}

View File

@@ -60,6 +60,7 @@ class LoginURL extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
Session::Set('auth_user', $sAuthUser);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -68,8 +69,7 @@ class LoginURL extends AbstractLoginFSMExtension
{
if (Session::Get('login_mode') == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
LoginWebPage::OnLoginSuccess(Session::Get('auth_user'), 'internal', Session::Get('login_mode'));
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}

View File

@@ -112,7 +112,7 @@ class LoginWebPage extends NiceWebPage
*/
public static function SynchronizeProfiles(&$oUser, array $aProfiles, $sOrigin)
{
$oProfilesSet = $oUser->Get(profile_list);
$oProfilesSet = $oUser->Get('profile_list');
//delete old profiles
$aExistingProfiles = [];
while ($oProfile = $oProfilesSet->Fetch())
@@ -241,7 +241,7 @@ class LoginWebPage extends NiceWebPage
}
// This token allows the user to change the password without knowing the previous one
$sToken = substr(md5(APPROOT.uniqid()), 0, 16);
$sToken = bin2hex(random_bytes(32));
$oUser->Set('reset_pwd_token', $sToken);
CMDBObject::SetTrackInfo('Reset password');
$oUser->AllowWrite(true);
@@ -483,6 +483,7 @@ class LoginWebPage extends NiceWebPage
$iResponse = $oLoginFSMExtensionInstance->LoginAction($sLoginState, $iErrorCode);
if ($iResponse == self::LOGIN_FSM_RETURN)
{
Session::WriteClose();
return $iErrorCode; // Asked to exit FSM, generally login OK
}
if ($iResponse == self::LOGIN_FSM_ERROR)

View File

@@ -77,17 +77,28 @@ function _MaintenanceHtmlMessage($sMessage)
*/
function _MaintenanceJsonMessage($sTitle, $sMessage)
{
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
if (class_exists('ajax_page'))
if (class_exists('JsonPage'))
{
$oP = new ajax_page($sTitle);
$oP = new JsonPage($sTitle);
$oP->add_header('Access-Control-Allow-Origin: *');
$oP->SetContentType('application/json');
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
$aMessage = [
'code' => 100,
'message' =>$sMessage
];
$oP->AddData($aMessage);
$oP->Output();
}
else
{
_MaintenanceTextMessage($sMessage);
} 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);
}
}
}

View File

@@ -5,7 +5,6 @@
*/
use Combodo\iTop\Application\Helper\WebResourcesHelper;
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/application/template.class.inc.php');
@@ -266,6 +265,14 @@ class ApplicationMenu
/** @var \MenuGroup $oMenuNode */
$oMenuNode = static::GetMenuNode($sMenuGroupIdx);
if (!($oMenuNode instanceof MenuGroup)) {
IssueLog::Error('Menu node was not displayed as a menu group as it is actually not a menu group', LogChannels::CONSOLE, [
'menu_node_class' => get_class($oMenuNode),
'menu_node_label' => $oMenuNode->GetLabel(),
]);
continue;
}
$aMenuGroups[] = [
'sId' => $oMenuNode->GetMenuID(),
'sIconCssClasses' => $oMenuNode->GetDecorationClasses(),
@@ -654,8 +661,7 @@ abstract class MenuNode
$this->sMenuId = $sMenuId;
$this->iParentIndex = $iParentIndex;
$this->aReflectionProperties = array();
if (strlen($sEnableClass) > 0)
{
if (utils::IsNotNullOrEmptyString($sEnableClass)) {
$this->aReflectionProperties['enable_class'] = $sEnableClass;
$this->aReflectionProperties['enable_action'] = $iActionCode;
$this->aReflectionProperties['enable_permission'] = $iAllowedResults;
@@ -1126,16 +1132,20 @@ class OQLMenuNode extends MenuNode
{
$sUsageId = utils::GetSafeId($sUsageId);
$oSearch = DBObjectSearch::FromOQL($sOql);
$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->Display($oPage, 0);
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>");
}
$oPage->add("<div class='sf_results_area' data-target='search_results'>");
$oTitle = TitleUIBlockFactory::MakeForPage($sTitle);
$oPage->AddUiBlock($oTitle);
else {
$oPage->add("<div class='sf_results_area' data-target='search_results'>");
}
$aExtraParams['panel_class'] =$sClass;
$aExtraParams['panel_title'] = $sTitle;
$aExtraParams['panel_icon'] = $sIcon;
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);

View File

@@ -288,7 +288,8 @@ class ShortcutOQL extends Shortcut
$oPage->add_ready_script(
<<<JS
// Note: the title gets deleted by the validation mechanism
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
$('#attr_auto_reload').change( function(ev) {

View File

@@ -66,7 +66,6 @@ register_shutdown_function(function()
});
$oKPI = new ExecutionKPI();
Session::Start();
Session::WriteClose();
$oKPI->ComputeAndReport("Session Start");
$sSwitchEnv = utils::ReadParam('switch_env', null);

View File

@@ -29,7 +29,7 @@ class ThemeHandlerService
{
}
public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null){
return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp="", $aThemeParameters, $aImportsPaths, $sWorkingPath);
public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp = "", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null){
return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp, $aThemeParameters, $aImportsPaths, $sWorkingPath);
}
}

View File

@@ -2,6 +2,7 @@
namespace Combodo\iTop;
use AttributeDate;
use AttributeDateTime;
use Dict;
use Exception;
@@ -55,6 +56,10 @@ class TwigExtension
{
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)
{

View File

@@ -61,6 +61,8 @@ class UIExtKeyWidget
protected $sAttCode;
protected $bSearchMode;
//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
/**
* @param \WebPage $oPage
* @param string $sAttCode
@@ -80,18 +82,13 @@ class UIExtKeyWidget
* @throws \Exception
*
* @since 3.0.0 N°3750 new $sInputType parameter
* @since 2.7.7 3.0.1 3.1.0 N°3129 Add default value for $aArgs for PHP 8.0 compat
*/
public static function DisplayFromAttCode(
$oPage, $sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName = '', $sFormPrefix = '',
$aArgs = [], $bSearchMode = false, &$sInputType = ''
)
{
// we will only use key & name, so let's reduce fields loaded !
$aAttToLoad = [
$sClass => [], // nothing, id and friendlyname are automatically added by the API
];
$oAllowedValues->OptimizeColumnLoad($aAttToLoad);
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sTargetClass = $oAttDef->GetTargetClass();
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
@@ -214,14 +211,23 @@ class UIExtKeyWidget
$sClassAllowed = $oAllowedValues->GetClass();
$bAddingValue = false;
// N°4792 - load only the required fields
$aFieldsToLoad = [];
$aComplementAttributeSpec = MetaModel::GetNameSpec($oAllowedValues->GetClass(), FriendlyNameType::COMPLEMENTARY);
$sFormatAdditionalField = $aComplementAttributeSpec[0];
$aAdditionalField = $aComplementAttributeSpec[1];
if (count($aAdditionalField) > 0) {
$bAddingValue = true;
$aFieldsToLoad[$sClassAllowed] = $aAdditionalField;
}
$sObjectImageAttCode = MetaModel::GetImageAttributeCode($sClassAllowed);
if (!empty($sObjectImageAttCode)) {
$aFieldsToLoad[$sClassAllowed][] = $sObjectImageAttCode;
}
$aFieldsToLoad[$sClassAllowed][] = 'friendlyname';
$oAllowedValues->OptimizeColumnLoad($aFieldsToLoad);
$bInitValue = false;
while ($oObj = $oAllowedValues->Fetch()) {
$aOption = [];
@@ -254,7 +260,7 @@ class UIExtKeyWidget
$aOption['picture_url'] = $oImage->GetDisplayURL($sClassAllowed, $oObj->GetKey(), $sObjectImageAttCode);
$aOption['initials'] = '';
} else {
$aOption['initials'] = utils::ToAcronym($oObj->Get('friendlyname'));
$aOption['initials'] = utils::FormatInitialsForMedallion(utils::ToAcronym($oObj->Get('friendlyname')));
}
}
array_push($aOptions, $aOption);
@@ -772,14 +778,14 @@ JS
* @param DBObject $oObj The current object for the OQL context
* @param string $sContains The text of the autocomplete to filter the results
* @param string $sOutputFormat
* @param null $sOperation for the values @see ValueSetObjects->LoadValues()
* @param null $sOperation for the values @see ValueSetObjects->LoadValues() not used since 3.0.0
*
* @throws CoreException
* @throws OQLException
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $oObj for PHP 8.0 compatibility
*/
public function AutoComplete(
WebPage $oP, $sFilter, $oObj = null, $sContains = '', $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null
)
public function AutoComplete(WebPage $oP, $sFilter, $oObj, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null )
{
if (is_null($sFilter)) {
throw new Exception('Implementation: null value for allowed values definition');
@@ -793,13 +799,13 @@ JS
$oValuesSet->SetSort(false);
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oValuesSet->SetLimit($iMax);
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
asort($aValuesContains);
$aValues = $aValuesContains;
$aValuesStartWith = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
asort($aValuesStartWith);
$aValues = $aValuesStartWith;
if (sizeof($aValues) < $iMax) {
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
asort($aValuesContains);
$iSize = sizeof($aValuesContains);
$iSize = sizeof($aValues);
foreach ($aValuesContains as $sKey => $sFriendlyName)
{
if (!isset($aValues[$sKey]))
@@ -815,7 +821,9 @@ JS
elseif (!in_array($sContains, $aValues))
{
$aValuesEquals = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals');
$aValues = array_merge($aValuesEquals, $aValues);
// Note: Here we cannot use array_merge as it would reindex the numeric keys starting from 0 when keys are actually the objects ID.
// As a workaround we use array_replace as it does preserve numeric keys. It's ok if some values from $aValuesEquals are replaced with values from $aValues as they contain the same data.
$aValues = array_replace($aValuesEquals, $aValues);
}
switch($sOutputFormat)
@@ -830,7 +838,7 @@ JS
}
if (array_key_exists('initials', $aValue)) {
$aElt['initials'] = $aValue['initials'];
$aElt['initials'] = utils::FormatInitialsForMedallion($aValue['initials']);
if (array_key_exists('picture_url', $aValue)) {
$aElt['picture_url'] = $aValue['picture_url'];
}
@@ -974,7 +982,7 @@ HTML
);
$oPage->add_ready_script(<<<JS
$('#ac_create_{$this->iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
$('#ac_create_{$this->iId}').dialog({ width: $(window).width() * 0.6, height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
$('#dcr_{$this->iId} form').removeAttr('onsubmit');
$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);
JS

View File

@@ -75,9 +75,15 @@ class UILinksWidgetDirect
* @param array $aArgs
* @param string $sFormPrefix
* @param DBObject $oCurrentObj
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aArgs for PHP 8.0 compatibility (handling wrong values at method start)
*/
public function Display(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
public function Display(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj)
{
if (empty($aArgs)) {
$aArgs = [];
}
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
switch($oLinksetDef->GetEditMode())
{
@@ -127,8 +133,10 @@ class UILinksWidgetDirect
* @param string $sFormPrefix
* @param DBObject $oCurrentObj
* @param bool $bDisplayMenu
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aArgs for PHP 8.0 compatibility (protected method, always called with default value)
*/
protected function DisplayAsBlock(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $bDisplayMenu)
protected function DisplayAsBlock(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj, $bDisplayMenu)
{
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$sTargetClass = $oLinksetDef->GetLinkedClass();
@@ -228,8 +236,10 @@ class UILinksWidgetDirect
* @param string $sFormPrefix
* @param DBObject $oCurrentObj
* @param array $aButtons
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aArgs for PHP 8.0 compatibility (protected method, caller already handles it)
*/
protected function DisplayEditInPlace(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
protected function DisplayEditInPlace(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
{
$aAttribs = $this->GetTableConfig();
$oValue->Rewind();
@@ -296,7 +306,7 @@ class UILinksWidgetDirect
}
$oHiddenCriteria = $oHiddenFilter->GetCriteria();
$aArgs = $oHiddenFilter->GetInternalParams();
$sHiddenCriteria = $oHiddenCriteria->Render($aArgs);
$sHiddenCriteria = $oHiddenCriteria->RenderExpression(false, $aArgs);
$oLinkSetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$valuesDef = $oLinkSetDef->GetValuesDef();

View File

@@ -21,6 +21,8 @@ use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\UI\Base\iUIBlock;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
use ScssPhp\ScssPhp\Compiler;
use ScssPhp\ScssPhp\OutputStyle;
use ScssPhp\ScssPhp\ValueConverter;
/**
@@ -97,6 +99,11 @@ class utils
* @since 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_RAW_DATA = 'raw_data';
/**
* @var string
* @since 3.0.2, 3.1.0 N°4899
*/
public const ENUM_SANITIZATION_FILTER_URL = 'url';
/**
* @var string
@@ -377,6 +384,7 @@ class utils
* @since 2.5.2 2.6.0 new 'transaction_id' filter
* @since 2.7.0 new 'element_identifier' filter
* @since 3.0.0 new utils::ENUM_SANITIZATION_* const
* @since 2.7.7, 3.0.2, 3.1.0 N°4899 - new 'url' filter
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
@@ -454,6 +462,11 @@ class utils
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
break;
// For URL
case static::ENUM_SANITIZATION_FILTER_URL:
$retValue = filter_var($value, FILTER_SANITIZE_URL);
break;
default:
case static::ENUM_SANITIZATION_FILTER_RAW_DATA:
$retValue = $value;
@@ -1930,19 +1943,23 @@ class utils
public static function CompileCSSFromSASS($sSassContent, $aImportPaths = array(), $aVariables = array())
{
$oSass = new Compiler();
$oSass->setFormatter('ScssPhp\\ScssPhp\\Formatter\\Compressed');
$oSass->setOutputStyle(OutputStyle::COMPRESSED);
// Setting our variables
$oSass->setVariables($aVariables);
$aScssVariables = [];
foreach ($aVariables as $entry => $value) {
$aScssVariables[$entry] = ValueConverter::parseValue($value);
}
$oSass->addVariables($aScssVariables);
// Setting our imports paths
$oSass->setImportPaths($aImportPaths);
// Temporary disabling max exec time while compiling
$iCurrentMaxExecTime = (int) ini_get('max_execution_time');
set_time_limit(0);
// Compiling SASS
$sCss = $oSass->compile($sSassContent);
$sCss = $oSass->compileString($sSassContent);
set_time_limit(intval($iCurrentMaxExecTime));
return $sCss;
return $sCss->getCss();
}
public static function GetImageSize($sImageData)
@@ -2118,11 +2135,21 @@ class utils
}
/**
* Returns the relative (to MODULESROOT) path of the root directory of the module containing the file where the call to
* this function is made
* or an empty string if no such module is found (or not called within a module file)
* @param number $iCallDepth The depth of the module in the callstack. Zero when called directly from within the module
* @return string
* **Warning** : returned result can be invalid as we're using backtrace to find the module dir name
*
* @param int $iCallDepth The depth of the module in the callstack. Zero when called directly from within the module
*
* @return string the relative (to MODULESROOT) path of the root directory of the module containing the file where the call to
* this function is made
* or an empty string if no such module is found (or not called within a module file)
*
* @uses \debug_backtrace()
*
* @since 3.0.0 Before writing model.*.php file, compiler will now always delete it.
* If you have symlinks enabled, base dir will be original module dir, but since this behavior change this won't be true anymore for model.*.php
* In consequence the backtrace analysis won't be possible for this file
* See N°4854
* @link https://www.itophub.io/wiki/page?id=3_0_0%3Arelease%3A3_0_whats_new#compiler_always_generate_new_model_php compiler behavior change documentation
*/
public static function GetCurrentModuleDir($iCallDepth)
{
@@ -2147,9 +2174,14 @@ class utils
}
/**
* **Warning** : as this method uses {@see GetCurrentModuleDir} it produces hazardous results.
* You should better uses directly {@see GetAbsoluteUrlModulesRoot} and add the module dir name yourself ! See N°4573
*
* @return string the base URL for all files in the current module from which this method is called
* or an empty string if no such module is found (or not called within a module file)
* @throws \Exception
*
* @uses GetCurrentModuleDir
*/
public static function GetCurrentModuleUrl()
{
@@ -2404,43 +2436,19 @@ class utils
}
/**
* @return string eg : '2_7_0' ITOP_VERSION is '2.7.1-dev'
* @return string eg : '2_7_0' if iTop core version is '2.7.5-2'
* @throws \ApplicationException if constant value is invalid
* @uses ITOP_CORE_VERSION
*/
public static function GetItopVersionWikiSyntax() {
$sMinorVersion = self::GetItopMinorVersion();
public static function GetItopVersionWikiSyntax($sItopVersion = ITOP_CORE_VERSION)
{
$aExplodedVersion = explode('.', $sItopVersion);
return str_replace('.', '_', $sMinorVersion).'_0';
}
/**
* @param string $sPatchVersion if non provided, will call GetItopPatchVersion
*
* @return string eg 2.7 if ITOP_VERSION is '2.7.0-dev'
* @throws \Exception
*/
public static function GetItopMinorVersion($sPatchVersion = null) {
if (is_null($sPatchVersion)) {
$sPatchVersion = self::GetItopPatchVersion();
}
$aExplodedVersion = explode('.', $sPatchVersion);
if (count($aExplodedVersion) < 2) {
throw new Exception('iTop version is wrongfully configured!');
}
if (($aExplodedVersion[0] == '') || ($aExplodedVersion[1] == '')) {
throw new Exception('iTop version is wrongfully configured!');
if ((false === isset($aExplodedVersion[0])) || (false === isset($aExplodedVersion[1]))) {
throw new ApplicationException('iTop version is wrongfully configured!');
}
return sprintf('%d.%d', $aExplodedVersion[0], $aExplodedVersion[1]);
}
/**
* @return string eg '2.7.0' if ITOP_VERSION is '2.7.0-dev'
*/
public static function GetItopPatchVersion() {
$aExplodedVersion = explode('-', ITOP_VERSION);
return $aExplodedVersion[0];
return "{$aExplodedVersion[0]}_{$aExplodedVersion[1]}_0";
}
/**
@@ -2828,6 +2836,54 @@ HTML;
return $aPrefs[$sShortcutId];
}
//----------------------------------------------
// PHP function helpers
//----------------------------------------------
/**
* Helper around the native strlen() PHP method to keep allowing usage of null value when computing the length of a string as null value is no longer allowed with PHP 8.1+
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
*
* @param string|null $sString
*
* @return int Length of $sString, 0 if null
* @since 3.0.2 N°5172
*/
public static function StrLen(?string $sString): int
{
return strlen($sString ?? '');
}
/**
* Helper around the native strlen() PHP method to test a string for null or empty value
*
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
*
* @param string|null $sString
*
* @return bool if string null or empty
* @since 3.0.2 N°5302
*/
public static function IsNullOrEmptyString(?string $sString): bool
{
return $sString === null || strlen($sString) === 0;
}
/**
* Helper around the native strlen() PHP method to test a string not null or empty value
*
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
*
* @param string|null $sString
*
* @return bool if string is not null and not empty
* @since 3.0.2 N°5302
*/
public static function IsNotNullOrEmptyString(?string $sString): bool
{
return !static::IsNullOrEmptyString($sString);
}
//----------------------------------------------
// Environment helpers
//----------------------------------------------
@@ -3059,6 +3115,20 @@ HTML;
return $aMentionedObjects;
}
/**
* Note: This method is not ideal, but other solutions seemed even less ideal:
* * Add a "$sMaxLength" param. to utils::ToAcronym(): Does not work for every use cases (see corresponding ticket) as in some parts utils::ToAcronym isn't necessarly meant to be used in a medallion.
*
* @param string $sInitials
*
* @return string Truncates $sInitials so it can fit in medallions
* @since 3.0.1 N°4913
*/
public static function FormatInitialsForMedallion(string $sInitials): string
{
return mb_substr($sInitials, 0, 3);
}
/**
* @param $sUrl
* @param string $sParamName

View File

@@ -4,8 +4,25 @@ define('APPROOT', dirname(__FILE__).'/');
define('APPCONF', APPROOT.'conf/');
/**
* iTop framework Version
* iTop Datamodel XML format version
*
* It was also used in iTop 3.0.0 to get iTop core version (instead of {@see ITOP_VERSION} which gives the application version).
* To address this need you should now use {@see ITOP_CORE_VERSION}
*
* @see ITOP_CORE_VERSION to get full iTop core version
*/
define('ITOP_DESIGN_LATEST_VERSION', '3.0');
/**
* Constant containing the iTop core version, whatever application was built
*
* Note that in iTop 3.0.0 we used {@see ITOP_DESIGN_LATEST_VERSION} to get core version.
* When releasing, both constants should be updated : see `.make/release/update-versions.php` for that !
*
* @since 2.7.7 3.0.1 3.1.0 N°4714 constant creation
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '3.0.2');
require_once APPROOT.'bootstrap.inc.php';

View File

@@ -1,6 +1,8 @@
{
"name": "combodo/itop",
"description": "IT Operations Portal",
"type": "project",
"license": "AGPLv3",
"license": "AGPL-3.0-only",
"require": {
"php": ">=7.1.3 <8.0.0",
"ext-ctype": "*",
@@ -10,22 +12,27 @@
"ext-json": "*",
"ext-mysqli": "*",
"ext-soap": "*",
"combodo/tcpdf": "6.3.5",
"nikic/php-parser": "^4.12.0",
"pear/archive_tar": "1.4.14",
"pelago/emogrifier": "3.1.0",
"scssphp/scssphp": "1.0.6",
"swiftmailer/swiftmailer": "5.4.12",
"symfony/console": "3.4.*",
"symfony/dotenv": "3.4.*",
"symfony/framework-bundle": "3.4.*",
"symfony/polyfill-php70": "1.*",
"symfony/twig-bundle": "3.4.*",
"symfony/yaml": "3.4.*"
"combodo/tcpdf": "~6.4.4",
"guzzlehttp/guzzle": "^6.5.8",
"laminas/laminas-mail": "^2.11",
"laminas/laminas-servicemanager": "^3.5",
"league/oauth2-google": "^3.0",
"nikic/php-parser": "~4.13.2",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "~3.1.0",
"scssphp/scssphp": "^1.10.3",
"swiftmailer/swiftmailer": "~6.3.0",
"symfony/console": "~3.4.47",
"symfony/dotenv": "~3.4.47",
"symfony/framework-bundle": "~3.4.47",
"symfony/twig-bundle": "~3.4.47",
"symfony/yaml": "~3.4.47",
"thenetworg/oauth2-azure": "^2.0",
"twig/twig": "~1.43.1"
},
"require-dev": {
"symfony/stopwatch": "3.4.*",
"symfony/web-profiler-bundle": "3.4.*"
"symfony/stopwatch": "~3.4.47",
"symfony/web-profiler-bundle": "~3.4.47"
},
"suggest": {
"ext-libsodium": "Required to use the AttributeEncryptedString.",
@@ -54,12 +61,6 @@
"sources"
],
"exclude-from-classmap": [
"core/dbobjectsearch.class.php",
"core/legacy/dbobjectsearchlegacy.class.php",
"core/querybuildercontext.class.inc.php",
"core/legacy/querybuildercontextlegacy.class.inc.php",
"core/querybuilderexpressions.class.inc.php",
"core/legacy/querybuilderexpressionslegacy.class.inc.php",
"core/oql/build/PHP/",
"core/apc-emulation.php",
"application/startup.inc.php",

2763
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -200,6 +200,17 @@ abstract class ActionNotification extends Action
*/
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';
/**
* @inheritDoc
*/
@@ -207,13 +218,13 @@ class ActionEmail extends ActionNotification
{
$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",
"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" => "",
);
MetaModel::Init_Params($aParams);
@@ -266,7 +277,7 @@ class ActionEmail extends ActionNotification
protected function FindRecipients($sRecipAttCode, $aArgs)
{
$sOQL = $this->Get($sRecipAttCode);
if (strlen($sOQL) == '') return '';
if (strlen($sOQL) === 0) return '';
try
{
@@ -416,9 +427,8 @@ class ActionEmail extends ActionNotification
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
$oObj = $aContextArgs['this->object()'];
$sMessageId = sprintf('iTop_%s_%d_%f@%s.openitop.org', get_class($oObj), $oObj->GetKey(), microtime(true /* get as float*/),
MetaModel::GetEnvironmentId());
$sReference = '<'.$sMessageId.'>';
$sMessageId = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_MESSAGE_ID);
$sReference = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_REFERENCES);
}
catch (Exception $e) {
/** @noinspection PhpUnhandledExceptionInspection */
@@ -456,8 +466,7 @@ class ActionEmail extends ActionNotification
$oEmail = new EMail();
if ($this->IsBeingTested())
{
if ($this->IsBeingTested()) {
$oEmail->SetSubject('TEST['.$sSubject.']');
$sTestBody = $sBody;
$sTestBody .= "<div style=\"border: dashed;\">\n";
@@ -467,8 +476,8 @@ class ActionEmail extends ActionNotification
$sTestBody .= "<li>TO: $sTo</li>\n";
$sTestBody .= "<li>CC: $sCC</li>\n";
$sTestBody .= "<li>BCC: $sBCC</li>\n";
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n": "<li>From: $sFromLabel &lt;$sFrom&gt;</li>\n";
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n": "<li>Reply-To: $sReplyToLabel &lt;$sReplyTo&gt;</li>\n";
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n" : "<li>From: $sFromLabel &lt;$sFrom&gt;</li>\n";
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n" : "<li>Reply-To: $sReplyToLabel &lt;$sReplyTo&gt;</li>\n";
$sTestBody .= "<li>References: $sReference</li>\n";
$sTestBody .= "</ul>\n";
$sTestBody .= "</p>\n";
@@ -478,9 +487,9 @@ class ActionEmail extends ActionNotification
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
$oEmail->SetReferences($sReference);
$oEmail->SetMessageId($sMessageId);
}
else
{
// 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
$oEmail->SetInReplyTo($sReference);
} else {
$oEmail->SetSubject($sSubject);
$oEmail->SetBody($sBody, 'text/html', $sStyles);
$oEmail->SetRecipientTO($sTo);
@@ -490,6 +499,8 @@ class ActionEmail extends ActionNotification
$oEmail->SetRecipientReplyTo($sReplyTo, $sReplyToLabel);
$oEmail->SetReferences($sReference);
$oEmail->SetMessageId($sMessageId);
// 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
$oEmail->SetInReplyTo($sReference);
}
if (isset($aContextArgs['attachments']))
@@ -516,26 +527,64 @@ class ActionEmail extends ActionNotification
{
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)
{
} else {
if (is_array($this->m_aMailErrors) && count($this->m_aMailErrors) > 0) {
$sError = implode(', ', $this->m_aMailErrors);
}
else
{
} else {
$sError = 'Unknown reason';
}
return 'Notification was not sent: '.$sError;
}
}
/**
* @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.0.1 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);
}
}

View File

@@ -293,7 +293,7 @@ abstract class AsyncTask extends DBObject
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
}
$this->Set('last_error', $sErrorMessage);
$this->SetTrim('last_error', $sErrorMessage);
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
$this->Set('last_attempt', time());

View File

@@ -1685,7 +1685,7 @@ class AttributeLinkedSet extends AttributeDefinition
{
if ($sObjClass == $this->GetLinkedClass())
{
// Simplify the output if the exact class could be determined implicitely
// Simplify the output if the exact class could be determined implicitely
continue;
}
}
@@ -2007,7 +2007,7 @@ class AttributeLinkedSet extends AttributeDefinition
{
if ($sObjClass == $this->GetLinkedClass())
{
// Simplify the output if the exact class could be determined implicitely
// Simplify the output if the exact class could be determined implicitely
continue;
}
}
@@ -2412,7 +2412,7 @@ class AttributeDBFieldVoid extends AttributeDefinition
return false;
}
//
//
protected function ScalarToSQL($value)
{
return $value;
@@ -4587,7 +4587,13 @@ class AttributeCaseLog extends AttributeLongText
{
if (strlen($proposedValue) > 0)
{
$oCaseLog->AddLogEntry($proposedValue);
//N°5135 - add impersonation information in caselog
if (UserRights::IsImpersonated()){
$sOnBehalfOf = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName());
$oCaseLog->AddLogEntry($proposedValue, $sOnBehalfOf, UserRights::GetConnectedUserId());
} else {
$oCaseLog->AddLogEntry($proposedValue);
}
}
}
$ret = $oCaseLog;
@@ -5394,7 +5400,7 @@ class AttributeEnum extends AttributeString
{
if (is_null($sValue))
{
// Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
// Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
$sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue,
Dict::S('Enum:Undefined'));
}
@@ -5416,7 +5422,7 @@ class AttributeEnum extends AttributeString
{
if (is_null($sValue))
{
// Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
// Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+',
Dict::S('Enum:Undefined'));
}
@@ -5717,7 +5723,7 @@ class AttributeMetaEnum extends AttributeEnum
$aLocalizedValues = array();
foreach($aRawValues as $sKey => $sValue)
{
$aLocalizedValues[$sKey] = Str::pure2html($this->GetValueLabel($sKey));
$aLocalizedValues[$sKey] = $this->GetValueLabel($sKey);
}
return $aLocalizedValues;
@@ -7213,7 +7219,7 @@ class AttributeExternalField extends AttributeDefinition
protected function GetSQLCol($bFullSpec = false)
{
// throw new CoreException("external attribute: does it make any sense to request its type ?");
// throw new CoreException("external attribute: does it make any sense to request its type ?");
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetSQLCol($bFullSpec);
@@ -9262,7 +9268,7 @@ class AttributeSubItem extends AttributeDefinition
return $res;
}
//
//
// protected function ScalarToSQL($value) {return $value;} // format value as a valuable SQL literal (quoted outside)
public function FromSQLToValue($aCols, $sPrefix = '')

View File

@@ -11,7 +11,7 @@ define('UTF8_BOM', chr(239).chr(187).chr(191)); // 0xEF, 0xBB, 0xBF
/**
* CellChangeSpec
* A series of classes, keeping the information about a given cell: could it be changed or not (and why)?
* A series of classes, keeping the information about a given cell: could it be changed or not (and why)?
*
* @package iTopORM
*/
@@ -42,6 +42,17 @@ abstract class CellChangeSpec
return $this->m_sOql;
}
/**
* @since 3.1.0 N°5305
*/
public function GetDisplayableValueAndDescription(): string
{
return sprintf("%s%s",
$this->GetDisplayableValue(),
$this->GetDescription()
);
}
abstract public function GetDescription();
}
@@ -86,26 +97,90 @@ class CellStatus_Issue extends CellStatus_Modify
parent::__construct($proposedValue, $previousValue);
}
public function GetDescription()
public function GetDisplayableValue()
{
if (is_null($this->m_proposedValue))
{
return Dict::Format('UI:CSVReport-Value-SetIssue', $this->m_sReason);
return Dict::Format('UI:CSVReport-Value-SetIssue');
}
return Dict::Format('UI:CSVReport-Value-ChangeIssue', $this->m_proposedValue, $this->m_sReason);
return Dict::Format('UI:CSVReport-Value-ChangeIssue', \utils::EscapeHtml($this->m_proposedValue));
}
public function GetDescription()
{
return $this->m_sReason;
}
/*
* @since 3.1.0 N°5305
*/
public function GetDisplayableValueAndDescription(): string
{
return sprintf("%s. %s",
$this->GetDisplayableValue(),
$this->GetDescription()
);
}
}
class CellStatus_SearchIssue extends CellStatus_Issue
{
public function __construct()
/** @var string|null $m_sAllowedValues */
private $m_sAllowedValues;
/**
* @since 3.1.0 N°5305
* @var string $sSerializedSearch
*/
private $sSerializedSearch;
/** @var string|null $m_sTargetClass */
private $m_sTargetClass;
/**
* CellStatus_SearchIssue constructor.
* @since 3.1.0 N°5305
*
* @param string $sOql : main message
* @param string $sReason : main message
* @param null $sClass : used for additional message that provides allowed values for current class $sClass
* @param null $sAllowedValues : used for additional message that provides allowed values $sAllowedValues for current class
*/
public function __construct($sSerializedSearch, $sReason, $sClass=null, $sAllowedValues=null)
{
parent::__construct(null, null, null);
parent::__construct(null, null, $sReason);
$this->sSerializedSearch = $sSerializedSearch;
$this->m_sAllowedValues = $sAllowedValues;
$this->m_sTargetClass = $sClass;
}
public function GetDisplayableValue()
{
if (null === $this->m_sReason) {
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
}
return $this->m_sReason;
}
public function GetDescription()
{
return Dict::S('UI:CSVReport-Value-NoMatch');
if (\utils::IsNullOrEmptyString($this->m_sAllowedValues) ||
\utils::IsNullOrEmptyString($this->m_sTargetClass)) {
return '';
}
return Dict::Format('UI:CSVReport-Value-NoMatch-PossibleValues', $this->m_sTargetClass, $this->m_sAllowedValues);
}
/**
* @since 3.1.0 N°5305
* @return string
*/
public function GetSearchLinkUrl()
{
return sprintf("UI.php?operation=search&filter=%s",
rawurlencode($this->sSerializedSearch)
);
}
}
@@ -126,11 +201,24 @@ class CellStatus_NullIssue extends CellStatus_Issue
class CellStatus_Ambiguous extends CellStatus_Issue
{
protected $m_iCount;
/**
* @since 3.1.0 N°5305
* @var string
*/
protected $sSerializedSearch;
public function __construct($previousValue, $iCount, $sOql)
/**
* @since 3.1.0 N°5305
*
* @param $previousValue
* @param int $iCount
* @param string $sSerializedSearch
*
*/
public function __construct($previousValue, $iCount, $sSerializedSearch)
{
$this->m_iCount = $iCount;
$this->m_sQuery = $sOql;
$this->sSerializedSearch = $sSerializedSearch;
parent::__construct(null, $previousValue, '');
}
@@ -139,12 +227,23 @@ class CellStatus_Ambiguous extends CellStatus_Issue
$sCount = $this->m_iCount;
return Dict::Format('UI:CSVReport-Value-Ambiguous', $sCount);
}
/**
* @since 3.1.0 N°5305
* @return string
*/
public function GetSearchLinkUrl()
{
return sprintf("UI.php?operation=search&filter=%s",
rawurlencode($this->sSerializedSearch)
);
}
}
/**
* RowStatus
* A series of classes, keeping the information about a given row: could it be changed or not (and why)?
* A series of classes, keeping the information about a given row: could it be changed or not (and why)?
*
* @package iTopORM
*/
@@ -211,6 +310,26 @@ class RowStatus_Issue extends RowStatus
}
}
/**
* class dedicated to testability
* not used/ignored in csv imports UI/CLI
* @since 3.1.0 N°5305
*/
class RowStatus_Error extends RowStatus
{
/** @var string */
protected $m_sError;
public function __construct($sError)
{
$this->m_sError = $sError;
}
public function GetDescription()
{
return $this->m_sError;
}
}
/**
* BulkChange
@@ -220,17 +339,35 @@ class RowStatus_Issue extends RowStatus
*/
class BulkChange
{
protected $m_sClass;
/** @var string */
protected $m_sClass;
protected $m_aData; // Note: hereafter, iCol maybe actually be any acceptable key (string)
// #@# todo: rename the variables to sColIndex
protected $m_aAttList; // attcode => iCol
protected $m_aExtKeys; // aExtKeys[sExtKeyAttCode][sExtReconcKeyAttCode] = iCol;
protected $m_aReconcilKeys; // attcode (attcode = 'id' for the pkey)
protected $m_sSynchroScope; // OQL - if specified, then the missing items will be reported
protected $m_aOnDisappear; // array of attcode => value, values to be set when an object gets out of scope (ignored if no scope has been defined)
protected $m_sDateFormat; // Date format specification, see DateTime::createFromFormat
protected $m_bLocalizedValues; // Values in the data set are localized (see AttributeEnum)
protected $m_aExtKeysMappingCache; // Cache for resolving external keys based on the given search criterias
/** @var array<string, string> attcode as key, iCol as value */
protected $m_aAttList;
/** @var array<string, array<string, string>> sExtKeyAttCode as key, array of sExtReconcKeyAttCode/iCol as value */
protected $m_aExtKeys;
/** @var string[] list of attcode (attcode = 'id' for the pkey) */
protected $m_aReconcilKeys;
/** @var string OQL - if specified, then the missing items will be reported */
protected $m_sSynchroScope;
/**
* @var array<string, mixed> attcode as key, attvalue as value. Values to be set when an object gets out of scope
* (ignored if no scope has been defined)
*/
protected $m_aOnDisappear;
/**
* @see DateTime::createFromFormat
* @var string Date format specification
*/
protected $m_sDateFormat;
/**
* @see AttributeEnum
* @var boolean true if Values in the data set are localized
*/
protected $m_bLocalizedValues;
/** @var array Cache for resolving external keys based on the given search criterias */
protected $m_aExtKeysMappingCache;
public function __construct($sClass, $aData, $aAttList, $aExtKeys, $aReconcilKeys, $sSynchroScope = null, $aOnDisappear = null, $sDateFormat = null, $bLocalize = false)
{
@@ -261,30 +398,30 @@ class BulkChange
$this->m_sReportCsvSep = $sSeparator;
$this->m_sReportCsvDelimiter = $sDelimiter;
}
protected function ResolveExternalKey($aRowData, $sAttCode, &$aResults)
{
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$oReconFilter = new DBObjectSearch($oExtKey->GetTargetClass());
foreach ($this->m_aExtKeys[$sAttCode] as $sForeignAttCode => $iCol)
foreach ($this->m_aExtKeys[$sAttCode] as $sReconKeyAttCode => $iCol)
{
if ($sForeignAttCode == 'id')
if ($sReconKeyAttCode == 'id')
{
$value = (int) $aRowData[$iCol];
}
else
{
// The foreign attribute is one of our reconciliation key
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sReconKeyAttCode);
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
}
$oExtObjects = new CMDBObjectSet($oReconFilter);
$aKeys = $oExtObjects->ToArray();
return array($oReconFilter->ToOql(), $aKeys);
return array($oReconFilter, $aKeys);
}
// Returns true if the CSV data specifies that the external key must be left undefined
@@ -318,10 +455,10 @@ class BulkChange
{
$aResults = array();
$aErrors = array();
// External keys reconciliation
//
foreach($this->m_aExtKeys as $sAttCode => $aKeyConfig)
foreach($this->m_aExtKeys as $sAttCode => $aReconKeys)
{
// Skip external keys used for the reconciliation process
// if (!array_key_exists($sAttCode, $this->m_aAttList)) continue;
@@ -330,7 +467,7 @@ class BulkChange
if ($this->IsNullExternalKeySpec($aRowData, $sAttCode))
{
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
{
// Default reporting
// $aRowData[$iCol] is always null
@@ -352,25 +489,24 @@ class BulkChange
$oReconFilter = new DBObjectSearch($oExtKey->GetTargetClass());
$aCacheKeys = array();
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
if ($sForeignAttCode == 'id')
if ($sReconKeyAttCode == 'id')
{
$value = $aRowData[$iCol];
}
else
{
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sReconKeyAttCode);
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
$aCacheKeys[] = $value;
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
}
$sCacheKey = implode('_|_', $aCacheKeys); // Unique key for this query...
$iForeignKey = null;
$sOQL = '';
// TODO: check if *too long* keys can lead to collisions... and skip the cache in such a case...
if (!array_key_exists($sAttCode, $this->m_aExtKeysMappingCache))
{
@@ -379,9 +515,8 @@ class BulkChange
if (array_key_exists($sCacheKey, $this->m_aExtKeysMappingCache[$sAttCode]))
{
// Cache hit
$iCount = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['c'];
$iObjectFoundCount = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['c'];
$iForeignKey = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['k'];
$sOQL = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['oql'];
// Record the hit
$this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['h']++;
}
@@ -389,34 +524,35 @@ class BulkChange
{
// Cache miss, let's initialize it
$oExtObjects = new CMDBObjectSet($oReconFilter);
$iCount = $oExtObjects->Count();
if ($iCount == 1)
$iObjectFoundCount = $oExtObjects->Count();
if ($iObjectFoundCount == 1)
{
$oForeignObj = $oExtObjects->Fetch();
$iForeignKey = $oForeignObj->GetKey();
}
$this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey] = array(
'c' => $iCount,
'c' => $iObjectFoundCount,
'k' => $iForeignKey,
'oql' => $oReconFilter->ToOql(),
'h' => 0, // number of hits on this cache entry
);
}
switch($iCount)
switch($iObjectFoundCount)
{
case 0:
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-NotFound');
$aResults[$sAttCode]= new CellStatus_SearchIssue();
break;
$oCellStatus_SearchIssue = $this->GetCellSearchIssue($oReconFilter);
$aResults[$sAttCode] = $oCellStatus_SearchIssue;
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-NotFound');
break;
case 1:
// Do change the external key attribute
$oTargetObj->Set($sAttCode, $iForeignKey);
break;
// Do change the external key attribute
$oTargetObj->Set($sAttCode, $iForeignKey);
break;
default:
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $iCount);
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $iCount, $sOQL);
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $iObjectFoundCount);
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $iObjectFoundCount, $oReconFilter->serialize());
}
}
@@ -433,7 +569,7 @@ class BulkChange
else
{
$aResults[$sAttCode]= new CellStatus_Modify($iForeignObj, $oTargetObj->GetOriginal($sAttCode));
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
{
// Report the change on reconciliation values as well
$aResults[$iCol] = new CellStatus_Modify(utils::HtmlEntities($aRowData[$iCol]));
@@ -446,7 +582,7 @@ class BulkChange
}
}
}
// Set the object attributes
//
foreach ($this->m_aAttList as $sAttCode => $iCol)
@@ -487,7 +623,13 @@ class BulkChange
$value = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
if (is_null($value) && (strlen($aRowData[$iCol]) > 0))
{
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-NoMatch', $sAttCode);
if ($oAttDef instanceof AttributeEnum || $oAttDef instanceof AttributeTagSet){
/** @var AttributeDefinition $oAttributeDefinition */
$oAttributeDefinition = $oAttDef;
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-AllowedValues', $sAttCode, implode(',', $oAttributeDefinition->GetAllowedValues()));
} else {
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-NoMatch', $sAttCode);
}
}
else
{
@@ -504,7 +646,7 @@ class BulkChange
}
}
}
// Reporting on fields
//
$aChangedFields = $oTargetObj->ListChanges();
@@ -556,7 +698,7 @@ class BulkChange
}
}
}
// Checks
//
$res = $oTargetObj->CheckConsistency();
@@ -567,12 +709,101 @@ class BulkChange
}
return $aResults;
}
/**
* search with current permissions did not match
* let's search why and give some more feedbacks to the user through proper labels
*
* @param DBObjectSearch $oDbSearchWithConditions search used to find external key
*
* @return \CellStatus_SearchIssue
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*
* @since 3.1.0 N°5305
*/
protected function GetCellSearchIssue($oDbSearchWithConditions) : CellStatus_SearchIssue {
//current search with current permissions did not match
//let's search why and give some more feedback to the user
$sSerializedSearch = $oDbSearchWithConditions->serialize();
// Count all objects with all permissions without any condition
$oDbSearchWithoutAnyCondition = new DBObjectSearch($oDbSearchWithConditions->GetClass());
$oDbSearchWithoutAnyCondition->AllowAllData(true);
$oExtObjectSet = new CMDBObjectSet($oDbSearchWithoutAnyCondition);
$iAllowAllDataObjectCount = $oExtObjectSet->Count();
if ($iAllowAllDataObjectCount === 0) {
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject', $oDbSearchWithConditions->GetClass());
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
}
// Count all objects with current user permissions
$oDbSearchWithoutAnyCondition->AllowAllData(false);
$oExtObjectSetWithCurrentUserPermissions = new CMDBObjectSet($oDbSearchWithoutAnyCondition);
$iCurrentUserRightsObjectCount = $oExtObjectSetWithCurrentUserPermissions->Count();
if ($iCurrentUserRightsObjectCount === 0){
// No objects visible by current user
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject-ForCurrentUser', $oDbSearchWithConditions->GetClass());
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
}
try{
$aDisplayedAllowedValues = [];
// Possibles values are displayed to UI user. we have to limit the amount of displayed values
$oExtObjectSetWithCurrentUserPermissions->SetLimit(4);
for($i = 0; $i < 3; $i++){
/** @var \DBObject $oVisibleObject */
$oVisibleObject = $oExtObjectSetWithCurrentUserPermissions->Fetch();
if (is_null($oVisibleObject)){
break;
}
$aCurrentAllowedValueFields = [];
foreach ($oDbSearchWithConditions->GetInternalParams() as $sForeignAttCode => $sValue){
$aCurrentAllowedValueFields[] = $oVisibleObject->Get($sForeignAttCode);
}
$aDisplayedAllowedValues[] = implode(" ", $aCurrentAllowedValueFields);
}
$allowedValues = implode(", ", $aDisplayedAllowedValues);
if ($oExtObjectSetWithCurrentUserPermissions->Count() > 3){
$allowedValues .= "...";
}
} catch(Exception $e) {
IssueLog::Error("failure during CSV import when fetching few visible objects: ", null,
[ 'target_class' => $oDbSearchWithConditions->GetClass(), 'criteria' => $oDbSearchWithConditions->GetCriteria(), 'message' => $e->getMessage()]
);
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject-ForCurrentUser', $oDbSearchWithConditions->GetClass());
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
}
if ($iAllowAllDataObjectCount != $iCurrentUserRightsObjectCount) {
// No match and some objects NOT visible by current user. including current search maybe...
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-SomeObjectNotVisibleForCurrentUser', $oDbSearchWithConditions->GetClass());
return new CellStatus_SearchIssue($sSerializedSearch, $sReason, $oDbSearchWithConditions->GetClass(), $allowedValues);
}
// No match. This is not linked to any right issue
// Possible values: DD,DD
$aCurrentValueFields = [];
foreach ($oDbSearchWithConditions->GetInternalParams() as $sValue){
$aCurrentValueFields[] = $sValue;
}
$value =implode(" ", $aCurrentValueFields);
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch', $value);
return new CellStatus_SearchIssue($sSerializedSearch, $sReason, $oDbSearchWithConditions->GetClass(), $allowedValues);
}
protected function PrepareMissingObject(&$oTargetObj, &$aErrors)
{
$aResults = array();
$aErrors = array();
// External keys
//
foreach($this->m_aExtKeys as $sAttCode => $aKeyConfig)
@@ -585,7 +816,7 @@ class BulkChange
$aResults[$iCol] = new CellStatus_Void('?');
}
}
// Update attributes
//
foreach($this->m_aOnDisappear as $sAttCode => $value)
@@ -596,7 +827,7 @@ class BulkChange
}
$oTargetObj->Set($sAttCode, $value);
}
// Reporting on fields
//
$aChangedFields = $oTargetObj->ListChanges();
@@ -616,7 +847,7 @@ class BulkChange
$aResults[$iCol]= new CellStatus_Void($oTargetObj->Get($sAttCode));
}
}
// Checks
//
$res = $oTargetObj->CheckConsistency();
@@ -674,14 +905,16 @@ class BulkChange
}
$aResult[$iRow] = $this->PrepareObject($oTargetObj, $aRowData, $aErrors);
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
//__ERRORS__ used by tests only
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
return $oTargetObj;
}
// Check that any external key will have a value proposed
$aMissingKeys = array();
foreach (MetaModel::GetExternalKeys($this->m_sClass) as $sExtKeyAttCode => $oExtKey)
@@ -689,7 +922,7 @@ class BulkChange
if (!$oExtKey->IsNullAllowed())
{
if (!array_key_exists($sExtKeyAttCode, $this->m_aExtKeys) && !array_key_exists($sExtKeyAttCode, $this->m_aAttList))
{
{
$aMissingKeys[] = $oExtKey->GetLabel();
}
}
@@ -745,14 +978,16 @@ class BulkChange
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
//__ERRORS__ used by tests only
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
return;
}
$aChangedFields = $oTargetObj->ListChanges();
if (count($aChangedFields) > 0)
{
$aResult[$iRow]["__STATUS__"] = new RowStatus_Modify(count($aChangedFields));
// Optionaly record the results
//
if ($oChange)
@@ -794,9 +1029,11 @@ class BulkChange
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
//__ERRORS__ used by tests only
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
return;
}
$aChangedFields = $oTargetObj->ListChanges();
if (count($aChangedFields) > 0)
{
@@ -821,7 +1058,7 @@ class BulkChange
$aResult[$iRow]["__STATUS__"] = new RowStatus_Disappeared(0);
}
}
public function Process(CMDBChange $oChange = null)
{
if ($oChange)
@@ -866,7 +1103,7 @@ class BulkChange
foreach ($this->m_aAttList as $sAttCode => $iCol)
{
if ($sAttCode == 'id') continue;
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
{
@@ -881,14 +1118,18 @@ class BulkChange
$sFormat = $sDateFormat;
}
$oFormat = new DateTimeFormat($sFormat);
$sDateExample = $oFormat->Format(new DateTime('2022-10-23 16:25:33'));
$sRegExp = $oFormat->ToRegExpr('/');
if (!preg_match($sRegExp, $this->m_aData[$iRow][$iCol]))
$sErrorMsg = Dict::Format('UI:CSVReport-Row-Issue-ExpectedDateFormat', $sDateExample);
if (!preg_match($sRegExp, $sValue))
{
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$iCol] = new CellStatus_Issue(utils::HtmlEntities($sValue), null, $sErrorMsg);
}
else
{
$oDate = DateTime::createFromFormat($sFormat, $this->m_aData[$iRow][$iCol]);
$oDate = DateTime::createFromFormat($sFormat, $sValue);
if ($oDate !== false)
{
$sNewDate = $oDate->format($oAttDef->GetInternalFormat());
@@ -898,7 +1139,7 @@ class BulkChange
{
// Leave the cell unchanged
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, utils::HtmlEntities($this->m_aData[$iRow][$iCol]), Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
}
}
}
@@ -952,23 +1193,26 @@ class BulkChange
else
{
// The value has to be found or verified
list($sQuery, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
/** var DBObjectSearch $oReconFilter */
list($oReconFilter, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
if (count($aMatches) == 1)
{
$oRemoteObj = reset($aMatches); // first item
$valuecondition = $oRemoteObj->GetKey();
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oRemoteObj->GetKey());
}
}
elseif (count($aMatches) == 0)
{
$aResult[$iRow][$sAttCode] = new CellStatus_SearchIssue();
}
$oCellStatus_SearchIssue = $this->GetCellSearchIssue($oReconFilter);
$aResult[$iRow][$sAttCode] = $oCellStatus_SearchIssue;
}
else
{
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $sQuery);
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $oReconFilter->serialize());
}
}
}
}
else
{
@@ -1019,7 +1263,7 @@ class BulkChange
default:
// Found several matches, ambiguous
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Ambiguous'));
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->ToOql());
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->serialize());
$aResult[$iRow]["finalclass"]= 'n/a';
}
}
@@ -1110,7 +1354,7 @@ class BulkChange
}
}
$oBulkChanges->Seek(0);
$aDetails = array();
while ($oChange = $oBulkChanges->Fetch())
{
@@ -1274,7 +1518,7 @@ EOF
$oOldTarget = MetaModel::GetObject($oAttDef->GetTargetClass(), $oOperation->Get('oldvalue'));
$sOldValue = $oOldTarget->GetHyperlink();
}
$sNewValue = Dict::S('UI:UndefinedObject');
if ($oOperation->Get('newvalue') != 0)
{
@@ -1300,11 +1544,11 @@ EOF
}
else
{
$aAttributes[$sAttCode] = 1;
$aAttributes[$sAttCode] = 1;
}
}
}
$aDetails = array();
foreach($aObjects as $iUId => $aObjData)
{
@@ -1356,6 +1600,6 @@ EOF
$aConfig[$sAttCode] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'description' => MetaModel::GetDescription($sClass, $sAttCode));
}
$oPage->table($aConfig, $aDetails);
}
}
}

View File

@@ -79,22 +79,30 @@ class CMDBChangeOp extends DBObject implements iCMDBChangeOp
/**
* @inheritDoc
*/
*/
public function GetDescription()
{
return '';
}
/**
* Safety net: in case the change is not given, let's guarantee that it will
* be set to the current ongoing change (or create a new one)
*/
* Safety net:
* * if change isn't persisted yet, use the current change and persist it if needed
* * in case the change is not given, let's guarantee that it will be set to the current ongoing change (or create a new one)
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 do persist the current change if needed
*/
protected function OnInsert()
{
if ($this->Get('change') <= 0)
{
$this->Set('change', CMDBObject::GetCurrentChange());
$iChange = $this->Get('change');
if (($iChange <= 0) || (is_null($iChange))) {
$oChange = CMDBObject::GetCurrentChange();
if ($oChange->IsNew()) {
$oChange->DBWrite();
}
$this->Set('change', $oChange);
}
parent::OnInsert();
}
}
@@ -353,7 +361,8 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "target" => '_blank', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
//old value can have an old validation pattern -> force it to anything
MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "target" => '_blank', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array(), "validation_pattern" => '.*')));
MetaModel::Init_AddAttribute(new AttributeURL("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "target" => '_blank', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
@@ -1077,7 +1086,7 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
{
$oField = new FieldExpression('objclass', $oSearch->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($aLinkClasses)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
$oSearch->AddConditionExpression($oNewCondition);
}

View File

@@ -3,7 +3,7 @@
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -113,6 +113,26 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange = $oChange;
}
/**
* @param string $sUserInfo
* @param string $sOrigin
* @param \DateTime $oDate
*
* @throws \CoreException
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 new method to reset current change
*/
public static function SetCurrentChangeFromParams($sUserInfo, $sOrigin = null, $oDate = null)
{
static::SetTrackInfo($sUserInfo);
static::SetTrackOrigin($sOrigin);
static::CreateChange();
if (!is_null($oDate)) {
static::$m_oCurrChange->Set("date", $oDate);
}
}
//
// Todo: simplify the APIs and do not pass the current change as an argument anymore
// SetTrackInfo to be invoked in very few cases (UI.php, CSV import, Data synchro)
@@ -144,6 +164,8 @@ abstract class CMDBObject extends DBObject
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
* $iChangeId = $oMyChange->DBInsert();
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetCurrentChange to specify a CMDBObject instance instead
*
* @param string $sInfo
@@ -171,6 +193,8 @@ abstract class CMDBObject extends DBObject
/**
* Provides information about the origin of the change
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetTrackInfo
* @see SetCurrentChange to specify a CMDBObject instance instead
*
@@ -181,19 +205,21 @@ abstract class CMDBObject extends DBObject
{
self::$m_sOrigin = $sOrigin;
}
/**
* Get the additional information (defaulting to user name)
*/
protected static function GetTrackInfo()
*/
public static function GetTrackInfo()
{
if (is_null(self::$m_sInfo))
{
if (is_null(self::$m_sInfo)) {
return CMDBChange::GetCurrentUserName();
}
else
{
return self::$m_sInfo;
} else {
//N°5135 - add impersonation information in activity log/current cmdb change
if (UserRights::IsImpersonated()){
return sprintf("%s (%s)", CMDBChange::GetCurrentUserName(), self::$m_sInfo);
} else {
return self::$m_sInfo;
}
}
}
@@ -206,7 +232,10 @@ abstract class CMDBObject extends DBObject
*/
protected static function GetTrackUserId()
{
if (is_null(self::$m_sUserId))
if (is_null(self::$m_sUserId)
//N°5135 - indicate impersonation inside changelogs
&& (false === UserRights::IsImpersonated())
)
{
return CMDBChange::GetCurrentUserId();
}
@@ -215,10 +244,10 @@ abstract class CMDBObject extends DBObject
return self::$m_sUserId;
}
}
/**
* Get the 'origin' information (defaulting to 'interactive')
*/
*/
protected static function GetTrackOrigin()
{
if (is_null(self::$m_sOrigin))
@@ -243,15 +272,17 @@ abstract class CMDBObject extends DBObject
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 {@see CMDBChange} **will be persisted later** in {@see \CMDBChangeOp::OnInsert} (was done previously directly here)
* This will avoid creating in DB CMDBChange lines without any corresponding CMDBChangeOp
*/
protected static function CreateChange()
public static function CreateChange()
{
self::$m_oCurrChange = MetaModel::NewObject("CMDBChange");
self::$m_oCurrChange->Set("date", time());
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
self::$m_oCurrChange->Set("user_id", self::GetTrackUserId());
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
self::$m_oCurrChange->DBInsert();
}
/**
@@ -601,7 +632,7 @@ abstract class CMDBObject extends DBObject
protected function DBCloneTracked_Internal($newKey = null)
{
$newKey = parent::DBClone($newKey);
$oClone = MetaModel::GetObject(get_class($this), $newKey);
$oClone = MetaModel::GetObject(get_class($this), $newKey);
return $newKey;
}
@@ -614,7 +645,7 @@ abstract class CMDBObject extends DBObject
{
return;
}
$ret = parent::DBUpdate();
return $ret;
}
@@ -738,11 +769,11 @@ abstract class CMDBObject extends DBObject
class CMDBObjectSet extends DBObjectSet
{
// this is the public interface (?)
// I have to define those constructors here... :-(
// just to get the right object class in return.
// I have to think again to those things: maybe it will work fine if a have a constructor define here (?)
static public function FromScratch($sClass)
{
$oFilter = new DBObjectSearch($sClass);
@@ -751,7 +782,7 @@ class CMDBObjectSet extends DBObjectSet
// NOTE: THIS DOES NOT WORK IF m_bLoaded is private in the base class (and you will not get any error message)
$oRetSet->m_bLoaded = true; // no DB load
return $oRetSet;
}
}
// create an object set ex nihilo
// input = array of objects
@@ -760,7 +791,7 @@ class CMDBObjectSet extends DBObjectSet
$oRetSet = self::FromScratch($sClass);
$oRetSet->AddObjectArray($aObjects, $sClass);
return $oRetSet;
}
}
static public function FromArrayAssoc($aClasses, $aObjects)
{

View File

@@ -350,6 +350,12 @@ class CMDBSource
}
/**
* @return string
* @throws \MySQLException
*
* @uses \CMDBSource::QueryToCol() so needs a connection opened !
*/
public static function GetDBVersion()
{
$aVersions = self::QueryToCol('SELECT Version() as version', 'version');
@@ -367,8 +373,10 @@ class CMDBSource
/**
* Get the DB vendor between MySQL and its main forks
* @return string
*
* @uses \CMDBSource::GetServerVariable() so needs a connection opened !
*/
static public function GetDBVendor()
public static function GetDBVendor()
{
$sDBVendor = static::ENUM_DB_VENDOR_MYSQL;
@@ -672,13 +680,13 @@ class CMDBSource
private static function StartTransaction()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
$bHasExistingTransactions = self::IsInsideTransaction();
if (!$bHasExistingTransactions) {
IssueLog::Trace("START TRANSACTION $sCaller", LogChannels::CMDB_SOURCE);
IssueLog::Trace("START TRANSACTION was sent to the DB", LogChannels::CMDB_SOURCE, ['stacktrace' => $aStackTrace]);
self::DBQuery('START TRANSACTION');
} else {
IssueLog::Trace("Ignore nested (".self::$m_iTransactionLevel.") START TRANSACTION $sCaller", LogChannels::CMDB_SOURCE);
IssueLog::Trace("START TRANSACTION ignored as a transaction is already opened", LogChannels::CMDB_SOURCE, ['stacktrace' => $aStackTrace]);
}
self::AddTransactionLevel();
@@ -697,7 +705,11 @@ class CMDBSource
private static function Commit()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
if(isset($aStackTrace[2]['class']) && isset($aStackTrace[2]['function'])) {
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
} else {
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].') ';
}
if (!self::IsInsideTransaction()) {
// should not happen !
IssueLog::Error("No Transaction COMMIT $sCaller", LogChannels::CMDB_SOURCE);
@@ -731,7 +743,11 @@ class CMDBSource
private static function Rollback()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
if(isset($aStackTrace[2]['class']) && isset($aStackTrace[2]['function'])) {
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
} else {
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].') ';
}
if (!self::IsInsideTransaction()) {
// should not happen !
IssueLog::Error("No Transaction ROLLBACK $sCaller", LogChannels::CMDB_SOURCE);

View File

@@ -22,7 +22,15 @@
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
define('ITOP_VERSION', '3.0.0-dev');
/**
* Constant containing the application version
* Warning: this might be different from iTop core version!
*
* @see ITOP_CORE_VERSION to get iTop core version
*/
define('ITOP_VERSION', '3.0.1-dev');
define('ITOP_VERSION_NAME', 'Fullmoon');
define('ITOP_REVISION', 'svn');
define('ITOP_BUILD_DATE', '$WCNOW$');
@@ -481,13 +489,21 @@ class Config
'show_in_conf_sample' => true,
],
'cron_max_execution_time' => [
'type' => 'integer',
'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout',
'default' => 600,
'value' => 600,
'source_of_value' => '',
'type' => 'integer',
'description' => 'Duration (seconds) of the cron.php script : if exceeded the script will exit even if there are remaining tasks to process. Must be shorter than php max_execution_time setting (note than when using CLI, this is set to 0 by default which means unlimited). If cron.php is ran via web, it must be shorter than the web server response timeout.',
'default' => 600,
'value' => 600,
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'cron_task_max_execution_time' => [
'type' => 'integer',
'description' => 'Background tasks will use this value (integer) multiplicated by its periodicity (in seconds) as max duration per cron execution. 0 is unlimited time',
'default' => 0,
'value' => 0,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'cron_sleep' => [
'type' => 'integer',
'description' => 'Duration (seconds) before cron.php checks again if something must be done',
@@ -514,7 +530,7 @@ class Config
],
'email_transport' => [
'type' => 'string',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)',
'description' => 'Mean to send emails: PHPMail (uses the function mail()), SMTP (implements the client protocol) or SMTP_OAuth (connect to the server using OAuth 2.0)',
'default' => "PHPMail",
'value' => "PHPMail",
'source_of_value' => '',
@@ -536,7 +552,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'email_transport_smtp.encryption' => [
'email_transport_smtp.encryption' => [
'type' => 'string',
'description' => 'tls or ssl (optional)',
'default' => "",
@@ -544,28 +560,28 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'email_transport_smtp.username' => [
'type' => 'string',
'description' => 'Authentication user (optional)',
'default' => "",
'value' => "",
'source_of_value' => '',
'email_transport_smtp.username' => [
'type' => 'string',
'description' => 'Authentication user (optional)',
'default' => "",
'value' => "",
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'email_transport_smtp.password' => [
'type' => 'string',
'description' => 'Authentication password (optional)',
'default' => "",
'value' => "",
'source_of_value' => '',
'email_transport_smtp.password' => [
'type' => 'string',
'description' => 'Authentication password (optional)',
'default' => "",
'value' => "",
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'email_css' => [
'type' => 'string',
'description' => 'CSS that will override the standard stylesheet used for the notifications',
'default' => "",
'value' => "",
'source_of_value' => '',
'email_css' => [
'type' => 'string',
'description' => 'CSS that will override the standard stylesheet used for the notifications',
'default' => "",
'value' => "",
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'email_default_sender_address' => [
@@ -608,6 +624,13 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
/**
* The timezone is automatically set using this parameter in \utils::InitTimeZone
* This method is called almost everywhere, cause it's called in \MetaModel::LoadConfig and exec.php... but you might
* need to get it yourself !
*
* @used-by utils::InitTimeZone()
*/
'timezone' => [
'type' => 'string',
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitly configured in PHP',
@@ -851,13 +874,23 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'impact_analysis_lazy_loading' => [
'type' => 'bool',
'description' => 'In the impact analysis view: display the analysis or filter before display',
'default' => false,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'url_validation_pattern' => [
'type' => 'string',
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
'default' => '(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?',
// SHEME.......... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH........................ GET............................................ ANCHOR............................
'default' => /** @lang RegExp */
'(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9:%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z0-9_.-][a-zA-Z0-9+\$_.-]*)?',
// SCHEME....... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH......................... GET............................................ ANCHOR..........................
// Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor
// Origin of this regexp: http://www.php.net/manual/fr/function.preg-match.php#93824
// RegExp source: http://www.php.net/manual/fr/function.preg-match.php#93824
// Update with N°4515
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
@@ -975,8 +1008,8 @@ class Config
'type' => 'integer',
'description' => 'Maximum length of the history table (in the "History" tab on each object) before it gets truncated. Latest modifications are displayed first.',
// examples... not used
'default' => 50,
'value' => 50,
'default' => 200,
'value' => 200,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
@@ -1175,7 +1208,7 @@ class Config
],
'compatibility.include_deprecated_js_files' => [
'type' => 'bool',
'description' => 'Include the deprecated JS files to ease usage of not migrated extensions',
'description' => 'Include the deprecated JS files (in iTop previous version) to ease usage of not migrated extensions',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -1191,7 +1224,7 @@ class Config
],
'compatibility.include_deprecated_css_files' => [
'type' => 'bool',
'description' => 'Include the deprecated CSS files to ease usage of not migrated extensions',
'description' => 'Include the deprecated CSS files (in iTop previous version) to ease usage of not migrated extensions',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -1205,6 +1238,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'navigation_menu.show_organization_filter' => [
'type' => 'bool',
'description' => 'Display organization filter in menu',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'quick_create.enabled' => [
'type' => 'bool',
'description' => 'Whether or not the quick create is enabled',
@@ -1423,14 +1464,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'use_legacy_dbsearch' => [
'type' => 'bool',
'description' => 'If set, DBSearch will use legacy SQL query generation',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'query_cache_enabled' => [
'type' => 'bool',
'description' => 'If set, DBSearch will use cache for query generation',
@@ -1600,6 +1633,16 @@ class Config
return $this->m_aSettings[$sPropCode]['value'];
}
/**
* @return mixed
*
* @since 3.0.1 N°4515
*/
public function GetDefault(string $sPropCode)
{
return $this->m_aSettings[$sPropCode]['default'];
}
/**
* Whether the $sPropCode parameter has a custom value or the default one.
*
@@ -1826,7 +1869,7 @@ class Config
}
if (strlen($sNoise) > 0)
{
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
throw new ConfigException('Syntax error in configuration file',
array('file' => $sConfigFile, 'error' => '<tt>'.htmlentities($sNoise, ENT_QUOTES, 'UTF-8').'</tt>'));
}
@@ -2636,7 +2679,7 @@ class ConfigPlaceholdersResolver
}
$sPattern = '/\%(env|server)\((\w+)\)(?:\?:(\w*))?\%/'; //3 capturing groups, ie `%env(HTTP_PORT)?:8080%` produce: `env` `HTTP_PORT` and `8080`.
if (! preg_match_all($sPattern, $rawValue, $aMatchesCollection, PREG_SET_ORDER))
{
return $rawValue;

View File

@@ -220,16 +220,15 @@ class CSVBulkExport extends TabularBulkExport
$sFormatInput = '<input type="text" size="15" name="date_format" id="csv_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "csv_date_format_radio", "custom", "csv_date_time_format_custom", "radio");
$oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip'));
$oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat());
$oRadioCustom->SetBeforeInput(false);
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oFieldSetDate->AddSubBlock($oRadioCustom);
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
$oP->add_ready_script(
<<<EOF
$('#csv_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
$('#form_part_csv_options').on('preview_updated', function() { FormatDatesInPreview('csv', 'csv'); });
$('#csv_date_time_format_default').on('click', function() { FormatDatesInPreview('csv', 'csv'); });
$('#csv_date_time_format_custom').on('click', function() { FormatDatesInPreview('csv', 'csv'); });

View File

@@ -1,6 +1,6 @@
<?php
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @copyright Copyright (C) 2010-2022 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -1471,7 +1471,7 @@ abstract class DBObject implements iDisplay
public function GetIcon($bImgTag = true)
{
$sClass = get_class($this);
if($this->HasHighlightIcon()) {
$sIconUrl = MetaModel::GetHighlightScale($sClass)[$this->ComputeHighlightCode()]['icon'];
if($bImgTag) {
@@ -1506,7 +1506,7 @@ abstract class DBObject implements iDisplay
{
$bHasInstanceIcon = false;
$sClass = get_class($this);
if (!$this->IsNew() && MetaModel::HasImageAttributeCode($sClass)) {
$sImageAttCode = MetaModel::GetImageAttributeCode($sClass);
if (!empty($sImageAttCode)) {
@@ -1515,7 +1515,7 @@ abstract class DBObject implements iDisplay
$bHasInstanceIcon = !$oImage->IsEmpty();
}
}
return $bHasInstanceIcon;
}
@@ -1540,7 +1540,7 @@ abstract class DBObject implements iDisplay
$bHasHighlightIcon = true;
}
}
return $bHasHighlightIcon;
}
@@ -1929,7 +1929,7 @@ abstract class DBObject implements iDisplay
/** @var \AttributeExternalKey $oAtt */
$sTargetClass = $oAtt->GetTargetClass();
if (false === MetaModel::IsObjectInDB($sTargetClass, $toCheck)) {
return "Target object not found ($sTargetClass::$toCheck)";
return "Target object not found (".$sTargetClass.".::".$toCheck.")";
}
}
if ($oAtt->IsHierarchicalKey())
@@ -2026,9 +2026,9 @@ abstract class DBObject implements iDisplay
/**
* check attributes together
*
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return bool
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return true|string true if successful, the error description otherwise
*/
public function CheckConsistency()
{
@@ -2249,8 +2249,9 @@ abstract class DBObject implements iDisplay
foreach($aChanges as $sAttCode => $value) {
$res = $this->CheckValue($sAttCode);
if ($res !== true) {
$sAttLabel = $this->GetLabel($sAttCode);
// $res contains the error description
$this->m_aCheckIssues[] = "Unexpected value for attribute '$sAttCode': $res";
$this->m_aCheckIssues[] = Dict::Format('Core:CheckValueError', $sAttLabel, $sAttCode, $res);
}
$this->DoCheckLinkedSetDuplicates($sAttCode, $value);
@@ -2265,7 +2266,7 @@ abstract class DBObject implements iDisplay
if ($res !== true)
{
// $res contains the error description
$this->m_aCheckIssues[] = "Consistency rules not followed: $res";
$this->m_aCheckIssues[] = Dict::Format('Core:CheckConsistencyError', $res);
}
// Synchronization: are we attempting to modify an attribute for which an external source is master?
@@ -2278,12 +2279,10 @@ abstract class DBObject implements iDisplay
if ($iFlags & OPT_ATT_SLAVE)
{
// Note: $aReasonInfo['name'] could be reported (the task owning the attribute)
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
if (!empty($aReasons))
{
// Todo: associate the attribute code with the error
$this->m_aCheckIssues[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $sAttLabel);
$sAttLabel = $this->GetLabel($sAttCode);
$this->m_aCheckIssues[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $sAttLabel, $sAttCode);
}
}
}
@@ -2935,6 +2934,9 @@ abstract class DBObject implements iDisplay
}
}
// - TriggerOnObjectMention
$this->ActivateOnMentionTriggers(true);
return $this->m_iKey;
}
@@ -3197,60 +3199,17 @@ abstract class DBObject implements iDisplay
// Activate any existing trigger
$sClass = get_class($this);
// - TriggerOnObjectMention
// 1 - Check if any caselog updated
$aUpdatedLogAttCodes = array();
foreach($aChanges as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if($oAttDef instanceof AttributeCaseLog)
{
$aUpdatedLogAttCodes[] = $sAttCode;
}
}
// 2 - Find mentioned objects
$aMentionedObjects = array();
foreach ($aUpdatedLogAttCodes as $sAttCode) {
/** @var \ormCaseLog $oUpdatedCaseLog */
$oUpdatedCaseLog = $this->Get($sAttCode);
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
}
// 3 - Trigger for those objects
// TODO: This should be refactored and moved into the caselogs loop, otherwise, we won't be able to know which case log triggered the action.
foreach ($aMentionedObjects as $sMentionedClass => $aMentionedIds) {
foreach ($aMentionedIds as $sMentionedId) {
/** @var \DBObject $oMentionedObject */
$oMentionedObject = MetaModel::GetObject($sMentionedClass, $sMentionedId);
$aTriggerArgs = $this->ToArgs('this') + array('mentioned->object()' => $oMentionedObject);
$this->ActivateOnMentionTriggers(false);
$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectMention AS t WHERE t.target_class IN (:class_list)"), array(), $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectMention $oTrigger */
try {
// Ensure to handle only mentioned object in the trigger's scope
if ($oTrigger->IsMentionedObjectInScope($oMentionedObject) === false) {
continue;
}
$oTrigger->DoActivate($aTriggerArgs);
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
}
$bHasANewExternalKeyValue = false;
$bNeedReload = false;
$aHierarchicalKeys = array();
$aDBChanges = array();
foreach ($aChanges as $sAttCode => $valuecurr)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAttDef->IsExternalKey())
if ($oAttDef->IsExternalKey() || $oAttDef->IsLinkSet())
{
$bHasANewExternalKeyValue = true;
$bNeedReload = true;
}
if ($oAttDef->IsBasedOnDBColumns())
{
@@ -3408,24 +3367,10 @@ abstract class DBObject implements iDisplay
$this->m_aModifiedAtt = array();
try {
// - TriggerOnObjectUpdate
$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)"),
array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
$oTrigger->DoActivate($this->ToArgs('this'));
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
$this->AfterUpdate();
// Reload to get the external attributes
if ($bHasANewExternalKeyValue) {
if ($bNeedReload) {
$this->Reload(true /* AllowAllData */);
} else {
// Reset original values although the object has not been reloaded
@@ -3438,6 +3383,20 @@ abstract class DBObject implements iDisplay
}
}
}
// - TriggerOnObjectUpdate
$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)'),
array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
$oTrigger->DoActivate($this->ToArgs('this'));
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
catch (Exception $e)
{
@@ -3453,6 +3412,74 @@ abstract class DBObject implements iDisplay
return $this->m_iKey;
}
/**
* Activate TriggerOnObjectMention triggers for the current object
*
* @param bool $bNewlyCreatedObject
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
* @since 3.0.1 N°4741
*/
private function ActivateOnMentionTriggers(bool $bNewlyCreatedObject): void
{
$sClass = get_class($this);
$aChanges = $bNewlyCreatedObject ? $this->m_aOrigValues : $this->ListChanges();
// 1 - Check if any caselog updated
$aUpdatedLogAttCodes = [];
foreach ($aChanges as $sAttCode => $value) {
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeCaseLog) {
// Skip empty log on creation
if ($bNewlyCreatedObject && $value->GetModifiedEntry() === '') {
continue;
}
$aUpdatedLogAttCodes[] = $sAttCode;
}
}
// 2 - Find mentioned objects
$aMentionedObjects = [];
foreach ($aUpdatedLogAttCodes as $sAttCode) {
/** @var \ormCaseLog $oUpdatedCaseLog */
$oUpdatedCaseLog = $this->Get($sAttCode);
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
}
// 3 - Trigger for those objects
// TODO: This should be refactored and moved into the caselogs loop, otherwise, we won't be able to know which case log triggered the action.
foreach ($aMentionedObjects as $sMentionedClass => $aMentionedIds) {
foreach ($aMentionedIds as $sMentionedId) {
/** @var \DBObject $oMentionedObject */
$oMentionedObject = MetaModel::GetObject($sMentionedClass, $sMentionedId);
$aTriggerArgs = $this->ToArgs('this') + ['mentioned->object()' => $oMentionedObject];
$aParams = ['class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectMention AS t WHERE t.target_class IN (:class_list)"), [], $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectMention $oTrigger */
try {
// Ensure to handle only mentioned object in the trigger's scope
if ($oTrigger->IsMentionedObjectInScope($oMentionedObject) === false) {
continue;
}
$oTrigger->DoActivate($aTriggerArgs);
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
}
}
/**
* @internal
* Save updated fields previous values for {@see DBObject::DBUpdate()} callbacks
@@ -3741,7 +3768,7 @@ abstract class DBObject implements iDisplay
}
/**
* @internal
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return array
*
@@ -4358,14 +4385,22 @@ abstract class DBObject implements iDisplay
$sAttCode = $sPlaceholderAttCode;
}
if ($sVerb == 'hyperlink')
if (in_array($sVerb, ['hyperlink', 'url']))
{
$sPortalId = ($sAttCode === '') ? 'console' : $sAttCode;
if (!array_key_exists($sPortalId, self::$aPortalToURLMaker))
{
throw new Exception("Unknown portal id '$sPortalId' in placeholder '$sPlaceholderAttCode''");
}
$ret = $this->GetHyperlink(self::$aPortalToURLMaker[$sPortalId], false);
if($sVerb == 'hyperlink')
{
$ret = $this->GetHyperlink(self::$aPortalToURLMaker[$sPortalId], false);
}
else
{
$ret = ApplicationContext::MakeObjectUrl(get_class($this), $this->GetKey(), self::$aPortalToURLMaker[$sPortalId], false);
}
}
else
{
@@ -5378,7 +5413,7 @@ abstract class DBObject implements iDisplay
}
$oLnk->Set($sRoleAttCode, $sRoleValue);
}
$oLinkSet->AddObject($oLnk);
$oLinkSet->AddItem($oLnk);
$this->Set($sTargetListAttCode, $oLinkSet);
}
break;

View File

@@ -416,6 +416,10 @@ class DBObjectSearch extends DBSearch
* @param string $sFilterCode
* @param mixed $value
* @param string $sOpCode operator to use : 'IN', 'NOT IN', 'Contains',' Begins with', 'Finishes with', ...
* If no operator is specified then :
* * for id field we will use "="
* * for other fields we will call the corresponding {@link AttributeDefinition::GetSmartConditionExpression} method impl
* to generate the expression
* @param bool $bParseSearchString
*
* @throws \CoreException
@@ -465,14 +469,14 @@ class DBObjectSearch extends DBSearch
if (!is_array($value)) $value = array($value);
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
break;
case 'NOTIN':
if (!is_array($value)) $value = array($value);
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." NOT IN $sListExpr";
$sOQLCondition = $oField->RenderExpression()." NOT IN $sListExpr";
break;
case 'Contains':
@@ -1232,7 +1236,7 @@ class DBObjectSearch extends DBSearch
elseif (MetaModel::IsParentClass($oRightFilter->GetFirstJoinedClass(), $oLeftFilter->GetClass()))
{
// Specialize $oRightFilter
$oRightFilter->ChangeClass($oLeftFilter->GetClass());
$oRightFilter->ChangeClass($oLeftFilter->GetFirstJoinedClass());
}
else
{
@@ -1368,7 +1372,7 @@ class DBObjectSearch extends DBSearch
public function GetQueryParams($bExcludeMagicParams = true)
{
$aParams = array();
$this->m_oSearchCondition->Render($aParams, true);
$this->m_oSearchCondition->RenderExpression(false, $aParams, true);
if ($bExcludeMagicParams)
{
@@ -1457,7 +1461,7 @@ class DBObjectSearch extends DBSearch
$sRes .= ' ' . $this->GetFirstJoinedClass() . ' AS `' . $this->GetFirstJoinedClassAlias() . '`';
$sRes .= $this->ToOQL_Joins();
$sRes .= " WHERE ".$this->m_oSearchCondition->Render($aParams, $bRetrofitParams);
$sRes .= " WHERE ".$this->m_oSearchCondition->RenderExpression(false, $aParams, $bRetrofitParams);
if ($bWithAllowAllFlag && $this->m_bAllowAllData)
{

View File

@@ -18,23 +18,6 @@
*/
$bUseLegacyDBSearch = utils::GetConfig()->Get('use_legacy_dbsearch');
if ($bUseLegacyDBSearch)
{
// excluded from autoload
require_once (APPROOT.'core/legacy/querybuilderexpressionslegacy.class.inc.php');
require_once (APPROOT.'core/legacy/querybuildercontextlegacy.class.inc.php');
require_once(APPROOT.'core/legacy/dbobjectsearchlegacy.class.php');
}
else
{
// excluded from autoload
require_once (APPROOT.'core/querybuilderexpressions.class.inc.php');
require_once (APPROOT.'core/querybuildercontext.class.inc.php');
require_once(APPROOT.'core/dbobjectsearch.class.php');
}
/**
* An object search
*
@@ -1659,7 +1642,7 @@ abstract class DBSearch
$oSet = new DBObjectSet($this);
if (MetaModel::IsStandaloneClass($sClass))
{
$oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array('')));
$oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array()));
$aIds = array($sClass => $oSet->GetColumnAsArray('id'));
}
else
@@ -1724,4 +1707,16 @@ abstract class DBSearch
{
$this->SetShowObsoleteData(utils::ShowObsoleteData());
}
/**
* To ease the debug of filters
* @internal
*
* @return string
*
*/
public function __toString()
{
return $this->ToOQL();
}
}

View File

@@ -416,7 +416,11 @@ class DBUnionSearch extends DBSearch
$aSearches = array();
foreach ($this->aSearches as $oSearch)
{
$aSearches[] = $oSearch->Filter($sClassAlias, $oFilter);
if (!$oSearch->IsAllDataAllowed()) {
$aSearches[] = $oSearch->Filter($sClassAlias, $oFilter);
} else {
$aSearches[] = $oSearch;
}
}
return new DBUnionSearch($aSearches);
}

View File

@@ -26,8 +26,10 @@
namespace Combodo\iTop;
use \DOMDocument;
use \DOMFormatException;
use DOMDocument;
use DOMFormatException;
use IssueLog;
use LogAPI;
/**
* Class \Combodo\iTop\DesignDocument
@@ -64,9 +66,13 @@ class DesignDocument extends DOMDocument
* @param $filename
* @param int $options
*/
public function load($filename, $options = 0)
public function load($filename, $options = null)
{
parent::load($filename, LIBXML_NOBLANKS);
libxml_clear_errors();
if (parent::load($filename, LIBXML_NOBLANKS) === false) {
$aErrors = libxml_get_errors();
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
}
}
/**
@@ -77,10 +83,10 @@ class DesignDocument extends DOMDocument
*
* @return int
*/
public function save($filename, $options = 0)
public function save($filename, $options = null)
{
$this->documentElement->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
return parent::save($filename, LIBXML_NOBLANKS);
return parent::save($filename);
}
/**

View File

@@ -302,13 +302,12 @@ class Dict
*
* @param $sSourceCode
* @param $sDestCode
* @since 3.0.1 Not clone sSourceCode entry if sDestCode entry already exist
*/
public static function CloneString($sSourceCode, $sDestCode)
{
foreach(self::$m_aLanguages as $sLanguageCode => $foo)
{
if (isset(self::$m_aData[$sLanguageCode][$sSourceCode]))
{
foreach(self::$m_aLanguages as $sLanguageCode => $foo) {
if (isset(self::$m_aData[$sLanguageCode][$sSourceCode]) && !isset(self::$m_aData[$sLanguageCode][$sDestCode] )) {
self::$m_aData[$sLanguageCode][$sDestCode] = self::$m_aData[$sLanguageCode][$sSourceCode];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2021 Combodo SARL
// Copyright (C) 2010-2022 Combodo SARL
//
// This file is part of iTop.
//
@@ -20,13 +20,12 @@
/**
* Send an email (abstraction for synchronous/asynchronous modes)
*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @copyright Copyright (C) 2010-2022 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Pelago\Emogrifier\CssInliner;
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
use Combodo\iTop\Core\Email\EmailFactory;
use Combodo\iTop\Core\Email\iEMail;
Swift_Preferences::getInstance()->setCharset('UTF-8');
@@ -35,31 +34,18 @@ define ('EMAIL_SEND_OK', 0);
define ('EMAIL_SEND_PENDING', 1);
define ('EMAIL_SEND_ERROR', 2);
class EMail
class EMail implements iEMail
{
protected $oMailer;
// Serialization formats
const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object.
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed)
protected static $m_oConfig = null;
protected $m_aData; // For storing data to serialize
public function LoadConfig($sConfigFile = ITOP_DEFAULT_CONFIG_FILE)
{
if (is_null(self::$m_oConfig))
{
self::$m_oConfig = new Config($sConfigFile);
}
}
protected $m_oMessage;
public function __construct()
{
$this->m_aData = array();
$this->m_oMessage = Swift_Message::newInstance();
$this->SetRecipientFrom(MetaModel::GetConfig()->Get('email_default_sender_address'), MetaModel::GetConfig()->Get('email_default_sender_label'));
$this->oMailer = EmailFactory::GetMailer();
}
/**
@@ -70,490 +56,111 @@ class EMail
*/
public function SerializeV2()
{
return serialize($this->m_aData);
return $this->oMailer->SerializeV2();
}
/**
* Custom de-serialization method
*
* @param string $sSerializedMessage The serialized representation of the message
*
* @return \Email
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
static public function UnSerializeV2($sSerializedMessage)
{
$aData = unserialize($sSerializedMessage);
$oMessage = new Email();
if (array_key_exists('body', $aData))
{
$oMessage->SetBody($aData['body']['body'], $aData['body']['mimeType']);
}
if (array_key_exists('message_id', $aData))
{
$oMessage->SetMessageId($aData['message_id']);
}
if (array_key_exists('bcc', $aData))
{
$oMessage->SetRecipientBCC($aData['bcc']);
}
if (array_key_exists('cc', $aData))
{
$oMessage->SetRecipientCC($aData['cc']);
}
if (array_key_exists('from', $aData))
{
$oMessage->SetRecipientFrom($aData['from']['address'], $aData['from']['label']);
}
if (array_key_exists('reply_to', $aData))
{
$oMessage->SetRecipientReplyTo($aData['reply_to']['address'], $aData['reply_to']['label']);
}
if (array_key_exists('to', $aData))
{
$oMessage->SetRecipientTO($aData['to']);
}
if (array_key_exists('subject', $aData))
{
$oMessage->SetSubject($aData['subject']);
}
if (array_key_exists('headers', $aData))
{
foreach($aData['headers'] as $sKey => $sValue)
{
$oMessage->AddToHeader($sKey, $sValue);
}
}
if (array_key_exists('parts', $aData))
{
foreach($aData['parts'] as $aPart)
{
$oMessage->AddPart($aPart['text'], $aPart['mimeType']);
}
}
if (array_key_exists('attachments', $aData))
{
foreach($aData['attachments'] as $aAttachment)
{
$oMessage->AddAttachment(base64_decode($aAttachment['data']), $aAttachment['filename'], $aAttachment['mimeType']);
}
}
return $oMessage;
}
protected function SendAsynchronous(&$aIssues, $oLog = null)
{
try
{
AsyncSendEmail::AddToQueue($this, $oLog);
}
catch(Exception $e)
{
$aIssues = array($e->GetMessage());
return EMAIL_SEND_ERROR;
}
$aIssues = array();
return EMAIL_SEND_PENDING;
}
protected function SendSynchronous(&$aIssues, $oLog = null)
{
// If the body of the message is in HTML, embed all images based on attachments
$this->EmbedInlineImages();
$this->LoadConfig();
$sTransport = self::$m_oConfig->Get('email_transport');
switch ($sTransport)
{
case 'SMTP':
$sHost = self::$m_oConfig->Get('email_transport_smtp.host');
$sPort = self::$m_oConfig->Get('email_transport_smtp.port');
$sEncryption = self::$m_oConfig->Get('email_transport_smtp.encryption');
$sUserName = self::$m_oConfig->Get('email_transport_smtp.username');
$sPassword = self::$m_oConfig->Get('email_transport_smtp.password');
$oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption);
if (strlen($sUserName) > 0)
{
$oTransport->setUsername($sUserName);
$oTransport->setPassword($sPassword);
}
break;
case 'Null':
$oTransport = Swift_NullTransport::newInstance();
break;
case 'LogFile':
$oTransport = Swift_LogFileTransport::newInstance();
$oTransport->setLogFile(APPROOT.'log/mail.log');
break;
case 'PHPMail':
default:
$oTransport = Swift_MailTransport::newInstance();
}
$oMailer = Swift_Mailer::newInstance($oTransport);
$aFailedRecipients = array();
$this->m_oMessage->setMaxLineLength(0);
$oKPI = new ExecutionKPI();
try
{
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
if ($iSent === 0)
{
// Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!!
IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: '.implode(', ', $aFailedRecipients));
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
else
{
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
}
catch (Exception $e)
{
$oKPI->ComputeStats('Email Sent', 'Error received');
throw $e;
}
}
/**
* Reprocess the body of the message (if it is an HTML message)
* to replace the URL of images based on attachments by a link
* to an embedded image (i.e. cid:....)
*/
protected function EmbedInlineImages()
{
if ($this->m_aData['body']['mimeType'] == 'text/html')
{
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$this->m_aData['body']['body']); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
if ($oImagesList->length != 0)
{
foreach($oImagesList as $oImg)
{
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
{
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$oSwiftImage = new Swift_Image($oDoc->GetData(), $oDoc->GetFileName(), $oDoc->GetMimeType());
$sCid = $this->m_oMessage->embed($oSwiftImage);
$oImg->setAttribute('src', $sCid);
}
}
}
$sHtmlBody = $oDOMDoc->saveHTML();
$this->m_oMessage->setBody($sHtmlBody, 'text/html', 'UTF-8');
}
return EmailFactory::GetMailer()::UnSerializeV2($sSerializedMessage);
}
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
{
//select a default sender if none is provided.
if(empty($this->m_aData['from']['address']) && !empty($this->m_aData['to'])){
$this->SetRecipientFrom($this->m_aData['to']);
}
if ($bForceSynchronous)
{
return $this->SendSynchronous($aIssues, $oLog);
}
else
{
$bConfigASYNC = MetaModel::GetConfig()->Get('email_asynchronous');
if ($bConfigASYNC)
{
return $this->SendAsynchronous($aIssues, $oLog);
}
else
{
return $this->SendSynchronous($aIssues, $oLog);
}
}
return $this->oMailer->Send($aIssues, $bForceSynchronous, $oLog);
}
public function AddToHeader($sKey, $sValue)
{
if (!array_key_exists('headers', $this->m_aData))
{
$this->m_aData['headers'] = array();
}
$this->m_aData['headers'][$sKey] = $sValue;
if (strlen($sValue) > 0)
{
$oHeaders = $this->m_oMessage->getHeaders();
switch(strtolower($sKey))
{
case 'return-path':
$this->m_oMessage->setReturnPath($sValue);
break;
default:
$oHeaders->addTextHeader($sKey, $sValue);
}
}
$this->oMailer->AddToHeader($sKey, $sValue);
}
public function SetMessageId($sId)
{
$this->m_aData['message_id'] = $sId;
// Note: Swift will add the angle brackets for you
// so let's remove the angle brackets if present, for historical reasons
$sId = str_replace(array('<', '>'), '', $sId);
$oMsgId = $this->m_oMessage->getHeaders()->get('Message-ID');
$oMsgId->SetId($sId);
$this->oMailer->SetMessageId($sId);
}
public function SetReferences($sReferences)
{
$this->AddToHeader('References', $sReferences);
$this->oMailer->SetReferences($sReferences);
}
/**
* Set the "In-Reply-To" header to allow emails to group as a conversation in modern mail clients (GMail, Outlook 2016+, ...)
*
* @link https://en.wikipedia.org/wiki/Email#Header_fields
*
* @param string $sMessageId
*
* @since 3.0.1 N°4849
*/
public function SetInReplyTo(string $sMessageId)
{
$this->AddToHeader('In-Reply-To', $sMessageId);
}
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
{
if (($sMimeType === 'text/html') && ($sCustomStyles !== null))
{
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
}
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
$this->m_oMessage->setBody($sBody, $sMimeType);
$this->oMailer->SetBody($sBody, $sMimeType, $sCustomStyles);
}
public function AddPart($sText, $sMimeType = 'text/html')
{
if (!array_key_exists('parts', $this->m_aData))
{
$this->m_aData['parts'] = array();
}
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
$this->m_oMessage->addPart($sText, $sMimeType);
$this->oMailer->AddPart($sText, $sMimeType);
}
public function AddAttachment($data, $sFileName, $sMimeType)
{
if (!array_key_exists('attachments', $this->m_aData))
{
$this->m_aData['attachments'] = array();
}
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
$this->oMailer->AddAttachment($data, $sFileName, $sMimeType);
}
public function SetSubject($sSubject)
{
$this->m_aData['subject'] = $sSubject;
$this->m_oMessage->setSubject($sSubject);
$this->oMailer->SetSubject($sSubject);
}
public function GetSubject()
{
return $this->m_oMessage->getSubject();
return $this->oMailer->GetSubject();
}
/**
* Helper to transform and sanitize addresses
* - get rid of empty addresses
*/
protected function AddressStringToArray($sAddressCSVList)
{
$aAddresses = array();
foreach(explode(',', $sAddressCSVList) as $sAddress)
{
$sAddress = trim($sAddress);
if (strlen($sAddress) > 0)
{
$aAddresses[] = $sAddress;
}
}
return $aAddresses;
}
public function SetRecipientTO($sAddress)
{
$this->m_aData['to'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setTo($aAddresses);
}
$this->oMailer->SetRecipientTO($sAddress);
}
public function GetRecipientTO($bAsString = false)
{
$aRes = $this->m_oMessage->getTo();
if ($aRes === null)
{
// There is no "To" header field
$aRes = array();
}
if ($bAsString)
{
$aStrings = array();
foreach ($aRes as $sEmail => $sName)
{
if (is_null($sName))
{
$aStrings[] = $sEmail;
}
else
{
$sName = str_replace(array('<', '>'), '', $sName);
$aStrings[] = "$sName <$sEmail>";
}
}
return implode(', ', $aStrings);
}
else
{
return $aRes;
}
return $this->oMailer->GetRecipientTO($bAsString);
}
public function SetRecipientCC($sAddress)
{
$this->m_aData['cc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setCc($aAddresses);
}
$this->oMailer->SetRecipientCC($sAddress);
}
public function SetRecipientBCC($sAddress)
{
$this->m_aData['bcc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setBcc($aAddresses);
}
$this->oMailer->SetRecipientBCC($sAddress);
}
public function SetRecipientFrom($sAddress, $sLabel = '')
{
$this->m_aData['from'] = array('address' => $sAddress, 'label' => $sLabel);
if ($sLabel != '')
{
$this->m_oMessage->setFrom(array($sAddress => $sLabel));
}
else if (!empty($sAddress))
{
$this->m_oMessage->setFrom($sAddress);
}
$this->oMailer->SetRecipientFrom($sAddress, $sLabel);
}
public function SetRecipientReplyTo($sAddress, $sLabel = '')
{
$this->m_aData['reply_to'] = array('address' => $sAddress, 'label' => $sLabel);
if ($sLabel != '')
{
$this->m_oMessage->setReplyTo(array($sAddress => $sLabel));
}
else if (!empty($sAddress))
{
$this->m_oMessage->setReplyTo($sAddress);
}
$this->oMailer->SetRecipientReplyTo($sAddress);
}
}
/////////////////////////////////////////////////////////////////////////////////////
/**
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
* but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
{
protected $sLogFile;
/**
* Sends the given message.
*
* @param Swift_Mime_Message $message
* @param string[] $failedRecipients An array of failures by-reference
*
* @return int The number of sent emails
*/
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
{
$hFile = @fopen($this->sLogFile, 'a');
if ($hFile)
{
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
$sTxt .= $message->toString()."\n";
@fwrite($hFile, $sTxt);
@fclose($hFile);
}
return parent::send($message, $failedRecipients);
}
public function setLogFile($sFilename)
{
$this->sLogFile = $sFilename;
}
}
/**
* Pretends messages have been sent, but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
{
/**
* Create a new LogFileTransport.
*/
public function __construct()
{
call_user_func_array(
array($this, 'Swift_Transport_LogFileTransport::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('transport.null')
);
}
/**
* Create a new LogFileTransport instance.
*
* @return Swift_LogFileTransport
*/
public static function newInstance()
{
return new self();
}
}

View File

@@ -111,16 +111,15 @@ class ExcelBulkExport extends TabularBulkExport
$sFormatInput = '<input type="text" size="15" name="date_format" id="excel_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "excel_date_format_radio", "custom", "excel_date_time_format_custom", "radio");
$oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip'));
$oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat());
$oRadioCustom->SetBeforeInput(false);
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oFieldSetDate->AddSubBlock($oRadioCustom);
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
$oP->add_ready_script(
<<<EOF
$('#excel_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
$('#form_part_xlsx_options').on('preview_updated', function() { FormatDatesInPreview('excel', 'xlsx'); });
$('#excel_date_time_format_default').on('click', function() { FormatDatesInPreview('excel', 'xlsx'); });
$('#excel_date_time_format_custom').on('click', function() { FormatDatesInPreview('excel', 'xlsx'); });

View File

@@ -108,6 +108,18 @@ abstract class DOMSanitizer extends HTMLSanitizer
{
/** @var DOMDocument */
protected $oDoc;
/**
* @var string Class to use for InlineImage static method calls
* @used-by \Combodo\iTop\Test\UnitTest\Core\Sanitizer\HTMLDOMSanitizerTest::testDoSanitizeCallInlineImageProcessImageTag
*/
protected $sInlineImageClassName;
public function __construct($sInlineImageClassName = InlineImage::class)
{
parent::__construct();
$this->sInlineImageClassName = $sInlineImageClassName;
}
abstract public function GetTagsWhiteList();
@@ -203,7 +215,7 @@ abstract class DOMSanitizer extends HTMLSanitizer
// Recurse
$this->CleanNode($oNode);
if (($oNode instanceof DOMElement) && (strtolower($oNode->tagName) == 'img')) {
InlineImage::ProcessImageTag($oNode);
$this->sInlineImageClassName::ProcessImageTag($oNode);
}
}
}
@@ -338,6 +350,30 @@ class HTMLDOMSanitizer extends DOMSanitizer
'white-space',
);
public function __construct($sInlineImageClassName = InlineImage::class)
{
parent::__construct($sInlineImageClassName);
// Building href validation pattern from url and email validation patterns as the patterns are not used the same way in HTML content than in standard attributes value.
// eg. "foo@bar.com" vs "mailto:foo@bar.com?subject=Title&body=Hello%20world"
if (!array_key_exists('href', self::$aAttrsWhiteList)) {
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
// Mailto urls
$sMailtoPattern = '(mailto:('.utils::GetConfig()->Get('email_validation_pattern').')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
// Notification placeholders
// eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
// Note: Authorize both $xxx$ and %24xxx%24 as the latter one is encoded when used in HTML attributes (eg. a[href])
$sPlaceholderPattern = '(\$|%24)[\w-]*(->[\w]*(\([\w-]*?\))?)?(\$|%24)';
$sPattern = $sUrlPattern.'|'.$sMailtoPattern.'|'.$sPlaceholderPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
}
public function GetTagsWhiteList()
{
return static::$aTagsWhiteList;
@@ -363,31 +399,6 @@ class HTMLDOMSanitizer extends DOMSanitizer
return static::$aStylesWhiteList;
}
public function __construct()
{
parent::__construct();
// Building href validation pattern from url and email validation patterns as the patterns are not used the same way in HTML content than in standard attributes value.
// eg. "foo@bar.com" vs "mailto:foo@bar.com?subject=Title&body=Hello%20world"
if (!array_key_exists('href', self::$aAttrsWhiteList))
{
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
// Mailto urls
$sMailtoPattern = '(mailto:(' . utils::GetConfig()->Get('email_validation_pattern') . ')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
// Notification placeholders
// eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
// Note: Authorize both $xxx$ and %24xxx%24 as the latter one is encoded when used in HTML attributes (eg. a[href])
$sPlaceholderPattern = '(\$|%24)[\w-]*(->[\w]*(\([\w-]*?\))?)?(\$|%24)';
$sPattern = $sUrlPattern . '|' . $sMailtoPattern . '|' . $sPlaceholderPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
}
public function LoadDoc($sHTML)
{
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +0,0 @@
<?php
// Copyright (C) 2010-2021 Combodo SARL
//
// 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/>
/**
* Associated with the metamodel -> MakeQuery/MakeQuerySingleTable
*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class QueryBuilderContext
{
protected $m_oRootFilter;
protected $m_aClassAliases;
protected $m_aTableAliases;
protected $m_aModifierProperties;
protected $m_aSelectedClasses;
protected $m_aFilteredTables;
public $m_oQBExpressions;
public function __construct($oFilter, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null)
{
$this->m_oRootFilter = $oFilter;
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter, $aGroupByExpr, $aSelectExpr);
$this->m_aClassAliases = $oFilter->GetJoinedClasses();
$this->m_aTableAliases = array();
$this->m_aFilteredTables = array();
$this->m_aModifierProperties = $aModifierProperties;
if (is_null($aSelectedClasses))
{
$this->m_aSelectedClasses = $oFilter->GetSelectedClasses();
}
else
{
// For the unions, the selected classes can be upper in the hierarchy (lowest common ancestor)
$this->m_aSelectedClasses = $aSelectedClasses;
}
}
public function GetRootFilter()
{
return $this->m_oRootFilter;
}
public function GenerateTableAlias($sNewName, $sRealName)
{
return MetaModel::GenerateUniqueAlias($this->m_aTableAliases, $sNewName, $sRealName);
}
public function GenerateClassAlias($sNewName, $sRealName)
{
return MetaModel::GenerateUniqueAlias($this->m_aClassAliases, $sNewName, $sRealName);
}
public function GetModifierProperties($sPluginClass)
{
if (array_key_exists($sPluginClass, $this->m_aModifierProperties))
{
return $this->m_aModifierProperties[$sPluginClass];
}
else
{
return array();
}
}
public function GetSelectedClass($sAlias)
{
return $this->m_aSelectedClasses[$sAlias];
}
public function AddFilteredTable($sTableAlias, $oCondition)
{
if (array_key_exists($sTableAlias, $this->m_aFilteredTables))
{
$this->m_aFilteredTables[$sTableAlias][] = $oCondition;
}
else
{
$this->m_aFilteredTables[$sTableAlias] = array($oCondition);
}
}
public function GetFilteredTables()
{
return $this->m_aFilteredTables;
}
}

View File

@@ -1,186 +0,0 @@
<?php
class QueryBuilderExpressions
{
/**
* @var Expression
*/
protected $m_oConditionExpr;
/**
* @var Expression[]
*/
protected $m_aSelectExpr;
/**
* @var Expression[]
*/
protected $m_aGroupByExpr;
/**
* @var Expression[]
*/
protected $m_aJoinFields;
/**
* @var string[]
*/
protected $m_aClassIds;
public function __construct(DBObjectSearch $oSearch, $aGroupByExpr = null, $aSelectExpr = null)
{
$this->m_oConditionExpr = $oSearch->GetCriteria();
if (!$oSearch->GetShowObsoleteData())
{
foreach ($oSearch->GetSelectedClasses() as $sAlias => $sClass)
{
if (MetaModel::IsObsoletable($sClass))
{
$oNotObsolete = new BinaryExpression(new FieldExpression('obsolescence_flag', $sAlias), '=', new ScalarExpression(0));
$this->m_oConditionExpr = $this->m_oConditionExpr->LogAnd($oNotObsolete);
}
}
}
$this->m_aSelectExpr = is_null($aSelectExpr) ? array() : $aSelectExpr;
$this->m_aGroupByExpr = $aGroupByExpr;
$this->m_aJoinFields = array();
$this->m_aClassIds = array();
foreach ($oSearch->GetJoinedClasses() as $sClassAlias => $sClass)
{
$this->m_aClassIds[$sClassAlias] = new FieldExpression('id', $sClassAlias);
}
}
public function GetSelect()
{
return $this->m_aSelectExpr;
}
public function GetGroupBy()
{
return $this->m_aGroupByExpr;
}
public function GetCondition()
{
return $this->m_oConditionExpr;
}
/**
* @return Expression|mixed
*/
public function PopJoinField()
{
return array_pop($this->m_aJoinFields);
}
/**
* @param string $sAttAlias
* @param Expression $oExpression
*/
public function AddSelect($sAttAlias, Expression $oExpression)
{
$this->m_aSelectExpr[$sAttAlias] = $oExpression;
}
/**
* @param Expression $oExpression
*/
public function AddCondition(Expression $oExpression)
{
$this->m_oConditionExpr = $this->m_oConditionExpr->LogAnd($oExpression);
}
/**
* @param Expression $oExpression
*/
public function PushJoinField(Expression $oExpression)
{
array_push($this->m_aJoinFields, $oExpression);
}
/**
* Get tables representing the queried objects
* Could be further optimized: when the first join is an outer join, then the rest can be omitted
*
* @param array $aTables
*
* @return array
*/
public function GetMandatoryTables(&$aTables = null)
{
if (is_null($aTables))
{
$aTables = array();
}
foreach ($this->m_aClassIds as $sClass => $oExpression)
{
$oExpression->CollectUsedParents($aTables);
}
return $aTables;
}
public function GetUnresolvedFields($sAlias, &$aUnresolved)
{
$this->m_oConditionExpr->GetUnresolvedFields($sAlias, $aUnresolved);
foreach ($this->m_aSelectExpr as $sColAlias => $oExpr)
{
$oExpr->GetUnresolvedFields($sAlias, $aUnresolved);
}
if ($this->m_aGroupByExpr)
{
foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr)
{
$oExpr->GetUnresolvedFields($sAlias, $aUnresolved);
}
}
foreach ($this->m_aJoinFields as $oExpression)
{
$oExpression->GetUnresolvedFields($sAlias, $aUnresolved);
}
}
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
{
$this->m_oConditionExpr = $this->m_oConditionExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
foreach ($this->m_aSelectExpr as $sColAlias => $oExpr)
{
$this->m_aSelectExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
if ($this->m_aGroupByExpr)
{
foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr)
{
$this->m_aGroupByExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
foreach ($this->m_aJoinFields as $index => $oExpression)
{
$this->m_aJoinFields[$index] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
foreach ($this->m_aClassIds as $sClass => $oExpression)
{
$this->m_aClassIds[$sClass] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
public function RenameParam($sOldName, $sNewName)
{
$this->m_oConditionExpr->RenameParam($sOldName, $sNewName);
foreach ($this->m_aSelectExpr as $sColAlias => $oExpr)
{
$this->m_aSelectExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName);
}
if ($this->m_aGroupByExpr)
{
foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr)
{
$this->m_aGroupByExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName);
}
}
foreach ($this->m_aJoinFields as $index => $oExpression)
{
$this->m_aJoinFields[$index] = $oExpression->RenameParam($sOldName, $sNewName);
}
}
}

View File

@@ -542,14 +542,33 @@ class FileLog
*/
class LogChannels
{
public const CLI = 'CLI';
public const CONSOLE = 'console';
public const DEADLOCK = 'DeadLock';
public const INLINE_IMAGE = 'InlineImage';
public const PORTAL = 'portal';
public const CMDB_SOURCE = 'cmdbsource';
public const CORE = 'core';
public const APC = 'apc';
/**
* @var string
* @since 3.0.1 N°4849
* @since 2.7.7 N°4635
*/
public const NOTIFICATIONS = 'notifications';
public const CLI = 'CLI';
/**
* @var string
* @since 2.7.7 N°4558 use this new channel when logging DB transactions
* @since 3.0.0 logs info in CMDBSource (see commit a117906f)
*/
public const CMDB_SOURCE = 'cmdbsource';
public const CONSOLE = 'console';
public const CORE = 'core';
public const DEADLOCK = 'DeadLock';
public const INLINE_IMAGE = 'InlineImage';
public const PORTAL = 'portal';
}
@@ -692,6 +711,7 @@ abstract class LogAPI
/**
* @throws \ConfigException if log wrongly configured
* @uses GetMinLogLevel
* @since 3.0.0 N°3731
*/
final public static function IsLogLevelEnabled(string $sLevel, string $sChannel, string $sConfigKey = self::ENUM_CONFIG_PARAM_FILE): bool
{
@@ -1137,7 +1157,12 @@ class DeprecatedCallsLog extends LogAPI
*/
public static function NotifyDeprecatedFile(?string $sAdditionalMessage = null): void
{
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_FILE)) {
try {
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_FILE)) {
return;
}
}
catch (ConfigException $e) {
return;
}

View File

@@ -461,7 +461,7 @@ abstract class MetaModel
$oStyle = self::$m_aClassParams[$sClass]['style'];
$sIcon = $oStyle->GetIconAsAbsUrl();
}
if (strlen($sIcon) == 0) {
if (utils::IsNullOrEmptyString($sIcon)) {
$sParentClass = self::GetParentPersistentClass($sClass);
if (strlen($sParentClass) > 0) {
return self::GetClassIcon($sParentClass, $bImgTag, $sMoreStyles);
@@ -494,7 +494,7 @@ abstract class MetaModel
$oStyle = new ormStyle("ibo-class-style--$sClass", "ibo-class-style-alt--$sClass");
}
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIconAsRelPath()) > 0)) {
if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) {
// all the parameters are set, no need to search in the parent classes
return $oStyle;
}
@@ -504,18 +504,18 @@ abstract class MetaModel
while (strlen($sParentClass) > 0) {
$oParentStyle = self::GetClassStyle($sParentClass);
if (!is_null($oParentStyle)) {
if (strlen($oStyle->GetMainColor()) == 0) {
if (utils::IsNullOrEmptyString($oStyle->GetMainColor())) {
$oStyle->SetMainColor($oParentStyle->GetMainColor());
$oStyle->SetStyleClass($oParentStyle->GetStyleClass());
}
if (strlen($oStyle->GetComplementaryColor()) == 0) {
if (utils::IsNullOrEmptyString($oStyle->GetComplementaryColor())) {
$oStyle->SetComplementaryColor($oParentStyle->GetComplementaryColor());
$oStyle->SetAltStyleClass($oParentStyle->GetAltStyleClass());
}
if (strlen($oStyle->GetIconAsRelPath()) == 0) {
if (utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) {
$oStyle->SetIcon($oParentStyle->GetIconAsRelPath());
}
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIconAsRelPath()) > 0)) {
if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) {
// all the parameters are set, no need to search in the parent classes
return $oStyle;
}
@@ -523,7 +523,7 @@ abstract class MetaModel
$sParentClass = self::GetParentPersistentClass($sParentClass);
}
if ((strlen($oStyle->GetMainColor()) == 0) && (strlen($oStyle->GetComplementaryColor()) == 0) && (strlen($oStyle->GetIconAsRelPath()) == 0)) {
if (utils::IsNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) {
return null;
}
@@ -655,7 +655,7 @@ abstract class MetaModel
* @param string $sRuleId
*
* @throws \CoreException
* @since 2.6.1 N°1918 (sous les pavés, la plage) initialize in 'root_class' property the class that has the first
* @since 2.6.1 N°1968 (sous les pavés, la plage) initialize in 'root_class' property the class that has the first
* definition of the rule in the hierarchy
*/
private static function SetUniquenessRuleRootClass($sRootClass, $sRuleId)

View File

@@ -2762,25 +2762,96 @@ class FunctionExpression extends Expression
return $iRet;
case 'DATE_FORMAT':
if (count($this->m_aArgs) != 2)
{
if (count($this->m_aArgs) != 2) {
throw new \Exception("Function {$this->m_sVerb} requires 2 arguments");
}
$oDate = new DateTime($this->m_aArgs[0]->Evaluate($aArgs));
$sFormat = $this->m_aArgs[1]->Evaluate($aArgs);
$sFormat = str_replace(
array('%y', '%x', '%w', '%W', '%v', '%T', '%S', '%r', '%p', '%M', '%l', '%k', '%I', '%h', '%b', '%a', '%D', '%c', '%e', '%Y', '%d', '%m', '%H', '%i', '%s'),
array('y', 'o', 'w', 'l', 'W', 'H:i:s', 's', 'h:i:s A', 'A', 'F', 'g', 'H', 'h', 'h','M', 'D', 'jS', 'n', 'j', 'Y', 'd', 'm', 'H', 'i', 's'),
$sFormat);
if (preg_match('/%j/', $sFormat))
{
$sFormat = str_replace('%j', date_format($oDate, 'z') + 1, $sFormat);
}
if (preg_match('/%[fUuVX]/', $sFormat))
{
$sFormatForMysqlDateFormat = $this->m_aArgs[1]->Evaluate($aArgs);
if (preg_match('/%[fUuVX]/', $sFormatForMysqlDateFormat)) {
throw new NotYetEvaluatedExpression("Expression ".$this->RenderExpression().' cannot be evaluated (known limitation)');
}
$sRet = date_format($oDate, $sFormat);
if (preg_match('/%j/', $sFormatForMysqlDateFormat)) {
$sFormatForMysqlDateFormat = str_replace('%j', 'z', $sFormatForMysqlDateFormat);
$sRet = date_format($oDate, $sFormatForMysqlDateFormat);
$sRet++;
/** @noinspection PhpUnnecessaryLocalVariableInspection */
$sRet = str_pad($sRet, 3, '0', STR_PAD_LEFT);
return $sRet;
}
/**
* @var string[] $aFormatsForMysqlDateFormat
* @link https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format
*/
//@formatter:off we want to keep every single item on its own line to ease comp between MySQL and PHP formats !
$aFormatsForMysqlDateFormat = [
'%y',
'%x',
'%w',
'%W',
'%v',
'%T',
'%S',
'%r',
'%p',
'%M',
'%l',
'%k',
'%I',
'%h',
'%b',
'%a',
'%D',
'%c',
'%e',
'%Y',
'%d',
'%m',
'%H',
'%i',
'%s'
];
//@formatter:on
/**
* @var string[] $aFormatsForPhpDateFormat
* @link https://www.php.net/manual/en/datetime.format.php
*/
//@formatter:off we want to keep every single item on its own line to ease comp between MySQL and PHP formats !
$aFormatsForPhpDateFormat = [
'y',
'o',
'w',
'l',
'W',
'H:i:s',
's',
'h:i:s A',
'A',
'F',
'g',
'G',
'h',
'h',
'M',
'D',
'jS',
'n',
'j',
'Y',
'd',
'm',
'H',
'i',
's'
];
//@formatter:on
$sFormatForPhpDateFormat = str_replace($aFormatsForMysqlDateFormat, $aFormatsForPhpDateFormat, $sFormatForMysqlDateFormat);
/** @noinspection PhpUnnecessaryLocalVariableInspection */
$sRet = date_format($oDate, $sFormatForPhpDateFormat);
return $sRet;
case 'TO_DAYS':

View File

@@ -50,7 +50,7 @@ class ormStyle
*/
public function HasMainColor(): bool
{
return strlen($this->sMainColor) > 0;
return utils::IsNotNullOrEmptyString($this->sMainColor);
}
/**
@@ -68,7 +68,7 @@ class ormStyle
*/
public function SetMainColor(?string $sMainColor)
{
$this->sMainColor = (strlen($sMainColor) === 0) ? null : $sMainColor;
$this->sMainColor = utils::IsNullOrEmptyString($sMainColor) ? null : $sMainColor;
return $this;
}
@@ -78,7 +78,7 @@ class ormStyle
*/
public function HasComplementaryColor(): bool
{
return strlen($this->sComplementaryColor) > 0;
return utils::IsNotNullOrEmptyString($this->sComplementaryColor);
}
/**
@@ -96,7 +96,7 @@ class ormStyle
*/
public function SetComplementaryColor(?string $sComplementaryColor)
{
$this->sComplementaryColor = (strlen($sComplementaryColor) === 0) ? null : $sComplementaryColor;
$this->sComplementaryColor = utils::IsNullOrEmptyString($sComplementaryColor) ? null : $sComplementaryColor;
return $this;
}
@@ -116,7 +116,7 @@ class ormStyle
*/
public function HasStyleClass(): bool
{
return strlen($this->sStyleClass) > 0;
return utils::IsNotNullOrEmptyString($this->sStyleClass);
}
/**
@@ -134,7 +134,7 @@ class ormStyle
*/
public function SetStyleClass(?string $sStyleClass)
{
$this->sStyleClass = (strlen($sStyleClass) === 0) ? null : $sStyleClass;
$this->sStyleClass = utils::IsNullOrEmptyString($sStyleClass) ? null : $sStyleClass;
return $this;
}
@@ -144,7 +144,7 @@ class ormStyle
*/
public function HasAltStyleClass(): bool
{
return strlen($this->sAltStyleClass) > 0;
return utils::IsNotNullOrEmptyString($this->sAltStyleClass);
}
/**
@@ -162,7 +162,7 @@ class ormStyle
*/
public function SetAltStyleClass(?string $sAltStyleClass)
{
$this->sAltStyleClass = (strlen($sAltStyleClass) === 0) ? null : $sAltStyleClass;
$this->sAltStyleClass = utils::IsNullOrEmptyString($sAltStyleClass) ? null : $sAltStyleClass;
return $this;
}
@@ -172,7 +172,7 @@ class ormStyle
*/
public function HasDecorationClasses(): bool
{
return strlen($this->sDecorationClasses) > 0;
return utils::IsNotNullOrEmptyString($this->sDecorationClasses);
}
/**
@@ -190,7 +190,7 @@ class ormStyle
*/
public function SetDecorationClasses(?string $sDecorationClasses)
{
$this->sDecorationClasses = (strlen($sDecorationClasses) === 0) ? null : $sDecorationClasses;
$this->sDecorationClasses = utils::IsNullOrEmptyString($sDecorationClasses) ? null : $sDecorationClasses;
return $this;
}
@@ -200,7 +200,7 @@ class ormStyle
*/
public function HasIcon(): bool
{
return strlen($this->sIcon) > 0;
return utils::IsNotNullOrEmptyString($this->sIcon);
}
/**
@@ -210,7 +210,7 @@ class ormStyle
*/
public function SetIcon(?string $sIcon)
{
$this->sIcon = (strlen($sIcon) === 0) ? null : $sIcon;
$this->sIcon = utils::IsNullOrEmptyString($sIcon) ? null : $sIcon;
return $this;
}

View File

@@ -155,7 +155,7 @@ class ormCaseLog {
break;
case static::ENUM_FORMAT_HTML:
$sHtmlEntry = $sTextEntry;
$sHtmlEntry = InlineImage::FixUrls($sTextEntry);
$sTextEntry = utils::HtmlToText($sHtmlEntry);
break;
}
@@ -723,7 +723,7 @@ class ormCaseLog {
}
else
{
$sRes = $sRaw;
$sRes = InlineImage::FixUrls($sRaw);
}
break;
}
@@ -758,6 +758,6 @@ class ormCaseLog {
}
$iPos += $this->m_aIndex[$index]['separator_length'];
$sText = substr($this->m_sLog, $iPos, $this->m_aIndex[$index]['text_length']);
return $sText;
return InlineImage::FixUrls($sText);
}
}

View File

@@ -31,13 +31,13 @@ class iTopOwnershipToken extends DBObject
{
$aParams = array
(
'category' => 'application',
'key_type' => 'autoincrement',
'name_attcode' => array('obj_class', 'obj_key'),
'state_attcode' => '',
'reconc_keys' => array(''),
'db_table' => 'priv_ownership_token',
'db_key_field' => 'id',
'category' => '',
'key_type' => 'autoincrement',
'name_attcode' => array('obj_class', 'obj_key'),
'state_attcode' => '',
'reconc_keys' => array(''),
'db_table' => 'priv_ownership_token',
'db_key_field' => 'id',
'db_finalclass_field' => '',
);
MetaModel::Init_Params($aParams);

View File

@@ -95,15 +95,14 @@ class PDFBulkExport extends HTMLBulkExport
$sFormatInput = '<input type="text" size="15" name="date_format" id="pdf_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "pdf_date_format_radio", "custom", "pdf_date_time_format_custom", "radio");
$oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip'));
$oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat());
$oRadioCustom->SetBeforeInput(false);
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oFieldSetDate->AddSubBlock($oRadioCustom);
$sJSTooltip = json_encode('<div id="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
$oP->add_ready_script(
<<<EOF
$('#pdf_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
$('#form_part_pdf_options').on('preview_updated', function() { FormatDatesInPreview('pdf', 'html'); });
$('#pdf_date_time_format_default').on('click', function() { FormatDatesInPreview('pdf', 'html'); });
$('#pdf_date_time_format_custom').on('click', function() { FormatDatesInPreview('pdf', 'html'); });

View File

@@ -84,15 +84,14 @@ class SpreadsheetBulkExport extends TabularBulkExport
$sFormatInput = '<input type="text" size="15" name="date_format" id="spreadsheet_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "spreadsheet_date_format_radio", "custom", "spreadsheet_date_time_format_custom", "radio");
$oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip'));
$oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat());
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
$oRadioCustom->SetBeforeInput(false);
$oFieldSetDate->AddSubBlock($oRadioCustom);
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
$oP->add_ready_script(
<<<EOF
$('#spreadsheet_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
$('#form_part_spreadsheet_options').on('preview_updated', function() { FormatDatesInPreview('spreadsheet', 'spreadsheet'); });
$('#spreadsheet_date_time_format_default').on('click', function() { FormatDatesInPreview('spreadsheet', 'spreadsheet'); });
$('#spreadsheet_date_time_format_custom').on('click', function() { FormatDatesInPreview('spreadsheet', 'spreadsheet'); });

View File

@@ -494,7 +494,17 @@ class SQLObjectQuery extends SQLQuery
}
}
private function PrepareSingleTable(SQLObjectQuery $oRootQuery, &$aFrom, $sCallerAlias = '', $aJoinData)
/**
* @param \SQLObjectQuery $oRootQuery
* @param $aFrom
* @param $sCallerAlias
* @param $aJoinData
*
* @return string
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $sCallerAlias for PHP 8.0 compat (Private method with only 2 calls in the class, both providing the optional parameter)
*/
private function PrepareSingleTable(SQLObjectQuery $oRootQuery, &$aFrom, $sCallerAlias, $aJoinData)
{
$aTranslationTable[$this->m_sTable]['*'] = $this->m_sTableAlias;
$sJoinCond = '';
@@ -613,6 +623,7 @@ class SQLObjectQuery extends SQLQuery
$aTempFrom = array(); // temporary subset of 'from' specs, to be grouped in the final query
foreach ($this->m_aJoinSelects as $aJoinData)
{
/** @var \SQLObjectQuery $oRightSelect */
$oRightSelect = $aJoinData["select"];
$oRightSelect->PrepareSingleTable($oRootQuery, $aTempFrom, $this->m_sTableAlias, $aJoinData);

View File

@@ -19,7 +19,7 @@ define('UR_ACTION_CREATE', 7); // Instantiate an object
define('UR_ACTION_APPLICATION_DEFINED', 10000); // Application specific actions (CSV import, View schema...)
/**
* User management module API
* User management module API
*
* @package iTopORM
*/
@@ -139,7 +139,7 @@ abstract class UserRightsAddOnAPI
$oExpression = new FieldExpression($sAttCode, $sClass);
$oFilter = new DBObjectSearch($sClass);
$oListExpr = ListExpression::FromScalars($aAllowedOrgs);
$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
$oFilter->AddConditionExpression($oCondition);
@@ -156,7 +156,7 @@ abstract class UserRightsAddOnAPI
$oShareSearch = new DBObjectSearch('SharedObject');
$oOrgField = new FieldExpression('org_id', 'SharedObject');
$oShareSearch->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr));
$oSearchSharers = new DBObjectSearch('Organization');
$oSearchSharers->AllowAllData();
$oSearchSharers->AddCondition_ReferencedBy($oShareSearch, 'sharing_org_id');
@@ -172,16 +172,16 @@ abstract class UserRightsAddOnAPI
$oFilter->MergeConditionExpression(new BinaryExpression($oExpression, 'IN', $oSharersList));
}
}
$aShareProperties = SharedObject::GetSharedClassProperties($sClass);
if ($aShareProperties)
{
$sShareClass = $aShareProperties['share_class'];
$sShareAttCode = $aShareProperties['attcode'];
$oSearchShares = new DBObjectSearch($sShareClass);
$oSearchShares->AllowAllData();
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
$oOrgField = new FieldExpression('org_id', $sShareClass);
$oSearchShares->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr));
@@ -217,11 +217,12 @@ abstract class User extends cmdbAbstractObject
"category" => "core,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "login",
"state_attcode" => "",
"state_attcode" => "status",
"reconc_keys" => array(),
"db_table" => "priv_user",
"db_key_field" => "id",
"db_finalclass_field" => "",
"style" => new ormStyle("ibo-dm-class--User", "ibo-dm-class-alt--User", "var(--ibo-dm-class--User--main-color)", "var(--ibo-dm-class--User--complementary-color)", null, "itop-structure/../../images/icons/icons8-security-pass.svg"),
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
@@ -235,8 +236,8 @@ abstract class User extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("login", array("allowed_values"=>null, "sql"=>"login", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql"=>"language", "default_value"=>"EN US", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values" => new ValueSetEnum('enabled,disabled'), "sql"=>"status", "default_value"=>"enabled", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values" => new ValueSetEnum('enabled,disabled'), "styled_values"=>['enabled' => new ormStyle('ibo-dm-enum--User-status-enabled', 'ibo-dm-enum-alt--User-status-enabled', 'var(--ibo-dm-enum--User-status-enabled--main-color)', 'var(--ibo-dm-enum--User-status-enabled--complementary-color)', null, null),'disabled' => new ormStyle('ibo-dm-enum--User-status-disabled', 'ibo-dm-enum-alt--User-status-disabled', 'var(--ibo-dm-enum--User-status-disabled--main-color)', 'var(--ibo-dm-enum--User-status-disabled--complementary-color)', null, null)], "sql"=>"status", "default_value"=>"enabled", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("profile_list", array("linked_class"=>"URP_UserProfile", "ext_key_to_me"=>"userid", "ext_key_to_remote"=>"profileid", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("allowed_org_list", array("linked_class"=>"URP_UserOrg", "ext_key_to_me"=>"userid", "ext_key_to_remote"=>"allowed_org_id", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
@@ -504,7 +505,7 @@ abstract class User extends cmdbAbstractObject
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
}
}
function DoShowGrantSumary($oPage, $sClassCategory)
{
if (UserRights::IsAdministrator($this))
@@ -536,7 +537,7 @@ abstract class User extends cmdbAbstractObject
{
$sStimuli = '<em title="'.Dict::S('UI:UserManagement:NoLifeCycleApplicable+').'">'.Dict::S('UI:UserManagement:NoLifeCycleApplicable').'</em>';
}
$aDisplayData[] = array(
'class' => MetaModel::GetName($sClass),
'read' => $this->GetGrantAsHtml($sClass, UR_ACTION_READ),
@@ -550,7 +551,7 @@ abstract class User extends cmdbAbstractObject
}
$oKPI->ComputeAndReport('Computation of user rights');
$aDisplayConfig = array();
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
@@ -585,7 +586,7 @@ abstract class User extends cmdbAbstractObject
}
}
public function CheckToDelete(&$oDeletionPlan)
{
if (MetaModel::GetConfig()->Get('demo_mode'))
@@ -597,8 +598,8 @@ abstract class User extends cmdbAbstractObject
return false;
}
return parent::CheckToDelete($oDeletionPlan);
}
}
protected function DBDeleteSingleObject()
{
if (MetaModel::GetConfig()->Get('demo_mode'))
@@ -633,7 +634,7 @@ abstract class User extends cmdbAbstractObject
*/
abstract class UserInternal extends User
{
// Nothing special, just a base class to categorize this type of authenticated users
// Nothing special, just a base class to categorize this type of authenticated users
public static function Init()
{
$aParams = array
@@ -662,15 +663,15 @@ abstract class UserInternal extends User
/**
* Use with care!
*/
*/
public function SetPassword($sNewPassword)
{
}
/**
* The email recipient is the person who is allowed to regain control when the password gets lost
* The email recipient is the person who is allowed to regain control when the password gets lost
* Throws an exception if the feature cannot be available
*/
*/
public function GetResetPasswordEmail()
{
if (!MetaModel::IsValidAttCode(get_class($this), 'contactid'))
@@ -703,7 +704,7 @@ abstract class UserInternal extends User
}
/**
* Self register extension
* Self register extension
*
* @package iTopORM
*/
@@ -719,10 +720,10 @@ interface iSelfRegister
* @return bool true if the user is a valid one, false otherwise
*/
public static function CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication);
/**
* Called after the user has been authenticated and found in iTop. This method can
* Update the user's definition on the fly (profiles...) to keep it in sync with an external source
* Update the user's definition on the fly (profiles...) to keep it in sync with an external source
* @param User $oUser The user to update/synchronize
* @param string $sLoginMode The login mode used (cas|form|basic|url)
* @param string $sAuthentication The authentication method used
@@ -732,7 +733,7 @@ interface iSelfRegister
}
/**
* User management core API
* User management core API
*
* @package iTopORM
*/
@@ -830,7 +831,7 @@ class UserRights
else
{
return true;
}
}
}
/**
@@ -1053,6 +1054,11 @@ class UserRights
Dict::SetUserLanguage(self::GetUserLanguage());
Session::Set('impersonate_user', $sLogin);
self::_ResetSessionCache();
//N°5135 - Impersonate: history of changes versus log entries
//track impersonation inside changelogs
CMDBObject::SetTrackUserId(null);
CMDBObject::CreateChange();
}
}
return $bRet;
@@ -1066,9 +1072,15 @@ class UserRights
if (!is_null(self::$m_oRealUser))
{
self::$m_oUser = self::$m_oRealUser;
//N°5135 - fix IsImpersonated() after calling Deimpersonate()
self::$m_oRealUser = null;
Dict::SetUserLanguage(self::GetUserLanguage());
Session::Unset('impersonate_user');
self::_ResetSessionCache();
//N°5135 - Impersonate: history of changes versus log entries
//stop tracking impersonation inside changelogs
CMDBObject::CreateChange();
}
}
@@ -1136,7 +1148,7 @@ class UserRights
if (is_null(self::$m_oUser))
{
return 'EN US';
}
else
{
@@ -1483,7 +1495,7 @@ class UserRights
{
if (!self::IsLoggedIn())
{
//throw new UserRightException('No user logged in', array());
//throw new UserRightException('No user logged in', array());
return false;
}
return true;
@@ -1871,7 +1883,7 @@ class UserRights
case 'internal':
$sBaseClass = 'UserInternal';
break;
default:
echo "<p>sAuthentication = $sAuthentication</p>\n";
assert(false); // should never happen
@@ -1936,7 +1948,7 @@ class UserRights
Session::Unset('profile_list');
Session::Unset('archive_allowed');
}
/**
* Fake error handler to silently discard fatal errors
* @param int $iErrNo
@@ -1968,7 +1980,7 @@ class ActionChecker
var $iActionCode;
var $iAllowedCount = null;
var $aAllowedIDs = null;
public function __construct(DBSearch $oFilter, $iActionCode)
{
$this->oFilter = $oFilter;
@@ -1976,7 +1988,7 @@ class ActionChecker
$this->iAllowedCount = null;
$this->aAllowedIDs = null;
}
/**
* returns the number of objects for which the action is allowed
* @return integer The number of "allowed" objects 0..N
@@ -1986,7 +1998,7 @@ class ActionChecker
if ($this->iAllowedCount == null) $this->CheckObjects();
return $this->iAllowedCount;
}
/**
* If IsAllowed returned UR_ALLOWED_DEPENDS, this methods returns
* an array of ObjKey => Status (true|false)
@@ -1997,7 +2009,7 @@ class ActionChecker
if ($this->aAllowedIDs == null) $this->IsAllowed();
return $this->aAllowedIDs;
}
/**
* Check if the speficied stimulus is allowed for the set of objects
* @return UR_ALLOWED_YES, UR_ALLOWED_NO or UR_ALLOWED_DEPENDS
@@ -2048,7 +2060,7 @@ class ActionChecker
class StimulusChecker extends ActionChecker
{
var $sState = null;
public function __construct(DBSearch $oFilter, $sState, $iStimulusCode)
{
parent::__construct($oFilter, $iStimulusCode);
@@ -2063,7 +2075,7 @@ class StimulusChecker extends ActionChecker
{
$sClass = $this->oFilter->GetClass();
if (MetaModel::IsAbstract($sClass)) return UR_ALLOWED_NO; // Safeguard, not implemented if the base class of the set is abstract !
$oSet = new DBObjectSet($this->oFilter);
$iActionAllowed = UserRights::IsStimulusAllowed($sClass, $this->iActionCode, $oSet);
if ($iActionAllowed == UR_ALLOWED_NO)
@@ -2075,7 +2087,7 @@ class StimulusChecker extends ActionChecker
{
// Hmmm, may not be needed right now because we limit the "multiple" action to object in
// the same state... may be useful later on if we want to extend this behavior...
// Check for each object if the action is allowed or not
$this->aAllowedIDs = array();
$oSet->Rewind();
@@ -2100,15 +2112,15 @@ class StimulusChecker extends ActionChecker
$this->aAllowedIDs[$oObj->GetKey()] = true;
$this->iState = $oObj->GetState();
$this->iAllowedCount++;
}
}
}
else
{
$this->aAllowedIDs[$oObj->GetKey()] = false;
}
$this->aAllowedIDs[$oObj->GetKey()] = false;
}
}
}
if ($this->iAllowedCount == $oSet->Count())
{
$iActionAllowed = UR_ALLOWED_YES;
@@ -2120,9 +2132,9 @@ class StimulusChecker extends ActionChecker
return $iActionAllowed;
}
public function GetState()
{
return $this->iState;
}
}
}

View File

@@ -49,6 +49,10 @@ css/backoffice/
| |- tabular-fields
| ...
|
|- *datamodel/ # SCSS / CSS3 variables and CSS classes for PHP classes of the DM that are part of the core (not in a module) and cannot be styled otherwise
| |- _user.scss
| ...
|
| pages/
| | _home.scss # Home specific styles
| | _contact.scss # Contact specific styles

View File

@@ -4,4 +4,5 @@
*/
@import "collapsible-section-with-blocks";
@import "collapsible-section-within-caselog-list";
@import "collapsible-section-within-caselog-list";
@import "collapsible-section-within-alert";

View File

@@ -0,0 +1,26 @@
/*
* @copyright Copyright (C) 2010-2022 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/* SCSS variables */
$ibo-collapsible-section-within-alert--body--padding: $ibo-spacing-300 !default;
$ibo-collapsible-section-within-alert--body--text-color: $ibo-color-grey-900 !default;
.ibo-alert--body {
.ibo-collapsible-section {
.ibo-collapsible-section--header .ibo-collapsible-section--title,
.ibo-collapsible-section--body {
@extend %ibo-font-size-150;
}
.ibo-collapsible-section--body {
color: $ibo-collapsible-section-within-alert--body--text-color;
padding: $ibo-collapsible-section-within-alert--body--padding;
}
}
> * + .ibo-collapsible-section {
margin-top: 8px;
}
}

View File

@@ -3,4 +3,5 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
@import "field-with-field";
@import "field-with-field";
@import "field-with-fieldset";

View File

@@ -0,0 +1,10 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-field--spacing-top--with-fieldset: $ibo-spacing-700 !default;
.ibo-fieldset + .ibo-field {
margin-top: $ibo-field--spacing-top--with-fieldset;
}

View File

@@ -3,5 +3,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
@import "fieldset-with-field";
@import "fieldset-with-fieldset";
@import "fieldset-with-multicolumn";

View File

@@ -0,0 +1,10 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-fieldset--spacing-top--with-field: $ibo-spacing-700 !default;
.ibo-field + .ibo-fieldset:not(.ibo-column) {
margin-top: $ibo-fieldset--spacing-top--with-field;
}

View File

@@ -3,8 +3,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-fieldset--spacing-left--with-fieldset: $ibo-spacing-800 !default;
$ibo-fieldset--spacing-top--with-fieldset: $ibo-spacing-800 !default;
.ibo-fieldset + .ibo-fieldset:not(.ibo-column) {
margin-top: $ibo-fieldset--spacing-left--with-fieldset;
margin-top: $ibo-fieldset--spacing-top--with-fieldset;
}

View File

@@ -3,9 +3,9 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-fieldset--spacing-left--with-multicolumn: $ibo-spacing-800 !default;
$ibo-fieldset--spacing-top--with-multicolumn: $ibo-spacing-800 !default;
.ibo-multi-column + .ibo-fieldset {
margin-top: $ibo-fieldset--spacing-left--with-multicolumn;
margin-top: $ibo-fieldset--spacing-top--with-multicolumn;
}

View File

@@ -11,4 +11,18 @@ $ibo-input--spacing-left--with-label: $ibo-spacing-300 !default;
select + label, label + select, label > select,
input + label, label + input, label > input {
margin-left: $ibo-input--spacing-left--with-label;
}
.ibo-input-with-label--label {
&.ibo-has-description {
&::after {
content: $ibo-field--label--description--content;
padding-left: $ibo-field--label--description--padding-left;
vertical-align: top;
cursor: pointer;
color: $ibo-field--label--description--color;
@extend %ibo-font-ral-bol-50;
}
}
}

View File

@@ -479,6 +479,22 @@ $ibo-button-colors: (
&.ibo-action-button {
float: right;
}
.ibo-button--loading-icon {
display: none;
}
&.ibo-is-loading {
.ibo-button--icon{
display: none;
}
.ibo-button--loading-icon {
display: inline-block;
&+ .ibo-button--label{
margin-left: $ibo-button--label--margin-left;
}
}
}
}
.ibo-button--label {

View File

@@ -122,6 +122,26 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
}
}
.ibo-datatable--selected-count{
.ibo-datatable--selected-count, .ibo-datatable--result-count{
padding-right: 0.2em;
padding-left: 0.1em;
}
//
.ibo-datatable[data-status="loading"]{
margin-top: $ibo-datatable--toolbar--table-spacing;
td, th {
position: relative;
padding: $ibo-vendors-datatables--cell--padding-y $ibo-vendors-datatables--cell--padding-x;
}
td{
@extend %ibo-font-ral-med-100;
}
tr:nth-child(even){
background-color: $ibo-vendors-datatables--row--background-color--is-even;
}
th {
@extend %ibo-font-ral-sembol-100;
border-bottom: $ibo-vendors-datatables--columns-header--border-bottom;
}
}

View File

@@ -101,7 +101,7 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
/* N°4318 - Visible scrollbar background for large fields overflowing to ease "limits" visualization by the user */
.ibo-field--value > * {
--ibo-scrollbar--scrollbar-track-background-color: $ibo-field--value--scrollbar-track-background-color;
--ibo-scrollbar--scrollbar-track-background-color: #{$ibo-field--value--scrollbar-track-background-color};
}
/* Fullscreen mode */

View File

@@ -89,7 +89,7 @@ $ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
.ibo-panel {
--ibo-main-color: map-get($ibo-panel-colors, 'neutral'); /* --ibo-main-color is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
--ibo-main-color: #{map-get($ibo-panel-colors, 'neutral')}; /* --ibo-main-color is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
position: relative;

View File

@@ -79,8 +79,8 @@ $ibo-pill-states-colors: (
/* Rules */
.ibo-pill {
/* --ibo-main-color-xxx is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
--ibo-main-color--100: map-get(map-get($ibo-pill-states-colors, 'neutral'), 'primary-color');
--ibo-main-color--900: map-get(map-get($ibo-pill-states-colors, 'neutral'), 'secondary-color');
--ibo-main-color--100: #{map-get(map-get($ibo-pill-states-colors, 'neutral'), 'primary-color')};
--ibo-main-color--900: #{map-get(map-get($ibo-pill-states-colors, 'neutral'), 'secondary-color')};
@extend %ibo-fully-centered-content;
max-width: $ibo-pill--max-width;

View File

@@ -235,7 +235,7 @@ $ibo-quick-create--compartment--placeholder-hint--text-color: $ibo-color-grey-70
}
&:hover{
cursor: pointer;
@extend a:hover;
@extend a;
}
.highlight{

View File

@@ -345,6 +345,7 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
/* Form group (operators) is displayed only when the criteria is toggled to opened state */
display: none;
max-width: 450px;
width: max-content;
max-height: 520px;
overflow-x: auto;
overflow-y: hidden;
@@ -374,7 +375,7 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
}
.sfc_op_name {
width: 90px;
width: 96px;
}
.sfc_op_content {

View File

@@ -8,6 +8,8 @@ $ibo-title--padding-y: $ibo-spacing-400 !default;
$ibo-title--padding-x: $ibo-spacing-0 !default;
$ibo-title--icon--size: 90px !default;
$ibo-title--icon--size-2: 80px !default;
$ibo-title--icon--size-3: 70px !default;
$ibo-title--icon-background--size--must-contain: contain !default;
$ibo-title--icon-background--size--must-cover: cover !default;
@@ -29,6 +31,18 @@ $ibo-title--icon-background--size--must-zoomout: 66.67% !default;
min-height: $ibo-title--icon--size;
overflow: hidden;
}
.ibo-title--icon > .ibo-title--icon-level-2{
width: $ibo-title--icon--size-2;
height: $ibo-title--icon--size-2;
min-width: $ibo-title--icon--size-2;
min-height: $ibo-title--icon--size-2;
}
.ibo-title--icon > .ibo-title--icon-level-3{
width: $ibo-title--icon--size-3;
height: $ibo-title--icon--size-3;
min-width: $ibo-title--icon--size-3;
min-height: $ibo-title--icon--size-3;
}
.ibo-title--icon-background {
width: 100%;

View File

@@ -3,6 +3,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-image--image-view--min-height: 96px !default;
$ibo-input-image--image-view--background-color: $ibo-color-grey-200 !default;
$ibo-input-image--image-view--border-radius: $ibo-border-radius-500 !default;
@@ -18,6 +19,7 @@ $ibo-input-image--edit-buttons--elements-spacing: $ibo-input-image--edit-buttons
.ibo-input-image--image-view {
position: relative;
overflow: hidden;
min-height: $ibo-input-image--image-view--min-height;
background-color: $ibo-input-image--image-view--background-color;
border-radius: $ibo-input-image--image-view--border-radius;
@extend %ibo-fully-centered-content;

View File

@@ -1,4 +1,4 @@
/*!
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -64,6 +64,8 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
color: inherit;
border-color: $ibo-color-white-100;
padding-left: $ibo-input-select--padding-x;
@extend %ibo-font-ral-nor-150;
}
> [data-value] {
@@ -102,6 +104,13 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
> input {
background-color: unset;
border: unset;
&:focus{
outline: none !important; /* Overwrite browsers default focus outline */
}
}
&.input-active{
border: 1px solid $ibo-input--focus--border-color;
}
}
.ibo-input-select-wrapper{

View File

@@ -22,7 +22,6 @@ $ibo-input--placeholder--color: $ibo-color-grey-600 !default;
$ibo-input--disabled--background-color: $ibo-color-grey-300 !default;
$ibo-input--placeholder--color: $ibo-color-grey-700 !default;
$ibo-input-wrapper--is-error--background-color: $ibo-color-red-200 !default;
$ibo-input-wrapper--is-error--border-color: $ibo-color-red-600 !default;
$ibo-field-validation: $ibo-color-red-700 !default;
@@ -38,6 +37,8 @@ $ibo-input--margin-x: $ibo-spacing-200 !default;
border: 1px solid $ibo-input--border-color;
border-radius: $ibo-input--border-radius;
@extend %ibo-font-ral-nor-150;
&:focus{
border: 1px solid $ibo-input--focus--border-color;
}
@@ -55,7 +56,6 @@ textarea.ibo-input{
.ibo-input-wrapper.is-error, .ibo-input-field-wrapper.is-error {
.ibo-input, .ibo-input-vanilla, .cke, textarea {
border: 1px solid $ibo-input-wrapper--is-error--border-color;
background-color: $ibo-input-wrapper--is-error--background-color;
}
.ibo-input-vanilla input{
border: 0;

View File

@@ -0,0 +1,12 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**************************************************************************************************************************/
/* SCSS / CSS3 variables and CSS classes are based on what the compiler generates and will be used across the application */
/* In case you doubt what to put here, check the "env-xxx/branding/themes/datamodel-compiled-scss-rules.scss" file to */
/* to see what the compiler generates for XML DM classes. */
/**************************************************************************************************************************/
@import "user";

View File

@@ -0,0 +1,64 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Class itself
$ibo-dm-class--User--main-color: $ibo-color-blue-grey-600 !default;
$ibo-dm-class--User--complementary-color: $ibo-color-white-100 !default;
:root {
--ibo-dm-class--User--main-color: #{$ibo-dm-class--User--main-color};
--ibo-dm-class--User--complementary-color: #{$ibo-dm-class--User--complementary-color};
}
.ibo-dm-class--User {
--ibo-main-color: #{$ibo-dm-class--User--main-color};
--ibo-main-color--100: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-class--User--main-color, $ibo-color-base-lightness-100), $ibo-color-base-opacity-for-lightness-100)};
--ibo-main-color--900: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-class--User--main-color, $ibo-color-base-lightness-900), $ibo-color-base-opacity-for-lightness-900)};
--ibo-complementary-color: #{$ibo-dm-class--User--complementary-color};
}
.ibo-dm-class-alt--User {
--ibo-main-color: #{$ibo-dm-class--User--complementary-color};
--ibo-complementary-color: #{$ibo-dm-class--User--main-color};
}
// State attribute, "enabled" value
$ibo-dm-enum--User-status-enabled--main-color: $ibo-lifecycle-active-state-primary-color !default;
$ibo-dm-enum--User-status-enabled--complementary-color: $ibo-lifecycle-active-state-secondary-color !default;
:root {
--ibo-dm-enum--User-status-enabled--main-color: #{$ibo-dm-enum--User-status-enabled--main-color};
--ibo-dm-enum--User-status-enabled--complementary-color: #{$ibo-dm-enum--User-status-enabled--complementary-color};
}
.ibo-dm-enum--User-status-enabled {
--ibo-main-color: #{$ibo-dm-enum--User-status-enabled--main-color};
--ibo-main-color--100: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-enum--User-status-enabled--main-color, $ibo-color-base-lightness-100), $ibo-color-base-opacity-for-lightness-100)};
--ibo-main-color--900: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-enum--User-status-enabled--main-color, $ibo-color-base-lightness-900), $ibo-color-base-opacity-for-lightness-900)};
--ibo-complementary-color: #{$ibo-dm-enum--User-status-enabled--complementary-color};
}
.ibo-dm-enum-alt--User-status-enabled {
--ibo-main-color: #{$ibo-dm-enum--User-status-enabled--complementary-color};
--ibo-complementary-color: #{$ibo-dm-enum--User-status-enabled--main-color};
}
// State attribute, "disabled" value
$ibo-dm-enum--User-status-disabled--main-color: $ibo-lifecycle-inactive-state-primary-color !default;
$ibo-dm-enum--User-status-disabled--complementary-color: $ibo-lifecycle-inactive-state-secondary-color !default;
:root {
--ibo-dm-enum--User-status-disabled--main-color: #{$ibo-dm-enum--User-status-disabled--main-color};
--ibo-dm-enum--User-status-disabled--complementary-color: #{$ibo-dm-enum--User-status-disabled--complementary-color};
}
.ibo-dm-enum--User-status-disabled {
--ibo-main-color: #{$ibo-dm-enum--User-status-disabled--main-color};
--ibo-main-color--100: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-enum--User-status-disabled--main-color, $ibo-color-base-lightness-100), $ibo-color-base-opacity-for-lightness-100)};
--ibo-main-color--900: #{ibo-adjust-alpha(ibo-adjust-lightness($ibo-dm-enum--User-status-disabled--main-color, $ibo-color-base-lightness-900), $ibo-color-base-opacity-for-lightness-900)};
--ibo-complementary-color: #{$ibo-dm-enum--User-status-disabled--complementary-color};
}
.ibo-dm-enum-alt--User-status-disabled {
--ibo-main-color: #{$ibo-dm-enum--User-status-disabled--complementary-color};
--ibo-complementary-color: #{$ibo-dm-enum--User-status-disabled--main-color};
}

View File

@@ -14,7 +14,7 @@ $ibo-navigation-menu--body--background-color: $ibo-color-blue-grey-900 !default;
$ibo-navigation-menu--body--text-color: $ibo-color-grey-300 !default;
$ibo-navigation-menu--top-part--height: 120px !default;
$ibo-navigation-menu--top-part--padding-y: $ibo-navigation-menu--body--padding-y !default;
$ibo-navigation-menu--top-part--padding-y: $ibo-spacing-400 !default;
$ibo-navigation-menu--top-part--padding-x: $ibo-navigation-menu--body--padding-x !default;
$ibo-navigation-menu--top-part--elements-spacing: 20px !default;
@@ -70,13 +70,13 @@ $ibo-navigation-menu--square-company-logo--width: 38px !default;
$ibo-navigation-menu--square-company-logo--height: 38px !default;
$ibo-navigation-menu--square-company-logo--margin-top: $ibo-spacing-0 !default;
$ibo-navigation-menu--square-company-logo--margin-x: -5px !default;
$ibo-navigation-menu--square-company-logo--margin-bottom: $ibo-navigation-menu--body--padding-y * 2 !default;
$ibo-navigation-menu--square-company-logo--margin-bottom: ($ibo-navigation-menu--body--padding-y * 2) + 12px !default; /* +12px to keep burger & menu groups icons align in both expanded and collapsed mode */
$ibo-navigation-menu--full-company-logo--width: $ibo-navigation-menu--body--width-expanded !default;
$ibo-navigation-menu--full-company-logo--height: 70px !default;
$ibo-navigation-menu--full-company-logo--margin-top: $ibo-spacing-0 !default;
$ibo-navigation-menu--full-company-logo--margin-right: $ibo-spacing-0 !default;
$ibo-navigation-menu--full-company-logo--margin-bottom: $ibo-spacing-0 !default;
$ibo-navigation-menu--full-company-logo--margin-bottom: $ibo-spacing-400 !default;
$ibo-navigation-menu--full-company-logo--margin-left: -$ibo-navigation-menu--body--padding-y !default;
$ibo-navigation-menu--full-company-logo--image--margin-x: auto !default;
$ibo-navigation-menu--full-company-logo--image--margin-y: $ibo-spacing-0 !default;

View File

@@ -41,6 +41,12 @@ $ibo-activity-panel--tab-title-decoration--border-radius: $ibo-border-radius-300
$ibo-activity-panel--tab-title-draft-indicator--margin-x: $ibo-activity-panel--tab-title-decoration--margin-right !default;
$ibo-activity-panel--tab-title-messages-count--margin-left: $ibo-activity-panel--tab-title-draft-indicator--margin-x !default;
$ibo-activity-panel--tab-title-messages-count--background-color: $ibo-color-grey-200 !default;
$ibo-activity-panel--tab-title-messages-count--padding-x: $ibo-spacing-200 !default;
$ibo-activity-panel--tab-title-messages-count--padding-y: $ibo-spacing-0 !default;
$ibo-activity-panel--tab-title-messages-count--border-radius: $ibo-border-radius-300 !default;
$ibo-activity-panel--tab-title-text--max-width: 100px !default;
/* - Tab toolbar */
@@ -180,6 +186,9 @@ $ibo-activity-panel--open-icon--margin-left: 0.75rem !default;
.ibo-activity-panel--tab-title{
background-color: $ibo-activity-panel--tab-title--is-active--background-color;
}
.ibo-activity-panel--tab-title-messages-count{
display: none;
}
}
&.ibo-is-draft{
.ibo-activity-panel--tab-title-draft-indicator{
@@ -213,6 +222,17 @@ $ibo-activity-panel--open-icon--margin-left: 0.75rem !default;
border-radius: $ibo-activity-panel--tab-title-decoration--border-radius;
@extend %ibo-depression-100;
}
.ibo-activity-panel--tab-title-messages-count{
display: inline-block;
margin-left: $ibo-activity-panel--tab-title-messages-count--margin-left;
background-color: $ibo-activity-panel--tab-title-messages-count--background-color;
padding: $ibo-activity-panel--tab-title-messages-count--padding-y $ibo-activity-panel--tab-title-messages-count--padding-x;
border-radius: $ibo-activity-panel--tab-title-messages-count--border-radius;
&[data-messages-count="0"]{
display: none;
}
}
.ibo-activity-panel--tab-title-draft-indicator{
display: none;
margin-left: $ibo-activity-panel--tab-title-draft-indicator--margin-x;

View File

@@ -118,13 +118,14 @@ $ibo-tab-container--tab-container--last--min-height: 60vh !default;
}
.ibo-tab-container--extra-tabs-list {
position: absolute;
z-index: 1;
top: calc(100% + 6px);
right: 12px;
position: fixed;
z-index: 10; /* To be above linkedset datatables */
/* top: Must be computed on menu opening, if set back to absolute, value must be calc(100% + 6px); */
/* right: Must be computed on menu opening, if set back to absolute, value must be 12px; */
max-height: $ibo-tab-container--extra-tabs-list--max-height;
display: flex;
flex-direction: column;
overflow-y: auto;
background-color: $ibo-tab-container--extra-tabs-list--background-color;
border-radius: $ibo-tab-container--extra-tabs-list--border-radius;
@@ -136,7 +137,9 @@ $ibo-tab-container--tab-container--last--min-height: 60vh !default;
max-width: $ibo-tab-container--extra-tab-toggler--max-width;
color: $ibo-tab-container--extra-tab-toggler--text-color;
@extend %ibo-text-truncated-with-ellipsis;
overflow-x: clip; /* For unknown reason yet, this is necessary otherwise the element will have almost no height */
&:hover,
&:active {

View File

@@ -9,6 +9,7 @@
@import "components/all";
@import "layout/all";
@import "application/all";
@import "datamodel/all";
@import "pages/all";
@import "blocks-integrations/all";
@import "themes/all";

View File

@@ -0,0 +1,20 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-about-box--top-part--children--padding-y: $ibo-spacing-500 !default;
$ibo-about-box--top-part--children--padding-x: $ibo-spacing-400 !default;
$ibo-about-box--top-part--children--margin-y: auto !default;
$ibo-about-box--top-part--children--margin-x: auto !default;
$ibo-about-box--top-part--children--width: 50% !default;
.ibo-about-box--top-part{
display: flex;
flex-direction: row;
align-content: center;
> div{
padding: $ibo-about-box--top-part--children--padding-y $ibo-about-box--top-part--children--padding-x;
margin: $ibo-about-box--top-part--children--margin-y $ibo-about-box--top-part--children--margin-x;
width: $ibo-about-box--top-part--children--width;
}
}

View File

@@ -3,6 +3,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
@import "about";
@import "base";
@import "preferences";
@import "attachments";
@@ -12,4 +13,6 @@
@import "datamodel-viewer";
@import "csv-import";
@import "global-search";
@import "welcome-popup";
@import "run-query";
@import "welcome-popup";
@import "oauth.wizard";

View File

@@ -27,11 +27,6 @@ tr.ibo-csv-import--row-unchanged td {
border-bottom: 1px $ibo-color-grey-400 solid;
}
.wizContainer table tr.ibo-csv-import--row-error td {
border-bottom: 1px $ibo-color-grey-400 solid;
background-color: $ibo-color-red-200;
}
tr.ibo-csv-import--row-modified td {
border-bottom: 1px $ibo-color-grey-400 solid;
}
@@ -44,4 +39,4 @@ tr.ibo-csv-import--row-added td {
font-size: 4em;
color: $ibo-color-primary-400;
margin: 20px;
}
}

View File

@@ -0,0 +1,16 @@
.ibo-oauth-wizard .ibo-panel--body{
.ibo-oauth-wizard--form--container{
display: flex;
flex-direction: row;
flex-grow: 1;
}
.ibo-oauth-wizard--form {
}
.ibo-oauth-wizard--illustration svg{
max-height: 400px;
}
}
#ibo-oauth-wizard--conf--result{
white-space: pre-wrap
}

View File

@@ -0,0 +1,10 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-run-query--highlight--background-color: $ibo-color-primary-300 !default;
.ibo-run-query--highlight{
background-color: $ibo-run-query--highlight--background-color;
}

View File

@@ -134,6 +134,9 @@ body.ibo-has-fullscreen-descendant {
@extend %ibo-font-code-150;
}
.ibo-add-margin-top-250{
margin-top: $ibo-spacing-400;
}
/*
* A single class to handle WYSIWYG generated content, where only HTML tags are available
* See https://bulma.io/documentation/elements/content/
@@ -158,7 +161,7 @@ body.ibo-has-fullscreen-descendant {
/* Preserve original text color in code blocks, except for the Highlight.js blocks which have their own colors */
& > code,
:not(pre.hljs) code {
code:not(.hljs) {
color: inherit;
}
}

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