Compare commits

..

457 Commits

Author SHA1 Message Date
Stephen Abello
dc553ca83c N°5298 - Update CKEditor to version 5 2024-04-15 12:53:21 +02:00
vdumas
14c637c7f3 N°7428 - Fix spelling mistake on FR dictionary (lnkxxxToFunctionalCI) 2024-04-15 12:27:56 +02:00
odain
3ce6c8b7cf Merge branch 'support/3.1' into support/3.2 2024-04-15 10:23:37 +02:00
odain
b4cdf5cf6d Merge branch 'support/3.0' into support/3.1 2024-04-15 10:23:22 +02:00
odain
77cc4672b0 Merge branch 'support/2.7' into support/3.0 2024-04-15 10:20:49 +02:00
vdumas
331e66e594 N°7447 - Ease User Dashboard clean-up for iTop administrator 2024-04-15 10:11:39 +02:00
odain
b65e931c4c N°7439 - setup wizard broken on essential targets after fresh install via unattended CLI 2024-04-15 09:57:54 +02:00
odain
de5a9261df Merge branch 'support/3.1' into support/3.2 2024-04-12 17:19:25 +02:00
odain
46b0dabb1d Merge branch 'support/3.0' into support/3.1 2024-04-12 17:18:44 +02:00
odain
dfbfab7005 N°7407 - adapt test to 3.0 test SDK evolutions 2024-04-12 17:17:03 +02:00
odain
aa831b632c Merge branch 'support/2.7' into support/3.0 2024-04-12 17:16:22 +02:00
odain
6cb3519308 N°7407 - test readability 2024-04-12 16:59:56 +02:00
odain
cfb9fae648 N°7407 - fix previous commit 2024-04-12 16:49:11 +02:00
odain
f4e791734f N°7407 - remove phpunit annotation 2024-04-12 14:49:20 +02:00
odain
6653ab0668 N°7407 - fix missing extension installation via unattended from production-modules or extension folder 2024-04-12 13:25:40 +02:00
odain
7ab258ba03 N°7439 - setup wizard broken on essential targets 2024-04-12 11:32:04 +02:00
odain
b5af30a93f N°7407 - refactor unattended tests to make work anywhere 2024-04-12 11:32:04 +02:00
Molkobain
dad406d208 N°6964 - Improve PHPDoc and method name to explicit that paths are relative 2024-04-12 10:50:59 +02:00
Molkobain
a6d01739ba N°6964 - Fix unit test data not compliant with tested API 2024-04-12 10:45:56 +02:00
Molkobain
e3501447ad Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-04-12 10:12:04 +02:00
Molkobain
2294fce5da Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-04-12 10:06:27 +02:00
Molkobain
ce5c05234d Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-04-12 10:02:19 +02:00
Molkobain
bbfa601ab1 N°7446 - Add temporary workaround to fix an issue due to DB views creation. 2024-04-12 09:59:14 +02:00
Lars Kaltefleiter
93e1f6ae03 N°6964 - Add API to allow modules to register files to include in the backup (#547)
* Allow to include backup extra file via interface

* Update application/applicationextension.inc.php

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

* Add iBackupExtraFilesExtension to plugin list

* decouple extra_files via config and interface

* Add unit tests for iBackupExtraFilesExtension

* Enable recursive creation of destination directories

* Update application/applicationextension.inc.php

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

* Update setup/backup.class.inc.php

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

* Update tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php

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

* Update application/applicationextension.inc.php

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

* Update core/metamodel.class.php

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

* Update setup/backup.class.inc.php

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

---------

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@me.com>
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-04-12 09:17:17 +02:00
odain
2a9add241e Merge branch 'support/3.1' into support/3.2 2024-04-11 18:55:50 +02:00
odain
c9a9ec2fed Merge branch 'support/3.0' into support/3.1 2024-04-11 18:55:25 +02:00
odain
83764deedb Merge branch 'support/2.7' into support/3.0 2024-04-11 18:55:00 +02:00
odain
172b1cb1ff N°7407 - add phpunit annotation to exclude tests on top of targets 2024-04-11 18:54:43 +02:00
Molkobain
8a4e144725 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-04-11 17:00:40 +02:00
Molkobain
5f35effad9 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-04-11 16:58:02 +02:00
Molkobain
e1374a0e6b Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-04-11 16:56:25 +02:00
Molkobain
ca356859a3 N°7446 - Add comment for better understanding 2024-04-11 16:55:48 +02:00
Molkobain
5efe294895 N°7446 - Fix custom datamodel test class not creating DB tables correctly 2024-04-11 16:50:27 +02:00
odain
6a6dacc8ce N°7407 - fix ci test adapt to 3.2 DM 2024-04-10 15:35:01 +02:00
odain
28feddb6c9 Merge branch 'support/3.1' into support/3.2 2024-04-10 14:26:29 +02:00
odain
e6fa589412 Merge branch 'support/3.0' into support/3.1 2024-04-10 14:14:28 +02:00
odain
18d0b88531 N°7407 - fix merge 2024-04-10 14:11:58 +02:00
odain
3139a0b610 Merge branch 'support/2.7' into support/3.0 2024-04-10 14:06:41 +02:00
odain
e0170ccc7e N°7407 - InstallationFileServiceTest relies on local installation.xml to reduce maintenance 2024-04-10 14:05:39 +02:00
jf-cbd
c24e7ef318 Merge branch 'refs/heads/support/3.1' into support/3.2 2024-04-10 10:34:50 +02:00
jf-cbd
ffefa5495a Adding CSRF protection to simulation step in CSV import 2024-04-10 10:34:06 +02:00
odain
3f773539fe Merge branch 'support/3.1' into support/3.2 2024-04-09 21:29:11 +02:00
odain
a371b7f03b N°7407 - fix ci itop installation 2024-04-09 21:21:46 +02:00
odain
de97a6263f N°7407 - fix test and itop install in ci envt 2024-04-09 16:52:06 +02:00
odain
233bbebd93 Merge branch 'support/3.1' into support/3.2 2024-04-09 11:06:54 +02:00
odain
f0c5264fc8 Merge branch 'support/3.0' into support/3.1 2024-04-09 11:06:38 +02:00
odain
367aac3e04 Merge branch 'support/2.7' into support/3.0 2024-04-09 11:06:17 +02:00
odain
3b78885f38 N°7407 - unattended test cleanup for PHP 8.x deprecations 2024-04-09 11:06:03 +02:00
odain
793f5c7cbe N°7407 - adapt unattended test to 3.2 installation.xml choices 2024-04-09 11:02:05 +02:00
odain
1d4cb6034d Merge branch 'support/3.1' into support/3.2 2024-04-09 10:55:29 +02:00
odain
e6814d6860 N°7407 - adapt unattended test to 3.1 installation.xml choices 2024-04-09 10:55:05 +02:00
Molkobain
79198f51a3 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-04-09 10:52:00 +02:00
odain
f14b4c32be N°7407 - adapt unattended test to 3.0 installation.xml choices 2024-04-09 10:46:44 +02:00
Molkobain
6be5264fe9 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-04-09 10:41:08 +02:00
Molkobain
6a30d6caa9 N°7438 - Dashboard: Fix crash when closing the editor modal 2024-04-09 10:40:06 +02:00
odain
628a7319d1 Merge branch 'support/3.1' into support/3.2
# Conflicts:
#	setup/applicationinstaller.class.inc.php
2024-04-09 10:12:29 +02:00
odain
bc8543d88c Merge branch 'support/3.0' into support/3.1
# Conflicts:
#	setup/modulediscovery.class.inc.php
#	setup/runtimeenv.class.inc.php
#	setup/unattended-install/unattended-install.php
#	tests/setup_params/default-params.xml
2024-04-09 10:11:06 +02:00
odain
a51242dc36 N°7407 - remove 2.7 requires in unattended service 2024-04-09 10:08:43 +02:00
odain
64ba706083 Merge branch 'support/2.7' into support/3.0
# Conflicts:
#	setup/applicationinstaller.class.inc.php
#	setup/modulediscovery.class.inc.php
#	setup/runtimeenv.class.inc.php
#	setup/unattended-install/unattended-install.php
#	tests/setup_params/default-params.xml
2024-04-09 10:07:40 +02:00
odain
ed562c9f73 N°7407 - fix unattended test enhancement 2024-04-09 10:02:06 +02:00
odain-cbd
85c576a986 N°7407 - N°7306 - Ease iTop installation via unattended CLI by using installation.xml choices (#641)
* N°7306 - Use iTop configuration settings to run unattended installation (instead of XML file settings)

* 7306 - fix infinite loop with db_tls.ca null

* 7306 - complete fields to use from itop configuration instead of XML setup

* fix using default language from conf

* 6365 - temp work

* 6365 - add option to select modules from installation.xml

* 6365-select modules option in unattended install

* 6365 - pass env to service + debug failed test

* 6365 - debug ci again + separate process annotation

* 6365 - fix test + cleanup

* 6365 - ci using use_installation_xml mode

* 6365 - ci using use_installation_xml mode

* 6365 - pass selected_modules to unattended

* N°6365 - Compute selected modules based on selected extensions coming from XML setup

* switch constr parameters and fix call from unattended cli

* 6365 - use use_installation_xml for unattended install only when no selected modules already provided

* test ci XML setup including selected extensions but no modules

* test ci installing iTop without selected modules/extenesions: guess via installation.xml

* same but without even providing XML setup - comment it in ci_description.ini

* 7306 - cleanup requires

* use infra master

* N°6365 - make current unattended CLI work with any iTop version (CLIPage compatibility)

* N°6365 - log which modules will be installed during setup

* N°6365 - unattended documentation + bash helper

* 6365- fix warning due to copies index access

* 6365 - enhance traces feedback to understant which and how modules are computes

* 6365 - enhance bash CLI + doc

* 6365 - fix require clipage compatibility

* 6365 - add return for better cli ouput

* 6365 - enhance ouput messages

* Document the usage and harmonize argument names (still not perfect)

* 6365 - fix use of new param param-file

* 6365 - fix test + vardump cleanup

* N°6365 - use underscore for unattended install options as advices in the PR

* 6365 -enhance test by using PHP_BINARY

---------

Co-authored-by: Romain Quetiez <romain.quetiez@combodo.com>
2024-04-09 10:00:58 +02:00
Molkobain
3deb74a4d1 N°6964 - Allow folder creation to be recursive 2024-04-08 21:46:02 +02:00
jf-cbd
b9dd891aac Merge branch 'refs/heads/support/3.1' into support/3.2 2024-04-08 17:26:14 +02:00
jf-cbd
1f2469e1e4 Remove mixed type uses in itop 3.1 2024-04-08 17:24:51 +02:00
jf-cbd
8fa56a6f3f Add namespace for 3.2 2024-04-08 17:12:48 +02:00
jf-cbd
22af1a8787 Remove namespace for 3.1 2024-04-08 17:10:05 +02:00
Molkobain
5e15fbec45 N°7312 - Dashboard: Fix JS crash on custom version creation of UserRequest Overview page on Windows server 2024-04-08 17:03:02 +02:00
Molkobain
3a6a5ca49d N°7416 - Fix typo in composer.json 2024-04-08 15:11:28 +02:00
jf-cbd
3d6509e246 Merge remote-tracking branch 'refs/remotes/origin/support/3.1' into support/3.2 2024-04-08 14:09:54 +02:00
jf-cbd
cd34f8b5eb Removed namespaces in 3.1 2024-04-08 12:19:43 +02:00
jf-cbd
8357c86361 🐛 Fix php 7.4 compatibility in bulkchange.class.inc.php (for itop 3.1) 2024-04-08 11:10:12 +02:00
Molkobain
d48b5d7d21 N°7416 - Setup: Add warning for optionnal PHP extension "APCu" 2024-04-08 10:51:19 +02:00
vdumas
efe61201e5 N°7417 - Improve error message when a Root Menu is not a MenuGroup 2024-04-05 18:20:19 +02:00
vdumas
a458d98688 N°7399 - Remove deprecated datamodel methods 2024-04-05 15:59:00 +02:00
jf-cbd
a3553202d9 Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	pages/csvimport.php
2024-04-05 14:56:38 +02:00
jf-cbd
b10d381dda N°7374 - Security hardening 2024-04-05 14:40:56 +02:00
Eric Espie
9dc7b6dc0c N°7405 - Fix unit tests 2024-04-05 11:29:41 +02:00
Eric Espie
1be67f349f N°7405 - Cache error message 2024-04-05 11:08:47 +02:00
Molkobain
4ca92affcf N°7264 - Fix visual glitches due to seletize.js upgrade 2024-04-04 15:01:57 +02:00
Stephen Abello
3f401e4de0 N°7391 N°7392 - Add themes for accessibility (#639)
* N°7391 - Add color blind friendly themes

* N°7392 - Add high contrast theme

* Add modules to installation.xml
2024-04-04 11:17:14 +02:00
Molkobain
9b198bc76e N°7264 - Fix regression from ff130516 2024-04-04 09:43:24 +02:00
Molkobain
f7230de6d6 N°7264 - Improve async load of CSS files to avoid duplicates in the webpage.
Based on the same mechanism that was made for JS files.
2024-04-03 16:16:10 +02:00
odain
a4aa494e5d Merge branch 'support/3.1' into support/3.2 2024-04-02 15:06:36 +02:00
odain
8647414a33 N°5120 - PR merge adaptation to CLIPage 3.0 2024-04-02 15:05:35 +02:00
odain
a58f0bfc0b Merge branch 'support/3.0' into support/3.1 2024-04-02 15:02:26 +02:00
odain
ff1305165e N°5120 - PR merge adaptation to CLIPage 2024-04-02 14:42:21 +02:00
Molkobain
d9b87064a1 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-04-02 10:39:59 +02:00
Molkobain
a468bf8f7e Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-04-02 10:38:30 +02:00
Molkobain
65c706fdfe Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-04-02 10:37:08 +02:00
Molkobain
0853645264 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-04-02 10:26:27 +02:00
Molkobain
e6162fe958 N°7402 - Fix JS error when trying to add two or more items on an indirect linkset when updating the source object 2024-04-02 10:22:44 +02:00
Stephen Abello
25f266ef66 N°4631 - Update fullscreen class 2024-04-02 10:13:28 +02:00
Stephen Abello
fee07960ca Update stickers preview 2024-03-29 11:17:54 +01:00
odain-cbd
5a34c76cc4 N°5120 - Unattended install : use cty toolkit version (#624)
* N°5120 - Unattended install : use cty toolkit version

* N°5120 - CLI mode validation

* 5120 - bring CI enhancements

* 5120 - bring back saas use-itop-config option: to read db settings from conf directly

* 5120 - move unattended script in setup folder/unattended-install

* 5120 - use-itop-config option: take db_tls_enabled and db_tls_ca into account

* 5120 - move test

* 5120 - put ci enhancements back - logs and conf preservation with install mode

* 5120 - keep PR simple - remove saas use-itop-config option for now

* 5120 - remove ci enhancement to preserve configuration

* Update setup/unattended-install/README.md

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

* 5120 - documentation

* 5120 - fix log level

* 5120 - fix test

* fix phpunit test comment

---------

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2024-03-29 11:09:27 +01:00
Stephen Abello
5efb1a0872 N°4631 - Fix a display issue when description field is fullscreen white using vertical tabs 2024-03-28 17:01:45 +01:00
Eric Espie
2c68f78027 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-28 13:32:33 +01:00
Eric Espie
7f9b60d66f N°5913 - Add Event Listener methods & enhance methods management 2024-03-28 11:02:55 +01:00
Eric Espie
816df1b551 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-27 11:29:32 +01:00
Eric Espie
1278c4b196 N°7165 - Error message on application upgrade fatal Error due to CSS compilation 2024-03-27 11:11:55 +01:00
Eric Espie
a7f3bf9a56 N°7294 - EVENT_ADD_ATTACHMENT_TO_OBJECT not triggered 2024-03-27 10:34:48 +01:00
Eric Espie
4eed5bdeb9 N°7165 - Error message on application upgrade fatal Error due to CSS compilation 2024-03-27 10:12:21 +01:00
Molkobain
739afdb1ec Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-26 13:00:25 +01:00
Molkobain
75a01db959 N°7194 - Remove "external link" icon in the tooltip 2024-03-26 12:04:59 +01:00
Stephen Abello
c29bff4d91 N°7355 - Fix deprecated jQuery call 2024-03-26 11:58:17 +01:00
Eric Espie
7b999cef50 Compilation issue 2024-03-26 11:57:08 +01:00
Anne-Catherine
69e481dbc1 Improve Clear function in ExtKeyWidget (#519) 2024-03-26 11:49:14 +01:00
Anne-Catherine
279b29a98c N°7194 - Add link to datamodel class schema on object details (#613) 2024-03-26 11:35:44 +01:00
Molkobain
12b30c1531 N°7355 - Upgrade datatables.net to 1.13.11 (and plugins) 2024-03-26 11:02:46 +01:00
Molkobain
bcfbacc625 N°7355 - Fix deprecated usage of .bind() due to jQuery migrate upgrade 2024-03-26 10:59:48 +01:00
Molkobain
36d6c13941 N°7355 - Fix deprecated usage of .offset() due to jQuery migrate upgrade 2024-03-26 10:46:04 +01:00
Stephen Abello
4952fc5575 Fix deprecated jQuery call to bind 2024-03-26 10:44:58 +01:00
Stephen Abello
7b8634e9e7 Fix deprecated jQuery call 2024-03-26 10:41:24 +01:00
Molkobain
c86ebba60d N°7355 - Update jQuery-contextmenu to 2.9.2 2024-03-22 16:40:50 +01:00
Molkobain
db4c70cea3 N°7355 - Update jQuery-migrate to 3.4.1 2024-03-22 16:35:41 +01:00
Molkobain
e8c4c45c5c N°7355 - Update jQuery to 3.7.1 2024-03-22 16:32:43 +01:00
Molkobain
a3d5712087 N°7355 - Update showdown to 2.1.0 2024-03-22 16:27:46 +01:00
Molkobain
5b8a3459f5 N°7331 - Update Composer cleanup script with existing questionable folders 2024-03-22 15:59:48 +01:00
Molkobain
8a983ecbb7 N°7355 - Update magnific-popup to 1.1.0 2024-03-22 15:55:44 +01:00
Molkobain
e62473d4e9 N°7355 - Update clipboard to 2.0.11 2024-03-22 15:53:21 +01:00
Molkobain
054520cdac N°7355 - Update ace-builds to 1.32.7 2024-03-22 15:48:41 +01:00
Molkobain
b38a7c8ab6 N°7331 - Update cleanup script to remove denied folders no matter if they seem questionable 2024-03-22 15:47:25 +01:00
Molkobain
3588a50597 N°7355 - Update blueimp-file-upload to 10.32.0 and remove optional dependencies 2024-03-22 14:36:05 +01:00
Molkobain
babdd9f163 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-22 14:23:00 +01:00
Molkobain
5d8a0f8e9f N°7355 - Update @popperjs to 2.11.8 2024-03-22 14:22:43 +01:00
Molkobain
52106fe48c N°7331 - Remove unnecessary files 2024-03-22 14:21:44 +01:00
Molkobain
e7a04e0e70 N°7331 - Fix cleanup script to remove all denied folders 2024-03-22 11:55:16 +01:00
Eric Espie
90458f6048 N°6974 - Flatten classes in datamodel - Allow _delta="merge" in strict mode 2024-03-22 10:11:25 +01:00
Molkobain
3a990f46d3 N°7157 - Add 'subscription_policy' to remaning Trigger zlists 2024-03-22 09:46:31 +01:00
Molkobain
673b01585d Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	css/setup.css
#	setup/setuppage.class.inc.php
2024-03-21 17:38:49 +01:00
Molkobain
3653a4bc90 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	css/setup.css
2024-03-21 15:52:57 +01:00
Molkobain
bdfd956825 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	css/setup.css
#	setup/setuppage.class.inc.php
2024-03-21 15:37:33 +01:00
Molkobain
da99a250bf N°7075 - Add check for Content Security Policies (CSP) in the setup 2024-03-21 14:20:22 +01:00
Molkobain
d57fd05552 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-21 14:06:14 +01:00
Molkobain
5554241877 N°7122 N°4164 - Fix wrong merge in b08b5297 2024-03-21 14:04:18 +01:00
vdumas
d9232a645d N°7379 - Default search for Workorder, lnkContactToTicket & Contact 2024-03-20 16:47:46 +01:00
Molkobain
def10a9877 Add log channel for data integrity 2024-03-20 10:09:10 +01:00
Benjamin Dalsass
b29597110e N°6937 - Symfony 6.4 - Handle Symfony configuration files 2024-03-19 20:58:00 +01:00
Eric Espie
c7a8d90364 Fix XML version 2024-03-19 15:29:49 +01:00
Molkobain
86489dbbe1 N°6974 - Fix autoloaders 2024-03-19 14:51:24 +01:00
Eric Espie
6098842d9f Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	core/designdocument.class.inc.php
#	lib/composer/autoload_files.php
#	lib/composer/autoload_static.php
2024-03-19 14:06:24 +01:00
Eric Espié
2f30a0146e N°6974 - Flatten classes in datamodel (#603)
* N°6974 - Flatten classes in datamodel

* N°6882 - LoadDelta() in lax/strict mode

* N°6974 - Flatten classes in datamodel

* N°6882 - LoadDelta() in lax/strict mode

* N°7186 - Code hardening

* N°6974 - Flatten classes in datamodel

* N°6660 and N°7318 - Support delete_if_exists and define_if_not_exists in XML injection

* N°6974 - Flatten classes in datamodel

* Apply suggestions from code review

* Update core/designdocument.class.inc.php

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-03-19 13:53:14 +01:00
Pierre Goiffon
193af6c759 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-18 18:20:07 +01:00
Pierre Goiffon
1de9e704fc Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-18 18:19:52 +01:00
Pierre Goiffon
f4b9a9a5fe N°6455 Fix datepicker widget icon on button
The buttonText is now escaped

(cherry picked from commit fa5d03fc6e)
2024-03-18 18:19:30 +01:00
Pierre Goiffon
561e743fc3 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-18 18:15:52 +01:00
Pierre Goiffon
fa5d03fc6e N°6455 Fix datepicker widget icon on button
The buttonText is now escaped
2024-03-18 18:15:39 +01:00
Molkobain
7b5fa0a912 N°7122 - Fix wrongfully merged JS inclusion in b08b5297 2024-03-15 11:05:08 +01:00
Molkobain
5f88391935 N°7122 - Fix wrongfully merged JS inclusion 2024-03-15 09:36:15 +01:00
Pierre Goiffon
29300fd91e N°7264 Update selectize.js from 0.12.4 to 0.15.2
Source https://github.com/selectize/selectize.js/releases/tag/v0.15.2
2024-03-14 17:14:51 +01:00
Pierre Goiffon
2c8b2f6c71 N°7264 Update raphael-min.js from 2.1.2 to 2.3.0 2024-03-14 17:14:51 +01:00
Pierre Goiffon
4cde461876 N°7264 Update jquery-ui-timepicker-addon.js from 1.6.1 to 1.6.3
Source https://github.com/trentrichardson/jQuery-Timepicker-Addon/tags
2024-03-14 17:14:51 +01:00
Pierre Goiffon
5a3bfa8043 N°7264 Update jquery.blockUI.js from 2.59.0-2013.04.05 to 2.70
Source https://github.com/malsup/blockui
2024-03-14 17:13:12 +01:00
jf-cbd
c5544a7a1e Merge branch 'support/3.1' into support/3.2 2024-03-14 17:02:52 +01:00
jf-cbd
8ffcb01c43 Merge branch 'support/3.0' into support/3.1 2024-03-14 17:00:20 +01:00
jf-cbd
5c46b4ef4a Added modules to GetLtsCompatibleModulesList (Dictionnarie tests) 2024-03-14 16:59:32 +01:00
Pierre Goiffon
912c7fa956 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-14 09:14:30 +01:00
Pierre Goiffon
79cdb837b5 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	core/log.class.inc.php
2024-03-14 09:13:56 +01:00
Molkobain
db2ea617d3 N°7331 - Fix wrong method call due to previous refactoring 2024-03-13 16:30:59 +01:00
Pierre Goiffon
7499e41e40 N°7351 Fix name in package.json 2024-03-13 16:23:20 +01:00
Pierre Goiffon
a97935ca01 N°7336 DeprecatedCallsLog robustness (#632)
Was creating PHP notices when deprecated method caller wasn't a class/method
Found in iTop 3.2.0-dev with itop-object-copier copy.php : it is calling WebPage::add_linked_script directly inside the copy.php script (no class nor function)

Co-authored-by: odain <olivier.dain@combodo.com>
2024-03-13 15:38:21 +01:00
Molkobain
dc6ea37f23 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-13 15:29:22 +01:00
Molkobain
87181669d1 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-13 15:18:33 +01:00
Molkobain
efd7fb0f59 N°7331 - Fix wrong file extension in .htaccess file 2024-03-13 15:16:46 +01:00
Molkobain
c2f72f713a N°7331 - Refactor for better understanding 2024-03-13 15:07:47 +01:00
Molkobain
700c4d0b04 N°7331 - Remove "example" (single) as well 2024-03-13 15:07:47 +01:00
Molkobain
43a8152de1 N°7331 - Remove unnecessary files from node_modules 2024-03-13 15:07:47 +01:00
Molkobain
8c1d986a03 N°7331 - Ensure to keep folder browsing protection files after install/update command 2024-03-13 15:07:47 +01:00
Molkobain
f3dd414a51 N°7331 - Add NPM cleanup scripts 2024-03-13 15:07:47 +01:00
Molkobain
d1a4d333eb N°7331 - Refactor Composer cleanup scripts to be used by other dependencies managers as well 2024-03-13 15:07:47 +01:00
Pierre Goiffon
b934cbe89e Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-13 10:08:28 +01:00
Pierre Goiffon
71a0f8b87d Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-13 10:03:48 +01:00
Pierre Goiffon
a4edf8cb21 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	tests/php-unit-tests/unitary-tests/setup/SetupUtilsTest.php
2024-03-13 09:59:28 +01:00
Pierre Goiffon
dbd5ba0377 N°7302 Fix SetupUtilsTest::testHumanReadableSize 2024-03-13 09:56:31 +01:00
Pierre Goiffon
5d6f293956 N°7302 Report SetupUtilsTest::testHumanReadableSize in the 2.7 branch 2024-03-13 09:48:46 +01:00
Pierre Goiffon
65e6c84477 N°7302 Fix SetupUtilsTest::testHumanReadableSize 2024-03-13 09:37:34 +01:00
Pierre Goiffon
61e04c5a73 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-13 09:27:53 +01:00
Pierre Goiffon
9cc7ccb1cd Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-13 09:27:39 +01:00
Pierre Goiffon
a337ef3d88 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	setup/modelfactory.class.inc.php
#	setup/setuputils.class.inc.php
2024-03-13 09:27:06 +01:00
Pierre Goiffon
27ac1fe276 N°7345 Accept DateTime objects for DBObject::Set() calls on AttributeDateTime and children (#618) 2024-03-12 18:29:55 +01:00
Pierre Goiffon
986c24d777 N°7302 Fix unit name in \SetupUtils::HumanReadableSize (#626) 2024-03-12 18:09:29 +01:00
Pierre Goiffon
763112c179 N°7344 rest.php core/get : add try/catch around query execution (#622)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-03-12 18:08:04 +01:00
Pierre Goiffon
a5efd981d8 N°7343 Catch ParseError when loading dict files in setup (#615) 2024-03-12 18:05:38 +01:00
Pierre Goiffon
6450b52697 Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	core/dbobject.class.php
#	tests/php-unit-tests/unitary-tests/core/DBObjectTest.php
2024-03-12 17:44:33 +01:00
Pierre Goiffon
c0e4d04a1c Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	tests/php-unit-tests/unitary-tests/core/DBObjectTest.php
2024-03-12 17:36:04 +01:00
Pierre Goiffon
289ca7b505 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-12 17:34:51 +01:00
Pierre Goiffon
2922b22478 \DBObject::GetSearchForUniquenessRule remove wrong @api 2024-03-12 17:34:28 +01:00
Pierre Goiffon
2af05a437e N°4314 - Fix Uniqueness rules not working with Silo
(cherry picked from commit e8c11f38d2)
2024-03-12 17:32:56 +01:00
vdumas
71d9536bc4 N°7268 Method SetComputedDate fails on Date only attribute
(cherry picked from commit b6caa51552)
(cherry picked from commit c8810708ef)
2024-03-12 17:29:04 +01:00
Molkobain
b1e1a66496 N°7157 - Remove dict entries for advanced mode in notifications center 2024-03-12 11:34:31 +01:00
Molkobain
d7270c56cd N°7315 - Migrate usages in TwigBase::Controller to use new API if possible 2024-03-12 11:22:03 +01:00
Benjamin Dalsass
7a7b7381c9 N°2732 - DataSynchro : process stopped when memory peak usage exceeds 2 2024-03-12 09:48:01 +01:00
Molkobain
da32362ef6 N°7157 - Remove advanced mode in notifications center 2024-03-12 09:12:02 +01:00
Molkobain
5569df5950 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-11 21:59:10 +01:00
Molkobain
b08b5297cf N°7122 N°4164 - Adjustment to Symfony 5.4 2024-03-11 21:57:37 +01:00
Molkobain
3e6e096f62 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig
2024-03-11 21:27:59 +01:00
Molkobain
6377a738c5 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-11 21:18:53 +01:00
Molkobain
a9f8dcc5e8 N°7122 N°4164 - Portal: Hide log off button when user can't actually log off (eg. SSO using SAML or other providers) (#599)
* N°7122 N°4164 - Portal: Hide log off button when user can't actually log off (eg. SSO using SAML or other providers)

* N°7122 - Fix typo

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

---------

Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2024-03-11 21:13:09 +01:00
Pierre Goiffon
9470d9b9ec Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-11 16:40:26 +01:00
Pierre Goiffon
9750fec959 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-11 16:40:14 +01:00
Pierre Goiffon
969a301cbb Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-11 16:40:01 +01:00
Pierre Goiffon
c325294e17 N°6599 Update moment from 2.22.2 to 2.30.1 2024-03-11 16:39:05 +01:00
Pierre Goiffon
8588757da9 N°6599 Update moment from 2.22.2 to 2.30.1 2024-03-11 16:31:24 +01:00
Pierre Goiffon
f894cb24c6 N°6599 Move moment.js 2.22.2 to NPM 2024-03-11 16:27:44 +01:00
Stephen Abello
722765c0aa N°7130 - When moving data in the setup from multiple columns, prevent later data from erasing previous data when it's NULL 2024-03-11 16:11:30 +01:00
Benjamin Dalsass
5e9b4da68c Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-11 16:04:48 +01:00
Benjamin Dalsass
af2c6d9ab8 N°7279 - AttributeClass defined in XML datamodel compilation issue
- make more_values property optional
2024-03-11 16:03:38 +01:00
Stephen Abello
0176905c20 N°2039 - Fix button margins in view all notifications page 2024-03-11 10:09:21 +01:00
Stephen Abello
5e4f76bde9 N°2039 - Fix button margins in view all notifications page 2024-03-11 09:25:17 +01:00
Molkobain
0c3e839381 N°7303 - Fix failure to add attachment in portal due to regression from e830c903 2024-03-08 17:18:32 +01:00
Thomas Casteleyn
5be386d03e N°4894 - Improve AttributeDecimal validation during CSV import (#248)
* Update AttributeDecimal validation pattern

* Update phpdoc

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

* Reduce unneeded sprintf flags

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-03-08 17:03:51 +01:00
Molkobain
2ced460ec6 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-08 16:05:35 +01:00
Pierre Goiffon
ae9bda8bbb N°7328 Deprecate js/jquery.autocomplete.js
This lib isn't used since iTop 3.0.0 (replaced by JQuery UI autocomplete widget)
2024-03-08 15:54:50 +01:00
Molkobain
9566963835 N°7157 - Fix unit test when using symlinks 2024-03-08 15:49:47 +01:00
Eric Espie
cf6e8ab22a N°6974 - Add unit tests for compatibility validation 2024-03-08 13:29:04 +01:00
Molkobain
2aa1385958 N°7157 - Add unit test for subscription mechanism and refactor repository methods 2024-03-08 12:22:29 +01:00
Pierre Goiffon
509df0939e Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	js/jquery-ui.custom.min.js
2024-03-08 11:14:51 +01:00
Pierre Goiffon
9032dac314 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-08 11:13:43 +01:00
Pierre Goiffon
a29b0a8e33 N°6455 Update JQuery-UI from 1.12.1 to 1.13.2 2024-03-08 11:13:32 +01:00
Stephen Abello
fee1897932 N°7157 - Add link to notifications center in view all newsroom page 2024-03-08 10:46:03 +01:00
Stephen Abello
093a4cec75 N°7157 - Add more information to notifications center table 2024-03-08 10:33:21 +01:00
Stephen Abello
892a7fa95f N°7327 - Allows to differentiate newsroom priorities 2024-03-08 09:53:23 +01:00
Pierre Goiffon
48f7ae8476 N°6455 Update JQuery-UI to 1.13.2 2024-03-08 09:16:27 +01:00
Pierre Goiffon
10ef277982 N°6455 Add jquery-ui NPM package
We need jquery-ui-dist for inclusion in our web pages, but there are no security returned on this package :/
So we are adding jquery-ui, ignoring the corresponding files (only add it to package.json).
2024-03-08 09:16:27 +01:00
Molkobain
ebe7da7acb N°7157 - Fix URI passed to scandir() function in user's image placeholder selection 2024-03-07 17:26:56 +01:00
Pierre Goiffon
9fa036df7e N°5621 Move jquery-migrate 3.1.0 to NPM 2024-03-07 15:27:38 +01:00
Molkobain
c24c1ba73c N°7157 - Fix Selectize plugin error due to file being loaded twice due to slightly different URIs 2024-03-07 15:26:10 +01:00
Stephen Abello
3650cf761d N°2039 - Correctly pass context arguments to recipients OQL 2024-03-07 15:06:53 +01:00
Benjamin Dalsass
34c4d753d3 N°797 - Delete of DataSynchro incomplete 2024-03-07 14:05:50 +01:00
Molkobain
4d1f8e5704 N°7157 - Fix ValueSetEnum values as array must conserve keys 2024-03-07 11:17:35 +01:00
Pierre Goiffon
7ac283bffb Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-07 11:11:48 +01:00
Pierre Goiffon
c1efad7556 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-07 11:11:34 +01:00
Pierre Goiffon
f78b57521a Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-07 11:11:19 +01:00
Pierre Goiffon
da490739be 💡 Fix \CMDBSource::Query phpdoc block 2024-03-07 11:10:53 +01:00
Molkobain
8e8d586dcc N°7157 - Add support for backed-enum in \ValueSetEnum constructor 2024-03-07 11:02:23 +01:00
Molkobain
e05b4e772c N°7157 - Fix usage of Enum case value 2024-03-06 23:05:16 +01:00
Molkobain
02efea4e55 N°7157 - Migrate enum values from strings to PHP Enum 2024-03-06 19:31:17 +01:00
Molkobain
17bab06ff5 N°7157 - Migrate enum values from strings to PHP Enum 2024-03-06 18:40:47 +01:00
Molkobain
ab4f224a00 N°7315 - Fix regression from previous commit 2024-03-06 16:26:13 +01:00
Molkobain
fe6ee083f6 N°7315 - Migrate deprecated usages of WebPage::add_linked_stylesheet() 2024-03-05 23:06:44 +01:00
Molkobain
655539c289 N°7315 - Introduce WebPage::LinkStylesheetXXX() methods to replace WebPage::add_linked_stylesheet() 2024-03-05 22:58:59 +01:00
Molkobain
33ba754277 N°7315 - Migrate deprecated usages of WebPage::add_linked_script() 2024-03-05 22:58:57 +01:00
Molkobain
7948793674 N°7315 - Introduce WebPage::LinkScriptXXX() methods to replace WebPage::add_linked_script() 2024-03-05 22:58:28 +01:00
Molkobain
8c7b33fb06 N°7315 - Migrate relative images URLs to absolute ones in order to support pages on different depth levels 2024-03-05 21:55:00 +01:00
Molkobain
db4dfe1ba3 N°7315 - Migrate usages of WebPage::add_linked_script() to absolute URIs to ensure they are correctly loaded no matter the endpoint location 2024-03-05 21:53:04 +01:00
Stephen Abello
e00112d6e1 N°2039 - Empty newsroom cache when modifying notifications from view all page 2024-03-04 15:24:36 +01:00
Stephen Abello
3404306de8 N°2039 - Update event zlist detail 2024-03-04 15:24:36 +01:00
Stephen Abello
ff7e4d3db6 N°2039 - Display actions as independent icon buttons 2024-03-04 15:24:36 +01:00
Pierre Goiffon
e371db846a N°5621 Move showdown 2.0.0-alpha1 to NPM
Current file header is : /*! showdown v 2.0.0-alpha1 - 25-09-2018 */

Official 2.0.0-alpha doesn't match neither on content nor date :(
Considering date we would be at 1.8.7, but it is also quite different (and has vulnerabilities)
In consequence switching to 2.0.0.
2024-03-04 10:31:27 +01:00
Pierre Goiffon
5bbf3c9c35 N°5621 Move jquery.magnific-popup.js 1.0.0 to NPM 2024-03-04 10:31:27 +01:00
Pierre Goiffon
fe4233e218 N°5621 Move jquery.fileupload.js 9.22.0 (?) to NPM
Update to 9.22.1 to fix https://github.com/advisories/GHSA-4cj8-g9cp-v5wr
2024-03-04 10:31:27 +01:00
Pierre Goiffon
8490c2a22f N°5621 Move jquery.contextMenu 1.6.7 (?) to NPM 2024-03-04 10:31:27 +01:00
Pierre Goiffon
e758527ca9 N°5621 Move clipboard 2.0.4 to NPM 2024-03-04 10:31:27 +01:00
Pierre Goiffon
3e9f4df1bf N°5621 Move D3 3.5.16 to NPM 2024-03-04 10:31:26 +01:00
Pierre Goiffon
f3fbce7459 N°5621 Move C3 0.4.11 to NPM 2024-03-04 10:31:26 +01:00
Pierre Goiffon
ff079f7d01 N°5621 Move mousetrap 1.6.5 to NPM 2024-03-04 10:31:26 +01:00
Pierre Goiffon
d4c54b6e1c N°5621 Move ace 1.2.8 to NPM
As the package sizes 37.5MB (!!!!), we are keeping only the directory we are using (src-min).
The rest (demo, src, src-min-noconflict, src-noconflict) is added in the root .gitignore and not present in the index.
Description of those directories content is available in the GitHub repo README : https://github.com/ajaxorg/ace-builds
2024-03-04 10:31:26 +01:00
Pierre Goiffon
39d1ddeab8 N°5621 Move JQuery 3.5.1 to NPM 2024-03-04 10:31:26 +01:00
Pierre Goiffon
fada9793f0 N°5621 Move JQuery UI 1.12.1 to NPM 2024-03-04 10:31:25 +01:00
Pierre Goiffon
45a8e6d1c8 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-04 08:41:54 +01:00
Pierre Goiffon
bf4b07a366 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-04 08:41:25 +01:00
Pierre Goiffon
48de13b5cf Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-04 08:32:59 +01:00
Pierre Goiffon
b867faa355 Fix DBObjectTest
Error was "Class 'Combodo\iTop\Test\UnitTest\Core\DBObjectSet' not found"
2024-03-04 08:09:35 +01:00
Molkobain
1848b5f231 N°7314 - Add some PHPDoc about new recommendations 2024-03-01 21:27:19 +01:00
Molkobain
9fa53d43ab N°7314 - Add Symfony Response alternative to Webpage::output() 2024-03-01 21:10:37 +01:00
Molkobain
646e86b207 N°7314 - Remove danger zone from iTopWebPage as it was only kept to ensure we didn't a miss in 3.0.0 2024-03-01 21:10:26 +01:00
Pierre Goiffon
e93c9b8537 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-01 17:26:39 +01:00
Pierre Goiffon
849c495093 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-03-01 17:26:19 +01:00
Pierre Goiffon
e878938e25 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-03-01 17:26:05 +01:00
jf-cbd
7453cc184f ✏️ fix a typo 2024-03-01 17:25:08 +01:00
Stephen Abello
2d5cd7042a Fix not being able to unsubscribe from newsroom anymore 2024-03-01 11:08:25 +01:00
Eric Espie
7b01108c91 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-03-01 09:43:24 +01:00
Eric Espie
3b9ca4ad18 N°7310 - New Event to handle available Transitions 2024-03-01 09:39:00 +01:00
Stephen Abello
59129bc3ce N°2039 N°7298 - Allow Actions to be asynchronous (#625)
* N°2039 - Allows Actions to be asynchronous

* Add unit test

* Apply suggestions from code review

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

* GetAsynchronousGlobalSetting is now static

* None of the async task for itop notification attribute should be null

* Rename follow_global_setting to user_global_setting

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-03-01 09:27:56 +01:00
Anne-Cath
eddc750ca8 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	pages/audit.php
#	tests/php-unit-tests/unitary-tests/core/DBSearchTest.php
2024-02-29 16:53:39 +01:00
Anne-Cath
f3abe1ff13 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	pages/audit.php
2024-02-29 16:50:04 +01:00
Anne-Catherine
473cf004b6 N°6968 - Audit duration : add of a rule multiplie by 4 the time of response (#575) 2024-02-29 16:33:04 +01:00
Anne-Catherine
90a5a7a9a7 N°6968 - Audit duration : add of a rule multiplie by 4 the time of response (#575) 2024-02-29 16:18:03 +01:00
Anne-Catherine
5574952033 N°5170 - In a transition DoCheckToWrite returned error, generes a Fatal error (#539) 2024-02-29 16:14:43 +01:00
Stephen Abello
1a8de82be5 Add toast feedback when resetting newsroom cache or change image placeholder in preferences 2024-02-29 11:07:48 +01:00
Benjamin Dalsass
d15a0a0070 N°6086 - CSV import: Treat first line as a header 2024-02-28 17:04:35 +01:00
Pierre Goiffon
76167a3d54 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-28 16:44:11 +01:00
Pierre Goiffon
46273dfc12 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-28 16:43:51 +01:00
Pierre Goiffon
24f1cf8ca1 💡 Fix deprecated in JSDoc 2024-02-28 16:43:40 +01:00
Stephen Abello
2a5337d84c N°2039 - Fix notifications sorting 2024-02-28 15:20:36 +01:00
Pierre Goiffon
fbe7f559d2 N°7251 Remove usages of deprecated JS libs
Only js/json.js was used, but it is a polyfill that is not necessary anymore considering our browser requirements (see https://www.itophub.io/wiki/page?id=latest:install:requirements#web_browser)
2024-02-28 15:10:06 +01:00
vdumas
c8810708ef N°7268 - Add test on method SetComputedDate 2024-02-28 12:52:08 +01:00
vdumas
e8c11f38d2 N°4314 - Fix Uniqueness rules not working with Silo (2) 2024-02-28 10:00:21 +01:00
Anne-Catherine
1394bc221d N°3363 - Add favicon in branding (#522) 2024-02-28 09:59:11 +01:00
Anne-Catherine
baa05ba8d4 N°4342 - Improve generic bulk deletion function with memory limit handling (#321) 2024-02-28 09:55:04 +01:00
Stephen Abello
e7b493dafa N°2039 - Rework view all notifications page (#617)
* N°2039 - Rework view all notifications page

* N°2039 - Replace modals with toasts

* N°2039 - Add bulk mode to view all notifications page

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Update css/backoffice/pages/_notifications.scss

* Update dictionaries/ui/application/newsroom/fr.dictionary.itop.newsroom.php

* Apply suggestions from code review

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

* Add since in phpdoc

* Change newsroom empty notification illustration

* N°2039 - Refactor code to factorize logic

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-28 09:22:39 +01:00
Molkobain
940833a66f N°7157 - Fix trigger init to null when not passed 2024-02-27 21:46:04 +01:00
Molkobain
2b172d6e19 N°7157 - Fix ActioniTopNotification friendlyname 2024-02-27 21:28:53 +01:00
Molkobain
69677954b4 N°7157 - Change way to pass calling trigger to action in order to ease extensibility and to be able to use its attributes in placeholders 2024-02-27 21:28:51 +01:00
Anne-Cath
9c35cddfc0 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-27 18:01:33 +01:00
Anne-Catherine
86bf6ba0b0 N°5547 - Object deletion fails if friendlyname too long (#529) 2024-02-27 17:59:37 +01:00
Anne-Catherine
82e19f6eca N°6543 - Fix display of AttributeText with width parameter (#521) 2024-02-27 17:42:59 +01:00
Eric Espie
8f1d8b1dc2 N°7294 - EVENT_ADD_ATTACHMENT_TO_OBJECT not triggered on the object 2024-02-27 17:39:53 +01:00
Anne-Catherine
b67057c863 N°7163 - Avoid having an empty list when "items per page" is set to 0 as it makes no sense (#616) 2024-02-27 17:34:53 +01:00
Anne-Catherine
0546a7b82b N°6808 - Rank management (order) in iTop actions (#558) 2024-02-27 17:06:12 +01:00
vdumas
3d360e99da N°4314 - Fix Uniqueness rules not working with Silo 2024-02-27 14:53:07 +01:00
Molkobain
3cc3f0e4ff N°7288 - Fix page crash due to unescaped characters in relations row actions (#620) 2024-02-27 08:34:34 +01:00
jf-cbd
b6230ed486 🐛 N°7284 - Themehandler enhancement - use of utils::RealPath instead of php's method 2024-02-23 10:46:22 +01:00
Molkobain
123dfd8dd3 N°2039 - Fix broken image in icon attribute when empty 2024-02-22 15:57:48 +01:00
Molkobain
e9bd76f2cd N°2039 - Choose news icon depending on context
Icon from action if defined > Icon from source object class > Icon from branding (compact)
2024-02-22 15:28:16 +01:00
Molkobain
47f7dfeb47 N°2039 - Fix crash when opening all newsroom page due a missing use statement 2024-02-22 15:03:53 +01:00
Molkobain
405919f204 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-21 18:28:47 +01:00
Molkobain
b7f43ba22b Fix test case case when context tag is present more than once 2024-02-21 18:27:21 +01:00
Molkobain
b813a32225 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-21 18:21:18 +01:00
Molkobain
b13e0c92a5 Fix test case dependant to setup option Change Management Simple vs ITIL 2024-02-21 18:13:27 +01:00
jf-cbd
a6e5f95ff4 Add read right to "other" so www-data is able to read the configuration file after the tests 2024-02-21 17:12:43 +01:00
jf-cbd
2e5f0b064c Merge remote-tracking branch 'origin/support/3.2' into support/3.2 2024-02-21 16:38:16 +01:00
jf-cbd
a9f6e86381 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-21 16:37:18 +01:00
Molkobain
c6548ace61 N°2039 - Fix PHPDoc 2024-02-21 16:36:34 +01:00
jf-cbd
aa81c94dad Improved test and test cleanup 2024-02-21 16:30:00 +01:00
Molkobain
478afb88e3 N°7044 - Update installer to move "language" attribute to ActionNotification class (iTop 3.2.0 min) 2024-02-21 15:38:31 +01:00
Molkobain
7c17957ec7 N°7157 - Fix subscription check when no existing lnk yet 2024-02-21 11:09:22 +01:00
Benjamin Dalsass
ba0a585256 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-21 10:48:22 +01:00
Benjamin Dalsass
f41f2a063d N°7279 - AttributeClass defined in XML datamodel compilation issue 2024-02-21 10:41:47 +01:00
Molkobain
d7e9ae1a77 N°6406 - Change internal newsroom to open in current page 2024-02-21 10:21:15 +01:00
Molkobain
dd6a138ea1 N°6406 - Restore news being opened in a new tab by default to compensate iTop Hub lack of configuration 2024-02-21 10:10:16 +01:00
vdumas
b6caa51552 N°7268 - Method SetComputedDate fails on Date only attribute 2024-02-21 08:47:14 +01:00
Pierre Goiffon
8a67ceff57 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-20 12:12:29 +01:00
Pierre Goiffon
095c94a917 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-20 12:11:57 +01:00
Pierre Goiffon
102a4a0c75 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	core/attributedef.class.inc.php
2024-02-20 12:11:02 +01:00
Pierre Goiffon
f6fec506b1 💡 Some PHPDoc hints on value types to pass to DBObject::Set 2024-02-20 12:10:00 +01:00
Stephen Abello
829d82dfe3 N°7243 - Fix toasts CSS using extended compound 2024-02-20 10:20:06 +01:00
Stephen Abello
5fdf8d7687 N°2039 - Use another way to pass down current trigger info in Action in order to avoid bc changes in method profiles 2024-02-20 10:20:06 +01:00
Pierre Goiffon
1ddf8b419a Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-20 09:27:39 +01:00
Pierre Goiffon
7d0801f74f Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-20 09:27:26 +01:00
Pierre Goiffon
3b9f281afd N°7246 DictionariesConsistencyTest : remove combodo-approval-light
We have an invalid CS dict in the 1.2.3 module version
2024-02-20 09:27:15 +01:00
Pierre Goiffon
c718fcf176 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-20 09:12:59 +01:00
Pierre Goiffon
bcba666483 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-20 09:12:47 +01:00
Pierre Goiffon
ec465174f7 N°7246 DictionariesConsistencyTest : remove syntax incompatible with PHP < 7.3 2024-02-20 09:11:47 +01:00
Molkobain
2982911df7 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-19 20:22:44 +01:00
Molkobain
9f675fef02 N°7231 - PHP 8.1: Migrate deprecated usages of rawurlencode() with null value 2024-02-19 20:19:36 +01:00
Stephen Abello
c7cb7c0b68 N°7157 - Add robustness 2024-02-19 10:17:27 +01:00
Molkobain
68f229f91c Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-19 09:56:58 +01:00
Molkobain
1d106eb33a Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-19 09:51:08 +01:00
Molkobain
31bd763b90 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-02-19 09:49:26 +01:00
Molkobain
5c12151c26 📝 Update PR template 2024-02-19 09:46:12 +01:00
Stephen Abello
ceba1ad1e9 N°7157 - Allow users to unsubscribe from notification channels (#611)
* N°7157 - Allow users to unsubscribe from notification channels

* Fix type hinting

* Add missing dict entries

* Allows to subscribe/unsubscribe from notifications individually

* Refactor NotificationsService to singleton pattern

* Refactor NotificationsRepository to singleton pattern and rename methods to a more functional naming

* Add PHPDoc and type hints

* Dump autoloaders

* Replace modals with toasts

* Add dict entry

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-19 09:25:47 +01:00
Molkobain
efe5f004a1 N°2039 - Fix dictionary entry hard-coded on "iTop" app name 2024-02-16 17:27:04 +01:00
Molkobain
b716a3965c N°7008 - Fix missing background tasks in CRON when autoloaded and NOT in "developer_mode" (#578) 2024-02-16 17:14:53 +01:00
vdumas
15fa495458 N°6659 - Fix attribute "team_name" on Ticket class 2024-02-16 15:23:38 +01:00
Stephen Abello
1dfb2e0a1a N°7243 - Add toast notifications to iTop (#614)
* N°7243 - Add toast notifications to iTop

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* Update js/pages/backoffice/toolbox.js

* Update js/utils.js

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

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-16 11:06:09 +01:00
Stephen Abello
d775658980 N°2039 - Prevent Persons with no User linked from being notified 2024-02-16 11:00:05 +01:00
Stephen Abello
2bd40bef47 N°2039 - Fix dictionaries and zlist for ActioniTopNotification 2024-02-16 11:00:04 +01:00
vdumas
961315cf34 N°6826 - Add SQL value for file attribute in DocumentFile 2024-02-16 10:37:44 +01:00
Pierre Goiffon
67d43c19ec N°7251 Deprecate unused files in /js 2024-02-15 17:14:15 +01:00
Pierre Goiffon
2695aeb64b Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-15 14:53:27 +01:00
Pierre Goiffon
95fef002a6 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-15 14:43:19 +01:00
Pierre Goiffon
9777ac1a5c N°7246 DictionariesConsistencyTest : don't test extensions modules in old iTop builds 2024-02-15 14:39:00 +01:00
Pierre Goiffon
9e24447835 N°7246 DictionariesConsistencyTest : add link to file 2024-02-15 11:31:23 +01:00
Pierre Goiffon
296250b20f N°7246 Fix dict files : translated keys with tildes in /dictionaries/** 2024-02-15 11:06:18 +01:00
Pierre Goiffon
38601bf0cf N°7247 Fix IT dict invalid syntax 2024-02-15 11:05:44 +01:00
Pierre Goiffon
9f46aad80a Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	dictionaries/ui/components/datatable/it.dictionary.itop.datatable.php
#	dictionaries/ui/layouts/navigation-menu/it.dictionary.itop.navigation-menu.php
2024-02-15 11:04:35 +01:00
Pierre Goiffon
ba0020fa63 N°7246 Fix dict files : translated keys with tildes in /dictionaries/** 2024-02-15 10:59:10 +01:00
Pierre Goiffon
1e83f2eb60 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	dictionaries/ui/layouts/navigation-menu/pt_br.dictionary.itop.navigation-menu.php
#	dictionaries/ui/layouts/navigation-menu/zh_cn.dictionary.itop.navigation-menu.php
2024-02-15 10:55:54 +01:00
Pierre Goiffon
dd27a3ebb4 N°7246 Fix dict files : translated keys with tildes in /dictionaries/** 2024-02-15 10:50:08 +01:00
Pierre Goiffon
54439ad529 N°7249 DictionariesConsistencyTest : also scan /dictionaries sub-directories
Since 3.0.0 we introduced sub directories
2024-02-15 10:46:42 +01:00
Pierre Goiffon
a492f7a664 N°7247 Fix IT dict inconsistencies 2024-02-15 09:50:54 +01:00
Pierre Goiffon
85a49262e9 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-15 09:49:26 +01:00
Pierre Goiffon
2c61ac4949 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-15 09:47:55 +01:00
Pierre Goiffon
8f7bf00551 N°7246 DictionariesConsistencyTest : add /extensions for local debugging 2024-02-15 09:46:14 +01:00
Molkobain
0483cea226 N°7212 - PHP 8.1: Migrate remaining usages of strlen() with null value (#607) 2024-02-14 19:29:26 +01:00
Molkobain
922a842e96 N°7213 - PHP 8.1: Migrate remaining usages of md5() with null value (#608)
* N°7213 - PHP 8.1: Migrate remaining usages of md5() with null value

* Update core/attributedef.class.inc.php
2024-02-14 19:27:14 +01:00
DarkNight97boss
955d04252e N°7247 - Update italian translations thanks to @DarkNight97boss (#594)
* Improved IT Translation

🌐 
I proceeded to improve the Italian translation of iTop.

Currently some files, despite having the Italian classification, are not Italian.

* Update it.dict.authent-ldap.php

* Update it.dict.itop-config.php

* Update it.dict.itop-tickets.php

* Update it.dict.itop-faq-light.php

* Update it.dict.itop-bridge-cmdb-ticket.php

* Update it.dict.itop-portal-base.php

* Update it.dict.combodo-db-tools.php

* Update it.dict.itop-oauth-client.php

* Update it.dict.itop-files-information.php

* Update it.dict.itop-service-mgmt.php

* Update it.dict.itop-change-mgmt-itil.php

* Update it.dict.itop-backup.php

* Update it.dict.itop-core-update.php

* Update it.dict.authent-local.php

* Update it.dict.itop-request-mgmt-itil.php

* Update it.dict.itop-attachments.php

* Update it.dict.itop-hub-connector.php

* Update it.dict.itop-bridge-cmdb-services.php

* Update it.dict.authent-cas.php

* Update it.dict.itop-change-mgmt.php

* Update it.dict.itop-config-mgmt.php

* Update it.dict.itop-request-mgmt.php

* Update it.dict.itop-service-mgmt-provider.php

* Update it.dict.combodo-backoffice-darkmoon-theme.php

* Update it.dictionary.itop.core.php

* Update it.dictionary.itop.ui.php

* Update it.dictionary.itop.object.php

* Update it.dictionary.itop.bulk.php

* Update it.dictionary.itop.page-content.php

* Update en.dictionary.itop.object.php

* Update it.dictionary.itop.preferences.php

* Update it.dictionary.itop.orm-document.php

* Update it.dictionary.itop.display-block.php

* Update it.dictionary.itop.modal.php

* Update it.dictionary.itop.errorpage.php

* Update it.dictionary.itop.breadcrumbs.php

* Update it.dictionary.itop.tab-container.php

* Update it.dictionary.itop.quick-create.php

* Update it.dictionary.itop.activity-panel.php

* Update it.dictionary.itop.object-details.php

* Update it.dictionary.itop.global-search.php

* Update it.dictionary.itop.navigation-menu.php

* Update it.dictionary.itop.ui-content-block.php

* Update it.dictionary.itop.links.php

* Update it.dictionary.itop.datatable.php

* Update it.dictionary.itop.input.php

* Update it.dictionary.itop.field.php

* Update it.dictionary.itop.uniqueness-rule.php

* Update en.dictionary.itop.object.php - reverting

revert bad changes for mistake

* Apply suggestions from code review

* Remove trailing ~~ from translated entries

* Restore deleted entries

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-14 16:57:43 +01:00
Pierre Goiffon
95c4a93f2e Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-14 15:17:32 +01:00
Pierre Goiffon
e4f068a518 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-14 15:17:14 +01:00
Pierre Goiffon
c020de59a7 📝 tests README : retrofit of the support/3.2 version 2024-02-14 15:16:58 +01:00
Pierre Goiffon
85dac470aa Merge remote-tracking branch 'origin/support/3.1' into support/3.2
# Conflicts:
#	datamodels/2.x/itop-files-information/dictionaries/zh_cn.dict.itop-files-information.php
#	datamodels/2.x/itop-oauth-client/dictionaries/zh_cn.dict.itop-oauth-client.php
#	datamodels/2.x/itop-portal-base/dictionaries/zh_cn.dict.itop-portal-base.php
#	dictionaries/cs.dictionary.itop.core.php
#	dictionaries/cs.dictionary.itop.ui.php
#	dictionaries/zh_cn.dictionary.itop.core.php
#	dictionaries/zh_cn.dictionary.itop.ui.php
#	tests/php-unit-tests/README.md
2024-02-14 15:09:23 +01:00
vdumas
3c2350961d N°7217 - Not able to create a link between "Audit Domain" and "Audit category" with an "Audit Manager" profile 2024-02-14 14:38:21 +01:00
Pierre Goiffon
391c78ae42 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	datamodels/2.x/combodo-db-tools/dictionaries/zh_cn.dict.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/dictionaries/zh_cn.dict.itop-attachments.php
#	datamodels/2.x/itop-backup/dictionaries/da.dict.itop-backup.php
#	datamodels/2.x/itop-backup/dictionaries/it.dict.itop-backup.php
#	datamodels/2.x/itop-backup/dictionaries/ja.dict.itop-backup.php
#	datamodels/2.x/itop-backup/dictionaries/sk.dict.itop-backup.php
#	datamodels/2.x/itop-backup/dictionaries/tr.dict.itop-backup.php
#	datamodels/2.x/itop-config-mgmt/dictionaries/it.dict.itop-config-mgmt.php
#	datamodels/2.x/itop-config/dictionaries/da.dict.itop-config.php
#	datamodels/2.x/itop-config/dictionaries/it.dict.itop-config.php
#	datamodels/2.x/itop-config/dictionaries/ja.dict.itop-config.php
#	datamodels/2.x/itop-config/dictionaries/sk.dict.itop-config.php
#	datamodels/2.x/itop-config/dictionaries/tr.dict.itop-config.php
#	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/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/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-faq-light/dictionaries/zh_cn.dict.itop-faq-light.php
#	datamodels/2.x/itop-files-information/dictionaries/de.dict.itop-files-information.php
#	datamodels/2.x/itop-files-information/dictionaries/pl.dict.itop-files-information.php
#	datamodels/2.x/itop-files-information/dictionaries/zh_cn.dict.itop-files-information.php
#	datamodels/2.x/itop-hub-connector/dictionaries/pt_br.dict.itop-hub-connector.php
#	datamodels/2.x/itop-oauth-client/dictionaries/cs.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/da.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/es_cr.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/it.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/ja.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/nl.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/pt_br.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/ru.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/sk.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/tr.dict.itop-oauth-client.php
#	datamodels/2.x/itop-oauth-client/dictionaries/zh_cn.dict.itop-oauth-client.php
#	datamodels/2.x/itop-service-mgmt-provider/dictionaries/de.dict.itop-service-mgmt-provider.php
#	datamodels/2.x/itop-tickets/dictionaries/da.dict.itop-tickets.php
#	datamodels/2.x/itop-tickets/dictionaries/hu.dict.itop-tickets.php
#	datamodels/2.x/itop-tickets/dictionaries/it.dict.itop-tickets.php
#	datamodels/2.x/itop-tickets/dictionaries/ja.dict.itop-tickets.php
#	dictionaries/cs.dictionary.itop.ui.php
#	dictionaries/da.dictionary.itop.core.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.core.php
#	dictionaries/it.dictionary.itop.ui.php
#	dictionaries/ja.dictionary.itop.core.php
#	dictionaries/ja.dictionary.itop.ui.php
#	dictionaries/nl.dictionary.itop.ui.php
#	dictionaries/pl.dictionary.itop.core.php
#	dictionaries/pl.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
#	tests/php-unit-tests/integration-tests/DictionariesConsistencyTest.php
2024-02-14 14:21:22 +01:00
Pierre Goiffon
aa53de467d Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-02-14 11:39:42 +01:00
Pierre Goiffon
bc6efc99ed N°7246 Fix dict files : remove keys defined multiple times in the same file 2024-02-14 11:20:02 +01:00
Pierre Goiffon
bb3ab76205 N°7246 Fix dict files : missing constants in dict labels 2024-02-14 11:20:02 +01:00
Pierre Goiffon
0b1bdfff55 N°7246 Fix dict files : translated keys with tildes
Note that there were some keys in EN files with tildes at the end
2024-02-14 11:20:02 +01:00
Pierre Goiffon
77c0cdf5aa N°7246 📝 test README : add markTestAsSkipped restrictions 2024-02-14 11:20:02 +01:00
Pierre Goiffon
af9fb74c54 N°7246 Add new tests methods in DictionariesConsistencyTest (#610)
Adding following checks:
* no duplicate key in the same file
* for each value different than its EN counterpart, no tildes at the end
* good use of iTop name constants (ITOP_APPLICATION_SHORT, ITOP_APPLICATION, ITOP_VERSION_NAME), eg `'my value ITOP_APPLICATION'` instead of `'my value '.ITOP_APPLICATION`
2024-02-14 11:20:02 +01:00
Pierre Goiffon
5d6c4939f6 N°7245 Bettor logs on RunTimeEnvironment::CallInstallerHandlers exceptions (#606) 2024-02-14 11:01:12 +01:00
Pierre Goiffon
41eb927480 N°7244 Fix setup ContextTag init (#609) 2024-02-14 10:51:52 +01:00
Pierre Goiffon
5663c61e51 N°7179 Remove unused var in ActionEmail::PrepareMessageContent (#605)
Introduced in fed149d in 3.1.0
2024-02-14 10:32:23 +01:00
Pierre Goiffon
bec5e250a5 N°5472 Notification Action objects : add a last executions tab (#549)
This tab is an ajax tab (deferred on demand loading)
The tab will display the last EventNotification for this action. Number of objects displayed is based on the new `notifications.last_executions_days` config parameter (default to 61 days, can be set to 0 for no limit)
2024-02-14 10:07:24 +01:00
Pierre Goiffon
51d0d16a11 N°7052 synchro_import.php: fix undefined offset notices (#583)
Regression brought by #269
2024-02-14 09:53:31 +01:00
Molkobain
9fe45e9472 N°7068 - Update PHPDoc 2024-02-13 21:20:22 +01:00
Thomas Casteleyn
78133418d7 N°7068 - Add emulation for apc_exists function (#460)
* Emulate missing apc_exists

* Apply suggestions from code review

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

* Update core/apc-emulation.php

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-02-13 21:13:41 +01:00
Pierre Goiffon
8275de8fa7 N°5580 Remove jquery.tabs-ie.css
File was present both in /js and /css, but never called anywhere
And we aren't supporting MSIE anymore...
2024-02-13 15:32:51 +01:00
Anne-Cath
ba7c154e84 Revert "N°7194 - Datamodel - Make classe name clickable on every object."
This reverts commit d2b0140fa4.
2024-02-13 10:31:30 +01:00
Anne-Cath
d2b0140fa4 N°7194 - Datamodel - Make classe name clickable on every object. 2024-02-13 10:27:41 +01:00
Pierre Goiffon
5c4ba74237 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-09 13:41:35 +01:00
Pierre Goiffon
848528567e Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	dictionaries/en.dictionary.itop.ui.php
2024-02-09 13:41:23 +01:00
Pierre Goiffon
b0634c9fbc N°7232 Fix regression on UI:RunQuery:Error
In the UI:RunQuery:Error key, the placeholder was removed when we migrated run_query.php to using UiBlock and Panel.
But it was restored by mistake in f65c6904 (N°5491 in 3.0.4 / 3.1.1)
This was the only key modified for this bug in a EN file.
2024-02-09 13:30:47 +01:00
Pierre Goiffon
7f4b50ca7f Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-09 12:05:11 +01:00
Pierre Goiffon
fabeea8dba Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-09 12:05:00 +01:00
Pierre Goiffon
c951a33646 📝 Update js/README.md file locations 2024-02-09 12:04:21 +01:00
Molkobain
e7687a0fe6 N°6406 - Revert test data 2024-02-09 11:18:23 +01:00
Pierre Goiffon
5dd5986b88 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-02-08 11:34:48 +01:00
Pierre Goiffon
8f250e82f4 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-02-08 11:34:32 +01:00
Pierre Goiffon
ed694b09b0 💡 Update test PHPDoc 2024-02-08 11:34:13 +01:00
Molkobain
3e0ca6a70a N°6406 - Fix news (global) hyperlink not opening since refactoring 2024-02-07 11:05:08 +01:00
Molkobain
3b08ed5f51 N°6406 - Update setup compiled stylesheet 2024-02-07 09:42:10 +01:00
Molkobain
41dcb26283 N°7222 - PHP 8.2: Fix DisplayableNode::$bFiltered dynamic property 2024-02-06 15:43:09 +01:00
Molkobain
d4879b9bd8 N°6406 - Revert test data 2024-02-06 09:56:31 +01:00
Molkobain
87856fe382 N°6406 - Newsroom: Allow news to contain hyperlinks without breaking DOM 2024-02-06 09:43:55 +01:00
Molkobain
205a37a879 N°6406 - Refactor SCSS to add a text helper to force hyperlinks color 2024-02-06 09:43:28 +01:00
Anne-Catherine
e830c90314 N°6619 - Attachment : Make contact_id an AttributeExternalKey instead of AttributeExternalField (#532) 2024-02-05 14:07:51 +01:00
Pierre Goiffon
5308b49cd2 N°7175 TCPDF examples : don't keep this dir in iTop 2024-02-01 16:07:14 +01:00
Pierre Goiffon
216ea34a3c N°7175 TCPDF fonts : keep only the minimum necessary files 2024-02-01 15:34:18 +01:00
Pierre Goiffon
0a9c5250f8 N°7175 Update tecnickcom/tcpdf from 6.4.4 to 6.6.5 2024-02-01 10:25:46 +01:00
Pierre Goiffon
0e91c75dc2 N°7175 Replace combodo/tcpdf 6.4.4 by tecnickcom/tcpdf 6.4.4
The only difference was the presence of the DroidSansFallback font added in #49 / N°1947
We are keeping this font thanks to a custom Composer script to copy the corresponding files in the fonts dir (/lib/tecnickcom/tcpdf/fonts)
2024-02-01 10:25:40 +01:00
Molkobain
cf996dda0b N°4897 - Add method to improve deprecated PHP API logs (eg. for \iPageUIExtension) 2024-02-01 10:10:05 +01:00
Anne-Cath
21638e6a9e Add missing use 2024-01-31 10:34:47 +01:00
Pierre Goiffon
272d6e9b66 N°7178 Update scssphp/scssphp from 1.10.5 to 1.12.1 2024-01-30 11:10:31 +01:00
Molkobain
87b08669d7 N°6037 - PHP 8.2: Migrate usage of strlen() with null value 2024-01-30 10:10:52 +01:00
Molkobain
de86682562 N°6037 - Increase PHP max. non-supported version to 8.4.0 2024-01-30 09:52:52 +01:00
Molkobain
25c2e34eed N°7184 - Fix dict entry with 1 extra placeholder 2024-01-30 08:58:05 +01:00
Pierre Goiffon
e92b006f70 N°7177 Update pelago/emogrifier from 6.0.0 to 7.2.0 2024-01-29 17:18:15 +01:00
Pavel Stetina
962eb08e40 N°7184 - Update czech translations thanks to @tacsaby (#602) 2024-01-29 16:58:01 +01:00
Pierre Goiffon
6342e0065a N°5809 Update psr/log from 2.0.0 to 3.0.0 2024-01-29 16:16:26 +01:00
Pierre Goiffon
ac44ffcdff N°5809 Fix compilation error due to CASLogger VS LoggerInterface in psr/log
"Declaration of Combodo\iTop\Cas\CASLogger::emergency($message, array $context = []) must be compatible with Psr\Log\LoggerInterface::emergency(Stringable|string $message, array $context = [])"

psr/log 3.0.0 brings the BC break
Switching to 2.0.0 is nice as it will bring improvements for PHP 8.0+ !
So adding psr/log ^2.0.0 to composer.json
2024-01-29 16:16:22 +01:00
Pierre Goiffon
dfb5a4875a N°5809 Update Symfony artifacts from 6.4.0 to 6.4.2
symfony/console
symfony/dotenv
symfony/framework-bundle
symfony/http-foundation
symfony/http-kernel
symfony/var-dumper
symfony/web-profiler-bundle
2024-01-29 16:16:17 +01:00
Pierre Goiffon
ddce3058be N°5809 composer.json : reorder Symfony packages declarations 2024-01-29 16:16:12 +01:00
Pierre Goiffon
9235c395b4 N°5809 Update thenetworg/oauth2-azure from 2.1.1 to 2.2.2 2024-01-29 16:16:08 +01:00
Pierre Goiffon
e1296105f9 N°5809 Update nikic/php-parser from 4.14.0 to 4.18.0 2024-01-29 16:16:01 +01:00
Pierre Goiffon
38cdcf4f61 N°5809 Update league/oauth2-google from 3.0.4 to 4.0.1 2024-01-29 16:15:57 +01:00
Pierre Goiffon
5623decdb3 N°5809 Update laminas/laminas-servicemanager from 3.16.0 to 3.22.1 2024-01-29 16:15:48 +01:00
Pierre Goiffon
0f39ea8ac7 N°5809 Update laminas/laminas-mail from 2.16.0 to 2.22.0 2024-01-29 16:15:40 +01:00
Pierre Goiffon
f3d3ec6ef7 N°5809 Update guzzlehttp/guzzle from 7.7.0 to 7.8.1 2024-01-29 16:15:35 +01:00
Pierre Goiffon
fde01d5004 N°5809 Update firebase/php-jwt from 6.4.0 to 6.10.0 2024-01-29 16:15:30 +01:00
Pierre Goiffon
71d9710322 N°5809 Update apereo/phpcas from 1.6.0 to 1.6.1 2024-01-29 16:15:19 +01:00
Timothee
7a5ce8cd6b Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-01-29 15:42:07 +01:00
Timmy38
18deb79068 N°7172 HTML markup for n:n set properties (#604)
* N°7172 HTML markup for n:n set properties
2024-01-29 15:35:17 +01:00
Molkobain
16b3e62587 N°6037 - PHP 8.2: Migrate usage of strlen() with null value 2024-01-29 13:07:48 +01:00
Molkobain
6c1edadc55 N°6037 - PHP 8.2: Migrate usages of strings interpolation 2024-01-26 17:02:16 +01:00
Molkobain
8928a87b14 N°6037 - PHP 8.2: Migrate usages of strtolower() and strtolower() that depends on current locale 2024-01-26 16:36:25 +01:00
Molkobain
8eca200023 N°6037 - PHP 8.3: Fix calling ReflectionProperty::setValue() with a single argument is deprecated 2024-01-24 20:35:40 +01:00
Molkobain
865b6d14f0 N°6037 - PHP 8.3: Update parameters and return type hints to match parent's 2024-01-24 20:35:40 +01:00
Molkobain
b63af9b919 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-01-24 15:21:05 +01:00
Molkobain
4d4cdf9e60 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-01-24 15:18:37 +01:00
Molkobain
3868d57d28 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-01-24 15:11:29 +01:00
Molkobain
1b3a2c8470 N°5775 - Show error message to user in case of issue during token generation 2024-01-24 14:49:51 +01:00
Dennis Lassiter
618d8e6468 N°5775 - Allow configuration of OAuth client on MS Azure with single tenant (#553)
* Add Tenant-Support for Azure OAuthClient

* Improvement: Make tenant required

* Improvment: Removed check for null-value

Since last commit, the "tenant"-field either set to a custom value or "common" by default. It is not allowed to be null

* Add field description

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2024-01-24 14:38:54 +01:00
odain
53a2a7a8e2 N°7147 - cleanup 2024-01-23 20:45:35 +01:00
odain
9a26c37ffd N°7147 - Error HTTP 500 due to access_token not URL decoded 2024-01-23 16:50:21 +01:00
Pierre Goiffon
1e3ef6846d N°3677 - Fix AttributeImage.default_image URLs not up to date after app_root_url change (#526)
Many thanks to @sg-gcouronne for this contribution !
2024-01-22 16:02:41 +01:00
Molkobain
31225b9e23 Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-01-17 23:03:02 +01:00
jf-cbd
436b6808b5 N°7134 - Can't retrieve the list of changes when editing URP_UserProfile 2024-01-17 15:12:55 +01:00
Eric Espie
cc5e105d7f N°7070 - remove _delta attribute from datamodel and avoid _delta attributes under a node having _delta in [define, define_if_not_exist, redefine, force] in deltas 2024-01-17 15:12:08 +01:00
jf-cbd
7f62bd61e3 N°7134 - Can't retrieve the list of changes when editing URP_UserProfile 2024-01-17 15:05:30 +01:00
Molkobain
aecc34a78b Merge remote-tracking branch 'origin/support/3.1' into support/3.2 2024-01-16 19:53:42 +01:00
Molkobain
72bbc31cd9 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-01-16 19:48:33 +01:00
Molkobain
f54d1273c9 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2024-01-16 19:46:55 +01:00
Molkobain
01a955a16f 📝 Add PR template 2024-01-16 19:42:39 +01:00
Pierre Goiffon
ed99433448 Merge remote-tracking branch 'origin/support/3.1' into develop 2024-01-16 11:22:04 +01:00
Pierre Goiffon
669e6f93fa Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2024-01-16 11:00:52 +01:00
Pierre Goiffon
a5aac0caad N°7143 Woops removed forgotten echo 2024-01-16 10:25:28 +01:00
Pierre Goiffon
31e29506fa N°7143 DictionariesConsistencyTest::testNoDictFileInDatamodelsModuleRootDirectory Add exclusion list to remove modules that must be compatible with iTop 2.7 2024-01-16 10:18:50 +01:00
4919 changed files with 327877 additions and 262632 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

83
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,83 @@
<!--
IMPORTANT: Please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
Any PRs not following the guidelines or with missing information will not be considered.
-->
## Base information
| Question | Answer
|---------------------------------------------------------------|--------
| Related to a SourceForge thead / Another PR / Combodo ticket? | <!-- Put the URL -->
| Type of change? | Bug fix / Enhancement / Translations
## Symptom (bug) / Objective (enhancement)
<!--
If it's a bug
- Explain the symptom in details
- If possible put error messages, logs or screenshots (you can paste image directly in this editor).
If it's an enhancement
- Describe what is blocking you, what is the objective with as much details as possible.
- Add screenshots if it's related to UI.
-->
## Reproduction procedure (bug)
<!--
Remove this section only if it's NOT a bug.
Otherwise, explain step by step how to reproduce the issue on a standard iTop Community.
If it requires a custom datamodel, provide the minimal XML delta to reproduce it on a standard iTop Community.
-->
1. On iTop x.y.z <!-- Put complete iTop version (eg. 3.1.0-2) -->
2. With PHP x.y.z <!-- Put complete PHP version (eg. 8.1.24) -->
2. First go there
2. Then do that
3. ...
4. Finally, see that...
## Cause (bug)
<!--
Remove this section only if it's NOT a bug.
Otherwise, explain what is the cause of the issue (where in the code and why)
-->
## Proposed solution (bug and enhancement)
<!--
Explain in details how you are proposing to solve this:
- What did you do in the code and why
- If you changed something in the UI, put before / after screenshots (you can paste image directly in this editor)
-->
## Checklist before requesting a review
<!--
Don't remove these lines, check them once done.
-->
- [ ] I have performed a self-review of my code
- [ ] I have tested all changes I made on an iTop instance
- [ ] I have added a unit test, otherwise I have explained why I couldn't
- [ ] Is the PR clear and detailed enough so anyone can understand digging in the code?
## Checklist of things to do before PR is ready to merge
<!--
Things that needs to be done in the PR before it can be considered as ready to be merged
Examples:
- Changes requested in the review
- Unit test to add
- Dictionary entries to translate
- ...
-->
- [ ] ...
- [ ] ...
- [ ] ...

3
.gitignore vendored
View File

@@ -47,6 +47,9 @@ tests/*/vendor/*
!/log/index.php
!/log/web.config
# NPM: `jquery-ui` package is just there for vulnerability scans, so we don't want to version its files (only `jquery-ui-dist` is used within the code base)
/node_modules/jquery-ui/**
# PHPUnit: Cache file, local XML working copies
/tests/php-unit-tests/.phpunit.result.cache
/tests/php-unit-tests/phpunit.xml

View File

@@ -4,7 +4,7 @@ $iBeginTime = time();
chdir(__DIR__);
$aCommands = [
'php composer/rmDeniedTestDir.php',
'php composer/rmUnnecessaryFolders.php',
'php build/commands/setupCssCompiler.php',
// 'bash /tmp/gabuzomeu.sh',
];
@@ -22,13 +22,13 @@ $iElapsed = time() - $iBeginTime;
if (count($aFailedCommands))
{
fwrite(STDERR, "\nafterBuild execution failed! (in ${iElapsed}s)\n");
fwrite(STDERR, "\nafterBuild execution failed! (in {$iElapsed}s)\n");
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
exit(1);
}
echo "\nDone (${iElapsed}s)\n";
echo "\nDone ({$iElapsed}s)\n";
exit(0);
/**
@@ -74,7 +74,7 @@ function ExecCommand($cmd) {
}
else
{
echo "| elapsed:${iElapsed}s \n";
echo "| elapsed:{$iElapsed}s \n";
}
if (!empty($stderr))

View File

@@ -1,73 +0,0 @@
<?php
/**
* Copyright (C) 2010-2023 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/>
*
*/
use Combodo\iTop\Composer\iTopComposer;
$iTopFolder = __DIR__ . "/../../" ;
require_once ("$iTopFolder/approot.inc.php");
require_once (APPROOT."/setup/setuputils.class.inc.php");
if (php_sapi_name() !== 'cli')
{
throw new \Exception('This script can only run from CLI');
}
clearstatcache();
$oiTopComposer = new iTopComposer();
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
echo "\n";
foreach ($aDeniedButStillPresent as $sDir)
{
if (false === iTopComposer::IsTestDir($sDir))
{
echo "ERROR found INVALID denied test dir: '$sDir'\n";
throw new \Exception("$sDir must end with /Test/ or /test/");
}
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,7 +26,7 @@
* @link https://getcomposer.org/doc/03-cli.md#show
*/
$iTopFolder = __DIR__."/../../";
$iTopFolder = __DIR__."/../../../";
require_once("$iTopFolder/approot.inc.php");
$sApproot = APPROOT;

View File

@@ -0,0 +1,56 @@
courier.php
courierb.php
courierbi.php
courieri.php
dejavusans.ctg.z
dejavusans.php
dejavusans.z
dejavusansb.ctg.z
dejavusansb.php
dejavusansb.z
dejavusansbi.ctg.z
dejavusansbi.php
dejavusansbi.z
dejavusanscondensed.ctg.z
dejavusanscondensed.php
dejavusanscondensed.z
dejavusanscondensedb.ctg.z
dejavusanscondensedb.php
dejavusanscondensedb.z
dejavusanscondensedbi.ctg.z
dejavusanscondensedbi.php
dejavusanscondensedbi.z
dejavusanscondensedi.ctg.z
dejavusanscondensedi.php
dejavusanscondensedi.z
dejavusansextralight.ctg.z
dejavusansextralight.php
dejavusansextralight.z
dejavusansi.ctg.z
dejavusansi.php
dejavusansi.z
dejavusansmono.ctg.z
dejavusansmono.php
dejavusansmono.z
dejavusansmonob.ctg.z
dejavusansmonob.php
dejavusansmonob.z
dejavusansmonobi.ctg.z
dejavusansmonobi.php
dejavusansmonobi.z
dejavusansmonoi.ctg.z
dejavusansmonoi.php
dejavusansmonoi.z
droidsansfallback.ctg.z
droidsansfallback.php
droidsansfallback.z
helvetica.php
helveticab.php
helveticabi.php
helveticai.php
symbol.php
times.php
timesb.php
timesbi.php
timesi.php
zapfdingbats.php

View File

@@ -0,0 +1,101 @@
<?php
/**
* This script will copy custom fonts in the TCPDF lib fonts directory.
* If you need to add other files :
* - add the corresponding files in this script directory
* - modify this script to copy also your files
*
* @since 2.7.0 N°1947 add DroidSansFallback font (see also PR #49 in the links below)
* @since 2.7.0 N°2435 TCPPDF lib forked and added in composer.json (at that time the lib was announced as deprecated and rewritten in tecnickcom/tc-lib-pdf)
* @since 3.2.0 N°7175 switch back to TCPDF original lib (which is finally still maintained, tecnickcom/tc-lib-pdf us still under dev), script creation to keep custom DroidSansFallback font
*
* @link https://github.com/Combodo/iTop/pull/49 add DroidSansFallback font
* @link https://github.com/tecnickcom/TCPDF?tab=readme-ov-file#note TCPDF is in support only mode
*/
$sItopRootFolder = realpath(__DIR__ . "/../../../../");
$sCurrentScriptFileName = basename(__FILE__);
require_once ("$sItopRootFolder/lib/autoload.php");
$sTcPdfRootFolder = $sItopRootFolder.'/lib/tecnickcom/tcpdf';
if (false === file_exists($sTcPdfRootFolder)) {
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
return;
}
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/Fonts/';
/**
* 1) Cleaning up the fonts directory to keep only the ones we want in iTop
*/
echo $sCurrentScriptFileName.": ---1) Cleaning up the fonts files\n";
$aTcpdfDefaultFontsToKeepInItop = file(__DIR__.'/tcpdfDefaultFontsToKeepInItop.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$aTcpdfFontsDirContent = scandir($sTcPdfFontsFolder);
foreach ($aTcpdfFontsDirContent as $sTcpdfFontResourceName) {
if ($sTcpdfFontResourceName === '.') {
continue;
}
if ($sTcpdfFontResourceName === '..') {
continue;
}
if (!in_array($sTcpdfFontResourceName, $aTcpdfDefaultFontsToKeepInItop, true)) {
echo $sCurrentScriptFileName.": Removing $sTcpdfFontResourceName !\n";
$sTcpdfFontResourceFullPath = $sTcPdfFontsFolder.$sTcpdfFontResourceName;
if (is_file($sTcpdfFontResourceFullPath)) {
unlink($sTcpdfFontResourceFullPath);
} elseif (is_dir($sTcpdfFontResourceFullPath)) {
rrmdir($sTcpdfFontResourceFullPath);
}
}
}
/**
* 2) Then adding the DroidSansFallback font (useful for CJK data for example)
*/
echo $sCurrentScriptFileName.": ---2) Copying font files to TCPDF ($sTcPdfFontsFolder)...\n";
$aFontFilesToCopy = glob(__DIR__.'\droidsansfallback.*');
foreach ($aFontFilesToCopy as $sFontFileToCopy) {
$sFontFileName = basename($sFontFileToCopy);
echo $sCurrentScriptFileName.': copying '.$sFontFileName."\n";
copy($sFontFileToCopy, $sTcPdfFontsFolder.$sFontFileName);
}
echo $sCurrentScriptFileName.": Done !\n";
/*-----------------------------------------------------------------------------------------------*/
/**
* Recursively delete a directory and its content
*
* @param $sDirToRemovePath
*
* @return void
*/
function rrmdir($sDirToRemovePath):void
{
if (is_dir($sDirToRemovePath)) {
$objects = scandir($sDirToRemovePath);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($sDirToRemovePath."/".$object) == "dir") {
rrmdir($sDirToRemovePath."/".$object);
} else {
unlink($sDirToRemovePath."/".$object);
}
}
}
reset($objects);
rmdir($sDirToRemovePath);
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Copyright (C) 2010-2023 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/>
*
*/
/**
* Ensure that the files for folder browsing protection (.htaccess, web.config) are kept after an "npm install/update" command
*/
$iTopFolder = __DIR__."/../../../";
require_once("$iTopFolder/approot.inc.php");
$sDependenciesRootFolderAbsPath = APPROOT . "node_modules/";
$aFilesToCheck = [
".htaccess",
"web.config",
];
echo "This command aims at ensuring that folder browsing protection files (.htaccess, web.config) are present in the dependencies folder even after an install/upgrade command\n";
echo "Checking files:\n";
foreach($aFilesToCheck as $sFileToCheck) {
if (file_exists($sDependenciesRootFolderAbsPath . $sFileToCheck)) {
echo "✔️ $sFileToCheck is present\n";
continue;
}
// If missing, copy the one from /lib as it contains the necessary allow/deny directives for third-parties
copy(APPROOT . "lib/$sFileToCheck", $sDependenciesRootFolderAbsPath . $sFileToCheck);
echo "✔️ $sFileToCheck was missing and has been re-created\n";
}
// Ensure separation with following scripts
echo "\n";

View File

@@ -0,0 +1,95 @@
<?php
/**
* Copyright (C) 2010-2023 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/>
*
*/
$iTopFolder = __DIR__ . "/../../" ;
require_once ("$iTopFolder/approot.inc.php");
require_once (APPROOT."/setup/setuputils.class.inc.php");
if (php_sapi_name() !== 'cli')
{
throw new \Exception('This script can only run from CLI');
}
clearstatcache();
// Read params
$key = array_search("--manager", $argv);
if (false === $key || false === isset($argv[$key + 1]) ) {
throw new \InvalidArgumentException("Usage: " . __FILE__ . " --manager composer|npm");
}
$sDependenciesHandlerCode = $argv[$key + 1];
switch ($sDependenciesHandlerCode) {
case "composer":
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\Composer\iTopComposer::class;
break;
case "npm":
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\NPM\iTopNPM::class;
break;
default:
throw new \Exception("Invalid dependencies handler code, $sDependenciesHandlerCode given, expected composer|npm");
}
// Start handler
$oDependenciesHandler = new $sDependenciesHandlerFQCN();
$aDeniedButStillPresent = $oDependenciesHandler->ListDeniedButStillPresentFoldersAbsPaths();
echo "\n";
foreach ($aDeniedButStillPresent as $sDir)
{
if (false === $oDependenciesHandler::IsQuestionnableFolder($sDir))
{
echo "ERROR found INVALID denied test dir: '$sDir'\n";
throw new \RuntimeException("$sDir is in the denied list but doesn't comply with the rule (see IsQuestionnableFolder method)");
}
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 "✔️ Remove denied test dir: '$sDir'\n";
}
catch (\Exception $e) {
echo "\n❌ FAILED to remove denied test dir: '$sDir'\n";
}
}
$aAllowedAndDeniedDirs = array_merge(
$oDependenciesHandler->ListAllowedFoldersAbsPaths(),
$oDependenciesHandler->ListDeniedFoldersAbsPaths()
);
$aExistingDirs = $oDependenciesHandler->ListAllFoldersAbsPaths();
$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 {$sDependenciesHandlerFQCN}\n"
.' List of dirs:'."\n".var_export($aMissing, true)."\n";
}
// Ensure separation with following scripts
echo "\n";

View File

@@ -159,6 +159,6 @@ We have one sticker per contribution type. You might get multiple stickers with
* Beta tester: Test and give feedback on beta releases
* Extension developer: Develop and publish an extension
Here is the design of each stickers for year 2022:
Here is the design of each stickers for year 2024:
![iTop stickers 2023](.doc/contributing-guide/2023.contributing-stickers-side-by-side.png)
![iTop stickers 2024](.doc/contributing-guide/2024.contributing-stickers-side-by-side.png)

View File

@@ -1274,8 +1274,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
*/
public function GetNorthPaneHtml(iTopWebPage $oPage)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
return '';
}
@@ -1284,8 +1282,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
*/
public function GetSouthPaneHtml(iTopWebPage $oPage)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
return '';
}
@@ -1294,8 +1290,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
*/
public function GetBannerHtml(iTopWebPage $oPage)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
return '';
}
@@ -2105,8 +2099,16 @@ class RestUtils
elseif (is_string($key))
{
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
}
try {
$oSearch = DBObjectSearch::FromOQL($key);
} catch (Exception $e) {
throw new CoreOqlException('Query failed to execute', [
'query' => $key,
'exception_class' => get_class($e),
'exception_message' => $e->getMessage(),
]);
}
}
else
{
throw new Exception("Wrong format for key");
@@ -2279,4 +2281,19 @@ interface iKPILoggerExtension
* @return mixed
*/
public function LogOperation($oKpiLogData);
}
}
/**
* Implement this interface to add files to the backup
*
* @api
* @since 3.2.0
*/
interface iBackupExtraFilesExtension
{
/**
* @api
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
*/
public function GetExtraFilesRelPaths(): array;
}

View File

@@ -86,7 +86,7 @@ class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
{
$aParams = array
(
"category" => "application, grant_by_profile",
"category" => "application,grant_by_profile",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",

View File

@@ -4,6 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Combodo\iTop\Application\Helper\CKEditorHelper;
use Combodo\iTop\Application\Helper\FormHelper;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\Helper\WebResourcesHelper;
@@ -137,6 +138,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
/** @var string */
public const ENUM_INPUT_TYPE_TAGSET = 'tagset';
/** @var string */
public const ENUM_INPUT_TYPE_TAGSET_LINKEDSET = 'tagset_linkedset';
/** @var string */
public const ENUM_INPUT_TYPE_RADIO = 'radio';
/** @var string */
public const ENUM_INPUT_TYPE_CHECKBOX = 'checkbox';
@@ -2321,14 +2324,14 @@ JS
// To change the default settings of the editor,
// a) edit the file /js/ckeditor/config.js
// b) or override some of the configuration settings, using the second parameter of ckeditor()
$aConfig = utils::GetCkeditorPref();
$aConfig = CKEditorHelper::GetCkeditorPref();
$aConfig['placeholder'] = Dict::S('UI:CaseLogTypeYourTextHere');
// - Final config
$sConfigJS = json_encode($aConfig);
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
$oPage->add_ready_script("CombodoCKEditorHandler.CreateInstance('#$iId')");
$oPage->add_ready_script(
<<<EOF
@@ -2362,6 +2365,7 @@ EOF
case 'LinkedSet':
if ($oAttDef->GetDisplayStyle() === LINKSET_DISPLAY_STYLE_PROPERTY) {
$sInputType = self::ENUM_INPUT_TYPE_TAGSET_LINKEDSET;
if (array_key_exists('bulk_context', $aArgs)) {
$oTagSetBlock = LinkSetUIBlockFactory::MakeForBulkLinkSet($iId, $oAttDef, $value, $sWizardHelperJsVarName, $aArgs['bulk_context']);
} else {
@@ -2426,7 +2430,7 @@ HTML;
$sInputType = self::ENUM_INPUT_TYPE_IMAGE;
$aEventsList[] = 'validate';
$aEventsList[] = 'change';
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/edit_image.js');
$oPage->LinkScriptFromAppRoot('js/edit_image.js');
$oDocument = $value; // Value is an ormDocument objectm
$sDefaultUrl = $oAttDef->Get('default_image');
if (is_object($oDocument) && !$oDocument->IsEmpty()) {
@@ -2542,11 +2546,11 @@ HTML;
$sHTMLValue .= '</div></div>';
$sHTMLValue .= '<div>'.$sReloadSpan.'</div>'; // No validation span for this one: it does handle its own validation!
$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" type=\"hidden\" id=\"$iId\" value=\"\"/>\n";
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/console_form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_set.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_field.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/subform_field.js');
$oPage->LinkScriptFromAppRoot('js/form_handler.js');
$oPage->LinkScriptFromAppRoot('js/console_form_handler.js');
$oPage->LinkScriptFromAppRoot('js/field_set.js');
$oPage->LinkScriptFromAppRoot('js/form_field.js');
$oPage->LinkScriptFromAppRoot('js/subform_field.js');
$oPage->add_ready_script(
<<<JS
$('#{$iId}_field_set').field_set($sFieldSetOptions);
@@ -2572,9 +2576,9 @@ JS
case 'Set':
case 'TagSet':
$sInputType = self::ENUM_INPUT_TYPE_TAGSET;
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js');
$oPage->LinkScriptFromAppRoot('js/selectize.min.js');
$oPage->LinkStylesheetFromAppRoot('css/selectize.default.css');
$oPage->LinkScriptFromAppRoot('js/jquery.itop-set-widget.js');
$oPage->add_dict_entry('Core:AttributeSet:placeholder');
@@ -3449,7 +3453,7 @@ EOF
// Dummy collapsible section created in order to get JS files
$oCollapsibleSection = new CollapsibleSection('');
foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) {
$oPage->add_linked_script($sJSFile);
$oPage->LinkScriptFromURI($sJSFile);
}
}
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
@@ -3589,16 +3593,26 @@ EOF
$oPage->add_ready_script(InlineImage::EnableCKEditorImageUpload($this, $sTempId));
} else {
//we can directly apply the stimuli
$sExceptionMessage = null;
try {
$bApplyStimulus = $this->ApplyStimulus($sStimulus); // will write the object in the DB
if (!$bApplyStimulus) {
throw new ApplicationException(Dict::S('UI:FailedToApplyStimuli'));
} else {
}
catch (Exception $oException) {
// Catch any exception happening during the stimulus
$bApplyStimulus = false;
$sExceptionMessage = ($oException instanceof CoreCannotSaveObjectException) ? $oException->getHtmlMessage() : $oException->getMessage();
}
finally {
if ($sOwnershipToken !== null) {
// Release the concurrent lock, if any
iTopOwnershipLock::ReleaseLock($sClass, $iKey, $sOwnershipToken);
}
return true;
if (!$bApplyStimulus) {
// Throw an application oriented exception if necessary
throw new ApplicationException($sExceptionMessage ?? Dict::S('UI:FailedToApplyStimuli'));
} else {
return true;
}
}
}

View File

@@ -480,7 +480,7 @@ abstract class Dashboard
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
$('#attr_auto_reload').change( function(ev) {
$('#attr_auto_reload').on('change', function(ev) {
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
} );
@@ -563,8 +563,8 @@ JS
}
if (!$bEditMode) {
$oPage->add_linked_script('../js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js');
$oPage->LinkScriptFromAppRoot('js/dashlet.js');
$oPage->LinkScriptFromAppRoot('js/dashboard.js');
}
return $oDashboard;
@@ -1118,8 +1118,8 @@ JS
*/
protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aExtraParams)
{
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
$oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
$oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
@@ -1272,6 +1272,7 @@ EOF
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sTitle = utils::HtmlEntities($this->sTitle);
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
$sFileForJS = json_encode($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sReloadURL = $this->GetReloadURL();
@@ -1333,9 +1334,9 @@ $('#dashboard_editor .ui-layout-center').runtimedashboard({
auto_reload: $sAutoReload,
auto_reload_sec: $sAutoReloadSec,
submit_to: '$sUrl',
submit_parameters: {operation: 'save_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
submit_parameters: {operation: 'save_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl',
render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_parameters: {operation: 'render_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
new_dashlet_parameters: {operation: 'new_dashlet'}
});

View File

@@ -187,7 +187,9 @@
</menus>
<events>
<event id="EVENT_DB_BEFORE_WRITE" _delta="define">
<description>An object is about to be written into the database. The object can be modified.</description>
<name>Before create or update</name>
<description><![CDATA[An object is about to be written into the database.
The object can be modified.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -208,7 +210,9 @@
</event_data>
</event>
<event id="EVENT_DB_CHECK_TO_WRITE" _delta="define">
<description>Check an object before it is written into the database (no change possible). Call DBObject::AddCheckIssue() to signal an issue</description>
<name>Check to write</name>
<description><![CDATA[Check an object before it is written into the database (no change possible).
Call $this->AddCheckIssue() to signal an issue.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -229,7 +233,9 @@
</event_data>
</event>
<event id="EVENT_DB_AFTER_WRITE" _delta="define">
<description>An object has been written into the database. The modifications can be propagated to other objects.</description>
<name>After create or update</name>
<description><![CDATA[An object has been written into the database.
The modifications can be propagated to other objects.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -244,7 +250,7 @@
<type>boolean</type>
</event_datum>
<event_datum id="changes">
<description>For updates, the list of changes done during this operation</description>
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
<type>array</type>
</event_datum>
<event_datum id="debug_info">
@@ -254,7 +260,9 @@
</event_data>
</event>
<event id="EVENT_DB_CHECK_TO_DELETE" _delta="define">
<description>Check an object before it is deleted from the database. Call DBObject::AddDeleteIssue() to signal an issue</description>
<name>Check to delete</name>
<description><![CDATA[Check an object before it is deleted from the database.
Call $this->AddDeleteIssue() to signal an issue.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -271,7 +279,8 @@
</event_data>
</event>
<event id="EVENT_DB_ABOUT_TO_DELETE" _delta="define">
<description>An object is about to be deleted from the database</description>
<name>Before delete</name>
<description><![CDATA[An object is about to be deleted from the database]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -288,7 +297,8 @@
</event_data>
</event>
<event id="EVENT_DB_AFTER_DELETE" _delta="define">
<description>An object has been deleted into the database</description>
<name>After delete</name>
<description><![CDATA[An object has been deleted into the database]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -304,8 +314,10 @@
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_BEFORE_APPLY_STIMULUS" _delta="define">
<description>A stimulus is about to be applied to an object</description>
<event id="EVENT_ENUM_TRANSITIONS" _delta="define">
<name>Enum transitions</name>
<description><![CDATA[Manage the allowed transitions in current object state.
The only action allowed is to deny transitions with $this->DenyTransition()]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -314,89 +326,9 @@
<description>The object where the stimulus is targeted</description>
<type>DBObject</type>
</event_datum>
<event_datum id="stimulus">
<description>Current stimulus applied</description>
<type>string</type>
</event_datum>
<event_datum id="previous_state">
<description>Object previous state</description>
<type>string</type>
</event_datum>
<event_datum id="new_state">
<description>Object new state</description>
<type>string</type>
</event_datum>
<event_datum id="save_object">
<description>The object must be saved in the database</description>
<type>boolean</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_AFTER_APPLY_STIMULUS" _delta="define">
<description>A stimulus has been applied to an object</description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
<event_data>
<event_datum id="object">
<description>The object where the stimulus is targeted</description>
<type>DBObject</type>
</event_datum>
<event_datum id="stimulus">
<description>Current stimulus applied</description>
<type>string</type>
</event_datum>
<event_datum id="previous_state">
<description>Object previous state</description>
<type>string</type>
</event_datum>
<event_datum id="new_state">
<description>Object new state</description>
<type>string</type>
</event_datum>
<event_datum id="save_object">
<description>The object is asked to be saved in the database</description>
<type>boolean</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>
</event_datum>
</event_data>
</event>
<event id="EVENT_DB_APPLY_STIMULUS_FAILED" _delta="define">
<description>A stimulus has failed</description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
<event_data>
<event_datum id="action">
<description>The action that failed to apply the stimulus</description>
<type>string</type>
</event_datum>
<event_datum id="object">
<description>The object where the stimulus is targeted</description>
<type>DBObject</type>
</event_datum>
<event_datum id="stimulus">
<description>Current stimulus applied</description>
<type>string</type>
</event_datum>
<event_datum id="previous_state">
<description>Object previous state</description>
<type>string</type>
</event_datum>
<event_datum id="new_state">
<description>Object new state</description>
<type>string</type>
</event_datum>
<event_datum id="save_object">
<description>The object must be saved in the database</description>
<type>boolean</type>
<event_datum id="allowed_stimuli">
<description>The list of available stimuli in the current state</description>
<type>array</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
@@ -405,7 +337,8 @@
</event_data>
</event>
<event id="EVENT_DB_LINKS_CHANGED" _delta="define">
<description>At least one link class was changed</description>
<name>Links on object have changed</name>
<description><![CDATA[At least one link class was changed]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -421,7 +354,9 @@
</event_data>
</event>
<event id="EVENT_DB_OBJECT_RELOAD" _delta="define">
<description>An object has been re-loaded from the database</description>
<name>Object reload</name>
<internal>true</internal>
<description><![CDATA[An object has been re-loaded from the database]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -437,7 +372,8 @@
</event_data>
</event>
<event id="EVENT_DB_COMPUTE_VALUES" _delta="define">
<description>An object needs to be recomputed after changes</description>
<name>Recompute object values</name>
<description><![CDATA[An object needs to be recomputed after changes]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -454,7 +390,8 @@
</event_data>
</event>
<event id="EVENT_DB_ARCHIVE" _delta="define">
<description>An object has been archived</description>
<name>Object archived</name>
<description><![CDATA[An object has been archived]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -470,7 +407,8 @@
</event_data>
</event>
<event id="EVENT_DB_UNARCHIVE" _delta="define">
<description>An object has been unarchived</description>
<name>Object unarchived</name>
<description><![CDATA[An object has been unarchived]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -486,7 +424,9 @@
</event_data>
</event>
<event id="EVENT_DB_SET_ATTRIBUTES_FLAGS" _delta="define">
<description>Set object attributes flags. Call cmdbAbstractObject::AddAttributeFlags() for all the attributes to be set for this target state.</description>
<name>Set attributes flags</name>
<description><![CDATA[Set object attributes flags.
Call $this->AddAttributeFlags() for all the attributes to be set for this target state.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -497,7 +437,7 @@
</event_datum>
<event_datum id="target_state">
<description>The target state in which to evaluate the flags</description>
<type>array</type>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
@@ -506,7 +446,9 @@
</event_data>
</event>
<event id="EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS" _delta="define">
<description>Set object initial attributes flags. Call cmdbAbstractObject::AddInitialAttributeFlags() for all the initial attributes to be set initially.</description>
<name>Set initial attributes flags</name>
<description><![CDATA[Set object initial attributes flags.
Call $this->AddInitialAttributeFlags() for all the initial attributes to be set initially.]]></description>
<sources>
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
</sources>
@@ -522,7 +464,8 @@
</event_data>
</event>
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
<description>A document has been downloaded from the GUI</description>
<name>Document downloaded</name>
<description><![CDATA[A document has been downloaded from the GUI]]></description>
<sources>
<source id="Document">Document</source>
</sources>
@@ -550,7 +493,9 @@
</event_data>
</event>
<event id="EVENT_LOGIN" _delta="define">
<description>Inform the listeners about the connection states</description>
<name>Login</name>
<internal>true</internal>
<description><![CDATA[Inform the listeners about the connection states]]></description>
<event_data>
<event_datum id="code">
<description>The login step result code (LoginWebPage::EXIT_CODE_...) </description>

View File

@@ -326,6 +326,7 @@ class DataTable
$sPagesLinks = implode('', $aPagesToDisplay);
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
$sHtml =
<<<EOF
@@ -333,11 +334,11 @@ class DataTable
<div $sPagerStyle>
<table id="pager{$this->iListId}" class="pager"><tr>
<td>$sPages</td>
<td><img src="../images/first.png" class="first"/></td>
<td><img src="../images/prev.png" class="prev"/></td>
<td><img src="{$sAppRootUrl}images/first.png" class="first"/>AAAA</td>
<td><img src="{$sAppRootUrl}images/prev.png" class="prev"/></td>
<td><span id="index">$sPagesLinks</span></td>
<td><img src="../images/next.png" class="next"/></td>
<td><img src="../images/last.png" class="last"/></td>
<td><img src="{$sAppRootUrl}images/next.png" class="next"/></td>
<td><img src="{$sAppRootUrl}images/last.png" class="last"/></td>
<td>$sPageSizeCombo</td>
<td><span id="loading">&nbsp;</span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
</td>

View File

@@ -570,7 +570,7 @@ class DisplayBlock
} else {
// render it as an Ajax (asynchronous) call
$oHtml->AddCSSClass("loading");
$oHtml->AddHtml("<p><img src=\"../images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>');
$oHtml->AddHtml("<p><img src=\"".utils::GetAbsoluteUrlAppRoot()."images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>');
$oPage->add_script('
$.post("ajax.render.php?style='.$this->m_sStyle.'",
{ operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },

View File

@@ -82,7 +82,7 @@ class LoginWebPage extends NiceWebPage
}
protected static $m_sLoginFailedMessage = '';
public function __construct($sTitle = null)
{
if ($sTitle === null) {
@@ -97,8 +97,17 @@ class LoginWebPage extends NiceWebPage
public function SetStyleSheet()
{
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
$this->LinkStylesheetFromAppRoot('css/login.css');
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
}
/**
* @inheritDoc
* @since 3.2.0
*/
protected function GetFaviconAbsoluteUrl()
{
return Branding::GetLoginFavIconAbsoluteUrl();
}
public static function SetLoginFailedMessage($sMessage)
@@ -910,13 +919,13 @@ class LoginWebPage extends NiceWebPage
$aAllProfiles = array();
while ($oProfile = $oProfilesSet->Fetch())
{
$aAllProfiles[strtolower($oProfile->GetName())] = $oProfile->GetKey();
$aAllProfiles[mb_strtolower($oProfile->GetName())] = $oProfile->GetKey();
}
$aProfiles = array();
foreach ($aRequestedProfiles as $sRequestedProfile)
{
$sRequestedProfile = strtolower($sRequestedProfile);
$sRequestedProfile = mb_strtolower($sRequestedProfile);
if (isset($aAllProfiles[$sRequestedProfile]))
{
$aProfiles[] = $aAllProfiles[$sRequestedProfile];

View File

@@ -125,9 +125,7 @@ class ApplicationMenu
*/
public static function CheckMenuIdEnabled($sMenuId)
{
self::LoadAdditionalMenus();
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
if (is_null($oMenuNode) || !$oMenuNode->IsEnabled())
if (self::IsMenuIdEnabled($sMenuId) === false)
{
require_once(APPROOT.'/setup/setuppage.class.inc.php');
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
@@ -138,6 +136,19 @@ class ApplicationMenu
}
}
/**
* @param $sMenuId
*
* @return bool true if the menu exists and current user is allowed to see the menu
* @since 3.2.0
*/
public static function IsMenuIdEnabled($sMenuId):bool
{
self::LoadAdditionalMenus();
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
return is_null($oMenuNode) === false && $oMenuNode->IsEnabled();
}
/**
* Main function to add a menu entry into the application, can be called during the definition
* of the data model objects
@@ -269,9 +280,11 @@ class ApplicationMenu
$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, [
IssueLog::Error('Menu node without parent (root menu) must be of type menu group. Parent menu is missing or not visible to user.', LogChannels::CONSOLE, [
'menu_node_class' => get_class($oMenuNode),
'menu_node_id' => $oMenuNode->GetMenuID(),
'menu_node_label' => $oMenuNode->GetLabel(),
'current_user_id' => UserRights::GetUserId(),
]);
continue;
}

View File

@@ -293,7 +293,7 @@ $("#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) {
$('#attr_auto_reload').on('change', function(ev) {
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
} );

View File

@@ -232,12 +232,13 @@ class DisplayTemplate
static public function UnitTest()
{
require_once(APPROOT.'/application/startup.inc.php');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1>
</div>
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<img src="'.$sAppRootUrl.'images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itoptabs>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock>
@@ -350,7 +351,8 @@ class ObjectDetailsTemplate extends DisplayTemplate
if ($iFlags & OPT_ATT_SLAVE)
{
$iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sAppRooturl = utils::GetAbsoluteUrlAppRoot();
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = '';
foreach($aReasons as $aRow)
{

View File

@@ -536,7 +536,7 @@ CSS;
if (static::HasImageExtension($sImg)
&& ! array_key_exists($sImg, $aImages))
{
$sFilePath = realpath($sImg);
$sFilePath = utils::RealPath($sImg, APPROOT);
if ($sFilePath !== false) {
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
$aImages[$sImg] = $sFilePathWithSlashes;
@@ -544,7 +544,7 @@ CSS;
}
$sCanonicalPath = static::CanonicalizePath($sTargetThemeFolderPath.'/'.$sImg);
$sFilePath = realpath($sCanonicalPath);
$sFilePath = utils::RealPath($sCanonicalPath, APPROOT);
if ($sFilePath !== false) {
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
$aImages[$sImg] = $sFilePathWithSlashes;

View File

@@ -161,8 +161,8 @@ class UIExtKeyWidget
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '')
{
$sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
@@ -368,7 +368,7 @@ JS
*/
public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle)
{
$oPage->add_linked_script('../js/forms-json-utils.js');
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
@@ -477,8 +477,8 @@ JS
$this->bSearchMode = $bSearchMode;
}
$sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
@@ -734,7 +734,7 @@ HTML
],
});
$('#fs_{$this->iId}').on('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
$('#dc_{$this->iId}').on('resize', oACWidget_{$this->iId}.UpdateSizes);
JS
);
}

View File

@@ -15,8 +15,11 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\Helper\CKEditorHelper;
use Combodo\iTop\Application\Helper\WebResourcesHelper;
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Renderer\BlockRenderer;
/**
* Class UIHTMLEditorWidget
@@ -72,21 +75,32 @@ class UIHTMLEditorWidget
// To change the default settings of the editor,
// a) edit the file /js/ckeditor/config.js
// b) or override some of the configuration settings, using the second parameter of ckeditor()
$aConfig = utils::GetCkeditorPref();
$sJSDefineWidth = '';
$aConfig = CKEditorHelper::GetCkeditorPref();
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
if ($sWidthSpec != '')
{
$aConfig['width'] = $sWidthSpec;
if ($sWidthSpec != '') {
/*N°6543 - the function min allow to keep text inside the column when width is defined*/
$aConfig['width'] = "min($sWidthSpec,100%)";
$sJSDefineWidth = '$("#cke_'.$iId.' iframe").contents().find("body").css("width", "'.$sWidthSpec.'")';
}
$sHeightSpec = addslashes(trim($this->m_oAttDef->GetHeight()));
if ($sHeightSpec != '')
{
if ($sHeightSpec != '') {
$aConfig['height'] = $sHeightSpec;
}
// TODO 3.2.0 Add the configuration for the editor
$sConfigJS = json_encode($aConfig);
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
$oPage->add_ready_script("CombodoCKEditorHandler.CreateInstance('#$iId', $sConfigJS)");
// inject mention item renderer template
$oTwig = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH);
$sTemplate = $oTwig->render('application/object/set/option_renderer.html.twig');
$oPage->add(<<<HTML
<template id="{$iId}_items_template">
$sTemplate
</template>
HTML);
// Please read...
// ValidateCKEditField triggers a timer... calling itself indefinitely
@@ -111,6 +125,7 @@ $('#$iId').on('update', function(evt){
else
{
oMe.data('ckeditorInstance').setReadOnly(oMe.prop('disabled'));
$sJSDefineWidth
}
};
setTimeout(delayedSetReadOnly, 50);

View File

@@ -99,7 +99,7 @@ HTML
});
$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
$('#SearchFormToAdd_{$this->m_iInputId}').resize(oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
$('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
JS
);
}

View File

@@ -35,7 +35,7 @@ class UserDashboard extends DBObject
(
"category" => "gui",
"key_type" => "autoincrement",
"name_attcode" => "user_id",
"name_attcode" => array('user_id', 'menu_code'),
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_app_dashboards",
@@ -47,6 +47,15 @@ class UserDashboard extends DBObject
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("menu_code", array("allowed_values"=>null, "sql"=>"menu_code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("contents", array("allowed_values"=>null, "sql"=>"contents", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_SetZListItems('default_search', array (
0 => 'user_id',
1 => 'menu_code',
));
MetaModel::Init_SetZListItems('list', array (
0 => 'user_id',
1 => 'menu_code',
));
}
/**

View File

@@ -167,7 +167,11 @@ class utils
private static $iNextId = 0;
private static $m_sAppRootUrl = null;
/**
* @var ?string
* @used-by GetAbsoluteUrlAppRoot
*/
private static $sAbsoluteUrlAppRootCache = null;
protected static function LoadParamFile($sParamFile)
{
@@ -1037,28 +1041,27 @@ class utils
return $bTrustProxies;
}
/**
* Returns the absolute URL to the application root path
*
* @param bool $bForceTrustProxy
*
* @return string The absolute URL to the application root, without the first slash
*
* @throws \Exception
*
* @since 2.7.4 $bForceTrustProxy param added
*/
/**
* Returns the absolute URL to the application root path
*
* @param bool $bForceTrustProxy
*
* @return string The absolute URL to the application root, without the first slash
*
* @throws \Exception
*
* @since 2.7.4 $bForceTrustProxy param added
*/
public static function GetAbsoluteUrlAppRoot($bForceTrustProxy = false)
{
$sUrl = static::$m_sAppRootUrl;
if ($sUrl === null || $bForceTrustProxy)
if (static::$sAbsoluteUrlAppRootCache === null || $bForceTrustProxy)
{
$sUrl = self::GetConfig()->Get('app_root_url');
if ($sUrl == '')
static::$sAbsoluteUrlAppRootCache = self::GetConfig()->Get('app_root_url');
if (static::$sAbsoluteUrlAppRootCache == '')
{
$sUrl = self::GetDefaultUrlAppRoot($bForceTrustProxy);
static::$sAbsoluteUrlAppRootCache = self::GetDefaultUrlAppRoot($bForceTrustProxy);
}
elseif (strpos($sUrl, SERVER_NAME_PLACEHOLDER) > -1)
elseif (strpos(static::$sAbsoluteUrlAppRootCache, SERVER_NAME_PLACEHOLDER) > -1)
{
if (isset($_SERVER['SERVER_NAME']))
{
@@ -1069,11 +1072,10 @@ class utils
// CLI mode ?
$sServerName = php_uname('n');
}
$sUrl = str_replace(SERVER_NAME_PLACEHOLDER, $sServerName, $sUrl);
static::$sAbsoluteUrlAppRootCache = str_replace(SERVER_NAME_PLACEHOLDER, $sServerName, static::$sAbsoluteUrlAppRootCache);
}
static::$m_sAppRootUrl = $sUrl;
}
return static::$m_sAppRootUrl;
return static::$sAbsoluteUrlAppRootCache;
}
/**
@@ -2778,76 +2780,6 @@ SQL;
return static::$iNextId++;
}
/**
* Return the CKEditor config as an array
*
* @return array
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @since 3.0.0
*/
public static function GetCkeditorPref()
{
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
$aDefaultConf = array(
'language'=> $sLanguage,
'contentsLanguage' => $sLanguage,
'extraPlugins' => 'disabler,codesnippet,mentions,objectshortcut,font,uploadimage',
'uploadUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
'contentsCss' => array(utils::GetAbsoluteUrlAppRoot().'js/ckeditor/contents.css', utils::GetAbsoluteUrlAppRoot().'css/ckeditor/contents.css'),
);
// Mentions
$aMentionsAllowedClasses = MetaModel::GetConfig()->Get('mentions.allowed_classes');
if(!empty($aMentionsAllowedClasses)) {
$aDefaultConf['mentions'] = [];
foreach($aMentionsAllowedClasses as $sMentionMarker => $sMentionScope) {
// Retrieve mention class
// - First test if the conf is a simple Datamodel class
if (MetaModel::IsValidClass($sMentionScope)) {
$sMentionClass = $sMentionScope;
}
// - Otherwise it must be a valid OQL
else {
$oTmpSearch = DBSearch::FromOQL($sMentionScope);
$sMentionClass = $oTmpSearch->GetClass();
unset($oTmpSearch);
}
// Note: Endpoints are defaults only and should be overloaded by other GUIs such as the end-users portal
$sMentionEndpoint = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=cke_mentions&marker='.urlencode($sMentionMarker).'&needle={encodedQuery}';
$sMentionItemUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.$sMentionClass.'&id={id}';
$sMentionItemPictureTemplate = (empty(MetaModel::GetImageAttributeCode($sMentionClass))) ? '' : <<<HTML
<span class="ibo-vendors-ckeditor--autocomplete-item-image" style="{picture_style}">{initials}</span>
HTML;
$sMentionItemTemplate = <<<HTML
<li class="ibo-vendors-ckeditor--autocomplete-item" data-id="{id}">{$sMentionItemPictureTemplate}<span class="ibo-vendors-ckeditor--autocomplete-item-title">{friendlyname}</span></li>
HTML;
$sMentionOutputTemplate = <<<HTML
<a href="$sMentionItemUrl" data-role="object-mention" data-object-class="{class}" data-object-id="{id}">{$sMentionMarker}{friendlyname}</a>
HTML;
$aDefaultConf['mentions'][] = [
'feed' => $sMentionEndpoint,
'marker' => $sMentionMarker,
'minChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'),
'itemTemplate' => $sMentionItemTemplate,
'outputTemplate' => $sMentionOutputTemplate,
'throttle' => 500,
];
}
}
$aRichTextConfig = json_decode(appUserPreferences::GetPref('richtext_config', '{}'), true);
return array_merge($aDefaultConf, $aRichTextConfig);
}
/**
* @param string $sInterface
* @param string $sClassNameFilter

View File

@@ -4,7 +4,7 @@
"type": "project",
"license": "AGPL-3.0-only",
"require": {
"php": ">=8.1.0 <8.2.0",
"php": ">=8.1.0 <8.4.0",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
@@ -13,42 +13,42 @@
"ext-mysqli": "*",
"ext-soap": "*",
"apereo/phpcas": "~1.6.0",
"combodo/tcpdf": "~6.4.4",
"firebase/php-jwt": "~6.4.0",
"firebase/php-jwt": "^6.4.0",
"guzzlehttp/guzzle": "^7.5.1",
"laminas/laminas-mail": "^2.11",
"laminas/laminas-servicemanager": "^3.5",
"league/oauth2-google": "^3.0",
"nikic/php-parser": "~4.14.0",
"league/oauth2-google": "^4.0.1",
"nikic/php-parser": "^4.14.0",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "^6.0.0",
"scssphp/scssphp": "^1.10.3",
"pelago/emogrifier": "^7.2.0",
"psr/log": "^3.0.0",
"scssphp/scssphp": "^1.12.1",
"symfony/console": "~6.4.0",
"symfony/dotenv": "~6.4.0",
"symfony/form": "~6.4.0",
"symfony/framework-bundle": "~6.4.0",
"symfony/http-foundation": "~6.4.0",
"symfony/http-kernel": "~6.4.0",
"symfony/runtime": "~6.4.0",
"symfony/serializer": "^6.4",
"symfony/twig-bundle": "~6.4.0",
"symfony/validator": "~6.4.0",
"symfony/var-dumper": "~6.4.0",
"symfony/yaml": "~6.4.0",
"thenetworg/oauth2-azure": "^2.0"
"tecnickcom/tcpdf": "^6.6.0",
"thenetworg/oauth2-azure": "^2.0",
"masterminds/html5": "^2.8.0"
},
"require-dev": {
"symfony/debug-bundle": "~6.4.0",
"symfony/stopwatch": "~6.4.0",
"symfony/web-profiler-bundle": "~6.4.0",
"symfony/debug-bundle": "~6.4.0"
"symfony/web-profiler-bundle": "~6.4.0"
},
"suggest": {
"ext-libsodium": "Required to use the AttributeEncryptedString.",
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
"ext-mcrypt": "Can be used as a polyfill if either libsodium and openssl are not installed (libsodium and openssl are more secure)",
"ext-apcu": "For better performance and stability",
"ext-imap": "Required by the extension \"Mail to ticket automation\"",
"ext-ldap": "Required to use LDAP as an identity provider",
"ext-posix": "Not required by the core, but some extensions uses it.",
"ext-imap": "Required by the extension \"Mail to ticket automation\""
"ext-posix": "Not required by the core, but some extensions uses it."
},
"config": {
"platform": {
@@ -95,12 +95,13 @@
"require": "3.4.*"
},
"runtime": {
"dotenv_path": "symfony/.env"
"dotenv_path": "resources/symfony/.env"
}
},
"scripts": {
"post-install-cmd": ["@rmDeniedTestDir"],
"post-update-cmd": ["@rmDeniedTestDir"],
"rmDeniedTestDir": "@php .make/composer/rmDeniedTestDir.php"
"post-install-cmd": ["@rmUnnecessaryFolders", "@tcpdfCustomFonts"],
"post-update-cmd": ["@rmUnnecessaryFolders", "@tcpdfCustomFonts"],
"rmUnnecessaryFolders": "@php .make/dependencies/rmUnnecessaryFolders.php --manager composer",
"tcpdfCustomFonts": "@php .make/dependencies/composer/tcpdf/tcpdfUpdateFonts.php"
}
}

1449
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -521,6 +521,6 @@ class Str
public static function islowcase($sString)
{
return (strtolower($sString) == $sString);
return (mb_strtolower($sString) == $sString);
}
}

View File

@@ -17,7 +17,11 @@
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Service\Notification\NotificationsRepository;
use Combodo\iTop\Service\Notification\NotificationsService;
use Combodo\iTop\Service\Router\Router;
/**
* Persistent classes (internal): user defined actions
@@ -77,6 +81,7 @@ abstract class Action extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list",
array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "action_id", "ext_key_to_remote" => "trigger_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => array(), "display_style" => 'property')));
MetaModel::Init_AddAttribute(new AttributeEnum("asynchronous", array("allowed_values" => new ValueSetEnum(['use_global_setting' => 'Use global settings','yes' => 'Yes' ,'no' => 'No']), "sql" => "asynchronous", "default_value" => 'use_global_setting', "is_null_allowed" => false, "depends_on" => array())));
// Display lists
// - Attributes to be displayed for the complete details
@@ -168,6 +173,100 @@ abstract class Action extends cmdbAbstractObject
$this->m_aCheckWarnings[] = Dict::S('Action:WarningNoTriggerLinked');
}
}
/**
* @since 3.2.0 N°5472 method creation
*/
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
parent::DisplayBareRelations($oPage, false);
if ($oPage instanceof iTopWebPage) {
$this->GenerateLastExecutionsTab($oPage, $bEditMode);
}
}
/**
* @since 3.2.0 N°5472 method creation
*/
protected function GenerateLastExecutionsTab(iTopWebPage $oPage, $bEditMode)
{
$oRouter = Router::GetInstance();
$sActionLastExecutionsPageUrl = $oRouter->GenerateUrl('notifications.action.last_executions_tab', ['action_id' => $this->GetKey()]);
$oPage->AddAjaxTab('action_errors', $sActionLastExecutionsPageUrl, false, Dict::S('Action:last_executions_tab'));
}
/**
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
*
* @throws \ApplicationException
* @throws \ArchivedObjectException
* @throws \ConfigException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \InvalidConfigParamException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \ReflectionException
* @since 3.2.0 N°5472 method creation
*/
public function GetLastExecutionsTabContent(WebPage $oPage): void
{
$oConfig = utils::GetConfig();
$sLastExecutionDaysConfigParamName = 'notifications.last_executions_days';
$iLastExecutionDays = $oConfig->Get($sLastExecutionDaysConfigParamName);
if ($iLastExecutionDays < 0) {
throw new InvalidConfigParamException("Invalid value for {$sLastExecutionDaysConfigParamName} config parameter. Param desc: " . $oConfig->GetDescription($sLastExecutionDaysConfigParamName));
}
$sActionQueryOql = 'SELECT EventNotification WHERE action_id = :action_id';
$aActionQueryParams = ['action_id' => $this->GetKey()];
if ($iLastExecutionDays > 0) {
$sActionQueryOql .= ' AND date > DATE_SUB(NOW(), INTERVAL :days DAY)';
$aActionQueryParams['days'] = $iLastExecutionDays;
$sActionQueryLimit = Dict::Format('Action:last_executions_tab_limit_days', $iLastExecutionDays);
} else {
$sActionQueryLimit = Dict::S('Action:last_executions_tab_limit_none');
}
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle]);
$oPage->AddUiBlock($oExecutionsListBlock);
}
/**
* Will be overloaded by the children classes to return the value of their global asynchronous setting (eg. `email_asynchronous` for `\ActionEmail`, `prefer_asynchronous` for `\ActionWebhook`, ...)
*
* @return bool true if the global setting for this kind of action if to be executed asynchronously, false otherwise.
* @since 3.2.0
*/
public static function GetAsynchronousGlobalSetting(): bool
{
return false;
}
/**
* @return bool true if that action instance should be executed asynchronously, otherwise false
* @throws \ArchivedObjectException
* @throws \CoreException
* @since 3.2.0
*/
public function IsAsynchronous(): bool
{
$sAsynchronous = $this->Get('asynchronous');
if ($sAsynchronous === 'use_global_setting') {
return static::GetAsynchronousGlobalSetting();
}
return $sAsynchronous === 'yes';
}
}
/**
@@ -285,6 +384,7 @@ class ActionEmail extends ActionNotification
"db_table" => "priv_action_email",
"db_key_field" => "id",
"db_finalclass_field" => "",
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-mailing.svg'),
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
@@ -321,6 +421,7 @@ class ActionEmail extends ActionNotification
),
'fieldset:ActionEmail:trigger' => array(
0 => 'trigger_list',
1 => 'asynchronous'
),
),
'col:col2' => array(
@@ -355,27 +456,33 @@ class ActionEmail extends ActionNotification
protected $m_aMailErrors; //array of strings explaining the issue
/**
* Return a the list of emails as a string, or a detailed error description
* Return the list of emails as a string, or a detailed error description
*
* @param string $sRecipAttCode
* @param array $aArgs
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
protected function FindRecipients($sRecipAttCode, $aArgs)
{
$oTrigger = $aArgs['trigger->object()'] ?? null;
$sOQL = $this->Get($sRecipAttCode);
if (strlen($sOQL) === 0) return '';
if (utils::IsNullOrEmptyString($sOQL)) return '';
try
{
$oSearch = DBObjectSearch::FromOQL($sOQL);
if ($this->Get('ignore_notify') === 'no') {
// In theory it is possible to notify *any* kind of object,
// In theory, it is possible to notify *any* kind of object,
// as long as there is an email attribute in the class
// So let's not assume that the selected class is a Person
$sFirstSelectedClass = $oSearch->GetClass();
@@ -408,16 +515,29 @@ class ActionEmail extends ActionNotification
return "The objects of the class '$sClass' do not have any email attribute";
}
if($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
$aArgs['trigger_id'] = $oTrigger->GetKey();
$aArgs['action_id'] = $this->GetKey();
$sSubscribedContactsOQL = NotificationsRepository::GetInstance()->GetSearchOQLContactUnsubscribedByTriggerAndAction();
$sSubscribedContactsOQL->ApplyParameters($aArgs);
$sAlias = $oSearch->GetClassAlias();
$oSearch->AddConditionExpression(Expression::FromOQL("`$sAlias`.id NOT IN ($sSubscribedContactsOQL)"));
}
$oSet = new DBObjectSet($oSearch, array() /* order */, $aArgs);
$aRecipients = array();
while ($oObj = $oSet->Fetch())
{
$sAddress = trim($oObj->Get($sEmailAttCode));
if (strlen($sAddress) > 0)
if (utils::IsNotNullOrEmptyString($sAddress))
{
$aRecipients[] = $sAddress;
$this->m_iRecipients++;
}
if ($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oObj);
}
}
return implode(', ', $aRecipients);
}
@@ -537,7 +657,7 @@ class ActionEmail extends ActionNotification
else
{
$aErrors = [];
$iRes = $oEmail->Send($aErrors, false, $oLog); // allow asynchronous mode
$iRes = $oEmail->Send($aErrors, $this->IsAsynchronous() ? Email::ENUM_SEND_FORCE_ASYNCHRONOUS : Email::ENUM_SEND_FORCE_SYNCHRONOUS, $oLog);
switch ($iRes)
{
case EMAIL_SEND_OK:
@@ -566,8 +686,17 @@ class ActionEmail extends ActionNotification
* @param \EventNotification $oLog
*
* @return array
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \Exception
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \DictExceptionMissingString
* @throws \DictExceptionUnknownLanguage
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @since 3.1.0 N°918
*/
protected function PrepareMessageContent($aContextArgs, &$oLog): array
@@ -646,9 +775,7 @@ class ActionEmail extends ActionNotification
$oLog->Set('body', HTMLSanitizer::Sanitize($aMessageContent['body']));
}
}
$sStyles = file_get_contents(APPROOT.'css/email.css');
$sStyles .= MetaModel::GetConfig()->Get('email_css');
if ($this->IsBeingTested()) {
$sTestBody = $aMessageContent['body'];
$sTestBody .= "<div style=\"border: dashed;\">\n";
@@ -677,10 +804,11 @@ class ActionEmail extends ActionNotification
if (isset($aContextArgs['attachments']))
{
$aAttachmentReport = array();
/** @var \ormDocument $oDocument */
foreach($aContextArgs['attachments'] as $oDocument)
{
$aMessageContent['attachments'][] = ['data' => $oDocument->GetData(), 'filename' => $oDocument->GetFileName(), 'mime_type' => $oDocument->GetMimeType()];
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData()));
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData() ?? ''));
}
$oLog->Set('attachments', $aAttachmentReport);
}
@@ -790,4 +918,13 @@ class ActionEmail extends ActionNotification
}
}
}
/**
* @inheritDoc
* @since 3.2.0
*/
public static function GetAsynchronousGlobalSetting(): bool
{
return utils::GetConfig()->Get('email_asynchronous');
}
}

View File

@@ -60,14 +60,15 @@ function apc_store($key, $var = NULL, $ttl = 0)
*/
function apc_fetch($key)
{
if (is_array($key))
{
$aResult = array();
foreach($key as $sKey)
{
if (is_array($key)) {
$aResult = [];
foreach ($key as $sKey) {
$aResult[$sKey] = apcFile::FetchOneFile($sKey);
}
return $aResult;
} elseif (is_null($key)) {
return false;
}
return apcFile::FetchOneFile($key);
}
@@ -97,6 +98,31 @@ function apc_delete($key)
return $bRet1 || $bRet2;
}
/**
* Checks if APCu emulation key exists
*
* @param string|string[] $keys A string, or an array of strings, that contain keys.
*
* @return bool|string[] Returns TRUE if the key exists, otherwise FALSE
* Or if an array was passed to keys, then an array is returned that
* contains all existing keys, or an empty array if none exist.
* @since 3.2.0 N°7068
*/
function apc_exists($keys)
{
if (is_array($keys)) {
$aExistingKeys = [];
foreach ($keys as $sKey) {
if (apcFile::ExistsOneFile($sKey)) {
$aExistingKeys[] = $sKey;
}
}
return $aExistingKeys;
} else {
return apcFile::ExistsOneFile($keys);
}
}
class apcFile
{
// Check only once per request
@@ -183,6 +209,16 @@ class apcFile
return true;
}
/**
* Check if cache key exists
* @param $sKey
* @return bool
* @since 3.2.0 N°7068
*/
static public function ExistsOneFile($sKey) {
return is_file(self::GetCacheFileName('-' . $sKey)) || is_file(self::GetCacheFileName($sKey));
}
/** Get one cache entry content.
* @param $sKey
* @return bool|mixed
@@ -211,21 +247,16 @@ class apcFile
*/
static public function StoreOneFile($sKey, $value, $iTTL)
{
if (empty($sKey))
{
if (empty($sKey)) {
return false;
}
if (is_file(self::GetCacheFileName($sKey)))
{
if (is_file(self::GetCacheFileName($sKey))) {
@unlink(self::GetCacheFileName($sKey));
}
if (is_file(self::GetCacheFileName('-'.$sKey)))
{
if (is_file(self::GetCacheFileName('-'.$sKey))) {
@unlink(self::GetCacheFileName('-'.$sKey));
}
if ($iTTL > 0)
{
if ($iTTL > 0) {
// hint for ttl management
$sKey = '-'.$sKey;
}
@@ -233,15 +264,14 @@ class apcFile
$sFilename = self::GetCacheFileName($sKey);
// try to create the folder
$sDirname = dirname($sFilename);
if (!file_exists($sDirname))
{
if (!@mkdir($sDirname, 0755, true))
{
if (!is_dir($sDirname)) {
if (!@mkdir($sDirname, 0755, true)) {
return false;
}
}
$bRes = !(@file_put_contents($sFilename, serialize($value), LOCK_EX) === false);
self::AddFile($sFilename);
return $bRes;
}
@@ -325,19 +355,15 @@ class apcFile
*/
static protected function ReadCacheLocked($sFilename)
{
if (!is_file($sFilename))
{
return false;
}
$sContent = false;
$file = @fopen($sFilename, 'r');
if ($file === false)
{
return false;
if ($file !== false) {
if (flock($file, LOCK_SH)) {
$sContent = file_get_contents($sFilename);
flock($file, LOCK_UN);
}
fclose($file);
}
flock($file, LOCK_SH);
$sContent = @fread($file, @filesize($sFilename));
flock($file, LOCK_UN);
fclose($file);
return $sContent;
}

View File

@@ -15,6 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Service\Notification\Event\EventiTopNotificationService;
/**
@@ -457,3 +458,87 @@ class AsyncSendEmail extends AsyncTask
return '';
}
}
/**
* An async notification to be sent to iTop users
* @since 3.2.0
*/
class AsyncSendiTopNotifications extends AsyncTask {
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "created",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_async_send_itop_notifications",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("recipients", array("allowed_values"=>null, "sql"=>"recipients", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "allowed_values"=>null, "sql"=>"action_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "allowed_values"=>null, "sql"=>"trigger_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("title", array("allowed_values"=>null, "sql"=>"title", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values"=>null, "sql"=>"object_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("object_class", array("allowed_values"=>null, "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("url", array("allowed_values"=>null, "sql"=>"url", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
}
/**
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public static function AddToQueue(int $iActionId, int $iTriggerId, array $aRecipients, string $sMessage, string $sTitle, string $sUrl, int $iObjectId, ?string $sObjectClass): void
{
$oNew = new static();
$oNew->Set('action_id', $iActionId);
$oNew->Set('trigger_id', $iTriggerId);
$oNew->Set('recipients', json_encode($aRecipients));
$oNew->Set('message', $sMessage);
$oNew->Set('title', $sTitle);
$oNew->Set('url', $sUrl);
$oNew->Set('object_id', $iObjectId);
$oNew->Set('object_class', $sObjectClass);
$oNew->SetCurrentDate('date');
$oNew->DBInsert();
}
/**
* @inheritDoc
*/
public function DoProcess()
{
$oAction = MetaModel::GetObject('Action', $this->Get('action_id'));
$iTriggerId = $this->Get('trigger_id');
$aRecipients = json_decode($this->Get('recipients'));
$sMessage = $this->Get('message');
$sTitle = $this->Get('title');
$sUrl = $this->Get('url');
$iObjectId = $this->Get('object_id');
$sObjectClass = $this->Get('object_class');
$sDate = $this->Get('date');
foreach ($aRecipients as $iRecipientId)
{
$oEvent = EventiTopNotificationService::MakeEventFromAction($oAction, $iRecipientId, $iTriggerId, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass, $sDate);
$oEvent->DBInsertNoReload();
}
return "Sent";
}
}

View File

@@ -73,6 +73,11 @@ define('DEL_SILENT', 2);
*/
define('DEL_MOVEUP', 3);
/**
* Do nothing at least automatically
*/
define('DEL_NONE', 4);
/**
* For Link sets: tracking_level
@@ -3062,6 +3067,11 @@ class AttributeObjectKey extends AttributeDBFieldVoid
return ((int) $proposedValue) !== 0;
}
/**
* @inheritDoc
*
* @param int|DBObject $proposedValue Object key or valid ({@see MetaModel::IsValidObject()}) datamodel object
*/
public function MakeRealValue($proposedValue, $oHostObj)
{
if (is_null($proposedValue))
@@ -3074,7 +3084,6 @@ class AttributeObjectKey extends AttributeDBFieldVoid
}
if (MetaModel::IsValidObject($proposedValue))
{
/** @var \DBObject $proposedValue */
return $proposedValue->GetKey();
}
@@ -3192,9 +3201,19 @@ class AttributeDecimal extends AttributeDBField
{
$iNbDigits = $this->Get('digits');
$iPrecision = $this->Get('decimals');
$iNbIntegerDigits = $iNbDigits - $iPrecision - 1; // -1 because the first digit is treated separately in the pattern below
$iNbIntegerDigits = $iNbDigits - $iPrecision;
return "^[\-\+]?[0-9]\d{0,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$";
return "^[\-\+]?\d{1,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$";
}
/**
* @inheritDoc
* @since 3.2.0
*/
public function CheckFormat($value)
{
$sRegExp = $this->GetValidationPattern();
return preg_match("/$sRegExp/", $value);
}
public function GetBasicFilterOperators()
@@ -3289,7 +3308,7 @@ class AttributeDecimal extends AttributeDBField
if (!is_null($value) && ($value !== ''))
{
$value = sprintf("%01.".$this->Get('decimals')."F", $value);
$value = sprintf("%1.".$this->Get('decimals')."F", $value);
}
return $value; // null or string
}
@@ -3506,7 +3525,7 @@ class AttributeBoolean extends AttributeInteger
$sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null,
$sAttributeQualifier = null
) {
$sInput = strtolower(trim($sProposedValue));
$sInput = mb_strtolower(trim($sProposedValue));
if ($bLocalizedValue)
{
switch ($sInput)
@@ -4531,7 +4550,6 @@ class AttributeText extends AttributeString
$sStyle = '';
if (count($aStyles) > 0)
{
$aStyles[] = 'overflow:auto';
$sStyle = 'style="'.implode(';', $aStyles).'"';
}
@@ -6511,32 +6529,46 @@ class AttributeDateTime extends AttributeDBField
}
}
/**
* @inheritDoc
*
* @param int|DateTime|string $proposedValue possible values :
* - timestamp ({@see DateTime::getTimestamp())
* - {@see \DateTime} PHP object
* - string, following the {@see GetInternalFormat} format.
*
* @throws \CoreUnexpectedValue if invalid value type or the string passed cannot be converted
*/
public function MakeRealValue($proposedValue, $oHostObj)
{
if (is_null($proposedValue))
{
return null;
}
if (is_string($proposedValue) && ($proposedValue == "") && $this->IsNullAllowed())
{
return null;
if (is_numeric($proposedValue)) {
return date(static::GetInternalFormat(), $proposedValue);
}
if (!is_numeric($proposedValue))
{
// Check the format
try
{
$oFormat = new DateTimeFormat($this->GetInternalFormat());
if (is_object($proposedValue) && ($proposedValue instanceof DateTime)) {
return $proposedValue->format(static::GetInternalFormat());
}
if (is_string($proposedValue)) {
if (($proposedValue === '') && $this->IsNullAllowed()) {
return null;
}
try {
$oFormat = new DateTimeFormat(static::GetInternalFormat());
$oFormat->Parse($proposedValue);
} catch (Exception $e)
{
throw new Exception('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"');
} catch (Exception $e) {
throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"');
}
return $proposedValue;
}
return date(static::GetInternalFormat(), $proposedValue);
throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode());
}
public function ScalarToSQL($value)
@@ -8300,9 +8332,9 @@ class AttributeBlob extends AttributeDefinition
}
/**
* Users can provide the document from an URL (including an URL on iTop itself)
* for CSV import. Administrators can even provide the path to a local file
* {@inheritDoc}
* {@inheritDoc}
*
* @param string $proposedValue Can be an URL (including an URL to iTop itself), or a local path (CSV import)
*
* @see AttributeDefinition::MakeRealValue()
*/
@@ -8543,7 +8575,7 @@ class AttributeBlob extends AttributeDefinition
$sFingerprint = '';
if ($value instanceOf ormDocument)
{
$sFingerprint = md5($value->GetData());
$sFingerprint = $value->GetSignature();
}
return $sFingerprint;
@@ -8654,6 +8686,20 @@ class AttributeImage extends AttributeBlob
parent::__construct($sCode, $aParams);
}
public function Get($sParamName)
{
$oParamValue = parent::Get($sParamName);
if ($sParamName === 'default_image') {
/** @noinspection NestedPositiveIfStatementsInspection */
if (!empty($oParamValue)) {
return utils::GetAbsoluteUrlModulesRoot() . $oParamValue;
}
}
return $oParamValue;
}
public function GetEditClass()
{
return "Image";

View File

@@ -35,11 +35,37 @@ abstract class CellChangeSpec
return $this->m_proposedValue;
}
public function GetDisplayableValue()
/**
* @throws \Exception
* @since 3.2.0
*/
public function GetCLIValue(bool $bLocalizedValues = false): string
{
if (is_object($this->m_proposedValue)) {
if ($this->m_proposedValue instanceof ReportValue) {
return $this->m_proposedValue->GetAsCSV($bLocalizedValues, ',', '"');
}
throw new Exception('Unexpected class : '. get_class($this->m_proposedValue));
}
return $this->m_proposedValue;
}
/**
* @throws \Exception
* @since 3.2.0
*/
public function GetHTMLValue(bool $bLocalizedValues = false): string
{
if (is_object($this->m_proposedValue)) {
if ($this->m_proposedValue instanceof ReportValue) {
return $this->m_proposedValue->GetAsHTML($bLocalizedValues);
}
throw new Exception('Unexpected class : '. get_class($this->m_proposedValue));
}
return utils::EscapeHtml($this->m_proposedValue);
}
/**
* @since 3.1.0 N°5305
*/
@@ -54,12 +80,12 @@ abstract class CellChangeSpec
}
/**
* @since 3.1.0 N°5305
* @since 3.2.0
*/
public function GetDisplayableValueAndDescription(): string
public function GetCLIValueAndDescription(): string
{
return sprintf("%s%s",
$this->GetDisplayableValue(),
$this->GetCLIValue(),
$this->GetDescription()
);
}
@@ -108,13 +134,25 @@ class CellStatus_Issue extends CellStatus_Modify
parent::__construct($proposedValue, $previousValue);
}
public function GetDisplayableValue()
public function GetCLIValue(bool $bLocalizedValues = false): string
{
if (is_null($this->m_proposedValue)) {
return Dict::Format('UI:CSVReport-Value-SetIssue');
}
return Dict::Format('UI:CSVReport-Value-ChangeIssue',$this->m_proposedValue);
}
public function GetHTMLValue(bool $bLocalizedValues = false): string
{
if (is_null($this->m_proposedValue))
{
return Dict::Format('UI:CSVReport-Value-SetIssue');
}
return Dict::Format('UI:CSVReport-Value-ChangeIssue', \utils::EscapeHtml($this->m_proposedValue));
if ($this->m_proposedValue instanceof ReportValue)
{
return Dict::Format('UI:CSVReport-Value-ChangeIssue', $this->m_proposedValue->GetAsHTML($bLocalizedValues));
}
return Dict::Format('UI:CSVReport-Value-ChangeIssue',utils::EscapeHtml($this->m_proposedValue));
}
public function GetDescription()
@@ -122,12 +160,12 @@ class CellStatus_Issue extends CellStatus_Modify
return $this->m_sReason;
}
/*
* @since 3.1.0 N°5305
* @since 3.2.0
*/
public function GetDisplayableValueAndDescription(): string
public function GetCLIValueAndDescription(): string
{
return sprintf("%s. %s",
$this->GetDisplayableValue(),
$this->GetCLIValue(),
$this->GetDescription()
);
}
@@ -163,7 +201,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
* @param null $sAllowedValues : used for additional message that provides allowed values $sAllowedValues for current class
* @param string|null $sAllowedValuesSearch : used to search all allowed values
*/
public function __construct($sSerializedSearch, $sReason, $sClass=null, $sAllowedValues=null, string $sAllowedValuesSearch=null)
public function __construct($sSerializedSearch, $sReason, $sClass = null, $sAllowedValues = null, string $sAllowedValuesSearch = null)
{
parent::__construct(null, null, $sReason);
$this->sSerializedSearch = $sSerializedSearch;
@@ -172,7 +210,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
$this->sAllowedValuesSearch = $sAllowedValuesSearch;
}
public function GetDisplayableValue()
public function GetCLIValue(bool $bLocalizedValues = false): string
{
if (null === $this->m_sReason) {
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
@@ -181,6 +219,15 @@ class CellStatus_SearchIssue extends CellStatus_Issue
return $this->m_sReason;
}
public function GetHTMLValue(bool $bLocalizedValues = false): string
{
if (null === $this->m_sReason) {
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
}
return utils::EscapeHtml($this->m_sReason);
}
public function GetDescription()
{
if (\utils::IsNullOrEmptyString($this->m_sAllowedValues) ||
@@ -198,7 +245,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
public function GetSearchLinkUrl()
{
return sprintf("UI.php?operation=search&filter=%s",
rawurlencode($this->sSerializedSearch)
rawurlencode($this->sSerializedSearch ?? "")
);
}
@@ -209,7 +256,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
public function GetAllowedValuesLinkUrl(): ?string
{
return sprintf("UI.php?operation=search&filter=%s",
rawurlencode($this->sAllowedValuesSearch)
rawurlencode($this->sAllowedValuesSearch ?? "")
);
}
}
@@ -227,6 +274,33 @@ class CellStatus_NullIssue extends CellStatus_Issue
}
}
/**
* Class to differ formatting depending on the caller
*/
class ReportValue
{
/**
* @param DBObject $oObject
* @param string $sAttCode
* @param bool $bOriginal
*/
public function __construct(protected DBObject $oObject, protected string $sAttCode, protected bool $bOriginal){}
public function GetAsHTML(bool $bLocalizedValues)
{
if ($this->bOriginal) {
return $this->oObject->GetOriginalAsHTML($this->sAttCode, $bLocalizedValues);
}
return $this->oObject->GetAsHTML($this->sAttCode, $bLocalizedValues);
}
public function GetAsCSV (bool $bLocalizedValues, string $sCsvSep, string $sCsvDelimiter) {
if ($this->bOriginal) {
return $this->oObject->GetOriginalAsCSV($this->sAttCode, $sCsvSep, $sCsvDelimiter, $bLocalizedValues);
}
return $this->oObject->GetAsCSV($this->sAttCode, $sCsvSep, $sCsvDelimiter, $bLocalizedValues);
}
}
class CellStatus_Ambiguous extends CellStatus_Issue
{
@@ -265,7 +339,7 @@ class CellStatus_Ambiguous extends CellStatus_Issue
public function GetSearchLinkUrl()
{
return sprintf("UI.php?operation=search&filter=%s",
rawurlencode($this->sSerializedSearch)
rawurlencode($this->sSerializedSearch ?? "")
);
}
}
@@ -413,22 +487,6 @@ class BulkChange
$this->m_aExtKeysMappingCache = array();
}
protected $m_bReportHtml = false;
protected $m_sReportCsvSep = ',';
protected $m_sReportCsvDelimiter = '"';
public function SetReportHtml()
{
$this->m_bReportHtml = true;
}
public function SetReportCsv($sSeparator = ',', $sDelimiter = '"')
{
$this->m_bReportHtml = false;
$this->m_sReportCsvSep = $sSeparator;
$this->m_sReportCsvDelimiter = $sDelimiter;
}
protected function ResolveExternalKey($aRowData, $sAttCode, &$aResults)
{
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
@@ -446,7 +504,7 @@ class BulkChange
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
$oExtObjects = new CMDBObjectSet($oReconFilter);
@@ -470,7 +528,7 @@ class BulkChange
}
/**
* @param \DBObject $oTargetObj
* @param DBObject $oTargetObj
* @param array $aRowData
* @param array $aErrors
*
@@ -533,7 +591,7 @@ class BulkChange
}
$aCacheKeys[] = $value;
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
$sCacheKey = implode('_|_', $aCacheKeys); // Unique key for this query...
$iForeignKey = null;
@@ -602,7 +660,7 @@ class BulkChange
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
{
// Report the change on reconciliation values as well
$aResults[$iCol] = new CellStatus_Modify(utils::HtmlEntities($aRowData[$iCol]));
$aResults[$iCol] = new CellStatus_Modify($aRowData[$iCol]);
}
}
}
@@ -680,50 +738,32 @@ class BulkChange
// Reporting on fields
//
$aChangedFields = $oTargetObj->ListChanges();
foreach ($this->m_aAttList as $sAttCode => $iCol)
{
if ($sAttCode == 'id')
{
$aResults[$iCol]= new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
foreach ($this->m_aAttList as $sAttCode => $iCol) {
if ($sAttCode == 'id') {
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
}
else
{
if ($this->m_bReportHtml)
{
$sCurValue = $oTargetObj->GetAsHTML($sAttCode, $this->m_bLocalizedValues);
$sOrigValue = $oTargetObj->GetOriginalAsHTML($sAttCode, $this->m_bLocalizedValues);
else {
$sCurValue = new ReportValue($oTargetObj, $sAttCode, false);
$sOrigValue = new ReportValue($oTargetObj, $sAttCode, true);
if (isset($aErrors[$sAttCode])) {
$aResults[$iCol]= new CellStatus_Issue($aRowData[$iCol], $sOrigValue, $aErrors[$sAttCode]);
}
else
{
$sCurValue = $oTargetObj->GetAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
$sOrigValue = $oTargetObj->GetOriginalAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
}
if (isset($aErrors[$sAttCode]))
{
$aResults[$iCol]= new CellStatus_Issue(utils::HtmlEntities($aRowData[$iCol]), $sOrigValue, $aErrors[$sAttCode]);
}
elseif (array_key_exists($sAttCode, $aChangedFields))
{
if ($oTargetObj->IsNew())
{
elseif (array_key_exists($sAttCode, $aChangedFields)){
if ($oTargetObj->IsNew()) {
$aResults[$iCol]= new CellStatus_Void($sCurValue);
}
else
{
else {
$aResults[$iCol]= new CellStatus_Modify($sCurValue, $sOrigValue);
}
}
else
{
else {
// By default... nothing happens
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oAttDef instanceof AttributeDateTime)
{
if ($oAttDef instanceof AttributeDateTime) {
$aResults[$iCol]= new CellStatus_Void($oAttDef->GetFormat()->Format($aRowData[$iCol]));
}
else
{
$aResults[$iCol]= new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
else {
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
}
}
}
@@ -788,7 +828,7 @@ class BulkChange
// 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 */
/** @var DBObject $oVisibleObject */
$oVisibleObject = $oExtObjectSetWithCurrentUserPermissions->Fetch();
if (is_null($oVisibleObject)){
break;
@@ -1155,7 +1195,7 @@ class BulkChange
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);
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
}
else
@@ -1168,6 +1208,7 @@ class BulkChange
}
else
{
// almost impossible ti reproduce since even incorrect dates with correct formats are formated and $oDate will not be false
// Leave the cell unchanged
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
@@ -1307,7 +1348,7 @@ class BulkChange
{
if (!array_key_exists($iCol, $aResult[$iRow]))
{
$aResult[$iRow][$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
}
foreach($this->m_aExtKeys as $sAttCode => $aForeignAtts)
@@ -1321,7 +1362,7 @@ class BulkChange
if (!array_key_exists($iCol, $aResult[$iRow]))
{
// The foreign attribute is one of our reconciliation key
$aResult[$iRow][$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
}
}
@@ -1446,7 +1487,7 @@ EOF
<<<EOF
function OnTruncatedHistoryToggle(bShowAll)
{
$('#csv_history_reload').html('<img src="../images/indicator.gif"/>');
$('#csv_history_reload').html('<img src="' + GetAbsoluteUrlAppRoot() + 'images/indicator.gif"/>');
$.get(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?{$sAppContext}', {operation: 'displayCSVHistory', showall: bShowAll}, function(data)
{
$('#$sAjaxDivId').html(data);

View File

@@ -335,7 +335,7 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this)));
$oMyChangeOp->Set("objkey", $objkey);
$oMyChangeOp->Set("fclass", get_class($this));
$oMyChangeOp->Set("fname", substr($this->GetRawName(), 0, 255)); // Protect against very long friendly names
$oMyChangeOp->SetTrim("fname", $this->GetRawName()); // Protect against very long friendly names
$iId = $oMyChangeOp->DBInsertNoReload();
}

View File

@@ -549,10 +549,9 @@ class CMDBSource
/**
* @param string $sSQLQuery
*
* @return \mysqli_result|null
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \CoreException
* @return mysqli_result|null
* @throws MySQLException
* @throws MySQLHasGoneAwayException
*
* @since 2.7.0 N°679 handles nested transactions
*/

View File

@@ -447,14 +447,14 @@ class Config
'show_in_conf_sample' => true,
],
'export_pdf_font' => [ // @since 2.7.0 PR #49 / N°1947
'type' => 'string',
'description' => 'Font used when generating a PDF file',
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
'type' => 'string',
'description' => 'Font used when generating a PDF file',
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'access_mode' => [
'type' => 'integer',
@@ -1119,6 +1119,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'purge_data.max_chunk_size' => [
'type' => 'integer',
'description' => 'Maximum number of items deleted per loop. Used in function MetaModel::PurgeData',
'default' => 1000,
'value' => 1000,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'max_history_length' => [
'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.',
@@ -1324,9 +1332,9 @@ class Config
'draft_attachments_lifetime' => [
'type' => 'integer',
'description' => 'Lifetime (in seconds) of drafts\' attachments and inline images: after this duration, the garbage collector will delete them.',
'default' => 86400,
'value' => '',
'source_of_value' => '',
'default' => 86400,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'date_and_time_format' => [
@@ -1611,6 +1619,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'notifications.itop.send_asynchronously' => [
'type' => 'bool',
'description' => 'If true then iTop notifications will be sent asynchronously',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'notifications.itop.newsroom_cache_time' => [
'type' => 'integer',
'description' => 'Duration in min between each fetch for notifications in newsroom',
@@ -1619,6 +1635,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'notifications.last_executions_days' => [
'type' => 'integer',
'description' => 'Number of days to display in the Action\'s last executions tab (0 means no limit)',
'default' => 30 + 31, // 2 months
'value' => 61,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'regenerate_session_id_enabled' => [
'type' => 'bool',
'description' => 'If true then session id will be regenerated on each login, to prevent session fixation.',
@@ -1874,6 +1898,7 @@ class Config
* @var integer Number of seconds between two reloads of the display (standard)
*/
protected $m_iStandardReloadInterval;
/**
* @var integer Number of seconds between two reloads of the display (fast)
*/
@@ -2545,9 +2570,9 @@ class Config
// Old fashioned integer settings
$aIntValues = array(
'fast_reload_interval' => $this->m_iFastReloadInterval,
'max_display_limit' => $this->m_iMaxDisplayLimit,
'min_display_limit' => $this->m_iMinDisplayLimit,
'fast_reload_interval' => $this->m_iFastReloadInterval,
'max_display_limit' => $this->m_iMaxDisplayLimit,
'min_display_limit' => $this->m_iMinDisplayLimit,
'standard_reload_interval' => $this->m_iStandardReloadInterval,
);
foreach ($aIntValues as $sKey => $iValue)

View File

@@ -1,6 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<classes>
<class id="lnkActionNotificationToContact" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>core/cmdb,application</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>priv_lnk_action_notif_to_contact</db_table>
<db_key_field>id</db_key_field>
<db_final_class_field/>
<naming>
<attributes>
<attribute id="action_id"/>
<attribute id="contact_id"/>
</attributes>
</naming>
<uniqueness_rules>
<rule>
<attributes>
<attribute id="action_id"/>
<attribute id="contact_id"/>
<attribute id="trigger_id"/>
</attributes>
<filter/>
<disabled>false</disabled>
<is_blocking>true</is_blocking>
</rule>
</uniqueness_rules>
</properties>
<fields>
<field id="action_id" xsi:type="AttributeExternalKey">
<sql>action_id</sql>
<target_class>ActionNotification</target_class>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="contact_id" xsi:type="AttributeExternalKey">
<sql>contact_id</sql>
<target_class>Contact</target_class>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="trigger_id" xsi:type="AttributeExternalKey">
<sql>trigger_id</sql>
<target_class>Trigger</target_class>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="subscribed" xsi:type="AttributeBoolean">
<sql>subscribed</sql>
<default_value>true</default_value>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
<presentation>
<details>
<items>
<item id="col:col1">
<items>
<item id="fieldset:lnkActionNotificationToContact:content">
<items>
<item id="action_id">
<rank>10</rank>
</item>
<item id="contact_id">
<rank>20</rank>
</item>
<item id="title">
<rank>30</rank>
</item>
</items>
</item>
</items>
</item>
</items>
</details>
<list>
<items>
<item id="action_id">
<rank>10</rank>
</item>
<item id="contact_id">
<rank>20</rank>
</item>
<item id="title">
<rank>30</rank>
</item>
</items>
</list>
</presentation>
<methods/>
</class>
<class id="ActioniTopNotification" _delta="define">
<php_parent>
<name>ActionNotification</name>
@@ -15,9 +106,12 @@
<db_final_class_field/>
<naming>
<attributes>
<attribute id="title"/>
<attribute id="name"/>
</attributes>
</naming>
<style>
<icon>../../images/icons/icons8-notification.svg</icon>
</style>
</properties>
<fields>
<field id="title" xsi:type="AttributeString">
@@ -38,7 +132,7 @@
<display_max_height>96</display_max_height>
<storage_max_width>256</storage_max_width>
<storage_max_height>256</storage_max_height>
<default_image>null</default_image>
<default_image />
</field>
<field id="priority" xsi:type="AttributeEnum">
<sql>priority</sql>
@@ -94,6 +188,16 @@
</item>
</items>
</item>
<item id="fieldset:ActioniTopNotification:trigger">
<items>
<item id="trigger_list">
<rank>10</rank>
</item>
<item id="asynchronous">
<rank>20</rank>
</item>
</items>
</item>
</items>
</item>
<item id="col:col2">
@@ -152,29 +256,62 @@
<static>false</static>
<access>public</access>
<code><![CDATA[
public function DoExecute($oTrigger, $aContextArgs)
public function DoExecute($oTrigger, $aContextArgs)
{
$oRecipientsSearch = DBObjectSearch::FromOQL($this->Get('recipients'));
$oRecipientsSearch->AllowAllData();
$oRecipientsSet = new DBObjectSet($oRecipientsSearch);
$oRecipientsSet = new DBObjectSet($oRecipientsSearch, array(), $aContextArgs);
$bIsAsync = $this->IsAsynchronous();
[$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage();
while ($oRecipient = $oRecipientsSet->Fetch()) {
$oEvent = new EventiTopNotification();
$oEvent->Set('title', MetaModel::ApplyParams($this->Get('title'), $aContextArgs));
$oEvent->Set('message', MetaModel::ApplyParams($this->Get('message'), $aContextArgs));
$oIcon = !$this->Get('icon')->IsEmpty() ? $this->Get('icon') : MetaModel::GetAttributeDef('EventiTopNotification', 'icon')->MakeRealValue(Combodo\iTop\Application\Branding::GetCompactMainLogoAbsoluteUrl(), $oEvent);
$oEvent->Set('icon', $oIcon);
$oEvent->Set('priority', $this->Get('priority'));
$oEvent->Set('contact_id', $oRecipient->GetKey());
$oEvent->Set('trigger_id', $oTrigger->GetKey());
$oEvent->Set('action_id', $this->GetKey());
$iObjectId = array_key_exists('this->object()', $aContextArgs) ? $aContextArgs['this->object()']->GetKey() : 0;
$oEvent->Set('object_id', $iObjectId);
$oEvent->Set('url', MetaModel::ApplyParams($this->Get('url'), $aContextArgs));
$oEvent->DBInsertNoReload();
if($bIsAsync === true){
$aRecipients = [];
}
$sMessage = MetaModel::ApplyParams($this->Get('message'), $aContextArgs);
$sTitle = MetaModel::ApplyParams($this->Get('title'), $aContextArgs);
$sUrl = MetaModel::ApplyParams($this->Get('url'), $aContextArgs);
$iObjectId = 0;
$sObjectClass = null;
if (array_key_exists('this->object()', $aContextArgs)) {
$iObjectId = $aContextArgs['this->object()']->GetKey();
$sObjectClass = get_class($aContextArgs['this->object()']);
}
while ($oRecipient = $oRecipientsSet->Fetch()) {
// Skip recipients that have no users
if (get_class($oRecipient) === Person::class && UserRights::GetUserFromPerson($oRecipient) === null) {
continue;
}
if (!\Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->IsSubscribed($oTrigger, $this, $oRecipient)) {
continue;
}
if($bIsAsync === true) {
$aRecipients[] = $oRecipient->GetKey();
} else {
$oEvent = Combodo\iTop\Service\Notification\Event\EventiTopNotificationService::MakeEventFromAction($this, $oRecipient->GetKey(), $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
$oEvent->DBInsertNoReload();
}
\Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oRecipient);
}
if ($bIsAsync === true) {
AsyncSendiTopNotifications::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipients, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
}
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
}
]]></code>
</method>
<method id="GetAsynchronousGlobalSetting">
<comment></comment>
<static>true</static>
<access>public</access>
<code><![CDATA[
public static function GetAsynchronousGlobalSetting(): bool
{
return utils::GetConfig()->Get('notifications.itop.send_asynchronously');
}
]]></code>
</method>
</methods>
@@ -207,7 +344,7 @@
<sql>icon</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
<default_image>null</default_image>
<default_image />
</field>
<field id="priority" xsi:type="AttributeEnum">
<sql>priority</sql>
@@ -259,7 +396,46 @@
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
<presentation/>
<presentation>
<details>
<items>
<item id="date">
<rank>10</rank>
</item>
<item id="title">
<rank>20</rank>
</item>
<item id="message">
<rank>30</rank>
</item>
<item id="contact_id">
<rank>40</rank>
</item>
<item id="trigger_id">
<rank>50</rank>
</item>
<item id="action_id">
<rank>60</rank>
</item>
<item id="read">
<rank>70</rank>
</item>
<item id="url">
<rank>80</rank>
</item>
</items>
</details>
<summary>
<items>
<item id="date">
<rank>10</rank>
</item>
<item id="message">
<rank>20</rank>
</item>
</items>
</summary>
</presentation>
<methods/>
</class>
</classes>

View File

@@ -210,6 +210,7 @@ abstract class DBObject implements iDisplay
const MAX_UPDATE_LOOP_COUNT = 10;
private $aEventListeners = [];
private array $aAllowedTransitions = [];
/**
* DBObject constructor.
@@ -608,11 +609,10 @@ abstract class DBObject implements iDisplay
* Attributes setter
*
* Set $sAttCode to $value.
* The value must be valid according to the type of attribute.
* The value must be valid according to the type of attribute : see the different {@see AttributeDefinition::MakeRealValue()} implementations
* The value will not be recorded into the DB until DBObject::DBWrite() is called.
*
* @api
* @see DBWrite()
*
* @param string $sAttCode
* @param mixed $value
@@ -620,6 +620,8 @@ abstract class DBObject implements iDisplay
* @return bool
* @throws CoreException
* @throws CoreUnexpectedValue
*
* @see DBWrite()
*/
public function Set($sAttCode, $value)
{
@@ -2317,16 +2319,17 @@ abstract class DBObject implements iDisplay
}
/**
* @param array $aUniquenessRuleProperties uniqueness rule properties
*
* @param string $sUniquenessRuleId uniqueness rule ID
* @return \DBSearch
* @throws \OQLException
* @throws \CoreException
*
* @internal
*
* @param string $sUniquenessRuleId uniqueness rule ID
* @param array $aUniquenessRuleProperties uniqueness rule properties
*
* @return \DBSearch
* @throws \CoreException
* @throws \OQLException
* @since 2.6.0 N°659 uniqueness constraint
* @api
* @since 2.6.0 N°659 uniqueness constraint
* @since 2.7.11 3.1.2 3.2.0 N°4314 Fix Uniqueness rules not working with Silo
*/
protected function GetSearchForUniquenessRule($sUniquenessRuleId, $aUniquenessRuleProperties)
{
@@ -2355,6 +2358,8 @@ abstract class DBObject implements iDisplay
$oUniquenessQuery->AddConditionForInOperatorUsingParam('finalclass', $aChildClassesWithRuleDisabled, false);
}
$oUniquenessQuery->AllowAllData();
return $oUniquenessQuery;
}
@@ -4401,9 +4406,32 @@ abstract class DBObject implements iDisplay
]);
}
$this->aAllowedTransitions = $aSortedTransitions;
$this->FireEvent(EVENT_ENUM_TRANSITIONS, ['allowed_stimuli' => array_keys($aSortedTransitions)]);
$aSortedTransitions = $this->aAllowedTransitions;
$this->aAllowedTransitions = [];
return $aSortedTransitions;
}
/**
* Remove a transition for a specific stimulus.
* This is only usable by EVENT_ENUM_TRANSITIONS listeners in order
* to manage the allowed transitions in the current object state.
*
* @param string $sStimulus
*
* @return void
* @api
* @since 3.1.2
*/
public function DenyTransition(string $sStimulus): void
{
if (isset($this->aAllowedTransitions[$sStimulus])) {
unset($this->aAllowedTransitions[$sStimulus]);
}
}
/**
* Helper to reset a stop-watch
* Suitable for use as a lifecycle action
@@ -4489,14 +4517,6 @@ abstract class DBObject implements iDisplay
$sNewState = $aTransitionDef['target_state'];
$this->Set($sStateAttCode, $sNewState);
$aEventData = [
'stimulus' => $sStimulusCode,
'previous_state' => $sPreviousState,
'new_state' => $sNewState,
'save_object' => !$bDoNotWrite,
];
$this->FireEvent(EVENT_DB_BEFORE_APPLY_STIMULUS, $aEventData);
// $aTransitionDef is an
// array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
@@ -4581,8 +4601,6 @@ abstract class DBObject implements iDisplay
if (!$bDoNotWrite) {
$this->DBWrite();
}
$this->FireEvent(EVENT_DB_AFTER_APPLY_STIMULUS, $aEventData);
}
else
{
@@ -4591,8 +4609,6 @@ abstract class DBObject implements iDisplay
{
$this->m_aCurrValues[$sAttCode] = $aBackupValues[$sAttCode];
}
$aEventData['action'] = $sActionDesc;
$this->FireEvent(EVENT_DB_APPLY_STIMULUS_FAILED, $aEventData);
}
return $bSuccess;
}
@@ -4729,7 +4745,7 @@ abstract class DBObject implements iDisplay
}
}
$oDate->modify($sModifier);
$this->Set($sAttCode, $oDate->format('Y-m-d H:i:s'));
$this->Set($sAttCode, $oDate);
}
/**
@@ -5346,16 +5362,19 @@ abstract class DBObject implements iDisplay
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
protected function GetReferencingObjects($bAllowAllData = false)
protected function GetReferencingObjectsForDeletion($bAllowAllData = false)
{
$aDependentObjects = array();
$aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this));
foreach($aRererencingMe as $sRemoteClass => $aExtKeys)
{
/** @var \AttributeExternalKey $oExtKeyAttDef */
foreach($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef)
{
// skip if external key doesn't require the deletion cascading
if($oExtKeyAttDef->GetDeletionPropagationOption() === DEL_NONE) continue;
// skip if this external key is behind an external field
/** @var \AttributeDefinition $oExtKeyAttDef */
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue;
$oSearch = new DBObjectSearch($sRemoteClass);
@@ -5419,13 +5438,11 @@ abstract class DBObject implements iDisplay
$this->CheckToWriteForTargetObjects(true);
$oDeletionPlan->SetDeletionIssues($this, $this->m_aDeleteIssues, $this->m_bSecurityIssue);
$aDependentObjects = $this->GetReferencingObjects(true /* allow all data */);
// Getting and setting time limit are not symmetric:
// www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time');
foreach ($aDependentObjects as $aPotentialDeletes)
foreach ($this->GetReferencingObjectsForDeletion(true /* allow all data */) as $aPotentialDeletes)
{
foreach ($aPotentialDeletes as $aData)
{

View File

@@ -851,11 +851,11 @@ abstract class DBSearch
return;
}
if (count($aColumns) == 0)
{
$aColumns = array_keys(MetaModel::ListAttributeDefs($this->GetClass()));
// Add the standard id (as first column)
array_unshift($aColumns, 'id');
if (count($aColumns) == 0)
{
$aColumns = array_keys(MetaModel::ListAttributeDefs($this->GetClass()));
// Add the standard id (as first column)
array_unshift($aColumns, 'id');
}
$aQueryCols = CMDBSource::GetColumns($resQuery, $sSQL);
@@ -885,6 +885,55 @@ abstract class DBSearch
return $aRes;
}
/**
* Selects a column ($sAttCode) from the specified class ($sClassAlias - default main class) of the DBsearch object and gives the result as an array
* @param string $sAttCode
* @param string|null $sClassAlias
*
* @return array
* @throws ConfigException
* @throws CoreException
* @throws MissingQueryArgument
* @throws MySQLException
* @throws MySQLHasGoneAwayException
*/
public function SelectAttributeToArray(string $sAttCode, ?string $sClassAlias = null):array
{
if(is_null($sClassAlias)) {
$sClassAlias = $this->GetClassAlias();
}
$sClass = $this->GetClass();
if($sAttCode === 'id'){
$aAttToLoad[$sClassAlias]=[];
} else {
$aAttToLoad[$sClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sClass, $sAttCode);
}
$sSQL = $this->MakeSelectQuery([], [], $aAttToLoad);
$resQuery = CMDBSource::Query($sSQL);
if (!$resQuery)
{
return [];
}
$sColName = $sClassAlias.$sAttCode;
$aRes = [];
while ($aRow = CMDBSource::FetchArray($resQuery))
{
$aMappedRow = array();
if($sAttCode === 'id') {
$aMappedRow[$sAttCode] = $aRow[$sColName];
} else {
$aMappedRow[$sAttCode] = $aAttToLoad[$sClassAlias][$sAttCode]->FromSQLToValue($aRow, $sColName);
}
$aRes[] = $aMappedRow;
}
CMDBSource::FreeResult($resQuery);
return $aRes;
}
////////////////////////////////////////////////////////////////////////////
//
// Construction of the SQL queries

View File

@@ -28,8 +28,13 @@ namespace Combodo\iTop;
use DOMDocument;
use DOMFormatException;
use DOMNode;
use DOMNodeList;
use DOMXPath;
use Exception;
use IssueLog;
use LogAPI;
use MFElement;
use utils;
/**
@@ -41,6 +46,11 @@ use utils;
*/
class DesignDocument extends DOMDocument
{
/** To fix DOMNode::getLineNo() ref https://www.php.net/manual/en/domnode.getlineno.php */
public const XML_PARSE_BIG_LINES = 4194304;
/**
* @throws \Exception
*/
@@ -64,16 +74,22 @@ class DesignDocument extends DOMDocument
/**
* Overload of the standard API
*
* @param $filename
* @param string $filename
* @param int $options
*
* @return bool
*/
public function load($filename, $options = null)
public function load(string $filename, int $options = 0): bool
{
libxml_clear_errors();
if (parent::load($filename, LIBXML_NOBLANKS) === false) {
$aErrors = libxml_get_errors();
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
if (is_file($filename)) {
libxml_clear_errors();
if (parent::load($filename, LIBXML_NOBLANKS | LIBXML_BIGLINES | LIBXML_PARSEHUGE | self::XML_PARSE_BIG_LINES) === false) {
$aErrors = libxml_get_errors();
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
}
}
return true;
}
/**
@@ -227,6 +243,56 @@ class DesignElement extends \DOMElement
return '';
}
/**
* Compatibility with PHP8.0
*
* @return \DOMElement|null
*
* @since 3.1.2
*/
public function GetFirstElementChild()
{
if (property_exists($this, 'firstElementChild')) {
return $this->firstElementChild;
}
$oChildNode = $this->firstChild;
while (!is_null($oChildNode)) {
if ($oChildNode instanceof \DOMElement) {
return $oChildNode;
}
$oChildNode = $oChildNode->nextSibling;
}
return null;
}
/**
* Compatibility with PHP8.0
*
* @return \DOMElement|null
*
* @since 3.1.2
*/
public function GetNextElementSibling()
{
if (property_exists($this, 'nextElementSibling')) {
return $this->nextElementSibling;
}
$oSibling = $this->nextSibling;
while (!is_null($oSibling)) {
if ($oSibling instanceof \DOMElement) {
return $oSibling;
}
$oSibling = $oSibling->nextSibling;
}
return null;
}
/**
* Returns the node directly under the given node
* @param $sTagName
@@ -307,4 +373,146 @@ class DesignElement extends \DOMElement
}
return $sRet;
}
/**
* Check that the current node is actually a class node, under classes
* @since 3.1.2 3.2.0 N°6974
*/
public function IsClassNode(): bool
{
if ($this->tagName == 'class') {
// Beware: classes/class also exists in the group definition
if (($this->parentNode->tagName == 'classes') && ($this->parentNode->parentNode->tagName == 'itop_design')) {
return true;
}
}
return false;
}
/**
* True if the node is contained in a _delta="merge" tree
* @return bool
*/
public function IsInSpecifiedMerge(): bool
{
// Iterate through the parents: reset the flag if any of them has a flag set
for ($oParent = $this; $oParent instanceof MFElement; $oParent = $oParent->parentNode) {
$sDeltaSpec = $oParent->getAttribute('_delta');
if ($sDeltaSpec === 'merge') {
return true;
}
if (in_array($sDeltaSpec, ['define', 'define_if_not_exists', 'force', 'redefine'])) {
return false;
}
}
return false;
}
/**
* Find the child node matching the given node.
* UNSAFE: may return nodes marked as _alteration="removed"
* A method with the same signature MUST exist in MFDocument for the recursion to work fine
*
* @param DesignElement $oRefNode The node to search for
* @param null|string $sSearchId substitutes to the value of the 'id' attribute
*
* @return DesignElement|null
* @throws \Exception
* @since 3.1.2 3.2.0 N°6974
*/
public function _FindChildNode(DesignElement $oRefNode, $sSearchId = null): ?DesignElement
{
return self::_FindNode($this, $oRefNode, $sSearchId);
}
/**
* Find the child node matching the given node.
* UNSAFE: may return nodes marked as _alteration="removed"
* A method with the same signature MUST exist in MFDocument for the recursion to work fine
*
* @param DesignElement $oRefNode The node to search for
*
* @return DesignElement|null
* @throws \Exception
* @since 3.1.2 3.2.0 N°6974
*/
public function _FindChildNodes(DesignElement $oRefNode): ?DesignElement
{
return self::_FindNodes($this, $oRefNode);
}
/**
* Find the child node matching the given node under the specified parent.
* UNSAFE: may return nodes marked as _alteration="removed"
*
* @param \DOMNode $oParent
* @param DesignElement $oRefNode
* @param string|null $sSearchId
*
* @return DesignElement|null
* @throws Exception
* @since 3.1.2 3.2.0 N°6974
*/
public static function _FindNode(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null): ?DesignElement
{
$oNodes = self::_FindNodes($oParent, $oRefNode, $sSearchId);
if ($oNodes instanceof DOMNodeList) {
/** @var DesignElement $oNode */
$oNode = $oNodes->item(0);
return $oNode;
}
return null;
}
/**
* Find the child node matching the given node under the specified parent.
* UNSAFE: may return nodes marked as _alteration="removed"
*
* @param \DOMNode $oParent
* @param DesignElement $oRefNode
* @param string|null $sSearchId
*
* @return \DOMNodeList|false|mixed
* @since 3.1.2 3.2.0 N°6974
*/
public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null)
{
if ($oParent instanceof DOMDocument)
{
$oDoc = $oParent->firstChild->ownerDocument;
$oRoot = $oParent;
}
else
{
$oDoc = $oParent->ownerDocument;
$oRoot = $oParent;
}
$oXPath = new DOMXPath($oDoc);
if ($oRefNode->hasAttribute('id'))
{
// Find the elements having the same tag name and id
if (!$sSearchId)
{
$sSearchId = $oRefNode->getAttribute('id');
}
$sXPath = './'.$oRefNode->tagName."[@id='$sSearchId']";
$oRes = $oXPath->query($sXPath, $oRoot);
}
else
{
// Get the elements having the same tag name
$sXPath = './'.$oRefNode->tagName;
$oRes = $oXPath->query($sXPath, $oRoot);
}
return $oRes;
}
}

View File

@@ -37,6 +37,7 @@ class DisplayableNode extends GraphNode
{
public $x;
public $y;
public bool $bFiltered;
/**
* Create a new node inside a graph

View File

@@ -15,6 +15,8 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Masterminds\HTML5;
/**
* Base class for all possible implementations of HTML Sanitization
*/
@@ -287,7 +289,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
'u' => array(),
'em' => array(),
'strong' => array(),
'img' => array('src', 'style', 'alt', 'title'),
'img' => array('src', 'style', 'alt', 'title', 'width', 'height'),
'ul' => array('style'),
'ol' => array('reversed', 'start', 'style', 'type'),
'li' => array('style', 'value'),
@@ -321,6 +323,8 @@ class HTMLDOMSanitizer extends DOMSanitizer
'hr' => array('style'),
'pre' => array(),
'center' => array(),
'figure' => array('class'), // Ckeditor 5 puts images in figures
'mark' => array('class')
);
protected static $aAttrsWhiteList = array(
@@ -332,6 +336,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
*/
protected static $aStylesWhiteList = array(
'aspect-ratio',
'background-color',
'border',
'border-collapse',

View File

@@ -536,6 +536,11 @@ JS
$sAbsoluteUrlAppRoot = utils::GetAbsoluteUrlAppRoot();
$sToggleFullScreen = utils::EscapeHtml(Dict::S('UI:ToggleFullScreen'));
return <<<JS
$('.htmlEditor').each(function() {
CombodoCKEditorHandler.EnableImageUpload('#' + $(this).attr('id'), '$sAbsoluteUrlAppRoot'+'pages/ajax.render.php?operation=cke_img_upload&temp_id=$sTempId&obj_class=$sObjClass&obj_key=$iObjKey');
});
JS;
return
<<<JS
@@ -605,6 +610,13 @@ JS
JS
;
}
public static function EnableCKEditor5ImageUpload(DBObject $oObject, $sTempId){
return <<<JS
// Hook the file upload of all CKEditor instances
JS;
}
/**
* @inheritDoc

View File

@@ -575,6 +575,12 @@ class LogChannels
*/
public const DATATABLE = 'Datatable';
/**
* @var string Everything related to the data integrity
* @since 3.2.0
*/
public const DATA_INTEGRITY = 'DataIntegrity';
public const DEADLOCK = 'DeadLock';
/**
* @var string Everything related to PHP sessions tracking
@@ -1090,6 +1096,11 @@ class DeadLockLog extends LogAPI
*/
class DeprecatedCallsLog extends LogAPI
{
/**
* @var string
* @since 3.2.0 N°4897
*/
public const ENUM_CHANNEL_PHP_API = 'deprecated-php-api';
public const ENUM_CHANNEL_PHP_METHOD = 'deprecated-php-method';
/**
* @var string
@@ -1283,6 +1294,35 @@ class DeprecatedCallsLog extends LogAPI
static::Warning($sMessage, static::ENUM_CHANNEL_FILE);
}
/**
* @param string $sImplementationClass Class implementing the deprecated API
* @param string $sDeprecatedApi Class name of the deprecated API
* @param string $sDeprecatedMethod Method name of the deprecated API
* @param string|null $sAdditionalMessage Additional message, mostly used to explain what API to use instead
*
* @return void
* @since 3.2.0 N°4897
*/
public static function NotifyDeprecatedPhpApi(string $sImplementationClass, string $sDeprecatedApi, string $sDeprecatedMethod, ?string $sAdditionalMessage = null): void
{
try {
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_API)) {
return;
}
}
catch (ConfigException $oException) {
return;
}
$sMessage = "Implementation of {$sDeprecatedApi}::{$sDeprecatedMethod}() in class {$sImplementationClass}";
if (!is_null($sAdditionalMessage)) {
$sMessage .= " : $sAdditionalMessage";
}
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_API);
}
/**
* @param string|null $sAdditionalMessage
*
@@ -1301,19 +1341,7 @@ class DeprecatedCallsLog extends LogAPI
}
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$iStackDeprecatedMethodLevel = 1; // level 0 = current method, level 1 = method containing the `NotifyDeprecatedPhpMethod` call
$sDeprecatedObject = $aStack[$iStackDeprecatedMethodLevel]['class'];
$sDeprecatedMethod = $aStack[$iStackDeprecatedMethodLevel]['function'];
$sCallerFile = $aStack[$iStackDeprecatedMethodLevel]['file'];
$sCallerLine = $aStack[$iStackDeprecatedMethodLevel]['line'];
$sMessage = "Call to {$sDeprecatedObject}::{$sDeprecatedMethod} in {$sCallerFile}#L{$sCallerLine}";
$iStackCallerMethodLevel = $iStackDeprecatedMethodLevel + 1; // level 2 = caller of the deprecated method
if (array_key_exists($iStackCallerMethodLevel, $aStack)) {
$sCallerObject = $aStack[$iStackCallerMethodLevel]['class'];
$sCallerMethod = $aStack[$iStackCallerMethodLevel]['function'];
$sMessage .= " ({$sCallerObject}::{$sCallerMethod})";
}
$sMessage = self::GetMessageFromStack($aStack);
if (!is_null($sAdditionalMessage)) {
$sMessage .= ' : '.$sAdditionalMessage;
@@ -1322,6 +1350,45 @@ class DeprecatedCallsLog extends LogAPI
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_METHOD);
}
/**
* @param array $aDebugBacktrace data from {@see debug_backtrace()}
*
* @return string message to print to the log
*/
private static function GetMessageFromStack(array $aDebugBacktrace): string
{
// level 0 = current method
// level 1 = deprecated method, containing the `NotifyDeprecatedPhpMethod` call
$sMessage = 'Call'.self::GetMessageForCurrentStackLevel($aDebugBacktrace[1], " to ");
// level 2 = caller of the deprecated method
if (array_key_exists(2, $aDebugBacktrace)) {
$sMessage .= ' (from ';
$sMessage .= self::GetMessageForCurrentStackLevel($aDebugBacktrace[2]);
$sMessage .= ')';
}
return $sMessage;
}
private static function GetMessageForCurrentStackLevel(array $aCurrentLevelDebugTrace, ?string $sPrefix = ""): string
{
$sMessage = "";
if (array_key_exists('class', $aCurrentLevelDebugTrace)) {
$sDeprecatedObject = $aCurrentLevelDebugTrace['class'];
$sDeprecatedMethod = $aCurrentLevelDebugTrace['function'] ?? "";
$sMessage = "{$sPrefix}{$sDeprecatedObject}::{$sDeprecatedMethod} in ";
}
if (array_key_exists('file', $aCurrentLevelDebugTrace)) {
$sCallerFile = $aCurrentLevelDebugTrace['file'];
$sCallerLine = $aCurrentLevelDebugTrace['line'] ?? "";
$sMessage .= "{$sCallerFile}#L{$sCallerLine}";
}
return $sMessage;
}
/**
* @param string|null $sAdditionalMessage
* @since 3.1.0

View File

@@ -6846,18 +6846,6 @@ abstract class MetaModel
$sClass = $aRow[$sClassAlias."finalclass"];
}
// if an object is already being updated, then this method will return this object instead of recreating a new one.
// At this point the method DBUpdate of a new object with the same class and id won't do anything due to reentrance protection,
// so to ensure that the potential modifications are correctly saved, the object currently being updated is returned.
// DBUpdate() method then will take care that all the modifications will be saved.
if (array_key_exists($sClassAlias.'id', $aRow)) {
$iKey = $aRow[$sClassAlias."id"];
$oObject = self::GetReentranceObject($sClass, $iKey);
if ($oObject !== false) {
return $oObject;
}
}
return new $sClass($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
}
@@ -7180,32 +7168,45 @@ abstract class MetaModel
*/
public static function PurgeData($oFilter)
{
$iMaxChunkSize = MetaModel::GetConfig()->Get('purge_data.max_chunk_size');
$sTargetClass = $oFilter->GetClass();
$oSet = new DBObjectSet($oFilter);
$oSet->OptimizeColumnLoad(array($sTargetClass => array('finalclass')));
$aIdToClass = $oSet->GetColumnAsArray('finalclass', true);
$iNbIdsDeleted = 0;
$bExecuteQuery = true;
$aIds = array_keys($aIdToClass);
if (count($aIds) > 0)
{
$aQuotedIds = CMDBSource::Quote($aIds);
$sIdList = implode(',', $aQuotedIds);
$aTargetClasses = array_merge(
self::EnumChildClasses($sTargetClass, ENUM_CHILD_CLASSES_ALL),
self::EnumParentClasses($sTargetClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)
);
foreach($aTargetClasses as $sSomeClass)
{
$sTable = MetaModel::DBGetTable($sSomeClass);
$sPKField = MetaModel::DBGetKey($sSomeClass);
// This loop allows you to delete objects in batches of $iMaxChunkSize elements
while ($bExecuteQuery) {
$oSet = new DBObjectSet($oFilter);
$oSet->SetLimit($iMaxChunkSize);
$oSet->OptimizeColumnLoad(array($sTargetClass => array('finalclass')));
$aIdToClass = $oSet->GetColumnAsArray('finalclass', true);
$sDeleteSQL = "DELETE FROM `$sTable` WHERE `$sPKField` IN ($sIdList)";
CMDBSource::DeleteFrom($sDeleteSQL);
$aIds = array_keys($aIdToClass);
$iNbIds = count($aIds);
if ($iNbIds > 0) {
$aQuotedIds = CMDBSource::Quote($aIds);
$sIdList = implode(',', $aQuotedIds);
$aTargetClasses = array_merge(
self::EnumChildClasses($sTargetClass, ENUM_CHILD_CLASSES_ALL),
self::EnumParentClasses($sTargetClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)
);
foreach ($aTargetClasses as $sSomeClass) {
$sTable = MetaModel::DBGetTable($sSomeClass);
$sPKField = MetaModel::DBGetKey($sSomeClass);
$sDeleteSQL = "DELETE FROM `$sTable` WHERE `$sPKField` IN ($sIdList)";
CMDBSource::DeleteFrom($sDeleteSQL);
}
$iNbIdsDeleted += $iNbIds;
}
// stop loop if query returned fewer objects than $iMaxChunkSize. In this case, all objects have been deleted.
if ($iNbIds < $iMaxChunkSize) {
$bExecuteQuery = false;
}
}
return count($aIds);
}
return $iNbIdsDeleted;
}
// Links
//
//

View File

@@ -739,7 +739,7 @@ class PHP_ParserGenerator
while (isset($errmsg[$restart]) && $errmsg[$restart] == ' ') {
$restart++;
}
printf("%s%.${end}s\n", $prefix, $errmsg);
printf("%s%.{$end}s\n", $prefix, $errmsg);
$errmsg = substr($errmsg, $restart);
}
}
@@ -771,7 +771,7 @@ class PHP_ParserGenerator
for ($j = $i; $j < $this->nsymbol; $j += $skip) {
$sp = $this->symbols[$j];
//assert( sp->index==j );
printf(" %3d %-${maxlen}.${maxlen}s", $j, $sp->name);
printf(" %3d %-{$maxlen}.{$maxlen}s", $j, $sp->name);
}
print "\n";
}

View File

@@ -231,19 +231,19 @@ class PHP_ParserGenerator_Action
switch ($this->type)
{
case self::SHIFT:
fprintf($fp, "%${indent}s shift %d", $this->sp->name, $this->x->statenum);
fprintf($fp, "%{$indent}s shift %d", $this->sp->name, $this->x->statenum);
break;
case self::REDUCE:
fprintf($fp, "%${indent}s reduce %d", $this->sp->name, $this->x->index);
fprintf($fp, "%{$indent}s reduce %d", $this->sp->name, $this->x->index);
break;
case self::ACCEPT:
fprintf($fp, "%${indent}s accept", $this->sp->name);
fprintf($fp, "%{$indent}s accept", $this->sp->name);
break;
case self::ERROR:
fprintf($fp, "%${indent}s error", $this->sp->name);
fprintf($fp, "%{$indent}s error", $this->sp->name);
break;
case self::CONFLICT:
fprintf($fp, "%${indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index);
fprintf($fp, "%{$indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index);
break;
case self::SH_RESOLVED:
case self::RD_RESOLVED:

View File

@@ -170,7 +170,7 @@ class ormCaseLog {
}
// Process the case of an eventual remainder (quick migration of AttributeText fields)
if ($iPos < (strlen($this->m_sLog) - 1))
if ($iPos < (utils::StrLen($this->m_sLog) - 1))
{
$sTextEntry = substr($this->m_sLog, $iPos);
@@ -293,7 +293,7 @@ class ormCaseLog {
}
// Process the case of an eventual remainder (quick migration of AttributeText fields)
if ($iPos < (strlen($this->m_sLog) - 1)) {
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
$sTextEntry = substr($this->m_sLog, $iPos);
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
@@ -374,7 +374,7 @@ class ormCaseLog {
}
// Process the case of an eventual remainder (quick migration of AttributeText fields)
if ($iPos < (strlen($this->m_sLog) - 1)) {
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
$sTextEntry = substr($this->m_sLog, $iPos);
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
@@ -468,7 +468,7 @@ class ormCaseLog {
$oBlock->AddSubBlock($oCollapsibleBlock);
}
// Process the case of an eventual remainder (quick migration of AttributeText fields)
if ($iPos < (strlen($this->m_sLog) - 1)) {
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
// In this case the format is always "text"
$sTextEntry = substr($this->m_sLog, $iPos);
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
@@ -516,7 +516,7 @@ class ormCaseLog {
$sScript = '<script src="'.$sFileAbsUrl.'"></></script>';
$sHtml .= $sScript;
} else {
$oP->add_linked_script($sFileAbsUrl);
$oP->LinkScriptFromURI($sFileAbsUrl);
}
}
}

View File

@@ -344,6 +344,6 @@ class ormDocument
*/
public function GetSignature(): string
{
return md5($this->GetData());
return md5($this->GetData() ?? '');
}
}

View File

@@ -217,7 +217,7 @@ class ormStopWatch
}
else
{
$aProperties['Elapsed'] = 'running <img src="../images/indicator.gif">';
$aProperties['Elapsed'] = 'running <img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/indicator.gif">';
}
$aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted);

View File

@@ -53,9 +53,10 @@ abstract class Trigger extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags, true), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12)));
// "complement" is a computed field, fed by Trigger sub-classes, in general in ComputeValues method, for eg. the TriggerOnObject fed it with target_class info
MetaModel::Init_AddAttribute(new AttributeString("complement", array("allowed_values" => null, "sql" => "complement", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", array("allowed_values" => new ValueSetEnum(Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::cases()), "sql" => "subscription_policy", "default_value" => \Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::AllowNoChannel->value, "is_null_allowed" => false, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'action_list', 'complement')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'subscription_policy', 'action_list', 'complement')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'complement')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
@@ -111,19 +112,31 @@ abstract class Trigger extends cmdbAbstractObject
return;
}
$aContextArgs['trigger->object()'] = $this;
// Find the related actions
$oLinkedActions = $this->Get('action_list');
while ($oLink = $oLinkedActions->Fetch())
{
/** @var \DBObject $oLink */
$iActionId = $oLink->Get('action_id');
/** @var \Action $oAction */
$oAction = MetaModel::GetObject('Action', $iActionId);
if ($oAction->IsActive())
{
$oKPI = new ExecutionKPI();
$oAction->DoExecute($this, $aContextArgs);
$oKPI->ComputeStatsForExtension($oAction, 'DoExecute');
// Order actions as expected
$aActionListOrdered = [];
while ($oLink = $oLinkedActions->Fetch()) {
$aActionListOrdered[(int) $oLink->Get('order')][] = $oLink;
}
ksort($aActionListOrdered);
// Execute actions
foreach ($aActionListOrdered as $aActionSubList) {
foreach ($aActionSubList as $oLink) /** @var \DBObject $oLink */ {
/** @var \DBObject $oLink */
$iActionId = $oLink->Get('action_id');
/** @var \Action $oAction */
$oAction = MetaModel::GetObject('Action', $iActionId);
if ($oAction->IsActive()) {
$oKPI = new ExecutionKPI();
$aContextArgs['action->object()'] = $oAction;
$oAction->DoExecute($this, $aContextArgs);
$oKPI->ComputeStatsForExtension($oAction, 'DoExecute');
}
}
}
}
@@ -172,7 +185,7 @@ abstract class TriggerOnObject extends Trigger
MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('default_search', array('description', 'target_class')); // Default criteria of the search banner
@@ -372,7 +385,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
// Search criteria
}
@@ -405,7 +418,7 @@ abstract class TriggerOnStateChange extends TriggerOnObject
MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('target_class'))));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
@@ -438,7 +451,7 @@ class TriggerOnStateEnter extends TriggerOnStateChange
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
@@ -471,7 +484,7 @@ class TriggerOnStateLeave extends TriggerOnStateChange
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
@@ -504,7 +517,7 @@ class TriggerOnObjectCreate extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -537,7 +550,7 @@ class TriggerOnObjectDelete extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -572,7 +585,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', array("allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => array('target_class'))));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -668,7 +681,7 @@ class TriggerOnObjectMention extends TriggerOnObject
MetaModel::Init_AddAttribute(new AttributeOQL("mentioned_filter", array("allowed_values" => null, "sql" => "mentioned_filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'mentioned_filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'mentioned_filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -827,7 +840,7 @@ class TriggerOnThresholdReached extends TriggerOnObject
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'threshold_index', 'threshold_index')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form

View File

@@ -162,7 +162,7 @@ abstract class UserRightsAddOnAPI
$oSearchSharers->AllowAllData();
$oSearchSharers->AddCondition_ReferencedBy($oShareSearch, 'sharing_org_id');
$aSharers = array();
foreach($oSearchSharers->ToDataArray(array('id')) as $aRow)
foreach($oSearchSharers->SelectAttributeToArray('id') as $aRow)
{
$aSharers[] = $aRow['id'];
}
@@ -187,7 +187,7 @@ abstract class UserRightsAddOnAPI
$oOrgField = new FieldExpression('org_id', $sShareClass);
$oSearchShares->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr));
$aShared = array();
foreach($oSearchShares->ToDataArray(array($sShareAttCode)) as $aRow)
foreach($oSearchShares->SelectAttributeToArray($sShareAttCode) as $aRow)
{
$aShared[] = $aRow[$sShareAttCode];
}

View File

@@ -476,6 +476,7 @@ class ValueSetEnum extends ValueSetDefinition
* @param bool $bLocalizedSort
*
* @since 3.1.0 N°1646 Add $bLocalizedSort parameter
* @since 3.2.0 N°7157 $Values can be an array of backed-enum cases
*/
public function __construct($Values, bool $bSortByValues = false)
{
@@ -523,13 +524,21 @@ class ValueSetEnum extends ValueSetDefinition
*/
protected function LoadValues($aArgs)
{
$aValues = [];
if (is_array($this->m_values))
{
$aValues = $this->m_values;
foreach ($this->m_values as $key => $value) {
// Handle backed-enum case
if (is_object($value) && enum_exists(get_class($value))) {
$aValues[$value->value] = $value->value;
continue;
}
$aValues[$key] = $value;
}
}
elseif (is_string($this->m_values) && strlen($this->m_values) > 0)
{
$aValues = array();
foreach (explode(",", $this->m_values) as $sVal)
{
$sVal = trim($sVal);
@@ -539,7 +548,7 @@ class ValueSetEnum extends ValueSetDefinition
}
else
{
$aValues = array();
$aValues = [];
}
$this->m_aValues = $aValues;
return true;

View File

@@ -49,3 +49,63 @@
.ibo-navigation-menu.ibo-is-active .ibo-navigation-menu--drawer{
transform: translate3d(0,0,0);
}
// Toggler legacy CSS that has somehow been added to iTop 3.0 and that is now used by some extensions
// Round Toggle
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
vertical-align: baseline;
}
/* Hide default HTML checkbox */
.switch input {
display: none;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: $ibo-color-secondary-600;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 3px;
bottom: 3px;
background-color: $ibo-color-secondary-300;
transition: .4s;
}
input:checked + .slider {
background-color: $ibo-color-primary-600;
}
input:focus + .slider {
box-shadow: 0 0 1px $ibo-color-primary-600;
}
input:checked + .slider:before {
transform: translateX(14.5px);
}
/* Rounded sliders */
.slider.round {
border-radius: 20px;
}
.slider.round:before {
border-radius: 7px;
}

View File

@@ -11,10 +11,6 @@ $ibo-scrollbar--scrollbar-thumb-background-color: $ibo-color-grey-300 !default;
$ibo-scrollbar--scrollbar-thumb-border: none !default;
$ibo-scrollbar--scrollbar-thumb-border-radius: $ibo-border-radius-500 !default;
$ibo-hyperlink-color: $ibo-color-primary-700 !default;
$ibo-hyperlink-color--on-hover: $ibo-color-primary-800 !default;
$ibo-hyperlink-color--on-active: $ibo-color-primary-900 !default;
$ibo-svg-illustration--fill: $ibo-color-primary-500 !default;
$ibo-content-block--background-color: $ibo-color-white-100 !default;
@@ -29,10 +25,6 @@ $ibo-content-block--border: 1px solid $ibo-color-grey-400 !default;
--ibo-scrollbar--scrollbar-thumb-background-color: #{$ibo-scrollbar--scrollbar-thumb-background-color};
--ibo-scrollbar--scrollbar-thumb-border: #{$ibo-scrollbar--scrollbar-thumb-border};
--ibo-scrollbar--scrollbar-thumb-border-radius: #{$ibo-scrollbar--scrollbar-thumb-border-radius};
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
--ibo-hyperlink-color--on-hover: #{$ibo-hyperlink-color--on-hover};
--ibo-hyperlink-color--on-active: #{$ibo-hyperlink-color--on-active};
}
/* Box sizing reset */
@@ -73,17 +65,19 @@ html{
/* Hyperlinks reset, ensure that they are of the right color and without decoration everywhere (of course this can be overloaded in some components) */
a{
color: var(--ibo-hyperlink-color);
text-decoration: none;
text-decoration: var(--ibo-hyperlink-text-decoration);
&:hover,
&:active,
&:visited{
text-decoration: none;
text-decoration: var(--ibo-hyperlink-text-decoration);
}
&:hover{
color: var(--ibo-hyperlink-color--on-hover);
text-decoration: var(--ibo-hyperlink-text-decoration--on-hover);
}
&:active{
color: var(--ibo-hyperlink-color--on-active);
text-decoration: var(--ibo-hyperlink-text-decoration--on-active);
}
}

View File

@@ -41,7 +41,7 @@ $ibo-alert-colors: (
$bg-color: nth($aColorValues, 1);
$highlight-color: nth($aColorValues, 2);
$text-color: nth($aColorValues, 3);
.ibo-alert.ibo-is-#{$sColor} {
%ibo-alert-#{$sColor}, .ibo-alert.ibo-is-#{$sColor} {
background-color: $bg-color;
color: $text-color;
a {

View File

@@ -32,4 +32,5 @@
@import "search-form";
@import "field-badge";
@import "file-select";
@import "medallion-icon";
@import "medallion-icon";
@import "toast";

View File

@@ -80,16 +80,29 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
}
}
}
/*N°6543 - We need the rule to keep text inside the column when width is defined*/
&[data-attribute-type="AttributeHtml"],
&[data-attribute-type="AttributeText"] {
&[data-attribute-flag-read-only="true"] {
display: grid;
> .ibo-field--value {
max-width: 100%;
overflow: auto;
}
}
}
}
/* Large field = Label on top, value below */
.ibo-field-large {
display: block;
/* Large field = Label on top, value below */
.ibo-field-large {
display: block;
.ibo-field--label {
position: relative; /* Necessary for fullscreen toggler */
display: flex;
align-items: center;
.ibo-field--label {
position: relative; /* Necessary for fullscreen toggler */
display: flex;
align-items: center;
max-width: initial;
width: 100%;
}

View File

@@ -19,9 +19,19 @@ $ibo-navigation-menu--notifications--item--content--padding-x: 14px !default;
$ibo-navigation-menu--notifications--item--content--img--max-height: 100px !default;
$ibo-navigation-menu--notifications--item--content--img--padding: 5px !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--width: 10px !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--height: 10px !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-blue-500 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--width: 13px !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--height: 13px !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-red-100 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-red-500 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-orange-100 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-orange-500 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-blue-100 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-blue-500 !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--background-color !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--border: $ibo-navigation-menu--notifications--item--new-message-indicator--border !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--border-radius: $ibo-border-radius-full !default;
$ibo-navigation-menu--notifications--item--new-message-indicator--margin-top: $ibo-spacing-200 !default;
@@ -36,31 +46,30 @@ $ibo-popover-menu--item--no-message--image--svg--padding : 15px !default;
#ibo-navigation-menu--notifications-menu {
flex-flow: column;
min-width: $ibo-navigation-menu--notifications-menu--min-width;
.ibo-navigation-menu--notifications--messages-section{
.ibo-navigation-menu--notifications--messages-section {
overflow: auto;
}
}
.ibo-navigation-menu--notifications--show-all-messages, .ibo-navigation-menu--notifications-dismiss-all, .ibo-navigation-menu--notifications-show-all-multiple{
.ibo-navigation-menu--notifications--show-all-messages, .ibo-navigation-menu--notifications-dismiss-all, .ibo-navigation-menu--notifications-show-all-multiple {
overflow-x: inherit;
text-align: center;
min-height: 45px;
}
.ibo-navigation-menu--notifications--item--image{
.ibo-navigation-menu--notifications--item--image {
max-width: $ibo-navigation-menu--notifications--item--image--max-width;
max-height: $ibo-navigation-menu--notifications--item--image--max-height;
margin: $ibo-navigation-menu--notifications--item--image--margin-y $ibo-navigation-menu--notifications--item--image--margin-x;
border-radius: $ibo-navigation-menu--notifications--item--image--border-radius;
}
img.ibo-navigation-menu--notifications--item--image[src=""]{
.ibo-navigation-menu--notifications--item--image[src=""] {
display: none;
}
img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-navigation-menu--notifications--item--image
{
.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ .ibo-navigation-menu--notifications--item--image {
display: none;
}
.ibo-navigation-menu--notifications--item--bottom-text{
.ibo-navigation-menu--notifications--item--bottom-text {
display: flex;
flex-direction: column;
align-items: center;
@@ -68,41 +77,63 @@ img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-naviga
align-self: center;
margin-left: $ibo-navigation-menu--notifications--item--bottom-text--margin-left;
}
.ibo-navigation-menu--notifications--item--content{
.ibo-navigation-menu--notifications--item--content {
padding: $ibo-navigation-menu--notifications--item--content--padding-y $ibo-navigation-menu--notifications--item--content--padding-x;
img{
img {
max-height: $ibo-navigation-menu--notifications--item--content--img--max-height;
padding: $ibo-navigation-menu--notifications--item--content--img--padding;
}
}
.ibo-navigation-menu--notifications-item{
.ibo-navigation-menu--notifications-item {
display: flex;
flex-direction: row;
.ibo-navigation-menu--notifications--item--content a {
@extend %ibo-hyperlink-forced-colors;
}
}
.ibo-navigation-menu--notifications--item--new-message-indicator{
.ibo-navigation-menu--notifications--item--new-message-indicator {
width: $ibo-navigation-menu--notifications--item--new-message-indicator--width;
height: $ibo-navigation-menu--notifications--item--new-message-indicator--height;
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--background-color;
border: $ibo-navigation-menu--notifications--item--new-message-indicator--border;
border-radius: $ibo-navigation-menu--notifications--item--new-message-indicator--border-radius;
margin-top: $ibo-navigation-menu--notifications--item--new-message-indicator--margin-top;
&.ibo-is-priority-1{
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color;
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border;
}
&.ibo-is-priority-2{
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color;
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border;
}
&.ibo-is-priority-3{
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color;
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border;
}
&.ibo-is-priority-4{
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--background-color;
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--border;
}
}
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu{
.ibo-navigation-menu--notifications--item--new-message-indicator{
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu {
.ibo-navigation-menu--notifications--item--new-message-indicator {
display: inline-block;
margin-right: $ibo-navigation-menu--notifications-show-all-multiple--ibo-popover-menu--indicator--margin-right;
}
.ibo-navigation-menu--notifications-show-all-multiple--counter{
.ibo-navigation-menu--notifications-show-all-multiple--counter {
@extend %ibo-font-weight-600;
}
}
.ibo-navigation-menu--notifications-dismiss-all--icon{
.ibo-navigation-menu--notifications-dismiss-all--icon {
margin: $ibo-navigation-menu--notifications-dismiss-all--icon--margin;
}
.ibo-popover-menu--item--no-message{
.ibo-popover-menu--item--no-message {
text-align: center;
}
.ibo-popover-menu--item--no-message--image>svg{
.ibo-popover-menu--item--no-message--image > svg {
display: flex;
width: $ibo-popover-menu--item--no-message--image--svg--width;
height: $ibo-popover-menu--item--no-message--image--svg--height;

View File

@@ -85,6 +85,9 @@ $ibo-panel--collapsible-toggler--margin-right: $ibo-spacing-300 !default;
$ibo-panel--collapsible-toggler--font-size: $ibo-font-size-250 !default;
$ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
$ibo-panel--is-selectable--body--after--z-index: $ibo-panel--header--z-index + 1 !default;
$ibo-panel--is-selectable--body--after--font-size: $ibo-font-size-700 !default;
/* Rules */
.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 */
@@ -128,6 +131,30 @@ $ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
}
}
}
&.ibo-is-selectable .ibo-panel--body::after {
@include ibo-selectable;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
z-index: $ibo-panel--is-selectable--body--after--z-index;
font-size: $ibo-panel--is-selectable--body--after--font-size;
}
&.ibo-is-selectable:hover .ibo-panel--body::after {
@include ibo-selectable-hover;
display: flex;
}
&.ibo-is-selected .ibo-panel--body::after {
@include ibo-selected;
display: flex;
}
&.ibo-is-selected:hover .ibo-panel--body::after {
@include ibo-selected-hover;
display: flex;
}
}
.ibo-panel--header {

View File

@@ -0,0 +1,62 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/* SCSS variables */
$ibo-toast--padding-y: $ibo-spacing-400 !default;
$ibo-toast--padding-right: $ibo-spacing-300 !default;
$ibo-toast--padding-left: $ibo-spacing-500 !default;
$ibo-toast--border-radius: $ibo-border-radius-300 !default;
$ibo-toast--box-shadow: $ibo-elevation-200 !default;
$ibo-toast--max-width: calc(50% - 20px) !default;
@keyframes decreaseHighlight {
0% {
height: 100%;
}
8%{
border-radius: 0 0 0 3px;
}
100% {
height: 0;
}
}
.ibo-toast {
display: inline-flex;
position: fixed;
align-items: center;
max-width: $ibo-toast--max-width ;
padding: $ibo-toast--padding-y $ibo-toast--padding-right $ibo-toast--padding-y $ibo-toast--padding-left;
border-radius: $ibo-toast--border-radius;
box-shadow: $ibo-toast--box-shadow;
transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
z-index: 2147483647;
&::before {
@include ibo-vertical-highlight;
top: initial;
bottom: 0;
border-radius: $ibo-toast--border-radius 0 0 $ibo-toast--border-radius;
}
&.ibo-is-auto-closeable::before{
animation: decreaseHighlight 5s linear forwards;
}
&:hover::before {
animation: none; /* Pause animation on hover */
}
&.ibo-is-error{
@extend %ibo-alert-danger;
}
&.ibo-is-warning{
@extend %ibo-alert-warning;
}
&.ibo-is-success{
@extend %ibo-alert-success;
}
&.ibo-is-information{
@extend %ibo-alert-information;
}
}

View File

@@ -123,6 +123,13 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
.ibo-datatable--row-actions-toolbar{
justify-content: end;
}
/* N°6543 - We need the rule to keep text inside the column when width is defined */
> [data-attribute-type="AttributeHtml"],
> [data-attribute-type="AttributeText"] {
max-width: 100%;
overflow: auto;
}
}
}

View File

@@ -22,6 +22,9 @@ $ibo-datatableconfig--settings-panel--option--margin-right: $ibo-spacing-200 !de
}
.ibo-datatableconfig--attributes-panel--per-page--input{
margin: $ibo-datatableconfig--attributes-panel--per-page--input--margin-y $ibo-datatableconfig--attributes-panel--per-page--input--margin-x;
max-width: 4em;
@extend .ibo-input;
display: initial;
}
.ibo-datatableconfig--settings-panel .ibo-panel--body{

View File

@@ -16,3 +16,4 @@
@import "input-one-way-password";
@import "input-set";
@import "input-text";
@import "input-toggler";

View File

@@ -49,10 +49,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
.ibo-input-select {
display: inline-flex;
min-width: $ibo-input-select--value--min-midth;
&:not(.ibo-input-select-autocomplete):not(.ibo-input-selectize) {
appearance: none;
}
appearance: none;
&.ibo-input-selectize {
padding-right: 0;
@@ -108,7 +105,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
outline: none !important; /* Overwrite browsers default focus outline */
}
}
&.input-active{
border: 1px solid $ibo-input--focus--border-color;
}
@@ -123,15 +120,16 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
}
.ibo-input-select-wrapper::after{
position: absolute;
z-index: 1;
content: "\f0d7";
font-family: "Font Awesome 5 Free";
font-weight: 600;
height: $ibo-input-select-wrapper--after--height;
margin-left: $ibo-input-select-wrapper--after--margin-left;
margin-top: $ibo-input-select-wrapper--after--margin-top;
padding-top: $ibo-input-select-wrapper--after--padding-top;
background-color: $ibo-input-select-wrapper--after--background-color;
color: $ibo-input-select-wrapper--after--color;
pointer-events: none;
@@ -146,6 +144,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
.ibo-input-select-wrapper--with-buttons:not(.ibo-input-select-autocomplete-wrapper)::after {
position: absolute;
z-index: 1;
content: "\f0d7";
font-family: "Font Awesome 5 Free";
font-weight: 600;
@@ -163,6 +162,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
}
.ibo-input-select--action-buttons{
position: absolute;
z-index: 1;
display: flex;
height: $ibo-input-select--action-button--height;
margin-top: $ibo-input-select--action-button--margin-top;
@@ -224,7 +224,11 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
margin-right: $ibo-input-select--autocomplete-item-image--margin-right;
background-color: $ibo-input-select--autocomplete-item-image--background-color;
border: $ibo-input-select--autocomplete-item-image--border;
&.ibo-is-not-medallion{
border: unset;
border-radius: 0;
background-color: unset;
}
@extend %ibo-fully-centered-content;
}

View File

@@ -0,0 +1,72 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-toggler--wrapper--width: 36px !default;
$ibo-toggler--wrapper--height: 20px !default;
$ibo-toggler--slider--border-radius: $ibo-border-radius-900 !default;
$ibo-toggler--slider--background-color: $ibo-color-secondary-600 !default;
$ibo-toggler--slider--before--height: 15px !default;
$ibo-toggler--slider--before--width: 15px !default;
$ibo-toggler--slider--before--border-radius: $ibo-border-radius-full !default;
$ibo-toggler--slider--before--background-color: $ibo-color-grey-100 !default;
$ibo-toggler--slider--checked--background-color: $ibo-color-primary-600 !default;
$ibo-toggler--slider--focus--box-shadow: 0 0 1px $ibo-color-primary-600 !default;
$ibo-toggler--label--margin-left: 4px !default;
.ibo-toggler--wrapper {
position: relative;
display: inline-block;
width: $ibo-toggler--wrapper--width;
height: $ibo-toggler--wrapper--height;
vertical-align: baseline;
.ibo-toggler {
display: none;
}
}
.ibo-toggler--slider{
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: $ibo-toggler--slider--border-radius;
background-color: $ibo-toggler--slider--background-color;
transition: .4s;
}
.ibo-toggler--slider:before {
content: "";
position: absolute;
left: 3px;
bottom: 3px;
height: $ibo-toggler--slider--before--height;
width: $ibo-toggler--slider--before--width;
border-radius: $ibo-toggler--slider--before--border-radius;
background-color: $ibo-toggler--slider--before--background-color;
transition: .4s;
}
.ibo-toggler--wrapper input:checked + .ibo-toggler--slider {
background-color: $ibo-toggler--slider--checked--background-color;
}
input:focus + .ibo-toggler--slider {
box-shadow: $ibo-toggler--slider--focus--box-shadow;
}
input:checked + .ibo-toggler--slider:before {
transform: translateX(14.5px);
}
label ~ .ibo-toggler--wrapper {
margin-left: $ibo-toggler--label--margin-left;
}

View File

@@ -8,7 +8,11 @@ $ibo-input--width: 100% !default;
$ibo-input--color: $ibo-color-grey-900 !default;
$ibo-input--background-color: $ibo-color-white-100 !default;
$ibo-input--border-color: $ibo-color-grey-500 !default;
$ibo-input--border-size: 1px !default;
$ibo-input--border-style: solid !default;
$ibo-input--border: $ibo-input--border-size $ibo-input--border-style $ibo-input--border-color !default;
$ibo-input--padding-x: 10px !default;
$ibo-input--padding-y: $ibo-spacing-0 !default;
@@ -34,13 +38,13 @@ $ibo-input--margin-x: $ibo-spacing-200 !default;
background-color: $ibo-input--background-color;
color: $ibo-input--color;
padding: $ibo-input--padding-y $ibo-input--padding-x;
border: 1px solid $ibo-input--border-color;
border: $ibo-input--border;
border-radius: $ibo-input--border-radius;
@extend %ibo-font-ral-nor-150;
&:focus{
border: 1px solid $ibo-input--focus--border-color;
border-color: $ibo-input--focus--border-color;
}
&:disabled{
background-color: $ibo-input--disabled--background-color;
@@ -54,8 +58,8 @@ textarea.ibo-input{
height:unset;
}
.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;
.ibo-input, .ibo-input-vanilla, .ck-editor, textarea {
border-color: $ibo-input-wrapper--is-error--border-color;
}
.ibo-input-vanilla input{
border: 0;

View File

@@ -62,63 +62,4 @@ $ibo-top-bar--toolbar-dashboard-title--max-width: 350px !default;
@extend %ibo-full-height-content;
display: flex;
align-items: center;
}
// Round Toggle
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
vertical-align: baseline;
}
/* Hide default HTML checkbox */
.switch input {
display: none;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: $ibo-color-secondary-600;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 3px;
bottom: 3px;
background-color: $ibo-color-secondary-300;
transition: .4s;
}
input:checked + .slider {
background-color: $ibo-color-primary-600;
}
input:focus + .slider {
box-shadow: 0 0 1px $ibo-color-primary-600;
}
input:checked + .slider:before {
transform: translateX(14.5px);
}
/* Rounded sliders */
.slider.round {
border-radius: 20px;
}
.slider.round:before {
border-radius: 7px;
}
}

View File

@@ -83,6 +83,7 @@ $ibo-object-details--header-right--padding-right--is-sticking: $ibo-spacing-300
.ibo-object-details--status + .ibo-object-details--object-class {
margin-left: 0.5rem;
display: inline-flex; /* To avoid having spaces around the class name due to the indentation */
&::before {
content: "(";

View File

@@ -3,7 +3,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-object-summary--header--margin-y: $ibo-panel--highlight--height!default;
$ibo-object-summary--header--margin-top: $ibo-panel--highlight--height!default;
$ibo-object-summary--header--margin-bottom: $ibo-spacing-0!default;
$ibo-object-summary--header--margin-x: $ibo-spacing-0 !default;
$ibo-object-summary--header--padding-y: $ibo-spacing-300 !default;
@@ -51,7 +52,7 @@ $ibo-object-summary--content--attributes--code--padding-right: $ibo-spacing-500
}
.ibo-object-summary--header{
margin: $ibo-object-summary--header--margin-y $ibo-object-summary--header--margin-x;
margin: $ibo-object-summary--header--margin-top $ibo-object-summary--header--margin-x $ibo-object-summary--header--margin-bottom $ibo-object-summary--header--margin-x;
padding: $ibo-object-summary--header--padding-y $ibo-object-summary--header--padding-x;
background-color: $ibo-object-summary--header--background-color;
border-bottom: $ibo-object-summary--header--border;

View File

@@ -15,4 +15,6 @@
@import "global-search";
@import "run-query";
@import "welcome-popup";
@import "oauth.wizard";
@import "oauth.wizard";
@import "notifications";
@import "notifications-center";

View File

@@ -0,0 +1,18 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-select--notification-item--mixed-value--color: $ibo-color-primary-800 !default;
$ibo-input-select--notification-item--mixed-value--margin-left: 4px !default;
.ibo-input-select--notification-item {
display: flex !important; // override selectize default display with a stronger rule
flex-direction: row;
@extend .ibo-input-select--autocomplete-item
}
.ibo-input-select--notification-item--mixed-value{
font-size: $ibo-font-size-100;
color: $ibo-input-select--notification-item--mixed-value--color;
margin-left: $ibo-input-select--notification-item--mixed-value--margin-left;
}

View File

@@ -0,0 +1,82 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-notifications--view-all--container--grid-gap: $ibo-spacing-600 !default;
$ibo-notifications--view-all--container--object-summary--panel--body--max-height: unset !default;
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-red-600 !default;
$ibo-notifications--view-all--item--read--highlight--background-color: $ibo-color-grey-200 !default;
$ibo-notifications--view-all--container--large--grid-template-columns: repeat(3, 1fr) !default;
$ibo-notifications--view-all--container--medium--grid-template-columns: repeat(2, 1fr) !default;
$ibo-notifications--view-all--container--small--grid-template-columns: repeat(1, 1fr) !default;
$ibo-notifications--view-all--empty--margin-top: $ibo-spacing-950 !default;
$ibo-notifications--view-all--empty--svg--max-width: 30% !default;
.ibo-notifications--view-all--container{
display: grid;
grid-gap: $ibo-notifications--view-all--container--grid-gap;
.ibo-object-summary .ibo-panel--title{
font-size: $ibo-font-size-250;
}
.ibo-object-summary .ibo-panel--toolbar{
min-width: 102px;
}
.ibo-object-summary > .ibo-panel--body{
box-shadow: none;
max-height: $ibo-notifications--view-all--container--object-summary--panel--body--max-height;
}
.ibo-object-summary + .ibo-object-summary{
margin-top: 0;
}
@include mobile {
grid-template-columns: $ibo-notifications--view-all--container--small--grid-template-columns;
}
@include desktop {
grid-template-columns: $ibo-notifications--view-all--container--medium--grid-template-columns;
}
@include fullhd {
grid-template-columns: $ibo-notifications--view-all--container--large--grid-template-columns; }
}
.ibo-notifications--view-all--toolbar {
justify-content: space-between;
}
.ibo-notifications--view-all--toggler {
display: flex;
align-content: center;
}
.ibo-notifications--view-all--item--read .ibo-panel--body::before{
background-color: $ibo-notifications--view-all--item--read--highlight--background-color;
}
.ibo-notifications--view-all--item--unread .ibo-panel--body::before{
background-color: $ibo-notifications--view-all--item--unread--highlight--background-color;
}
.ibo-notifications--view-all--container {
.ibo-notifications--view-all--read-action, .ibo-notifications--view-all--unread-action {
margin-left: 0 !important;
}
}
.ibo-notifications--view-all--item--read .ibo-notifications--view-all--read-action {
display: none;
}
.ibo-notifications--view-all--item--unread .ibo-notifications--view-all--unread-action {
display: none;
}
.ibo-notifications--view-all--empty {
@extend %ibo-fully-centered-content;
flex-direction: column;
margin-top: $ibo-notifications--view-all--empty--margin-top;
svg {
max-width: $ibo-notifications--view-all--empty--svg--max-width;
height: auto;
}
}

View File

@@ -12,6 +12,23 @@ $ibo-has-description--font-size: 0.7em !default; /* Font size is em on purpose a
$ibo-is-code--background-color: $ibo-color-white-200 !default;
$ibo-is-code--padding: 1.25rem 1.5rem !default;
$ibo-hyperlink-color: $ibo-color-primary-700 !default;
$ibo-hyperlink-text-decoration: none !default;
$ibo-hyperlink-color--on-hover: $ibo-color-primary-800 !default;
$ibo-hyperlink-text-decoration--on-hover: $ibo-hyperlink-text-decoration !default;
$ibo-hyperlink-color--on-active: $ibo-color-primary-900 !default;
$ibo-hyperlink-text-decoration--on-active: $ibo-hyperlink-text-decoration !default;
/* CSS variables */
:root{
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
--ibo-hyperlink-text-decoration: #{$ibo-hyperlink-text-decoration};
--ibo-hyperlink-color--on-hover: #{$ibo-hyperlink-color--on-hover};
--ibo-hyperlink-text-decoration--on-hover: #{$ibo-hyperlink-text-decoration--on-hover};
--ibo-hyperlink-color--on-active: #{$ibo-hyperlink-color--on-active};
--ibo-hyperlink-text-decoration--on-active: #{$ibo-hyperlink-text-decoration--on-active};
}
/* Rules */
%ibo-text-truncated-with-ellipsis {
white-space: nowrap;
@@ -32,6 +49,20 @@ $ibo-is-code--padding: 1.25rem 1.5rem !default;
color: inherit;
}
}
/* Use this when you want the hyperlink to be of the color of its container's text instead of the global hyperlink color */
%ibo-hyperlink-forced-colors {
color: $ibo-hyperlink-color;
text-decoration: $ibo-hyperlink-text-decoration;
&:hover {
color: $ibo-hyperlink-color--on-hover;
text-decoration: $ibo-hyperlink-text-decoration--on-hover;
}
&:active {
color: $ibo-hyperlink-color--on-active;
text-decoration: $ibo-hyperlink-text-decoration--on-active;
}
}
.ibo-is-broken-hyperlink {
text-decoration: line-through;

View File

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

View File

@@ -0,0 +1,40 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-selectable--background-color: transparent !default;
$ibo-selectable--hover--color: $ibo-color-grey-100 !default;
$ibo-selectable--hover--background-color: $ibo-color-grey-600 !default;
$ibo-selectable--hover--background-opacity: 0.6 !default;
$ibo-selected--color: $ibo-color-grey-100 !default;
$ibo-selected--background-color: $ibo-color-grey-900 !default;
$ibo-selected--background-opacity: 0.5 !default;
$ibo-selected--hover--background-color: $ibo-color-grey-700 !default;
$ibo-selected--hover--background-opacity: 0.5 !default;
@mixin ibo-selectable {
content: ' ';
@extend %fa-solid-base;
background-color: $ibo-selectable--background-color;
cursor: pointer;
}
@mixin ibo-selectable-hover {
@extend %fa-regular-base;
content: '\f058';
color: $ibo-selectable--hover--color;
background-color: transparentize($ibo-selectable--hover--background-color, $ibo-selectable--hover--background-opacity);
}
@mixin ibo-selected {
@extend %fa-solid-base;
content: '\f058';
color: $ibo-selected--color;
background-color: transparentize($ibo-selected--background-color, $ibo-selected--background-opacity);
}
@mixin ibo-selected-hover {
background-color: transparentize($ibo-selected--hover--background-color, $ibo-selected--hover--background-opacity);
}

View File

@@ -13,6 +13,7 @@ $ibo-spacing-600: $ibo-size-300 !default;
$ibo-spacing-700: $ibo-size-350 !default;
$ibo-spacing-800: $ibo-size-400 !default;
$ibo-spacing-900: $ibo-size-450 !default;
$ibo-spacing-950: $ibo-size-500 !default;
:root{
--ibo-spacing-0: #{$ibo-size-0};

View File

@@ -15,6 +15,9 @@ $ibo-font-size-400: 2rem !default; /* 24px */
$ibo-font-size-450: 2.5rem !default; /* 30px */
$ibo-font-size-500: 3rem !default; /* 36px */
$ibo-font-size-550: 4rem !default; /* 48px */
$ibo-font-size-600: 5rem !default; /* 60px */
$ibo-font-size-650: 6rem !default; /* 72px */
$ibo-font-size-700: 7rem !default; /* 84px */
/* Value Common weight name (https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) */
$ibo-font-weight-100: 100 !default; /* 100 Thin (Harline) */

View File

@@ -17,4 +17,5 @@
@import "jquery-treeview";
@import "jquery-blockui";
@import "magnific-popup";
@import "selectize";
@import "selectize";
@import "toastify";

View File

@@ -22,6 +22,10 @@ $ibo-vendors-ckeditor--autocomplete-item-image--border: 1px solid $ibo-color-gre
$ibo-vendors-ckeditor--autocomplete-item-title--text-color: #3A3A3A !default;
.ck-editor__editable_inline:not(.ck-comment__input *) {
min-height: 200px;
}
/* Fullscreen button (Combodo custom) */
.ibo-vendors-ckeditor--toolbar-fullscreen-button {
display: none;

View File

@@ -21,82 +21,87 @@ $ibo-vendors-selectize--item--ignore-partial--background-color: $ibo-color-grey-
$ibo-vendors-selectize--input-error--border: 1px solid $ibo-color-red-600 !default;
.selectize-dropdown-content {
max-height: unset; /* Overloaded as it will be handled by the _input-select.scss partial */
}
.selectize-input input{
color: $ibo-vendors-selectize-input--color;
.selectize-control.single .selectize-input {
box-shadow: unset;
background-color: unset;
background-image: unset;
background-repeat: unset;
}
.selectize-input,
.selectize-control.single .selectize-input.input-active {
background: unset;
cursor: text;
display: inline-flex;
}
.selectize-control.plugin-combodo_add_button{
display: flex;
.selectize-control.single .selectize-input.dropdown-active:after {
margin-top: unset;
border-width: unset;
border-color: unset;
}
.selectize-control.single .selectize-input:after {
content: unset;
}
.selectize-input::after {
content: unset;
}
.selectize-add-option {
display: inline-flex;
justify-content: center;
align-items: center;
position: absolute;
right: $ibo-vendors-selectize-control--plugin-add-button--add-option--right;
height: $ibo-vendors-selectize-control--plugin-add-button--add-option--height;
width: $ibo-vendors-selectize-control--plugin-add-button--add-option--width;
z-index: 1;
color: $ibo-vendors-selectize-control--plugin-add-button--add-option--color;
@extend %ibo-font-size-100;
.selectize-input>* {
display: inline-flex;
}
.selectize-control.single .selectize-input, .selectize-dropdown.single {
border-color: $ibo-color-grey-500;
}
.selectize-dropdown {
.selected,
.active,
.active:not(.selected){
background: #f5fafd;
color: #495c68;
}
[data-selectable],
.optgroup-header {
padding: 5px 8px;
}
.option {
opacity: 1;
}
}
// Simple options renderer
.simple-option-renderer--container {
display: flex;
align-items: center;
}
.simple-option-renderer--container--icon {
width: 25px;
text-align: center;
}
.simple-option-renderer--container--label {
margin-left: 3px;
flex-grow: 1;
}
.selectize-input{
.attribute-set-item{
>* {
// Bulk modification: add / remove / partial items states
.selectize-input {
.attribute-set-item {
> * {
display: inline;
}
&.item-add::before,&.item-remove::before{
&.item-add::before,&.item-remove::before {
@extend %fa-solid-base;
margin-right: $ibo-vendors-selectize--item--icon--margin-right;
}
&.item-add{
&.item-add {
background-color: $ibo-vendors-selectize--item--add--background-color !important;
&::before{
&::before {
color: $ibo-vendors-selectize--item--add--icon--color;
content: '\f067';
}
}
&.item-remove{
&.item-remove {
background-color: $ibo-vendors-selectize--item--remove--background-color !important;
&::before{
&::before {
color: $ibo-vendors-selectize--item--remove--icon--color;
content: '\f1f8';
}
}
&.item-ignore-partial{
&.item-ignore-partial {
background-color: $ibo-vendors-selectize--item--ignore-partial--background-color !important;
}
}
&.selectize-input-error{
&.selectize-input-error {
border: $ibo-vendors-selectize--input-error--border;
}
}
}

76
css/backoffice/vendors/_toastify.scss vendored Normal file
View File

@@ -0,0 +1,76 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/* SCSS variables */
$ibo-vendors-toastify--right--right: $ibo-spacing-500 !default;
$ibo-vendors-toastify--left--left: $ibo-spacing-500 !default;
$ibo-vendors-toastify--top--top: -150px !default;
$ibo-vendors-toastify--bottom--bottom: -150px !default;
$ibo-vendors-toastify--close--background: transparent !default;
$ibo-vendors-toastify--close--padding: 0 !default;
$ibo-vendors-toastify--close--margin-left: $ibo-spacing-300 !default;
.toastify.on {
opacity: 1;
}
.toast-close {
background: $ibo-vendors-toastify--close--background;
border: 0;
color: inherit;
cursor: pointer;
font-family: inherit;
padding: $ibo-vendors-toastify--close--padding;
margin-left: $ibo-vendors-toastify--close--margin-left;
}
.toastify-right {
right: $ibo-vendors-toastify--right--right;
}
.toastify-left {
left: $ibo-vendors-toastify--left--left;
}
.toastify-top {
top: $ibo-vendors-toastify--top--top;
}
.toastify-bottom {
bottom: $ibo-vendors-toastify--bottom--bottom;
}
.toastify-rounded {
border-radius: 25px;
}
.toastify-avatar {
width: 1.5em;
height: 1.5em;
margin: -7px 5px;
border-radius: 2px;
}
.toastify-center {
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
max-width: fit-content;
max-width: -moz-fit-content;
}
@media only screen and (max-width: 360px) {
.toastify-right, .toastify-left {
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
max-width: fit-content;
}
}

4
css/c3.min.css vendored
View File

@@ -1 +1,5 @@
/*
* @deprecated 3.2.0 N°5621 Moved to NPM
*/
.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}

View File

@@ -3,18 +3,32 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
/* These rules should be the same as those in css/backoffice/vendors/ckeditor.css */
body{
margin: 5px 10px;
.ibo-mention-item{
line-height: 1.6rem;
}
.cke_editable{
line-height: 1.4;
[data-role="object-mention"]{
color: #0782C1;
}
figure{
border: solid 1px #ccc;
border-radius: 2px;
}
p{
margin-top: 0.25em;
margin-bottom: 0.25em;
[data-role="object-mention"]:hover{
color: #2b6bb0;
}
.ck.ck-editor.cke-maximized{
position: fixed;
left: 0px;
top:0px;
right: 0px;
bottom: 0px;
z-index: 999;
display: flex;
flex-direction: column;
}
.ck.ck-editor.cke-maximized .ck.ck-editor__main{
flex-grow: 1;
}
.ck.ck-editor.cke-maximized .ck-editor__editable_inline:not(.ck-comment__input *){
height: 100%;
}

View File

@@ -1,75 +0,0 @@
/**
* Widgets Factory.
*
* @package FormSDK
* @since 3.2.0
*/
/* debug purpose */
.form-type-pictograms{
display: inline-block;
float: right;
margin-left: 5px;
color: grey;
cursor: pointer;
padding: 0px 5px;
border-radius: 8px;
font-size: 0.9rem;
}
.form-type-pictograms i{
width: 15px;
}
.complete .form-type-pictograms .pattern:after{
content: '\f00c';
font-family: "Font Awesome 6 Free";
font-weight: 900;
background-color: #20b220;
border-radius: 50%;
font-size: 7px;
color: white;
position: relative;
top: -10px;
padding: 2px;
}
/* form label */
.form-label.required:after{
content: '*';
color: #e63535;
margin-left: 3px;
}
.cke_focus .cke_contents{
border: 1px #86b7fe solid;
outline: 0;
border-radius: 6px;
box-shadow: 0 0 0 0.25rem rgba(13,110,253,.25);
}
.form_interval_horizontal{
display: flex;
}
.form_interval_horizontal > div{
margin-right: 8px;
}
.form-compound-fieldset{
padding: 8px;
border-radius: 10px;
border: 1px dashed lightgrey;
}
.form-layout-row{
display: flex;
flex-direction: row;
}
.form-layout-column{
margin: 10px;
}
.form-layout-column:first-child{
margin-left: 0px;
}
.form-layout-column:last-child{
margin-right: 0px;
}

View File

@@ -1,88 +0,0 @@
.layout-grow{
flex-grow: 1;
}
.custom-container{
position: relative;
border-radius: 10px;
padding: 40px 20px 0px;
}
.custom-container:before{
content: 'Custom Layout CSS';
font-weight: 500;
position: absolute;
left: 50%;
top: -10px;
transform: translateX(-50%);
/*border: 1px solid #9c21af;*/
background-color: white;
padding: 5px 15px;
border-radius: 10px;
}
.container-flower{
background-color: #f3deff;
background-size: 500px;
background-repeat: no-repeat;
background-position-x: right;
background-position-y: bottom;
background: linear-gradient( to right bottom, rgb(248 242 251) 50%, rgb(241 187 255) );
padding-bottom: 200px;
}
.container-flower fieldset{
position: relative;
z-index: 1;
}
.container-flower:after{
content: '';
width: 300px;
height: 200px;
background-image: url('../../sources/FormImplementation/Resources/6662396.png');
background-size: 300px;
position: absolute;
bottom: 0px;
right: 0px;
border-radius: 10px;
}
.container-flower .col-form-label{
color: #8d63b7;
}
.container-flower .form-compound-fieldset{
border: 1px solid #8d63b7;
}
.container-color{
position: relative;
border-radius: 10px;
background-color: #faf7ff;
}
.container-color .form-compound-fieldset{
background-color: #ebe4f6;
border: none;
}
.container-color2{
position: relative;
border-radius: 10px;
background-color: #f7f9ff;
}
.container-color2 .form-compound-fieldset{
background-color: #e8edf9;
border: none;
}
.error-label{
color: #d32f2f;
}
.container-color2 .form-compound-fieldset fieldset{
border-bottom: 1px dashed #a3adc5;
}
.container-color2 .form-compound-fieldset fieldset:last-child{
border-bottom: none;
}

View File

@@ -16,11 +16,11 @@
/* Shortened version style */
.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; }

View File

@@ -1,3 +1,7 @@
/**
* @deprecated 3.2.0 N°5621 Moved to NPM
*/
/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*

View File

@@ -1,15 +0,0 @@
/*
Tabs - additional IE specific bug fixes
Recommended usage (Conditional Comments):
<!--[if lte IE 7]>
<link rel="stylesheet" href="tabs_ie.css" type="text/css" media="projection, screen" />
<![endif]-->
*/
.tabs-nav { /* auto clear */
display: inline-block;
}
.tabs-nav .tabs-disabled a {
filter: alpha(opacity=40);
}

View File

@@ -1,3 +1,7 @@
/*
* @deprecated 3.2.0 N°5621 Moved to NPM
*/
/* Magnific Popup CSS */
.mfp-bg {
top: 0;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -58,6 +58,9 @@ $progress-bar-error-bg-color: #F56565 !default;
.center {
text-align: center;
}
.hidden {
display: none;
}
/* Animations */
@keyframes progress_bar_color_ongoing {

View File

@@ -6,7 +6,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'CAS:Error:UserNotAllowed' => 'User not allowed~~',
'CAS:Login:SignIn' => 'Sign in with CAS~~',
'CAS:Login:SignInTooltip' => 'Click here to authenticate yourself with the CAS server~~',
'CAS:Error:UserNotAllowed' => 'Utente non autorizzato',
'CAS:Login:SignIn' => 'Accedi con CAS',
'CAS:Login:SignInTooltip' => 'Clicca qui per autenticarti con il server CAS',
));

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