mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-21 11:24:19 +01:00
Compare commits
310 Commits
feature/41
...
saas/3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d6f4569ef | ||
|
|
1e41e805a2 | ||
|
|
bd1e4389f7 | ||
|
|
b059fb72a2 | ||
|
|
cdcc069099 | ||
|
|
8c639fc23a | ||
|
|
1b3b2e8a69 | ||
|
|
da5a825c7e | ||
|
|
b9230ad402 | ||
|
|
959ac7e3be | ||
|
|
1884596ecd | ||
|
|
584cfa8cbf | ||
|
|
eebc61385d | ||
|
|
3c15186685 | ||
|
|
fa038ded3d | ||
|
|
e7ea1b831c | ||
|
|
f15ac75f8f | ||
|
|
c6edbf982d | ||
|
|
5aea7ccbc9 | ||
|
|
e28dbebbd5 | ||
|
|
4aff65f98b | ||
|
|
8aba578cfa | ||
|
|
9d3e389011 | ||
|
|
7e7f8577e8 | ||
|
|
3c94974d9d | ||
|
|
d6e5069dd5 | ||
|
|
f839638e0b | ||
|
|
740ff8c649 | ||
|
|
cfe227e0c7 | ||
|
|
ed79c8f099 | ||
|
|
4560f751d1 | ||
|
|
46e869d1f4 | ||
|
|
fbd72b2783 | ||
|
|
6b448e29f5 | ||
|
|
7cb6af0a2b | ||
|
|
778118cfb4 | ||
|
|
096ed9a63a | ||
|
|
06eb79d4f4 | ||
|
|
ddc9952ec1 | ||
|
|
4e95ca3c7b | ||
|
|
4c626d0782 | ||
|
|
1114ed9562 | ||
|
|
1ddfaf0b61 | ||
|
|
c6fb03547f | ||
|
|
34368fe795 | ||
|
|
db46298cb8 | ||
|
|
064e8ee511 | ||
|
|
424e7b37d7 | ||
|
|
ca7aa482ab | ||
|
|
368b3f4ef7 | ||
|
|
dc8e6f314a | ||
|
|
a1a9ffe192 | ||
|
|
001194835f | ||
|
|
8ffddeff01 | ||
|
|
21d37fb237 | ||
|
|
fca4006811 | ||
|
|
7728082c00 | ||
|
|
955aefc05b | ||
|
|
970183ef45 | ||
|
|
6c2db1e687 | ||
|
|
034ca26d01 | ||
|
|
c3b00939dd | ||
|
|
75df33f606 | ||
|
|
32d74fbc8e | ||
|
|
477f2f51e9 | ||
|
|
94ea8e60e8 | ||
|
|
b9a00b15f5 | ||
|
|
e87f5af465 | ||
|
|
97d717b016 | ||
|
|
d03bd706e2 | ||
|
|
251fd3c67b | ||
|
|
78d8829d65 | ||
|
|
307edd3f7a | ||
|
|
6bf906a72f | ||
|
|
0f016d7511 | ||
|
|
d782987f50 | ||
|
|
b1fd7716f6 | ||
|
|
ac7abb3049 | ||
|
|
3689f3d026 | ||
|
|
5ee6223434 | ||
|
|
4bfc1747b7 | ||
|
|
15f32bf843 | ||
|
|
0ba386c0bc | ||
|
|
0c3cdb202b | ||
|
|
03ac3d4e7c | ||
|
|
6510dc5c51 | ||
|
|
01faf39372 | ||
|
|
176e373d6c | ||
|
|
7b0a569c64 | ||
|
|
a34274b883 | ||
|
|
7176bc8686 | ||
|
|
03fb78c38c | ||
|
|
c9e656f7a0 | ||
|
|
976566ec71 | ||
|
|
d908827787 | ||
|
|
93c0b98eb7 | ||
|
|
9c0b906ded | ||
|
|
98ab5aa1a4 | ||
|
|
f117a2912b | ||
|
|
6594072617 | ||
|
|
6bed56b34e | ||
|
|
94e8151519 | ||
|
|
75b350f638 | ||
|
|
14cd60dd17 | ||
|
|
08f1e5a041 | ||
|
|
4c117d1a33 | ||
|
|
f91dfbcf23 | ||
|
|
58497b380b | ||
|
|
03bff9f2c2 | ||
|
|
a34d3f91be | ||
|
|
05753f174a | ||
|
|
d0c89343b4 | ||
|
|
3021234895 | ||
|
|
bccdb1bc3a | ||
|
|
0533916dad | ||
|
|
143410f4cd | ||
|
|
4cea418517 | ||
|
|
759b1825fe | ||
|
|
370c1345d9 | ||
|
|
af8f06c8c3 | ||
|
|
bfe55183d0 | ||
|
|
939771aa15 | ||
|
|
b174e4cab3 | ||
|
|
61bd8b6bb4 | ||
|
|
60b08586c2 | ||
|
|
28df2942e4 | ||
|
|
cd48d2ad37 | ||
|
|
5c9eb7fa38 | ||
|
|
e960a4ad53 | ||
|
|
7aad60ed1b | ||
|
|
97965277c7 | ||
|
|
93aee5883b | ||
|
|
18ed5ed526 | ||
|
|
bbf6476570 | ||
|
|
94c4f8c929 | ||
|
|
d40cf7fe3b | ||
|
|
6997c0fd83 | ||
|
|
822922df5c | ||
|
|
cb2be0eccd | ||
|
|
f55fc8d264 | ||
|
|
ea2140258c | ||
|
|
31f2666941 | ||
|
|
cac7e94a67 | ||
|
|
da02a05fa3 | ||
|
|
6d019615d0 | ||
|
|
ccdd315357 | ||
|
|
9db2205241 | ||
|
|
045985cd5b | ||
|
|
9f81e4875a | ||
|
|
4f102d764a | ||
|
|
dbd58cfeb6 | ||
|
|
99b7d66cf2 | ||
|
|
12ef74ec42 | ||
|
|
3ca4122673 | ||
|
|
efa20e77d0 | ||
|
|
effc4141c7 | ||
|
|
f75a51d59e | ||
|
|
9dc54d6e4c | ||
|
|
640b1b9176 | ||
|
|
3459dc5997 | ||
|
|
de7c9d965e | ||
|
|
4c127b6f61 | ||
|
|
61be903eb2 | ||
|
|
a50ed02057 | ||
|
|
0a7c8f9fd1 | ||
|
|
f65e14397c | ||
|
|
d7b94fb123 | ||
|
|
80a9ded404 | ||
|
|
c696a81c3a | ||
|
|
b9ed00d53f | ||
|
|
c4508ea80c | ||
|
|
16390c9b00 | ||
|
|
1271a895d1 | ||
|
|
030f1e2463 | ||
|
|
5729d6a9cd | ||
|
|
a5efef900c | ||
|
|
c851a10982 | ||
|
|
845adf43c6 | ||
|
|
5916e4ea39 | ||
|
|
7f37de777e | ||
|
|
bcf880f327 | ||
|
|
b593beb8c7 | ||
|
|
6aa9aa2831 | ||
|
|
d177ee4a7f | ||
|
|
fbc0a898ae | ||
|
|
36f8e58e25 | ||
|
|
6a7dbb06b0 | ||
|
|
5721a324c1 | ||
|
|
7de6c72154 | ||
|
|
c0cee02351 | ||
|
|
bb674fb873 | ||
|
|
6136eadd31 | ||
|
|
87cb73c038 | ||
|
|
11d8547cef | ||
|
|
0998c73a1a | ||
|
|
471f66649a | ||
|
|
e8bf9cf688 | ||
|
|
4f88a0e7d2 | ||
|
|
c6b0e273e6 | ||
|
|
d9539f9d01 | ||
|
|
a3e309acb5 | ||
|
|
c06cbfd4a9 | ||
|
|
1d7e4e1a42 | ||
|
|
524e65a29b | ||
|
|
df7d7c877d | ||
|
|
4bcad431aa | ||
|
|
5fe32aac15 | ||
|
|
88d9a29599 | ||
|
|
92a36dcfdd | ||
|
|
23b4d4cb6b | ||
|
|
b37e74b407 | ||
|
|
809b371520 | ||
|
|
9bbc7342b8 | ||
|
|
973c435138 | ||
|
|
1c3dfd6491 | ||
|
|
9400b697eb | ||
|
|
49748a0374 | ||
|
|
cb6232cc05 | ||
|
|
0d49c605e2 | ||
|
|
6d47b0f4f8 | ||
|
|
e1c28a5c22 | ||
|
|
296ee019a0 | ||
|
|
7c2f8f4d93 | ||
|
|
1f76ff940d | ||
|
|
bb26e48d38 | ||
|
|
26042b990f | ||
|
|
cf433f2f80 | ||
|
|
ae94e58a43 | ||
|
|
f66692d5cf | ||
|
|
2b917f6647 | ||
|
|
cda017fa4f | ||
|
|
dad22f6f83 | ||
|
|
9474f43d61 | ||
|
|
9077f7ba37 | ||
|
|
4d365c8a44 | ||
|
|
957ff40f30 | ||
|
|
7bb12c35ea | ||
|
|
aff9c7748b | ||
|
|
e518d34bc9 | ||
|
|
51a305b445 | ||
|
|
5577f4a62e | ||
|
|
f0141530b9 | ||
|
|
92a802947d | ||
|
|
ce5096a896 | ||
|
|
5efd45eafc | ||
|
|
23e0ed5e56 | ||
|
|
d412a52fcc | ||
|
|
cf5745b985 | ||
|
|
3e18ad590f | ||
|
|
b174aa9aeb | ||
|
|
34f03715b6 | ||
|
|
6a0cdb8705 | ||
|
|
22111bf667 | ||
|
|
6d0c46595d | ||
|
|
1e2205ecb0 | ||
|
|
d292a6b0c3 | ||
|
|
74702c8d06 | ||
|
|
df4a205ba0 | ||
|
|
e9c91d986d | ||
|
|
feafd5e2c9 | ||
|
|
70a6b276ca | ||
|
|
f77361ceb2 | ||
|
|
75f4751b82 | ||
|
|
65b6c0f4ea | ||
|
|
c05684945f | ||
|
|
6b1c033ec1 | ||
|
|
163276a6c2 | ||
|
|
4f14d1fb23 | ||
|
|
9b0c2f7324 | ||
|
|
e1807f598f | ||
|
|
02e63fff64 | ||
|
|
0864f05d9f | ||
|
|
1bbcd9656a | ||
|
|
34d8e52c22 | ||
|
|
ac7309e48c | ||
|
|
c8fade6013 | ||
|
|
ad052dd861 | ||
|
|
a5ea868609 | ||
|
|
0b03b3ef4d | ||
|
|
8c95bd5a65 | ||
|
|
b56f2f56f1 | ||
|
|
282d47aed4 | ||
|
|
2f8f0b658c | ||
|
|
e4884470ad | ||
|
|
68d44fa981 | ||
|
|
7e5307bd96 | ||
|
|
174cace20a | ||
|
|
e3f5dbfc80 | ||
|
|
40e24c25a2 | ||
|
|
d3f8e1c472 | ||
|
|
647b669eb9 | ||
|
|
5839d0e8e3 | ||
|
|
cd010afb48 | ||
|
|
be5a252be7 | ||
|
|
073488a7bd | ||
|
|
0cf8d731bb | ||
|
|
c6e4466c53 | ||
|
|
6638eb4adc | ||
|
|
4e7df37931 | ||
|
|
eb40968e34 | ||
|
|
4b670cfa90 | ||
|
|
87db88254b | ||
|
|
5ddc006f51 | ||
|
|
85a72d6a10 | ||
|
|
189ca3c555 | ||
|
|
c02b36a00c | ||
|
|
1e1f1f78bf | ||
|
|
1494604740 | ||
|
|
59b20ac1ee | ||
|
|
766c9f0e7e |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -19,7 +19,7 @@
|
||||
|
||||
# composer reserver directory, from sources, populate/update using "composer install"
|
||||
vendor/*
|
||||
test/vendor/*
|
||||
tests/*/vendor/*
|
||||
|
||||
# all conf but listing prevention
|
||||
/conf/**
|
||||
@@ -46,7 +46,7 @@ test/vendor/*
|
||||
!/log/web.config
|
||||
|
||||
# PHPUnit cache file
|
||||
/test/.phpunit.result.cache
|
||||
/tests/php-unit-tests/.phpunit.result.cache
|
||||
|
||||
|
||||
# Jetbrains
|
||||
|
||||
@@ -131,7 +131,7 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
|
||||
When your code is working, please:
|
||||
|
||||
* stash as much as possible your commits,
|
||||
* squash as much as possible your commits,
|
||||
* rebase your branch on our repo last commit,
|
||||
* create a pull request.
|
||||
|
||||
|
||||
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -1,6 +1,14 @@
|
||||
def infra
|
||||
|
||||
node(){
|
||||
properties([
|
||||
buildDiscarder(
|
||||
logRotator(
|
||||
daysToKeepStr: "28",
|
||||
numToKeepStr: "500")
|
||||
)
|
||||
])
|
||||
|
||||
checkout scm
|
||||
|
||||
infra = load '/var/lib/jenkins/workspace/itop-test-infra_master/src/Infra.groovy'
|
||||
|
||||
@@ -37,7 +37,7 @@ iTop also offers mass import tools to help you being even more efficient.
|
||||
- [iTop Forums][1]: community support
|
||||
- [iTop Tickets][2]: for feature requests and bug reports
|
||||
- [Releases download][3]
|
||||
- [Software requirements][4]
|
||||
- [iTop requirements][4]
|
||||
- [Documentation][5] covering both iTop and its official extensions
|
||||
- [iTop Hub][6] : discover and install extensions !
|
||||
|
||||
@@ -45,7 +45,7 @@ iTop also offers mass import tools to help you being even more efficient.
|
||||
[1]: https://sourceforge.net/p/itop/discussion/
|
||||
[2]: https://sourceforge.net/p/itop/tickets/
|
||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||
[4]: https://www.itophub.io/wiki/page?id=latest:install:upgrading_itop
|
||||
[4]: https://www.itophub.io/wiki/page?id=latest:install:requirements
|
||||
[5]: https://www.itophub.io/wiki
|
||||
[6]: https://store.itophub.io/en_US/
|
||||
|
||||
|
||||
@@ -376,26 +376,19 @@ class ApplicationContext
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
|
||||
if (is_null($sUrlMakerClass))
|
||||
{
|
||||
$sUrlMakerClass = self::GetUrlMakerClass();
|
||||
}
|
||||
if (is_null($sUrlMakerClass)) {
|
||||
$sUrlMakerClass = self::GetUrlMakerClass();
|
||||
}
|
||||
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey);
|
||||
if (strlen($sUrl) > 0)
|
||||
{
|
||||
if ($bWithNavigationContext)
|
||||
{
|
||||
return $sUrl."&".$oAppContext->GetForLink();
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sUrl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
if (utils::StrLen($sUrl) > 0) {
|
||||
if ($bWithNavigationContext) {
|
||||
return $sUrl."&".$oAppContext->GetForLink();
|
||||
} else {
|
||||
return $sUrl;
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,9 +30,9 @@ require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
||||
* You may implement such interfaces in a module file (e.g. main.mymodule.php)
|
||||
*
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @package Extensibility
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginExtension
|
||||
@@ -40,12 +40,16 @@ interface iLoginExtension
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginFSMExtension extends iLoginExtension
|
||||
@@ -57,6 +61,7 @@ interface iLoginFSMExtension extends iLoginExtension
|
||||
* if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
|
||||
* if LoginWebPage::LOGIN_FSM_RETURN_IGNORE is returned then the FSM will proceed to next plugin or state
|
||||
*
|
||||
* @api
|
||||
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
@@ -66,6 +71,8 @@ interface iLoginFSMExtension extends iLoginExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
@@ -112,6 +119,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
/**
|
||||
* Initialization
|
||||
*
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -125,6 +133,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
* Detect login mode explicitly without respecting configured order (legacy mode)
|
||||
* In most case do nothing here
|
||||
*
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -141,6 +150,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
* 1 - display login form
|
||||
* 2 - read the values posted by the user
|
||||
*
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -154,6 +164,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
* Control the validity of the data provided by the user
|
||||
* Automatic user provisioning can be done here
|
||||
*
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -164,6 +175,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -174,6 +186,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -184,6 +197,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -194,6 +208,7 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
|
||||
@@ -205,22 +220,28 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLogoutExtension extends iLoginExtension
|
||||
{
|
||||
/**
|
||||
* Execute all actions to log out properly
|
||||
* @api
|
||||
*/
|
||||
public function LogoutAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginUIExtension extends iLoginExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @return LoginTwigContext
|
||||
*/
|
||||
public function GetTwigContext();
|
||||
@@ -228,18 +249,20 @@ interface iLoginUIExtension extends iLoginExtension
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package PreferencesExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iPreferencesExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
*/
|
||||
public function DisplayPreferences(WebPage $oPage);
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param \WebPage $oPage
|
||||
* @param string $sOperation
|
||||
*
|
||||
@@ -252,7 +275,7 @@ interface iPreferencesExtension
|
||||
* Extend this class instead of implementing iPreferencesExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package PreferencesExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractPreferencesExtension implements iPreferencesExtension
|
||||
@@ -298,7 +321,7 @@ abstract class AbstractPreferencesExtension implements iPreferencesExtension
|
||||
* A recommended pattern is to cache data by the mean of static members.
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
*/
|
||||
interface iApplicationUIExtension
|
||||
{
|
||||
@@ -320,6 +343,7 @@ interface iApplicationUIExtension
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being displayed
|
||||
* @param WebPage $oPage The output context
|
||||
* @param boolean $bEditMode True if the edition form is being displayed
|
||||
@@ -333,6 +357,7 @@ interface iApplicationUIExtension
|
||||
*
|
||||
* The method is called rigth after all the tabs have been displayed
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being displayed
|
||||
* @param WebPage $oPage The output context
|
||||
* @param boolean $bEditMode True if the edition form is being displayed
|
||||
@@ -347,6 +372,7 @@ interface iApplicationUIExtension
|
||||
* The method is called after the changes from the standard form have been
|
||||
* taken into account, and before saving the changes into the database.
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being edited
|
||||
* @param string $sFormPrefix Prefix given to the HTML form inputs
|
||||
*
|
||||
@@ -361,6 +387,7 @@ interface iApplicationUIExtension
|
||||
* javascript into the edition form, and if that code requires to store temporary data
|
||||
* (this is the case when a file must be uploaded).
|
||||
*
|
||||
* @api
|
||||
* @param string $sTempId Unique temporary identifier made of session_id and transaction_id. It identifies the object in a unique way.
|
||||
*
|
||||
* @return void
|
||||
@@ -372,6 +399,7 @@ interface iApplicationUIExtension
|
||||
*
|
||||
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return string[] desc
|
||||
@@ -383,6 +411,7 @@ interface iApplicationUIExtension
|
||||
*
|
||||
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return string Path of the icon, relative to the modules directory.
|
||||
@@ -402,6 +431,7 @@ interface iApplicationUIExtension
|
||||
* * HILIGHT_CLASS_OK
|
||||
* * HILIGHT_CLASS_NONE
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return integer The value representing the mood of the object
|
||||
@@ -428,6 +458,7 @@ interface iApplicationUIExtension
|
||||
*
|
||||
* See also iPopupMenuExtension for greater flexibility
|
||||
*
|
||||
* @api
|
||||
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
|
||||
*
|
||||
* @return array
|
||||
@@ -439,7 +470,7 @@ interface iApplicationUIExtension
|
||||
* Extend this class instead of implementing iApplicationUIExtension if you don't need to overload
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
|
||||
@@ -513,7 +544,7 @@ abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
|
||||
* or through the GUI.
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package ORMExtensibilityAPI
|
||||
*/
|
||||
interface iApplicationObjectExtension
|
||||
{
|
||||
@@ -526,6 +557,7 @@ interface iApplicationObjectExtension
|
||||
* If the extension returns false, then the framework will perform the usual evaluation.
|
||||
* Otherwise, the answer is definitively "yes, the object has changed".
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
*
|
||||
* @return boolean True if something has changed for the target object
|
||||
@@ -538,6 +570,7 @@ interface iApplicationObjectExtension
|
||||
* The GUI calls this verb and reports any issue.
|
||||
* Anyhow, this API can be called in other contexts such as the CSV import tool.
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
*
|
||||
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
|
||||
@@ -551,6 +584,7 @@ interface iApplicationObjectExtension
|
||||
*
|
||||
* Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled.
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
*
|
||||
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
|
||||
@@ -566,6 +600,7 @@ interface iApplicationObjectExtension
|
||||
* * {@see DBObject::ListPreviousValuesForUpdatedAttributes()} : list of changed attributes and their values before the change
|
||||
* * {@see DBObject::Get()} : for a given attribute the new value that was persisted
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
|
||||
* once for all the changes made within the current page
|
||||
@@ -581,6 +616,7 @@ interface iApplicationObjectExtension
|
||||
*
|
||||
* The method is called right <b>after</b> the object has been written to the database.
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
|
||||
* once for all the changes made within the current page
|
||||
@@ -594,6 +630,7 @@ interface iApplicationObjectExtension
|
||||
*
|
||||
* The method is called right <b>before</b> the object will be deleted from the database.
|
||||
*
|
||||
* @api
|
||||
* @param \cmdbAbstractObject $oObject The target object
|
||||
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
|
||||
* once for all the changes made within the current page
|
||||
@@ -607,7 +644,7 @@ interface iApplicationObjectExtension
|
||||
* Extend this class instead of iApplicationObjectExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package ORMExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractApplicationObjectExtension implements iApplicationObjectExtension
|
||||
@@ -667,7 +704,7 @@ abstract class AbstractApplicationObjectExtension implements iApplicationObjectE
|
||||
* by the application, as long as the class definition is included somewhere in the code
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
interface iPopupMenuExtension
|
||||
@@ -676,18 +713,21 @@ interface iPopupMenuExtension
|
||||
* Insert an item into the Actions menu of a list
|
||||
*
|
||||
* $param is a DBObjectSet containing the list of objects
|
||||
* @api
|
||||
*/
|
||||
const MENU_OBJLIST_ACTIONS = 1;
|
||||
/**
|
||||
* Insert an item into the Toolkit menu of a list
|
||||
*
|
||||
* $param is a DBObjectSet containing the list of objects
|
||||
* @api
|
||||
*/
|
||||
const MENU_OBJLIST_TOOLKIT = 2;
|
||||
/**
|
||||
* Insert an item into the Actions menu on an object details page
|
||||
*
|
||||
* $param is a DBObject instance: the object currently displayed
|
||||
* @api
|
||||
*/
|
||||
const MENU_OBJDETAILS_ACTIONS = 3;
|
||||
/**
|
||||
@@ -697,12 +737,14 @@ interface iPopupMenuExtension
|
||||
* is being displayed.
|
||||
*
|
||||
* $param is a Dashboard instance: the dashboard currently displayed
|
||||
* @api
|
||||
*/
|
||||
const MENU_DASHBOARD_ACTIONS = 4;
|
||||
/**
|
||||
* Insert an item into the User menu (upper right corner)
|
||||
*
|
||||
* $param is null
|
||||
* @api
|
||||
*/
|
||||
const MENU_USER_ACTIONS = 5;
|
||||
/**
|
||||
@@ -710,6 +752,7 @@ interface iPopupMenuExtension
|
||||
*
|
||||
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object on
|
||||
* the current line)
|
||||
* @api
|
||||
*/
|
||||
const PORTAL_OBJLISTITEM_ACTIONS = 7;
|
||||
/**
|
||||
@@ -717,6 +760,7 @@ interface iPopupMenuExtension
|
||||
*
|
||||
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object
|
||||
* currently displayed)
|
||||
* @api
|
||||
*/
|
||||
const PORTAL_OBJDETAILS_ACTIONS = 8;
|
||||
|
||||
@@ -754,6 +798,7 @@ interface iPopupMenuExtension
|
||||
* This method is called by the framework for each menu.
|
||||
* The items will be inserted in the menu in the order of the returned array.
|
||||
*
|
||||
* @api
|
||||
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
|
||||
* @param mixed $param Depends on $iMenuId, see the constants defined above
|
||||
*
|
||||
@@ -766,7 +811,7 @@ interface iPopupMenuExtension
|
||||
* Base class for the various types of custom menus
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class ApplicationPopupMenuItem
|
||||
@@ -776,7 +821,7 @@ abstract class ApplicationPopupMenuItem
|
||||
/** @ignore */
|
||||
protected $sLabel;
|
||||
/** @ignore */
|
||||
protected $sTooltip;
|
||||
protected $sTooltip;
|
||||
/** @ignore */
|
||||
protected $sIconClass;
|
||||
/** @ignore */
|
||||
@@ -833,6 +878,7 @@ abstract class ApplicationPopupMenuItem
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param $aCssClasses
|
||||
*/
|
||||
public function SetCssClasses($aCssClasses)
|
||||
@@ -843,6 +889,7 @@ abstract class ApplicationPopupMenuItem
|
||||
/**
|
||||
* Adds a CSS class to the CSS classes that will be put on the menu item
|
||||
*
|
||||
* @api
|
||||
* @param $sCssClass
|
||||
*/
|
||||
public function AddCssClass($sCssClass)
|
||||
@@ -853,7 +900,7 @@ abstract class ApplicationPopupMenuItem
|
||||
|
||||
/**
|
||||
* @param $sTooltip
|
||||
*
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function SetTooltip($sTooltip)
|
||||
@@ -863,24 +910,24 @@ abstract class ApplicationPopupMenuItem
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetTooltip()
|
||||
{
|
||||
return $this->sTooltip;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sIconClass
|
||||
*
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function SetIconClass($sIconClass)
|
||||
{
|
||||
$this->sIconClass = $sIconClass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
@@ -890,7 +937,7 @@ abstract class ApplicationPopupMenuItem
|
||||
{
|
||||
return $this->sIconClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the components to create a popup menu item in HTML
|
||||
*
|
||||
@@ -912,7 +959,7 @@ abstract class ApplicationPopupMenuItem
|
||||
* Note: This works only in the backoffice, {@see \URLButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
@@ -925,6 +972,7 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @api
|
||||
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
||||
* @param string $sLabel The display label of the menu (must be localized)
|
||||
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
|
||||
@@ -948,7 +996,7 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
'tooltip' => $this->sTooltip
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** @ignore */
|
||||
public function GetUrl()
|
||||
{
|
||||
@@ -968,7 +1016,7 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
* Note: This works only in the backoffice, {@see \JSButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||
@@ -1018,13 +1066,13 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||
{
|
||||
return $this->aIncludeJSFiles;
|
||||
}
|
||||
|
||||
|
||||
/** @ignore */
|
||||
public function GetJsCode()
|
||||
{
|
||||
return $this->sJsCode;
|
||||
}
|
||||
|
||||
|
||||
/** @ignore */
|
||||
public function GetUrl()
|
||||
{
|
||||
@@ -1037,7 +1085,7 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||
* will automatically reduce several consecutive separators to just one
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
|
||||
@@ -1046,6 +1094,7 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -1063,7 +1112,7 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
|
||||
* Class for adding an item as a button that browses to the given URL
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class URLButtonItem extends URLPopupMenuItem
|
||||
@@ -1075,7 +1124,7 @@ class URLButtonItem extends URLPopupMenuItem
|
||||
* Class for adding an item as a button that runs some JS code
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class JSButtonItem extends JSPopupMenuItem
|
||||
@@ -1099,7 +1148,7 @@ class JSButtonItem extends JSPopupMenuItem
|
||||
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
* @deprecated 3.0.0 If you need to include:
|
||||
* * JS/CSS files/snippets, use {@see \iBackofficeLinkedScriptsExtension}, {@see \iBackofficeLinkedStylesheetsExtension}, etc instead
|
||||
@@ -1110,6 +1159,7 @@ interface iPageUIExtension
|
||||
/**
|
||||
* Add content to the header of the page
|
||||
*
|
||||
* @api
|
||||
* @param iTopWebPage $oPage The page to insert stuff into.
|
||||
*
|
||||
* @return string The HTML content to add into the page
|
||||
@@ -1119,6 +1169,7 @@ interface iPageUIExtension
|
||||
/**
|
||||
* Add content to the footer of the page
|
||||
*
|
||||
* @api
|
||||
* @param iTopWebPage $oPage The page to insert stuff into.
|
||||
*
|
||||
* @return string The HTML content to add into the page
|
||||
@@ -1128,6 +1179,7 @@ interface iPageUIExtension
|
||||
/**
|
||||
* Add content to the "admin banner"
|
||||
*
|
||||
* @api
|
||||
* @param iTopWebPage $oPage The page to insert stuff into.
|
||||
*
|
||||
* @return string The HTML content to add into the page
|
||||
@@ -1151,7 +1203,7 @@ interface iPageUIExtension
|
||||
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIBlockExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iPageUIBlockExtension
|
||||
@@ -1182,7 +1234,7 @@ interface iPageUIBlockExtension
|
||||
* Extend this class instead of iPageUIExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
* @deprecated since 3.0.0 use AbstractPageUIBlockExtension instead
|
||||
*/
|
||||
@@ -1224,7 +1276,7 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
||||
* Extend this class instead of iPageUIExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package UIBlockExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
|
||||
@@ -1259,6 +1311,7 @@ abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_linked_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeLinkedScriptsExtension
|
||||
@@ -1276,6 +1329,7 @@ interface iBackofficeLinkedScriptsExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_early_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeEarlyScriptExtension
|
||||
@@ -1292,6 +1346,7 @@ interface iBackofficeEarlyScriptExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeScriptExtension
|
||||
@@ -1308,6 +1363,7 @@ interface iBackofficeScriptExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_init_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeInitScriptExtension
|
||||
@@ -1324,6 +1380,7 @@ interface iBackofficeInitScriptExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_ready_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeReadyScriptExtension
|
||||
@@ -1340,6 +1397,7 @@ interface iBackofficeReadyScriptExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_linked_stylesheets
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeLinkedStylesheetsExtension
|
||||
@@ -1356,6 +1414,7 @@ interface iBackofficeLinkedStylesheetsExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_styles
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeStyleExtension
|
||||
@@ -1372,6 +1431,7 @@ interface iBackofficeStyleExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_dict_entries
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeDictEntriesExtension
|
||||
@@ -1388,6 +1448,7 @@ interface iBackofficeDictEntriesExtension
|
||||
*
|
||||
* @see \iTopWebPage::$a_dict_entries_prefixes
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeDictEntriesPrefixesExtension
|
||||
@@ -1403,7 +1464,7 @@ interface iBackofficeDictEntriesPrefixesExtension
|
||||
* Implement this interface to add content to any enhanced portal page
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package PortalExtensibilityAPI
|
||||
*
|
||||
* @since 2.4.0 interface creation
|
||||
* @since 2.7.0 change method signatures due to Silex to Symfony migration
|
||||
@@ -1417,6 +1478,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns an array of CSS file urls
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return array
|
||||
@@ -1426,6 +1488,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns inline (raw) CSS
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
@@ -1435,6 +1498,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns an array of JS file urls
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return array
|
||||
@@ -1444,6 +1508,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns raw JS code
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
@@ -1453,6 +1518,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the <body> tag
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
@@ -1462,6 +1528,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the #main-wrapper element
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
@@ -1471,6 +1538,7 @@ interface iPortalUIExtension
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the #topbar and #sidebar elements
|
||||
*
|
||||
* @api
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
@@ -1482,7 +1550,7 @@ interface iPortalUIExtension
|
||||
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package PortalExtensibilityAPI
|
||||
* @since 2.4.0
|
||||
*/
|
||||
abstract class AbstractPortalUIExtension implements iPortalUIExtension
|
||||
@@ -1548,7 +1616,7 @@ abstract class AbstractPortalUIExtension implements iPortalUIExtension
|
||||
* Implement this interface to add new operations to the REST/JSON web service
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package RESTExtensibilityAPI
|
||||
* @since 2.0.1
|
||||
*/
|
||||
interface iRestServiceProvider
|
||||
@@ -1556,6 +1624,7 @@ interface iRestServiceProvider
|
||||
/**
|
||||
* Enumerate services delivered by this class
|
||||
*
|
||||
* @api
|
||||
* @param string $sVersion The version (e.g. 1.0) supported by the services
|
||||
*
|
||||
* @return array An array of hash 'verb' => verb, 'description' => description
|
||||
@@ -1565,6 +1634,7 @@ interface iRestServiceProvider
|
||||
/**
|
||||
* Enumerate services delivered by this class
|
||||
*
|
||||
* @api
|
||||
* @param string $sVersion The version (e.g. 1.0) supported by the services
|
||||
* @param string $sVerb
|
||||
* @param array $aParams
|
||||
@@ -1578,69 +1648,90 @@ interface iRestServiceProvider
|
||||
* Minimal REST response structure. Derive this structure to add response data and error codes.
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package RESTExtensibilityAPI
|
||||
* @since 2.0.1
|
||||
*/
|
||||
class RestResult
|
||||
{
|
||||
/**
|
||||
* Result: no issue has been encountered
|
||||
* @api
|
||||
*/
|
||||
const OK = 0;
|
||||
/**
|
||||
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
|
||||
* @api
|
||||
*/
|
||||
const UNAUTHORIZED = 1;
|
||||
/**
|
||||
* Result: the parameter 'version' is missing
|
||||
* @api
|
||||
*/
|
||||
const MISSING_VERSION = 2;
|
||||
/**
|
||||
* Result: the parameter 'json_data' is missing
|
||||
* @api
|
||||
*/
|
||||
const MISSING_JSON = 3;
|
||||
/**
|
||||
* Result: the input structure is not a valid JSON string
|
||||
* @api
|
||||
*/
|
||||
const INVALID_JSON = 4;
|
||||
/**
|
||||
* Result: the parameter 'auth_user' is missing, authentication aborted
|
||||
* @api
|
||||
*/
|
||||
const MISSING_AUTH_USER = 5;
|
||||
/**
|
||||
* Result: the parameter 'auth_pwd' is missing, authentication aborted
|
||||
* @api
|
||||
*/
|
||||
const MISSING_AUTH_PWD = 6;
|
||||
/**
|
||||
* Result: no operation is available for the specified version
|
||||
* @api
|
||||
*/
|
||||
const UNSUPPORTED_VERSION = 10;
|
||||
/**
|
||||
* Result: the requested operation is not valid for the specified version
|
||||
* @api
|
||||
*/
|
||||
const UNKNOWN_OPERATION = 11;
|
||||
/**
|
||||
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
|
||||
* @api
|
||||
*/
|
||||
const UNSAFE = 12;
|
||||
/**
|
||||
* Result: the request page number is not valid. It must be an integer greater than 0
|
||||
* @api
|
||||
*/
|
||||
const INVALID_PAGE = 13;
|
||||
/**
|
||||
* Result: the operation could not be performed, see the message for troubleshooting
|
||||
* @api
|
||||
*/
|
||||
const INTERNAL_ERROR = 100;
|
||||
|
||||
/**
|
||||
* Default constructor - ok!
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->code = RestResult::OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @api
|
||||
*/
|
||||
public $code;
|
||||
/**
|
||||
* @var string
|
||||
* @api
|
||||
*/
|
||||
public $message;
|
||||
}
|
||||
|
||||
@@ -1648,7 +1739,7 @@ class RestResult
|
||||
* Helpers for implementing REST services
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @package RESTExtensibilityAPI
|
||||
*/
|
||||
class RestUtils
|
||||
{
|
||||
@@ -1797,6 +1888,7 @@ class RestUtils
|
||||
/**
|
||||
* Read and interpret object search criteria from a Rest/Json structure
|
||||
*
|
||||
* @api
|
||||
* @param string $sClass Name of the class
|
||||
* @param StdClass $oCriteria Hash of attribute code => value (can be a substructure or a scalar, depending on the nature of the
|
||||
* attriute)
|
||||
@@ -1906,6 +1998,7 @@ class RestUtils
|
||||
/**
|
||||
* Search objects from a polymorph search specification (Rest/Json)
|
||||
*
|
||||
* @api
|
||||
* @param string $sClass Name of the class
|
||||
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
|
||||
* @param int $iLimit The limit of results to return
|
||||
@@ -2091,5 +2184,50 @@ class RestUtils
|
||||
*/
|
||||
interface iModuleExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function __construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to provide messages to be displayed in the "Welcome Popup"
|
||||
*
|
||||
* @api
|
||||
* @private
|
||||
* @since 3.1.0
|
||||
*/
|
||||
interface iWelcomePopup
|
||||
{
|
||||
// Importance for ordering messages
|
||||
// Just two levels since less important messages have nothing to do in the welcome popup
|
||||
const IMPORTANCE_CRITICAL = 0;
|
||||
const IMPORTANCE_HIGH = 1;
|
||||
/**
|
||||
* @return [['importance' => IMPORTANCE_CRITICAL|IMPORTANCE_HIGH, 'id' => '...', 'title' => '', 'html' => '', 'twig' => '']]
|
||||
*/
|
||||
public function GetMessages();
|
||||
/**
|
||||
* The message specified by the given Id has been acknowledged by the current user
|
||||
* @param string $sMessageId
|
||||
*/
|
||||
public function AcknowledgeMessage(string $sMessageId): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from this class to provide messages to be displayed in the "Welcome Popup"
|
||||
*
|
||||
* @api
|
||||
* @since 3.1.0
|
||||
*/
|
||||
abstract class AbstractWelcomePopup implements iWelcomePopup
|
||||
{
|
||||
public function GetMessages()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
public function AcknowledgeMessage(string $sMessageId): void
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3054,7 +3054,16 @@ EOF
|
||||
|
||||
// Hook the cancel button via jQuery so that it can be unhooked easily as well if needed
|
||||
$sDefaultUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search_form&class='.$sClass.'&'.$oAppContext->GetForLink();
|
||||
$oPage->add_ready_script("$('#form_{$this->m_iFormId} button.cancel').on('click', function() { BackToDetails('$sClass', $iKey, '$sDefaultUrl', $sJSToken)} );");
|
||||
|
||||
$sCancelButtonOnClickScript = "let fOnClick{$this->m_iFormId}CancelButton = ";
|
||||
if(isset($aExtraParams['js_handlers']['cancel_button_on_click'])){
|
||||
$sCancelButtonOnClickScript .= $aExtraParams['js_handlers']['cancel_button_on_click'];
|
||||
} else {
|
||||
$sCancelButtonOnClickScript .= "function() { BackToDetails('$sClass', $iKey, '$sDefaultUrl', $sJSToken)};";
|
||||
}
|
||||
$sCancelButtonOnClickScript .= "$('#form_{$this->m_iFormId} button.cancel').on('click', fOnClick{$this->m_iFormId}CancelButton);";
|
||||
$oPage->add_ready_script($sCancelButtonOnClickScript);
|
||||
|
||||
|
||||
$iFieldsCount = count($aFieldsMap);
|
||||
$sJsonFieldsMap = json_encode($aFieldsMap);
|
||||
@@ -3374,13 +3383,14 @@ EOF
|
||||
// Consider only the "expected" fields for the target state
|
||||
if (array_key_exists($sAttCode, $aExpectedAttributes)) {
|
||||
$iExpectCode = $aExpectedAttributes[$sAttCode];
|
||||
|
||||
// Prompt for an attribute if
|
||||
// - the attribute must be changed or must be displayed to the user for confirmation
|
||||
// - or the field is mandatory and currently empty
|
||||
if (($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) == ''))) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && (false === $this->HasAValue($sAttCode)))) {
|
||||
$aArgs = array('this' => $this);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
// If the field is mandatory, set it to the only possible value
|
||||
if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY)) {
|
||||
if ($oAttDef->IsExternalKey()) {
|
||||
@@ -3409,32 +3419,35 @@ EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
$sInputType = '';
|
||||
$sInputId = 'att_'.$iFieldIndex;
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,
|
||||
$this->Get($sAttCode), $this->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode,
|
||||
$aArgs);
|
||||
$aAttrib = array(
|
||||
$this->Get($sAttCode), $this->GetEditValue($sAttCode), $sInputId, '', $iExpectCode,
|
||||
$aArgs, true, $sInputType);
|
||||
$aAttrib = array(
|
||||
'label' => '<span>'.$oAttDef->GetLabel().'</span>',
|
||||
'value' => "<span id=\"field_att_$iFieldIndex\">$sHTMLValue</span>",
|
||||
);
|
||||
|
||||
//add attrib for data-attribute
|
||||
// Prepare metadata attributes
|
||||
$sAttCode = $oAttDef->GetCode();
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$sAttCode = $oAttDef->GetCode();
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
$sAttLabel = MetaModel::GetLabel($sClass, $sAttCode);
|
||||
$sAttLabel = MetaModel::GetLabel($sClass, $sAttCode);
|
||||
|
||||
$aAttrib['attcode'] = $sAttCode;
|
||||
$aAttrib['atttype'] = $sAttDefClass;
|
||||
$aAttrib['attcode'] = $sAttCode;
|
||||
$aAttrib['atttype'] = $sAttDefClass;
|
||||
$aAttrib['attlabel'] = $sAttLabel;
|
||||
// - Attribute flags
|
||||
$aAttrib['attflags'] = $this->GetFormAttributeFlags($sAttCode) ;
|
||||
$aAttrib['attflags'] = $this->GetFormAttributeFlags($sAttCode);
|
||||
// - How the field should be rendered
|
||||
$aAttrib['layout'] = (in_array($oAttDef->GetEditClass(), static::GetAttEditClassesToRenderAsLargeField())) ? 'large' : 'small';
|
||||
$aAttrib['layout'] = (in_array($oAttDef->GetEditClass(), static::GetAttEditClassesToRenderAsLargeField())) ? 'large' : 'small';
|
||||
$aAttrib['inputid'] = $sInputId;
|
||||
$aAttrib['inputtype'] = $sInputType;
|
||||
// - For simple fields, we get the raw (stored) value as well
|
||||
$bExcludeRawValue = false;
|
||||
foreach (static::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||
{
|
||||
foreach (static::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) {
|
||||
$bExcludeRawValue = true;
|
||||
break;
|
||||
@@ -3442,8 +3455,8 @@ EOF
|
||||
}
|
||||
$aAttrib['value_raw'] = ($bExcludeRawValue === false) ? $this->Get($sAttCode) : '';
|
||||
|
||||
$aDetails[] = $aAttrib;
|
||||
$aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex;
|
||||
$aDetails[] = $aAttrib;
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
$iFieldIndex++;
|
||||
$bExistFieldToDisplay = true;
|
||||
}
|
||||
@@ -3667,7 +3680,7 @@ HTML;
|
||||
$sDisplayLabel = Dict::S('UI:OpenDocumentInNewWindow_');
|
||||
$sDisplayUrl = $oDocument->GetDisplayURL(get_class($this), $this->GetKey(), $sAttCode);
|
||||
|
||||
$sDownloadLabel = Dict::Format('UI:DownloadDocument_');
|
||||
$sDownloadLabel = Dict::S('UI:DownloadDocument_');
|
||||
$sDownloadUrl = $oDocument->GetDownloadURL(get_class($this), $this->GetKey(), $sAttCode);
|
||||
|
||||
$sDisplayValue = <<<HTML
|
||||
|
||||
@@ -1549,6 +1549,29 @@ JS
|
||||
return $this->sDefinitionFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDashboardFileRelative can also be an absolute path (compatibility with old URL)
|
||||
*
|
||||
* @return string full path to the Dashboard file
|
||||
* @throws \SecurityException if path isn't under approot
|
||||
* @uses utils::RealPath()
|
||||
* @since 2.7.8 3.0.3 3.1.0 N°4449 remove FPD
|
||||
*/
|
||||
public static function GetDashboardFileFromRelativePath($sDashboardFileRelative)
|
||||
{
|
||||
if (utils::RealPath($sDashboardFileRelative, APPROOT)) {
|
||||
// compatibility with old URL containing absolute path !
|
||||
return $sDashboardFileRelative;
|
||||
}
|
||||
|
||||
$sDashboardFile = APPROOT.$sDashboardFileRelative;
|
||||
if (false === utils::RealPath($sDashboardFile, APPROOT)) {
|
||||
throw new SecurityException('Invalid dashboard file !');
|
||||
}
|
||||
|
||||
return $sDashboardFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDefinitionFile
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,36 @@
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="WelcomePopupAcknowledge" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
<properties>
|
||||
<comment>/* Acknowledge welcome popup messages */</comment>
|
||||
<abstract>false</abstract>
|
||||
<category></category>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_welcome_popup_acknowledge</db_table>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="message_uuid" xsi:type="AttributeString">
|
||||
<sql>message_uuid</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="user_id" xsi:type="AttributeExternalKey">
|
||||
<sql>user_id</sql>
|
||||
<target_class>User</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_SILENT</on_target_delete>
|
||||
</field>
|
||||
<field id="acknowledge_date" xsi:type="AttributeDateTime">
|
||||
<sql>acknowledge_date</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
</classes>
|
||||
<portals>
|
||||
<portal id="backoffice" _delta="define">
|
||||
|
||||
@@ -386,7 +386,7 @@ EOF;
|
||||
if (!$oPage->IsPrintableVersion())
|
||||
{
|
||||
$sMenuTitle = Dict::S('UI:ConfigureThisList');
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||
|
||||
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
|
||||
$aActions = array(
|
||||
|
||||
@@ -304,7 +304,7 @@ class DisplayBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function GetFilter()
|
||||
{
|
||||
return $this->m_oFilter;
|
||||
@@ -1045,9 +1045,19 @@ JS
|
||||
$aCount = $aCounts[$sStateValue];
|
||||
$sHyperlink = $aCount['link'];
|
||||
$sCountLabel = $aCount['label'];
|
||||
$oPill = PillFactory::MakeForState($sClass, $sStateValue)
|
||||
->SetTooltip($sStateLabel)
|
||||
->AddHtml("<span class=\"ibo-dashlet-header-dynamic--count\">$sCountLabel</span><span class=\"ibo-dashlet-header-dynamic--label ibo-text-truncated-with-ellipsis\">".utils::HtmlEntities($sStateLabel)."</span>");
|
||||
|
||||
$oPill = PillFactory::MakeForState($sClass, $sStateValue);
|
||||
// N°5849 - Unencode label for ExternalKey attribute because friendlyname is already html encoded thanks to DBObject::GetName() in AttributeExternalKey::GetAllowedValues(). (A fix in this function may have too much impact).
|
||||
if ($oAttDef instanceof AttributeExternalKey) {
|
||||
$sPillTooltip = utils::HtmlEntityDecode($sStateLabel);
|
||||
$sPillLabel = $sStateLabel;
|
||||
} else {
|
||||
$sPillTooltip = $sStateLabel;
|
||||
$sPillLabel = utils::HtmlEntities($sStateLabel);
|
||||
}
|
||||
$oPill->SetTooltip($sPillTooltip)
|
||||
->AddHtml("<span class=\"ibo-dashlet-header-dynamic--count\">$sCountLabel</span><span class=\"ibo-dashlet-header-dynamic--label ibo-text-truncated-with-ellipsis\">".$sPillLabel."</span>");
|
||||
|
||||
if ($sHyperlink != '-') {
|
||||
$oPill->SetUrl($sHyperlink);
|
||||
}
|
||||
@@ -1601,6 +1611,7 @@ JS
|
||||
|
||||
$iTotalCount = 0;
|
||||
$aURLs = array();
|
||||
|
||||
foreach ($aRes as $iRow => $aRow) {
|
||||
$sValue = $aRow['grouped_by_1'];
|
||||
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
|
||||
@@ -1611,6 +1622,7 @@ JS
|
||||
'value' => (float)$aRow[$sFctVar],
|
||||
);
|
||||
|
||||
|
||||
// Build the search for this subset
|
||||
$oSubsetSearch = $this->m_oFilter->DeepClone();
|
||||
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($sValue));
|
||||
@@ -1627,9 +1639,13 @@ JS
|
||||
|
||||
switch ($sChartType) {
|
||||
case 'bars':
|
||||
$aNames = array();
|
||||
$iMaxNbCharsInLabel = 0;
|
||||
$aNames = [];
|
||||
foreach ($aValues as $idx => $aValue) {
|
||||
$aNames[$idx] = $aValue['label'];
|
||||
if ($iMaxNbCharsInLabel < mb_strlen($aValue['label'])) {
|
||||
$iMaxNbCharsInLabel = mb_strlen($aValue['label']);
|
||||
}
|
||||
}
|
||||
$oBlock = new BlockChartAjaxBars();
|
||||
$oBlock->sJSNames = json_encode($aNames);
|
||||
@@ -1637,21 +1653,31 @@ JS
|
||||
$oBlock->sId = $sId;
|
||||
$oBlock->sJSURLs = $sJSURLs;
|
||||
$oBlock->sURLForRefresh = str_replace("'", "\'", $sUrl);
|
||||
$oBlock->iMaxNbCharsInLabel = $iMaxNbCharsInLabel;
|
||||
break;
|
||||
|
||||
case 'pie':
|
||||
$aColumns = array();
|
||||
$aNames = array();
|
||||
$aColumns = [];
|
||||
$aNames = [];
|
||||
foreach ($aValues as $idx => $aValue) {
|
||||
$aColumns[] = array('series_'.$idx, (float)$aValue['value']);
|
||||
$aNames['series_'.$idx] = $aValue['label'];
|
||||
}
|
||||
|
||||
$iNbLinesToAddForName = 0;
|
||||
if (count($aNames) > 50) {
|
||||
// Calculation of the number of legends line add to the height of the graph to have a maximum of 5 legend columns
|
||||
$iNbLinesIncludedInChartHeight = 10;
|
||||
$iNbLinesToAddForName = ceil(count($aNames) / 5) - $iNbLinesIncludedInChartHeight;
|
||||
}
|
||||
|
||||
$oBlock = new BlockChartAjaxPie();
|
||||
$oBlock->sJSColumns = json_encode($aColumns);
|
||||
$oBlock->sJSNames = json_encode($aNames);
|
||||
$oBlock->sId = $sId;
|
||||
$oBlock->sJSURLs = $sJSURLs;
|
||||
$oBlock->sURLForRefresh = str_replace("'", "\'", $sUrl);
|
||||
$oBlock->iNbLinesToAddForName = $iNbLinesToAddForName;
|
||||
break;
|
||||
}
|
||||
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
|
||||
|
||||
@@ -9,6 +9,7 @@ use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/application/template.class.inc.php');
|
||||
require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
||||
require_once(APPROOT."/setup/parentmenunodecompiler.class.inc.php");
|
||||
|
||||
|
||||
/**
|
||||
@@ -103,7 +104,7 @@ class ApplicationMenu
|
||||
{
|
||||
self::$sFavoriteSiloQuery = $sOQL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the query used to limit the list of displayed organizations in the drop-down menu
|
||||
* @return string The OQL query returning a list of Organization objects
|
||||
@@ -273,12 +274,23 @@ class ApplicationMenu
|
||||
continue;
|
||||
}
|
||||
|
||||
$aSubMenuNodes = static::GetSubMenuNodes($sMenuGroupIdx, $aExtraParams);
|
||||
if (! ParentMenuNodeCompiler::$bUseLegacyMenuCompilation && !($oMenuNode instanceof ShortcutMenuNode)){
|
||||
if (is_array($aSubMenuNodes) && 0 === sizeof($aSubMenuNodes)){
|
||||
IssueLog::Error('Empty menu node not displayed', LogChannels::CONSOLE, [
|
||||
'menu_node_class' => get_class($oMenuNode),
|
||||
'menu_node_label' => $oMenuNode->GetLabel(),
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$aMenuGroups[] = [
|
||||
'sId' => $oMenuNode->GetMenuID(),
|
||||
'sIconCssClasses' => $oMenuNode->GetDecorationClasses(),
|
||||
'sInitials' => $oMenuNode->GetInitials(),
|
||||
'sTitle' => $oMenuNode->GetTitle(),
|
||||
'aSubMenuNodes' => static::GetSubMenuNodes($sMenuGroupIdx, $aExtraParams),
|
||||
'aSubMenuNodes' => $aSubMenuNodes,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -525,7 +537,7 @@ EOF
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the currently active menu (if any, otherwise the first menu is the default)
|
||||
* @return string The Id of the currently active menu
|
||||
@@ -533,7 +545,7 @@ EOF
|
||||
public static function GetActiveNodeId()
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
|
||||
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
|
||||
if ($sMenuId === null)
|
||||
{
|
||||
$sMenuId = self::GetDefaultMenuId();
|
||||
@@ -643,7 +655,7 @@ abstract class MenuNode
|
||||
|
||||
/**
|
||||
* Stimulus to check: if the user can 'apply' this stimulus, then she/he can see this menu
|
||||
*/
|
||||
*/
|
||||
protected $m_aEnableStimuli;
|
||||
|
||||
/**
|
||||
@@ -804,7 +816,7 @@ abstract class MenuNode
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a limiting display condition for the same menu node. The conditions will be combined with a AND
|
||||
* @param $oMenuNode MenuNode Another definition of the same menu node, with potentially different access restriction
|
||||
@@ -977,7 +989,7 @@ class TemplateMenuNode extends MenuNode
|
||||
* @var string
|
||||
*/
|
||||
protected $sTemplateFile;
|
||||
|
||||
|
||||
/**
|
||||
* Create a menu item based on a custom template and inserts it into the application's main menu
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
@@ -1048,7 +1060,7 @@ class OQLMenuNode extends MenuNode
|
||||
* @var bool|null
|
||||
*/
|
||||
protected $bSearchFormOpen;
|
||||
|
||||
|
||||
/**
|
||||
* Extra parameters to be passed to the display block to fine tune its appearence
|
||||
*/
|
||||
@@ -1081,7 +1093,7 @@ class OQLMenuNode extends MenuNode
|
||||
// Enhancement: we could set as the "enable" condition that the user has enough rights to "read" the objects
|
||||
// of the class specified by the OQL...
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set some extra parameters to be passed to the display block to fine tune its appearence
|
||||
* @param array $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
|
||||
@@ -1109,7 +1121,7 @@ class OQLMenuNode extends MenuNode
|
||||
'Menu_'.$this->GetMenuId(),
|
||||
$this->bSearch, // Search pane
|
||||
$this->bSearchFormOpen, // Search open
|
||||
$oPage,
|
||||
$oPage,
|
||||
array_merge($this->m_aParams, $aExtraParams),
|
||||
true
|
||||
);
|
||||
@@ -1343,10 +1355,10 @@ class NewObjectMenuNode extends MenuNode
|
||||
{
|
||||
// Enable this menu, only if the current user has enough rights to create such an object, or an object of
|
||||
// any child class
|
||||
|
||||
|
||||
$aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
||||
$bActionIsAllowed = false;
|
||||
|
||||
|
||||
foreach($aSubClasses as $sCandidateClass)
|
||||
{
|
||||
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
|
||||
@@ -1355,7 +1367,7 @@ class NewObjectMenuNode extends MenuNode
|
||||
break; // Enough for now
|
||||
}
|
||||
}
|
||||
return $bActionIsAllowed;
|
||||
return $bActionIsAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1497,7 +1509,7 @@ class DashboardMenuNode extends MenuNode
|
||||
throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1538,7 +1550,7 @@ class ShortcutContainerMenuNode extends MenuNode
|
||||
$sName = $this->GetMenuId().'_'.$oShortcut->GetKey();
|
||||
new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++);
|
||||
}
|
||||
|
||||
|
||||
// Complete the tree
|
||||
//
|
||||
parent::PopulateChildMenus();
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<div style="width:100%;background: #fff url(../images/welcome.jpg) top left no-repeat;">
|
||||
<style>
|
||||
.welcome_popup_cell {
|
||||
vertical-align:top;
|
||||
width:50%;
|
||||
border:0px solid #000;
|
||||
-moz-border-radius:10px;
|
||||
padding:5px;
|
||||
text-align:left;
|
||||
}
|
||||
tr td.welcome_popup_cell, tr td.welcome_popup_cell ul {
|
||||
font-size:10pt;
|
||||
}
|
||||
</style>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p style="text-align:left; font-size:32px;padding-left:400px;padding-top:40px;margin-bottom:30px;margin-top:0;color:#FFFFFF;"><itopstring>UI:WelcomeMenu:Title</itopstring></p>
|
||||
<p></p>
|
||||
<table border="0" style="padding:10px;border-spacing: 10px;width:100%">
|
||||
<tr>
|
||||
<td class="welcome_popup_cell">
|
||||
<itopstring>UI:WelcomeMenu:LeftBlock</itopstring>
|
||||
</td>
|
||||
<td class="welcome_popup_cell">
|
||||
<itopstring>UI:WelcomeMenu:RightBlock</itopstring>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -6,7 +6,6 @@ use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Twig_Environment;
|
||||
use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
@@ -111,22 +110,6 @@ class TwigExtension
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
}));
|
||||
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_config_parameter', function($sParamName)
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->Get($sParamName);
|
||||
}));
|
||||
|
||||
// Function to get a module setting
|
||||
// Usage in twig: {{ get_module_setting(<MODULE_CODE>, <PROPERTY_CODE> [, <DEFAULT_VALUE>]) }}
|
||||
// since 3.0.0, but see N°4034 for upcoming evolutions in the 3.1
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_module_setting', function (string $sModuleCode, string $sPropertyCode, $defaultValue = null) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->GetModuleSetting($sModuleCode, $sPropertyCode, $defaultValue);
|
||||
}));
|
||||
|
||||
// Function to get the URL of a static page in a module
|
||||
// Usage in twig: {{ get_static_page_module_url('itop-my-module', 'path-to-my-page') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_static_page_module_url', function($sModuleName, $sPage)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
@@ -323,12 +324,12 @@ EOF
|
||||
EOF
|
||||
);
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||
$sHTMLValue .= " <div class=\"ibo-input-select--action-button ibo-input-select--action-button--clear ibo-is-hidden\" id=\"mini_clear_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Clear();\" data-tooltip-content='".Dict::S('UI:Button:Clear')."'><i class=\"fas fa-times\"></i></div>";
|
||||
$sHTMLValue .= " <a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--clear ibo-is-hidden\" id=\"mini_clear_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Clear();\" data-tooltip-content='".Dict::S('UI:Button:Clear')."'><i class=\"fas fa-times\"></i></a>";
|
||||
}
|
||||
if ($bCreate && $bExtensions) {
|
||||
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
||||
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-button ibo-input-select--action-button--create\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\" data-tooltip-content='".Dict::S('UI:Button:Create')."'><i class=\"fas fa-plus\"></i></div>";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--create\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\" data-tooltip-content='".Dict::S('UI:Button:Create')."'><i class=\"fas fa-plus\"></i></a>";
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
if ($('#ajax_{$this->iId}').length == 0)
|
||||
@@ -339,7 +340,7 @@ JS
|
||||
);
|
||||
}
|
||||
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\" data-tooltip-content='".Dict::S('UI:Button:SearchInHierarchy')."'><i class=\"fas fa-sitemap\"></i></div>";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\" data-tooltip-content='".Dict::S('UI:Button:SearchInHierarchy')."'><i class=\"fas fa-sitemap\"></i></a>";
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
if ($('#ac_tree_{$this->iId}').length == 0)
|
||||
@@ -350,7 +351,7 @@ JS
|
||||
);
|
||||
}
|
||||
if ($oAllowedValues->CountExceeds($iMaxComboLength)) {
|
||||
$sHTMLValue .= " <div class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\" data-tooltip-content='".Dict::S('UI:Button:Search')."'><i class=\"fas fa-search\"></i></div>";
|
||||
$sHTMLValue .= " <a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\" data-tooltip-content='".Dict::S('UI:Button:Search')."'><i class=\"fas fa-search\"></i></a>";
|
||||
}
|
||||
$sHTMLValue .= "</div>";
|
||||
$sHTMLValue .= "</div>";
|
||||
@@ -904,7 +905,7 @@ JS
|
||||
{
|
||||
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
||||
// and that the current user is allowed to create objects of this class
|
||||
$aSubClasses = MetaModel::EnumChildClasses($this->sTargetClass);
|
||||
$aSubClasses = MetaModel::EnumChildClasses($this->sTargetClass, ENUM_CHILD_CLASSES_ALL);
|
||||
$aPossibleClasses = array();
|
||||
foreach($aSubClasses as $sCandidateClass)
|
||||
{
|
||||
@@ -924,6 +925,7 @@ JS
|
||||
$sDialogTitleEscaped = addslashes($sDialogTitle);
|
||||
$oPage->add_ready_script("$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitleEscaped'});\n");
|
||||
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').removeAttr('onsubmit');");
|
||||
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').find('select').attr('id', 'ac_create_{$this->iId}_select');");
|
||||
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,23 @@ class UILinksWidgetDirect
|
||||
$oObj = DBObject::MakeDefaultInstance($sRealClass);
|
||||
$aPrefillParam = array('source_obj' => $oSourceObj);
|
||||
$oObj->PrefillForm('creation_from_editinplace', $aPrefillParam);
|
||||
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, array(), array('formPrefix' => $this->sInputid, 'noRelations' => true, 'fieldsFlags' => $aFieldFlags));
|
||||
$aFormExtraParams = array(
|
||||
'formPrefix' => $this->sInputid,
|
||||
'noRelations' => true,
|
||||
'fieldsFlags' => $aFieldFlags,
|
||||
'js_handlers' => [
|
||||
'cancel_button_on_click' =>
|
||||
<<<JS
|
||||
function() {
|
||||
// Do nothing, already handled by linksdirectwidget.js
|
||||
};
|
||||
JS
|
||||
,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, array(), $aFormExtraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -100,15 +100,18 @@ class UILinksWidget
|
||||
* @param array $aArgs Extra context arguments
|
||||
* @param DBObject $oCurrentObj The object to which all the elements of the linked set refer to
|
||||
* @param int $iUniqueId A unique identifier of new links
|
||||
* @param boolean $bReadOnly Display link as editable or read-only. Default is false (editable)
|
||||
* @param bool $bReadOnly Display link as editable or read-only. Default is false (editable)
|
||||
* @param bool $bAllowRemoteExtKeyEdit If true, the ext. key to the remote object can be edited, otherwise it will be read-only
|
||||
*
|
||||
* @return array The HTML fragment of the one-row form
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 3.1.0 3.0.4 3.0.3-1 N°6124 - Workaround performance problem on the modification of an object with an n:n relation having a large volume
|
||||
*/
|
||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false)
|
||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false, $bAllowRemoteExtKeyEdit = true)
|
||||
{
|
||||
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
|
||||
$aRow = array();
|
||||
@@ -139,8 +142,11 @@ class UILinksWidget
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
|
||||
foreach ($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
// N°6124 - Force remote ext. key as read-only if too many items in the linkset
|
||||
$bReadOnlyField = ($sFieldCode === $this->m_sExtKeyToRemote) && (false === $bAllowRemoteExtKeyEdit);
|
||||
|
||||
$sSafeFieldId = $this->GetFieldId($linkObjOrId->GetKey(), $sFieldCode);
|
||||
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $linkObjOrId, $oP, $sNameSuffix, $sSafeFieldId);
|
||||
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $linkObjOrId, $oP, $sNameSuffix, $sSafeFieldId, $bReadOnlyField);
|
||||
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||
}
|
||||
}
|
||||
@@ -201,8 +207,11 @@ EOF
|
||||
|
||||
foreach($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
// N°6124 - Force remote ext. key as read-only if too many items in the linkset
|
||||
$bReadOnlyField = ($sFieldCode === $this->m_sExtKeyToRemote) && (false === $bAllowRemoteExtKeyEdit);
|
||||
|
||||
$sSafeFieldId = $this->GetFieldId($iUniqueId, $sFieldCode);
|
||||
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $oNewLinkObj, $oP, $sNameSuffix, $sSafeFieldId);
|
||||
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $oNewLinkObj, $oP, $sNameSuffix, $sSafeFieldId, $bReadOnlyField);
|
||||
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||
|
||||
$sValue = $oNewLinkObj->Get($sFieldCode);
|
||||
@@ -255,11 +264,24 @@ JS
|
||||
return $aRow;
|
||||
}
|
||||
|
||||
private function AddRowForFieldCode(&$aRow, $sFieldCode, &$aArgs, $oLnk, $oP, $sNameSuffix, $sSafeFieldId): void
|
||||
/**
|
||||
* @param $aRow
|
||||
* @param $sFieldCode
|
||||
* @param $aArgs
|
||||
* @param $oLnk
|
||||
* @param $oP
|
||||
* @param $sNameSuffix
|
||||
* @param $sSafeFieldId
|
||||
* @param bool $bReadOnlyField If true, the field will be read-only, otherwise it can be edited
|
||||
*
|
||||
* @return void
|
||||
* @since 3.1.0 3.0.4 3.0.3-1 N°6124 - Workaround performance problem on the modification of an object with an n:n relation having a large volume
|
||||
*/
|
||||
private function AddRowForFieldCode(&$aRow, $sFieldCode, &$aArgs, $oLnk, $oP, $sNameSuffix, $sSafeFieldId, $bReadOnlyField = false): void
|
||||
{
|
||||
if (($sFieldCode === $this->m_sExtKeyToRemote))
|
||||
{
|
||||
// current field is the lnk extkey to the remote class
|
||||
// Current field is the lnk extkey to the remote class
|
||||
$aArgs['replaceDependenciesByRemoteClassFields'] = true;
|
||||
$sRowFieldCode = 'static::key';
|
||||
$aArgs['wizHelperRemote'] = $aArgs['wizHelper'].'_remote';
|
||||
@@ -281,20 +303,31 @@ JS
|
||||
$sDisplayValue = $oLnk->GetEditValue($sFieldCode);
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
||||
|
||||
$aRow[$sRowFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'
|
||||
.cmdbAbstractObject::GetFormElementForField(
|
||||
$oP,
|
||||
$this->m_sLinkedClass,
|
||||
$sFieldCode,
|
||||
$oAttDef,
|
||||
$sValue,
|
||||
$sDisplayValue,
|
||||
$sSafeFieldId,
|
||||
$sNameSuffix,
|
||||
0,
|
||||
$aArgs
|
||||
)
|
||||
.'</div></div></div>';
|
||||
if ($bReadOnlyField) {
|
||||
$sFieldForHtml = $sDisplayValue;
|
||||
} else {
|
||||
$sFieldForHtml = cmdbAbstractObject::GetFormElementForField(
|
||||
$oP,
|
||||
$this->m_sLinkedClass,
|
||||
$sFieldCode,
|
||||
$oAttDef,
|
||||
$sValue,
|
||||
$sDisplayValue,
|
||||
$sSafeFieldId,
|
||||
$sNameSuffix,
|
||||
0,
|
||||
$aArgs
|
||||
);
|
||||
}
|
||||
|
||||
$aRow[$sRowFieldCode] = <<<HTML
|
||||
<div class="field_container" style="border:none;">
|
||||
<div class="field_data">
|
||||
<div class="field_value">$sFieldForHtml</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML
|
||||
;
|
||||
}
|
||||
|
||||
private function GetFieldId($iLnkId, $sFieldCode, $bSafe = true)
|
||||
@@ -374,6 +407,7 @@ JS
|
||||
$oBlock->sRemoteClass = $this->m_sRemoteClass;
|
||||
|
||||
$oValue->Rewind();
|
||||
$bAllowRemoteExtKeyEdit = $oValue->Count() <= utils::GetConfig()->Get('link_set_max_edit_ext_key');
|
||||
$aForm = array();
|
||||
$iMaxAddedId = 0;
|
||||
$iAddedId = -1; // Unique id for new links
|
||||
@@ -398,7 +432,7 @@ JS
|
||||
}
|
||||
|
||||
$iMaxAddedId = max($iMaxAddedId, $key);
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly, $bAllowRemoteExtKeyEdit);
|
||||
}
|
||||
$oBlock->iMaxAddedId = (int) $iMaxAddedId;
|
||||
|
||||
@@ -571,10 +605,11 @@ JS
|
||||
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||
|
||||
$iAdditionId = $iMaxAddedId + 1;
|
||||
$bAllowRemoteExtKeyEdit = count($aLinkedObjectIds) <= utils::GetConfig()->Get('link_set_max_edit_ext_key');
|
||||
foreach ($aLinkedObjectIds as $iObjectId) {
|
||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
|
||||
if (is_object($oLinkedObj)) {
|
||||
$aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids
|
||||
$aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId, false /* Default value */, $bAllowRemoteExtKeyEdit); // Not yet created link get negative Ids
|
||||
$aData = [];
|
||||
foreach ($aRow as $item) {
|
||||
$aData[] = $item;
|
||||
|
||||
@@ -60,7 +60,7 @@ class UISearchFormForeignKeys
|
||||
|
||||
$oPage->add(<<<HTML
|
||||
<form id="ObjectsAddForm_{$this->m_iInputId}">
|
||||
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
||||
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;">
|
||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
</div>
|
||||
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
||||
|
||||
@@ -158,7 +158,7 @@ class utils
|
||||
self::$m_aParamsFromFile = array();
|
||||
}
|
||||
|
||||
$aParamLines = explode("\n", $sParams);
|
||||
$aParamLines = explode("\n", $sParams ?? '');
|
||||
foreach ($aParamLines as $sLine)
|
||||
{
|
||||
$sLine = trim($sLine);
|
||||
@@ -1467,19 +1467,19 @@ class utils
|
||||
$oDashboard = $param;
|
||||
$sDashboardId = $oDashboard->GetId();
|
||||
$sDashboardFile = $oDashboard->GetDefinitionFile();
|
||||
$sDashboardFileRelative = utils::LocalPath($sDashboardFile);
|
||||
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
|
||||
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
|
||||
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
|
||||
$sDashboardFileJS = addslashes($sDashboardFile);
|
||||
$sDashboardFileURL = urlencode($sDashboardFile);
|
||||
$sDashboardFileJS = addslashes($sDashboardFileRelative);
|
||||
$sDashboardFileURL = urlencode($sDashboardFileRelative);
|
||||
$sUploadDashboardTransactId = utils::GetNewTransactionId();
|
||||
$aResult = array(
|
||||
new SeparatorPopupMenuItem(),
|
||||
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
|
||||
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
|
||||
);
|
||||
if ($oDashboard->GetReloadURL())
|
||||
{
|
||||
if ($oDashboard->GetReloadURL()) {
|
||||
$aResult[] = new SeparatorPopupMenuItem();
|
||||
$aResult[] = new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $oDashboard->GetReloadURL().'&printable=1', '_blank');
|
||||
}
|
||||
@@ -1687,7 +1687,7 @@ class utils
|
||||
// If cURL is available, let's use it, since it provides a greater control over the various HTTP/SSL options
|
||||
// For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112
|
||||
// by setting the SSLVERSION to 3 as done below.
|
||||
$aHeaders = explode("\n", $sOptionnalHeaders);
|
||||
$aHeaders = explode("\n", $sOptionnalHeaders ?? '');
|
||||
// N°3267 - Webservices: Fix optional headers not being taken into account
|
||||
// See https://www.php.net/curl_setopt CURLOPT_HTTPHEADER
|
||||
$aHTTPHeaders = array();
|
||||
@@ -1864,20 +1864,37 @@ class utils
|
||||
return html_entity_decode($sValue, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sValue value encoded with {@see self::EscapeHtml()}
|
||||
*
|
||||
* @return string decoded value
|
||||
*
|
||||
* @uses \htmlspecialchars_decode()
|
||||
* @link https://www.php.net/manual/en/function.htmlspecialchars-decode.php
|
||||
* @since 3.0.3 3.1.0 N°6020 method creation
|
||||
*/
|
||||
public static function EscapedHtmlDecode($sValue)
|
||||
{
|
||||
return htmlspecialchars_decode(
|
||||
$sValue,
|
||||
ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string containing some (valid) HTML markup to plain text
|
||||
*
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function HtmlToText($sHtml)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
//return '<?xml encoding="UTF-8">'.$sHtml;
|
||||
return \Html2Text\Html2Text::convert('<?xml encoding="UTF-8">'.$sHtml);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
@@ -2254,7 +2271,7 @@ class utils
|
||||
$aParams = array();
|
||||
foreach(explode('&', $sQuery) as $sChunk)
|
||||
{
|
||||
$aParts = explode('=', $sChunk);
|
||||
$aParts = explode('=', $sChunk ?? '');
|
||||
if (count($aParts) != 2) continue;
|
||||
$aParams[$aParts[0]] = urldecode($aParts[1]);
|
||||
}
|
||||
@@ -2401,7 +2418,7 @@ class utils
|
||||
$aCleanHeaders = array();
|
||||
foreach( $aHeaders as $sKey => $sValue )
|
||||
{
|
||||
$aTokens = explode(':', $sValue, 2);
|
||||
$aTokens = explode(':', $sValue ?? '', 2);
|
||||
if(isset($aTokens[1]))
|
||||
{
|
||||
$aCleanHeaders[trim($aTokens[0])] = trim($aTokens[1]);
|
||||
@@ -2745,12 +2762,18 @@ HTML;
|
||||
$bSkipped = true;
|
||||
}
|
||||
else {
|
||||
foreach ($aExcludedPath as $sExcludedPath) {
|
||||
// Note: We use '#' as delimiters as usual '/' is often used in paths.
|
||||
if ($sExcludedPath !== '' && preg_match('#'.$sExcludedPath.'#', $sPHPFile) === 1) {
|
||||
$bSkipped = true;
|
||||
break;
|
||||
$sPHPFile = self::LocalPath($sPHPFile);
|
||||
if ($sPHPFile !== false) {
|
||||
$sPHPFile = '/'.$sPHPFile; // for regex
|
||||
foreach ($aExcludedPath as $sExcludedPath) {
|
||||
// Note: We use '#' as delimiters as usual '/' is often used in paths.
|
||||
if ($sExcludedPath !== '' && preg_match('#'.$sExcludedPath.'#', $sPHPFile) === 1) {
|
||||
$bSkipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$bSkipped = true; // file not found
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2788,7 +2811,7 @@ HTML;
|
||||
$aResultPref = [];
|
||||
$aShortcutPrefs = appUserPreferences::GetPref('keyboard_shortcuts', []);
|
||||
// Note: Mind the 4 blackslashes, see utils::GetClassesForInterface()
|
||||
$aShortcutClasses = utils::GetClassesForInterface('iKeyboardShortcut', '', array('[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]'));
|
||||
$aShortcutClasses = utils::GetClassesForInterface('iKeyboardShortcut', '', array('[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]'));
|
||||
|
||||
foreach ($aShortcutClasses as $cShortcutPlugin) {
|
||||
$sTriggeredElement = $cShortcutPlugin::GetShortcutTriggeredElementSelector();
|
||||
@@ -2796,7 +2819,7 @@ HTML;
|
||||
$sKey = isset($aShortcutPrefs[$aShortcutKey['id']]) ? $aShortcutPrefs[$aShortcutKey['id']] : $aShortcutKey['key'];
|
||||
|
||||
// Format key for display
|
||||
$aKeyParts = explode('+', $sKey);
|
||||
$aKeyParts = explode('+', $sKey ?? '');
|
||||
$aFormattedKeyParts = [];
|
||||
foreach ($aKeyParts as $sKeyPart) {
|
||||
$aFormattedKeyParts[] = ucfirst(trim($sKeyPart));
|
||||
|
||||
@@ -23,6 +23,11 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.0');
|
||||
* @used-by utils::GetItopVersionWikiSyntax()
|
||||
* @used-by iTopModulesPhpVersionIntegrationTest
|
||||
*/
|
||||
define('ITOP_CORE_VERSION', '3.0.2');
|
||||
define('ITOP_CORE_VERSION', '3.0.3');
|
||||
|
||||
/**
|
||||
* @since 3.0.4 N°6274 Allow to test if PHPUnit is currently running. Starting with PHPUnit 9.5 we'll be able to replace it with $GLOBALS['phpunit_version']
|
||||
*/
|
||||
define('ITOP_PHPUNIT_RUNNING_CONSTANT_NAME', 'ITOP_PHPUNIT_RUNNING');
|
||||
|
||||
require_once APPROOT.'bootstrap.inc.php';
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"ext-mysqli": "*",
|
||||
"ext-soap": "*",
|
||||
"combodo/tcpdf": "~6.4.4",
|
||||
"firebase/php-jwt": "~6.4.0",
|
||||
"guzzlehttp/guzzle": "^6.5.8",
|
||||
"laminas/laminas-mail": "^2.11",
|
||||
"laminas/laminas-servicemanager": "^3.5",
|
||||
|
||||
26
composer.lock
generated
26
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "86ca84263f7f271dfc10e5e63bd02385",
|
||||
"content-hash": "bad4899b1df95e6ab4ab2e42e4213acd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "combodo/tcpdf",
|
||||
@@ -266,25 +266,31 @@
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "v5.5.1",
|
||||
"version": "v6.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/firebase/php-jwt.git",
|
||||
"reference": "83b609028194aa042ea33b5af2d41a7427de80e6"
|
||||
"reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6",
|
||||
"reference": "83b609028194aa042ea33b5af2d41a7427de80e6",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/4dd1e007f22a927ac77da5a3fbb067b42d3bc224",
|
||||
"reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": "^7.1||^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.8 <=9"
|
||||
"guzzlehttp/guzzle": "^6.5||^7.4",
|
||||
"phpspec/prophecy-phpunit": "^1.1",
|
||||
"phpunit/phpunit": "^7.5||^9.5",
|
||||
"psr/cache": "^1.0||^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures",
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -317,9 +323,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v5.5.1"
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v6.4.0"
|
||||
},
|
||||
"time": "2021-11-08T20:18:51+00:00"
|
||||
"time": "2023-02-09T21:01:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
@@ -4752,7 +4758,7 @@
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3 <8.0.0",
|
||||
"php": ">=7.1.3 <8.1.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
|
||||
@@ -110,7 +110,7 @@ class apcFile
|
||||
*/
|
||||
static public function GetCacheFileName($sKey = '')
|
||||
{
|
||||
$sPath = str_replace(array(' ', '/', '\\', '.'), '-', $sKey);
|
||||
$sPath = str_replace(array(' ', '/', '\\', '.'), '-', $sKey ?? '');
|
||||
return utils::GetCachePath().'apc-emul/'.$sPath;
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ abstract class AsyncTask extends DBObject
|
||||
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($this)];
|
||||
$bExponential = (bool)$aConfig['exponential_delay'] ?? $bExponential;
|
||||
$bExponential = (bool) ($aConfig['exponential_delay'] ?? $bExponential);
|
||||
}
|
||||
return $bExponential;
|
||||
}
|
||||
|
||||
@@ -705,6 +705,18 @@ abstract class AttributeDefinition
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $proposedValue
|
||||
*
|
||||
* @return bool True if $proposedValue is an actual value set in the attribute, false is the attribute remains "empty"
|
||||
* @since 3.0.3, 3.1.0 N°5784
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Default implementation, we don't really know what type $proposedValue will be
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing!
|
||||
*
|
||||
@@ -1384,6 +1396,15 @@ class AttributeDashboard extends AttributeDefinition
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Always return false for now, we don't consider a custom version of a dashboard
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2233,6 +2254,22 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @param \ormLinkSet $proposedValue
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormLinkSet))
|
||||
{
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// We test if there is at least 1 item in the linkset (new or existing), not if an item is being added to it.
|
||||
return $proposedValue->Count() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2614,6 +2651,14 @@ class AttributeInteger extends AttributeDBField
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -2713,6 +2758,14 @@ class AttributeObjectKey extends AttributeDBFieldVoid
|
||||
return ($proposedValue == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return ((int) $proposedValue) !== 0;
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -2912,6 +2965,14 @@ class AttributeDecimal extends AttributeDBField
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -3323,6 +3384,14 @@ class AttributeString extends AttributeDBField
|
||||
return ($proposedValue == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -4478,6 +4547,22 @@ class AttributeCaseLog extends AttributeLongText
|
||||
return ($proposedValue->GetText() == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @param \ormCaseLog $proposedValue
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormCaseLog)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// We test if there is at least 1 entry in the log, not if the user is adding one
|
||||
return $proposedValue->GetEntryCount() > 0;
|
||||
}
|
||||
|
||||
|
||||
public function ScalarToSQL($value)
|
||||
{
|
||||
if (!is_string($value) && !is_null($value))
|
||||
@@ -6798,6 +6883,14 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
return ($proposedValue == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return ((int) $proposedValue) !== 0;
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -7530,6 +7623,16 @@ class AttributeExternalField extends AttributeDefinition
|
||||
return $oExtAttDef->IsNull($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
|
||||
return $oExtAttDef->HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
@@ -7664,6 +7767,17 @@ class AttributeExternalField extends AttributeDefinition
|
||||
*/
|
||||
class AttributeURL extends AttributeString
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* SCHEME....... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH......................... GET............................................ ANCHOR..........................
|
||||
* Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor
|
||||
* @link http://www.php.net/manual/fr/function.preg-match.php#93824 regexp source
|
||||
* @since 3.0.1 N°4515 handle Alfresco and Sharepoint URLs
|
||||
* @since 3.0.3 moved from Config to AttributeURL constant
|
||||
*/
|
||||
public const DEFAULT_VALIDATION_PATTERN = /** @lang RegExp */
|
||||
'(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9:%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.,-]*)?(#[a-zA-Z0-9_.-][a-zA-Z0-9+\$_.-]*)?';
|
||||
|
||||
/**
|
||||
* Useless constructor, but if not present PHP 7.4.0/7.4.1 is crashing :( (N°2329)
|
||||
*
|
||||
@@ -8105,6 +8219,20 @@ class AttributeBlob extends AttributeDefinition
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
if (false === ($proposedValue instanceof ormDocument)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// Empty file (no content, just a filename) are supported since PR {@link https://github.com/Combodo/combodo-email-synchro/pull/17}, so we check for both empty content and empty filename to determine that a document has no value
|
||||
return utils::IsNotNullOrEmptyString($proposedValue->GetData()) && utils::IsNotNullOrEmptyString($proposedValue->GetFileName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9131,6 +9259,17 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// A stopwatch always has a value
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9616,6 +9755,23 @@ class AttributeOneWayPassword extends AttributeDefinition implements iAttributeN
|
||||
return '*****';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormPassword)) {
|
||||
// On object creation, the attribute value is "" instead of an ormPassword...
|
||||
if (is_string($proposedValue)) {
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return $proposedValue->IsEmpty() === false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Indexed array having two dimensions
|
||||
@@ -9665,6 +9821,15 @@ class AttributeTable extends AttributeDBField
|
||||
return (count($proposedValue) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return count($proposedValue) > 0;
|
||||
}
|
||||
|
||||
|
||||
public function GetEditValue($sValue, $oHostObj = null)
|
||||
{
|
||||
return '';
|
||||
@@ -10186,6 +10351,18 @@ abstract class AttributeSet extends AttributeDBFieldVoid
|
||||
return $proposedValue->Count() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
if (false === ($proposedValue instanceof ormSet)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return $proposedValue->Count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be overloaded for localized enums
|
||||
*
|
||||
@@ -12893,6 +13070,21 @@ class AttributeCustomFields extends AttributeDefinition
|
||||
|
||||
return $bEquals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormCustomFieldsValue)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return count($proposedValue->GetValues()) > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class AttributeArchiveFlag extends AttributeBoolean
|
||||
|
||||
@@ -11,7 +11,7 @@ define('UTF8_BOM', chr(239).chr(187).chr(191)); // 0xEF, 0xBB, 0xBF
|
||||
|
||||
/**
|
||||
* CellChangeSpec
|
||||
* A series of classes, keeping the information about a given cell: could it be changed or not (and why)?
|
||||
* A series of classes, keeping the information about a given cell: could it be changed or not (and why)?
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
@@ -42,6 +42,17 @@ abstract class CellChangeSpec
|
||||
return $this->m_sOql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
*/
|
||||
public function GetDisplayableValueAndDescription(): string
|
||||
{
|
||||
return sprintf("%s%s",
|
||||
$this->GetDisplayableValue(),
|
||||
$this->GetDescription()
|
||||
);
|
||||
}
|
||||
|
||||
abstract public function GetDescription();
|
||||
}
|
||||
|
||||
@@ -86,26 +97,90 @@ class CellStatus_Issue extends CellStatus_Modify
|
||||
parent::__construct($proposedValue, $previousValue);
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
public function GetDisplayableValue()
|
||||
{
|
||||
if (is_null($this->m_proposedValue))
|
||||
{
|
||||
return Dict::Format('UI:CSVReport-Value-SetIssue', $this->m_sReason);
|
||||
return Dict::Format('UI:CSVReport-Value-SetIssue');
|
||||
}
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue', $this->m_proposedValue, $this->m_sReason);
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue', \utils::EscapeHtml($this->m_proposedValue));
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
{
|
||||
return $this->m_sReason;
|
||||
}
|
||||
/*
|
||||
* @since 3.1.0 N°5305
|
||||
*/
|
||||
public function GetDisplayableValueAndDescription(): string
|
||||
{
|
||||
return sprintf("%s. %s",
|
||||
$this->GetDisplayableValue(),
|
||||
$this->GetDescription()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
{
|
||||
public function __construct()
|
||||
/** @var string|null $m_sAllowedValues */
|
||||
private $m_sAllowedValues;
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
* @var string $sSerializedSearch
|
||||
*/
|
||||
private $sSerializedSearch;
|
||||
|
||||
/** @var string|null $m_sTargetClass */
|
||||
private $m_sTargetClass;
|
||||
|
||||
/**
|
||||
* CellStatus_SearchIssue constructor.
|
||||
* @since 3.1.0 N°5305
|
||||
*
|
||||
* @param string $sOql : main message
|
||||
* @param string $sReason : main message
|
||||
* @param null $sClass : used for additional message that provides allowed values for current class $sClass
|
||||
* @param null $sAllowedValues : used for additional message that provides allowed values $sAllowedValues for current class
|
||||
*/
|
||||
public function __construct($sSerializedSearch, $sReason, $sClass=null, $sAllowedValues=null)
|
||||
{
|
||||
parent::__construct(null, null, null);
|
||||
parent::__construct(null, null, $sReason);
|
||||
$this->sSerializedSearch = $sSerializedSearch;
|
||||
$this->m_sAllowedValues = $sAllowedValues;
|
||||
$this->m_sTargetClass = $sClass;
|
||||
}
|
||||
|
||||
public function GetDisplayableValue()
|
||||
{
|
||||
if (null === $this->m_sReason) {
|
||||
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
|
||||
}
|
||||
|
||||
return $this->m_sReason;
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
{
|
||||
return Dict::S('UI:CSVReport-Value-NoMatch');
|
||||
if (\utils::IsNullOrEmptyString($this->m_sAllowedValues) ||
|
||||
\utils::IsNullOrEmptyString($this->m_sTargetClass)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return Dict::Format('UI:CSVReport-Value-NoMatch-PossibleValues', $this->m_sTargetClass, $this->m_sAllowedValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchLinkUrl()
|
||||
{
|
||||
return sprintf("UI.php?operation=search&filter=%s",
|
||||
rawurlencode($this->sSerializedSearch)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +201,24 @@ class CellStatus_NullIssue extends CellStatus_Issue
|
||||
class CellStatus_Ambiguous extends CellStatus_Issue
|
||||
{
|
||||
protected $m_iCount;
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
* @var string
|
||||
*/
|
||||
protected $sSerializedSearch;
|
||||
|
||||
public function __construct($previousValue, $iCount, $sOql)
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
*
|
||||
* @param $previousValue
|
||||
* @param int $iCount
|
||||
* @param string $sSerializedSearch
|
||||
*
|
||||
*/
|
||||
public function __construct($previousValue, $iCount, $sSerializedSearch)
|
||||
{
|
||||
$this->m_iCount = $iCount;
|
||||
$this->m_sQuery = $sOql;
|
||||
$this->sSerializedSearch = $sSerializedSearch;
|
||||
parent::__construct(null, $previousValue, '');
|
||||
}
|
||||
|
||||
@@ -139,12 +227,23 @@ class CellStatus_Ambiguous extends CellStatus_Issue
|
||||
$sCount = $this->m_iCount;
|
||||
return Dict::Format('UI:CSVReport-Value-Ambiguous', $sCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchLinkUrl()
|
||||
{
|
||||
return sprintf("UI.php?operation=search&filter=%s",
|
||||
rawurlencode($this->sSerializedSearch)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* RowStatus
|
||||
* A series of classes, keeping the information about a given row: could it be changed or not (and why)?
|
||||
* A series of classes, keeping the information about a given row: could it be changed or not (and why)?
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
@@ -211,6 +310,26 @@ class RowStatus_Issue extends RowStatus
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* class dedicated to testability
|
||||
* not used/ignored in csv imports UI/CLI
|
||||
* @since 3.1.0 N°5305
|
||||
*/
|
||||
class RowStatus_Error extends RowStatus
|
||||
{
|
||||
/** @var string */
|
||||
protected $m_sError;
|
||||
|
||||
public function __construct($sError)
|
||||
{
|
||||
$this->m_sError = $sError;
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
{
|
||||
return $this->m_sError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BulkChange
|
||||
@@ -220,17 +339,35 @@ class RowStatus_Issue extends RowStatus
|
||||
*/
|
||||
class BulkChange
|
||||
{
|
||||
protected $m_sClass;
|
||||
/** @var string */
|
||||
protected $m_sClass;
|
||||
protected $m_aData; // Note: hereafter, iCol maybe actually be any acceptable key (string)
|
||||
// #@# todo: rename the variables to sColIndex
|
||||
protected $m_aAttList; // attcode => iCol
|
||||
protected $m_aExtKeys; // aExtKeys[sExtKeyAttCode][sExtReconcKeyAttCode] = iCol;
|
||||
protected $m_aReconcilKeys; // attcode (attcode = 'id' for the pkey)
|
||||
protected $m_sSynchroScope; // OQL - if specified, then the missing items will be reported
|
||||
protected $m_aOnDisappear; // array of attcode => value, values to be set when an object gets out of scope (ignored if no scope has been defined)
|
||||
protected $m_sDateFormat; // Date format specification, see DateTime::createFromFormat
|
||||
protected $m_bLocalizedValues; // Values in the data set are localized (see AttributeEnum)
|
||||
protected $m_aExtKeysMappingCache; // Cache for resolving external keys based on the given search criterias
|
||||
/** @var array<string, string> attcode as key, iCol as value */
|
||||
protected $m_aAttList;
|
||||
/** @var array<string, array<string, string>> sExtKeyAttCode as key, array of sExtReconcKeyAttCode/iCol as value */
|
||||
protected $m_aExtKeys;
|
||||
/** @var string[] list of attcode (attcode = 'id' for the pkey) */
|
||||
protected $m_aReconcilKeys;
|
||||
/** @var string OQL - if specified, then the missing items will be reported */
|
||||
protected $m_sSynchroScope;
|
||||
/**
|
||||
* @var array<string, mixed> attcode as key, attvalue as value. Values to be set when an object gets out of scope
|
||||
* (ignored if no scope has been defined)
|
||||
*/
|
||||
protected $m_aOnDisappear;
|
||||
/**
|
||||
* @see DateTime::createFromFormat
|
||||
* @var string Date format specification
|
||||
*/
|
||||
protected $m_sDateFormat;
|
||||
/**
|
||||
* @see AttributeEnum
|
||||
* @var boolean true if Values in the data set are localized
|
||||
*/
|
||||
protected $m_bLocalizedValues;
|
||||
/** @var array Cache for resolving external keys based on the given search criterias */
|
||||
protected $m_aExtKeysMappingCache;
|
||||
|
||||
public function __construct($sClass, $aData, $aAttList, $aExtKeys, $aReconcilKeys, $sSynchroScope = null, $aOnDisappear = null, $sDateFormat = null, $bLocalize = false)
|
||||
{
|
||||
@@ -261,30 +398,30 @@ class BulkChange
|
||||
$this->m_sReportCsvSep = $sSeparator;
|
||||
$this->m_sReportCsvDelimiter = $sDelimiter;
|
||||
}
|
||||
|
||||
|
||||
protected function ResolveExternalKey($aRowData, $sAttCode, &$aResults)
|
||||
{
|
||||
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
$oReconFilter = new DBObjectSearch($oExtKey->GetTargetClass());
|
||||
foreach ($this->m_aExtKeys[$sAttCode] as $sForeignAttCode => $iCol)
|
||||
foreach ($this->m_aExtKeys[$sAttCode] as $sReconKeyAttCode => $iCol)
|
||||
{
|
||||
if ($sForeignAttCode == 'id')
|
||||
if ($sReconKeyAttCode == 'id')
|
||||
{
|
||||
$value = (int) $aRowData[$iCol];
|
||||
}
|
||||
else
|
||||
{
|
||||
// The foreign attribute is one of our reconciliation key
|
||||
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
|
||||
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sReconKeyAttCode);
|
||||
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
|
||||
}
|
||||
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
|
||||
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
|
||||
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
}
|
||||
|
||||
$oExtObjects = new CMDBObjectSet($oReconFilter);
|
||||
$aKeys = $oExtObjects->ToArray();
|
||||
return array($oReconFilter->ToOql(), $aKeys);
|
||||
return array($oReconFilter, $aKeys);
|
||||
}
|
||||
|
||||
// Returns true if the CSV data specifies that the external key must be left undefined
|
||||
@@ -318,10 +455,10 @@ class BulkChange
|
||||
{
|
||||
$aResults = array();
|
||||
$aErrors = array();
|
||||
|
||||
|
||||
// External keys reconciliation
|
||||
//
|
||||
foreach($this->m_aExtKeys as $sAttCode => $aKeyConfig)
|
||||
foreach($this->m_aExtKeys as $sAttCode => $aReconKeys)
|
||||
{
|
||||
// Skip external keys used for the reconciliation process
|
||||
// if (!array_key_exists($sAttCode, $this->m_aAttList)) continue;
|
||||
@@ -330,7 +467,7 @@ class BulkChange
|
||||
|
||||
if ($this->IsNullExternalKeySpec($aRowData, $sAttCode))
|
||||
{
|
||||
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
|
||||
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
|
||||
{
|
||||
// Default reporting
|
||||
// $aRowData[$iCol] is always null
|
||||
@@ -352,25 +489,24 @@ class BulkChange
|
||||
$oReconFilter = new DBObjectSearch($oExtKey->GetTargetClass());
|
||||
|
||||
$aCacheKeys = array();
|
||||
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
|
||||
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
|
||||
{
|
||||
// The foreign attribute is one of our reconciliation key
|
||||
if ($sForeignAttCode == 'id')
|
||||
if ($sReconKeyAttCode == 'id')
|
||||
{
|
||||
$value = $aRowData[$iCol];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
|
||||
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sReconKeyAttCode);
|
||||
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
|
||||
}
|
||||
$aCacheKeys[] = $value;
|
||||
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
|
||||
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
|
||||
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
}
|
||||
$sCacheKey = implode('_|_', $aCacheKeys); // Unique key for this query...
|
||||
$iForeignKey = null;
|
||||
$sOQL = '';
|
||||
// TODO: check if *too long* keys can lead to collisions... and skip the cache in such a case...
|
||||
if (!array_key_exists($sAttCode, $this->m_aExtKeysMappingCache))
|
||||
{
|
||||
@@ -379,9 +515,8 @@ class BulkChange
|
||||
if (array_key_exists($sCacheKey, $this->m_aExtKeysMappingCache[$sAttCode]))
|
||||
{
|
||||
// Cache hit
|
||||
$iCount = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['c'];
|
||||
$iObjectFoundCount = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['c'];
|
||||
$iForeignKey = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['k'];
|
||||
$sOQL = $this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['oql'];
|
||||
// Record the hit
|
||||
$this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey]['h']++;
|
||||
}
|
||||
@@ -389,34 +524,35 @@ class BulkChange
|
||||
{
|
||||
// Cache miss, let's initialize it
|
||||
$oExtObjects = new CMDBObjectSet($oReconFilter);
|
||||
$iCount = $oExtObjects->Count();
|
||||
if ($iCount == 1)
|
||||
$iObjectFoundCount = $oExtObjects->Count();
|
||||
if ($iObjectFoundCount == 1)
|
||||
{
|
||||
$oForeignObj = $oExtObjects->Fetch();
|
||||
$iForeignKey = $oForeignObj->GetKey();
|
||||
}
|
||||
$this->m_aExtKeysMappingCache[$sAttCode][$sCacheKey] = array(
|
||||
'c' => $iCount,
|
||||
'c' => $iObjectFoundCount,
|
||||
'k' => $iForeignKey,
|
||||
'oql' => $oReconFilter->ToOql(),
|
||||
'h' => 0, // number of hits on this cache entry
|
||||
);
|
||||
}
|
||||
switch($iCount)
|
||||
switch($iObjectFoundCount)
|
||||
{
|
||||
case 0:
|
||||
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-NotFound');
|
||||
$aResults[$sAttCode]= new CellStatus_SearchIssue();
|
||||
break;
|
||||
|
||||
$oCellStatus_SearchIssue = $this->GetCellSearchIssue($oReconFilter);
|
||||
$aResults[$sAttCode] = $oCellStatus_SearchIssue;
|
||||
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-NotFound');
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Do change the external key attribute
|
||||
$oTargetObj->Set($sAttCode, $iForeignKey);
|
||||
break;
|
||||
|
||||
// Do change the external key attribute
|
||||
$oTargetObj->Set($sAttCode, $iForeignKey);
|
||||
break;
|
||||
|
||||
default:
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $iCount);
|
||||
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $iCount, $sOQL);
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $iObjectFoundCount);
|
||||
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $iObjectFoundCount, $oReconFilter->serialize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +569,7 @@ class BulkChange
|
||||
else
|
||||
{
|
||||
$aResults[$sAttCode]= new CellStatus_Modify($iForeignObj, $oTargetObj->GetOriginal($sAttCode));
|
||||
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
|
||||
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
|
||||
{
|
||||
// Report the change on reconciliation values as well
|
||||
$aResults[$iCol] = new CellStatus_Modify(utils::HtmlEntities($aRowData[$iCol]));
|
||||
@@ -446,7 +582,7 @@ class BulkChange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the object attributes
|
||||
//
|
||||
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
||||
@@ -467,27 +603,27 @@ class BulkChange
|
||||
$iFlags = ($oTargetObj->IsNew())
|
||||
? $oTargetObj->GetInitialStateAttributeFlags($sAttCode, $aReasons)
|
||||
: $oTargetObj->GetAttributeFlags($sAttCode, $aReasons);
|
||||
if ( (($iFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY) && ( $oTargetObj->Get($sAttCode) != $aRowData[$iCol]) ) {
|
||||
if ((($iFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY) && ($oTargetObj->Get($sAttCode) != $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues))) {
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-Readonly', $sAttCode, $oTargetObj->Get($sAttCode), $aRowData[$iCol]);
|
||||
}
|
||||
else if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
|
||||
{
|
||||
try
|
||||
{
|
||||
} else if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect()) {
|
||||
try {
|
||||
$oSet = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
|
||||
$oTargetObj->Set($sAttCode, $oSet);
|
||||
}
|
||||
catch(CoreException $e)
|
||||
{
|
||||
catch (CoreException $e) {
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-Format', $e->getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$value = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
|
||||
if (is_null($value) && (strlen($aRowData[$iCol]) > 0))
|
||||
{
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-NoMatch', $sAttCode);
|
||||
if ($oAttDef instanceof AttributeEnum || $oAttDef instanceof AttributeTagSet){
|
||||
/** @var AttributeDefinition $oAttributeDefinition */
|
||||
$oAttributeDefinition = $oAttDef;
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-AllowedValues', $sAttCode, implode(',', $oAttributeDefinition->GetAllowedValues()));
|
||||
} else {
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-NoMatch', $sAttCode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -504,7 +640,7 @@ class BulkChange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reporting on fields
|
||||
//
|
||||
$aChangedFields = $oTargetObj->ListChanges();
|
||||
@@ -556,7 +692,7 @@ class BulkChange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Checks
|
||||
//
|
||||
$res = $oTargetObj->CheckConsistency();
|
||||
@@ -567,12 +703,101 @@ class BulkChange
|
||||
}
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* search with current permissions did not match
|
||||
* let's search why and give some more feedbacks to the user through proper labels
|
||||
*
|
||||
* @param DBObjectSearch $oDbSearchWithConditions search used to find external key
|
||||
*
|
||||
* @return \CellStatus_SearchIssue
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*
|
||||
* @since 3.1.0 N°5305
|
||||
*/
|
||||
protected function GetCellSearchIssue($oDbSearchWithConditions) : CellStatus_SearchIssue {
|
||||
//current search with current permissions did not match
|
||||
//let's search why and give some more feedback to the user
|
||||
|
||||
$sSerializedSearch = $oDbSearchWithConditions->serialize();
|
||||
|
||||
// Count all objects with all permissions without any condition
|
||||
$oDbSearchWithoutAnyCondition = new DBObjectSearch($oDbSearchWithConditions->GetClass());
|
||||
$oDbSearchWithoutAnyCondition->AllowAllData(true);
|
||||
$oExtObjectSet = new CMDBObjectSet($oDbSearchWithoutAnyCondition);
|
||||
$iAllowAllDataObjectCount = $oExtObjectSet->Count();
|
||||
|
||||
if ($iAllowAllDataObjectCount === 0) {
|
||||
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject', $oDbSearchWithConditions->GetClass());
|
||||
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
|
||||
}
|
||||
|
||||
// Count all objects with current user permissions
|
||||
$oDbSearchWithoutAnyCondition->AllowAllData(false);
|
||||
$oExtObjectSetWithCurrentUserPermissions = new CMDBObjectSet($oDbSearchWithoutAnyCondition);
|
||||
$iCurrentUserRightsObjectCount = $oExtObjectSetWithCurrentUserPermissions->Count();
|
||||
|
||||
if ($iCurrentUserRightsObjectCount === 0){
|
||||
// No objects visible by current user
|
||||
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject-ForCurrentUser', $oDbSearchWithConditions->GetClass());
|
||||
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
|
||||
}
|
||||
|
||||
try{
|
||||
$aDisplayedAllowedValues = [];
|
||||
// Possibles values are displayed to UI user. we have to limit the amount of displayed values
|
||||
$oExtObjectSetWithCurrentUserPermissions->SetLimit(4);
|
||||
for($i = 0; $i < 3; $i++){
|
||||
/** @var \DBObject $oVisibleObject */
|
||||
$oVisibleObject = $oExtObjectSetWithCurrentUserPermissions->Fetch();
|
||||
if (is_null($oVisibleObject)){
|
||||
break;
|
||||
}
|
||||
|
||||
$aCurrentAllowedValueFields = [];
|
||||
foreach ($oDbSearchWithConditions->GetInternalParams() as $sForeignAttCode => $sValue){
|
||||
$aCurrentAllowedValueFields[] = $oVisibleObject->Get($sForeignAttCode);
|
||||
}
|
||||
$aDisplayedAllowedValues[] = implode(" ", $aCurrentAllowedValueFields);
|
||||
|
||||
}
|
||||
$allowedValues = implode(", ", $aDisplayedAllowedValues);
|
||||
if ($oExtObjectSetWithCurrentUserPermissions->Count() > 3){
|
||||
$allowedValues .= "...";
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
IssueLog::Error("failure during CSV import when fetching few visible objects: ", null,
|
||||
[ 'target_class' => $oDbSearchWithConditions->GetClass(), 'criteria' => $oDbSearchWithConditions->GetCriteria(), 'message' => $e->getMessage()]
|
||||
);
|
||||
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-NoObject-ForCurrentUser', $oDbSearchWithConditions->GetClass());
|
||||
return new CellStatus_SearchIssue($sSerializedSearch, $sReason);
|
||||
}
|
||||
|
||||
if ($iAllowAllDataObjectCount != $iCurrentUserRightsObjectCount) {
|
||||
// No match and some objects NOT visible by current user. including current search maybe...
|
||||
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch-SomeObjectNotVisibleForCurrentUser', $oDbSearchWithConditions->GetClass());
|
||||
return new CellStatus_SearchIssue($sSerializedSearch, $sReason, $oDbSearchWithConditions->GetClass(), $allowedValues);
|
||||
}
|
||||
|
||||
// No match. This is not linked to any right issue
|
||||
// Possible values: DD,DD
|
||||
$aCurrentValueFields = [];
|
||||
foreach ($oDbSearchWithConditions->GetInternalParams() as $sValue){
|
||||
$aCurrentValueFields[] = $sValue;
|
||||
}
|
||||
$value =implode(" ", $aCurrentValueFields);
|
||||
$sReason = Dict::Format('UI:CSVReport-Value-NoMatch', $value);
|
||||
return new CellStatus_SearchIssue($sSerializedSearch, $sReason, $oDbSearchWithConditions->GetClass(), $allowedValues);
|
||||
}
|
||||
|
||||
protected function PrepareMissingObject(&$oTargetObj, &$aErrors)
|
||||
{
|
||||
$aResults = array();
|
||||
$aErrors = array();
|
||||
|
||||
|
||||
// External keys
|
||||
//
|
||||
foreach($this->m_aExtKeys as $sAttCode => $aKeyConfig)
|
||||
@@ -585,7 +810,7 @@ class BulkChange
|
||||
$aResults[$iCol] = new CellStatus_Void('?');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update attributes
|
||||
//
|
||||
foreach($this->m_aOnDisappear as $sAttCode => $value)
|
||||
@@ -596,7 +821,7 @@ class BulkChange
|
||||
}
|
||||
$oTargetObj->Set($sAttCode, $value);
|
||||
}
|
||||
|
||||
|
||||
// Reporting on fields
|
||||
//
|
||||
$aChangedFields = $oTargetObj->ListChanges();
|
||||
@@ -616,7 +841,7 @@ class BulkChange
|
||||
$aResults[$iCol]= new CellStatus_Void($oTargetObj->Get($sAttCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Checks
|
||||
//
|
||||
$res = $oTargetObj->CheckConsistency();
|
||||
@@ -674,14 +899,16 @@ class BulkChange
|
||||
}
|
||||
|
||||
$aResult[$iRow] = $this->PrepareObject($oTargetObj, $aRowData, $aErrors);
|
||||
|
||||
|
||||
if (count($aErrors) > 0)
|
||||
{
|
||||
$sErrors = implode(', ', $aErrors);
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
|
||||
//__ERRORS__ used by tests only
|
||||
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
|
||||
return $oTargetObj;
|
||||
}
|
||||
|
||||
|
||||
// Check that any external key will have a value proposed
|
||||
$aMissingKeys = array();
|
||||
foreach (MetaModel::GetExternalKeys($this->m_sClass) as $sExtKeyAttCode => $oExtKey)
|
||||
@@ -689,7 +916,7 @@ class BulkChange
|
||||
if (!$oExtKey->IsNullAllowed())
|
||||
{
|
||||
if (!array_key_exists($sExtKeyAttCode, $this->m_aExtKeys) && !array_key_exists($sExtKeyAttCode, $this->m_aAttList))
|
||||
{
|
||||
{
|
||||
$aMissingKeys[] = $oExtKey->GetLabel();
|
||||
}
|
||||
}
|
||||
@@ -745,14 +972,16 @@ class BulkChange
|
||||
{
|
||||
$sErrors = implode(', ', $aErrors);
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
|
||||
//__ERRORS__ used by tests only
|
||||
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$aChangedFields = $oTargetObj->ListChanges();
|
||||
if (count($aChangedFields) > 0)
|
||||
{
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Modify(count($aChangedFields));
|
||||
|
||||
|
||||
// Optionaly record the results
|
||||
//
|
||||
if ($oChange)
|
||||
@@ -794,9 +1023,11 @@ class BulkChange
|
||||
{
|
||||
$sErrors = implode(', ', $aErrors);
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
|
||||
//__ERRORS__ used by tests only
|
||||
$aResult[$iRow]["__ERRORS__"] = new RowStatus_Error($sErrors);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$aChangedFields = $oTargetObj->ListChanges();
|
||||
if (count($aChangedFields) > 0)
|
||||
{
|
||||
@@ -821,7 +1052,7 @@ class BulkChange
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Disappeared(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function Process(CMDBChange $oChange = null)
|
||||
{
|
||||
if ($oChange)
|
||||
@@ -866,7 +1097,7 @@ class BulkChange
|
||||
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
||||
{
|
||||
if ($sAttCode == 'id') continue;
|
||||
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
|
||||
{
|
||||
@@ -881,14 +1112,18 @@ class BulkChange
|
||||
$sFormat = $sDateFormat;
|
||||
}
|
||||
$oFormat = new DateTimeFormat($sFormat);
|
||||
$sDateExample = $oFormat->Format(new DateTime('2022-10-23 16:25:33'));
|
||||
$sRegExp = $oFormat->ToRegExpr('/');
|
||||
if (!preg_match($sRegExp, $this->m_aData[$iRow][$iCol]))
|
||||
$sErrorMsg = Dict::Format('UI:CSVReport-Row-Issue-ExpectedDateFormat', $sDateExample);
|
||||
if (!preg_match($sRegExp, $sValue))
|
||||
{
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue(utils::HtmlEntities($sValue), null, $sErrorMsg);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDate = DateTime::createFromFormat($sFormat, $this->m_aData[$iRow][$iCol]);
|
||||
$oDate = DateTime::createFromFormat($sFormat, $sValue);
|
||||
if ($oDate !== false)
|
||||
{
|
||||
$sNewDate = $oDate->format($oAttDef->GetInternalFormat());
|
||||
@@ -898,7 +1133,7 @@ class BulkChange
|
||||
{
|
||||
// Leave the cell unchanged
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, utils::HtmlEntities($this->m_aData[$iRow][$iCol]), Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -952,23 +1187,26 @@ class BulkChange
|
||||
else
|
||||
{
|
||||
// The value has to be found or verified
|
||||
list($sQuery, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
|
||||
|
||||
|
||||
/** var DBObjectSearch $oReconFilter */
|
||||
list($oReconFilter, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
|
||||
|
||||
if (count($aMatches) == 1)
|
||||
{
|
||||
$oRemoteObj = reset($aMatches); // first item
|
||||
$valuecondition = $oRemoteObj->GetKey();
|
||||
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oRemoteObj->GetKey());
|
||||
}
|
||||
}
|
||||
elseif (count($aMatches) == 0)
|
||||
{
|
||||
$aResult[$iRow][$sAttCode] = new CellStatus_SearchIssue();
|
||||
}
|
||||
$oCellStatus_SearchIssue = $this->GetCellSearchIssue($oReconFilter);
|
||||
$aResult[$iRow][$sAttCode] = $oCellStatus_SearchIssue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $sQuery);
|
||||
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $oReconFilter->serialize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -990,7 +1228,7 @@ class BulkChange
|
||||
}
|
||||
else
|
||||
{
|
||||
$oReconciliationFilter->AddCondition($sAttCode, $valuecondition, '=');
|
||||
$oReconciliationFilter->AddCondition($sAttCode, $valuecondition, '=', true);
|
||||
}
|
||||
}
|
||||
if ($bSkipQuery)
|
||||
@@ -1019,7 +1257,7 @@ class BulkChange
|
||||
default:
|
||||
// Found several matches, ambiguous
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Ambiguous'));
|
||||
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->ToOql());
|
||||
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->serialize());
|
||||
$aResult[$iRow]["finalclass"]= 'n/a';
|
||||
}
|
||||
}
|
||||
@@ -1110,7 +1348,7 @@ class BulkChange
|
||||
}
|
||||
}
|
||||
$oBulkChanges->Seek(0);
|
||||
|
||||
|
||||
$aDetails = array();
|
||||
while ($oChange = $oBulkChanges->Fetch())
|
||||
{
|
||||
@@ -1274,7 +1512,7 @@ EOF
|
||||
$oOldTarget = MetaModel::GetObject($oAttDef->GetTargetClass(), $oOperation->Get('oldvalue'));
|
||||
$sOldValue = $oOldTarget->GetHyperlink();
|
||||
}
|
||||
|
||||
|
||||
$sNewValue = Dict::S('UI:UndefinedObject');
|
||||
if ($oOperation->Get('newvalue') != 0)
|
||||
{
|
||||
@@ -1300,11 +1538,11 @@ EOF
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAttributes[$sAttCode] = 1;
|
||||
$aAttributes[$sAttCode] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aDetails = array();
|
||||
foreach($aObjects as $iUId => $aObjData)
|
||||
{
|
||||
@@ -1356,6 +1594,6 @@ EOF
|
||||
$aConfig[$sAttCode] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'description' => MetaModel::GetDescription($sClass, $sAttCode));
|
||||
}
|
||||
$oPage->table($aConfig, $aDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
||||
$sDisplayLabel = Dict::S('UI:OpenDocumentInNewWindow_');
|
||||
$sDisplayUrl = $oPrevDoc->GetDisplayURL(get_class($this), $this->GetKey(), 'prevdata');
|
||||
|
||||
$sDownloadLabel = Dict::Format('UI:DownloadDocument_');
|
||||
$sDownloadLabel = Dict::S('UI:DownloadDocument_');
|
||||
$sDownloadUrl = $oPrevDoc->GetDownloadURL(get_class($this), $this->GetKey(), 'prevdata');
|
||||
|
||||
$sDocView = <<<HTML
|
||||
|
||||
@@ -480,6 +480,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'link_set_max_edit_ext_key' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Maximum number of items in the link that allow editing the remote external key. Above that limit, remote external key cannot be edited. Mind that setting this limit too high can have a negative impact on performances.',
|
||||
'default' => 50,
|
||||
'value' => 50,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'tag_set_item_separator' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Tag set from string: tag label separator',
|
||||
@@ -576,13 +584,29 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'email_css' => [
|
||||
'type' => 'string',
|
||||
'description' => 'CSS that will override the standard stylesheet used for the notifications',
|
||||
'default' => "",
|
||||
'value' => "",
|
||||
'email_transport_smtp.allow_self_signed' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'Allow self signed peer certificates',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'email_transport_smtp.verify_peer' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'Verify peer certificate',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'email_css' => [
|
||||
'type' => 'string',
|
||||
'description' => 'CSS that will override the standard stylesheet used for the notifications',
|
||||
'default' => "",
|
||||
'value' => "",
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'email_default_sender_address' => [
|
||||
'type' => 'string',
|
||||
@@ -883,16 +907,11 @@ class Config
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'url_validation_pattern' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
|
||||
'default' => /** @lang RegExp */
|
||||
'(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9:%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z0-9_.-][a-zA-Z0-9+\$_.-]*)?',
|
||||
// SCHEME....... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH......................... GET............................................ ANCHOR..........................
|
||||
// Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor
|
||||
// RegExp source: http://www.php.net/manual/fr/function.preg-match.php#93824
|
||||
// Update with N°4515
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'type' => 'string',
|
||||
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
|
||||
'default' => AttributeURL::DEFAULT_VALIDATION_PATTERN,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'email_validation_pattern' => [
|
||||
@@ -1238,6 +1257,22 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'navigation_menu.show_organization_filter' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Display organization filter in menu',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'navigation_menu.sorted_popup_user_menu_items' => [
|
||||
'type' => 'array',
|
||||
'description' => 'Sort user menu items after setup on page load',
|
||||
'default' => [],
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'quick_create.enabled' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Whether or not the quick create is enabled',
|
||||
@@ -1416,6 +1451,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'allow_rest_services_via_tokens' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'When set to true, REST endpoint token authorization works even with secure_rest_services set.',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'search_manual_submit' => [
|
||||
'type' => 'array',
|
||||
'description' => 'Force manual submit of search all requests',
|
||||
@@ -1861,7 +1904,7 @@ class Config
|
||||
}
|
||||
if (strlen($sNoise) > 0)
|
||||
{
|
||||
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
|
||||
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
|
||||
throw new ConfigException('Syntax error in configuration file',
|
||||
array('file' => $sConfigFile, 'error' => '<tt>'.htmlentities($sNoise, ENT_QUOTES, 'UTF-8').'</tt>'));
|
||||
}
|
||||
@@ -2671,7 +2714,7 @@ class ConfigPlaceholdersResolver
|
||||
}
|
||||
|
||||
$sPattern = '/\%(env|server)\((\w+)\)(?:\?:(\w*))?\%/'; //3 capturing groups, ie `%env(HTTP_PORT)?:8080%` produce: `env` `HTTP_PORT` and `8080`.
|
||||
|
||||
|
||||
if (! preg_match_all($sPattern, $rawValue, $aMatchesCollection, PREG_SET_ORDER))
|
||||
{
|
||||
return $rawValue;
|
||||
|
||||
@@ -396,6 +396,8 @@ abstract class DBObject implements iDisplay
|
||||
$this->m_aOrigValues = array();
|
||||
$this->m_aLoadedAtt = array();
|
||||
$this->m_bCheckStatus = true;
|
||||
$this->m_aCheckIssues = [];
|
||||
$this->m_bSecurityIssue = [];
|
||||
|
||||
// Get the key
|
||||
//
|
||||
@@ -1929,7 +1931,7 @@ abstract class DBObject implements iDisplay
|
||||
/** @var \AttributeExternalKey $oAtt */
|
||||
$sTargetClass = $oAtt->GetTargetClass();
|
||||
if (false === MetaModel::IsObjectInDB($sTargetClass, $toCheck)) {
|
||||
return "Target object not found (".$sTargetClass.".::".$toCheck.")";
|
||||
return "Target object not found ({$sTargetClass}::{$toCheck})";
|
||||
}
|
||||
}
|
||||
if ($oAtt->IsHierarchicalKey())
|
||||
@@ -2790,12 +2792,6 @@ abstract class DBObject implements iDisplay
|
||||
$this->DoComputeValues();
|
||||
$this->OnInsert();
|
||||
|
||||
if ($this->m_iKey < 0)
|
||||
{
|
||||
// This was a temporary "memory" key: discard it so that DBInsertSingleTable will not try to use it!
|
||||
$this->m_iKey = null;
|
||||
}
|
||||
|
||||
// If not automatically computed, then check that the key is given by the caller
|
||||
if (!MetaModel::IsAutoIncrementKey($sRootClass))
|
||||
{
|
||||
@@ -2812,6 +2808,12 @@ abstract class DBObject implements iDisplay
|
||||
throw new CoreCannotSaveObjectException(array('issues' => $aIssues, 'class' => get_class($this), 'id' => $this->GetKey()));
|
||||
}
|
||||
|
||||
if ($this->m_iKey < 0)
|
||||
{
|
||||
// This was a temporary "memory" key: discard it so that DBInsertSingleTable will not try to use it!
|
||||
$this->m_iKey = null;
|
||||
}
|
||||
|
||||
// Stop watches
|
||||
$sState = $this->GetState();
|
||||
if ($sState != '')
|
||||
@@ -2923,13 +2925,14 @@ abstract class DBObject implements iDisplay
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectCreate AS t WHERE t.target_class IN (:class_list)"), array(), $aParams);
|
||||
while ($oTrigger = $oSet->Fetch())
|
||||
{
|
||||
/** @var \Trigger $oTrigger */
|
||||
/** @var \TriggerOnObjectCreate $oTrigger */
|
||||
try
|
||||
{
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -3394,6 +3397,7 @@ abstract class DBObject implements iDisplay
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -3573,13 +3577,13 @@ abstract class DBObject implements iDisplay
|
||||
$aParams);
|
||||
while ($oTrigger = $oSet->Fetch())
|
||||
{
|
||||
/** @var \Trigger $oTrigger */
|
||||
/** @var \TriggerOnObjectDelete $oTrigger */
|
||||
try
|
||||
{
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
catch(Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -3968,6 +3972,7 @@ abstract class DBObject implements iDisplay
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -3979,6 +3984,7 @@ abstract class DBObject implements iDisplay
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -3995,6 +4001,20 @@ abstract class DBObject implements iDisplay
|
||||
return $bSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return bool True if $sAttCode has an actual value set, false is the attribute remains "empty"
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @since 3.0.3, 3.1.0 N°5784
|
||||
*/
|
||||
public function HasAValue(string $sAttCode): bool
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAttDef->HasAValue($this->Get($sAttCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to recover the default value (aka when an object is being created)
|
||||
* Suitable for use as a lifecycle action
|
||||
|
||||
@@ -1103,22 +1103,39 @@ class DBObjectSearch extends DBSearch
|
||||
public function Filter($sClassAlias, DBSearch $oFilter)
|
||||
{
|
||||
// If the conditions are the correct ones for Intersect
|
||||
if (MetaModel::IsParentClass($oFilter->GetFirstJoinedClass(),$this->GetFirstJoinedClass()))
|
||||
{
|
||||
if (MetaModel::IsParentClass($oFilter->GetFirstJoinedClass(), $this->GetFirstJoinedClass())) {
|
||||
return $this->Intersect($oFilter);
|
||||
}
|
||||
|
||||
/** @var \DBObjectSearch $oFilteredSearch */
|
||||
$oFilteredSearch = $this->DeepClone();
|
||||
$oFilterExpression = self::FilterSubClass($oFilteredSearch, $sClassAlias, $oFilter, $this->m_aClasses);
|
||||
if ($oFilterExpression === false)
|
||||
{
|
||||
throw new CoreException("Limitation: cannot filter search");
|
||||
if ($oFilter instanceof DBUnionSearch) {
|
||||
$aFilters = $oFilter->GetSearches();
|
||||
} else {
|
||||
$aFilters = [$oFilter];
|
||||
}
|
||||
|
||||
$oFilteredSearch->AddConditionExpression($oFilterExpression);
|
||||
$aSearches = [];
|
||||
foreach ($aFilters as $oRightFilter) {
|
||||
/** @var \DBObjectSearch $oFilteredSearch */
|
||||
$oFilteredSearch = $this->DeepClone();
|
||||
$oFilterExpression = self::FilterSubClass($oFilteredSearch, $sClassAlias, $oRightFilter, $this->m_aClasses);
|
||||
if ($oFilterExpression === false) {
|
||||
throw new CoreException("Limitation: cannot filter search");
|
||||
}
|
||||
|
||||
return $oFilteredSearch;
|
||||
$oFilteredSearch->AddConditionExpression($oFilterExpression);
|
||||
$aSearches[] = $oFilteredSearch;
|
||||
}
|
||||
|
||||
if (count($aSearches) == 0) {
|
||||
throw new CoreException('Filtering '.$this->ToOQL().' by '.$oFilter->ToOQL().' failed');
|
||||
}
|
||||
|
||||
if (count($aSearches) == 1) {
|
||||
// return a DBObjectSearch
|
||||
return $aSearches[0];
|
||||
}
|
||||
|
||||
return new DBUnionSearch($aSearches);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1184,22 +1201,10 @@ class DBObjectSearch extends DBSearch
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function Intersect(DBSearch $oFilter)
|
||||
{
|
||||
return $this->IntersectSubClass($oFilter, $this->m_aClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBSearch $oFilter
|
||||
* @param array $aRootClasses classes of the root search (for aliases)
|
||||
*
|
||||
* @return \DBUnionSearch|mixed
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function IntersectSubClass(DBSearch $oFilter, $aRootClasses)
|
||||
{
|
||||
if ($oFilter instanceof DBUnionSearch)
|
||||
{
|
||||
// Develop!
|
||||
// Develop!
|
||||
$aFilters = $oFilter->GetSearches();
|
||||
}
|
||||
else
|
||||
@@ -1210,56 +1215,61 @@ class DBObjectSearch extends DBSearch
|
||||
$aSearches = array();
|
||||
foreach ($aFilters as $oRightFilter)
|
||||
{
|
||||
// Limitation: the queried class must be the first declared class
|
||||
if ($oRightFilter->GetFirstJoinedClassAlias() != $oRightFilter->GetClassAlias())
|
||||
{
|
||||
throw new CoreException("Limitation: cannot merge two queries if the queried class ({$oRightFilter->GetClass()} AS {$oRightFilter->GetClassAlias()}) is not the first joined class ({$oRightFilter->GetFirstJoinedClass()} AS {$oRightFilter->GetFirstJoinedClassAlias()})");
|
||||
}
|
||||
|
||||
/** @var \DBObjectSearch $oLeftFilter */
|
||||
$oLeftFilter = $this->DeepClone();
|
||||
$oRightFilter = $oRightFilter->DeepClone();
|
||||
|
||||
$bAllowAllData = ($oLeftFilter->IsAllDataAllowed() && $oRightFilter->IsAllDataAllowed());
|
||||
if ($bAllowAllData)
|
||||
{
|
||||
$oLeftFilter->AllowAllData();
|
||||
}
|
||||
|
||||
if ($oLeftFilter->GetFirstJoinedClass() != $oRightFilter->GetClass())
|
||||
{
|
||||
if (MetaModel::IsParentClass($oLeftFilter->GetFirstJoinedClass(), $oRightFilter->GetClass()))
|
||||
{
|
||||
// Specialize $oLeftFilter
|
||||
$oLeftFilter->ChangeClass($oRightFilter->GetClass(), $oLeftFilter->GetFirstJoinedClassAlias());
|
||||
}
|
||||
elseif (MetaModel::IsParentClass($oRightFilter->GetFirstJoinedClass(), $oLeftFilter->GetClass()))
|
||||
{
|
||||
// Specialize $oRightFilter
|
||||
$oRightFilter->ChangeClass($oLeftFilter->GetFirstJoinedClass());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CoreException("Attempting to merge a filter of class '{$oLeftFilter->GetClass()}' with a filter of class '{$oRightFilter->GetClass()}'");
|
||||
}
|
||||
}
|
||||
|
||||
$aAliasTranslation = array();
|
||||
$oLeftFilter->RenameNestedQueriesAliasesInNameSpace($aRootClasses, $aAliasTranslation);
|
||||
$oLeftFilter->MergeWith_InNamespace($oRightFilter, $aRootClasses, $aAliasTranslation);
|
||||
$oRightFilter->RenameNestedQueriesAliasesInNameSpace($aRootClasses, $aAliasTranslation);
|
||||
$oLeftFilter->TransferConditionExpression($oRightFilter, $aAliasTranslation);
|
||||
$aSearches[] = $oLeftFilter;
|
||||
$aSearches[] = $this->IntersectSubClass($oRightFilter, $this->m_aClasses);
|
||||
}
|
||||
|
||||
if (count($aSearches) == 1)
|
||||
{
|
||||
// return a DBObjectSearch
|
||||
return $aSearches[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DBUnionSearch($aSearches);
|
||||
|
||||
return new DBUnionSearch($aSearches);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObjectSearch $oRightFilter
|
||||
* @param array $aRootClasses classes of the root search (for aliases)
|
||||
*
|
||||
* @return \DBObjectSearch
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function IntersectSubClass(DBObjectSearch $oRightFilter, array $aRootClasses): DBObjectSearch
|
||||
{
|
||||
// Limitation: the queried class must be the first declared class
|
||||
if ($oRightFilter->GetFirstJoinedClassAlias() != $oRightFilter->GetClassAlias()) {
|
||||
throw new CoreException("Limitation: cannot merge two queries if the queried class ({$oRightFilter->GetClass()} AS {$oRightFilter->GetClassAlias()}) is not the first joined class ({$oRightFilter->GetFirstJoinedClass()} AS {$oRightFilter->GetFirstJoinedClassAlias()})");
|
||||
}
|
||||
|
||||
/** @var \DBObjectSearch $oLeftFilter */
|
||||
$oLeftFilter = $this->DeepClone();
|
||||
/** @var DBObjectSearch $oRightFilter */
|
||||
$oRightFilter = $oRightFilter->DeepClone();
|
||||
|
||||
$bAllowAllData = ($oLeftFilter->IsAllDataAllowed() && $oRightFilter->IsAllDataAllowed());
|
||||
if ($bAllowAllData) {
|
||||
$oLeftFilter->AllowAllData();
|
||||
}
|
||||
|
||||
if ($oLeftFilter->GetFirstJoinedClass() != $oRightFilter->GetClass()) {
|
||||
if (MetaModel::IsParentClass($oLeftFilter->GetFirstJoinedClass(), $oRightFilter->GetClass())) {
|
||||
// Specialize $oLeftFilter
|
||||
$oLeftFilter->ChangeClass($oRightFilter->GetClass(), $oLeftFilter->GetFirstJoinedClassAlias());
|
||||
} elseif (MetaModel::IsParentClass($oRightFilter->GetFirstJoinedClass(), $oLeftFilter->GetClass())) {
|
||||
// Specialize $oRightFilter
|
||||
$oRightFilter->ChangeClass($oLeftFilter->GetFirstJoinedClass());
|
||||
} else {
|
||||
throw new CoreException("Attempting to merge a filter of class '{$oLeftFilter->GetClass()}' with a filter of class '{$oRightFilter->GetClass()}'");
|
||||
}
|
||||
}
|
||||
|
||||
$aAliasTranslation = array();
|
||||
$oLeftFilter->RenameNestedQueriesAliasesInNameSpace($aRootClasses, $aAliasTranslation);
|
||||
$oLeftFilter->MergeWith_InNamespace($oRightFilter, $aRootClasses, $aAliasTranslation);
|
||||
$oRightFilter->RenameNestedQueriesAliasesInNameSpace($aRootClasses, $aAliasTranslation);
|
||||
$oLeftFilter->TransferConditionExpression($oRightFilter, $aAliasTranslation);
|
||||
|
||||
return $oLeftFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -141,7 +141,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
||||
{
|
||||
$sRet = '';
|
||||
$this->Rewind();
|
||||
$sRet .= "Set (".$this->m_oFilter->ToOQL().")<br/>\n";
|
||||
$sRet .= "Set (".$this->m_oFilter->ToOQL(true).")<br/>\n";
|
||||
$sRet .= "Query: <pre style=\"font-size: smaller; display:inline;\">".$this->m_oFilter->MakeSelectQuery().")</pre>\n";
|
||||
|
||||
$sRet .= $this->Count()." records<br/>\n";
|
||||
@@ -154,6 +154,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
||||
}
|
||||
$sRet .= "</ul>\n";
|
||||
}
|
||||
$this->Rewind();
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
|
||||
@@ -773,14 +773,14 @@ abstract class DBSearch
|
||||
* @see DBSearch::ToOQL()
|
||||
*
|
||||
* @param string $sQuery The OQL to convert to a DBSearch
|
||||
* @param mixed[string] $aParams array of <mixed> params index by <string> name
|
||||
* @param array $aParams array of <mixed> params index by <string> name
|
||||
* @param ModelReflection|null $oMetaModel The MetaModel to use when checking the consistency of the OQL
|
||||
*
|
||||
* @return DBObjectSearch|DBUnionSearch
|
||||
*
|
||||
* @throws OQLException
|
||||
*/
|
||||
static public function FromOQL($sQuery, $aParams = null, ModelReflection $oMetaModel=null)
|
||||
public static function FromOQL($sQuery, $aParams = null, ModelReflection $oMetaModel=null)
|
||||
{
|
||||
if (empty($sQuery))
|
||||
{
|
||||
@@ -1717,6 +1717,6 @@ abstract class DBSearch
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->ToOQL();
|
||||
return $this->ToOQL(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,32 +34,35 @@ abstract class HTMLSanitizer
|
||||
|
||||
/**
|
||||
* Sanitize an HTML string with the configured sanitizer, falling back to HTMLDOMSanitizer in case of Exception or invalid configuration
|
||||
*
|
||||
* @param string $sHTML
|
||||
* @param string $sConfigKey eg. 'html_sanitizer', 'svg_sanitizer'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function Sanitize($sHTML)
|
||||
public static function Sanitize($sHTML, $sConfigKey = 'html_sanitizer')
|
||||
{
|
||||
$sSanitizerClass = MetaModel::GetConfig()->Get('html_sanitizer');
|
||||
if(!class_exists($sSanitizerClass))
|
||||
{
|
||||
IssueLog::Warning('The configured "html_sanitizer" class "'.$sSanitizerClass.'" is not a valid class. Will use HTMLDOMSanitizer as the default sanitizer.');
|
||||
$sSanitizerClass = 'HTMLDOMSanitizer';
|
||||
}
|
||||
else if(!is_subclass_of($sSanitizerClass, 'HTMLSanitizer'))
|
||||
{
|
||||
IssueLog::Warning('The configured "html_sanitizer" class "'.$sSanitizerClass.'" is not a subclass of HTMLSanitizer. Will use HTMLDOMSanitizer as the default sanitizer.');
|
||||
$sSanitizerClass = utils::GetConfig()->Get($sConfigKey);
|
||||
if (!class_exists($sSanitizerClass)) {
|
||||
IssueLog::Warning('The configured "'.$sConfigKey.'" class "'.$sSanitizerClass.'" is not a valid class. Will use HTMLDOMSanitizer as the default sanitizer.');
|
||||
$sSanitizerClass = 'HTMLDOMSanitizer';
|
||||
} else if (!is_subclass_of($sSanitizerClass, 'HTMLSanitizer')) {
|
||||
if ($sConfigKey === 'html_sanitizer') {
|
||||
IssueLog::Warning('The configured "'.$sConfigKey.'" class "'.$sSanitizerClass.'" is not a subclass of '.HTMLSanitizer::class.'. Will use HTMLDOMSanitizer as the default sanitizer.');
|
||||
$sSanitizerClass = 'HTMLDOMSanitizer';
|
||||
} else {
|
||||
IssueLog::Error('The configured "'.$sConfigKey.'" class "'.$sSanitizerClass.'" is not a subclass of '.HTMLSanitizer::class.' ! Won\'t sanitize string.');
|
||||
|
||||
return $sHTML;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oSanitizer = new $sSanitizerClass();
|
||||
$sCleanHTML = $oSanitizer->DoSanitize($sHTML);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
if($sSanitizerClass != 'HTMLDOMSanitizer')
|
||||
{
|
||||
catch (Exception $e) {
|
||||
if ($sSanitizerClass != 'HTMLDOMSanitizer') {
|
||||
IssueLog::Warning('Failed to sanitize an HTML string with "'.$sSanitizerClass.'". The following exception occured: '.$e->getMessage());
|
||||
IssueLog::Warning('Will try to sanitize with HTMLDOMSanitizer.');
|
||||
// try again with the HTMLDOMSanitizer
|
||||
|
||||
@@ -242,7 +242,7 @@ class InlineImage extends DBObject
|
||||
public static function OnFormCancel($sTempId): bool
|
||||
{
|
||||
// Protection against unfortunate massive delete of inline images when a null temp ID is passed
|
||||
if (strlen($sTempId) === 0) {
|
||||
if (utils::IsNullOrEmptyString($sTempId)) {
|
||||
IssueLog::Trace('OnFormCancel "error" $sTempId is null or empty', LogChannels::INLINE_IMAGE, array(
|
||||
'$sTempId' => $sTempId,
|
||||
'$sUser' => UserRights::GetUser(),
|
||||
|
||||
@@ -545,12 +545,8 @@ class LogChannels
|
||||
public const APC = 'apc';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.0.1 N°4849
|
||||
* @since 2.7.7 N°4635
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public const NOTIFICATIONS = 'notifications';
|
||||
|
||||
public const CLI = 'CLI';
|
||||
|
||||
/**
|
||||
@@ -560,15 +556,31 @@ class LogChannels
|
||||
*/
|
||||
public const CMDB_SOURCE = 'cmdbsource';
|
||||
|
||||
public const CONSOLE = 'console';
|
||||
/**
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public const CONSOLE = 'console';
|
||||
|
||||
public const CORE = 'core';
|
||||
public const CORE = 'core';
|
||||
|
||||
public const DEADLOCK = 'DeadLock';
|
||||
public const DEADLOCK = 'DeadLock';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 2.7.9 3.0.3 3.1.0 N°5588
|
||||
*/
|
||||
public const EXPORT = 'export';
|
||||
|
||||
public const INLINE_IMAGE = 'InlineImage';
|
||||
|
||||
public const PORTAL = 'portal';
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.0.1 N°4849
|
||||
* @since 2.7.7 N°4635
|
||||
*/
|
||||
public const NOTIFICATIONS = 'notifications';
|
||||
|
||||
public const PORTAL = 'portal';
|
||||
}
|
||||
|
||||
|
||||
@@ -949,7 +961,9 @@ class ToolsLog extends LogAPI
|
||||
|
||||
/**
|
||||
* @see \CMDBSource::LogDeadLock()
|
||||
* @since 2.7.1
|
||||
* @since 2.7.1 PR #139
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks.html
|
||||
*/
|
||||
class DeadLockLog extends LogAPI
|
||||
{
|
||||
@@ -974,10 +988,10 @@ class DeadLockLog extends LogAPI
|
||||
{
|
||||
switch ($iMysqlErrorNo)
|
||||
{
|
||||
case 1205:
|
||||
case CMDBSource::MYSQL_ERRNO_WAIT_TIMEOUT:
|
||||
return self::CHANNEL_WAIT_TIMEOUT;
|
||||
break;
|
||||
case 1213:
|
||||
case CMDBSource::MYSQL_ERRNO_DEADLOCK:
|
||||
return self::CHANNEL_DEADLOCK_FOUND;
|
||||
break;
|
||||
default:
|
||||
@@ -1007,7 +1021,14 @@ class DeadLockLog extends LogAPI
|
||||
|
||||
|
||||
/**
|
||||
* @since 3.0.0 N°3731
|
||||
* Starting with the WARNING level we will log in a dedicated file (/log/deprecated-calls.log) :
|
||||
* - iTop deprecated files or code
|
||||
* - protected trigger_error calls with E_DEPRECATED or E_USER_DEPRECATED
|
||||
*
|
||||
* For the last category, if {@see utils::IsDevelopmentEnvironment()} is true we will do a trigger_error()
|
||||
*
|
||||
* @since 3.0.0 N°3731 first implementation
|
||||
* @link https://www.itophub.io/wiki/page?id=latest:admin:log:channels#deprecated_calls channel used
|
||||
*/
|
||||
class DeprecatedCallsLog extends LogAPI
|
||||
{
|
||||
@@ -1016,6 +1037,7 @@ class DeprecatedCallsLog extends LogAPI
|
||||
public const ENUM_CHANNEL_FILE = 'deprecated-file';
|
||||
public const CHANNEL_DEFAULT = self::ENUM_CHANNEL_PHP_METHOD;
|
||||
|
||||
/** @var string Warning this constant won't be used directly ! To see the real default level check {@see GetLevelDefault()} */
|
||||
public const LEVEL_DEFAULT = self::LEVEL_ERROR;
|
||||
|
||||
/** @var \FileLog we want our own instance ! */
|
||||
@@ -1049,16 +1071,19 @@ class DeprecatedCallsLog extends LogAPI
|
||||
* @uses \set_error_handler() to catch deprecated notices
|
||||
*
|
||||
* @since 3.0.0 N°3002 logs deprecated notices in called code
|
||||
* @since 3.0.4 N°6274 do not set handler when in PHPUnit context (otherwise PHP notices won't be caught)
|
||||
*/
|
||||
public static function Enable($sTargetFile = null): void
|
||||
{
|
||||
public static function Enable($sTargetFile = null): void {
|
||||
if (empty($sTargetFile)) {
|
||||
$sTargetFile = APPROOT.'log/deprecated-calls.log';
|
||||
}
|
||||
parent::Enable($sTargetFile);
|
||||
|
||||
if (static::IsLogLevelEnabledSafe(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD)) {
|
||||
set_error_handler([static::class, 'DeprecatedNoticesErrorHandler']);
|
||||
if (
|
||||
(false === defined(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME))
|
||||
&& static::IsLogLevelEnabledSafe(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD)
|
||||
) {
|
||||
set_error_handler([static::class, 'DeprecatedNoticesErrorHandler'], E_DEPRECATED | E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,7 +1115,12 @@ class DeprecatedCallsLog extends LogAPI
|
||||
}
|
||||
|
||||
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4);
|
||||
$iStackDeprecatedMethodLevel = 2; // level 0 = current method, level 1 = @trigger_error, level 2 = method containing the `trigger_error` call
|
||||
$iStackDeprecatedMethodLevel = 2; // level 0 = current method, level 1 = @trigger_error, level 2 = method containing the `trigger_error` call (can be either 'trigger_deprecation' or the faulty method), level 3 = In some cases, method containing the 'trigger_deprecation' call
|
||||
// In case current level is actually a 'trigger_deprecation' call, try to go one level further to get the real deprecated method
|
||||
if (array_key_exists($iStackDeprecatedMethodLevel, $aStack) && ($aStack[$iStackDeprecatedMethodLevel]['function'] === 'trigger_deprecation') && array_key_exists($iStackDeprecatedMethodLevel + 1, $aStack)) {
|
||||
$iStackDeprecatedMethodLevel++;
|
||||
}
|
||||
|
||||
$sDeprecatedObject = $aStack[$iStackDeprecatedMethodLevel]['class'];
|
||||
$sDeprecatedMethod = $aStack[$iStackDeprecatedMethodLevel]['function'];
|
||||
if (($sDeprecatedObject === __CLASS__) && ($sDeprecatedMethod === 'Log')) {
|
||||
@@ -1135,7 +1165,6 @@ class DeprecatedCallsLog extends LogAPI
|
||||
* - else call parent method
|
||||
*
|
||||
* In other words, when in dev mode all deprecated calls will be logged to file
|
||||
*
|
||||
*/
|
||||
protected static function GetLevelDefault(string $sConfigKey)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ class ormPassword
|
||||
|
||||
public function IsEmpty()
|
||||
{
|
||||
return ($this->m_hashed == null);
|
||||
return utils::IsNullOrEmptyString($this->m_sHashed);
|
||||
}
|
||||
|
||||
public function GetHash()
|
||||
|
||||
@@ -21,6 +21,19 @@ use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactor
|
||||
*/
|
||||
class PDFBulkExport extends HTMLBulkExport
|
||||
{
|
||||
/**
|
||||
* @var string For sample purposes
|
||||
* @internal
|
||||
* @since 2.7.8
|
||||
*/
|
||||
const ENUM_OUTPUT_TYPE_SAMPLE = 'sample';
|
||||
/**
|
||||
* @var string For the real export
|
||||
* @internal
|
||||
* @since 2.7.8
|
||||
*/
|
||||
const ENUM_OUTPUT_TYPE_REAL = 'real';
|
||||
|
||||
public function DisplayUsage(Page $oP)
|
||||
{
|
||||
$oP->p(" * pdf format options:");
|
||||
@@ -197,46 +210,46 @@ EOF
|
||||
return $sPDF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 2.7.8
|
||||
*/
|
||||
protected function GetSampleData($oObj, $sAttCode)
|
||||
{
|
||||
if ($sAttCode !== 'id')
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||
|
||||
// As sample data will be displayed in the web browser, AttributeImage needs to be rendered with a regular HTML format, meaning its "src" looking like "data:image/png;base64,iVBORw0KGgoAAAANSUh..."
|
||||
// Whereas for the PDF generation it needs to be rendered with a TCPPDF-compatible format, meaning its "src" looking like "@iVBORw0KGgoAAAANSUh..."
|
||||
if ($oAttDef instanceof AttributeImage) {
|
||||
return $this->GetAttributeImageValue($oObj, $sAttCode, static::ENUM_OUTPUT_TYPE_SAMPLE);
|
||||
}
|
||||
}
|
||||
return parent::GetSampleData($oObj, $sAttCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $oObj
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GetValue($oObj, $sAttCode)
|
||||
{
|
||||
switch($sAttCode)
|
||||
{
|
||||
switch ($sAttCode) {
|
||||
case 'id':
|
||||
$sRet = parent::GetValue($oObj, $sAttCode);
|
||||
break;
|
||||
|
||||
default:
|
||||
$value = $oObj->Get($sAttCode);
|
||||
if ($value instanceof ormDocument)
|
||||
{
|
||||
if ($value instanceof ormDocument) {
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||
if ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
// To limit the image size in the PDF output, we have to enforce the size as height/width because max-width/max-height have no effect
|
||||
//
|
||||
$iDefaultMaxWidthPx = 48;
|
||||
$iDefaultMaxHeightPx = 48;
|
||||
if ($value->IsEmpty())
|
||||
{
|
||||
$iNewWidth = $iDefaultMaxWidthPx;
|
||||
$iNewHeight = $iDefaultMaxHeightPx;
|
||||
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
}
|
||||
else
|
||||
{
|
||||
list($iWidth, $iHeight) = utils::GetImageSize($value->GetData());
|
||||
$iMaxWidthPx = min($iDefaultMaxWidthPx, $oAttDef->Get('display_max_width'));
|
||||
$iMaxHeightPx = min($iDefaultMaxHeightPx, $oAttDef->Get('display_max_height'));
|
||||
|
||||
$fScale = min($iMaxWidthPx / $iWidth, $iMaxHeightPx / $iHeight);
|
||||
$iNewWidth = $iWidth * $fScale;
|
||||
$iNewHeight = $iHeight * $fScale;
|
||||
|
||||
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
|
||||
}
|
||||
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px">' : '';
|
||||
$sRet = '<div class="ibo-input-image--image-view">'.$sRet.'</div>';
|
||||
$sRet = $this->GetAttributeImageValue($oObj, $sAttCode, static::ENUM_OUTPUT_TYPE_REAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -251,6 +264,76 @@ EOF
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $oObj
|
||||
* @param string $sAttCode
|
||||
* @param string $sOutputType {@see \PDFBulkExport::ENUM_OUTPUT_TYPE_SAMPLE}, {@see \PDFBulkExport::ENUM_OUTPUT_TYPE_REAL}
|
||||
*
|
||||
* @return string Rendered value of $oAttDef / $oValue according to the desired $sOutputType
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @since 2.7.8 N°2244 method creation
|
||||
* @since 2.7.9 N°5588 signature change to get the object so that we can log all the needed information
|
||||
*/
|
||||
protected function GetAttributeImageValue(DBObject $oObj, string $sAttCode, string $sOutputType)
|
||||
{
|
||||
$oValue = $oObj->Get($sAttCode);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||
|
||||
// To limit the image size in the PDF output, we have to enforce the size as height/width because max-width/max-height have no effect
|
||||
//
|
||||
$iDefaultMaxWidthPx = 48;
|
||||
$iDefaultMaxHeightPx = 48;
|
||||
if ($oValue->IsEmpty()) {
|
||||
$iNewWidth = $iDefaultMaxWidthPx;
|
||||
$iNewHeight = $iDefaultMaxHeightPx;
|
||||
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
} else {
|
||||
$iMaxWidthPx = min($iDefaultMaxWidthPx, $oAttDef->Get('display_max_width'));
|
||||
$iMaxHeightPx = min($iDefaultMaxHeightPx, $oAttDef->Get('display_max_height'));
|
||||
|
||||
list($iWidth, $iHeight) = utils::GetImageSize($oValue->GetData());
|
||||
if ((is_null($iWidth)) || (is_null($iHeight)) || ($iWidth === 0) || ($iHeight === 0)) {
|
||||
// Avoid division by zero exception (SVGs, corrupted images, ...)
|
||||
$iNewWidth = $iDefaultMaxWidthPx;
|
||||
$iNewHeight = $iDefaultMaxHeightPx;
|
||||
|
||||
$sAttCode = $oAttDef->GetCode();
|
||||
IssueLog::Warning('AttributeImage: Cannot read image size', LogChannels::EXPORT, [
|
||||
'ObjClass' => get_class($oObj),
|
||||
'ObjKey' => $oObj->GetKey(),
|
||||
'ObjFriendlyName' => $oObj->GetName(),
|
||||
'AttCode' => $sAttCode,
|
||||
]);
|
||||
} else {
|
||||
$fScale = min($iMaxWidthPx / $iWidth, $iMaxHeightPx / $iHeight);
|
||||
$iNewWidth = $iWidth * $fScale;
|
||||
$iNewHeight = $iHeight * $fScale;
|
||||
}
|
||||
|
||||
$sValueAsBase64 = base64_encode($oValue->GetData());
|
||||
switch ($sOutputType) {
|
||||
case static::ENUM_OUTPUT_TYPE_SAMPLE:
|
||||
$sUrl = 'data:'.$oValue->GetMimeType().';base64,'.$sValueAsBase64;
|
||||
break;
|
||||
|
||||
case static::ENUM_OUTPUT_TYPE_REAL:
|
||||
default:
|
||||
// TCPDF requires base64-encoded images to be rendered without the usual "data:<MIMETYPE>;base64" header but with an "@"
|
||||
// @link https://tcpdf.org/examples/example_009/
|
||||
$sUrl = '@'.$sValueAsBase64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px;">' : '';
|
||||
$sRet = '<div class="ibo-input-image--image-view">'.$sRet.'</div>';
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function GetSupportedFormats()
|
||||
{
|
||||
return array('pdf' => Dict::S('Core:BulkExport:PDFFormat'));
|
||||
|
||||
@@ -30,18 +30,40 @@
|
||||
/**
|
||||
* Element of the response formed by RestResultWithObjects
|
||||
*
|
||||
* @package REST Services
|
||||
* @package RESTExtensibilityAPI
|
||||
* @api
|
||||
*/
|
||||
class ObjectResult
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @api
|
||||
*/
|
||||
public $code;
|
||||
/**
|
||||
* @var string
|
||||
* @api
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var mixed|null
|
||||
* @api
|
||||
*/
|
||||
public $class;
|
||||
/**
|
||||
* @var mixed|null
|
||||
* @api
|
||||
*/
|
||||
public $key;
|
||||
/**
|
||||
* @var array
|
||||
* @api
|
||||
*/
|
||||
public $fields;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
* @api
|
||||
*/
|
||||
public function __construct($sClass = null, $iId = null)
|
||||
{
|
||||
@@ -54,11 +76,17 @@ class ObjectResult
|
||||
|
||||
/**
|
||||
* Helper to make an output value for a given attribute
|
||||
*
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being reported
|
||||
* @param string $sAttCode The attribute code (must be valid)
|
||||
* @param boolean $bExtendedOutput Output all of the link set attributes ?
|
||||
*
|
||||
* @return string A scalar representation of the value
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
protected function MakeResultValue(DBObject $oObject, $sAttCode, $bExtendedOutput = false)
|
||||
{
|
||||
@@ -112,11 +140,17 @@ class ObjectResult
|
||||
|
||||
/**
|
||||
* Report the value for the given object attribute
|
||||
*
|
||||
*
|
||||
* @api
|
||||
* @param DBObject $oObject The object being reported
|
||||
* @param string $sAttCode The attribute code (must be valid)
|
||||
* @param boolean $bExtendedOutput Output all of the link set attributes ?
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function AddField(DBObject $oObject, $sAttCode, $bExtendedOutput = false)
|
||||
{
|
||||
@@ -129,8 +163,7 @@ class ObjectResult
|
||||
/**
|
||||
* REST response for services managing objects. Derive this structure to add information and/or constants
|
||||
*
|
||||
* @package Extensibility
|
||||
* @package REST Services
|
||||
* @package RESTExtensibilityAPI
|
||||
* @api
|
||||
*/
|
||||
class RestResultWithObjects extends RestResult
|
||||
@@ -139,13 +172,19 @@ class RestResultWithObjects extends RestResult
|
||||
|
||||
/**
|
||||
* Report the given object
|
||||
*
|
||||
* @param int An error code (RestResult::OK is no issue has been found)
|
||||
*
|
||||
* @api
|
||||
* @param int $iCode An error code (RestResult::OK is no issue has been found)
|
||||
* @param string $sMessage Description of the error if any, an empty string otherwise
|
||||
* @param DBObject $oObject The object being reported
|
||||
* @param array $aFieldSpec An array of class => attribute codes (Cf. RestUtils::GetFieldList). List of the attributes to be reported.
|
||||
* @param array|null $aFieldSpec An array of class => attribute codes (Cf. RestUtils::GetFieldList). List of the attributes to be reported.
|
||||
* @param boolean $bExtendedOutput Output all of the link set attributes ?
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function AddObject($iCode, $sMessage, $oObject, $aFieldSpec = null, $bExtendedOutput = false)
|
||||
{
|
||||
@@ -183,16 +222,30 @@ class RestResultWithObjects extends RestResult
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @package RESTExtensibilityAPI
|
||||
* @api
|
||||
*/
|
||||
class RestResultWithRelations extends RestResultWithObjects
|
||||
{
|
||||
public $relations;
|
||||
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->relations = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sSrcKey
|
||||
* @param $sDestKey
|
||||
*
|
||||
* @return void
|
||||
* @api
|
||||
*/
|
||||
public function AddRelation($sSrcKey, $sDestKey)
|
||||
{
|
||||
if (!array_key_exists($sSrcKey, $this->relations))
|
||||
@@ -206,7 +259,7 @@ class RestResultWithRelations extends RestResultWithObjects
|
||||
/**
|
||||
* Deletion result codes for a target object (either deleted or updated)
|
||||
*
|
||||
* @package Extensibility
|
||||
* @package RESTExtensibilityAPI
|
||||
* @api
|
||||
* @since 2.0.1
|
||||
*/
|
||||
@@ -214,30 +267,37 @@ class RestDelete
|
||||
{
|
||||
/**
|
||||
* Result: Object deleted as per the initial request
|
||||
* @api
|
||||
*/
|
||||
const OK = 0;
|
||||
/**
|
||||
* Result: general issue (user rights or ... ?)
|
||||
* Result: general issue (user rights or ... ?)
|
||||
* @api
|
||||
*/
|
||||
const ISSUE = 1;
|
||||
/**
|
||||
* Result: Must be deleted to preserve database integrity
|
||||
* Result: Must be deleted to preserve database integrity
|
||||
* @api
|
||||
*/
|
||||
const AUTO_DELETE = 2;
|
||||
/**
|
||||
* Result: Must be deleted to preserve database integrity, but that is NOT possible
|
||||
* Result: Must be deleted to preserve database integrity, but that is NOT possible
|
||||
* @api
|
||||
*/
|
||||
const AUTO_DELETE_ISSUE = 3;
|
||||
/**
|
||||
* Result: Must be deleted to preserve database integrity, but this must be requested explicitely
|
||||
* Result: Must be deleted to preserve database integrity, but this must be requested explicitly
|
||||
* @api
|
||||
*/
|
||||
const REQUEST_EXPLICITELY = 4;
|
||||
/**
|
||||
* Result: Must be updated to preserve database integrity
|
||||
* @api
|
||||
*/
|
||||
const AUTO_UPDATE = 5;
|
||||
/**
|
||||
* Result: Must be updated to preserve database integrity, but that is NOT possible
|
||||
* @api
|
||||
*/
|
||||
const AUTO_UPDATE_ISSUE = 6;
|
||||
}
|
||||
@@ -574,7 +634,7 @@ class CoreServices implements iRestServiceProvider
|
||||
$oObject = $oElement->GetProperty('object');
|
||||
if ($oObject)
|
||||
{
|
||||
if ($bEnableRedundancy)
|
||||
if ($bEnableRedundancy && $sDirection == 'down')
|
||||
{
|
||||
// Add only the "reached" objects
|
||||
if ($oElement->GetProperty('is_reached'))
|
||||
|
||||
@@ -250,21 +250,48 @@ abstract class TriggerOnObject extends Trigger
|
||||
public function IsTargetObject($iObjectId, $aChanges = array())
|
||||
{
|
||||
$sFilter = trim($this->Get('filter'));
|
||||
if (strlen($sFilter) > 0)
|
||||
{
|
||||
if (strlen($sFilter) > 0) {
|
||||
$oSearch = DBObjectSearch::FromOQL($sFilter);
|
||||
$oSearch->AddCondition('id', $iObjectId, '=');
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$bRet = ($oSet->Count() > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$bRet = true;
|
||||
}
|
||||
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Exception $oException
|
||||
* @param \DBObject $oObject
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @uses \IssueLog::Error()
|
||||
*
|
||||
* @since 2.7.9 3.0.3 3.1.0 N°5893
|
||||
*/
|
||||
public function LogException($oException, $oObject)
|
||||
{
|
||||
$sObjectKey = $oObject->GetKey(); // if object wasn't persisted yet, then we'll have a negative value
|
||||
|
||||
$aContext = [
|
||||
'exception.class' => get_class($oException),
|
||||
'exception.message' => $oException->getMessage(),
|
||||
'trigger.class' => get_class($this),
|
||||
'trigger.id' => $this->GetKey(),
|
||||
'trigger.friendlyname' => $this->GetRawName(),
|
||||
'object.class' => get_class($oObject),
|
||||
'object.id' => $sObjectKey,
|
||||
'object.friendlyname' => $oObject->GetRawName(),
|
||||
'current_user' => UserRights::GetUser(),
|
||||
'exception.stack' => $oException->getTraceAsString(),
|
||||
];
|
||||
|
||||
IssueLog::Error('A trigger did throw an exception', null, $aContext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1936,7 +1936,7 @@ class UserRights
|
||||
// The bug has been fixed in PHP 7.2, but in case session_regenerate_id()
|
||||
// fails we just silently ignore the error and keep the same session id...
|
||||
$old_error_handler = set_error_handler(array(__CLASS__, 'VoidErrorHandler'));
|
||||
session_regenerate_id(true);
|
||||
Session::RegenerateId(true);
|
||||
if ($old_error_handler !== null) {
|
||||
set_error_handler($old_error_handler);
|
||||
}
|
||||
|
||||
@@ -225,108 +225,106 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
|
||||
$this->m_aValues = array();
|
||||
|
||||
if ($this->m_bAllowAllData)
|
||||
{
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||
$oFilter = $this->GetFilter($sOperation, $sContains);
|
||||
|
||||
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
|
||||
if (empty($this->m_sValueAttCode)) {
|
||||
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
|
||||
} else {
|
||||
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObjects->OptimizeColumnLoad($aAttToLoad);
|
||||
while ($oObject = $oObjects->Fetch()) {
|
||||
if (empty($this->m_sValueAttCode)) {
|
||||
$this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
|
||||
} else {
|
||||
$this->m_aValues[$oObject->GetKey()] = $oObject->Get($this->m_sValueAttCode);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get filter for functions LoadValues and LoadValuesForAutocomplete
|
||||
*
|
||||
* @param $sOperation
|
||||
* @param $sContains
|
||||
*
|
||||
* @return \DBObjectSearch|\DBSearch|\DBUnionSearch|false|mixed
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
* @since 3.0.3 3.1.0
|
||||
*/
|
||||
protected function GetFilter($sOperation, $sContains)
|
||||
{
|
||||
$this->m_sContains = $sContains;
|
||||
$this->m_sOperation = $sOperation;
|
||||
|
||||
if ($this->m_bAllowAllData) {
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||
} else {
|
||||
$oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
|
||||
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
}
|
||||
if (!$oFilter) return false;
|
||||
if (!is_null($this->m_oExtraCondition))
|
||||
{
|
||||
if (!$oFilter) {
|
||||
return false;
|
||||
}
|
||||
if (!is_null($this->m_oExtraCondition)) {
|
||||
$oFilter = $oFilter->Intersect($this->m_oExtraCondition);
|
||||
}
|
||||
foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
|
||||
{
|
||||
foreach ($aProperties as $sProperty => $value)
|
||||
{
|
||||
foreach ($this->m_aModifierProperties as $sPluginClass => $aProperties) {
|
||||
foreach ($aProperties as $sProperty => $value) {
|
||||
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
||||
$aFields = $oExpression->ListRequiredFields();
|
||||
$sClass = $oFilter->GetClass();
|
||||
/*foreach($aFields as $sField)
|
||||
{
|
||||
$aFieldItems = explode('.', $sField);
|
||||
if ($aFieldItems[0] != $sClass)
|
||||
{
|
||||
$sOperation = 'contains';
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
switch ($sOperation)
|
||||
{
|
||||
switch ($this->m_sOperation) {
|
||||
case 'equals':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains);
|
||||
foreach($aAttributes as $sAttribute)
|
||||
{
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr);
|
||||
$oNewFilter->AddConditionExpression($oCondition);
|
||||
$aFilters[] = $oNewFilter;
|
||||
case 'start_with':
|
||||
if ($this->m_sOperation === 'start_with') {
|
||||
$this->m_sContains .= '%';
|
||||
$sOperator = 'LIKE';
|
||||
} else {
|
||||
$sOperator = '=';
|
||||
}
|
||||
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
if (count($aAttributes) > 0) {
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($this->m_sContains);
|
||||
foreach ($aAttributes as $sAttribute) {
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, $sOperator, $oValueExpr);
|
||||
$oNewFilter->AddConditionExpression($oCondition);
|
||||
$aFilters[] = $oNewFilter;
|
||||
}
|
||||
// Unions are much faster than OR conditions
|
||||
$oFilter = new DBUnionSearch($aFilters);
|
||||
} else {
|
||||
$oValueExpr = new ScalarExpression($this->m_sContains);
|
||||
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
||||
$oNewCondition = new BinaryExpression($oNameExpr, $sOperator, $oValueExpr);
|
||||
$oFilter->AddConditionExpression($oNewCondition);
|
||||
}
|
||||
// Unions are much faster than OR conditions
|
||||
$oFilter = new DBUnionSearch($aFilters);
|
||||
break;
|
||||
case 'start_with':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains.'%');
|
||||
foreach($aAttributes as $sAttribute)
|
||||
{
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||
$oNewFilter->AddConditionExpression($oCondition);
|
||||
$aFilters[] = $oNewFilter;
|
||||
}
|
||||
// Unions are much faster than OR conditions
|
||||
$oFilter = new DBUnionSearch($aFilters);
|
||||
break;
|
||||
|
||||
default:
|
||||
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
||||
$oValueExpr = new ScalarExpression('%'.$this->m_sContains.'%');
|
||||
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
||||
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||
$oFilter->AddConditionExpression($oNewCondition);
|
||||
break;
|
||||
}
|
||||
|
||||
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
|
||||
if (empty($this->m_sValueAttCode))
|
||||
{
|
||||
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
|
||||
}
|
||||
$oObjects->OptimizeColumnLoad($aAttToLoad);
|
||||
while ($oObject = $oObjects->Fetch())
|
||||
{
|
||||
if (empty($this->m_sValueAttCode))
|
||||
{
|
||||
$this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->m_aValues[$oObject->GetKey()] = $oObject->Get($this->m_sValueAttCode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return $oFilter;
|
||||
}
|
||||
|
||||
|
||||
public function GetValuesDescription()
|
||||
{
|
||||
return 'Filter: '.$this->m_sFilterExpr;
|
||||
@@ -376,73 +374,12 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
*/
|
||||
protected function LoadValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
|
||||
{
|
||||
$this->m_sContains = $sContains;
|
||||
$this->m_sOperation = $sOperation;
|
||||
|
||||
$this->m_aValues = array();
|
||||
|
||||
if ($this->m_bAllowAllData) {
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||
} else {
|
||||
$oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
|
||||
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
}
|
||||
|
||||
if (!$oFilter) {
|
||||
return false;
|
||||
}
|
||||
if (!is_null($this->m_oExtraCondition)) {
|
||||
$oFilter = $oFilter->Intersect($this->m_oExtraCondition);
|
||||
}
|
||||
foreach ($this->m_aModifierProperties as $sPluginClass => $aProperties) {
|
||||
foreach ($aProperties as $sProperty => $value) {
|
||||
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
|
||||
}
|
||||
}
|
||||
|
||||
//$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
||||
$oFilter = $this->GetFilter($sOperation, $sContains);
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
|
||||
switch ($sOperation) {
|
||||
case 'equals':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains);
|
||||
foreach ($aAttributes as $sAttribute) {
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr);
|
||||
$oNewFilter->AddConditionExpression($oCondition);
|
||||
$aFilters[] = $oNewFilter;
|
||||
}
|
||||
// Unions are much faster than OR conditions
|
||||
$oFilter = new DBUnionSearch($aFilters);
|
||||
break;
|
||||
case 'start_with':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains.'%');
|
||||
foreach($aAttributes as $sAttribute)
|
||||
{
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||
$oNewFilter->AddConditionExpression($oCondition);
|
||||
$aFilters[] = $oNewFilter;
|
||||
}
|
||||
// Unions are much faster than OR conditions
|
||||
$oFilter = new DBUnionSearch($aFilters);
|
||||
break;
|
||||
|
||||
default:
|
||||
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
||||
$oNameExpr = new FieldExpression('friendlyname', $sClassAlias);
|
||||
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||
$oFilter->AddConditionExpression($oNewCondition);
|
||||
break;
|
||||
}
|
||||
|
||||
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
|
||||
if (empty($this->m_sValueAttCode)) {
|
||||
$aAttToLoad = ['friendlyname'];
|
||||
|
||||
@@ -1,46 +1,60 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-table-preview--header-cell--padding: $ibo-spacing-200 $ibo-spacing-600 $ibo-spacing-200 $ibo-spacing-200 !default;
|
||||
$ibo-table-preview--header-cell--background-color: $ibo-color-white-200 !default;
|
||||
$ibo-table-preview--header-cell--border-width: 1px 1px 0 !default;
|
||||
|
||||
$ibo-table-preview--body-cell--padding-x: $ibo-spacing-200 !default;
|
||||
$ibo-table-preview--body-cell--border-width: 0 1px !default;
|
||||
$ibo-table-preview--body-cell--last--border-bottom-width: 1px !default;
|
||||
|
||||
$ibo-preview-header--margin-bottom: $ibo-spacing-200 !default;
|
||||
$ibo-table-preview--remove-column--top: $ibo-spacing-300 !default;
|
||||
$ibo-table-preview--remove-column--right: $ibo-spacing-300 !default;
|
||||
$ibo-table-preview--remove-column--font-size: 8px !default;
|
||||
|
||||
$ibo-form-part-interactive-fields--margin-top: $ibo-spacing-600 !default;
|
||||
|
||||
.ibo-table-preview {
|
||||
margin-top: 20px;
|
||||
overflow-x: auto;
|
||||
|
||||
th {
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
padding-right: $ibo-spacing-600;
|
||||
border-width: 1px 1px 0;
|
||||
padding: $ibo-table-preview--header-cell--padding;
|
||||
border-width: $ibo-table-preview--header-cell--border-width;
|
||||
border-style: groove groove none;
|
||||
background: $ibo-color-white-200;
|
||||
background: $ibo-table-preview--header-cell--background-color;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
border-width: 0 1px;
|
||||
padding-right: $ibo-table-preview--body-cell--padding-x;
|
||||
padding-left: $ibo-table-preview--body-cell--padding-x;
|
||||
border-width: $ibo-table-preview--body-cell--border-width;
|
||||
border-style: none groove;
|
||||
}
|
||||
|
||||
tr:last-child td {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-width: $ibo-table-preview--body-cell--last--border-bottom-width;
|
||||
border-bottom-style: groove;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-preview-header {
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: $ibo-preview-header--margin-bottom;
|
||||
}
|
||||
.ibo-table-preview--remove-column {
|
||||
position: absolute;
|
||||
top: $ibo-spacing-300;
|
||||
right: $ibo-spacing-300;
|
||||
top: $ibo-table-preview--remove-column--top;
|
||||
right: $ibo-table-preview--remove-column--right;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
font-size: 8px;
|
||||
font-size: $ibo-table-preview--remove-column--font-size;
|
||||
}
|
||||
|
||||
#form_part_interactive_fields_xlsx, #form_part_interactive_fields_csv, #form_part_interactive_fields_pdf {
|
||||
margin-top: $ibo-spacing-600;
|
||||
margin-top: $ibo-form-part-interactive-fields--margin-top;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ $ibo-datatable--row--background-color--is-selected: $ibo-color-primary-300 !defa
|
||||
$ibo-datatable--selection-validation-buttons-toolbar--margin-top: 10px !default;
|
||||
$ibo-list-column--max-height: 150px !default;
|
||||
|
||||
$ibo-datatable--sort-order--color: $ibo-color-orange-600 !default;
|
||||
$ibo-datatable--sort-order--color: $ibo-color-primary-600 !default;
|
||||
|
||||
$ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
|
||||
|
||||
|
||||
@@ -253,3 +253,6 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
|
||||
margin-left: $ibo-field--enable-bulk--checkbox--margin-left;
|
||||
}
|
||||
|
||||
.ibo-input-select--action-buttons a {
|
||||
@extend %ibo-hyperlink-inherited-colors;
|
||||
}
|
||||
@@ -6,10 +6,6 @@
|
||||
$ibo-attachment--datatable--icon-preview--max-height: 44px !default;
|
||||
$ibo-attachment--datatable--icon-preview--max-width: $ibo-attachment--datatable--icon-preview--max-height !default;
|
||||
|
||||
$ibo-attachment--datatable--line-height: $ibo-attachment--datatable--icon-preview--max-height !default;
|
||||
|
||||
$ibo-attachment--datatable--first-column--line-height: 0px !default;
|
||||
|
||||
$ibo-attachment--drag-in--border: 2px $ibo-color-grey-400 dashed !default;
|
||||
$ibo-attachment--upload-file--drop-zone-hint--max-height: 200px !default;
|
||||
$ibo-attachment--upload-file--drop-zone-hint--margin: 22px $ibo-spacing-0 !default;
|
||||
@@ -33,10 +29,7 @@ $ibo-attachment--tab-header--drop-in--icon--color: $ibo-color-blue-600 !default;
|
||||
max-width: $ibo-attachment--datatable--icon-preview--max-width;
|
||||
}
|
||||
.ibo-attachment--datatable tbody tr td {
|
||||
line-height: $ibo-attachment--datatable--line-height;
|
||||
}
|
||||
.ibo-attachment--datatable tbody tr td:nth-child(1){
|
||||
line-height: $ibo-attachment--datatable--first-column--line-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ibo-attachment--upload-file--drop-zone-hint{
|
||||
|
||||
34
css/backoffice/pages/_csv-import.scss
vendored
34
css/backoffice/pages/_csv-import.scss
vendored
@@ -3,7 +3,14 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-csv-import--cell-message-padding:3px;
|
||||
$ibo-csv-import--cell-message--padding-top: 3px !default;
|
||||
$ibo-csv-import--cell-modified--color: $ibo-color-blue-700 !default;
|
||||
$ibo-csv-import--cell-error--color: $ibo-color-red-700 !default;
|
||||
$ibo-csv-import--row--border-color: $ibo-color-grey-400 !default;
|
||||
$ibo-csv-import--row-error--background-color: $ibo-color-red-200 !default;
|
||||
$ibo-csv-import--download-file--color: $ibo-color-primary-400 !default;
|
||||
$ibo-csv-import--download-file--font-size: 4em !default;
|
||||
$ibo-csv-import--download-file--margin: 20px !default;
|
||||
|
||||
#tabs1-import .ibo-field--label {
|
||||
max-width: 50%;
|
||||
@@ -11,37 +18,32 @@ $ibo-csv-import--cell-message-padding:3px;
|
||||
|
||||
div.ibo-csv-import--cell-modified {
|
||||
font-weight: bold;
|
||||
color: $ibo-color-blue-700;
|
||||
color: $ibo-csv-import--cell-modified--color;
|
||||
}
|
||||
|
||||
div.ibo-csv-import--cell-error {
|
||||
font-weight: bold;
|
||||
color: $ibo-color-red-700;
|
||||
color: $ibo-csv-import--cell-error--color;
|
||||
}
|
||||
|
||||
div.ibo-csv-import--cell-message {
|
||||
padding-top: $ibo-csv-import--cell-message-padding;
|
||||
padding-top: $ibo-csv-import--cell-message--padding-top;
|
||||
}
|
||||
|
||||
tr.ibo-csv-import--row-unchanged td {
|
||||
border-bottom: 1px $ibo-color-grey-400 solid;
|
||||
}
|
||||
|
||||
.wizContainer table tr.ibo-csv-import--row-error td {
|
||||
border-bottom: 1px $ibo-color-grey-400 solid;
|
||||
background-color: $ibo-color-red-200;
|
||||
border-bottom: 1px $ibo-csv-import--row--border-color solid;
|
||||
}
|
||||
|
||||
tr.ibo-csv-import--row-modified td {
|
||||
border-bottom: 1px $ibo-color-grey-400 solid;
|
||||
border-bottom: 1px $ibo-csv-import--row--border-color solid;
|
||||
}
|
||||
|
||||
tr.ibo-csv-import--row-added td {
|
||||
border-bottom: 1px $ibo-color-grey-400 solid;
|
||||
border-bottom: 1px $ibo-csv-import--row--border-color solid;
|
||||
}
|
||||
|
||||
.ibo-csv-import--download-file {
|
||||
font-size: 4em;
|
||||
color: $ibo-color-primary-400;
|
||||
margin: 20px;
|
||||
}
|
||||
font-size: $ibo-csv-import--download-file--font-size;
|
||||
color: $ibo-csv-import--download-file--color;
|
||||
margin: $ibo-csv-import--download-file--margin;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
$ibo-datamodel-viewer--parent--spacer--padding-y: $ibo-spacing-0 !default;
|
||||
$ibo-datamodel-viewer--parent--spacer--padding-x: $ibo-spacing-300 !default;
|
||||
|
||||
$ibo-datamodel-viewer--classes-list--selectize-input--background-color: $ibo-color-white-100 !default;
|
||||
$ibo-datamodel-viewer--classes-list--selectize-input--color: $ibo-color-grey-800 !default;
|
||||
$ibo-datamodel-viewer--classes-list--selectize-input--border-color: $ibo-color-grey-500 !default;
|
||||
|
||||
$ibo-datamodel-viewer--attributes-table--first-column--width: 3px !default;
|
||||
|
||||
$ibo-datamodel-viewer--origin-cell--diameter: 8px !default;
|
||||
@@ -45,6 +49,15 @@ $ibo-datamodel-viewer--lifecycle-image--margin-bottom: $ibo-spacing-500 !default
|
||||
padding: $ibo-datamodel-viewer--parent--spacer--padding-y $ibo-datamodel-viewer--parent--spacer--padding-x;
|
||||
}
|
||||
|
||||
// Overwrite selectize rules with !important
|
||||
.ibo-datamodel-viewer--classes-list .selectize-input{
|
||||
background-color: $ibo-datamodel-viewer--classes-list--selectize-input--background-color !important;
|
||||
background-image: none !important;
|
||||
color: $ibo-datamodel-viewer--classes-list--selectize-input--color;
|
||||
box-shadow: none !important;
|
||||
border-color: $ibo-datamodel-viewer--classes-list--selectize-input--border-color !important;
|
||||
}
|
||||
|
||||
#ibo-datamodel-viewer--attributes-table{
|
||||
> tbody tr td:first-child{
|
||||
width: $ibo-datamodel-viewer--attributes-table--first-column--width;
|
||||
|
||||
@@ -17,7 +17,9 @@ $ibo-welcome-popup--text--options--bottom: 10px !default;
|
||||
|
||||
#welcome_popup{
|
||||
display: flex;
|
||||
|
||||
}
|
||||
.ibo-welcome-popup--columns{
|
||||
display: flex;
|
||||
}
|
||||
.ibo-welcome-popup--image{
|
||||
display: flex;
|
||||
@@ -44,7 +46,39 @@ $ibo-welcome-popup--text--options--bottom: 10px !default;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ibo-welcome-popup--text--options{
|
||||
position: absolute;
|
||||
bottom: $ibo-welcome-popup--text--options--bottom;
|
||||
.ibo-welcome-popup--dialog {
|
||||
width: 60rem;
|
||||
}
|
||||
.ibo-welcome-popup--content {
|
||||
width: 100%;
|
||||
.ibo-welcome-popup--message {
|
||||
width: 100%;
|
||||
min-height: 12rem;
|
||||
}
|
||||
.ibo-welcome-popup--button {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 1rem;
|
||||
position: absolute;
|
||||
bottom: 4.5rem;
|
||||
}
|
||||
}
|
||||
.ibo-welcome-popup--indicators {
|
||||
width: 100%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 0;
|
||||
height: 3rem;
|
||||
.ibo-welcome-popup--indicator {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: $ibo-color-secondary-600;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ibo-welcome-popup--active {
|
||||
background-color: $ibo-color-information-600 !important;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,10 @@ $ibo-sticky-sentinel-bottom--height: $ibo-sticky-sentinel--height !default;
|
||||
opacity: 1 !important; /* Note: !important is necessary as it needs to overload any standard rules */
|
||||
}
|
||||
|
||||
.ibo-is-disabled {
|
||||
cursor: not-allowed !important; /* Note: !important is necessary as it needs to overload any standard rules */
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* Disposition / alignement */
|
||||
/****************************/
|
||||
@@ -159,6 +163,16 @@ body.ibo-has-fullscreen-descendant {
|
||||
border-spacing: 2px;
|
||||
}
|
||||
|
||||
/*
|
||||
* N°5317 - Handle overlapping tables when table cells have fixed widths
|
||||
* Force table cell NOT to have a fixed width and to wrap when necessary
|
||||
*/
|
||||
td {
|
||||
width: unset !important;
|
||||
word-break: break-word !important;
|
||||
white-space: unset !important;
|
||||
}
|
||||
|
||||
/* Preserve original text color in code blocks, except for the Highlight.js blocks which have their own colors */
|
||||
& > code,
|
||||
code:not(.hljs) {
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
@import "base";
|
||||
@import "base-palette";
|
||||
@import "semantic-palette";
|
||||
@import "lifecycle-palette";
|
||||
@import "lifecycle-palette";
|
||||
@import "skeleton-palette";
|
||||
17
css/backoffice/utils/variables/colors/_skeleton-palette.scss
Normal file
17
css/backoffice/utils/variables/colors/_skeleton-palette.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* Skeleton palette */
|
||||
/* - Colors used by skeletons svg to display placeholders */
|
||||
|
||||
$ibo-skeleton-start-color: $ibo-color-grey-200 !default;
|
||||
$ibo-skeleton-stop-color: $ibo-color-blue-grey-100 !default;
|
||||
|
||||
/* CSS variables */
|
||||
/* Skeleton CSS3 variables are not ibo prefixed as they are not iTop backoffice exclusives*/
|
||||
:root {
|
||||
--skeleton-start-color: #{$ibo-skeleton-start-color};
|
||||
--skeleton-stop-color: #{$ibo-skeleton-stop-color};
|
||||
}
|
||||
@@ -7,6 +7,16 @@
|
||||
*
|
||||
* Other modification done : replaced the `Alpha(` by `alpha(` to avoid warnings generated by SCSSPHP
|
||||
*/
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/* */
|
||||
/* @deprecated 3.0.0 N°3558 now we are using /css/backoffice/vendors/_jquery* */
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
|
||||
|
||||
|
||||
.ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
{
|
||||
"require" : {
|
||||
"apereo/phpcas" : "~1.3"
|
||||
}
|
||||
"config" : {
|
||||
"classmap-authoritative" : true
|
||||
},
|
||||
"autoload" : {
|
||||
"psr-4" : {
|
||||
"Combodo\\iTop\\Cas\\" : "src"
|
||||
}
|
||||
},
|
||||
"require" : {
|
||||
"apereo/phpcas" : "~1.6.0"
|
||||
}
|
||||
}
|
||||
86
datamodels/2.x/authent-cas/composer.lock
generated
86
datamodels/2.x/authent-cas/composer.lock
generated
@@ -4,28 +4,32 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "4db4df78154f0de344ba35a27fe766b7",
|
||||
"content-hash": "46afbbe7e92c2ccfe403f366ef1877e5",
|
||||
"packages": [
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
"version": "1.3.7",
|
||||
"version": "1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/apereo/phpCAS.git",
|
||||
"reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082"
|
||||
"reference": "f817c72a961484afef95ac64a9257c8e31f063b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/apereo/phpCAS/zipball/b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
|
||||
"reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
|
||||
"url": "https://api.github.com/repos/apereo/phpCAS/zipball/f817c72a961484afef95ac64a9257c8e31f063b9",
|
||||
"reference": "f817c72a961484afef95ac64a9257c8e31f063b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"php": ">=5.4.0"
|
||||
"ext-dom": "*",
|
||||
"php": ">=7.1.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~3.7.10"
|
||||
"monolog/monolog": "^1.0.0 || ^2.0.0",
|
||||
"phpstan/phpstan": "^1.5",
|
||||
"phpunit/phpunit": ">=7.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -45,11 +49,16 @@
|
||||
"authors": [
|
||||
{
|
||||
"name": "Joachim Fritschi",
|
||||
"homepage": "https://wiki.jasig.org/display/~fritschi"
|
||||
"email": "jfritschi@freenet.de",
|
||||
"homepage": "https://github.com/jfritschi"
|
||||
},
|
||||
{
|
||||
"name": "Adam Franco",
|
||||
"homepage": "https://wiki.jasig.org/display/~adamfranco"
|
||||
"homepage": "https://github.com/adamfranco"
|
||||
},
|
||||
{
|
||||
"name": "Henry Pan",
|
||||
"homepage": "https://github.com/phy25"
|
||||
}
|
||||
],
|
||||
"description": "Provides a simple API for authenticating users against a CAS server",
|
||||
@@ -59,7 +68,61 @@
|
||||
"cas",
|
||||
"jasig"
|
||||
],
|
||||
"time": "2019-04-22T19:48:16+00:00"
|
||||
"support": {
|
||||
"issues": "https://github.com/apereo/phpCAS/issues",
|
||||
"source": "https://github.com/apereo/phpCAS/tree/1.6.0"
|
||||
},
|
||||
"time": "2022-10-31T20:39:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
@@ -69,5 +132,6 @@
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__.'/vendor/autoload.php';
|
||||
require_once __DIR__.'/src/Config.php';
|
||||
require_once __DIR__.'/src/CASLoginExtension.php';
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-cas/3.0.2',
|
||||
'authent-cas/3.0.3',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
@@ -24,7 +24,8 @@ SetupWebPage::AddModule(
|
||||
//
|
||||
'datamodel' => array(
|
||||
'model.authent-cas.php',
|
||||
'main.php'
|
||||
'vendor/autoload.php',
|
||||
'src/CASLoginExtension.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
@@ -50,6 +51,7 @@ SetupWebPage::AddModule(
|
||||
'cas_port' => '',
|
||||
'cas_context' => '',
|
||||
'cas_version' => '',
|
||||
'service_base_url' => '',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
17
datamodels/2.x/authent-cas/src/CASLog.php
Normal file
17
datamodels/2.x/authent-cas/src/CASLog.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Cas;
|
||||
|
||||
use LogAPI;
|
||||
|
||||
class CASLog extends LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = 'CASLog';
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
}
|
||||
|
||||
81
datamodels/2.x/authent-cas/src/CASLogger.php
Normal file
81
datamodels/2.x/authent-cas/src/CASLogger.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Cas;
|
||||
|
||||
use IssueLog;
|
||||
use LogAPI;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class CASLogger implements LoggerInterface
|
||||
{
|
||||
public function __construct($sDebugFile)
|
||||
{
|
||||
CASLog::Enable($sDebugFile);
|
||||
}
|
||||
|
||||
const LEVEL_COMPAT = [
|
||||
LogLevel::EMERGENCY => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::ALERT => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::CRITICAL => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::ERROR => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::WARNING => LogAPI::LEVEL_WARNING,
|
||||
LogLevel::NOTICE => LogAPI::LEVEL_INFO,
|
||||
LogLevel::INFO => LogAPI::LEVEL_INFO,
|
||||
LogLevel::DEBUG => LogAPI::LEVEL_DEBUG,
|
||||
];
|
||||
|
||||
public function emergency($message, array $context = array())
|
||||
{
|
||||
CASLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function alert($message, array $context = array())
|
||||
{
|
||||
CASLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function critical($message, array $context = array())
|
||||
{
|
||||
CASLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function error($message, array $context = array())
|
||||
{
|
||||
CASLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function warning($message, array $context = array())
|
||||
{
|
||||
CASLog::Warning('WARNING: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function notice($message, array $context = array())
|
||||
{
|
||||
CASLog::Info('NOTICE: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function info($message, array $context = array())
|
||||
{
|
||||
CASLog::Info('INFO: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function debug($message, array $context = array())
|
||||
{
|
||||
CASLog::Debug('DEBUG: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function log($level, $message, array $context = array())
|
||||
{
|
||||
$sLevel = self::LEVEL_COMPAT[$level] ?? LogAPI::LEVEL_ERROR;
|
||||
CASLog::Log($sLevel, strtoupper($level).": $message", CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
$bCASDebug = Config::Get('cas_debug');
|
||||
if ($bCASDebug)
|
||||
{
|
||||
phpCAS::setDebug(APPROOT.'log/cas.log');
|
||||
phpCAS::setLogger(new CASLogger(APPROOT.'log/cas.log'));
|
||||
}
|
||||
|
||||
// Initialize phpCAS
|
||||
@@ -161,7 +161,8 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
$sCASHost = Config::Get('cas_host');
|
||||
$iCASPort = Config::Get('cas_port');
|
||||
$sCASContext = Config::Get('cas_context');
|
||||
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, false /* session already started */);
|
||||
$sServiceBaseURL = Config::Get('service_base_url', self::GetServiceBaseURL());
|
||||
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, $sServiceBaseURL, false /* session already started */);
|
||||
$sCASCACertPath = Config::Get('cas_server_ca_cert_path');
|
||||
if (empty($sCASCACertPath))
|
||||
{
|
||||
@@ -177,6 +178,38 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
}
|
||||
}
|
||||
|
||||
private static function GetServiceBaseURL()
|
||||
{
|
||||
$protocol = $_SERVER['REQUEST_SCHEME'];
|
||||
$protocol .= '://';
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
|
||||
// explode the host list separated by comma and use the first host
|
||||
$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
|
||||
// see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
|
||||
return $protocol . $hosts[0];
|
||||
} else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
|
||||
$server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
|
||||
} else {
|
||||
if (empty($_SERVER['SERVER_NAME'])) {
|
||||
$server_url = $_SERVER['HTTP_HOST'];
|
||||
} else {
|
||||
$server_url = $_SERVER['SERVER_NAME'];
|
||||
}
|
||||
}
|
||||
if (!strpos($server_url, ':')) {
|
||||
if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
|
||||
$server_port = $_SERVER['SERVER_PORT'];
|
||||
} else {
|
||||
$ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
|
||||
$server_port = $ports[0];
|
||||
}
|
||||
|
||||
$server_url .= ':';
|
||||
$server_url .= $server_port;
|
||||
}
|
||||
return $protocol . $server_url;
|
||||
}
|
||||
|
||||
private function DoUserProvisioning($sLogin)
|
||||
{
|
||||
$bCASUserSynchro = Config::Get('cas_user_synchro');
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS.php
|
||||
* @category Authentication
|
||||
@@ -27,4 +27,6 @@
|
||||
* @link https://wiki.jasig.org/display/CASC/phpCAS
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__).'/source/CAS.php';
|
||||
require_once __DIR__.'/source/CAS.php';
|
||||
|
||||
trigger_error('Including CAS.php is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED);
|
||||
|
||||
@@ -6,22 +6,21 @@ users via a Central Authentication Service (CAS) server.
|
||||
|
||||
Please see the wiki website for more information:
|
||||
|
||||
https://wiki.jasig.org/display/CASC/phpCAS
|
||||
https://apereo.github.io/phpCAS/
|
||||
|
||||
Api documentation can be found here:
|
||||
|
||||
https://apereo.github.io/phpCAS/
|
||||
https://apereo.github.io/phpCAS/api/
|
||||
|
||||
|
||||
[](https://travis-ci.org/apereo/phpCAS)
|
||||
|
||||
[](https://github.com/apereo/phpCAS/actions/workflows/test.yml)
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
Copyright 2007-2015, JA-SIG, Inc.
|
||||
This project includes software developed by Jasig.
|
||||
http://www.jasig.org/
|
||||
Copyright 2007-2020, Apereo Foundation.
|
||||
This project includes software developed by Apereo Foundation.
|
||||
http://www.apereo.org/
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this software except in compliance with the License.
|
||||
|
||||
@@ -1,29 +1,55 @@
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
"description": "Provides a simple API for authenticating users against a CAS server",
|
||||
"keywords": ["cas", "jasig", "apereo"],
|
||||
"homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
|
||||
"type": "library",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{"name": "Joachim Fritschi", "homepage": "https://wiki.jasig.org/display/~fritschi"},
|
||||
{"name": "Adam Franco", "homepage": "https://wiki.jasig.org/display/~adamfranco"}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"ext-curl": "*"
|
||||
"name" : "apereo/phpcas",
|
||||
"description" : "Provides a simple API for authenticating users against a CAS server",
|
||||
"keywords" : [
|
||||
"cas",
|
||||
"jasig",
|
||||
"apereo"
|
||||
],
|
||||
"homepage" : "https://wiki.jasig.org/display/CASC/phpCAS",
|
||||
"type" : "library",
|
||||
"license" : "Apache-2.0",
|
||||
"authors" : [{
|
||||
"name" : "Joachim Fritschi",
|
||||
"homepage" : "https://github.com/jfritschi",
|
||||
"email" : "jfritschi@freenet.de"
|
||||
}, {
|
||||
"name" : "Adam Franco",
|
||||
"homepage" : "https://github.com/adamfranco"
|
||||
}, {
|
||||
"name" : "Henry Pan",
|
||||
"homepage" : "https://github.com/phy25"
|
||||
}
|
||||
],
|
||||
"require" : {
|
||||
"php" : ">=7.1.0",
|
||||
"ext-curl" : "*",
|
||||
"ext-dom" : "*",
|
||||
"psr/log" : "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~3.7.10"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"source/"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
}
|
||||
}
|
||||
"require-dev" : {
|
||||
"monolog/monolog" : "^1.0.0 || ^2.0.0",
|
||||
"phpunit/phpunit" : ">=7.5",
|
||||
"phpstan/phpstan" : "^1.5"
|
||||
},
|
||||
"autoload" : {
|
||||
"classmap" : [
|
||||
"source/"
|
||||
]
|
||||
},
|
||||
"autoload-dev" : {
|
||||
"files": ["source/CAS.php"],
|
||||
"psr-4" : {
|
||||
"PhpCas\\" : "test/CAS/"
|
||||
}
|
||||
},
|
||||
"scripts" : {
|
||||
"test" : "phpunit",
|
||||
"phpstan" : "phpstan"
|
||||
},
|
||||
"extra" : {
|
||||
"branch-alias" : {
|
||||
"dev-master" : "1.3.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*
|
||||
*
|
||||
* Interface class of the phpCAS library
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/CAS.php
|
||||
* @category Authentication
|
||||
@@ -35,6 +35,7 @@
|
||||
* @ingroup public
|
||||
*/
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
//
|
||||
// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI']
|
||||
@@ -44,11 +45,6 @@ if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($
|
||||
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
|
||||
}
|
||||
|
||||
// Add a E_USER_DEPRECATED for php versions <= 5.2
|
||||
if (!defined('E_USER_DEPRECATED')) {
|
||||
define('E_USER_DEPRECATED', E_USER_NOTICE);
|
||||
}
|
||||
|
||||
|
||||
// ########################################################################
|
||||
// CONSTANTS
|
||||
@@ -61,7 +57,7 @@ if (!defined('E_USER_DEPRECATED')) {
|
||||
/**
|
||||
* phpCAS version. accessible for the user by phpCAS::getVersion().
|
||||
*/
|
||||
define('PHPCAS_VERSION', '1.3.7');
|
||||
define('PHPCAS_VERSION', '1.6.0');
|
||||
|
||||
/**
|
||||
* @addtogroup public
|
||||
@@ -140,11 +136,6 @@ define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');
|
||||
*/
|
||||
define("SAML_ATTRIBUTES", 'SAMLATTRIBS');
|
||||
|
||||
/**
|
||||
* SAML Attributes
|
||||
*/
|
||||
define("DEFAULT_ERROR", 'Internal script failure');
|
||||
|
||||
/** @} */
|
||||
/**
|
||||
* @addtogroup publicPGTStorage
|
||||
@@ -224,6 +215,8 @@ define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese');
|
||||
define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish');
|
||||
define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan');
|
||||
define("PHPCAS_LANG_CHINESE_SIMPLIFIED", 'CAS_Languages_ChineseSimplified');
|
||||
define("PHPCAS_LANG_GALEGO", 'CAS_Languages_Galego');
|
||||
define("PHPCAS_LANG_PORTUGUESE", 'CAS_Languages_Portuguese');
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -261,7 +254,7 @@ define('DEFAULT_DEBUG_DIR', gettmpdir()."/");
|
||||
/** @} */
|
||||
|
||||
// include the class autoloader
|
||||
require_once dirname(__FILE__) . '/CAS/Autoload.php';
|
||||
require_once __DIR__ . '/CAS/Autoload.php';
|
||||
|
||||
/**
|
||||
* The phpCAS class is a simple container for the phpCAS library. It provides CAS
|
||||
@@ -330,12 +323,22 @@ class phpCAS
|
||||
/**
|
||||
* phpCAS client initializer.
|
||||
*
|
||||
* @param string $server_version the version of the CAS server
|
||||
* @param string $server_hostname the hostname of the CAS server
|
||||
* @param int $server_port the port the CAS server is running on
|
||||
* @param string $server_uri the URI the CAS server is responding on
|
||||
* @param bool $changeSessionID Allow phpCAS to change the session_id (Single
|
||||
* Sign Out/handleLogoutRequests is based on that change)
|
||||
* @param string $server_version the version of the CAS server
|
||||
* @param string $server_hostname the hostname of the CAS server
|
||||
* @param int $server_port the port the CAS server is running on
|
||||
* @param string $server_uri the URI the CAS server is responding on
|
||||
* @param string|string[]|CAS_ServiceBaseUrl_Interface
|
||||
* $service_base_url the base URL (protocol, host and the
|
||||
* optional port) of the CAS client; pass
|
||||
* in an array to use auto discovery with
|
||||
* an allowlist; pass in
|
||||
* CAS_ServiceBaseUrl_Interface for custom
|
||||
* behavior. Added in 1.6.0. Similar to
|
||||
* serverName config in other CAS clients.
|
||||
* @param bool $changeSessionID Allow phpCAS to change the session_id
|
||||
* (Single Sign Out/handleLogoutRequests
|
||||
* is based on that change)
|
||||
* @param \SessionHandlerInterface $sessionHandler the session handler
|
||||
*
|
||||
* @return void a newly created CAS_Client object
|
||||
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
|
||||
@@ -343,7 +346,8 @@ class phpCAS
|
||||
* and phpCAS::setDebug()).
|
||||
*/
|
||||
public static function client($server_version, $server_hostname,
|
||||
$server_port, $server_uri, $changeSessionID = true
|
||||
$server_port, $server_uri, $service_base_url,
|
||||
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null
|
||||
) {
|
||||
phpCAS :: traceBegin();
|
||||
if (is_object(self::$_PHPCAS_CLIENT)) {
|
||||
@@ -362,8 +366,8 @@ class phpCAS
|
||||
// initialize the object $_PHPCAS_CLIENT
|
||||
try {
|
||||
self::$_PHPCAS_CLIENT = new CAS_Client(
|
||||
$server_version, false, $server_hostname, $server_port, $server_uri,
|
||||
$changeSessionID
|
||||
$server_version, false, $server_hostname, $server_port, $server_uri, $service_base_url,
|
||||
$changeSessionID, $sessionHandler
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
|
||||
@@ -374,12 +378,22 @@ class phpCAS
|
||||
/**
|
||||
* phpCAS proxy initializer.
|
||||
*
|
||||
* @param string $server_version the version of the CAS server
|
||||
* @param string $server_hostname the hostname of the CAS server
|
||||
* @param int $server_port the port the CAS server is running on
|
||||
* @param string $server_uri the URI the CAS server is responding on
|
||||
* @param bool $changeSessionID Allow phpCAS to change the session_id (Single
|
||||
* Sign Out/handleLogoutRequests is based on that change)
|
||||
* @param string $server_version the version of the CAS server
|
||||
* @param string $server_hostname the hostname of the CAS server
|
||||
* @param string $server_port the port the CAS server is running on
|
||||
* @param string $server_uri the URI the CAS server is responding on
|
||||
* @param string|string[]|CAS_ServiceBaseUrl_Interface
|
||||
* $service_base_url the base URL (protocol, host and the
|
||||
* optional port) of the CAS client; pass
|
||||
* in an array to use auto discovery with
|
||||
* an allowlist; pass in
|
||||
* CAS_ServiceBaseUrl_Interface for custom
|
||||
* behavior. Added in 1.6.0. Similar to
|
||||
* serverName config in other CAS clients.
|
||||
* @param bool $changeSessionID Allow phpCAS to change the session_id
|
||||
* (Single Sign Out/handleLogoutRequests
|
||||
* is based on that change)
|
||||
* @param \SessionHandlerInterface $sessionHandler the session handler
|
||||
*
|
||||
* @return void a newly created CAS_Client object
|
||||
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
|
||||
@@ -387,7 +401,8 @@ class phpCAS
|
||||
* and phpCAS::setDebug()).
|
||||
*/
|
||||
public static function proxy($server_version, $server_hostname,
|
||||
$server_port, $server_uri, $changeSessionID = true
|
||||
$server_port, $server_uri, $service_base_url,
|
||||
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null
|
||||
) {
|
||||
phpCAS :: traceBegin();
|
||||
if (is_object(self::$_PHPCAS_CLIENT)) {
|
||||
@@ -406,8 +421,8 @@ class phpCAS
|
||||
// initialize the object $_PHPCAS_CLIENT
|
||||
try {
|
||||
self::$_PHPCAS_CLIENT = new CAS_Client(
|
||||
$server_version, true, $server_hostname, $server_port, $server_uri,
|
||||
$changeSessionID
|
||||
$server_version, true, $server_hostname, $server_port, $server_uri, $service_base_url,
|
||||
$changeSessionID, $sessionHandler
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
|
||||
@@ -435,6 +450,24 @@ class phpCAS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set/unset PSR-3 logger
|
||||
*
|
||||
* @param LoggerInterface $logger the PSR-3 logger used for logging, or
|
||||
* null to stop logging.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setLogger($logger = null)
|
||||
{
|
||||
if (empty(self::$_PHPCAS_DEBUG['unique_id'])) {
|
||||
self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);
|
||||
}
|
||||
self::$_PHPCAS_DEBUG['logger'] = $logger;
|
||||
self::$_PHPCAS_DEBUG['indent'] = 0;
|
||||
phpCAS :: trace('START ('.date("Y-m-d H:i:s").') phpCAS-' . PHPCAS_VERSION . ' ******************');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/unset debug mode
|
||||
*
|
||||
@@ -442,9 +475,13 @@ class phpCAS
|
||||
* to stop debugging.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function setDebug($filename = '')
|
||||
{
|
||||
trigger_error('phpCAS::setDebug() is deprecated in favor of phpCAS::setLogger().', E_USER_DEPRECATED);
|
||||
|
||||
if ($filename != false && gettype($filename) != 'string') {
|
||||
phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)');
|
||||
}
|
||||
@@ -518,14 +555,7 @@ class phpCAS
|
||||
$indent_str = ".";
|
||||
|
||||
|
||||
if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
|
||||
// Check if file exists and modifiy file permissions to be only
|
||||
// readable by the webserver
|
||||
if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
|
||||
touch(self::$_PHPCAS_DEBUG['filename']);
|
||||
// Chmod will fail on windows
|
||||
@chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
|
||||
}
|
||||
if (isset(self::$_PHPCAS_DEBUG['logger']) || !empty(self::$_PHPCAS_DEBUG['filename'])) {
|
||||
for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) {
|
||||
|
||||
$indent_str .= '| ';
|
||||
@@ -533,7 +563,20 @@ class phpCAS
|
||||
// allow for multiline output with proper identing. Usefull for
|
||||
// dumping cas answers etc.
|
||||
$str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
|
||||
error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
|
||||
$str3 = self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2;
|
||||
if (isset(self::$_PHPCAS_DEBUG['logger'])) {
|
||||
self::$_PHPCAS_DEBUG['logger']->info($str3);
|
||||
}
|
||||
if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
|
||||
// Check if file exists and modifiy file permissions to be only
|
||||
// readable by the webserver
|
||||
if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
|
||||
touch(self::$_PHPCAS_DEBUG['filename']);
|
||||
// Chmod will fail on windows
|
||||
@chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
|
||||
}
|
||||
error_log($str3 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -567,8 +610,6 @@ class phpCAS
|
||||
}
|
||||
if (self::$_PHPCAS_VERBOSE) {
|
||||
echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n";
|
||||
} else {
|
||||
echo "<br />\n<b>Error</b>: <font color=\"FF0000\"><b>". DEFAULT_ERROR ."</b><br />\n";
|
||||
}
|
||||
phpCAS :: trace($msg . ' in ' . $file . 'on line ' . $line );
|
||||
phpCAS :: traceEnd();
|
||||
@@ -1869,6 +1910,14 @@ class phpCAS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CAS_Client
|
||||
*/
|
||||
public static function getCasClient()
|
||||
{
|
||||
return self::$_PHPCAS_CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purposes, use this method to set the client to a test double
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/AuthenticationException.php
|
||||
* @category Authentication
|
||||
@@ -72,11 +72,15 @@ implements CAS_Exception
|
||||
phpCAS::traceBegin();
|
||||
$lang = $client->getLangObj();
|
||||
$client->printHTMLHeader($lang->getAuthenticationFailed());
|
||||
printf(
|
||||
$lang->getYouWereNotAuthenticated(),
|
||||
htmlentities($client->getURL()),
|
||||
isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:''
|
||||
);
|
||||
|
||||
if (phpCAS::getVerbose()) {
|
||||
printf(
|
||||
$lang->getYouWereNotAuthenticated(),
|
||||
htmlentities($client->getURL()),
|
||||
$_SERVER['SERVER_ADMIN'] ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
phpCAS::trace($messages[] = 'CAS URL: '.$cas_url);
|
||||
phpCAS::trace($messages[] = 'Authentication failure: '.$failure);
|
||||
if ( $no_response ) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* Autoloader Class
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Autoload.php
|
||||
* @category Authentication
|
||||
@@ -26,18 +26,24 @@ function CAS_autoload($class)
|
||||
// Static to hold the Include Path to CAS
|
||||
static $include_path;
|
||||
// Check only for CAS classes
|
||||
if (substr($class, 0, 4) !== 'CAS_') {
|
||||
if (substr($class, 0, 4) !== 'CAS_' && substr($class, 0, 7) !== 'PhpCas\\') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup the include path if it's not already set from a previous call
|
||||
if (empty($include_path)) {
|
||||
$include_path = array(dirname(dirname(__FILE__)), dirname(dirname(__FILE__)) . '/../test/' );
|
||||
$include_path = array(dirname(__DIR__));
|
||||
}
|
||||
|
||||
// Declare local variable to store the expected full path to the file
|
||||
|
||||
foreach ($include_path as $path) {
|
||||
$file_path = $path . '/' . str_replace('_', '/', $class) . '.php';
|
||||
$class_path = str_replace('_', DIRECTORY_SEPARATOR, $class);
|
||||
// PhpCas namespace mapping
|
||||
if (substr($class_path, 0, 7) === 'PhpCas\\') {
|
||||
$class_path = 'CAS' . DIRECTORY_SEPARATOR . substr($class_path, 7);
|
||||
}
|
||||
|
||||
$file_path = $path . DIRECTORY_SEPARATOR . $class_path . '.php';
|
||||
$fp = @fopen($file_path, 'r', true);
|
||||
if ($fp) {
|
||||
fclose($fp);
|
||||
@@ -54,6 +60,7 @@ function CAS_autoload($class)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$e = new Exception(
|
||||
'Class ' . $class . ' could not be loaded from ' .
|
||||
$file_path . ', file does not exist (Path="'
|
||||
@@ -61,22 +68,22 @@ function CAS_autoload($class)
|
||||
);
|
||||
$trace = $e->getTrace();
|
||||
if (isset($trace[2]) && isset($trace[2]['function'])
|
||||
&& in_array($trace[2]['function'], array('class_exists', 'interface_exists'))
|
||||
&& in_array($trace[2]['function'], array('class_exists', 'interface_exists', 'trait_exists'))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (isset($trace[1]) && isset($trace[1]['function'])
|
||||
&& in_array($trace[1]['function'], array('class_exists', 'interface_exists'))
|
||||
&& in_array($trace[1]['function'], array('class_exists', 'interface_exists', 'trait_exists'))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
die ((string) $e);
|
||||
}
|
||||
|
||||
// set up __autoload
|
||||
if (!(spl_autoload_functions())
|
||||
|| !in_array('CAS_autoload', spl_autoload_functions())
|
||||
) {
|
||||
// Set up autoload if not already configured by composer.
|
||||
if (!class_exists('CAS_Client'))
|
||||
{
|
||||
trigger_error('phpCAS autoloader is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED);
|
||||
spl_autoload_register('CAS_autoload');
|
||||
if (function_exists('__autoload')
|
||||
&& !in_array('__autoload', spl_autoload_functions())
|
||||
@@ -86,5 +93,3 @@ if (!(spl_autoload_functions())
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/CookieJar.php
|
||||
* @category Authentication
|
||||
@@ -231,6 +231,7 @@ class CAS_CookieJar
|
||||
case 'commenturl':
|
||||
case 'discard':
|
||||
case 'httponly':
|
||||
case 'samesite':
|
||||
$cookie[$attributeNameLC] = $attributeValue;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Exception.php
|
||||
* @category Authentication
|
||||
@@ -56,4 +56,4 @@ interface CAS_Exception
|
||||
{
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/GracefullTerminationException.php
|
||||
* @category Authentication
|
||||
@@ -83,4 +83,4 @@ implements CAS_Exception
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/InvalidArgumentException.php
|
||||
* @category Authentication
|
||||
@@ -43,4 +43,4 @@ implements CAS_Exception
|
||||
{
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Catalan.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/ChineseSimplified.php
|
||||
* @category Authentication
|
||||
@@ -111,4 +111,4 @@ class CAS_Languages_ChineseSimplified implements CAS_Languages_LanguageInterface
|
||||
{
|
||||
return '服务器 <b>%s</b> 不可用(<b>%s</b>)。';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/English.php
|
||||
* @category Authentication
|
||||
@@ -111,4 +111,4 @@ class CAS_Languages_English implements CAS_Languages_LanguageInterface
|
||||
{
|
||||
return 'The service `<b>%s</b>\' is not available (<b>%s</b>).';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/French.php
|
||||
* @category Authentication
|
||||
@@ -113,4 +113,4 @@ class CAS_Languages_French implements CAS_Languages_LanguageInterface
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
||||
117
datamodels/2.x/authent-cas/vendor/apereo/phpcas/source/CAS/Languages/Galego.php
vendored
Normal file
117
datamodels/2.x/authent-cas/vendor/apereo/phpcas/source/CAS/Languages/Galego.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Galego.php
|
||||
* @category Authentication
|
||||
* @package PhpCAS
|
||||
* @author Enrique Huelva Rivero enrique.huelvarivero@plexus.es
|
||||
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://wiki.jasig.org/display/CASC/phpCAS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Galego language class
|
||||
*
|
||||
* @class CAS_Languages_Galego
|
||||
* @category Authentication
|
||||
* @package PhpCAS
|
||||
* @author Enrique Huelva Rivero enrique.huelvarivero@plexus.es
|
||||
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://wiki.jasig.org/display/CASC/phpCAS
|
||||
*
|
||||
|
||||
* @sa @link internalLang Internationalization @endlink
|
||||
* @ingroup internalLang
|
||||
*/
|
||||
class CAS_Languages_Galego implements CAS_Languages_LanguageInterface
|
||||
{
|
||||
/**
|
||||
* Get the using server string
|
||||
*
|
||||
* @return string using server
|
||||
*/
|
||||
public function getUsingServer()
|
||||
{
|
||||
return 'usando servidor';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication wanted string
|
||||
*
|
||||
* @return string authentication wanted
|
||||
*/
|
||||
public function getAuthenticationWanted()
|
||||
{
|
||||
return 'Autenticación CAS necesaria!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logout string
|
||||
*
|
||||
* @return string logout
|
||||
*/
|
||||
public function getLogout()
|
||||
{
|
||||
return 'Saída CAS necesaria!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the should have been redirected string
|
||||
*
|
||||
* @return string should habe been redirected
|
||||
*/
|
||||
public function getShouldHaveBeenRedirected()
|
||||
{
|
||||
return 'Xa debería ser redireccionado ao servidor CAS. Faga click <a href="%s">aquí</a> para continuar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication failed string
|
||||
*
|
||||
* @return string authentication failed
|
||||
*/
|
||||
public function getAuthenticationFailed()
|
||||
{
|
||||
return 'Autenticación CAS errada!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the your were not authenticated string
|
||||
*
|
||||
* @return string not authenticated
|
||||
*/
|
||||
public function getYouWereNotAuthenticated()
|
||||
{
|
||||
return '
|
||||
<p>Non estás autenticado</p><p>Podes volver tentalo facendo click <a href="%s">aquí</a>.</p><p>Se o problema persiste debería contactar con el <a href="mailto:%s">administrador deste sitio</a>.</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the service unavailable string
|
||||
*
|
||||
* @return string service unavailable
|
||||
*/
|
||||
public function getServiceUnavailable()
|
||||
{
|
||||
return 'O servizo `<b>%s</b>\' non está dispoñible (<b>%s</b>).';
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/German.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Greek.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Japanese.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/LanguageInterface.php
|
||||
* @category Authentication
|
||||
@@ -93,4 +93,4 @@ interface CAS_Languages_LanguageInterface
|
||||
public function getServiceUnavailable();
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
114
datamodels/2.x/authent-cas/vendor/apereo/phpcas/source/CAS/Languages/Portuguese.php
vendored
Normal file
114
datamodels/2.x/authent-cas/vendor/apereo/phpcas/source/CAS/Languages/Portuguese.php
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Portuguese.php
|
||||
* @category Authentication
|
||||
* @package PhpCAS
|
||||
* @author Sherwin Harris <sherwin.harris@gmail.com>
|
||||
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portuguese language class
|
||||
*
|
||||
* @class CAS_Languages_Portuguese
|
||||
* @category Authentication
|
||||
* @package PhpCAS
|
||||
* @author Sherwin Harris <sherwin.harris@gmail.com>
|
||||
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS
|
||||
*
|
||||
* @sa @link internalLang Internationalization @endlink
|
||||
* @ingroup internalLang
|
||||
*/
|
||||
class CAS_Languages_Portuguese implements CAS_Languages_LanguageInterface
|
||||
{
|
||||
/**
|
||||
* Get the using server string
|
||||
*
|
||||
* @return string using server
|
||||
*/
|
||||
public function getUsingServer()
|
||||
{
|
||||
return 'Usando o servidor';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication wanted string
|
||||
*
|
||||
* @return string authentication wanted
|
||||
*/
|
||||
public function getAuthenticationWanted()
|
||||
{
|
||||
return 'A autenticação do servidor CAS desejado!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logout string
|
||||
*
|
||||
* @return string logout
|
||||
*/
|
||||
public function getLogout()
|
||||
{
|
||||
return 'Saida do servidor CAS desejado!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the should have been redirected string
|
||||
*
|
||||
* @return string should have been redirected
|
||||
*/
|
||||
public function getShouldHaveBeenRedirected()
|
||||
{
|
||||
return 'Você já deve ter sido redirecionado para o servidor CAS. Clique <a href="%s">aqui</a> para continuar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication failed string
|
||||
*
|
||||
* @return string authentication failed
|
||||
*/
|
||||
public function getAuthenticationFailed()
|
||||
{
|
||||
return 'A autenticação do servidor CAS falheu!';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the your were not authenticated string
|
||||
*
|
||||
* @return string not authenticated
|
||||
*/
|
||||
public function getYouWereNotAuthenticated()
|
||||
{
|
||||
return '<p>Você não foi autenticado.</p><p>Você pode enviar sua solicitação novamente clicando <a href="%s">aqui</a>. </p><p>Se o problema persistir, você pode entrar em contato com <a href="mailto:%s">o administrador deste site</a>.</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the service unavailable string
|
||||
*
|
||||
* @return string service unavailable
|
||||
*/
|
||||
public function getServiceUnavailable()
|
||||
{
|
||||
return 'O serviço `<b>%s</b>\' não está disponível (<b>%s</b>).';
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/Language/Spanish.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/OutOfSequenceBeforeAuthenticationCallException.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/OutOfSequenceBeforeClientException.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/OutOfSequenceBeforeProxyException.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/OutOfSequenceException.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/PGTStorage/AbstractStorage.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/PGTStorage/Db.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/PGTStorage/AbstractStorage.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Abstract.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Exception.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Http.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Http/Abstract.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Http/Get.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Http/Post.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Imap.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxiedService/Testabel.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxyChain.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxyChain/AllowedList.php
|
||||
* @category Authentication
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* PHP Version 5
|
||||
* PHP Version 7
|
||||
*
|
||||
* @file CAS/ProxyChain/Any.php
|
||||
* @category Authentication
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user