mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-07 01:54:12 +01:00
Compare commits
339 Commits
3.0.0-beta
...
3.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9fc85e763 | ||
|
|
1a1439946b | ||
|
|
dade45308c | ||
|
|
142699c3b1 | ||
|
|
4c6a7ca30b | ||
|
|
57b08b5b24 | ||
|
|
548d08b1ec | ||
|
|
47fcddc9a6 | ||
|
|
f67f3eaf74 | ||
|
|
0d51dc61f9 | ||
|
|
9949b1b11a | ||
|
|
8be141f692 | ||
|
|
a11bc9ad33 | ||
|
|
3214ae91c7 | ||
|
|
21545da062 | ||
|
|
7476b6d059 | ||
|
|
b15c8e30bc | ||
|
|
39d71c9c43 | ||
|
|
75d913a003 | ||
|
|
2b38c98183 | ||
|
|
ca7f6362bf | ||
|
|
4d8ac5fee5 | ||
|
|
938de4c71c | ||
|
|
3ff117596d | ||
|
|
194459e0de | ||
|
|
95179b0c18 | ||
|
|
d76c9cee6f | ||
|
|
6e45b74665 | ||
|
|
3d8259a083 | ||
|
|
6d8a36e061 | ||
|
|
814038f5fd | ||
|
|
f237b4dd30 | ||
|
|
4cf4c0e4c3 | ||
|
|
86538cf88e | ||
|
|
722cae240e | ||
|
|
f0d3149a1c | ||
|
|
92e315e2c7 | ||
|
|
6150881154 | ||
|
|
cf223b583e | ||
|
|
eb5e5591d7 | ||
|
|
dcf4053c30 | ||
|
|
fedc3d4d76 | ||
|
|
e93c0123aa | ||
|
|
0004586779 | ||
|
|
7ae4fe06ed | ||
|
|
7404599721 | ||
|
|
eb8aed19c2 | ||
|
|
3a05e9159d | ||
|
|
99026cec1f | ||
|
|
029d2ad526 | ||
|
|
1cb100b010 | ||
|
|
197864ff83 | ||
|
|
1e73ee8ccd | ||
|
|
e2b73995e1 | ||
|
|
24cedbdebd | ||
|
|
0dc95f93a9 | ||
|
|
b6bd7fe400 | ||
|
|
03a19ab3f4 | ||
|
|
50849ae4ea | ||
|
|
70d7f576f3 | ||
|
|
bf491b7298 | ||
|
|
40ec7e35fd | ||
|
|
ffe5541361 | ||
|
|
73c55748d7 | ||
|
|
0754dda1d9 | ||
|
|
057bea196e | ||
|
|
e97a266c44 | ||
|
|
b4278a6987 | ||
|
|
50f860a0e8 | ||
|
|
198c9ed479 | ||
|
|
6e076ae1fa | ||
|
|
9d44f0982c | ||
|
|
fd933ce49a | ||
|
|
ae0c43a099 | ||
|
|
7c7386afc7 | ||
|
|
c306c6e30d | ||
|
|
d9ccac3aea | ||
|
|
d8316734e2 | ||
|
|
7ac5c1bbbb | ||
|
|
37585614ba | ||
|
|
03b728b394 | ||
|
|
ae2072f4d5 | ||
|
|
2f6ed8f8af | ||
|
|
1f5dabf8f6 | ||
|
|
eb5cdb053e | ||
|
|
25ee577eba | ||
|
|
f0aaf21a79 | ||
|
|
a906086751 | ||
|
|
ab17eaad27 | ||
|
|
469c1553bf | ||
|
|
4f72f8be0c | ||
|
|
5f2323f10b | ||
|
|
98013a68a4 | ||
|
|
f55193604c | ||
|
|
586b8c5c71 | ||
|
|
a771d35197 | ||
|
|
96e4ef68df | ||
|
|
df40b53b6b | ||
|
|
6d4f919519 | ||
|
|
8af116275c | ||
|
|
e930d34963 | ||
|
|
4de79afe56 | ||
|
|
daf24d8cb3 | ||
|
|
6e0d570d41 | ||
|
|
ce4379920d | ||
|
|
291bbdf3da | ||
|
|
61f6c1fe33 | ||
|
|
a1d6a705ca | ||
|
|
b861d45b08 | ||
|
|
fc7d2551cd | ||
|
|
b15267d8db | ||
|
|
94ce62e424 | ||
|
|
6271a33fdb | ||
|
|
4b6db53e84 | ||
|
|
540b9f8164 | ||
|
|
5839bab042 | ||
|
|
adc7666dd0 | ||
|
|
e3687b3cbb | ||
|
|
e81c02b25a | ||
|
|
28a8a4457e | ||
|
|
eee0f453da | ||
|
|
164a5501c0 | ||
|
|
ab3c1ad4af | ||
|
|
83a3530880 | ||
|
|
0ad23e272b | ||
|
|
b28ef803a3 | ||
|
|
b2155c042e | ||
|
|
b1b1d25186 | ||
|
|
61ee4d6807 | ||
|
|
443292e1f6 | ||
|
|
c025a7aa3b | ||
|
|
86ebb93149 | ||
|
|
120670240c | ||
|
|
5bd8a25440 | ||
|
|
754f755141 | ||
|
|
74b7223d44 | ||
|
|
1fb2ff355d | ||
|
|
61f3d3aeda | ||
|
|
99860e9e20 | ||
|
|
eb164b47e2 | ||
|
|
dbd197d9bc | ||
|
|
e638c65685 | ||
|
|
42b779d301 | ||
|
|
da3bab9647 | ||
|
|
94d53575ae | ||
|
|
c26cfad062 | ||
|
|
9cd9087cc7 | ||
|
|
df7991adeb | ||
|
|
2dcfe0e281 | ||
|
|
bac584a6b4 | ||
|
|
e4d7bf7dbb | ||
|
|
2d907f31dd | ||
|
|
e2001f4585 | ||
|
|
9810f666fd | ||
|
|
de5f47d43e | ||
|
|
d2662e27e1 | ||
|
|
9ac0100d3a | ||
|
|
1ea5983464 | ||
|
|
15081ba82c | ||
|
|
df189bd1f2 | ||
|
|
06f469faf2 | ||
|
|
b27aa70a1e | ||
|
|
0e35b8e4fa | ||
|
|
c0fc62bcb8 | ||
|
|
d1721b0834 | ||
|
|
66e4f369f7 | ||
|
|
c5e1dbce88 | ||
|
|
5d23a250ae | ||
|
|
b46357a1bd | ||
|
|
4433cdb21b | ||
|
|
45dc79f5af | ||
|
|
2ab0fab051 | ||
|
|
be81d1f6c0 | ||
|
|
ddedce1589 | ||
|
|
b557f16cfa | ||
|
|
30bf2015cb | ||
|
|
14b6e903cb | ||
|
|
4f6e040346 | ||
|
|
3e12799d1d | ||
|
|
7d0550879f | ||
|
|
6a765fad50 | ||
|
|
cbb70c94e5 | ||
|
|
b120488085 | ||
|
|
191891ac35 | ||
|
|
f171380396 | ||
|
|
f9e54e1dde | ||
|
|
15e99a898e | ||
|
|
27c397cc1a | ||
|
|
616229140e | ||
|
|
04e016c919 | ||
|
|
a4e43d3f17 | ||
|
|
ed6969be2c | ||
|
|
8105c4d6cd | ||
|
|
3b7073ad4e | ||
|
|
dbb84fa4e6 | ||
|
|
91c7ed9f4d | ||
|
|
e4c818cacb | ||
|
|
5b6b07af48 | ||
|
|
1331bc2139 | ||
|
|
08946066fb | ||
|
|
0de4e62fcd | ||
|
|
8edd155351 | ||
|
|
3980ba81e7 | ||
|
|
0193868581 | ||
|
|
d2b3de9734 | ||
|
|
d1c39c5e10 | ||
|
|
e29ae488a1 | ||
|
|
ad3e3195a8 | ||
|
|
738411005b | ||
|
|
40b095e407 | ||
|
|
3b7cb9a554 | ||
|
|
f474b3de06 | ||
|
|
7890cbd701 | ||
|
|
eef3e9b7ae | ||
|
|
3c081461b0 | ||
|
|
a916df64c9 | ||
|
|
1d0b96e10f | ||
|
|
28070f8682 | ||
|
|
3e428000bd | ||
|
|
165b11f948 | ||
|
|
c6495e7212 | ||
|
|
0fb0b9deab | ||
|
|
ecb1acf5af | ||
|
|
b239e822ef | ||
|
|
615aa594f0 | ||
|
|
2e346a7e80 | ||
|
|
f5b557b0bc | ||
|
|
2703075d39 | ||
|
|
f6fbd5a7a5 | ||
|
|
d1a05f41e5 | ||
|
|
6b67ad93b9 | ||
|
|
884d3c9477 | ||
|
|
26426123b8 | ||
|
|
6725a9f1ef | ||
|
|
8e0ae67803 | ||
|
|
979a43edc9 | ||
|
|
2aaac00015 | ||
|
|
c46cd1c514 | ||
|
|
74d2a6e46c | ||
|
|
1d57b4330b | ||
|
|
034516d0ef | ||
|
|
72d7758259 | ||
|
|
3e9a19b0ea | ||
|
|
6118ee6876 | ||
|
|
fea3c719af | ||
|
|
78eda6a2fc | ||
|
|
65db576654 | ||
|
|
69bca189fd | ||
|
|
5b78820b32 | ||
|
|
79954d3cee | ||
|
|
8a5c144e3b | ||
|
|
af28a2e01d | ||
|
|
55513b2f4b | ||
|
|
e4bf15feb3 | ||
|
|
0080caf55f | ||
|
|
aed8135d56 | ||
|
|
d0ba84068d | ||
|
|
d6d1a5cc23 | ||
|
|
6700de097a | ||
|
|
cf556de76e | ||
|
|
72cddf30fb | ||
|
|
5ec6a1cc0c | ||
|
|
fe0db8f357 | ||
|
|
1ab2b9c5d4 | ||
|
|
67cd5e321e | ||
|
|
81d9ea389d | ||
|
|
3ee9757a85 | ||
|
|
97e0150974 | ||
|
|
7f37c5912a | ||
|
|
2f5a1c99a5 | ||
|
|
5ce9b6ca99 | ||
|
|
bd9286f903 | ||
|
|
4ae7090a51 | ||
|
|
335074701f | ||
|
|
76f70d45dd | ||
|
|
6f147acd76 | ||
|
|
a84d2ce6bb | ||
|
|
ea9c1ab0b3 | ||
|
|
e1dc269171 | ||
|
|
16dc7de8e2 | ||
|
|
88e210d84d | ||
|
|
4f6bd5444b | ||
|
|
0f204f94eb | ||
|
|
f5ae76360e | ||
|
|
8d59024d8e | ||
|
|
32e0031242 | ||
|
|
3fdebdc217 | ||
|
|
7083807319 | ||
|
|
0f01dbc3e5 | ||
|
|
8289b028cf | ||
|
|
f72a6ee963 | ||
|
|
08359cdd05 | ||
|
|
de17439f55 | ||
|
|
6e555e29d1 | ||
|
|
9dae34461b | ||
|
|
06b1e581fe | ||
|
|
d4b515c7b7 | ||
|
|
20759eca23 | ||
|
|
4e420cbcd6 | ||
|
|
0e60c67910 | ||
|
|
808c1fa571 | ||
|
|
dbf8475883 | ||
|
|
2c2155a8e0 | ||
|
|
ffbd94d671 | ||
|
|
3abcdc9c58 | ||
|
|
242f499101 | ||
|
|
6b0106ff73 | ||
|
|
bf991ffb8a | ||
|
|
280afb35a9 | ||
|
|
e095749c90 | ||
|
|
ced0e7cc8f | ||
|
|
6df98c3d41 | ||
|
|
21e16fd2e8 | ||
|
|
bc2e25be99 | ||
|
|
0c5ebc3a84 | ||
|
|
43412b78e3 | ||
|
|
9126635cf2 | ||
|
|
d0986c048a | ||
|
|
fe0c52bedd | ||
|
|
8926c6783a | ||
|
|
95b6dd0cc3 | ||
|
|
121e39b738 | ||
|
|
48dee9c136 | ||
|
|
befde44215 | ||
|
|
a827eed59d | ||
|
|
1613c1bbdc | ||
|
|
909af7f59c | ||
|
|
495b39a7ab | ||
|
|
f9ff66941d | ||
|
|
29871bc6da | ||
|
|
1c983e8093 | ||
|
|
92a9a8c65f | ||
|
|
a3e1b95c8e | ||
|
|
bf2d98a1bf | ||
|
|
abe103eade | ||
|
|
034052cf4b | ||
|
|
4458f26379 | ||
|
|
27217815d1 | ||
|
|
2b71ea108a |
13
.make/git-hooks/README.md
Normal file
13
.make/git-hooks/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Git hooks for iTop
|
||||
|
||||
## ❓ Goal
|
||||
|
||||
Those [git hooks](https://git-scm.com/docs/githooks) aims to ease developing on [iTop](https://github.com/Combodo/iTop).
|
||||
|
||||
## ☑ Available hooks
|
||||
|
||||
* pre-commit : rejects commit if you have at least one SCSS file staged, and no CSS file
|
||||
|
||||
## ⚙ Install
|
||||
|
||||
Just run install.php !
|
||||
26
.make/git-hooks/install.php
Normal file
26
.make/git-hooks/install.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
$aHooks = [
|
||||
'pre-commit.php',
|
||||
];
|
||||
|
||||
$sAppRoot = dirname(__DIR__, 2);
|
||||
|
||||
|
||||
foreach ($aHooks as $sSourceHookFileName) {
|
||||
echo "Processing for `{$sSourceHookFileName}`...\n";
|
||||
$sSourceHookPath = __DIR__.DIRECTORY_SEPARATOR.$sSourceHookFileName;
|
||||
|
||||
$aPathParts = pathinfo($sSourceHookFileName);
|
||||
$sTargetHookPath = $sAppRoot.DIRECTORY_SEPARATOR.'.git'.DIRECTORY_SEPARATOR.'hooks'.DIRECTORY_SEPARATOR.$aPathParts['filename'];
|
||||
|
||||
if (file_exists($sTargetHookPath) || is_link($sTargetHookPath)) {
|
||||
echo "Existing $sTargetHookPath ! Removing...";
|
||||
unlink($sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
echo "Creating symlink for hook in $sTargetHookPath...";
|
||||
symlink($sSourceHookPath, $sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
49
.make/git-hooks/pre-commit.php
Normal file
49
.make/git-hooks/pre-commit.php
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
/**
|
||||
* Reject any commit containing .scss files, but no .css file !
|
||||
*/
|
||||
|
||||
echo "Checking files staged...\n";
|
||||
$sFilesToCommit = shell_exec('git diff --cached --name-only --diff-filter=ACMRT');
|
||||
$aFilesToCommit = explode("\n", $sFilesToCommit);
|
||||
|
||||
$aScssFiles = GetFilesWithExtension('scss', $aFilesToCommit);
|
||||
if (count($aScssFiles) === 0) {
|
||||
echo "No scss file : OK to go !\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$aCssFiles = GetFilesWithExtension('css', $aFilesToCommit);
|
||||
if (count($aCssFiles) === 0) {
|
||||
echo "There are SCSS files staged but no CSS file : REJECTING commit.\n";
|
||||
echo "You must add the compiled SCSS files by running the setup !\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "We have SCSS but also CSS => OK to commit !\n";
|
||||
exit(0);
|
||||
|
||||
|
||||
|
||||
function GetFilesWithExtension($sExtension, $aFiles) {
|
||||
return array_filter(
|
||||
$aFiles,
|
||||
function($item) use ($sExtension) {
|
||||
return (endsWith($item, '.'.$sExtension));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function endsWith( $haystack, $needle ) {
|
||||
$length = strlen( $needle );
|
||||
if( !$length ) {
|
||||
return true;
|
||||
}
|
||||
return substr( $haystack, -$length ) === $needle;
|
||||
}
|
||||
|
||||
function exitWithMessage($sMessage, $iCode) {
|
||||
echo $sMessage;
|
||||
exit($iCode);
|
||||
}
|
||||
@@ -152,5 +152,9 @@ Stickers' design might change from one year to another. For the first year we wa
|
||||
* White hat: Find and/or fix a vulnerability
|
||||
* Contributor: Contribute by finding a bug, making an extension or any other way
|
||||
* Partner: For Combodo's official partners
|
||||
* Graduated: Follow a Combodo's iTop training
|
||||
* Ambassador: Outstanding community contributors
|
||||
* Beta tester: Test and give feedback on beta releases
|
||||
* Extension developer: Develop and publish an extension
|
||||
|
||||

|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
@@ -227,6 +228,20 @@ class ApplicationContext
|
||||
}
|
||||
return $sContext;
|
||||
}
|
||||
/**
|
||||
* Returns the context an array of input blocks
|
||||
*
|
||||
* @return array The context as a sequence of <input type="hidden" /> tags
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetForUIForm()
|
||||
{
|
||||
$aContextInputBlocks = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", htmlentities($sValue, ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
return $aContextInputBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||
@@ -321,7 +336,7 @@ class ApplicationContext
|
||||
$sPrevious = self::GetUrlMakerClass();
|
||||
|
||||
self::$m_sUrlMakerClass = $sClass;
|
||||
$_SESSION['UrlMakerClass'] = $sClass;
|
||||
Session::Set('UrlMakerClass', $sClass);
|
||||
|
||||
return $sPrevious;
|
||||
}
|
||||
@@ -334,9 +349,9 @@ class ApplicationContext
|
||||
{
|
||||
if (is_null(self::$m_sUrlMakerClass))
|
||||
{
|
||||
if (isset($_SESSION['UrlMakerClass']))
|
||||
if (Session::IsSet('UrlMakerClass'))
|
||||
{
|
||||
self::$m_sUrlMakerClass = $_SESSION['UrlMakerClass'];
|
||||
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -389,9 +404,9 @@ class ApplicationContext
|
||||
*/
|
||||
protected static function LoadPluginProperties()
|
||||
{
|
||||
if (isset($_SESSION['PluginProperties']))
|
||||
if (Session::IsSet('PluginProperties'))
|
||||
{
|
||||
self::$m_aPluginProperties = $_SESSION['PluginProperties'];
|
||||
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -411,7 +426,7 @@ class ApplicationContext
|
||||
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||
|
||||
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
|
||||
$_SESSION['PluginProperties'][$sPluginClass][$sProperty] = $value;
|
||||
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -909,6 +909,8 @@ abstract class ApplicationPopupMenuItem
|
||||
/**
|
||||
* Class for adding an item into a popup menu that browses to the given URL
|
||||
*
|
||||
* Note: This works only in the backoffice, {@see \URLButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @since 2.0
|
||||
@@ -963,6 +965,8 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
/**
|
||||
* Class for adding an item into a popup menu that triggers some Javascript code
|
||||
*
|
||||
* Note: This works only in the backoffice, {@see \JSButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @since 2.0
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSection;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\StaticTable\StaticTable;
|
||||
@@ -18,7 +21,10 @@ use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\Form;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\HtmlFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\SelectUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\MedallionIcon\MedallionIcon;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\Title;
|
||||
@@ -260,15 +266,15 @@ JS
|
||||
public static function SetSessionMessage($sClass, $iKey, $sMessageId, $sMessage, $sSeverity, $fRank, $bMustNotExist = false)
|
||||
{
|
||||
$sMessageKey = $sClass.'::'.$iKey;
|
||||
if (!isset($_SESSION['obj_messages'][$sMessageKey])) {
|
||||
$_SESSION['obj_messages'][$sMessageKey] = array();
|
||||
if (!Session::IsSet(['obj_messages', $sMessageKey])) {
|
||||
Session::Set(['obj_messages', $sMessageKey], []);
|
||||
}
|
||||
if (!$bMustNotExist || !array_key_exists($sMessageId, $_SESSION['obj_messages'][$sMessageKey])) {
|
||||
$_SESSION['obj_messages'][$sMessageKey][$sMessageId] = array(
|
||||
if (!$bMustNotExist || !Session::IsSet(['obj_messages', $sMessageKey, $sMessageId])) {
|
||||
Session::Set(['obj_messages', $sMessageKey, $sMessageId], [
|
||||
'rank' => $fRank,
|
||||
'severity' => $sSeverity,
|
||||
'message' => $sMessage,
|
||||
);
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,7 +924,7 @@ HTML
|
||||
$sTip .= "<div class='synchro-source-description'>$sDescription</div>";
|
||||
}
|
||||
$sTip = utils::HtmlEntities($sTip);
|
||||
$sSynchroIcon = '<img id="synchro_'.$sInputId.'" src="../images/transp-lock.png" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true" />';
|
||||
$sSynchroIcon = '<div id="synchro_'.$sInputId.'" class="ibo-field--comments--synchro ibo-pill ibo-is-frozen" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true"><i class="fas fa-lock"></i></div>';
|
||||
$sComments = $sSynchroIcon;
|
||||
}
|
||||
|
||||
@@ -2238,6 +2244,7 @@ EOF
|
||||
// - Final config
|
||||
$sConfigJS = json_encode($aConfig);
|
||||
|
||||
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
|
||||
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
|
||||
|
||||
$oPage->add_ready_script(
|
||||
@@ -2776,7 +2783,7 @@ JS
|
||||
case UR_ALLOWED_YES:
|
||||
$oButton = ButtonUIBlockFactory::MakeForPrimaryAction($aStimuli[$sStimulusCode]->GetLabel(), 'next_action', $sStimulusCode, true);
|
||||
$oButton->AddCSSClass('action');
|
||||
$oButton->SetColor(Button::ENUM_COLOR_NEUTRAL);
|
||||
$oButton->SetColor(Button::ENUM_COLOR_SCHEME_NEUTRAL);
|
||||
$oToolbarButtons->AddSubBlock($oButton);
|
||||
break;
|
||||
|
||||
@@ -2835,11 +2842,10 @@ EOF
|
||||
);
|
||||
|
||||
if (isset($aExtraParams['nbBulkObj'])) {
|
||||
$sClassIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
$sTitle = Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $aExtraParams['nbBulkObj'], $sClass, $aExtraParams['nbBulkObj']);
|
||||
$oTitle = TitleUIBlockFactory::MakeForPageWithIcon($sTitle, $sClassIcon, Title::DEFAULT_ICON_COVER_METHOD, false);
|
||||
$oObjectDetails = PanelUIBlockFactory::MakeForClass(get_class($this), '');
|
||||
$oObjectDetails->SetTitleBlock($oTitle);
|
||||
$sClassIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
$oObjectDetails = PanelUIBlockFactory::MakeForClass($sClass, $sTitle);
|
||||
$oObjectDetails->SetIcon($sClassIcon);
|
||||
$oToolbarButtons->AddCSSClass('ibo-toolbar--button');
|
||||
} else {
|
||||
$oObjectDetails = ObjectFactory::MakeDetails($this, $sMode);
|
||||
@@ -2947,6 +2953,93 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the derived class to create
|
||||
* @param string $sClass
|
||||
* @param \WebPage $oP
|
||||
* @param \ApplicationContext $oAppContext
|
||||
* @param array $aPossibleClasses
|
||||
* @param array $aHiddenFields
|
||||
*
|
||||
* @return void
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function DisplaySelectClassToCreate(string $sClass, WebPage $oP, ApplicationContext $oAppContext, array $aPossibleClasses, array $aHiddenFields)
|
||||
{
|
||||
$sClassLabel = MetaModel::GetName($sClass);
|
||||
$sTitle = Dict::Format('UI:CreationTitle_Class', $sClassLabel);
|
||||
|
||||
$oP->set_title($sTitle);
|
||||
$sClassIconUrl = MetaModel::GetClassIcon($sClass, false);
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, $sTitle)
|
||||
->SetIcon($sClassIconUrl);
|
||||
|
||||
|
||||
$oClassForm = FormUIBlockFactory::MakeStandard();
|
||||
$oPanel->AddMainBlock($oClassForm);
|
||||
|
||||
$oClassForm->AddHtml($oAppContext->GetForForm())
|
||||
->AddSubBlock(InputUIBlockFactory::MakeForHidden('checkSubclass', '0'))
|
||||
->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'new'));
|
||||
|
||||
foreach ($aHiddenFields as $sKey => $sValue) {
|
||||
if (is_scalar($sValue)) {
|
||||
$oClassForm->AddSubBlock(InputUIBlockFactory::MakeForHidden($sKey, $sValue));
|
||||
}
|
||||
}
|
||||
|
||||
$aDefaults = utils::ReadParam('default', array(), false, 'raw_data');
|
||||
foreach ($aDefaults as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $key2 => $value2) {
|
||||
if (is_array($value2)) {
|
||||
foreach ($value2 as $key3 => $value3) {
|
||||
$sValue = utils::EscapeHtml($value3);
|
||||
$oClassForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("default[$key][$key2][$key3]", $sValue));
|
||||
}
|
||||
} else {
|
||||
$sValue = utils::EscapeHtml($value2);
|
||||
$oClassForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("default[$key][$key2]", $sValue));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sValue = utils::EscapeHtml($value);
|
||||
$oClassForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("default[$key]", $sValue));
|
||||
}
|
||||
}
|
||||
|
||||
$oClassForm->AddSubBlock(self::DisplayBlockSelectClassToCreate($sClass, $sClassLabel, $aPossibleClasses));
|
||||
|
||||
$oP->AddSubBlock($oPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClassLabel
|
||||
* @param array $aPossibleClasses
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return UIContentBlock
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public static function DisplayBlockSelectClassToCreate( string $sClass, string $sClassLabel,array $aPossibleClasses): UIContentBlock
|
||||
{
|
||||
$oBlock= UIContentBlockUIBlockFactory::MakeStandard();
|
||||
$oBlock->AddSubBlock(HtmlFactory::MakeRaw(Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel)));
|
||||
$oSelect = SelectUIBlockFactory::MakeForSelect('class');
|
||||
$oBlock->AddSubBlock($oSelect);
|
||||
asort($aPossibleClasses);
|
||||
foreach ($aPossibleClasses as $sClassName => $sClassLabel) {
|
||||
$oSelect->AddOption(SelectOptionUIBlockFactory::MakeForSelectOption($sClassName, $sClassLabel, ($sClassName == $sClass)));
|
||||
}
|
||||
|
||||
$oToolbar = ToolbarUIBlockFactory::MakeForAction();
|
||||
$oBlock->AddSubBlock($oToolbar);
|
||||
$oToolbar->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), null, null, true));
|
||||
return $oBlock;
|
||||
}
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param string $sClass
|
||||
@@ -3146,6 +3239,14 @@ EOF
|
||||
}
|
||||
} else
|
||||
{
|
||||
if ($oAttDef instanceof \AttributeCaseLog) {
|
||||
// Add JS files for display caselog
|
||||
// Dummy collapsible section created in order to get JS files
|
||||
$oCollapsibleSection = new CollapsibleSection('');
|
||||
foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) {
|
||||
$oPage->add_linked_script($sJSFile);
|
||||
}
|
||||
}
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
|
||||
if (is_array($aAllowedValues) && count($aAllowedValues) == 1)
|
||||
{
|
||||
@@ -3225,13 +3326,14 @@ HTML
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('ownership_token', utils::HtmlEntities($sOwnershipToken)));
|
||||
}
|
||||
|
||||
// Note: Remove the table is we want fields to occupy the whole width of the container
|
||||
$oForm->AddHtml('<table><tr><td>');
|
||||
$oForm->AddHtml($oPage->GetDetails($aDetails));
|
||||
$oForm->AddHtml('</td></tr></table>');
|
||||
// Note: Remove the table if we want fields to occupy the whole width of the container
|
||||
$sHtml = '<table><tr><td>';
|
||||
$sHtml .= $oPage->GetDetails($aDetails);
|
||||
$sHtml .= '</td></tr></table>';
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
$oForm->AddHtml($oAppContext->GetForForm());
|
||||
$sHtml .= $oAppContext->GetForForm();
|
||||
$oForm->AddHtml($sHtml);
|
||||
|
||||
$oCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel'), 'cancel', 'cancel');
|
||||
$oCancelButton->SetOnClickJsCode("BackToDetails('{$sClass}', '{$this->GetKey()}', '', '{$sOwnershipToken}');");
|
||||
@@ -4137,6 +4239,25 @@ HTML;
|
||||
|
||||
/**
|
||||
* Updates the object from a given page argument
|
||||
*
|
||||
* The values are read from parameters (GET or POST, using {@see utils::ReadParam()}).
|
||||
*
|
||||
* To pass the arg, either add in HTML :
|
||||
*
|
||||
* ```html
|
||||
* <input type="hidden" name="sArgName[attCode1]" value="...">
|
||||
* <input type="hidden" name="sArgName[attCode2]" value="...">
|
||||
* ```
|
||||
*
|
||||
* Or directly in the URL :
|
||||
*
|
||||
* ```php
|
||||
* $aObjectArgs = ['attCode1' => ..., 'attCode2' => ...];
|
||||
* $sQueryString = http_build_query(['sArgName' => $aObjectArgs]);
|
||||
* ```
|
||||
*
|
||||
* @uses utils::ReadParam()
|
||||
* @uses self::UpdateObjectFromArray
|
||||
*/
|
||||
public function UpdateObjectFromArg($sArgName, $aAttList = null, $aAttFlags = array())
|
||||
{
|
||||
@@ -4766,8 +4887,8 @@ HTML
|
||||
$sTip = Dict::S('UI:Component:Field:BulkModify:UnknownValues:Tooltip');
|
||||
|
||||
$oDummyObj->Set($sAttCode, null);
|
||||
$aComments[$sAttCode] = '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'"> ? </div>';
|
||||
$aComments[$sAttCode] = '<div class="multi_values ibo-field--enable-bulk ibo-pill ibo-is-failure" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'">?';
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" class="ibo-field--enable-bulk--checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/></div>';
|
||||
$sReadyScript .= 'ToggleField(false, \''.$iFormId.'_'.$sAttCode.'\');'."\n";
|
||||
} else {
|
||||
$iCount = count($aValues[$sAttCode]);
|
||||
@@ -4776,13 +4897,13 @@ HTML
|
||||
reset($aValues[$sAttCode]);
|
||||
$aKeys = array_keys($aValues[$sAttCode]);
|
||||
$currValue = $aKeys[0]; // The only value is the first key
|
||||
//echo "<p>current value for $sAttCode : $currValue</p>";
|
||||
$oDummyObj->Set($sAttCode, $currValue);
|
||||
$aComments[$sAttCode] = '';
|
||||
$sValueCheckbox = '';
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass) || !MetaModel::HasLifecycle($sClass)) {
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$sValueCheckbox .= '<input type="checkbox" class="ibo-field--enable-bulk--checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="mono_value">1</div>';
|
||||
$aComments[$sAttCode] .= '<div class="mono_value ibo-field--enable-bulk ibo-pill ibo-is-success">1'.$sValueCheckbox.'</div>';
|
||||
} else {
|
||||
// Non-homogeneous value
|
||||
$aMultiValues = $aValues[$sAttCode];
|
||||
@@ -4828,10 +4949,12 @@ HTML
|
||||
$oDummyObj->Set($sAttCode, null);
|
||||
}
|
||||
$aComments[$sAttCode] = '';
|
||||
$sValueCheckbox = '';
|
||||
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass) || !MetaModel::HasLifecycle($sClass)) {
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$sValueCheckbox = '<input type="checkbox" class="ibo-field--enable-bulk--checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToggleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true">'.$iCount.'</div>';
|
||||
$aComments[$sAttCode] .= '<div class="multi_values ibo-field--enable-bulk ibo-pill ibo-is-failure" id="multi_values_'.$sAttCode.'" data-tooltip-content="'.$sTip.'" data-tooltip-html-enabled="true">'.$iCount.$sValueCheckbox.'</div>';
|
||||
}
|
||||
$sReadyScript .= 'ToggleField('.(($iCount == 1) ? 'true' : 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
|
||||
}
|
||||
@@ -4851,10 +4974,6 @@ HTML
|
||||
//$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
|
||||
//$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
|
||||
}
|
||||
/*$sClassIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
$sTitle = Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $iAllowedCount, $sClass, $iAllowedCount);
|
||||
$oTitle = TitleUIBlockFactory::MakeForPageWithIcon($sTitle, $sClassIcon, Title::DEFAULT_ICON_COVER_METHOD, false);
|
||||
$oP->AddSubBlock($oTitle);*/
|
||||
|
||||
$oP->add("<div class=\"wizContainer\">\n");
|
||||
$sDisableFields = json_encode($aExcludeAttributes);
|
||||
@@ -4926,7 +5045,6 @@ EOF
|
||||
|
||||
$sHeaderTitle = Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), MetaModel::GetName($sClass));
|
||||
$sClassIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
$oTitle = TitleUIBlockFactory::MakeForPageWithIcon($sHeaderTitle, $sClassIcon, Title::DEFAULT_ICON_COVER_METHOD, false);
|
||||
|
||||
|
||||
$oP->set_title(Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass));
|
||||
@@ -4969,6 +5087,8 @@ EOF
|
||||
$oTable->AddOption("bFullscreen", true);
|
||||
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, '');
|
||||
$oPanel->SetIcon($sClassIcon);
|
||||
$oPanel->SetTitle($sHeaderTitle);
|
||||
$oPanel->AddCSSClass('ibo-datatable-panel');
|
||||
$oPanel->AddSubBlock($oTable);
|
||||
|
||||
@@ -4979,7 +5099,6 @@ EOF
|
||||
$oForm = FormUIBlockFactory::MakeStandard('')->SetAction($sFormAction);
|
||||
$oP->AddSubBlock($oForm);
|
||||
$oForm->AddSubBlock($oPanel);
|
||||
$oPanel->SetTitleBlock($oTitle);
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
$oP->add($oAppContext->GetForForm());
|
||||
@@ -5010,7 +5129,6 @@ EOF
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$oP->AddUiBlock($oTitle);
|
||||
$oP->AddUiBlock($oPanel);
|
||||
$oP->AddSubBlock(ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Done')))->SetOnClickJsCode("window.location.href='$sCancelUrl'")->AddCSSClass('mt-5');
|
||||
}
|
||||
@@ -5128,19 +5246,21 @@ EOF
|
||||
}
|
||||
|
||||
$iImpactedIndirectly = $oDeletionPlan->GetTargetCount() - count($aObjects);
|
||||
$sImpactedTableTitle = '';
|
||||
$sImpactedTableSubtitle = '';
|
||||
if ($iImpactedIndirectly > 0)
|
||||
{
|
||||
if (count($aObjects) == 1)
|
||||
{
|
||||
$oObj = $aObjects[0];
|
||||
$oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly,
|
||||
$oObj->GetName()));
|
||||
$sImpactedTableTitle = Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly,
|
||||
$oObj->GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly));
|
||||
$sImpactedTableTitle = Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly);
|
||||
}
|
||||
$oP->p(Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity'));
|
||||
$sImpactedTableSubtitle = Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity');
|
||||
}
|
||||
|
||||
if (($iImpactedIndirectly > 0) || $oDeletionPlan->FoundStopper())
|
||||
@@ -5152,7 +5272,11 @@ EOF
|
||||
'label' => 'Consequence',
|
||||
'description' => Dict::S('UI:Delete:Consequence+'),
|
||||
);
|
||||
$oP->AddSubBlock(DataTableUIBlockFactory::MakeForForm(preg_replace('/[^a-zA-Z0-9_-]/', '', uniqid('form_', true)), $aDisplayConfig, $aDisplayData));
|
||||
$oBlock = PanelUIBlockFactory::MakeNeutral($sImpactedTableTitle, $sImpactedTableSubtitle);
|
||||
|
||||
$oDataTable = DataTableUIBlockFactory::MakeForForm(utils::Sanitize(uniqid('form_', true), '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER), $aDisplayConfig, $aDisplayData);
|
||||
$oBlock->AddSubBlock($oDataTable);
|
||||
$oP->AddUiBlock($oBlock);
|
||||
}
|
||||
|
||||
if ($oDeletionPlan->FoundStopper()) {
|
||||
@@ -5183,7 +5307,6 @@ EOF
|
||||
$sSubtitle = Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects),
|
||||
MetaModel::GetName($sClass));
|
||||
}
|
||||
$oP->AddUiBlock(TitleUIBlockFactory::MakeStandard(new Html($sSubtitle)));
|
||||
|
||||
foreach ($aObjects as $oObj) {
|
||||
$aKeys[] = $oObj->GetKey();
|
||||
@@ -5193,7 +5316,14 @@ EOF
|
||||
$oSet = new CMDBobjectSet($oFilter);
|
||||
$oDisplaySet = UIContentBlockUIBlockFactory::MakeStandard("0");
|
||||
$oP->AddSubBlock($oDisplaySet);
|
||||
$oDisplaySet->AddSubBlock(CMDBAbstractObject::GetDisplaySetBlock($oP, $oSet, array('display_limit' => false, 'menu' => false)));
|
||||
$oDisplaySet->AddSubBlock(CMDBAbstractObject::GetDisplaySetBlock($oP, $oSet, array(
|
||||
'display_limit' => false,
|
||||
'menu' => false,
|
||||
'surround_with_panel' => true,
|
||||
'panel_title' => $sSubtitle,
|
||||
'panel_icon' => MetaModel::GetClassIcon($sClass, false),
|
||||
'panel_class' => $sClass,
|
||||
)));
|
||||
|
||||
$oForm = FormUIBlockFactory::MakeStandard('');
|
||||
$oP->AddSubBlock($oForm);
|
||||
@@ -5292,18 +5422,16 @@ EOF
|
||||
$sSubtitle = Dict::Format('UI:Delete:CleaningUpRefencesTo_Several_ObjectsOf_Class', count($aObjects),
|
||||
MetaModel::GetName($sClass));
|
||||
}
|
||||
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sSubtitle));
|
||||
|
||||
$aDisplayConfig = array();
|
||||
$aDisplayConfig['class'] = array('label' => 'Class', 'description' => '');
|
||||
$aDisplayConfig['object'] = array('label' => 'Object', 'description' => '');
|
||||
$aDisplayConfig['consequence'] = array('label' => 'Done', 'description' => Dict::S('UI:Delete:Done+'));
|
||||
|
||||
$oResultsPanel = PanelUIBlockFactory::MakeForInformation('');
|
||||
$oResultsPanel = PanelUIBlockFactory::MakeForInformation($sSubtitle);
|
||||
$oP->AddUiBlock($oResultsPanel);
|
||||
$oResultsPanel->AddSubBlock(
|
||||
DataTableUIBlockFactory::MakeForStaticData('', $aDisplayConfig, $aDisplayData)
|
||||
);
|
||||
$oDatatable = DataTableUIBlockFactory::MakeForStaticData('', $aDisplayConfig, $aDisplayData);
|
||||
$oResultsPanel->AddSubBlock($oDatatable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ EOF
|
||||
|
||||
if ($bFromDasboardPage) {
|
||||
$sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
|
||||
$sHtml = "<div class=\"ibo-top-bar--toolbar-dashboard-title\">{$sTitleForHTML}</div>";
|
||||
$sHtml = "<div class=\"ibo-top-bar--toolbar-dashboard-title\" title=\"{$sTitleForHTML}\">{$sTitleForHTML}</div>";
|
||||
if ($oPage instanceof iTopWebPage) {
|
||||
$oTopBar = $oPage->GetTopBarLayout();
|
||||
$oToolbar = ToolbarUIBlockFactory::MakeStandard();
|
||||
@@ -552,7 +552,7 @@ EOF
|
||||
$oToolbar->AddHtml($sHtml);
|
||||
} else {
|
||||
$oPage->add_script(<<<JS
|
||||
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML");
|
||||
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML").attr("title", "$sTitleForHTML");
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Dashlet\DashletContainer;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Dashlet\DashletFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
@@ -202,6 +203,24 @@ abstract class Dashlet
|
||||
$this->OnUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Rel. path to the app. root of the JS files required by the dashlet
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetJSFilesRelPaths(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Rel. path to the app. root of the CSS files required by the dashlet
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetCSSFilesRelPaths(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
@@ -224,6 +243,9 @@ abstract class Dashlet
|
||||
$oDashletContainer->AddCSSClasses($this->aCSSClasses);
|
||||
}
|
||||
|
||||
$oDashletContainer->AddMultipleJsFilesRelPaths($this->GetJSFilesRelPaths());
|
||||
$oDashletContainer->AddMultipleCssFilesRelPaths($this->GetCSSFilesRelPaths());
|
||||
|
||||
try {
|
||||
if (get_class($this->oModelReflection) == 'ModelReflectionRuntime') {
|
||||
$oBlock = $this->Render($oPage, $bEditMode, $aExtraParams);
|
||||
@@ -604,8 +626,7 @@ class DashletUnknown extends Dashlet
|
||||
|
||||
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div><div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
@@ -624,8 +645,7 @@ class DashletUnknown extends Dashlet
|
||||
|
||||
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div><div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
@@ -1676,6 +1696,28 @@ class DashletGroupByPie extends DashletGroupBy
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetJSFilesRelPaths(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::GetJSFilesRelPaths(),
|
||||
WebResourcesHelper::GetJSFilesRelPathsForC3JS()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCSSFilesRelPaths(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::GetCSSFilesRelPaths(),
|
||||
WebResourcesHelper::GetCSSFilesRelPathsForC3JS()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
||||
@@ -270,6 +270,8 @@ class DisplayBlock
|
||||
'panel_title',
|
||||
/** string class for panel block style */
|
||||
'panel_class',
|
||||
/** string class for panel block style */
|
||||
'panel_icon',
|
||||
];
|
||||
|
||||
if (isset($aAllowedParams[$sStyle])) {
|
||||
@@ -1010,9 +1012,10 @@ JS
|
||||
$aCountsQueryResults[$aCountGroupBySingleResult[0]] = $aCountGroupBySingleResult[1];
|
||||
}
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
|
||||
$aValues = $oAttDef->GetAllowedValues();
|
||||
foreach ($aStates as $sStateValue) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
|
||||
$aStateLabels[$sStateValue] = $oAttDef->GetAsPlainText($sStateValue);
|
||||
$aStateLabels[$sStateValue] = $aValues[$sStateValue];
|
||||
$aCounts[$sStateValue] = (array_key_exists($sStateValue, $aCountsQueryResults))
|
||||
? $aCountsQueryResults[$sStateValue]
|
||||
: 0;
|
||||
@@ -1040,8 +1043,7 @@ JS
|
||||
$sCountLabel = $aCount['label'];
|
||||
$oPill = PillFactory::MakeForState($sClass, $sStateValue)
|
||||
->SetTooltip($sStateLabel)
|
||||
->AddHtml("<span class=\"ibo-dashlet-header-dynamic--count\">$sCountLabel</span>")
|
||||
->AddHtml("<span class=\"ibo-dashlet-header-dynamic--label ibo-text-truncated-with-ellipsis\">$sStateLabel</span>");
|
||||
->AddHtml("<span class=\"ibo-dashlet-header-dynamic--count\">$sCountLabel</span><span class=\"ibo-dashlet-header-dynamic--label ibo-text-truncated-with-ellipsis\">$sStateLabel</span>");
|
||||
if ($sHyperlink != '-') {
|
||||
$oPill->SetUrl($sHyperlink);
|
||||
}
|
||||
@@ -1196,6 +1198,9 @@ JS
|
||||
$sTitle = Dict::Format($sFormat, $iTotalCount);
|
||||
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
|
||||
$oBlock->AddSubTitleBlock(new Html($sTitle));
|
||||
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
|
||||
$oBlock->SetIcon($aExtraParams["panel_icon"]);
|
||||
}
|
||||
$oDataTable = DataTableUIBlockFactory::MakeForStaticData("", $aAttribs, $aData, null, $aExtraParams, $this->m_oFilter->ToOQL(), $aOption);
|
||||
$oBlock->AddSubBlock($oDataTable);
|
||||
} else {
|
||||
@@ -1212,6 +1217,9 @@ JS
|
||||
}
|
||||
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
|
||||
$oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
|
||||
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
|
||||
$oBlock->SetIcon($aExtraParams["panel_icon"]);
|
||||
}
|
||||
$oBlock->AddSubBlock(new Html('<p>'.Dict::Format($sFormat, $iCount).'</p>'));
|
||||
} else {
|
||||
$oBlock = new Html('<p>'.Dict::Format($sFormat, $iCount).'</p>');
|
||||
@@ -1347,6 +1355,9 @@ JS
|
||||
|
||||
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
|
||||
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
|
||||
$oPanel->SetIcon($aExtraParams["panel_icon"]);
|
||||
}
|
||||
$oPanel->AddSubBlock($oBlock);
|
||||
|
||||
return $oPanel;
|
||||
@@ -1544,6 +1555,9 @@ JS
|
||||
|
||||
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
|
||||
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
|
||||
$oPanel->SetIcon($aExtraParams["panel_icon"]);
|
||||
}
|
||||
$oPanel->AddSubBlock($oBlock);
|
||||
|
||||
return $oPanel;
|
||||
@@ -1632,6 +1646,9 @@ JS
|
||||
}
|
||||
if (isset($aExtraParams["surround_with_panel"]) && $aExtraParams["surround_with_panel"]) {
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]);
|
||||
if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){
|
||||
$oPanel->SetIcon($aExtraParams["panel_icon"]);
|
||||
}
|
||||
$oPanel->AddSubBlock($oBlock);
|
||||
|
||||
return $oPanel;
|
||||
@@ -2319,7 +2336,7 @@ class MenuBlock extends DisplayBlock
|
||||
// - Refresh
|
||||
if ($sRefreshAction != '') {
|
||||
$oActionButton = ButtonUIBlockFactory::MakeAlternativeNeutral('', 'UI:Button:Refresh');
|
||||
$oActionButton->SetIconClass('fas fa-sync')
|
||||
$oActionButton->SetIconClass('fas fa-sync-alt')
|
||||
->SetOnClickJsCode($sRefreshAction)
|
||||
->SetTooltip(Dict::S('UI:Button:Refresh'))
|
||||
->AddCSSClasses(['ibo-action-button', 'ibo-regular-action-button']);
|
||||
|
||||
@@ -229,8 +229,8 @@ class DesignerForm
|
||||
$aRow = $oField->Render($oP, $sFormId, 'property');
|
||||
if ($oField->IsVisible()) {
|
||||
$sFieldId = $this->GetFieldId($oField->GetCode());
|
||||
$sValidation = $this->GetValidationArea($sFieldId, '<span data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></span>');
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply ibo-prop--apply ibo-button ibo-is-alternative" >'.$sValidation.'</td><td class="prop_icon prop_cancel ibo-prop--cancel ibo-button ibo-is-alternative"><span data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-times"></i></span></td>'
|
||||
$sValidation = $this->GetValidationArea($sFieldId, '<div class="ibo-button ibo-is-alternative ibo-is-success" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></div>');
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply ibo-prop--apply" >'.$sValidation.'</td><td class="prop_icon prop_cancel ibo-prop--cancel"><span><div class="ibo-button ibo-is-alternative ibo-is-neutral" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-undo"></i></div></span></td>'
|
||||
.$this->EndRow();
|
||||
|
||||
if (is_null($aRow['label'])) {
|
||||
@@ -1217,9 +1217,14 @@ class DesignerComboField extends DesignerFormField
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetAllowedValues($aAllowedValues)
|
||||
|
||||
public function SetAllowedValues(?array $aAllowedValues)
|
||||
{
|
||||
// Make sure to have an actual array for values
|
||||
if (is_null($aAllowedValues)) {
|
||||
$aAllowedValues = [];
|
||||
}
|
||||
|
||||
$this->aAllowedValues = $aAllowedValues;
|
||||
}
|
||||
|
||||
@@ -1296,11 +1301,11 @@ class DesignerComboField extends DesignerFormField
|
||||
{
|
||||
if ($this->bMultipleSelection)
|
||||
{
|
||||
$sHtml = "<select $sCSSClasses multiple size=\"8\"id=\"$sId\" name=\"$sName\">";
|
||||
$sHtml = "<span><select $sCSSClasses multiple size=\"8\"id=\"$sId\" name=\"$sName\">";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\">";
|
||||
$sHtml = "<span class=\"ibo-input-select-wrapper\"><select $sCSSClasses id=\"$sId\" name=\"$sName\">";
|
||||
if ($this->sNullLabel != '')
|
||||
{
|
||||
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
|
||||
@@ -1320,7 +1325,7 @@ class DesignerComboField extends DesignerFormField
|
||||
$sHtmlValue = str_replace(' ', ' ', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
|
||||
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
|
||||
}
|
||||
$sHtml .= "</select>";
|
||||
$sHtml .= "</select></span>";
|
||||
if ($this->bOtherChoices)
|
||||
{
|
||||
$sHtml .= '<br/><input type="checkbox" id="other_chk_'.$sId.'"><label for="other_chk_'.$sId.'"> Other:</label> <input type="text" id="other_'.$sId.'" name="other_'.$sName.'" size="30"/>';
|
||||
@@ -1498,7 +1503,7 @@ class DesignerIconSelectionField extends DesignerFormField
|
||||
$sPostUploadTo = ($this->sUploadUrl == null) ? 'null' : "'{$this->sUploadUrl}'";
|
||||
if (!$this->IsReadOnly()) {
|
||||
$sDefaultValue = ($this->defaultValue !== '') ? $this->defaultValue : $this->aAllowedValues[$idx]['value'];
|
||||
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/>";
|
||||
$sValue = "<span class=\"ibo-input-select-wrapper\"><input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/></span>";
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').icon_select({current_idx: $idx, items: $sJSItems, post_upload_to: $sPostUploadTo});
|
||||
@@ -1753,18 +1758,18 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
}
|
||||
$sHtml = "<span $sCSSClasses>".$sDisplayValue.$sHiddenValue."</span>";
|
||||
} else {
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||
$sHtml = "<span class=\"ibo-input-select-wrapper\"><select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||
foreach ($this->aSubForms as $iKey => $aFormData) {
|
||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');
|
||||
$sValue = htmlentities($aFormData['value'], ENT_QUOTES, 'UTF-8');
|
||||
$sSelected = ($iKey == $this->defaultValue) ? 'selected' : '';
|
||||
$sHtml .= "<option data-value=\"$sValue\" value=\"$iKey\" $sSelected>".$sDisplayValue."</option>";
|
||||
}
|
||||
$sHtml .= "</select>";
|
||||
$sHtml .= "</select></span>";
|
||||
}
|
||||
|
||||
if ($sRenderMode == 'property') {
|
||||
$sHtml .= '</td><td class="prop_icon prop_apply ibo-prop--apply ibo-button ibo-is-alternative"><span data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></span></td><td class="prop_icon prop_cancel ibo-prop--cancel ibo-button ibo-is-alternative"><span data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-times"></i></span></td></tr>';
|
||||
$sHtml .= '</td><td class="prop_icon prop_apply ibo-prop--apply"><span><button class="ibo-button ibo-is-alternative ibo-is-success" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></button></span></td><td class="prop_icon prop_cancel ibo-prop--cancel"><span><button class="ibo-button ibo-is-alternative ibo-is-neutral" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-times"></i></button></span></td></tr>';
|
||||
}
|
||||
foreach ($this->aSubForms as $sKey => $aFormData) {
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginBasic
|
||||
*
|
||||
@@ -20,19 +23,19 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
if (!Session::IsSet('login_mode'))
|
||||
{
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
Session::Set('login_mode', 'basic');
|
||||
}
|
||||
elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
Session::Set('login_mode', 'basic');
|
||||
}
|
||||
elseif (isset($_SERVER['PHP_AUTH_USER']))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
Session::Set('login_mode', 'basic');
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -40,10 +43,10 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']) || $_SESSION['login_mode'] == 'basic')
|
||||
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'basic')
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
list($sAuthUser) = $this->GetAuthUserAndPassword();
|
||||
Session::Set('login_temp_auth_user', $sAuthUser);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -51,10 +54,10 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
@@ -65,17 +68,17 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
{
|
||||
list($sAuthUser) = $this->GetAuthUserAndPassword();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
{
|
||||
LoginWebPage::HTTP401Error();
|
||||
}
|
||||
@@ -84,9 +87,9 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
Session::Set('can_logoff', true);
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginDefaultBefore
|
||||
*/
|
||||
@@ -23,7 +25,7 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_OK;
|
||||
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
Session::Unset('login_temp_auth_user');
|
||||
|
||||
// Check if proposed login mode is present and allowed
|
||||
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
|
||||
@@ -32,11 +34,11 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
|
||||
if ($index !== false)
|
||||
{
|
||||
// Force login mode
|
||||
$_SESSION['login_mode'] = $sProposedLoginMode;
|
||||
Session::Set('login_mode', $sProposedLoginMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($_SESSION['login_mode']);
|
||||
Session::Unset('login_mode');
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -91,7 +93,7 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
|
||||
protected function OnCredentialsOk(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
if (!Session::IsSet('login_mode'))
|
||||
{
|
||||
// If no plugin validated the user, exit
|
||||
self::ResetLoginSession();
|
||||
@@ -110,7 +112,7 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
Session::Unset('login_temp_auth_user');
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -118,11 +120,11 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
private static function ResetLoginSession()
|
||||
{
|
||||
LoginWebPage::ResetSession();
|
||||
foreach (array_keys($_SESSION) as $sKey)
|
||||
foreach (Session::ListVariables() as $sKey)
|
||||
{
|
||||
if (utils::StartsWith($sKey, 'login_'))
|
||||
{
|
||||
unset($_SESSION[$sKey]);
|
||||
Session::Unset($sKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginExternal
|
||||
*
|
||||
@@ -22,12 +24,12 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
if (!Session::IsSet('login_mode'))
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if ($sAuthUser && (strlen($sAuthUser) > 0))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'external';
|
||||
Session::Set('login_mode', 'external');
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -35,10 +37,10 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, '', Session::Get('login_mode'), 'external'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
@@ -49,19 +51,19 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', Session::Get('login_mode'));
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
{
|
||||
$_SESSION['can_logoff'] = false;
|
||||
Session::Set('can_logoff', false);
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -69,7 +71,7 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
{
|
||||
LoginWebPage::HTTP401Error();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginForm
|
||||
*
|
||||
@@ -29,8 +31,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form'))
|
||||
{
|
||||
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'form') {
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
|
||||
@@ -50,9 +51,8 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
$this->bForceFormOnError = false;
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
$_SESSION['login_mode'] = 'form';
|
||||
Session::Set('login_temp_auth_user', $sAuthUser);
|
||||
Session::Set('login_mode', 'form');
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -62,11 +62,11 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
@@ -80,19 +80,19 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
{
|
||||
if (isset($_SESSION['auth_user']))
|
||||
if (Session::IsSet('auth_user'))
|
||||
{
|
||||
// If FSM reenter this state (example 2FA) then the auth_user is not resubmitted
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
}
|
||||
// Store 'auth_user' in session for further use
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
{
|
||||
$this->bForceFormOnError = true;
|
||||
}
|
||||
@@ -114,9 +114,9 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
Session::Set('can_logoff', true);
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\TwigExtension;
|
||||
|
||||
/**
|
||||
@@ -238,16 +239,9 @@ class LoginTwigRenderer
|
||||
|
||||
public function GetDefaultVars()
|
||||
{
|
||||
$sLogo = 'itop-logo-external.png';
|
||||
$sBrandingLogo = 'login-logo.png';
|
||||
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo))
|
||||
{
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||
|
||||
$aVars = array(
|
||||
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginURL
|
||||
*
|
||||
@@ -26,13 +28,13 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred)
|
||||
if (!Session::IsSet('login_mode') && !$this->bErrorOccurred)
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (!empty($sAuthUser) && !empty($sAuthPwd))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'url';
|
||||
Session::Set('login_mode', 'url');
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -40,20 +42,20 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
{
|
||||
$_SESSION['login_temp_auth_user'] = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
Session::Set('login_temp_auth_user', utils::ReadParam('auth_user', '', false, 'raw_data'));
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
@@ -64,17 +66,17 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
{
|
||||
$this->bErrorOccurred = true;
|
||||
}
|
||||
@@ -83,9 +85,9 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
Session::Set('can_logoff', true);
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Web page used for displaying the login form
|
||||
*/
|
||||
@@ -139,16 +142,9 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
public function DisplayLoginHeader($bMainAppLogo = false)
|
||||
{
|
||||
$sLogo = 'itop-logo-external.png';
|
||||
$sBrandingLogo = 'login-logo.png';
|
||||
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo))
|
||||
{
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||
$this->add("<div id=\"login-logo\"><a href=\"".htmlentities($sIconUrl, ENT_QUOTES,
|
||||
self::PAGES_CHARSET)."\"><img title=\"$sVersionShort\" src=\"$sDisplayIcon\"></a></div>\n");
|
||||
}
|
||||
@@ -392,11 +388,11 @@ class LoginWebPage extends NiceWebPage
|
||||
public static function ResetSession()
|
||||
{
|
||||
// Unset all of the session variables.
|
||||
unset($_SESSION['auth_user']);
|
||||
unset($_SESSION['login_state']);
|
||||
unset($_SESSION['can_logoff']);
|
||||
unset($_SESSION['archive_mode']);
|
||||
unset($_SESSION['impersonate_user']);
|
||||
Session::Unset('auth_user');
|
||||
Session::Unset('login_state');
|
||||
Session::Unset('can_logoff');
|
||||
Session::Unset('archive_mode');
|
||||
Session::Unset('impersonate_user');
|
||||
UserRights::_ResetSessionCache();
|
||||
// If it's desired to kill the session, also delete the session cookie.
|
||||
// Note: This will destroy the session, and not just the session data!
|
||||
@@ -442,11 +438,11 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
$bLoginDebug = MetaModel::GetConfig()->Get('login_debug');
|
||||
|
||||
if (!isset($_SESSION['login_state']) || ($_SESSION['login_state'] == self::LOGIN_STATE_ERROR))
|
||||
if (Session::Get('login_state') == self::LOGIN_STATE_ERROR)
|
||||
{
|
||||
$_SESSION['login_state'] = self::LOGIN_STATE_START;
|
||||
Session::Set('login_state', self::LOGIN_STATE_START);
|
||||
}
|
||||
$sLoginState = $_SESSION['login_state'];
|
||||
$sLoginState = Session::Get('login_state');
|
||||
|
||||
$sSessionLog = '';
|
||||
if ($bLoginDebug)
|
||||
@@ -500,7 +496,7 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
// Every plugin has nothing else to do in this state, go forward
|
||||
$sLoginState = self::AdvanceLoginFSMState($sLoginState);
|
||||
$_SESSION['login_state'] = $sLoginState;
|
||||
Session::Set('login_state', $sLoginState);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
@@ -526,7 +522,7 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
if ($bFilterWithMode)
|
||||
{
|
||||
$sCurrentLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : '';
|
||||
$sCurrentLoginMode = Session::Get('login_mode', '');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -665,8 +661,8 @@ class LoginWebPage extends NiceWebPage
|
||||
$oLog->DBInsertNoReload();
|
||||
}
|
||||
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
$_SESSION['login_mode'] = $sLoginMode;
|
||||
Session::Set('auth_user', $sAuthUser);
|
||||
Session::Set('login_mode', $sLoginMode);
|
||||
UserRights::_InitSessionCache();
|
||||
}
|
||||
|
||||
@@ -681,10 +677,10 @@ class LoginWebPage extends NiceWebPage
|
||||
*/
|
||||
public static function CheckLoggedUser(&$iErrorCode)
|
||||
{
|
||||
if (isset($_SESSION['auth_user']))
|
||||
if (Session::IsSet('auth_user'))
|
||||
{
|
||||
// Already authenticated
|
||||
$bRet = UserRights::Login($_SESSION['auth_user']); // Login & set the user's language
|
||||
$bRet = UserRights::Login(Session::Get('auth_user')); // Login & set the user's language
|
||||
if ($bRet)
|
||||
{
|
||||
$iErrorCode = self::EXIT_CODE_OK;
|
||||
@@ -712,11 +708,11 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
public static function SetLoginModeAndReload($sNewLoginMode)
|
||||
{
|
||||
if (isset($_SESSION['login_mode']) && ($_SESSION['login_mode'] == $sNewLoginMode))
|
||||
if (Session::Get('login_mode') == $sNewLoginMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
$_SESSION['login_mode'] = $sNewLoginMode;
|
||||
Session::Set('login_mode', $sNewLoginMode);
|
||||
self::HTTPReload();
|
||||
}
|
||||
|
||||
@@ -829,9 +825,9 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
CMDBObject::SetTrackOrigin('custom-extension');
|
||||
$sInfo = 'External User provisioning';
|
||||
if (isset($_SESSION['login_mode']))
|
||||
if (Session::IsSet('login_mode'))
|
||||
{
|
||||
$sInfo .= " ({$_SESSION['login_mode']})";
|
||||
$sInfo .= " (".Session::Get('login_mode').")";
|
||||
}
|
||||
CMDBObject::SetTrackInfo($sInfo);
|
||||
|
||||
@@ -883,9 +879,9 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
CMDBObject::SetTrackOrigin('custom-extension');
|
||||
$sInfo = 'External User provisioning';
|
||||
if (isset($_SESSION['login_mode']))
|
||||
if (Session::IsSet('login_mode'))
|
||||
{
|
||||
$sInfo .= " ({$_SESSION['login_mode']})";
|
||||
$sInfo .= " (".Session::Get('login_mode').")";
|
||||
}
|
||||
CMDBObject::SetTrackInfo($sInfo);
|
||||
|
||||
@@ -924,9 +920,9 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
// Now synchronize the profiles
|
||||
$sOrigin = 'External User provisioning';
|
||||
if (isset($_SESSION['login_mode']))
|
||||
if (Session::IsSet('login_mode'))
|
||||
{
|
||||
$sOrigin .= " ({$_SESSION['login_mode']})";
|
||||
$sOrigin .= " (".Session::Get('login_mode').")";
|
||||
}
|
||||
$aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin);
|
||||
if ($oUser->IsModified())
|
||||
@@ -1011,7 +1007,6 @@ class LoginWebPage extends NiceWebPage
|
||||
$sMessage = self::HandleOperations($operation); // May exit directly
|
||||
|
||||
$iRet = self::Login($iOnExit);
|
||||
|
||||
if ($iRet == self::EXIT_CODE_OK)
|
||||
{
|
||||
if ($bMustBeAdmin && !UserRights::IsAdministrator())
|
||||
@@ -1091,11 +1086,11 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
else if ($operation == 'change_pwd')
|
||||
{
|
||||
if (isset($_SESSION['auth_user']))
|
||||
if (Session::IsSet('auth_user'))
|
||||
{
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
$sIssue = $_SESSION['pwd_issue'] ?? null;
|
||||
unset($_SESSION['pwd_issue']);
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
$sIssue = Session::Get('pwd_issue');
|
||||
Session::Unset('pwd_issue');
|
||||
$bFailedLogin = ($sIssue != null); // Force the "failed login" flag to display the "issue" message
|
||||
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
@@ -1107,7 +1102,7 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
else if ($operation == 'check_pwd_policy')
|
||||
{
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
|
||||
$aPwdMap = array();
|
||||
@@ -1125,9 +1120,9 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
if ($operation == 'do_change_pwd')
|
||||
{
|
||||
if (isset($_SESSION['auth_user']))
|
||||
if (Session::IsSet('auth_user'))
|
||||
{
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
$sOldPwd = utils::ReadPostedParam('old_pwd', '', 'raw_data');
|
||||
$sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data');
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
@@ -58,6 +59,10 @@ class ApplicationMenu
|
||||
* @var array
|
||||
*/
|
||||
static $aMenusIndex = array();
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
static $aMenusById = [];
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -166,6 +171,7 @@ class ApplicationMenu
|
||||
$aBacktrace = debug_backtrace();
|
||||
$sFile = isset($aBacktrace[2]["file"]) ? $aBacktrace[2]["file"] : $aBacktrace[1]["file"];
|
||||
self::$aMenusIndex[$index] = array('node' => $oMenuNode, 'children' => array(), 'parent' => $sParentId, 'rank' => $fRank, 'source_file' => $sFile);
|
||||
self::$aMenusById[$oMenuNode->GetMenuId()] = $index;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -506,17 +512,11 @@ EOF
|
||||
*/
|
||||
public static function GetMenuIndexById($sTitle)
|
||||
{
|
||||
$index = -1;
|
||||
/** @var MenuNode[] $aMenu */
|
||||
foreach(self::$aMenusIndex as $aMenu)
|
||||
{
|
||||
if ($aMenu['node']->GetMenuId() == $sTitle)
|
||||
{
|
||||
$index = $aMenu['node']->GetIndex();
|
||||
break;
|
||||
}
|
||||
if (isset(self::$aMenusById[$sTitle])) {
|
||||
return self::$aMenusById[$sTitle];
|
||||
}
|
||||
return $index;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -715,9 +715,10 @@ abstract class MenuNode
|
||||
{
|
||||
// Count the entries up to 99
|
||||
$oSearch = DBSearch::FromOQL($sOQL);
|
||||
|
||||
$oSearch->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
DBSearchHelper::AddContextFilter($oSearch);
|
||||
|
||||
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$iCount = $oSet->CountWithLimit(99);
|
||||
if ($iCount > 99) {
|
||||
@@ -1127,7 +1128,7 @@ class OQLMenuNode extends MenuNode
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
|
||||
if ($bSearchPane) {
|
||||
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => true], $aExtraParams);
|
||||
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams);
|
||||
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oPage, 0);
|
||||
}
|
||||
@@ -1414,6 +1415,8 @@ class DashboardMenuNode extends MenuNode
|
||||
$oDashboard = $this->GetDashboard();
|
||||
if ($oDashboard != null)
|
||||
{
|
||||
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
||||
|
||||
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
||||
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
|
||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
@@ -27,6 +30,9 @@ require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
ExecutionKPI::EnableDuration(1);
|
||||
ExecutionKPI::EnableMemory(1);
|
||||
|
||||
// This storage is freed on error (case of allowed memory exhausted)
|
||||
$sReservedMemory = str_repeat('*', 1024 * 1024);
|
||||
register_shutdown_function(function()
|
||||
@@ -62,14 +68,16 @@ register_shutdown_function(function()
|
||||
}
|
||||
}
|
||||
});
|
||||
$oKPI = new ExecutionKPI();
|
||||
Session::Start();
|
||||
Session::WriteClose();
|
||||
$oKPI->ComputeAndReport("Session Start");
|
||||
|
||||
session_name('itop-'.md5(APPROOT));
|
||||
session_start();
|
||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||
$bAllowCache = true;
|
||||
if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE)) && isset($_SESSION['itop_env']) && ($_SESSION['itop_env'] !== $sSwitchEnv))
|
||||
if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE) &&( Session::Get('itop_env') !== $sSwitchEnv))
|
||||
{
|
||||
$_SESSION['itop_env'] = $sSwitchEnv;
|
||||
Session::Set('itop_env', $sSwitchEnv);
|
||||
$sEnv = $sSwitchEnv;
|
||||
$bAllowCache = false;
|
||||
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
|
||||
@@ -85,14 +93,14 @@ if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FI
|
||||
}
|
||||
// TODO: reset the credentials as well ??
|
||||
}
|
||||
else if (isset($_SESSION['itop_env']))
|
||||
else if (Session::IsSet('itop_env'))
|
||||
{
|
||||
$sEnv = $_SESSION['itop_env'];
|
||||
$sEnv = Session::Get('itop_env');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sEnv = ITOP_DEFAULT_ENV;
|
||||
$_SESSION['itop_env'] = ITOP_DEFAULT_ENV;
|
||||
Session::Set('itop_env', ITOP_DEFAULT_ENV);
|
||||
}
|
||||
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||
|
||||
@@ -906,7 +906,8 @@ CSS;
|
||||
|
||||
foreach($aImportsPaths as $sPath)
|
||||
{
|
||||
$sFilePath = $sPath.'/'.$sFileURI;
|
||||
$sAlterableFileURI = $sFileURI;
|
||||
$sFilePath = $sPath.'/'.$sAlterableFileURI;
|
||||
$sImportedFile = realpath($sFilePath);
|
||||
if ($sImportedFile === false){
|
||||
// Handle shortcut syntax : @import "typo" ;
|
||||
@@ -914,7 +915,7 @@ CSS;
|
||||
$sFilePath2 = "$sFilePath.scss";
|
||||
$sImportedFile = realpath($sFilePath2);
|
||||
if ($sImportedFile){
|
||||
self::FindStylesheetFile("$sFileURI.scss", [ $sPath ], $oFindStylesheetObject, $bImports);
|
||||
self::FindStylesheetFile("$sAlterableFileURI.scss", [ $sPath ], $oFindStylesheetObject, $bImports);
|
||||
$sImportedFile = false;
|
||||
}
|
||||
}
|
||||
@@ -924,7 +925,7 @@ CSS;
|
||||
// file matched: _typo.scss
|
||||
$sShortCut = substr($sFilePath, strrpos($sFilePath, '/') + 1);
|
||||
$sFilePath = static::ReplaceLastOccurrence($sShortCut, "_$sShortCut.scss", $sFilePath);
|
||||
$sFileURI = static::ReplaceLastOccurrence($sShortCut, "_$sShortCut.scss", $sFileURI);
|
||||
$sAlterableFileURI = static::ReplaceLastOccurrence($sShortCut, "_$sShortCut.scss", $sAlterableFileURI);
|
||||
$sImportedFile = realpath($sFilePath);
|
||||
}
|
||||
|
||||
@@ -932,14 +933,14 @@ CSS;
|
||||
&& (!$oFindStylesheetObject->AlreadyFetched($sImportedFile)))
|
||||
{
|
||||
if ($bImports){
|
||||
$oFindStylesheetObject->AddImport($sFileURI, $sImportedFile);
|
||||
$oFindStylesheetObject->AddImport($sAlterableFileURI, $sImportedFile);
|
||||
}else{
|
||||
$oFindStylesheetObject->AddStylesheet($sFileURI, $sImportedFile);
|
||||
$oFindStylesheetObject->AddStylesheet($sAlterableFileURI, $sImportedFile);
|
||||
}
|
||||
$oFindStylesheetObject->UpdateLastModified($sImportedFile);
|
||||
|
||||
//Regexp matching on all included scss files : @import 'XXX.scss';
|
||||
$sDirUri = dirname($sFileURI);
|
||||
$sDirUri = dirname($sAlterableFileURI);
|
||||
preg_match_all('/@import \s*[\"\']([^\"\']*)\s*[\"\']\s*;/', file_get_contents($sImportedFile), $aMatches);
|
||||
if ( (is_array($aMatches)) && (count($aMatches)!==0) ){
|
||||
foreach ($aMatches[1] as $sImportedFile){
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* This class records the pending "transactions" corresponding to forms that have not been
|
||||
@@ -100,7 +101,8 @@ class privUITransaction
|
||||
|
||||
/**
|
||||
* The original (and by default) mechanism for storing transaction information
|
||||
* as an array in the $_SESSION variable
|
||||
* as an array in the _SESSION variable
|
||||
* @see \Combodo\iTop\Application\Helper\Session
|
||||
*
|
||||
*/
|
||||
class privUITransactionSession
|
||||
@@ -112,15 +114,15 @@ class privUITransactionSession
|
||||
*/
|
||||
public static function GetNewTransactionId()
|
||||
{
|
||||
if (!isset($_SESSION['transactions']))
|
||||
if (!Session::IsSet('transactions'))
|
||||
{
|
||||
$_SESSION['transactions'] = array();
|
||||
Session::Set('transactions', []);
|
||||
}
|
||||
// Strictly speaking, the two lines below should be grouped together
|
||||
// by a critical section
|
||||
// sem_acquire($rSemIdentified);
|
||||
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
|
||||
$_SESSION['transactions'][$id] = true;
|
||||
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime());
|
||||
Session::Set(['transactions', $id], true);
|
||||
// sem_release($rSemIdentified);
|
||||
|
||||
return (string)$id;
|
||||
@@ -137,17 +139,17 @@ class privUITransactionSession
|
||||
public static function IsTransactionValid($id, $bRemoveTransaction = true)
|
||||
{
|
||||
$bResult = false;
|
||||
if (isset($_SESSION['transactions']))
|
||||
if (Session::IsSet('transactions'))
|
||||
{
|
||||
// Strictly speaking, the eight lines below should be grouped together
|
||||
// inside the same critical section as above
|
||||
// sem_acquire($rSemIdentified);
|
||||
if (isset($_SESSION['transactions'][$id]))
|
||||
if (Session::IsSet(['transactions', $id]))
|
||||
{
|
||||
$bResult = true;
|
||||
if ($bRemoveTransaction)
|
||||
{
|
||||
unset($_SESSION['transactions'][$id]);
|
||||
Session::Unset(['transactions', $id]);
|
||||
}
|
||||
}
|
||||
// sem_release($rSemIdentified);
|
||||
@@ -162,14 +164,14 @@ class privUITransactionSession
|
||||
*/
|
||||
public static function RemoveTransaction($id)
|
||||
{
|
||||
if (isset($_SESSION['transactions']))
|
||||
if (Session::IsSet('transactions'))
|
||||
{
|
||||
// Strictly speaking, the three lines below should be grouped together
|
||||
// inside the same critical section as above
|
||||
// sem_acquire($rSemIdentified);
|
||||
if (isset($_SESSION['transactions'][$id]))
|
||||
if (Session::IsSet(['transactions', $id]))
|
||||
{
|
||||
unset($_SESSION['transactions'][$id]);
|
||||
Session::Unset(['transactions', $id]);
|
||||
}
|
||||
// sem_release($rSemIdentified);
|
||||
}
|
||||
|
||||
@@ -80,30 +80,14 @@ class TwigExtension
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?itopversion=".ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&itopversion=".ITOP_VERSION;
|
||||
}
|
||||
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'itopversion', ITOP_VERSION);
|
||||
return $sUrl;
|
||||
}));
|
||||
|
||||
// Filter to add a module's version to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
|
||||
}
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'moduleversion', $sModuleVersion);
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
@@ -137,4 +121,5 @@ class TwigExtension
|
||||
return utils::GetAbsoluteUrlModulePage($sModuleName, $sPage);
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||
|
||||
/**
|
||||
@@ -200,42 +204,35 @@ class UIExtKeyWidget
|
||||
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
|
||||
//$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
||||
$aOptions = [];
|
||||
$sDisplayValue = "";
|
||||
|
||||
$aOption = [];
|
||||
$aOption['value'] = "";
|
||||
$aOption['label'] = Dict::S('UI:SelectOne');
|
||||
array_push($aOptions,$aOption);
|
||||
array_push($aOptions, $aOption);
|
||||
|
||||
$oAllowedValues->Rewind();
|
||||
$bAddingValue=false;
|
||||
$sClassAllowed = $oAllowedValues->GetClass();
|
||||
$bAddingValue = false;
|
||||
|
||||
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($oAllowedValues->GetClass());
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($oAllowedValues->GetClass(), FriendlyNameType::COMPLEMENTARY);
|
||||
$sFormatAdditionalField = $aComplementAttributeSpec[0];
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
|
||||
if (count($aAdditionalField)>0)
|
||||
{
|
||||
$bAddingValue=true;
|
||||
if (count($aAdditionalField) > 0) {
|
||||
$bAddingValue = true;
|
||||
}
|
||||
while($oObj = $oAllowedValues->Fetch())
|
||||
{
|
||||
$aOption=[];
|
||||
$sObjectImageAttCode = MetaModel::GetImageAttributeCode($sClassAllowed);
|
||||
$bInitValue = false;
|
||||
while ($oObj = $oAllowedValues->Fetch()) {
|
||||
$aOption = [];
|
||||
$aOption['value'] = $oObj->GetKey();
|
||||
$aOption['label'] = $oObj->GetName();//.'<span class=\"object-ref-icon fas fa-eye-slash object-obsolete fa-1x fa-fw\"></span>';
|
||||
|
||||
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
|
||||
{
|
||||
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true')) {
|
||||
// When there is only once choice, select it by default
|
||||
$sDisplayValue=$oObj->GetName();
|
||||
if($value != $oObj->GetKey())
|
||||
{
|
||||
$value=$oObj->GetKey();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((is_array($value) && in_array($oObj->GetKey(), $value)) || ($value == $oObj->GetKey())) {
|
||||
$sDisplayValue = $oObj->GetName();
|
||||
if ($value != $oObj->GetKey()) {
|
||||
$value = $oObj->GetKey();
|
||||
$bInitValue = true;
|
||||
}
|
||||
}
|
||||
if ($oObj->IsObsolete()) {
|
||||
@@ -248,6 +245,17 @@ class UIExtKeyWidget
|
||||
}
|
||||
$aOption['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
||||
}
|
||||
if (!empty($sObjectImageAttCode)) {
|
||||
// Try to retrieve image for contact
|
||||
/** @var \ormDocument $oImage */
|
||||
$oImage = $oObj->Get($sObjectImageAttCode);
|
||||
if (!$oImage->IsEmpty()) {
|
||||
$aOption['picture_url'] = $oImage->GetDisplayURL($sClassAllowed, $oObj->GetKey(), $sObjectImageAttCode);
|
||||
$aOption['initials'] = '';
|
||||
} else {
|
||||
$aOption['initials'] = utils::ToAcronym($oObj->Get('friendlyname'));
|
||||
}
|
||||
}
|
||||
array_push($aOptions, $aOption);
|
||||
}
|
||||
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_DECORATED;
|
||||
@@ -259,10 +267,12 @@ class UIExtKeyWidget
|
||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||
oACWidget_{$this->iId}.AddSelectize('$sJsonOptions','$value');
|
||||
$('#$this->iId').on('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||
$('#$this->iId').on('change', function() { $(this).trigger('extkeychange') } );
|
||||
|
||||
$('#$this->iId').on('change', function() { $(this).trigger('extkeychange'); } );
|
||||
EOF
|
||||
);
|
||||
if ($bInitValue) {
|
||||
$oPage->add_ready_script("$('#$this->iId').one('validate', function() { $(this).trigger('change'); } );");
|
||||
}
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||
}
|
||||
else
|
||||
@@ -599,7 +609,7 @@ EOF
|
||||
|
||||
// the input for the auto-complete
|
||||
$sHTMLValue .= "<input class=\"field_autocomplete ibo-input-select\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\"><span class=\"field_input_btn\"><div class=\"mini_button ibo-input-select--action-button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span></div>";
|
||||
|
||||
// another hidden input to store & pass the object's Id
|
||||
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||
@@ -811,21 +821,24 @@ JS
|
||||
{
|
||||
case static::ENUM_OUTPUT_FORMAT_JSON:
|
||||
|
||||
$aJsonMap = array();
|
||||
foreach ($aValues as $sKey => $aValue)
|
||||
{
|
||||
if ($aValue['additional_field'] != '')
|
||||
{
|
||||
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag'], 'additional_field' => $aValue['additional_field']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag']);
|
||||
}
|
||||
}
|
||||
$aJsonMap = array();
|
||||
foreach ($aValues as $sKey => $aValue) {
|
||||
$aElt = ['value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag']];
|
||||
if ($aValue['additional_field'] != '') {
|
||||
$aElt['additional_field'] = $aValue['additional_field'];
|
||||
}
|
||||
|
||||
$oP->SetContentType('application/json');
|
||||
$oP->add(json_encode($aJsonMap));
|
||||
if (array_key_exists('initials', $aValue)) {
|
||||
$aElt['initials'] = $aValue['initials'];
|
||||
if (array_key_exists('picture_url', $aValue)) {
|
||||
$aElt['picture_url'] = $aValue['picture_url'];
|
||||
}
|
||||
}
|
||||
$aJsonMap[] = $aElt;
|
||||
}
|
||||
|
||||
$oP->SetContentType('application/json');
|
||||
$oP->add(json_encode($aJsonMap));
|
||||
break;
|
||||
|
||||
case static::ENUM_OUTPUT_FORMAT_CSV:
|
||||
@@ -892,26 +905,17 @@ JS
|
||||
}
|
||||
}
|
||||
|
||||
$sDialogTitle = '';
|
||||
$oPage->add('<div id="ac_create_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div id="dcr_'.$this->iId.'">');
|
||||
$oPage->add('<form>');
|
||||
|
||||
$sClassLabel = MetaModel::GetName($this->sTargetClass);
|
||||
$oPage->add('<p>'.Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel));
|
||||
$oPage->add('<nobr><select name="class">');
|
||||
asort($aPossibleClasses);
|
||||
foreach($aPossibleClasses as $sClassName => $sClassLabel)
|
||||
{
|
||||
$oPage->add("<option value=\"$sClassName\">$sClassLabel</option>");
|
||||
}
|
||||
$oPage->add('</select>');
|
||||
$oPage->add(' <button type="submit" class="action" style="margin-top:15px;"><span>' . Dict::S('UI:Button:Ok') . '</span></button></nobr></p>');
|
||||
$sDialogTitle = Dict::Format('UI:CreationTitle_Class', $sClassLabel);;
|
||||
$oBlock = UIContentBlockUIBlockFactory::MakeStandard('ac_create_'.$this->iId,['ibo-is-visible']);
|
||||
$oPage->AddSubBlock($oBlock);
|
||||
$oClassForm = FormUIBlockFactory::MakeStandard();
|
||||
$oBlock->AddSubBlock($oClassForm);
|
||||
$oClassForm->AddSubBlock(cmdbAbstractObject::DisplayBlockSelectClassToCreate( $sClassLabel, $this->sTargetClass, $aPossibleClasses));
|
||||
|
||||
$oPage->add('</form>');
|
||||
$oPage->add('</div></div></div>');
|
||||
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
|
||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
|
||||
$oPage->add_ready_script("$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').removeAttr('onsubmit');");
|
||||
$oPage->add_ready_script("$('#ac_create_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
|
||||
/**
|
||||
* Class UIHTMLEditorWidget
|
||||
@@ -83,6 +84,7 @@ class UIHTMLEditorWidget
|
||||
}
|
||||
$sConfigJS = json_encode($aConfig);
|
||||
|
||||
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
|
||||
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
|
||||
|
||||
// Please read...
|
||||
|
||||
@@ -49,6 +49,8 @@ class UIPasswordWidget
|
||||
*/
|
||||
public function Display(WebPage $oPage, $aArgs = array())
|
||||
{
|
||||
$oPage->add_dict_entry('UI:Component:Input:Password:DoesNotMatch');
|
||||
|
||||
$sCode = $this->sAttCode.$this->sNameSuffix;
|
||||
$iWidgetIndex = self::$iWidgetIndex;
|
||||
|
||||
@@ -57,11 +59,12 @@ class UIPasswordWidget
|
||||
$sConfirmPasswordValue = $aPasswordValues ? $aPasswordValues['confirm'] : '*****';
|
||||
$sChangedValue = (($sPasswordValue != '*****') || ($sConfirmPasswordValue != '*****')) ? 1 : 0;
|
||||
$sHtmlValue = '';
|
||||
$sHtmlValue .= '<div class="field_input_zone field_input_onewaypassword">';
|
||||
$sHtmlValue .= '<input type="password" maxlength="255" name="attr_'.$sCode.'[value]" id="'.$this->iId.'" value="'.htmlentities($sPasswordValue, ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$sHtmlValue .= '<input type="password" maxlength="255" id="'.$this->iId.'_confirm" value="'.htmlentities($sConfirmPasswordValue, ENT_QUOTES, 'UTF-8').'" name="attr_'.$sCode.'[confirm]"/>';
|
||||
$sHtmlValue .= '<span>'.Dict::S('UI:PasswordConfirm').'</span>';
|
||||
$sHtmlValue .= '<input id="'.$this->iId.'_reset" type="button" value="'.Dict::S('UI:Button:ResetPassword').'" onClick="ResetPwd(\''.$this->iId.'\');">';
|
||||
$sHtmlValue .= '<div class="field_input_zone field_input_onewaypassword ibo-input-wrapper">';
|
||||
$sHtmlValue .= '<input class="ibo-input" type="password" maxlength="255" name="attr_'.$sCode.'[value]" id="'.$this->iId.'" value="'.htmlentities($sPasswordValue, ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$sHtmlValue .= '<div class="ibo-input-wrapper ibo-input-wrapper--with-buttons"><input class="ibo-input" type="password" maxlength="255" id="'.$this->iId.'_confirm" value="'.htmlentities($sConfirmPasswordValue, ENT_QUOTES, 'UTF-8').'" name="attr_'.$sCode.'[confirm]"/>';
|
||||
$sHtmlValue .= '<div class="ibo-input-select--action-buttons"><div class="ibo-input-select--action-button ibo-input-select--action-button--create" data-tooltip-content="'.Dict::S('UI:PasswordConfirm').'"><i class="fas fa-question-circle"></i></div></div></div>';
|
||||
$sHtmlValue .= '<button id="'.$this->iId.'_reset" class="ibo-button ibo-is-regular ibo-is-neutral" onClick="ResetPwd(\''.$this->iId.'\');">';
|
||||
$sHtmlValue .= '<span class="ibo-button--icon fas fa-undo"></span><span class="ibo-button--label">'.Dict::S('UI:Button:ResetPassword').'</span></button>';
|
||||
$sHtmlValue .= '<input type="hidden" id="'.$this->iId.'_changed" name="attr_'.$sCode.'[changed]" value="'.$sChangedValue.'"/>';
|
||||
$sHtmlValue .= '</div>';
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
@@ -239,9 +240,9 @@ class utils
|
||||
|
||||
public static function InitArchiveMode()
|
||||
{
|
||||
if (isset($_SESSION['archive_mode']))
|
||||
if (Session::IsSet('archive_mode'))
|
||||
{
|
||||
$iDefault = $_SESSION['archive_mode'];
|
||||
$iDefault = Session::Get('archive_mode');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -249,9 +250,9 @@ class utils
|
||||
}
|
||||
// Read and record the value for switching the archive mode
|
||||
$iCurrent = self::ReadParam('with-archive', $iDefault);
|
||||
if (isset($_SESSION))
|
||||
if (Session::IsInitialized())
|
||||
{
|
||||
$_SESSION['archive_mode'] = $iCurrent;
|
||||
Session::Set('archive_mode', $iCurrent);
|
||||
}
|
||||
// Read and use the value for the current page (web services)
|
||||
$iCurrent = self::ReadParam('with_archive', $iCurrent, true);
|
||||
@@ -860,6 +861,8 @@ class utils
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $bForceGetFromDisk if true then will always read from disk without using instances in memory
|
||||
*
|
||||
* @return \Config Get object in the following order :
|
||||
* <ol>
|
||||
* <li>from {@link MetaModel::GetConfig} if loaded
|
||||
@@ -872,25 +875,26 @@ class utils
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @since 2.7.0 N°2478 this method will now always call {@link MetaModel::GetConfig} first, and cache in this class is only set when loading from disk
|
||||
* @since 3.0.0 N°4158 new $bReadFromDisk parameter
|
||||
*/
|
||||
public static function GetConfig()
|
||||
public static function GetConfig($bForceGetFromDisk = false)
|
||||
{
|
||||
$oMetaModelConfig = MetaModel::GetConfig();
|
||||
if ($oMetaModelConfig !== null)
|
||||
{
|
||||
return $oMetaModelConfig;
|
||||
}
|
||||
if (!$bForceGetFromDisk) {
|
||||
$oMetaModelConfig = MetaModel::GetConfig();
|
||||
if ($oMetaModelConfig !== null) {
|
||||
return $oMetaModelConfig;
|
||||
}
|
||||
|
||||
if (self::$oConfig !== null)
|
||||
{
|
||||
return self::$oConfig;
|
||||
if (self::$oConfig !== null) {
|
||||
return self::$oConfig;
|
||||
}
|
||||
}
|
||||
|
||||
$sCurrentEnvConfigPath = self::GetConfigFilePath();
|
||||
if (file_exists($sCurrentEnvConfigPath))
|
||||
{
|
||||
if (file_exists($sCurrentEnvConfigPath)) {
|
||||
$oCurrentEnvDiskConfig = new Config($sCurrentEnvConfigPath);
|
||||
self::SetConfig($oCurrentEnvDiskConfig);
|
||||
|
||||
return self::$oConfig;
|
||||
}
|
||||
|
||||
@@ -1210,7 +1214,7 @@ class utils
|
||||
*/
|
||||
static function CanLogOff()
|
||||
{
|
||||
return (isset($_SESSION['can_logoff']) ? $_SESSION['can_logoff'] : false);
|
||||
return Session::Get('can_logoff', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1219,7 +1223,7 @@ class utils
|
||||
*/
|
||||
public static function GetSessionLog()
|
||||
{
|
||||
return print_r($_SESSION, true);
|
||||
return Session::GetLog();
|
||||
}
|
||||
|
||||
static function DebugBacktrace($iLimit = 5)
|
||||
@@ -1312,14 +1316,7 @@ class utils
|
||||
*/
|
||||
public static function GetCurrentEnvironment()
|
||||
{
|
||||
if (isset($_SESSION['itop_env']))
|
||||
{
|
||||
return $_SESSION['itop_env'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return ITOP_DEFAULT_ENV;
|
||||
}
|
||||
return Session::Get('itop_env', ITOP_DEFAULT_ENV);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1922,7 +1919,7 @@ class utils
|
||||
public static function CompileCSSFromSASS($sSassContent, $aImportPaths = array(), $aVariables = array())
|
||||
{
|
||||
$oSass = new Compiler();
|
||||
$oSass->setFormatter('ScssPhp\\ScssPhp\\Formatter\\Expanded');
|
||||
$oSass->setFormatter('ScssPhp\\ScssPhp\\Formatter\\Compressed');
|
||||
// Setting our variables
|
||||
$oSass->setVariables($aVariables);
|
||||
// Setting our imports paths
|
||||
@@ -2656,7 +2653,7 @@ class utils
|
||||
$sMentionItemUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.$sMentionClass.'&id={id}';
|
||||
|
||||
$sMentionItemPictureTemplate = (empty(MetaModel::GetImageAttributeCode($sMentionClass))) ? '' : <<<HTML
|
||||
<span class="ibo-vendors-ckeditor--autocomplete-item-image" style="background-image: url('{picture_url}');">{initials}</span>
|
||||
<span class="ibo-vendors-ckeditor--autocomplete-item-image" style="{picture_style}">{initials}</span>
|
||||
HTML;
|
||||
$sMentionItemTemplate = <<<HTML
|
||||
<li class="ibo-vendors-ckeditor--autocomplete-item" data-id="{id}">{$sMentionItemPictureTemplate}<span class="ibo-vendors-ckeditor--autocomplete-item-title">{friendlyname}</span></li>
|
||||
@@ -2823,20 +2820,19 @@ HTML;
|
||||
//----------------------------------------------
|
||||
|
||||
/**
|
||||
* Check if iTop is in a development environment (VCS vs build number)
|
||||
* Check if iTop is in a development environment
|
||||
*
|
||||
* @return bool
|
||||
* @return bool true if development environment
|
||||
*
|
||||
* @since 2.6.0 method creation
|
||||
* @since 3.0.0 add the `developer_mode.enabled` config parameter
|
||||
*
|
||||
* @use `developer_mode.enabled` config parameter
|
||||
* @use ITOP_REVISION
|
||||
* @uses GetDeveloperModeParam
|
||||
* @uses ITOP_REVISION constant (check 'svn' value)
|
||||
*/
|
||||
public static function IsDevelopmentEnvironment()
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$bIsDevEnvInConfig = $oConfig->Get('developer_mode.enabled');
|
||||
$bIsDevEnvInConfig = static::GetDeveloperModeParam();
|
||||
if ($bIsDevEnvInConfig === true) {
|
||||
return true;
|
||||
}
|
||||
@@ -2854,7 +2850,36 @@ HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool : indicate whether we run under a windows environnement or not
|
||||
* In the setup there are times when the MetaModel config attribute is loaded but partially (only setup parameters are set, others have the default value)
|
||||
* So we need to load from disk then !
|
||||
*
|
||||
* But in other scenario we want to read from memory : for example when changing the option in a PHPUnit setUp method
|
||||
*
|
||||
* This method will first try to get the `developer_mode.enabled` config parameter the standard way (call to GetConfig without modification).
|
||||
* If we are getting null (not defined parameter), then we will load config from disk only (GetConfig(true))
|
||||
*
|
||||
* @return bool|null
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @uses developer_mode.enabled config parameter
|
||||
*/
|
||||
private static function GetDeveloperModeParam(): ?bool
|
||||
{
|
||||
$oConfig = static::GetConfig(false);
|
||||
$bIsDevEnvInConfig = $oConfig->Get('developer_mode.enabled');
|
||||
|
||||
if (!is_null($bIsDevEnvInConfig)) {
|
||||
return $bIsDevEnvInConfig;
|
||||
}
|
||||
|
||||
$oConfigFromDisk = static::GetConfig(true);
|
||||
|
||||
return $oConfigFromDisk->Get('developer_mode.enabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool true if we are running under a Windows environment
|
||||
* @since 2.7.4 : N°3412
|
||||
*/
|
||||
public static function IsWindowsEnvironment()
|
||||
@@ -3020,4 +3045,26 @@ HTML;
|
||||
|
||||
return $aMentionedObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sUrl
|
||||
* @param string $sParamName
|
||||
* @param string $sParamValue
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function AddParameterToUrl(string $sUrl, string $sParamName, string $sParamValue): string
|
||||
{
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl.'?'.urlencode($sParamName).'='.urlencode($sParamValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl.'&'.urlencode($sParamName).'='.urlencode($sParamValue);
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,7 @@ define('ITOP_DEFAULT_ENV', 'production');
|
||||
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
|
||||
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
|
||||
|
||||
if (function_exists('microtime')) {
|
||||
$fItopStarted = microtime(true);
|
||||
} else {
|
||||
$fItopStarted = 1000 * time();
|
||||
}
|
||||
$fItopStarted = microtime(true);
|
||||
|
||||
if (!isset($GLOBALS['bBypassAutoload']) || $GLOBALS['bBypassAutoload'] == false) {
|
||||
require_once APPROOT.'/lib/autoload.php';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"type": "project",
|
||||
"license": "AGPLv3",
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"php": ">=7.1.3 <8.0.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
@@ -13,7 +13,7 @@
|
||||
"combodo/tcpdf": "6.3.5",
|
||||
"nikic/php-parser": "^4.12.0",
|
||||
"pear/archive_tar": "1.4.13",
|
||||
"pelago/emogrifier": "2.1.0",
|
||||
"pelago/emogrifier": "3.1.0",
|
||||
"scssphp/scssphp": "1.0.6",
|
||||
"swiftmailer/swiftmailer": "5.4.12",
|
||||
"symfony/console": "3.4.*",
|
||||
@@ -37,14 +37,15 @@
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2.0"
|
||||
"php": "7.1.3"
|
||||
},
|
||||
"vendor-dir": "lib",
|
||||
"preferred-install": {
|
||||
"*": "dist"
|
||||
},
|
||||
"sort-packages": true,
|
||||
"classmap-authoritative": true
|
||||
"classmap-authoritative": true,
|
||||
"platform-check": true
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
|
||||
56
composer.lock
generated
56
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": "75f17b71005971207815906ec7e9cf67",
|
||||
"content-hash": "fb56686981ee4945791fe5b93735b022",
|
||||
"packages": [
|
||||
{
|
||||
"name": "combodo/tcpdf",
|
||||
@@ -411,34 +411,34 @@
|
||||
},
|
||||
{
|
||||
"name": "pelago/emogrifier",
|
||||
"version": "v2.1.0",
|
||||
"version": "v3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/emogrifier.git",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f"
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
|
||||
"symfony/css-selector": "^3.4.0 || ^4.0.0"
|
||||
"php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4",
|
||||
"symfony/css-selector": "^2.8 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.2.0",
|
||||
"phpmd/phpmd": "^2.6.0",
|
||||
"phpunit/phpunit": "^4.8.0",
|
||||
"squizlabs/php_codesniffer": "^3.3.2"
|
||||
"friendsofphp/php-cs-fixer": "^2.15.3",
|
||||
"phpmd/phpmd": "^2.7.0",
|
||||
"phpunit/phpunit": "^5.7.27",
|
||||
"squizlabs/php_codesniffer": "^3.5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -451,16 +451,6 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
@@ -469,9 +459,19 @@
|
||||
"name": "Zoli Szabó",
|
||||
"email": "zoli.szabo+github@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake@qzdesign.co.uk"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
}
|
||||
],
|
||||
"description": "Converts CSS styles into inline style attributes in your HTML code",
|
||||
@@ -481,7 +481,11 @@
|
||||
"email",
|
||||
"pre-processing"
|
||||
],
|
||||
"time": "2018-12-08T13:55:46+00:00"
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/emogrifier/issues",
|
||||
"source": "https://github.com/MyIntervals/emogrifier"
|
||||
},
|
||||
"time": "2019-12-26T19:37:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
@@ -2609,7 +2613,7 @@
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3",
|
||||
"php": ">=7.1.3 <8.0.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
@@ -2620,7 +2624,7 @@
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.2.0"
|
||||
"php": "7.1.3"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
||||
67
core/DbConnectionWrapper.php
Normal file
67
core/DbConnectionWrapper.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Core;
|
||||
|
||||
use mysqli;
|
||||
|
||||
/**
|
||||
* mysqli object is really hard to mock as it contains lots of attributes & methods ! Thought we need to mock it to test transactions !
|
||||
*
|
||||
* To solve this, a new attribute exists and is only used in specific use cases, so there are just few things to mock.
|
||||
*
|
||||
* This object adds more readability than previous model with 2 attributes in {@see CMDBSource}.
|
||||
*
|
||||
* @used-by \CMDBSource
|
||||
*
|
||||
* @since 3.0.0 N°4325 Object creation
|
||||
* This wrapper handles the 2 {@mysqli myqsli} attributes that were previously in {@see CMDBSource}
|
||||
* To allow testing we added a second mysqli object (N°3513 in 2.7.5) and code became a bit confusing :/
|
||||
* With this wrapper everything is in the same place, and we can express the intention more clearly !
|
||||
*/
|
||||
class DbConnectionWrapper
|
||||
{
|
||||
/** @var mysqli */
|
||||
protected static $oDbCnxStandard;
|
||||
|
||||
/**
|
||||
* Can contain a genuine mysqli object, or a mock that would emulate {@see mysqli::query()}
|
||||
*
|
||||
* @var mysqli
|
||||
* @used-by \Combodo\iTop\Test\UnitTest\Core\TransactionsTest
|
||||
*/
|
||||
protected static $oDbCnxMockableForQuery;
|
||||
|
||||
/**
|
||||
* @param bool $bIsForQuery set to true if using {@see mysqli::query()}
|
||||
*
|
||||
* @return \mysqli|null
|
||||
*/
|
||||
public static function GetDbConnection(bool $bIsForQuery = false): ?mysqli
|
||||
{
|
||||
if ($bIsForQuery) {
|
||||
return static::$oDbCnxMockableForQuery;
|
||||
}
|
||||
|
||||
return static::$oDbCnxStandard;
|
||||
}
|
||||
|
||||
public static function SetDbConnection(mysqli $oMysqli): void
|
||||
{
|
||||
static::$oDbCnxStandard = $oMysqli;
|
||||
static::SetDbConnectionMockForQuery($oMysqli);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to register a mock that will handle {@see mysqli::query()}
|
||||
*
|
||||
* @param \mysqli $oMysqli
|
||||
*/
|
||||
public static function SetDbConnectionMockForQuery(mysqli $oMysqli): void
|
||||
{
|
||||
static::$oDbCnxMockableForQuery = $oMysqli;
|
||||
}
|
||||
}
|
||||
@@ -66,9 +66,8 @@ class MyHelpers
|
||||
// getmicrotime()
|
||||
// format sss.mmmuuupppnnn
|
||||
public static function getmicrotime()
|
||||
{
|
||||
list($usec, $sec) = explode(" ",microtime());
|
||||
return ((float)$usec + (float)$sec);
|
||||
{
|
||||
return microtime(true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -4123,7 +4123,7 @@ class AttributeText extends AttributeString
|
||||
{
|
||||
// Propose a std link to the object
|
||||
$sClassLabel = MetaModel::GetName($sClass);
|
||||
$sToolTipForHtml = utils::EscapeHtml(Dict::S('Core:UnknownObjectTip'));
|
||||
$sToolTipForHtml = utils::EscapeHtml(Dict::Format('Core:UnknownObjectLabel', $sClass, $sName));
|
||||
$sReplacement = "<span class=\"wiki_broken_link ibo-is-broken-hyperlink\" data-tooltip-content=\"$sToolTipForHtml\">$sClassLabel:$sName" . (!empty($sLabel) ? " ($sLabel)" : "") . "</span>";
|
||||
$sText = str_replace($aMatches[0], $sReplacement, $sText);
|
||||
// Later: propose a link to create a new object
|
||||
@@ -10283,7 +10283,6 @@ abstract class AttributeSet extends AttributeDBFieldVoid
|
||||
} else {
|
||||
$sTooltipContent = <<<HTML
|
||||
<h4>$sLabel</h4>
|
||||
<br>
|
||||
<div>$sDescription</div>
|
||||
HTML;
|
||||
$sTooltipHtmlEnabled = 'true';
|
||||
@@ -11574,7 +11573,6 @@ class AttributeTagSet extends AttributeSet
|
||||
} else {
|
||||
$sTooltipContent = <<<HTML
|
||||
<h4>$sTagLabel</h4>
|
||||
<br>
|
||||
<div>$sTagDescription</div>
|
||||
HTML;
|
||||
$sTooltipHtmlEnabled = 'true';
|
||||
@@ -12545,10 +12543,12 @@ class AttributeCustomFields extends AttributeDefinition
|
||||
*/
|
||||
public function ReadValueFromPostedForm($oHostObject, $sFormPrefix)
|
||||
{
|
||||
$aRawData = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->GetCode()}", '{}', 'raw_data'),
|
||||
true);
|
||||
|
||||
return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRawData);
|
||||
$aRawData = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->GetCode()}", '{}', 'raw_data'), true);
|
||||
if ($aRawData != null) {
|
||||
return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRawData);
|
||||
} else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObject)
|
||||
|
||||
@@ -24,13 +24,15 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\DbConnectionWrapper;
|
||||
|
||||
require_once('MyHelpers.class.inc.php');
|
||||
require_once(APPROOT.'core/kpi.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
* CMDBSource
|
||||
* database access wrapper
|
||||
* database access wrapper
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
@@ -66,11 +68,6 @@ class CMDBSource
|
||||
*/
|
||||
protected static $m_sDBTlsCA;
|
||||
|
||||
/** @var mysqli $m_oMysqli */
|
||||
protected static $m_oMysqli;
|
||||
/** @var mysqli or mock used for test purpose, only used in query() method */
|
||||
protected static $oMySQLiForQuery;
|
||||
|
||||
/**
|
||||
* @var int number of level for nested transactions : 0 if no transaction was ever opened, +1 for each 'START TRANSACTION' sent
|
||||
* @since 2.7.0 N°679
|
||||
@@ -135,8 +132,8 @@ class CMDBSource
|
||||
self::$m_bDBTlsEnabled = empty($bTlsEnabled) ? false : $bTlsEnabled;
|
||||
self::$m_sDBTlsCA = empty($sTlsCA) ? null : $sTlsCA;
|
||||
|
||||
self::$m_oMysqli = self::GetMysqliInstance($sServer, $sUser, $sPwd, $sSource, $bTlsEnabled, $sTlsCA, true);
|
||||
self::SetMySQLiForQuery(self::$m_oMysqli);
|
||||
$oMysqli = self::GetMysqliInstance($sServer, $sUser, $sPwd, $sSource, $bTlsEnabled, $sTlsCA, true);
|
||||
DbConnectionWrapper::SetDbConnection($oMysqli);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,7 +249,7 @@ class CMDBSource
|
||||
* parameters were used.<br>
|
||||
* This method can be called to ensure that the DB connection really uses TLS.
|
||||
*
|
||||
* <p>We're using this object connection : {@link self::$m_oMysqli}
|
||||
* <p>We're using this object connection : {@see self::$m_oMysqli}
|
||||
*
|
||||
* @param \mysqli $oMysqli
|
||||
*
|
||||
@@ -345,7 +342,8 @@ class CMDBSource
|
||||
{
|
||||
// In case we don't have rights to enumerate the databases
|
||||
// Let's try to connect directly
|
||||
return @((bool)self::$m_oMysqli->query("USE `$sSource`"));
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
return @((bool)DbConnectionWrapper::GetDbConnection(true)->query("USE `$sSource`"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -361,7 +359,7 @@ class CMDBSource
|
||||
*/
|
||||
public static function GetServerInfo()
|
||||
{
|
||||
return mysqli_get_server_info ( self::$m_oMysqli );
|
||||
return mysqli_get_server_info(DbConnectionWrapper::GetDbConnection());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,9 +390,9 @@ class CMDBSource
|
||||
*/
|
||||
public static function SelectDB($sSource)
|
||||
{
|
||||
if (!((bool)self::$m_oMysqli->query("USE `$sSource`")))
|
||||
{
|
||||
throw new MySQLException('Could not select DB', array('db_name'=>$sSource));
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
if (!((bool)DbConnectionWrapper::GetDbConnection(true)->query("USE `$sSource`"))) {
|
||||
throw new MySQLException('Could not select DB', array('db_name' => $sSource));
|
||||
}
|
||||
self::$m_sDBName = $sSource;
|
||||
}
|
||||
@@ -445,51 +443,29 @@ class CMDBSource
|
||||
|
||||
/**
|
||||
* @return \mysqli
|
||||
*
|
||||
* @since 2.5.0 N°1260
|
||||
*/
|
||||
public static function GetMysqli()
|
||||
{
|
||||
return self::$m_oMysqli;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private static function GetMySQLiForQuery()
|
||||
{
|
||||
return self::$oMySQLiForQuery;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used for test purpose (mysqli mock)
|
||||
* @param $oMySQLi
|
||||
*/
|
||||
private static function SetMySQLiForQuery($oMySQLi)
|
||||
{
|
||||
self::$oMySQLiForQuery = $oMySQLi;
|
||||
return DbConnectionWrapper::GetDbConnection(false);
|
||||
}
|
||||
|
||||
public static function GetErrNo()
|
||||
{
|
||||
if (self::$m_oMysqli->errno != 0)
|
||||
{
|
||||
return self::$m_oMysqli->errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
return self::$m_oMysqli->connect_errno;
|
||||
if (DbConnectionWrapper::GetDbConnection()->errno != 0) {
|
||||
return DbConnectionWrapper::GetDbConnection()->errno;
|
||||
} else {
|
||||
return DbConnectionWrapper::GetDbConnection()->connect_errno;
|
||||
}
|
||||
}
|
||||
|
||||
public static function GetError()
|
||||
{
|
||||
if (self::$m_oMysqli->error != '')
|
||||
{
|
||||
return self::$m_oMysqli->error;
|
||||
}
|
||||
else
|
||||
{
|
||||
return self::$m_oMysqli->connect_error;
|
||||
if (DbConnectionWrapper::GetDbConnection()->error != '') {
|
||||
return DbConnectionWrapper::GetDbConnection()->error;
|
||||
} else {
|
||||
return DbConnectionWrapper::GetDbConnection()->connect_error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +505,8 @@ class CMDBSource
|
||||
// Quote if not a number or a numeric string
|
||||
if ($bAlways || is_string($value))
|
||||
{
|
||||
$value = $cQuoteStyle . self::$m_oMysqli->real_escape_string($value) . $cQuoteStyle;
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$value = $cQuoteStyle.DbConnectionWrapper::GetDbConnection()->real_escape_string($value).$cQuoteStyle;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
@@ -590,7 +567,7 @@ class CMDBSource
|
||||
/**
|
||||
* Send the query directly to the DB. **Be extra cautious with this !**
|
||||
*
|
||||
* Use {@link Query} if you're not sure.
|
||||
* Use {@see Query} if you're not sure.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
@@ -612,26 +589,25 @@ class CMDBSource
|
||||
$oKPI = new ExecutionKPI();
|
||||
try
|
||||
{
|
||||
$oResult = self::GetMySQLiForQuery()->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch (mysqli_sql_exception $e)
|
||||
{
|
||||
self::LogDeadLock($e);
|
||||
self::LogDeadLock($e, true);
|
||||
throw new MySQLException('Failed to issue SQL query', array('query' => $sSql, $e));
|
||||
}
|
||||
$oKPI->ComputeStats('Query exec (mySQL)', $sSql);
|
||||
if ($oResult === false)
|
||||
{
|
||||
if ($oResult === false) {
|
||||
$aContext = array('query' => $sSql);
|
||||
|
||||
$iMySqlErrorNo = self::$m_oMysqli->errno;
|
||||
$iMySqlErrorNo = DbConnectionWrapper::GetDbConnection(true)->errno;
|
||||
$aMySqlHasGoneAwayErrorCodes = MySQLHasGoneAwayException::getErrorCodes();
|
||||
if (in_array($iMySqlErrorNo, $aMySqlHasGoneAwayErrorCodes))
|
||||
{
|
||||
if (in_array($iMySqlErrorNo, $aMySqlHasGoneAwayErrorCodes)) {
|
||||
throw new MySQLHasGoneAwayException(self::GetError(), $aContext);
|
||||
}
|
||||
$e = new MySQLException('Failed to issue SQL query', $aContext);
|
||||
self::LogDeadLock($e);
|
||||
self::LogDeadLock($e, true);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -640,23 +616,24 @@ class CMDBSource
|
||||
|
||||
/**
|
||||
* @param \Exception $e
|
||||
* @param bool $bForQuery to get the proper DB connection
|
||||
*
|
||||
* @since 2.7.1
|
||||
* @since 3.0.0 N°4325 add new optional parameter to use the correct DB connection
|
||||
*/
|
||||
private static function LogDeadLock(Exception $e)
|
||||
private static function LogDeadLock(Exception $e, $bForQuery = false)
|
||||
{
|
||||
// checks MySQL error code
|
||||
$iMySqlErrorNo = self::$m_oMysqli->errno;
|
||||
if (!in_array($iMySqlErrorNo, array(self::MYSQL_ERRNO_WAIT_TIMEOUT, self::MYSQL_ERRNO_DEADLOCK)))
|
||||
{
|
||||
$iMySqlErrorNo = DbConnectionWrapper::GetDbConnection($bForQuery)->errno;
|
||||
if (!in_array($iMySqlErrorNo, array(self::MYSQL_ERRNO_WAIT_TIMEOUT, self::MYSQL_ERRNO_DEADLOCK))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get error info
|
||||
$sUser = UserRights::GetUser();
|
||||
$oError = self::$m_oMysqli->query('SHOW ENGINE INNODB STATUS');
|
||||
if ($oError !== false)
|
||||
{
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oError = DbConnectionWrapper::GetDbConnection(true)->query('SHOW ENGINE INNODB STATUS');
|
||||
if ($oError !== false) {
|
||||
$aData = $oError->fetch_all(MYSQLI_ASSOC);
|
||||
$sInnodbStatus = $aData[0];
|
||||
}
|
||||
@@ -829,7 +806,7 @@ class CMDBSource
|
||||
|
||||
public static function GetInsertId()
|
||||
{
|
||||
$iRes = self::$m_oMysqli->insert_id;
|
||||
$iRes = DbConnectionWrapper::GetDbConnection()->insert_id;
|
||||
if (is_null($iRes))
|
||||
{
|
||||
return 0;
|
||||
@@ -871,7 +848,8 @@ class CMDBSource
|
||||
$oKPI = new ExecutionKPI();
|
||||
try
|
||||
{
|
||||
$oResult = self::GetMySQLiForQuery()->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch(mysqli_sql_exception $e)
|
||||
{
|
||||
@@ -912,7 +890,8 @@ class CMDBSource
|
||||
$oKPI = new ExecutionKPI();
|
||||
try
|
||||
{
|
||||
$oResult = self::GetMySQLiForQuery()->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch(mysqli_sql_exception $e)
|
||||
{
|
||||
@@ -962,7 +941,8 @@ class CMDBSource
|
||||
$aData = array();
|
||||
try
|
||||
{
|
||||
$oResult = self::$m_oMysqli->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch(mysqli_sql_exception $e)
|
||||
{
|
||||
@@ -994,7 +974,8 @@ class CMDBSource
|
||||
{
|
||||
try
|
||||
{
|
||||
$oResult = self::GetMySQLiForQuery()->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch(mysqli_sql_exception $e)
|
||||
{
|
||||
@@ -1019,7 +1000,7 @@ class CMDBSource
|
||||
|
||||
public static function AffectedRows()
|
||||
{
|
||||
return self::$m_oMysqli->affected_rows;
|
||||
return DbConnectionWrapper::GetDbConnection()->affected_rows;
|
||||
}
|
||||
|
||||
public static function FetchArray($oResult)
|
||||
@@ -1137,7 +1118,7 @@ class CMDBSource
|
||||
*
|
||||
* We still need to do a case sensitive comparison for enum values !
|
||||
*
|
||||
* A better solution would be to generate SQL field definitions ({@link GetFieldSpec} method) based on the DB used... But for
|
||||
* A better solution would be to generate SQL field definitions ({@see GetFieldSpec} method) based on the DB used... But for
|
||||
* now (N°2490 / SF #1756 / PR #91) we did implement this simpler solution
|
||||
*
|
||||
* @see GetFieldDataTypeAndOptions extracts all info from the SQL field definition
|
||||
@@ -1482,7 +1463,8 @@ class CMDBSource
|
||||
$sSql = "SELECT * FROM `$sTable`";
|
||||
try
|
||||
{
|
||||
$oResult = self::GetMySQLiForQuery()->query($sSql);
|
||||
/** @noinspection NullPointerExceptionInspection this shouldn't be called with un-init DB */
|
||||
$oResult = DbConnectionWrapper::GetDbConnection(true)->query($sSql);
|
||||
}
|
||||
catch(mysqli_sql_exception $e)
|
||||
{
|
||||
|
||||
@@ -113,6 +113,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'log_level_min.write_in_db' => [
|
||||
'type' => 'array',
|
||||
'description' => 'Additional configuration that enable "in DB" logs for Exception on compatible code.',
|
||||
'default' => [ 'Exception' => 'Error', ],
|
||||
'value' => [ 'Exception' => 'Error', ],
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'app_env_label' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")',
|
||||
@@ -1141,6 +1149,38 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'compatibility.include_moved_js_files' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Include back JS files which are now only included when necessary to ease usage of not migrated extensions',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'compatibility.include_deprecated_js_files' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Include the deprecated JS files to ease usage of not migrated extensions',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'compatibility.include_moved_css_files' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Include back CSS files which are now only included when necessary to ease usage of not migrated extensions',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'compatibility.include_deprecated_css_files' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Include the deprecated CSS files to ease usage of not migrated extensions',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'navigation_menu.show_menus_count' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Display count badges for OQL menu entries',
|
||||
@@ -1415,6 +1455,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'security.disable_inline_documents_sandbox' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true then the sandbox for documents displayed in a browser tab will be disabled; enabling scripts and other interactive content. Note that setting this to true will open the application to potential XSS attacks!',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'behind_reverse_proxy' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)',
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
/**
|
||||
* All objects to be displayed in the application (either as a list or as details)
|
||||
* must implement this interface.
|
||||
@@ -946,10 +948,9 @@ abstract class DBObject implements iDisplay
|
||||
*/
|
||||
protected function ComputeHighlightCode()
|
||||
{
|
||||
// First if the state defines a HiglightCode, apply it
|
||||
$sState = $this->GetState();
|
||||
if ($sState != '')
|
||||
if (MetaModel::HasLifecycle(get_class($this)))
|
||||
{
|
||||
$sState = $this->GetState();
|
||||
$sCode = MetaModel::GetHighlightCode(get_class($this), $sState);
|
||||
$this->SetHighlightCode($sCode);
|
||||
}
|
||||
@@ -1525,14 +1526,15 @@ abstract class DBObject implements iDisplay
|
||||
* Helper to get the friendly name in a safe manner for displaying inside a web page
|
||||
*
|
||||
* @internal
|
||||
* @since 3.0.0 N°4106 This method is now internal. It will be set final in 3.1.0 (N°4107)
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0 N°4106 This method is now internal. It will be set final in 3.1.0 (N°4107)
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*
|
||||
*/
|
||||
public function GetName()
|
||||
public function GetName($sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
return htmlentities($this->GetRawName(), ENT_QUOTES, 'UTF-8');
|
||||
return htmlentities($this->GetRawName($sType), ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1546,11 +1548,17 @@ abstract class DBObject implements iDisplay
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0 N°4106 This method is now internal. It will be set final in 3.1.0 (N°4107)
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*
|
||||
*/
|
||||
public function GetRawName()
|
||||
public function GetRawName($sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
return $this->Get('friendlyname');
|
||||
if ($sType == FriendlyNameType::SHORT) {
|
||||
return $this->Get('friendlyname');
|
||||
} else {
|
||||
$oExpression = MetaModel::GetNameExpression(get_class($this), $sType);
|
||||
$this->EvaluateExpression($oExpression);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2134,28 +2142,23 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
if ($oAttDef->DuplicatesAllowed()) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// To control duplicates go through all the entries and check if the remote has been seen
|
||||
/** @var \ormLinkSet $value */
|
||||
$aModifiedLnk = $value->ListModifiedLinks();
|
||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||
$aExistingRemotesId = $value->GetColumnAsArray($sExtKeyToRemote, true);
|
||||
$aExistingRemotesFriendlyName = $value->GetColumnAsArray($sExtKeyToRemote.'_friendlyname', true);
|
||||
$aCurrentRemoteIds = [];
|
||||
$aDuplicatesFields = [];
|
||||
foreach ($aModifiedLnk as $oModifiedLnk) {
|
||||
$iModifiedLnkId = $oModifiedLnk->GetKey();
|
||||
$iModifiedLnkRemoteId = $oModifiedLnk->Get($sExtKeyToRemote);
|
||||
$aExistingRemotesIdToCheck = array_filter($aExistingRemotesId, function ($iLnkKey) use ($iModifiedLnkId) {
|
||||
return ($iLnkKey != $iModifiedLnkId);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
if (!in_array($iModifiedLnkRemoteId, $aExistingRemotesIdToCheck, true)) {
|
||||
continue;
|
||||
$value->rewind();
|
||||
while ($oCurrentLnk = $value->current()) {
|
||||
$iExtKeyToRemote = $oCurrentLnk->Get($sExtKeyToRemote);
|
||||
if (isset($aCurrentRemoteIds[$iExtKeyToRemote])) {
|
||||
$aDuplicatesFields[] = $oCurrentLnk->Get($sExtKeyToRemote.'_friendlyname');
|
||||
} else {
|
||||
$aCurrentRemoteIds[$iExtKeyToRemote] = true;
|
||||
}
|
||||
|
||||
$iLnkId = $oModifiedLnk->GetKey();
|
||||
$aDuplicatesFields[] = $aExistingRemotesFriendlyName[$iLnkId];
|
||||
$value->next();
|
||||
}
|
||||
|
||||
if (!empty($aDuplicatesFields)) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\MedallionIcon\MedallionIcon;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\Panel;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
@@ -464,7 +465,7 @@ class DisplayableNode extends GraphNode
|
||||
{
|
||||
$aRootCauses[] = $oRootCause->GetHyperlink();
|
||||
}
|
||||
$sHtml .= '<p><img style="max-height: 24px; vertical-align:bottom;" src="'.utils::GetAbsoluteUrlModulesRoot().$aContext['icon'].'" title="'.htmlentities(Dict::S($aContext['dict'])).'"> '.implode(', ', $aRootCauses).'</p>';
|
||||
$sHtml .= '<p><img style="max-height: 24px; vertical-align:bottom;" class="ibo-class-icon ibo-is-small" src="'.utils::GetAbsoluteUrlModulesRoot().$aContext['icon'].'" title="'.htmlentities(Dict::S($aContext['dict'])).'"> '.implode(', ', $aRootCauses).'</p>';
|
||||
}
|
||||
$sHtml .= '<hr/>';
|
||||
}
|
||||
@@ -805,7 +806,7 @@ class DisplayableGroupNode extends DisplayableNode
|
||||
$sHtml .= '<a href="#" onclick="$(\'.itop-simple-graph\').simple_graph(\'show_group\', \'relation_group_'.$iGroupIdx.'\');">'.Dict::Format('UI:RelationGroupNumber_N', (1+$iGroupIdx))."</a>";
|
||||
$sHtml .= '<hr/>';
|
||||
$sHtml .= '<table><tbody><tr>';
|
||||
$sHtml .= '<td style="vertical-align:top;padding-right: 0.5em;"><img src="'.$this->GetProperty('icon_url').'"></td><td style="vertical-align:top">'.MetaModel::GetName($this->GetObjectClass()).'<br/>';
|
||||
$sHtml .= '<td style="vertical-align:top;padding-right: 0.5em;"><img class="ibo-class-icon ibo-is-small" src="'.$this->GetProperty('icon_url').'"></td><td style="vertical-align:top">'.MetaModel::GetName($this->GetObjectClass()).'<br/>';
|
||||
$sHtml .= Dict::Format('UI_CountOfObjectsShort', $this->GetObjectCount()).'</td>';
|
||||
$sHtml .= '</tr></tbody></table>';
|
||||
return $sHtml;
|
||||
@@ -1446,7 +1447,7 @@ class DisplayableGraph extends SimpleGraph
|
||||
$sSftShort = Dict::S('UI:ElementsDisplayed');
|
||||
$sSearchToggle = Dict::S('UI:Search:Toggle');
|
||||
$oP->add("<div class=\"not-printable\">\n");
|
||||
$oUiSearchBlock = new Panel($sSftShort, [],Panel::ENUM_COLOR_CYAN, 'ds_flash');
|
||||
$oUiSearchBlock = new Panel($sSftShort, [],Panel::ENUM_COLOR_SCHEME_CYAN, 'ds_flash');
|
||||
$oUiSearchBlock->SetCSSClasses(["ibo-search-form-panel", "display_block"]);
|
||||
$oUiSearchBlock->SetIsCollapsible(true);
|
||||
$oUiHtmlBlock = new Combodo\iTop\Application\UI\Base\Component\Html\Html(
|
||||
@@ -1499,11 +1500,8 @@ EOF
|
||||
|
||||
$sDirection = utils::ReadParam('d', 'horizontal');
|
||||
$iGroupingThreshold = utils::ReadParam('g', 5);
|
||||
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/fraphael.js');
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/jquery.contextMenu.css');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.contextMenu.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/simple_graph.js');
|
||||
|
||||
WebResourcesHelper::EnableSimpleGraphInWebPage($oP);
|
||||
try
|
||||
{
|
||||
$this->InitFromGraphviz();
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
|
||||
|
||||
Swift_Preferences::getInstance()->setCharset('UTF-8');
|
||||
|
||||
|
||||
@@ -335,8 +339,9 @@ class EMail
|
||||
{
|
||||
if (($sMimeType === 'text/html') && ($sCustomStyles !== null))
|
||||
{
|
||||
$emogrifier = new \Pelago\Emogrifier($sBody, $sCustomStyles);
|
||||
$sBody = $emogrifier->emogrify(); // Adds html/body tags if not already present
|
||||
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
|
||||
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
|
||||
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
|
||||
}
|
||||
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
|
||||
$this->m_oMessage->setBody($sBody, $sMimeType);
|
||||
|
||||
@@ -222,6 +222,10 @@ class EventIssue extends Event
|
||||
//
|
||||
$this->Set('page', @$GLOBALS['_SERVER']['SCRIPT_NAME']);
|
||||
|
||||
if (strlen($this->Get('userinfo')) == 0) {
|
||||
$this->Set('userinfo', UserRights::GetUserId());
|
||||
}
|
||||
|
||||
if (array_key_exists('_GET', $GLOBALS) && is_array($GLOBALS['_GET']))
|
||||
{
|
||||
$this->Set('arguments_get', $GLOBALS['_GET']);
|
||||
|
||||
@@ -31,29 +31,38 @@ class ExecutionKPI
|
||||
static protected $m_bBlameCaller = false;
|
||||
static protected $m_sAllowedUser = '*';
|
||||
|
||||
static protected $m_aStats = array(); // Recurrent operations
|
||||
static protected $m_aExecData = array(); // One shot operations
|
||||
static protected $m_aStats = []; // Recurrent operations
|
||||
static protected $m_aExecData = []; // One shot operations
|
||||
/**
|
||||
* @var array[ExecutionKPI]
|
||||
*/
|
||||
static protected $m_aExecutionStack = []; // embedded execution stats
|
||||
|
||||
protected $m_fStarted = null;
|
||||
protected $m_fChildrenDuration = 0; // Count embedded
|
||||
protected $m_iInitialMemory = null;
|
||||
|
||||
static public function EnableDuration($iLevel)
|
||||
{
|
||||
if ($iLevel > 0)
|
||||
{
|
||||
if ($iLevel > 0) {
|
||||
self::$m_bEnabled_Duration = true;
|
||||
if ($iLevel > 1)
|
||||
{
|
||||
if ($iLevel > 1) {
|
||||
self::$m_bBlameCaller = true;
|
||||
} else {
|
||||
self::$m_bBlameCaller = false;
|
||||
}
|
||||
} else {
|
||||
self::$m_bEnabled_Duration = false;
|
||||
self::$m_bBlameCaller = false;
|
||||
}
|
||||
}
|
||||
|
||||
static public function EnableMemory($iLevel)
|
||||
{
|
||||
if ($iLevel > 0)
|
||||
{
|
||||
if ($iLevel > 0) {
|
||||
self::$m_bEnabled_Memory = true;
|
||||
} else {
|
||||
self::$m_bEnabled_Memory = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,16 +112,17 @@ class ExecutionKPI
|
||||
|
||||
$sTableStyle = 'background-color: #ccc; margin: 10px;';
|
||||
|
||||
self::Report("<hr/>");
|
||||
self::Report("<div style=\"background-color: grey; padding: 10px;\">");
|
||||
self::Report("<h3><a name=\"".md5($sExecId)."\">KPIs</a> - ".$_SERVER['REQUEST_URI']." (".$_SERVER['REQUEST_METHOD'].")</h3>");
|
||||
self::Report("<p>".date('Y-m-d H:i:s', $fItopStarted)."</p>");
|
||||
self::Report("<p>log_kpi_user_id: ".UserRights::GetUserId()."</p>");
|
||||
self::Report("<div>");
|
||||
self::Report("<table border=\"1\" style=\"$sTableStyle\">");
|
||||
self::Report("<thead>");
|
||||
self::Report(" <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>");
|
||||
self::Report("</thead>");
|
||||
$sHtml = "<hr/>";
|
||||
$sHtml .= "<div style=\"background-color: grey; padding: 10px;\">";
|
||||
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - ".$_SERVER['REQUEST_URI']." (".$_SERVER['REQUEST_METHOD'].")</h3>";
|
||||
$oStarted = DateTime::createFromFormat('U.u', $fItopStarted);
|
||||
$sHtml .= "<p>".$oStarted->format('Y-m-d H:i:s.u')."</p>";
|
||||
$sHtml .= "<p>log_kpi_user_id: ".UserRights::GetUserId()."</p>";
|
||||
$sHtml .= "<div>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>";
|
||||
$sHtml .= "</thead>";
|
||||
foreach (self::$m_aExecData as $aOpStats)
|
||||
{
|
||||
$sOperation = $aOpStats['op'];
|
||||
@@ -134,12 +144,12 @@ class ExecutionKPI
|
||||
}
|
||||
}
|
||||
|
||||
self::Report("<tr>");
|
||||
self::Report(" <td>$sOperation</td><td>$sBegin</td><td>$sEnd</td><td>$sDuration</td><td>$sMemBegin</td><td>$sMemEnd</td><td>$sMemPeak</td>");
|
||||
self::Report("</tr>");
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sOperation</td><td>$sBegin</td><td>$sEnd</td><td>$sDuration</td><td>$sMemBegin</td><td>$sMemEnd</td><td>$sMemPeak</td>";
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
self::Report("</table>");
|
||||
self::Report("</div>");
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "</div>";
|
||||
|
||||
$aConsolidatedStats = array();
|
||||
foreach (self::$m_aStats as $sOperation => $aOpStats)
|
||||
@@ -175,11 +185,11 @@ class ExecutionKPI
|
||||
);
|
||||
}
|
||||
|
||||
self::Report("<div>");
|
||||
self::Report("<table border=\"1\" style=\"$sTableStyle\">");
|
||||
self::Report("<thead>");
|
||||
self::Report(" <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>");
|
||||
self::Report("</thead>");
|
||||
$sHtml .= "<div>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>";
|
||||
$sHtml .= "</thead>";
|
||||
foreach ($aConsolidatedStats as $sOperation => $aOpStats)
|
||||
{
|
||||
$sOperation = '<a href="#'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||
@@ -189,22 +199,24 @@ class ExecutionKPI
|
||||
$sMax = '<a href="#'.md5($sExecId.$aOpStats['max_args']).'">'.round($aOpStats['max'], 3).'</a>';
|
||||
$sAvg = round($aOpStats['avg'], 3);
|
||||
|
||||
self::Report("<tr>");
|
||||
self::Report(" <td>$sOperation</td><td>$sCount</td><td>$sDuration</td><td>$sMin</td><td>$sMax</td><td>$sAvg</td>");
|
||||
self::Report("</tr>");
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sOperation</td><td>$sCount</td><td>$sDuration</td><td>$sMin</td><td>$sMax</td><td>$sAvg</td>";
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
self::Report("</table>");
|
||||
self::Report("</div>");
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "</div>";
|
||||
|
||||
self::Report("</div>");
|
||||
$sHtml .= "</div>";
|
||||
|
||||
self::Report("<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>");
|
||||
$sHtml .= "<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>";
|
||||
|
||||
$fSlowQueries = MetaModel::GetConfig()->Get('log_kpi_slow_queries');
|
||||
self::Report($sHtml);
|
||||
|
||||
// Report operation details
|
||||
foreach (self::$m_aStats as $sOperation => $aOpStats)
|
||||
{
|
||||
$sHtml = '';
|
||||
$bDisplayHeader = true;
|
||||
foreach ($aOpStats as $sArguments => $aEvents)
|
||||
{
|
||||
@@ -250,31 +262,59 @@ class ExecutionKPI
|
||||
if ($bDisplayHeader)
|
||||
{
|
||||
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||
self::Report("<h4>$sOperationHtml</h4>");
|
||||
self::Report("<table border=\"1\" style=\"$sTableStyle\">");
|
||||
self::Report("<thead>");
|
||||
self::Report(" <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>");
|
||||
self::Report("</thead>");
|
||||
$sHtml .= "<h4>$sOperationHtml</h4>";
|
||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||
$sHtml .= "<thead>";
|
||||
$sHtml .= " <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>";
|
||||
$sHtml .= "</thead>";
|
||||
$bDisplayHeader = false;
|
||||
}
|
||||
self::Report("<tr>");
|
||||
self::Report(" <td>$sHtmlArguments</td><td>$iCountInter</td><td>$sTotalInter</td><td>$sMinInter</td><td>$sMaxInter</td>");
|
||||
self::Report("</tr>");
|
||||
$sHtml .= "<tr>";
|
||||
$sHtml .= " <td>$sHtmlArguments</td><td>$iCountInter</td><td>$sTotalInter</td><td>$sMinInter</td><td>$sMaxInter</td>";
|
||||
$sHtml .= "</tr>";
|
||||
}
|
||||
}
|
||||
if (!$bDisplayHeader)
|
||||
{
|
||||
self::Report("</table>");
|
||||
self::Report("<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>");
|
||||
$sHtml .= "</table>";
|
||||
$sHtml .= "<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>";
|
||||
}
|
||||
self::Report($sHtml);
|
||||
}
|
||||
self::Report('<a name="end-'.md5($sExecId).'"> </a>');
|
||||
$sHtml = '<a name="end-'.md5($sExecId).'"> </a>';
|
||||
self::Report($sHtml);
|
||||
}
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ResetCounters();
|
||||
self::Push($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack executions to remove children duration from stats
|
||||
*
|
||||
* @param \ExecutionKPI $oExecutionKPI
|
||||
*/
|
||||
private static function Push(ExecutionKPI $oExecutionKPI)
|
||||
{
|
||||
array_push(self::$m_aExecutionStack, $oExecutionKPI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop current child and count its duration in its parent
|
||||
*
|
||||
* @param float|int $fChildDuration
|
||||
*/
|
||||
private static function Pop(float $fChildDuration = 0)
|
||||
{
|
||||
array_pop(self::$m_aExecutionStack);
|
||||
// Update the parent's children duration
|
||||
$oPrevExecutionKPI = end(self::$m_aExecutionStack);
|
||||
if ($oPrevExecutionKPI) {
|
||||
$oPrevExecutionKPI->m_fChildrenDuration += $fChildDuration;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the duration since startup, and reset the counter for the next measure
|
||||
@@ -285,13 +325,12 @@ class ExecutionKPI
|
||||
|
||||
$aNewEntry = null;
|
||||
|
||||
if (self::$m_bEnabled_Duration)
|
||||
{
|
||||
if (self::$m_bEnabled_Duration) {
|
||||
$fStopped = MyHelpers::getmicrotime();
|
||||
$aNewEntry = array(
|
||||
'op' => $sOperationDesc,
|
||||
'op' => $sOperationDesc,
|
||||
'time_begin' => $this->m_fStarted - $fItopStarted,
|
||||
'time_end' => $fStopped - $fItopStarted,
|
||||
'time_end' => $fStopped - $fItopStarted,
|
||||
);
|
||||
// Reset for the next operation (if the object is recycled)
|
||||
$this->m_fStarted = $fStopped;
|
||||
@@ -323,31 +362,30 @@ class ExecutionKPI
|
||||
|
||||
public function ComputeStats($sOperation, $sArguments)
|
||||
{
|
||||
if (self::$m_bEnabled_Duration)
|
||||
{
|
||||
$fDuration = 0;
|
||||
if (self::$m_bEnabled_Duration) {
|
||||
$fStopped = MyHelpers::getmicrotime();
|
||||
$fDuration = $fStopped - $this->m_fStarted;
|
||||
if (self::$m_bBlameCaller)
|
||||
{
|
||||
$fSelfDuration = $fDuration - $this->m_fChildrenDuration;
|
||||
if (self::$m_bBlameCaller) {
|
||||
self::$m_aStats[$sOperation][$sArguments][] = array(
|
||||
'time' => $fDuration,
|
||||
'time' => $fSelfDuration,
|
||||
'callers' => MyHelpers::get_callstack(1),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
self::$m_aStats[$sOperation][$sArguments][] = array(
|
||||
'time' => $fDuration
|
||||
'time' => $fSelfDuration,
|
||||
);
|
||||
}
|
||||
}
|
||||
self::Pop($fDuration);
|
||||
}
|
||||
|
||||
protected function ResetCounters()
|
||||
{
|
||||
if (self::$m_bEnabled_Duration)
|
||||
{
|
||||
$this->m_fStarted = MyHelpers::getmicrotime();
|
||||
$this->m_fStarted = microtime(true);
|
||||
}
|
||||
|
||||
if (self::$m_bEnabled_Memory)
|
||||
|
||||
@@ -587,6 +587,9 @@ abstract class LogAPI
|
||||
static::$m_oFileLog = new FileLog($sTargetFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal uses only for testing purpose.
|
||||
*/
|
||||
public static function MockStaticObjects($oFileLog, $oMetaModelConfig = null)
|
||||
{
|
||||
static::$m_oFileLog = $oFileLog;
|
||||
@@ -653,9 +656,9 @@ abstract class LogAPI
|
||||
* @throws \ConfigException if log wrongly configured
|
||||
* @uses GetMinLogLevel
|
||||
*/
|
||||
final public static function IsLogLevelEnabled(string $sLevel, string $sChannel): bool
|
||||
final public static function IsLogLevelEnabled(string $sLevel, string $sChannel, string $sCode = 'log_level_min'): bool
|
||||
{
|
||||
$sMinLogLevel = self::GetMinLogLevel($sChannel);
|
||||
$sMinLogLevel = self::GetMinLogLevel($sChannel, $sCode);
|
||||
|
||||
if ($sMinLogLevel === false || $sMinLogLevel === 'false') {
|
||||
return false;
|
||||
@@ -675,6 +678,7 @@ abstract class LogAPI
|
||||
|
||||
/**
|
||||
* @param string $sChannel
|
||||
* @param string $sCode
|
||||
*
|
||||
* @return string one of the LEVEL_* const value : the one configured it if exists, otherwise default log level for this channel
|
||||
* Config can be set :
|
||||
@@ -694,14 +698,14 @@ abstract class LogAPI
|
||||
*
|
||||
* @link https://www.itophub.io/wiki/page?id=3_0_0%3Aadmin%3Alog iTop log reference
|
||||
*/
|
||||
protected static function GetMinLogLevel($sChannel)
|
||||
protected static function GetMinLogLevel($sChannel, $sCode = 'log_level_min')
|
||||
{
|
||||
$oConfig = static::GetConfig();
|
||||
if (!$oConfig instanceof Config) {
|
||||
return static::GetLevelDefault();
|
||||
}
|
||||
|
||||
$sLogLevelMin = $oConfig->Get('log_level_min');
|
||||
$sLogLevelMin = $oConfig->Get($sCode);
|
||||
|
||||
if (empty($sLogLevelMin)) {
|
||||
return static::GetLevelDefault();
|
||||
@@ -733,7 +737,7 @@ abstract class LogAPI
|
||||
*/
|
||||
protected static function GetConfig(): ?Config
|
||||
{
|
||||
return static::$m_oMockMetaModelConfig ?? \MetaModel::GetConfig();
|
||||
return static::$m_oMockMetaModelConfig ?? \utils::GetConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -850,10 +854,32 @@ class DeprecatedCallsLog extends LogAPI
|
||||
/** @var \FileLog we want our own instance ! */
|
||||
protected static $m_oFileLog = null;
|
||||
|
||||
/**
|
||||
* Indirection to {@see \LogAPI::IsLogLevelEnabled()} that is handling possible {@see ConfigException}
|
||||
*
|
||||
* @param string $sLevel
|
||||
* @param string $sChannel
|
||||
*
|
||||
* @return bool if exception occurs, then returns false
|
||||
*
|
||||
* @uses \LogAPI::IsLogLevelEnabled()
|
||||
*/
|
||||
protected static function IsLogLevelEnabledSafe($sLevel, $sChannel): bool
|
||||
{
|
||||
try {
|
||||
$bIsLogLevelEnabled = static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD);
|
||||
}
|
||||
catch (ConfigException $e) {
|
||||
$bIsLogLevelEnabled = false;
|
||||
}
|
||||
|
||||
return $bIsLogLevelEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sTargetFile
|
||||
*
|
||||
*@uses \set_error_handler() to catch deprecated notices
|
||||
* @uses \set_error_handler() to catch deprecated notices
|
||||
*
|
||||
* @since 3.0.0 N°3002 logs deprecated notices in called code
|
||||
*/
|
||||
@@ -864,13 +890,7 @@ class DeprecatedCallsLog extends LogAPI
|
||||
}
|
||||
parent::Enable($sTargetFile);
|
||||
|
||||
try {
|
||||
$bIsLogLevelEnabled = static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD);
|
||||
}
|
||||
catch (ConfigException $e) {
|
||||
$bIsLogLevelEnabled = false;
|
||||
}
|
||||
if ($bIsLogLevelEnabled) {
|
||||
if (static::IsLogLevelEnabledSafe(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD)) {
|
||||
set_error_handler([static::class, 'DeprecatedNoticesErrorHandler']);
|
||||
}
|
||||
}
|
||||
@@ -897,6 +917,11 @@ class DeprecatedCallsLog extends LogAPI
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false === static::IsLogLevelEnabledSafe(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD)) {
|
||||
// returns true so that nothing is throwned !
|
||||
return true;
|
||||
}
|
||||
|
||||
$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
|
||||
$sDeprecatedObject = $aStack[$iStackDeprecatedMethodLevel]['class'];
|
||||
@@ -911,9 +936,21 @@ class DeprecatedCallsLog extends LogAPI
|
||||
|
||||
$iStackCallerMethodLevel = $iStackDeprecatedMethodLevel + 1; // level 3 = caller of the deprecated method
|
||||
if (array_key_exists($iStackCallerMethodLevel, $aStack)) {
|
||||
$sCallerObject = $aStack[3]['class'];
|
||||
$sCallerMethod = $aStack[3]['function'];
|
||||
$sMessage .= " ({$sCallerObject}::{$sCallerMethod})";
|
||||
$sCallerObject = $aStack[$iStackCallerMethodLevel]['class'] ?? null;
|
||||
$sCallerMethod = $aStack[$iStackCallerMethodLevel]['function'] ?? null;
|
||||
$sMessage .= ' (';
|
||||
if (!is_null($sCallerObject)) {
|
||||
$sMessage .= "{$sCallerObject}::{$sCallerMethod}";
|
||||
} else {
|
||||
$sCallerMethodFile = $aStack[$iStackCallerMethodLevel]['file'];
|
||||
$sCallerMethodLine = $aStack[$iStackCallerMethodLevel]['line'];
|
||||
if (!is_null($sCallerMethod)) {
|
||||
$sMessage .= "call to {$sCallerMethod}() in {$sCallerMethodFile}#L{$sCallerMethodLine}";
|
||||
} else {
|
||||
$sMessage .= "{$sCallerMethodFile}#L{$sCallerMethodLine}";
|
||||
}
|
||||
}
|
||||
$sMessage .= ')';
|
||||
}
|
||||
|
||||
if (!empty($errstr)) {
|
||||
@@ -1087,3 +1124,160 @@ class LogFileRotationProcess implements iScheduledProcess
|
||||
throw new ProcessException(self::class.' : The configured filename builder is invalid (log_filename_builder_impl="'.$sLogFileNameBuilder.'")');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log exceptions using dedicated API and logic.
|
||||
*
|
||||
* Please use {@see ExceptionLog::LogException()} to log exceptions
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class ExceptionLog extends LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = 'Exception';
|
||||
const CONTEXT_EXCEPTION = '__exception';
|
||||
|
||||
private static $oLastEventIssue = null;
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
|
||||
/**
|
||||
* This method should be used to write logs.
|
||||
*
|
||||
* As it encapsulate the operations performed using the Exception, you should prefer it to the standard API inherited from LogApi `ExceptionLog::Error($oException->getMessage(), get_class($oException), ['__exception' => $oException]);`
|
||||
* The parameter order is not standard, but in our use case, the resulting API is way more convenient this way.
|
||||
*/
|
||||
public static function LogException(Exception $oException, $aContext = array(), $sLevel = self::LEVEL_WARNING)
|
||||
{
|
||||
if (empty($aContext[self::CONTEXT_EXCEPTION])) {
|
||||
$aContext[self::CONTEXT_EXCEPTION] = $oException;
|
||||
}
|
||||
|
||||
if (empty($aContext['exception class'])) {
|
||||
$aContext['exception class'] = get_class($oException);
|
||||
}
|
||||
|
||||
if (empty($aContext['file'])) {
|
||||
$aContext['file'] = $oException->getFile();
|
||||
}
|
||||
|
||||
if (empty($aContext['line'])) {
|
||||
$aContext['line'] =$oException->getLine();
|
||||
}
|
||||
|
||||
self::Log($sLevel, $oException->getMessage(), get_class($oException), $aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \ConfigException if log wrongly configured
|
||||
*/
|
||||
public static function Log($sLevel, $sMessage, $sClass = null, $aContext = array())
|
||||
{
|
||||
if (!static::$m_oFileLog) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset(self::$aLevelsPriority[$sLevel])) {
|
||||
IssueLog::Error("invalid log level '{$sLevel}'");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$sChannel = self::FindClassChannel($sClass);
|
||||
if (static::IsLogLevelEnabled($sLevel, $sChannel)) {
|
||||
static::$m_oFileLog->$sLevel($sMessage, $sChannel, array_diff_key($aContext, [self::CONTEXT_EXCEPTION => null])); //The exception should not be included in the error.log because of its verbosity.
|
||||
}
|
||||
|
||||
$sDbChannel = self::FindClassChannel($sClass, 'log_level_min.write_in_db');
|
||||
if (static::IsLogLevelEnabled($sLevel, $sDbChannel, 'log_level_min.write_in_db')) {
|
||||
self::WriteToDb($aContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static function FindClassChannel($sClass, $sCode = 'log_level_min')
|
||||
{
|
||||
$oConfig = static::GetConfig();
|
||||
if (!$oConfig instanceof Config) {
|
||||
return static::GetLevelDefault();
|
||||
}
|
||||
|
||||
$sLogLevelMin = $oConfig->Get($sCode);
|
||||
|
||||
if (empty($sLogLevelMin)) {
|
||||
return $sClass;
|
||||
}
|
||||
|
||||
if (!is_array($sLogLevelMin)) {
|
||||
return $sClass;
|
||||
}
|
||||
|
||||
$sParentClass = $sClass;
|
||||
while (
|
||||
(!isset($sLogLevelMin[$sParentClass]))
|
||||
&&
|
||||
($sParentClass !== false)
|
||||
)
|
||||
{
|
||||
$sParentClass = get_parent_class($sParentClass);
|
||||
}
|
||||
|
||||
if (isset($sLogLevelMin[$sParentClass])) {
|
||||
return $sParentClass;
|
||||
}
|
||||
|
||||
return $sClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function Enable($sTargetFile = null)
|
||||
{
|
||||
if (empty($sTargetFile))
|
||||
{
|
||||
$sTargetFile = APPROOT.'log/error.log';
|
||||
}
|
||||
parent::Enable($sTargetFile);
|
||||
}
|
||||
|
||||
private static function WriteToDb(array $aContext): void
|
||||
{
|
||||
$oContextException = $aContext[self::CONTEXT_EXCEPTION];
|
||||
unset($aContext[self::CONTEXT_EXCEPTION]);
|
||||
|
||||
if (MetaModel::IsLogEnabledIssue()) {
|
||||
if (MetaModel::IsValidClass('EventIssue')) {
|
||||
try {
|
||||
self::$oLastEventIssue = new EventIssue();
|
||||
|
||||
$sIssue = ($oContextException instanceof CoreException) ? $oContextException->GetIssue() : 'PHP Exception';
|
||||
$sErrorStackTrace = ($oContextException instanceof CoreException) ? $oContextException->getFullStackTraceAsString() : $oContextException->getTraceAsString();
|
||||
$aContextData = ($oContextException instanceof CoreException) ? $oContextException->getContextData() : [];
|
||||
|
||||
|
||||
self::$oLastEventIssue->Set('message', $oContextException->getMessage());
|
||||
self::$oLastEventIssue->Set('userinfo', '');
|
||||
self::$oLastEventIssue->Set('issue', $sIssue);
|
||||
self::$oLastEventIssue->Set('impact', '');
|
||||
self::$oLastEventIssue->Set('callstack', $sErrorStackTrace);
|
||||
self::$oLastEventIssue->Set('data', array_merge($aContextData, $aContext));
|
||||
self::$oLastEventIssue->DBInsertNoReload();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
IssueLog::Error("Failed to log issue into the DB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Used by the tests
|
||||
*/
|
||||
private static function GetLastEventIssue()
|
||||
{
|
||||
return self::$oLastEventIssue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
require_once APPROOT.'core/modulehandler.class.inc.php';
|
||||
require_once APPROOT.'core/querymodifier.class.inc.php';
|
||||
require_once APPROOT.'core/metamodelmodifier.inc.php';
|
||||
@@ -443,10 +445,10 @@ abstract class MetaModel
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param bool $bImgTag
|
||||
* @param string $sMoreStyles
|
||||
* @param bool $bImgTag Whether to surround the icon URL with an HTML IMG tag or not
|
||||
* @param string $sMoreStyles Additional inline CSS style to add to the IMG tag. Only used if $bImgTag is set to true
|
||||
*
|
||||
* @return string
|
||||
* @return string Absolute URL the class icon
|
||||
* @throws \CoreException
|
||||
*/
|
||||
final public static function GetClassIcon($sClass, $bImgTag = true, $sMoreStyles = '')
|
||||
@@ -457,7 +459,7 @@ abstract class MetaModel
|
||||
if (array_key_exists('style', self::$m_aClassParams[$sClass])) {
|
||||
/** @var ormStyle $oStyle */
|
||||
$oStyle = self::$m_aClassParams[$sClass]['style'];
|
||||
$sIcon = $oStyle->GetIcon();
|
||||
$sIcon = $oStyle->GetIconAsAbsUrl();
|
||||
}
|
||||
if (strlen($sIcon) == 0) {
|
||||
$sParentClass = self::GetParentPersistentClass($sClass);
|
||||
@@ -492,7 +494,7 @@ abstract class MetaModel
|
||||
$oStyle = new ormStyle("ibo-class-style--$sClass", "ibo-class-style-alt--$sClass");
|
||||
}
|
||||
|
||||
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIcon()) > 0)) {
|
||||
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIconAsRelPath()) > 0)) {
|
||||
// all the parameters are set, no need to search in the parent classes
|
||||
return $oStyle;
|
||||
}
|
||||
@@ -510,10 +512,10 @@ abstract class MetaModel
|
||||
$oStyle->SetComplementaryColor($oParentStyle->GetComplementaryColor());
|
||||
$oStyle->SetAltStyleClass($oParentStyle->GetAltStyleClass());
|
||||
}
|
||||
if (strlen($oStyle->GetIcon()) == 0) {
|
||||
$oStyle->SetIcon($oParentStyle->GetIcon());
|
||||
if (strlen($oStyle->GetIconAsRelPath()) == 0) {
|
||||
$oStyle->SetIcon($oParentStyle->GetIconAsRelPath());
|
||||
}
|
||||
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIcon()) > 0)) {
|
||||
if ((strlen($oStyle->GetMainColor()) > 0) && (strlen($oStyle->GetComplementaryColor()) > 0) && (strlen($oStyle->GetIconAsRelPath()) > 0)) {
|
||||
// all the parameters are set, no need to search in the parent classes
|
||||
return $oStyle;
|
||||
}
|
||||
@@ -521,7 +523,7 @@ abstract class MetaModel
|
||||
$sParentClass = self::GetParentPersistentClass($sParentClass);
|
||||
}
|
||||
|
||||
if ((strlen($oStyle->GetMainColor()) == 0) && (strlen($oStyle->GetComplementaryColor()) == 0) && (strlen($oStyle->GetIcon()) == 0)) {
|
||||
if ((strlen($oStyle->GetMainColor()) == 0) && (strlen($oStyle->GetComplementaryColor()) == 0) && (strlen($oStyle->GetIconAsRelPath()) == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -752,17 +754,56 @@ abstract class MetaModel
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $sType {@see \Combodo\iTop\Core\MetaModel\FriendlyNameType}
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*/
|
||||
final public static function GetNameSpec($sClass)
|
||||
final public static function GetNameSpec($sClass, $sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
$nameRawSpec = self::$m_aClassParams[$sClass]["name_attcode"];
|
||||
|
||||
switch ($sType) {
|
||||
case FriendlyNameType::COMPLEMENTARY:
|
||||
if (!isset(self::$m_aClassParams[$sClass]["complementary_name_attcode"])) {
|
||||
return [$sClass, []];
|
||||
}
|
||||
$nameRawSpec = self::$m_aClassParams[$sClass]["complementary_name_attcode"];
|
||||
$sDictName = 'ComplementaryName';
|
||||
break;
|
||||
case FriendlyNameType::LONG:
|
||||
$nameRawSpec = self::$m_aClassParams[$sClass]["name_attcode"];
|
||||
if (!isset(self::$m_aClassParams[$sClass]["complementary_name_attcode"])) {
|
||||
return self::GetNameSpec($sClass, FriendlyNameType::SHORT);
|
||||
}
|
||||
$complementaryNameRawSpec = self::$m_aClassParams[$sClass]["complementary_name_attcode"];
|
||||
if (is_array($nameRawSpec)) {
|
||||
if (is_array($complementaryNameRawSpec)) {
|
||||
$nameRawSpec = merge($nameRawSpec, $complementaryNameRawSpec);
|
||||
} elseif (!empty($nameRawSpec)) {
|
||||
$nameRawSpec = merge($nameRawSpec, [$complementaryNameRawSpec]);
|
||||
}
|
||||
} elseif (empty($nameRawSpec)) {
|
||||
$nameRawSpec = $complementaryNameRawSpec;
|
||||
} else {
|
||||
if (is_array($complementaryNameRawSpec)) {
|
||||
$nameRawSpec = merge([$nameRawSpec], $complementaryNameRawSpec);
|
||||
} elseif (!empty($nameRawSpec)) {
|
||||
$nameRawSpec = [$nameRawSpec, $complementaryNameRawSpec];
|
||||
}
|
||||
}
|
||||
$sDictName = 'LongName';
|
||||
break;
|
||||
default:
|
||||
$nameRawSpec = self::$m_aClassParams[$sClass]["name_attcode"];
|
||||
$sDictName = 'Name';
|
||||
}
|
||||
|
||||
if (is_array($nameRawSpec)) {
|
||||
$sFormat = Dict::S("Class:$sClass/Name", '');
|
||||
$sFormat = Dict::S("Class:$sClass/$sDictName", '');
|
||||
if (strlen($sFormat) == 0) {
|
||||
// Default to "%1$s %2$s..."
|
||||
for ($i = 1; $i <= count($nameRawSpec); $i++) {
|
||||
@@ -774,12 +815,12 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
|
||||
return array($sFormat, $nameRawSpec);
|
||||
return [$sFormat, $nameRawSpec];
|
||||
} elseif (empty($nameRawSpec)) {
|
||||
return array($sClass, array());
|
||||
return [$sClass, []];
|
||||
} else {
|
||||
// string -> attcode
|
||||
return array('%1$s', array($nameRawSpec));
|
||||
return ['%1$s', [$nameRawSpec]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,24 +828,38 @@ abstract class MetaModel
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param bool $bWithAttributeDefinition
|
||||
* @param string $sType {@see \Combodo\iTop\Core\MetaModel\FriendlyNameType}
|
||||
*
|
||||
* @return array of attribute codes used by friendlyname
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0
|
||||
*/
|
||||
final public static function GetNameAttributes(string $sClass, $bWithAttributeDefinition = false): array
|
||||
final public static function GetNameAttributes(string $sClass, $bWithAttributeDefinition = false, $sType = FriendlyNameType::SHORT): array
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
$rawNameAttCodes = self::$m_aClassParams[$sClass]["name_attcode"];
|
||||
$aNameAttCodes = [];
|
||||
if (!is_array($rawNameAttCodes)) {
|
||||
if (self::IsValidAttCode($sClass, $rawNameAttCodes)) {
|
||||
$aNameAttCodes[] = $rawNameAttCodes;
|
||||
if ($sType == FriendlyNameType::SHORT || FriendlyNameType::LONG) {
|
||||
$rawNameAttCodes = self::$m_aClassParams[$sClass]["name_attcode"];
|
||||
if (!is_array($rawNameAttCodes)) {
|
||||
if (self::IsValidAttCode($sClass, $rawNameAttCodes)) {
|
||||
$aNameAttCodes[] = $rawNameAttCodes;
|
||||
}
|
||||
} else {
|
||||
$aNameAttCodes = $rawNameAttCodes;
|
||||
}
|
||||
}
|
||||
if ($sType == FriendlyNameType::COMPLEMENTARY || FriendlyNameType::LONG) {
|
||||
$rawNameAttCodes = self::$m_aClassParams[$sClass]["complementary_name_attcode"];
|
||||
if (!isEmpty($rawNameAttCodes)) {
|
||||
if (!is_array($rawNameAttCodes)) {
|
||||
if (self::IsValidAttCode($sClass, $rawNameAttCodes)) {
|
||||
$aNameAttCodes[] = array_merge($aNameAttCodes, [$rawNameAttCodes]);
|
||||
}
|
||||
} else {
|
||||
$aNameAttCodes = array_merge($rawNameAttCodes, $rawNameAttCodes);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$aNameAttCodes = $rawNameAttCodes;
|
||||
}
|
||||
|
||||
if ($bWithAttributeDefinition) {
|
||||
$aResults = [];
|
||||
foreach ($aNameAttCodes as $sAttCode) {
|
||||
@@ -842,68 +897,21 @@ abstract class MetaModel
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
final static public function GetComplementAttributeSpec($sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
if (!isset(self::$m_aClassParams[$sClass]["name_complement_for_select"]))
|
||||
{
|
||||
$sParentClass = static::GetParentClass($sClass);
|
||||
if (is_null($sParentClass)) {
|
||||
return array($sClass, array());
|
||||
} else {
|
||||
return static::GetComplementAttributeSpec($sParentClass);
|
||||
}
|
||||
}
|
||||
$nameRawSpec = self::$m_aClassParams[$sClass]["name_complement_for_select"];
|
||||
if (is_array($nameRawSpec))
|
||||
{
|
||||
$sFormat = Dict::S("Class:$sClass/ComplementForSelect", '');
|
||||
if (strlen($sFormat) == 0)
|
||||
{
|
||||
// Default to "%1$s %2$s..."
|
||||
for($i = 1; $i <= count($nameRawSpec); $i++)
|
||||
{
|
||||
if (empty($sFormat))
|
||||
{
|
||||
$sFormat .= '%'.$i.'$s';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sFormat .= ' %'.$i.'$s';
|
||||
}
|
||||
}
|
||||
}
|
||||
return array($sFormat, $nameRawSpec);
|
||||
}
|
||||
elseif (empty($nameRawSpec))
|
||||
{
|
||||
return array($sClass, array());
|
||||
}
|
||||
else
|
||||
{
|
||||
// string -> attcode
|
||||
return array('%1$s', array($nameRawSpec));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the friendly name expression for a given class
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param string $sType {@see \Combodo\iTop\Core\MetaModel\FriendlyNameType}
|
||||
*
|
||||
* @return Expression
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*/
|
||||
final public static function GetNameExpression($sClass)
|
||||
final public static function GetNameExpression($sClass, $sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
$aNameSpec = self::GetNameSpec($sClass);
|
||||
$aNameSpec = self::GetNameSpec($sClass, $sType);
|
||||
$sFormat = $aNameSpec[0];
|
||||
$aAttributes = $aNameSpec[1];
|
||||
|
||||
@@ -935,14 +943,17 @@ abstract class MetaModel
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $sType {@see \Combodo\iTop\Core\MetaModel\FriendlyNameType}
|
||||
*
|
||||
* @return string The friendly name IIF it is equivalent to a single attribute
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*/
|
||||
final public static function GetFriendlyNameAttributeCode($sClass)
|
||||
final public static function GetFriendlyNameAttributeCode($sClass, $sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
$aNameSpec = self::GetNameSpec($sClass);
|
||||
$aNameSpec = self::GetNameSpec($sClass, $sType);
|
||||
$sFormat = trim($aNameSpec[0]);
|
||||
$aAttributes = $aNameSpec[1];
|
||||
if (($sFormat != '') && ($sFormat != '%1$s')) {
|
||||
@@ -958,13 +969,16 @@ abstract class MetaModel
|
||||
/**
|
||||
* Returns the list of attributes composing the friendlyname
|
||||
*
|
||||
* @param $sClass
|
||||
* @param string $sClass
|
||||
* @param string $sType {@see \Combodo\iTop\Core\MetaModel\FriendlyNameType}
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.0.0 N°580 New $sType parameter
|
||||
*/
|
||||
final public static function GetFriendlyNameAttributeCodeList($sClass)
|
||||
final public static function GetFriendlyNameAttributeCodeList($sClass, $sType = FriendlyNameType::SHORT)
|
||||
{
|
||||
$aNameSpec = self::GetNameSpec($sClass);
|
||||
$aNameSpec = self::GetNameSpec($sClass, $sType);
|
||||
$aAttributes = $aNameSpec[1];
|
||||
|
||||
return $aAttributes;
|
||||
@@ -1133,7 +1147,8 @@ abstract class MetaModel
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
$oAtt = self::GetAttributeDef($sClass, $sAttCode);
|
||||
return $oAtt->GetPrerequisiteAttributes();
|
||||
|
||||
return $oAtt->GetPrerequisiteAttributes($sClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6509,6 +6524,7 @@ abstract class MetaModel
|
||||
*/
|
||||
public static function LoadConfig($oConfiguration, $bAllowCache = false)
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
self::$m_oConfig = $oConfiguration;
|
||||
|
||||
// N°2478 utils has his own private attribute
|
||||
@@ -6529,6 +6545,7 @@ abstract class MetaModel
|
||||
ToolsLog::Enable(APPROOT.'log/tools.log');
|
||||
DeadLockLog::Enable();
|
||||
DeprecatedCallsLog::Enable();
|
||||
ExceptionLog::Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6585,6 +6602,7 @@ abstract class MetaModel
|
||||
|
||||
$sSource = self::$m_oConfig->Get('db_name');
|
||||
$sTablePrefix = self::$m_oConfig->Get('db_subname');
|
||||
$oKPI->ComputeAndReport('Load config');
|
||||
|
||||
if (self::$m_bUseAPCCache)
|
||||
{
|
||||
@@ -7215,21 +7233,6 @@ abstract class MetaModel
|
||||
return $oRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.7.0 N°1627, use ItopCounter::incRootClass($sClass) instead
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return int
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public static function GetNextKey($sClass)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ItopCounter::incRootClass($sClass) instead');
|
||||
|
||||
return ItopCounter::IncClass($sClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletion of records, bypassing {@link DBObject::DBDelete} !!!
|
||||
* It is NOT recommended to use this shortcut
|
||||
@@ -7715,14 +7718,18 @@ abstract class MetaModel
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $sAttCode
|
||||
* @param string $sValue
|
||||
* @param string|null $sValue Code of the state value, can be null if allowed by the attribute definition
|
||||
*
|
||||
* @return \ormStyle|null
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public static function GetEnumStyle(string $sClass, string $sAttCode, string $sValue = ''): ?ormStyle
|
||||
public static function GetEnumStyle(string $sClass, string $sAttCode, ?string $sValue = ''): ?ormStyle
|
||||
{
|
||||
if (strlen($sAttCode) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$oAttDef = self::GetAttributeDef($sClass, $sAttCode);
|
||||
if (!$oAttDef instanceof AttributeEnum) {
|
||||
throw new CoreException("MetaModel::GetEnumStyle() Attribute $sAttCode of class $sClass is not an AttributeEnum\n");
|
||||
|
||||
@@ -7,41 +7,50 @@
|
||||
/**
|
||||
* Class ormStyle
|
||||
*
|
||||
* @since 3.0
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class ormStyle
|
||||
{
|
||||
/** @var string */
|
||||
/** @var string|null */
|
||||
protected $sMainColor;
|
||||
/** @var string */
|
||||
/** @var string|null */
|
||||
protected $sComplementaryColor;
|
||||
/** @var string CSS class with color and background-color */
|
||||
/** @var string|null CSS class with color and background-color */
|
||||
protected $sStyleClass;
|
||||
/** @var string CSS class with only color */
|
||||
/** @var string|null CSS class with only color */
|
||||
protected $sAltStyleClass;
|
||||
/** @var string */
|
||||
/** @var string|null */
|
||||
protected $sDecorationClasses;
|
||||
/** @var string */
|
||||
/** @var string|null Relative path (from current environment) to the icon */
|
||||
protected $sIcon;
|
||||
|
||||
/**
|
||||
* ormStyle constructor.
|
||||
*
|
||||
* @param string $sStyleClass
|
||||
* @param string $sAltStyleClass
|
||||
* @param string|null $sStyleClass
|
||||
* @param string|null $sAltStyleClass
|
||||
* @param string|null $sMainColor
|
||||
* @param string|null $sComplementaryColor
|
||||
* @param string|null $sDecorationClasses
|
||||
* @param string|null $sIcon
|
||||
*/
|
||||
public function __construct(string $sStyleClass, string $sAltStyleClass, string $sMainColor = null, string $sComplementaryColor = null, string $sDecorationClasses = null, string $sIcon = null)
|
||||
public function __construct(?string $sStyleClass = null, ?string $sAltStyleClass = null, ?string $sMainColor = null, ?string $sComplementaryColor = null, ?string $sDecorationClasses = null, ?string $sIcon = null)
|
||||
{
|
||||
$this->sMainColor = $sMainColor;
|
||||
$this->sComplementaryColor = $sComplementaryColor;
|
||||
$this->sStyleClass = $sStyleClass;
|
||||
$this->sAltStyleClass = $sAltStyleClass;
|
||||
$this->sDecorationClasses = $sDecorationClasses;
|
||||
$this->sIcon = $sIcon;
|
||||
$this->SetMainColor($sMainColor);
|
||||
$this->SetComplementaryColor($sComplementaryColor);
|
||||
$this->SetStyleClass($sStyleClass);
|
||||
$this->SetAltStyleClass($sAltStyleClass);
|
||||
$this->SetDecorationClasses($sDecorationClasses);
|
||||
$this->SetIcon($sIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sMainColor
|
||||
* @return bool
|
||||
*/
|
||||
public function HasMainColor(): bool
|
||||
{
|
||||
return strlen($this->sMainColor) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,10 +68,19 @@ class ormStyle
|
||||
*/
|
||||
public function SetMainColor(?string $sMainColor)
|
||||
{
|
||||
$this->sMainColor = $sMainColor;
|
||||
$this->sMainColor = (strlen($sMainColor) === 0) ? null : $sMainColor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sComplementaryColor
|
||||
* @return bool
|
||||
*/
|
||||
public function HasComplementaryColor(): bool
|
||||
{
|
||||
return strlen($this->sComplementaryColor) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -78,14 +96,33 @@ class ormStyle
|
||||
*/
|
||||
public function SetComplementaryColor(?string $sComplementaryColor)
|
||||
{
|
||||
$this->sComplementaryColor = $sComplementaryColor;
|
||||
$this->sComplementaryColor = (strlen($sComplementaryColor) === 0) ? null : $sComplementaryColor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sMainColor
|
||||
* @see static::$sComplementaryColor
|
||||
* @return bool
|
||||
*/
|
||||
public function HasAtLeastOneColor(): bool
|
||||
{
|
||||
return $this->HasMainColor() || $this->HasComplementaryColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sStyleClass
|
||||
* @return bool
|
||||
*/
|
||||
public function HasStyleClass(): bool
|
||||
{
|
||||
return strlen($this->sStyleClass) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetStyleClass(): string
|
||||
public function GetStyleClass(): ?string
|
||||
{
|
||||
return $this->sStyleClass;
|
||||
}
|
||||
@@ -95,16 +132,25 @@ class ormStyle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetStyleClass(string $sStyleClass)
|
||||
public function SetStyleClass(?string $sStyleClass)
|
||||
{
|
||||
$this->sStyleClass = $sStyleClass;
|
||||
$this->sStyleClass = (strlen($sStyleClass) === 0) ? null : $sStyleClass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sAltStyleClass
|
||||
* @return bool
|
||||
*/
|
||||
public function HasAltStyleClass(): bool
|
||||
{
|
||||
return strlen($this->sAltStyleClass) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAltStyleClass(): string
|
||||
public function GetAltStyleClass(): ?string
|
||||
{
|
||||
return $this->sAltStyleClass;
|
||||
}
|
||||
@@ -114,12 +160,21 @@ class ormStyle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetAltStyleClass(string $sAltStyleClass)
|
||||
public function SetAltStyleClass(?string $sAltStyleClass)
|
||||
{
|
||||
$this->sAltStyleClass = $sAltStyleClass;
|
||||
$this->sAltStyleClass = (strlen($sAltStyleClass) === 0) ? null : $sAltStyleClass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sDecorationClasses
|
||||
* @return bool
|
||||
*/
|
||||
public function HasDecorationClasses(): bool
|
||||
{
|
||||
return strlen($this->sDecorationClasses) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -135,16 +190,17 @@ class ormStyle
|
||||
*/
|
||||
public function SetDecorationClasses(?string $sDecorationClasses)
|
||||
{
|
||||
$this->sDecorationClasses = $sDecorationClasses;
|
||||
$this->sDecorationClasses = (strlen($sDecorationClasses) === 0) ? null : $sDecorationClasses;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @see static::$sIcon
|
||||
* @return bool
|
||||
*/
|
||||
public function GetIcon(): ?string
|
||||
public function HasIcon(): bool
|
||||
{
|
||||
return $this->sIcon;
|
||||
return strlen($this->sIcon) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,8 +210,30 @@ class ormStyle
|
||||
*/
|
||||
public function SetIcon(?string $sIcon)
|
||||
{
|
||||
$this->sIcon = $sIcon;
|
||||
$this->sIcon = (strlen($sIcon) === 0) ? null : $sIcon;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sIcon
|
||||
* @return string|null Relative path (from the current environment) of the icon
|
||||
*/
|
||||
public function GetIconAsRelPath(): ?string
|
||||
{
|
||||
return $this->sIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sIcon
|
||||
* @return string|null Absolute URL of the icon
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetIconAsAbsUrl(): ?string
|
||||
{
|
||||
if (is_null($this->sIcon)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return utils::GetAbsoluteUrlModulesRoot().$this->sIcon;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
|
||||
define('CASELOG_VISIBLE_ITEMS', 2);
|
||||
define('CASELOG_SEPARATOR', "\n".'========== %1$s : %2$s (%3$d) ============'."\n\n");
|
||||
|
||||
@@ -168,7 +174,6 @@ class ormCaseLog {
|
||||
return $aEntries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a "plain text" version of the log (equivalent to $this->m_sLog) where all the HTML markup from the 'html' entries have been removed
|
||||
* @return string
|
||||
@@ -201,6 +206,15 @@ class ormCaseLog {
|
||||
{
|
||||
return ($this->m_sLog === null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The number of entries in this log
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetEntryCount(): int
|
||||
{
|
||||
return count($this->m_aIndex);
|
||||
}
|
||||
|
||||
public function ClearModifiedFlag()
|
||||
{
|
||||
@@ -389,7 +403,7 @@ class ormCaseLog {
|
||||
{
|
||||
$bPrintableVersion = (utils::ReadParam('printable', '0') == '1');
|
||||
|
||||
$sHtml = '<table style="width:100%;table-layout:fixed"><tr><td>'; // Use table-layout:fixed to force the with to be independent from the actual content
|
||||
$oBlock = UIContentBlockUIBlockFactory::MakeStandard(null, ['ibo-caselog-list']);
|
||||
$iPos = 0;
|
||||
$aIndex = $this->m_aIndex;
|
||||
if (($bEditMode) && (count($aIndex) > 0) && $this->m_bModified)
|
||||
@@ -403,20 +417,16 @@ class ormCaseLog {
|
||||
{
|
||||
if (!$bPrintableVersion && ($index < count($aIndex) - CASELOG_VISIBLE_ITEMS))
|
||||
{
|
||||
$sOpen = '';
|
||||
$sDisplay = 'style="display:none;"';
|
||||
$bIsOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOpen = ' open';
|
||||
$sDisplay = '';
|
||||
$bIsOpen = true;
|
||||
}
|
||||
$iPos += $aIndex[$index]['separator_length'];
|
||||
$sTextEntry = substr($this->m_sLog, $iPos, $aIndex[$index]['text_length']);
|
||||
$sCSSClass= 'caselog_entry_html';
|
||||
if (!array_key_exists('format', $aIndex[$index]) || ($aIndex[$index]['format'] == 'text'))
|
||||
{
|
||||
$sCSSClass= 'caselog_entry';
|
||||
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sTextEntry, ENT_QUOTES, 'UTF-8'));
|
||||
if (!is_null($aTransfoHandler))
|
||||
{
|
||||
@@ -433,7 +443,6 @@ class ormCaseLog {
|
||||
}
|
||||
$iPos += $aIndex[$index]['text_length'];
|
||||
|
||||
$sEntry = '<div class="caselog_header'.$sOpen.'">';
|
||||
// Workaround: PHP < 5.3 cannot unserialize correctly DateTime objects,
|
||||
// therefore we have changed the format. To preserve the compatibility with existing
|
||||
// installations of iTop, both format are allowed:
|
||||
@@ -456,14 +465,11 @@ class ormCaseLog {
|
||||
$sDate = '';
|
||||
}
|
||||
}
|
||||
$sEntry .= sprintf(Dict::S('UI:CaseLog:Header_Date_UserName'), $sDate, $aIndex[$index]['user_name']);
|
||||
$sEntry .= '</div>';
|
||||
$sEntry .= '<div class="'.$sCSSClass.'"'.$sDisplay.'>';
|
||||
$sEntry .= $sTextEntry;
|
||||
$sEntry .= '</div>';
|
||||
$sHtml = $sHtml.$sEntry;
|
||||
$oCollapsibleBlock = CollapsibleSectionUIBlockFactory::MakeStandard( sprintf(Dict::S('UI:CaseLog:Header_Date_UserName'), $sDate, $aIndex[$index]['user_name']));
|
||||
$oCollapsibleBlock->AddSubBlock(new Html($sTextEntry));
|
||||
$oCollapsibleBlock->SetOpenedByDefault($bIsOpen);
|
||||
$oBlock->AddSubBlock($oCollapsibleBlock);
|
||||
}
|
||||
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1))
|
||||
{
|
||||
@@ -477,32 +483,38 @@ class ormCaseLog {
|
||||
|
||||
if (count($this->m_aIndex) == 0)
|
||||
{
|
||||
$sHtml .= '<div class="caselog_entry open">';
|
||||
$sHtml .= $sTextEntry;
|
||||
$sHtml .= '</div>';
|
||||
$oCollapsibleBlock = CollapsibleSectionUIBlockFactory::MakeStandard( '');
|
||||
$oCollapsibleBlock->AddSubBlock(new Html($sTextEntry));
|
||||
$oCollapsibleBlock->SetOpenedByDefault(true);
|
||||
$oBlock->AddSubBlock($oCollapsibleBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$bPrintableVersion && (count($this->m_aIndex) - CASELOG_VISIBLE_ITEMS > 0))
|
||||
{
|
||||
$sOpen = '';
|
||||
$sDisplay = 'style="display:none;"';
|
||||
$bIsOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOpen = ' open';
|
||||
$sDisplay = '';
|
||||
$bIsOpen = true;
|
||||
}
|
||||
$sHtml .= '<div class="caselog_header'.$sOpen.'">';
|
||||
$sHtml .= Dict::S('UI:CaseLog:InitialValue');
|
||||
$sHtml .= '</div>';
|
||||
$sHtml .= '<div class="caselog_entry"'.$sDisplay.'>';
|
||||
$sHtml .= $sTextEntry;
|
||||
$sHtml .= '</div>';
|
||||
$oCollapsibleBlock = CollapsibleSectionUIBlockFactory::MakeStandard( Dict::S('UI:CaseLog:InitialValue'));
|
||||
$oCollapsibleBlock->AddSubBlock(new Html($sTextEntry));
|
||||
$oCollapsibleBlock->SetOpenedByDefault($bIsOpen);
|
||||
}
|
||||
}
|
||||
$sHtml .= '</td></tr></table>';
|
||||
return $sHtml;
|
||||
$oBlockRenderer = new BlockRenderer($oBlock);
|
||||
$sHtml = $oBlockRenderer->RenderHtml();
|
||||
$sScript = $oBlockRenderer->RenderJsInlineRecursively($oBlock,iUIBlock::ENUM_JS_TYPE_ON_READY);
|
||||
if ($sScript!=''){
|
||||
if ($oP == null) {
|
||||
$sScript = '<script>'.$sScript.'</script>';
|
||||
$sHtml .= $sScript;
|
||||
} else {
|
||||
$oP->add_ready_script($sScript);
|
||||
}
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,7 +582,6 @@ class ormCaseLog {
|
||||
$this->m_bModified = true;
|
||||
}
|
||||
|
||||
|
||||
public function AddLogEntryFromJSON($oJson, $bCheckUserId = true)
|
||||
{
|
||||
if (isset($oJson->user_id))
|
||||
@@ -647,7 +658,6 @@ class ormCaseLog {
|
||||
$this->m_bModified = true;
|
||||
}
|
||||
|
||||
|
||||
public function GetModifiedEntry($sFormat = 'text')
|
||||
{
|
||||
$sModifiedEntry = '';
|
||||
@@ -726,4 +736,3 @@ class ormCaseLog {
|
||||
return $sText;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -803,6 +803,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
$oLinkSearch = $this->GetFilter();
|
||||
if ($oAttDef->IsIndirect())
|
||||
{
|
||||
$oLinkSearch->RenameAlias($oLinkSearch->GetClassAlias(), self::LINK_ALIAS);
|
||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||
/** @var \AttributeExternalKey $oLinkingAttDef */
|
||||
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
|
||||
@@ -810,12 +811,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
// N°2334 add pointed class (SELECT L,R) to have all fields (lnk + remote) in display
|
||||
// the pointed class is always present in the search, as generated by \AttributeLinkedSet::GetDefaultValue
|
||||
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
||||
$oRemoteClassSearch = new DBObjectSearch($sTargetClass);
|
||||
$oRemoteClassSearch = new DBObjectSearch($sTargetClass, self::REMOTE_ALIAS);
|
||||
|
||||
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
|
||||
{
|
||||
$oNotObsolete = new BinaryExpression(
|
||||
new FieldExpression('obsolescence_flag', $sTargetClass),
|
||||
new FieldExpression('obsolescence_flag', self::REMOTE_ALIAS),
|
||||
'=',
|
||||
new ScalarExpression(0)
|
||||
);
|
||||
@@ -825,7 +826,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass))
|
||||
{
|
||||
$oNotArchived = new BinaryExpression(
|
||||
new FieldExpression('archive_flag', $sTargetClass),
|
||||
new FieldExpression('archive_flag', self::REMOTE_ALIAS),
|
||||
'=',
|
||||
new ScalarExpression(0)
|
||||
);
|
||||
@@ -833,9 +834,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
$oRemoteClassSearch->AddConditionExpression($oNotArchived);
|
||||
}
|
||||
|
||||
$oLinkSearch->AddCondition_PointingTo($oRemoteClassSearch, $sExtKeyToRemote);
|
||||
$oLinkSearch->RenameAlias($oLinkSearch->GetClassAlias(), self::LINK_ALIAS);
|
||||
$oLinkSearch->RenameAlias($sTargetClass, self::REMOTE_ALIAS);
|
||||
$aReAliasingMap = [];
|
||||
$oLinkSearch->AddCondition_PointingTo($oRemoteClassSearch, $sExtKeyToRemote, TREE_OPERATOR_EQUALS, $aReAliasingMap);
|
||||
if (array_key_exists(self::REMOTE_ALIAS, $aReAliasingMap)) {
|
||||
// If 'Remote' alias has been renamed, change it back.
|
||||
if ($aReAliasingMap[self::REMOTE_ALIAS][0] != self::REMOTE_ALIAS) {
|
||||
$oLinkSearch->RenameAlias($aReAliasingMap[self::REMOTE_ALIAS][0], self::REMOTE_ALIAS);
|
||||
}
|
||||
}
|
||||
$oLinkSearch->SetSelectedClasses([self::LINK_ALIAS, self::REMOTE_ALIAS]);
|
||||
}
|
||||
$oLinkSet = new DBObjectSet($oLinkSearch);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
define('UR_ALLOWED_NO', 0);
|
||||
define('UR_ALLOWED_YES', 1);
|
||||
define('UR_ALLOWED_DEPENDS', 2);
|
||||
@@ -318,7 +321,14 @@ abstract class User extends cmdbAbstractObject
|
||||
{
|
||||
if (MetaModel::IsValidAttCode(get_class($this), 'contactid') && ($this->Get('contactid') != 0))
|
||||
{
|
||||
$this->oContactObject = MetaModel::GetObject('Contact', $this->Get('contactid'));
|
||||
$this->oContactObject = null;
|
||||
// The User Contact is generally a Person, so try it first
|
||||
if (MetaModel::IsValidClass('Person')) {
|
||||
$this->oContactObject = MetaModel::GetObject('Person', $this->Get('contactid'), false);
|
||||
}
|
||||
if (is_null($this->oContactObject)) {
|
||||
$this->oContactObject = MetaModel::GetObject('Contact', $this->Get('contactid'));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->oContactObject;
|
||||
@@ -381,9 +391,9 @@ abstract class User extends cmdbAbstractObject
|
||||
if (!in_array(ADMIN_PROFILE_NAME, $aProfiles)) {
|
||||
// Check if the user is yet allowed to modify Users
|
||||
if (method_exists($oAddon, 'ResetCache')) {
|
||||
$aCurrentProfiles = $_SESSION['profile_list'] ?? null;
|
||||
$aCurrentProfiles = Session::Get('profile_list');
|
||||
// Set the current profiles into a session variable (not yet in the database)
|
||||
$_SESSION['profile_list'] = $aProfiles;
|
||||
Session::Set('profile_list', $aProfiles);
|
||||
|
||||
$oAddon->ResetCache();
|
||||
if (!$oAddon->IsActionAllowed($this, 'User', UR_ACTION_MODIFY, null)) {
|
||||
@@ -392,9 +402,9 @@ abstract class User extends cmdbAbstractObject
|
||||
$oAddon->ResetCache();
|
||||
|
||||
if (is_null($aCurrentProfiles)) {
|
||||
unset($_SESSION['profile_list']);
|
||||
Session::IsSet('profile_list');
|
||||
} else {
|
||||
$_SESSION['profile_list'] = $aCurrentProfiles;
|
||||
Session::Set('profile_list', $aCurrentProfiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -840,10 +850,10 @@ class UserRights
|
||||
}
|
||||
self::$m_oUser = $oUser;
|
||||
|
||||
if (isset($_SESSION['impersonate_user']))
|
||||
if (Session::IsSet('impersonate_user'))
|
||||
{
|
||||
self::$m_oRealUser = self::$m_oUser;
|
||||
self::$m_oUser = self::FindUser($_SESSION['impersonate_user']);
|
||||
self::$m_oUser = self::FindUser(Session::Get('impersonate_user'));
|
||||
}
|
||||
|
||||
Dict::SetUserLanguage(self::GetUserLanguage());
|
||||
@@ -947,15 +957,15 @@ class UserRights
|
||||
{
|
||||
$bRet = false;
|
||||
}
|
||||
elseif (isset($_SESSION['archive_allowed']))
|
||||
elseif (Session::IsSet('archive_allowed'))
|
||||
{
|
||||
$bRet = $_SESSION['archive_allowed'];
|
||||
$bRet = Session::Get('archive_allowed');
|
||||
}
|
||||
else
|
||||
{
|
||||
// As of now, anybody can switch to the archive mode as soon as there is an archivable class
|
||||
$bRet = (count(MetaModel::EnumArchivableClasses()) > 0);
|
||||
$_SESSION['archive_allowed'] = $bRet;
|
||||
Session::Set('archive_allowed', $bRet);
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
@@ -1041,7 +1051,7 @@ class UserRights
|
||||
// Do impersonate!
|
||||
self::$m_oUser = $oUser;
|
||||
Dict::SetUserLanguage(self::GetUserLanguage());
|
||||
$_SESSION['impersonate_user'] = $sLogin;
|
||||
Session::Set('impersonate_user', $sLogin);
|
||||
self::_ResetSessionCache();
|
||||
}
|
||||
}
|
||||
@@ -1057,7 +1067,7 @@ class UserRights
|
||||
{
|
||||
self::$m_oUser = self::$m_oRealUser;
|
||||
Dict::SetUserLanguage(self::GetUserLanguage());
|
||||
unset($_SESSION['impersonate_user']);
|
||||
Session::Unset('impersonate_user');
|
||||
self::_ResetSessionCache();
|
||||
}
|
||||
}
|
||||
@@ -1193,17 +1203,26 @@ class UserRights
|
||||
// Then check if the user has a contact attached and if it has an picture defined
|
||||
$sContactId = UserRights::GetContactId($sLogin);
|
||||
if (!empty($sContactId)) {
|
||||
$oContact = MetaModel::GetObject('Contact', $sContactId, false, true);
|
||||
$oContact = null;
|
||||
// Picture if generally for Person, so try it first
|
||||
if (MetaModel::IsValidClass('Person')) {
|
||||
$oContact = MetaModel::GetObject('Person', $sContactId, false, true);
|
||||
}
|
||||
if (is_null($oContact)) {
|
||||
$oContact = MetaModel::GetObject('Contact', $sContactId, false, true);
|
||||
}
|
||||
$sContactClass = get_class($oContact);
|
||||
|
||||
// Check that Contact object still exists and that Contact class has a picture attribute
|
||||
if (!is_null($oContact) && MetaModel::IsValidAttCode($sContactClass, static::DEFAULT_CONTACT_PICTURE_ATTCODE)) {
|
||||
// - Try to get the semantic image attribute, or try to fallback on the default one if none defined
|
||||
$sContactPictureAttCode = MetaModel::HasImageAttributeCode($sContactClass) ? MetaModel::GetImageAttributeCode($sContactClass) : static::DEFAULT_CONTACT_PICTURE_ATTCODE;
|
||||
if (!is_null($oContact) && MetaModel::IsValidAttCode($sContactClass, $sContactPictureAttCode)) {
|
||||
/** @var \ormDocument $oPicture */
|
||||
$oPicture = $oContact->Get(static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||
$oPicture = $oContact->Get($sContactPictureAttCode);
|
||||
if ($oPicture->IsEmpty()) {
|
||||
if ($bAllowDefaultPicture === true) {
|
||||
/** @var \AttributeImage $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sContactClass, static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sContactClass, $sContactPictureAttCode);
|
||||
$sPictureUrl = $oAttDef->Get('default_image');
|
||||
} else {
|
||||
$sPictureUrl = null;
|
||||
@@ -1211,9 +1230,9 @@ class UserRights
|
||||
} else {
|
||||
if (ContextTag::Check(ContextTag::TAG_PORTAL)) {
|
||||
$sSignature = $oPicture->GetSignature();
|
||||
$sPictureUrl = utils::GetAbsoluteUrlAppRoot().'pages/exec.php/object/document/display/'.$sContactClass.'/'.$oContact->GetKey().'/'.static::DEFAULT_CONTACT_PICTURE_ATTCODE.'?cache=86400&s='.$sSignature.'&exec_module=itop-portal-base&exec_page=index.php&portal_id='.PORTAL_ID;
|
||||
$sPictureUrl = utils::GetAbsoluteUrlAppRoot().'pages/exec.php/object/document/display/'.$sContactClass.'/'.$oContact->GetKey().'/'.$sContactPictureAttCode.'?cache=86400&s='.$sSignature.'&exec_module=itop-portal-base&exec_page=index.php&portal_id='.PORTAL_ID;
|
||||
} else {
|
||||
$sPictureUrl = $oPicture->GetDisplayURL($sContactClass, $oContact->GetKey(), static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||
$sPictureUrl = $oPicture->GetDisplayURL($sContactClass, $oContact->GetKey(), $sContactPictureAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1755,9 +1774,9 @@ class UserRights
|
||||
elseif ((self::$m_oUser !== null) && ($oUser->GetKey() == self::$m_oUser->GetKey()))
|
||||
{
|
||||
// Data about the current user can be found into the session data
|
||||
if (array_key_exists('profile_list', $_SESSION))
|
||||
if (Session::IsSet('profile_list'))
|
||||
{
|
||||
$aProfiles = $_SESSION['profile_list'];
|
||||
$aProfiles = Session::Get('profile_list');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1792,11 +1811,6 @@ class UserRights
|
||||
self::$m_aAdmins = array();
|
||||
self::$m_aPortalUsers = array();
|
||||
}
|
||||
if (!isset($_SESSION) && !utils::IsModeCLI())
|
||||
{
|
||||
session_name('itop-'.md5(APPROOT));
|
||||
session_start();
|
||||
}
|
||||
self::_ResetSessionCache();
|
||||
if (self::$m_oAddOn)
|
||||
{
|
||||
@@ -1831,7 +1845,7 @@ class UserRights
|
||||
self::$m_aCacheUsers = array('internal' => array(), 'external' => array());
|
||||
}
|
||||
|
||||
if (!isset(self::$m_aCacheUsers[$sAuthentication][$sLogin]))
|
||||
if (!array_key_exists($sLogin, self::$m_aCacheUsers[$sAuthentication]))
|
||||
{
|
||||
switch($sAuthentication)
|
||||
{
|
||||
@@ -1881,10 +1895,7 @@ class UserRights
|
||||
public static function _InitSessionCache()
|
||||
{
|
||||
// Cache data about the current user into the session
|
||||
if (isset($_SESSION))
|
||||
{
|
||||
$_SESSION['profile_list'] = self::ListProfiles();
|
||||
}
|
||||
Session::Set('profile_list', self::ListProfiles());
|
||||
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$bSessionIdRegeneration = $oConfig->Get('regenerate_session_id_enabled');
|
||||
@@ -1906,14 +1917,8 @@ class UserRights
|
||||
|
||||
public static function _ResetSessionCache()
|
||||
{
|
||||
if (isset($_SESSION['profile_list']))
|
||||
{
|
||||
unset($_SESSION['profile_list']);
|
||||
}
|
||||
if (isset($_SESSION['archive_allowed']))
|
||||
{
|
||||
unset($_SESSION['archive_allowed']);
|
||||
}
|
||||
Session::Unset('profile_list');
|
||||
Session::Unset('archive_allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
require_once('MyHelpers.class.inc.php');
|
||||
|
||||
/**
|
||||
@@ -379,41 +381,35 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
|
||||
$this->m_aValues = array();
|
||||
|
||||
if ($this->m_bAllowAllData)
|
||||
{
|
||||
if ($this->m_bAllowAllData) {
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
} 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');
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
|
||||
switch ($sOperation)
|
||||
{
|
||||
switch ($sOperation) {
|
||||
case 'equals':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains);
|
||||
foreach($aAttributes as $sAttribute)
|
||||
{
|
||||
foreach ($aAttributes as $sAttribute) {
|
||||
$oNewFilter = $oFilter->DeepClone();
|
||||
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||
$oCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr);
|
||||
@@ -425,7 +421,6 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
break;
|
||||
case 'start_with':
|
||||
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$aFilters = array();
|
||||
$oValueExpr = new ScalarExpression($sContains.'%');
|
||||
foreach($aAttributes as $sAttribute)
|
||||
@@ -442,63 +437,67 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
|
||||
default:
|
||||
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
||||
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
||||
$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 = array($oFilter->GetClassAlias() => array('friendlyname'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
|
||||
if (empty($this->m_sValueAttCode)) {
|
||||
$aAttToLoad = ['friendlyname'];
|
||||
} else {
|
||||
$aAttToLoad = [$this->m_sValueAttCode];
|
||||
}
|
||||
|
||||
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($sClass);
|
||||
$sImageAttr = MetaModel::GetImageAttributeCode($sClass);
|
||||
if (!empty($sImageAttr)) {
|
||||
$aAttToLoad [] = $sImageAttr;
|
||||
}
|
||||
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($sClass, FriendlyNameType::COMPLEMENTARY);
|
||||
$sFormatAdditionalField = $aComplementAttributeSpec[0];
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
|
||||
if (count($aAdditionalField)>0)
|
||||
{
|
||||
$aAttToLoad = array_merge ($aAttToLoad, [$oFilter->GetClassAlias() => $aAdditionalField]);
|
||||
if (count($aAdditionalField) > 0) {
|
||||
if (is_array($aAdditionalField)) {
|
||||
$aAttToLoad = array_merge($aAttToLoad, $aAdditionalField);
|
||||
} else {
|
||||
$aAttToLoad [] = $aAdditionalField;
|
||||
}
|
||||
}
|
||||
|
||||
$oObjects->OptimizeColumnLoad($aAttToLoad);
|
||||
while ($oObject = $oObjects->Fetch())
|
||||
{
|
||||
$aData=[];
|
||||
if (empty($this->m_sValueAttCode))
|
||||
{
|
||||
$oObjects->OptimizeColumnLoad([$sClassAlias => $aAttToLoad]);
|
||||
while ($oObject = $oObjects->Fetch()) {
|
||||
$aData = [];
|
||||
if (empty($this->m_sValueAttCode)) {
|
||||
$aData['label'] = $oObject->GetName();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aData['label'] = $oObject->Get($this->m_sValueAttCode);
|
||||
}
|
||||
if($oObject->IsObsolete())
|
||||
{
|
||||
$aData['obsolescence_flag']='1';
|
||||
if ($oObject->IsObsolete()) {
|
||||
$aData['obsolescence_flag'] = '1';
|
||||
} else {
|
||||
$aData['obsolescence_flag'] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['obsolescence_flag']='0';
|
||||
}
|
||||
if (count($aAdditionalField)>0)
|
||||
{
|
||||
if (count($aAdditionalField) > 0) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField)
|
||||
{
|
||||
array_push ($aArguments,$oObject->Get($sAdditionalField));
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
array_push($aArguments, $oObject->Get($sAdditionalField));
|
||||
}
|
||||
$aData['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
||||
} else {
|
||||
$aData['additional_field'] = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['additional_field']='';
|
||||
if (!empty($sImageAttr)) {
|
||||
/** @var \ormDocument $oImage */
|
||||
$oImage = $oObject->Get($sImageAttr);
|
||||
if (!$oImage->IsEmpty()) {
|
||||
$aData['picture_url'] = $oImage->GetDisplayURL($sClass, $oObject->GetKey(), $sImageAttr);
|
||||
$aData['initials'] = '';
|
||||
} else {
|
||||
$aData['initials'] = utils::ToAcronym($aData['label']);
|
||||
}
|
||||
}
|
||||
$this->m_aValues[$oObject->GetKey()] = $aData;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
//==========================================================================
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "display-block/all";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-block-csv--textarea--width: 100% !default;
|
||||
$ibo-block-csv--textarea--min-height: 10em !default;
|
||||
$ibo-block-csv--textarea--margin-top: 10px !default;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "tabular-fields-selector";
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "base";
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-scrollbar--scrollbar-width: 8px !default;
|
||||
$ibo-scrollbar--scrollbar-height: $ibo-scrollbar--scrollbar-width !default; /* For horizontal scrollbars */
|
||||
$ibo-scrollbar--scrollbar-track-background-color: $ibo-color-transparent !default;
|
||||
$ibo-scrollbar--scrollbar-track-border-radius: $ibo-border-radius-500 !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-background-color: $ibo-color-grey-300 !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-border: none !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-border-radius: $ibo-border-radius-500 !default;
|
||||
@@ -37,6 +25,7 @@ $ibo-content-block--border: 1px solid $ibo-color-grey-400 !default;
|
||||
--ibo-scrollbar--scrollbar-width: #{$ibo-scrollbar--scrollbar-width};
|
||||
--ibo-scrollbar--scrollbar-height: #{$ibo-scrollbar--scrollbar-height};
|
||||
--ibo-scrollbar--scrollbar-track-background-color: #{$ibo-scrollbar--scrollbar-track-background-color};
|
||||
--ibo-scrollbar--scrollbar-track-border-radius: #{$ibo-scrollbar--scrollbar-track-border-radius};
|
||||
--ibo-scrollbar--scrollbar-thumb-background-color: #{$ibo-scrollbar--scrollbar-thumb-background-color};
|
||||
--ibo-scrollbar--scrollbar-thumb-border: #{$ibo-scrollbar--scrollbar-thumb-border};
|
||||
--ibo-scrollbar--scrollbar-thumb-border-radius: #{$ibo-scrollbar--scrollbar-thumb-border-radius};
|
||||
@@ -66,6 +55,7 @@ $ibo-content-block--border: 1px solid $ibo-color-grey-400 !default;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: var(--ibo-scrollbar--scrollbar-track-background-color);
|
||||
border-radius: var(--ibo-scrollbar--scrollbar-track-border-radius);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--ibo-scrollbar--scrollbar-thumb-background-color);
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* This is an overload of the default lib. stylesheet to use local fonts instead of the CDN */
|
||||
@@ -21,125 +8,143 @@
|
||||
font-family: Raleway;
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway Thin'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Thin.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-100-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 100;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway Thin'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Thin-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-100-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway ExtraLight'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-ExtraLight.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-200-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 200;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway ExtraLight'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-ExtraLight-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-200-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway Light'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Light.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-300-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway Light'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Light-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-300-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Regular.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-400-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Regular-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-400-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway Medium'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Medium.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-500-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway Medium'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Medium-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-500-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway SemiBold'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-SemiBold.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-600-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway SemiBold'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-SemiBold-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-600-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Bold.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-700-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Bold-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-700-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway ExtraBold'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-ExtraBold.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-800-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway ExtraBold'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-ExtraBold-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-800-italic.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: local('Raleway Black'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Black.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-900-normal.woff') format('woff'),
|
||||
}
|
||||
@font-face {
|
||||
font-family: Raleway;
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
src: local('Raleway Black'),
|
||||
url($approot-relative + 'node_modules/raleway-webfont/fonts/Raleway-Black-Italic.ttf') format('truetype'),
|
||||
url($approot-relative + 'node_modules/@fontsource/raleway/files/raleway-all-900-italic.woff') format('woff'),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -13,5 +13,7 @@
|
||||
@import "object-details-with-tab-container";
|
||||
@import "medallion-with-blocklist";
|
||||
@import "input-within-datatable";
|
||||
@import "field-badge-within-datatable";
|
||||
@import "jquery-blockui-within-dialog";
|
||||
@import "jquery-blockui-within-datatable";
|
||||
@import "jquery-blockui-within-datatable";
|
||||
@import "collapsible-section-within-caselog-list";
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
$ibo-caselog-entry-in-collapsible-section--body--background-color: transparentize($ibo-color-grey-100,0.5) !default;
|
||||
$ibo-caselog-entry-in-collapsible-section--body--padding: 8px !default;
|
||||
$ibo-caselog-entry-in-collapsible-section--body--color: $ibo-color-grey-900 !default;
|
||||
|
||||
/* - caselog display in ormcaselog */
|
||||
.ibo-caselog-list {
|
||||
.ibo-collapsible-section {
|
||||
margin: 0;
|
||||
min-width: 22em;
|
||||
|
||||
.ibo-collapsible-section--header .ibo-collapsible-section--title {
|
||||
@extend %ibo-font-size-100;
|
||||
}
|
||||
|
||||
.ibo-collapsible-section--body {
|
||||
@extend %ibo-font-size-100;
|
||||
color: $ibo-caselog-entry-in-collapsible-section--body--color;
|
||||
padding: $ibo-caselog-entry-in-collapsible-section--body--padding;
|
||||
background-color: $ibo-caselog-entry-in-collapsible-section--body--background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge--margin: 0 !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge--padding: 0 !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge--text-color: unset !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge--background-color: unset !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge-dot--size: 10px !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge-dot--spacing-x: $ibo-field-badge--label--spacing-x !default;
|
||||
$ibo-field-badge-within-datatable--ibo-field-badge-dot--background-color: $ibo-color-white-100 !default;
|
||||
|
||||
.ibo-datatable {
|
||||
.ibo-field-badge {
|
||||
margin: $ibo-field-badge-within-datatable--ibo-field-badge--margin;
|
||||
padding: $ibo-field-badge-within-datatable--ibo-field-badge--padding;
|
||||
color: $ibo-field-badge-within-datatable--ibo-field-badge--text-color;
|
||||
background-color: $ibo-field-badge-within-datatable--ibo-field-badge--background-color;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-flex;
|
||||
margin-right: $ibo-field-badge-within-datatable--ibo-field-badge-dot--spacing-x;
|
||||
width: $ibo-field-badge-within-datatable--ibo-field-badge-dot--size;
|
||||
height: $ibo-field-badge-within-datatable--ibo-field-badge-dot--size;
|
||||
min-width: $ibo-field-badge-within-datatable--ibo-field-badge-dot--size;
|
||||
min-height: $ibo-field-badge-within-datatable--ibo-field-badge-dot--size;
|
||||
background-color: var(--ibo-main-color);
|
||||
@extend %ibo-border-radius-full;
|
||||
}
|
||||
|
||||
.ibo-field-badge--decoration {
|
||||
display: none;
|
||||
+ .ibo-field-badge--label {
|
||||
margin-left: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-input-within-datatable--attribute-set-item--padding-x: $ibo-input-set--item--padding-x !default;
|
||||
$ibo-input-within-datatable--attribute-set-item--box-shadow: $ibo-elevation-100 !default;
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-vendors-blockui--blockoverlay--within--datatable--background-color: $ibo-color-white-100 !default;
|
||||
|
||||
.ibo-datatable .blockUI.blockOverlay{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-vendors-blockui--blockoverlay--within--dialog--background-color: $ibo-vendors-jqueryui--ui-dialog--background-color !default;
|
||||
|
||||
.ui-dialog .blockUI.blockOverlay{
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
.ibo-block-list--medallion{
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
.ibo-panel .ibo-panel--body{
|
||||
.ibo-datatable{
|
||||
width: 100%
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-panel-within-main-content--margin-bottom: 200px !default;
|
||||
|
||||
$ibo-panel-within-main-content--sticky-sentinel-top--top: -1 * $ibo-main-content--padding-top !default;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "alert";
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-breadcrumbs--margin-right: 32px !default;
|
||||
|
||||
$ibo-breadcrumbs--item--text-color: $ibo-color-grey-800 !default;
|
||||
|
||||
$ibo-breadcrumbs--item-icon--margin-x: 8px !default;
|
||||
@@ -27,8 +16,26 @@ $ibo-breadcrumbs--item-label--max-width: 100px !default;
|
||||
$ibo-breadcrumbs--item-separator--margin-x: 12px !default;
|
||||
$ibo-breadcrumbs--item-separator--text-color: $ibo-color-grey-500 !default;
|
||||
|
||||
$ibo-breadcrumbs--previous-items-list-toggler--text-color: $ibo-color-grey-700 !default;
|
||||
$ibo-breadcrumbs--previous-items-list-toggler--margin-right: 2 * $ibo-breadcrumbs--item-separator--margin-x !default;
|
||||
|
||||
$ibo-breadcrumbs--previous-items-list--top: 37px !default;
|
||||
$ibo-breadcrumbs--previous-items-list--padding-y: 8px !default;
|
||||
$ibo-breadcrumbs--previous-items-list--background-color: $ibo-color-white-100 !default;
|
||||
|
||||
$ibo-breadcrumbs--previous-item--text-color: $ibo-breadcrumbs--item--text-color !default;
|
||||
$ibo-breadcrumbs--previous-item--padding-x: 12px !default;
|
||||
$ibo-breadcrumbs--previous-item--padding-y: 12px !default;
|
||||
$ibo-breadcrumbs--previous-item-label--max-width: 200px !default;
|
||||
|
||||
.ibo-breadcrumbs{
|
||||
@extend %ibo-full-height-content;
|
||||
position: relative;
|
||||
margin-right: $ibo-breadcrumbs--margin-right;
|
||||
@extend %ibo-full-height-content;
|
||||
|
||||
&.ibo-is-overflowing {
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
* {
|
||||
display: flex;
|
||||
@@ -40,13 +47,6 @@ $ibo-breadcrumbs--item-separator--text-color: $ibo-color-grey-500 !default;
|
||||
@extend %ibo-font-ral-med-100;
|
||||
|
||||
&:not(:last-child){
|
||||
&::after{
|
||||
content: '\f054';
|
||||
margin: 0 $ibo-breadcrumbs--item-separator--margin-x;
|
||||
color: $ibo-breadcrumbs--item-separator--text-color;
|
||||
@extend %fa-solid-base;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
.ibo-breadcrumbs--item-icon{
|
||||
> *{
|
||||
@@ -78,3 +78,50 @@ $ibo-breadcrumbs--item-separator--text-color: $ibo-color-grey-500 !default;
|
||||
max-width: $ibo-breadcrumbs--item-label--max-width;
|
||||
@extend %ibo-text-truncated-with-ellipsis;
|
||||
}
|
||||
|
||||
.ibo-breadcrumbs--item,
|
||||
.ibo-breadcrumbs--previous-items-list-toggler {
|
||||
&:not(:last-child){
|
||||
&::after{
|
||||
content: '\f054';
|
||||
margin: 0 $ibo-breadcrumbs--item-separator--margin-x;
|
||||
color: $ibo-breadcrumbs--item-separator--text-color;
|
||||
@extend %fa-solid-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-breadcrumbs--previous-items-list-toggler {
|
||||
margin-right: $ibo-breadcrumbs--previous-items-list-toggler--margin-right;
|
||||
color: $ibo-breadcrumbs--previous-items-list-toggler--text-color !important;
|
||||
@extend %ibo-font-ral-med-100;
|
||||
|
||||
&:not(:last-child) {
|
||||
&::after {
|
||||
position: absolute; /* To be outside of the button */
|
||||
right: -1 * $ibo-breadcrumbs--previous-items-list-toggler--margin-right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ibo-breadcrumbs--previous-items-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch; /* For the items to occupy the full width */
|
||||
|
||||
position: fixed;
|
||||
top: $ibo-breadcrumbs--previous-items-list--top;
|
||||
padding: $ibo-breadcrumbs--previous-items-list--padding-y 0;
|
||||
|
||||
background-color: $ibo-breadcrumbs--previous-items-list--background-color;
|
||||
@extend %ibo-elevation-300;
|
||||
}
|
||||
|
||||
.ibo-breadcrumbs--previous-item {
|
||||
color: $ibo-breadcrumbs--previous-item--text-color;
|
||||
@extend %ibo-font-ral-med-100;
|
||||
padding: $ibo-breadcrumbs--previous-item--padding-y $ibo-breadcrumbs--previous-item--padding-x;
|
||||
|
||||
.ibo-breadcrumbs--item-label {
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -13,6 +13,9 @@ $ibo-button-group--elements-separator--width: 1px !default;
|
||||
$ibo-button-group--elements-separator--border-left: 1px solid transparent !default;
|
||||
|
||||
.ibo-button-group {
|
||||
display: inline-flex; /* Ensure that buttons of a same group always stay on the same line */
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.ibo-button {
|
||||
position: relative;
|
||||
}
|
||||
@@ -45,8 +48,10 @@ $ibo-button-group--elements-separator--border-left: 1px solid transparent !defau
|
||||
border-left: $ibo-button-group--elements-separator--border-left;
|
||||
}
|
||||
|
||||
/* Note: Selector cannot be simplified in the one above as the "::before" must be after the different classes */
|
||||
.ibo-button + .ibo-button {
|
||||
/* Note: Selector cannot be simplified in the one above as the "::before" must be after the different classes.
|
||||
* A more precise selector could be .ibo-button + .ibo-button, however .ibo-button is extended by multiple element and in a multiple loop it creates heavy selectors.
|
||||
*/
|
||||
> * + * {
|
||||
@each $sType, $aColors in $ibo-button-colors {
|
||||
@each $sColor, $aPseudoclasses in $aColors {
|
||||
@each $sPseudoclass, $aAttributes in $aPseudoclasses {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-button--sibling-spacing: 5px !default;
|
||||
$ibo-button--padding-y: 6px !default;
|
||||
$ibo-button--padding-x: 9px !default;
|
||||
@@ -461,6 +466,7 @@ $ibo-button-colors: (
|
||||
}
|
||||
|
||||
.ibo-button {
|
||||
position: relative;
|
||||
display: inline-block; /* Used to allow truncated text on .ibo-button--label */
|
||||
padding: $ibo-button--padding-y $ibo-button--padding-x;
|
||||
border: $ibo-button--border;
|
||||
@@ -470,7 +476,7 @@ $ibo-button-colors: (
|
||||
white-space: nowrap; /* To force sub elements to be on 1 line */
|
||||
@extend %ibo-font-ral-sembol-100;
|
||||
|
||||
& ~ .ibo-button {
|
||||
& + .ibo-button {
|
||||
margin-left: $ibo-button--sibling-spacing;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -77,11 +77,6 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ibo-datatable .ibo-field-badge {
|
||||
margin: 0;
|
||||
padding: 0px 4px;
|
||||
}
|
||||
|
||||
// Datatables configure this list dialog
|
||||
// Could be in a separate component, but is only used in datatables as of now
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-field-badge--margin: 0 !default;
|
||||
@@ -10,10 +10,15 @@ $ibo-field-badge--border-radius: $ibo-border-radius-300 !default;
|
||||
$ibo-field-badge--label--spacing-x: 0.5rem !default;
|
||||
|
||||
.ibo-field-badge {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
margin: $ibo-field-badge--margin;
|
||||
padding: $ibo-field-badge--padding;
|
||||
border-radius: $ibo-field-badge--border-radius;
|
||||
display: inline;
|
||||
|
||||
/* Mind the use of these "generic" variables that allow to automatically use the right colors for a field and its value depending on which class will be append to it (see those defined in the DM) */
|
||||
background-color: var(--ibo-main-color);
|
||||
color: var(--ibo-complementary-color);
|
||||
}
|
||||
|
||||
.ibo-field-badge--decoration + .ibo-field-badge--label {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -23,12 +23,21 @@ $ibo-field--fullscreen-toggler--size: 20px !default;
|
||||
$ibo-field--fullscreen-toggler--border-radius: $ibo-border-radius-500 !default;
|
||||
$ibo-field--fullscreen-toggler--background-color--on-hover: $ibo-color-white-200 !default;
|
||||
|
||||
$ibo-field--value--scrollbar-track-background-color: $ibo-color-white-200 !default;
|
||||
$ibo-field--value--padding-x--is-fullscreen: $ibo-field--label--padding-x--is-fullscreen !default;
|
||||
$ibo-field--value--padding-top--is-fullscreen: $ibo-field--label--padding-y--is-fullscreen + 32px !default;
|
||||
$ibo-field--value--padding-bottom--is-fullscreen: $ibo-field--label--padding-y--is-fullscreen !default;
|
||||
|
||||
$ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
|
||||
$ibo-field--enable-bulk--padding-y: 2px !default;
|
||||
$ibo-field--enable-bulk--padding-x: 5px !default;
|
||||
$ibo-field--enable-bulk--margin-left: 5px !default;
|
||||
$ibo-field--enable-bulk--height: calc(100% - #{$ibo-field--enable-bulk--padding-x}) !default;
|
||||
$ibo-field--enable-bulk--border-radius: $ibo-border-radius-500 !default;
|
||||
|
||||
$ibo-field--enable-bulk--checkbox--margin-left: 8px !default;
|
||||
|
||||
/* SCSS rules */
|
||||
.ibo-field {
|
||||
@extend %ibo-font-size-150;
|
||||
@@ -36,11 +45,18 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
/* Avoid value to overflow from its container with very long strings (typically URLs) */
|
||||
/* Note: Some types of attribute must be excluding as it can alter their rendering */
|
||||
&:not([data-attribute-type="AttributeBlob"]):not([data-attribute-type="AttributeFile"]):not([data-attribute-type="AttributeImage"]):not([data-attribute-type="AttributeCustomFields"]):not(.ibo-input-file-select--container) {
|
||||
/* We need the rule to apply for the class and all its descendants */
|
||||
/* We need the rule to apply for the class and all its descendants, hence the "&, & *" */
|
||||
.ibo-field--value {
|
||||
* {
|
||||
&, & * {
|
||||
word-break: break-word;
|
||||
white-space: pre-line;
|
||||
white-space: inherit; /* Here we don't put break-spaces as it would put ".ibo-field-small .ibo-field-value" on a new line due to the spaces/indentation of the HTML templates. For now we rather have this rule than diminish the templates readability/maintenability */
|
||||
}
|
||||
}
|
||||
&.ibo-field-large {
|
||||
.ibo-field--value {
|
||||
&, & * {
|
||||
white-space: break-spaces; /* For large fields we don't have the issue stated above */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +73,6 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
.ibo-field--label {
|
||||
position: relative; /* Necessary for fullscreen toggler */
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: initial;
|
||||
width: 100%;
|
||||
@@ -73,6 +88,11 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
/* N°4318 - Visible scrollbar background for large fields overflowing to ease "limits" visualization by the user */
|
||||
.ibo-field--value > * {
|
||||
--ibo-scrollbar--scrollbar-track-background-color: $ibo-field--value--scrollbar-track-background-color;
|
||||
}
|
||||
|
||||
/* Fullscreen mode */
|
||||
&.ibo-is-fullscreen {
|
||||
background-color: $ibo-field--background-color--is-fullscreen;
|
||||
@@ -113,7 +133,7 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
|
||||
@extend %ibo-hyperlink-inherited-colors;
|
||||
@extend %ibo-fully-centered-content;
|
||||
@extend %ibo-font-size-100;
|
||||
@extend %ibo-font-size-50;
|
||||
|
||||
&:hover {
|
||||
background-color: $ibo-field--fullscreen-toggler--background-color--on-hover;
|
||||
@@ -138,6 +158,9 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ibo-field--label-small .ibo-field--label{
|
||||
width: 20em;
|
||||
}
|
||||
.ibo-field--value {
|
||||
display: table;
|
||||
width: 100%;
|
||||
@@ -155,14 +178,13 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
.ibo-field--comments {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding-right: 10px;
|
||||
|
||||
> input[type="checkbox"] {
|
||||
margin-left: 5px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
> .multi_values, > .mono_value {
|
||||
> .multi_values, > .mono_value, > .ibo-field--comments--synchro{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
@@ -187,23 +209,18 @@ $ibo-field--value-decoration--spacing-x: 0.5rem !default;
|
||||
}
|
||||
}
|
||||
|
||||
.multi_values, .mono_value {
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
margin-left: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
.ibo-field--enable-bulk, .ibo-field--comments--synchro {
|
||||
display: inline;
|
||||
padding: $ibo-field--enable-bulk--padding-y $ibo-field--enable-bulk--padding-x;
|
||||
margin: 0 0 0 $ibo-field--enable-bulk--margin-left;
|
||||
height: $ibo-field--enable-bulk--height;
|
||||
border-radius: $ibo-field--enable-bulk--border-radius;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mono_value {
|
||||
background-color: #3c3;
|
||||
}
|
||||
|
||||
.multi_values {
|
||||
background-color: #c33;
|
||||
.ibo-field--enable-bulk--checkbox {
|
||||
margin-left: $ibo-field--enable-bulk--checkbox--margin-left;
|
||||
}
|
||||
|
||||
.form_field ~ .form_field {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-fieldset--sibling-spacing: 48px !default;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-input-file-select--file-name-margin-left: 10px !default;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
.ibo-prop-header {
|
||||
@extend %ibo-font-size-150;
|
||||
padding-bottom: 14px;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-medallion-icon--padding-y: 13px !default;
|
||||
$ibo-medallion-icon--padding-x: 0 !default;
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
@@ -32,11 +19,31 @@ $ibo-panel--base-transition: $ibo-panel--base-transition-property $ibo-panel--ba
|
||||
transition: $ibo-panel--base-transition;
|
||||
}
|
||||
|
||||
$ibo-panel-colors: (
|
||||
'primary': $ibo-color-primary-600,
|
||||
'secondary': $ibo-color-secondary-600,
|
||||
'neutral': $ibo-color-grey-600,
|
||||
'information': $ibo-color-information-600,
|
||||
'success': $ibo-color-success-600,
|
||||
'failure': $ibo-color-danger-600,
|
||||
'warning': $ibo-color-warning-600,
|
||||
'danger': $ibo-color-danger-600,
|
||||
'grey' : $ibo-color-grey-600,
|
||||
'blue-grey': $ibo-color-blue-grey-600,
|
||||
'blue': $ibo-color-blue-800,
|
||||
'cyan': $ibo-color-cyan-600,
|
||||
'green': $ibo-color-green-600,
|
||||
'orange' : $ibo-color-orange-600,
|
||||
'red': $ibo-color-red-600,
|
||||
'pink': $ibo-color-pink-600,
|
||||
) !default;
|
||||
|
||||
/* - Specific variables for the block */
|
||||
$ibo-panel--spacing-top: 24px !default;
|
||||
|
||||
$ibo-panel--highlight--width: 100% !default;
|
||||
$ibo-panel--highlight--height: 8px !default;
|
||||
$ibo-panel--highlight--background-color: 8px !default;
|
||||
$ibo-panel--highlight--border-radius: $ibo-border-radius-400 $ibo-border-radius-400 0 0 !default;
|
||||
$ibo-panel--highlight--padding-bottom: $ibo-panel--highlight--height !default;
|
||||
|
||||
@@ -81,47 +88,14 @@ $ibo-panel--collapsible-toggler--margin-right: 8px !default;
|
||||
$ibo-panel--collapsible-toggler--font-size: $ibo-font-size-250 !default;
|
||||
$ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
|
||||
|
||||
$ibo-panel-colors: (
|
||||
'primary': $ibo-color-primary-600,
|
||||
'secondary': $ibo-color-secondary-600,
|
||||
'neutral': $ibo-color-grey-600,
|
||||
'information': $ibo-color-information-600,
|
||||
'success': $ibo-color-success-600,
|
||||
'failure': $ibo-color-danger-600,
|
||||
'warning': $ibo-color-warning-600,
|
||||
'danger': $ibo-color-danger-600,
|
||||
'grey' : $ibo-color-grey-600,
|
||||
'blue-grey': $ibo-color-blue-grey-600,
|
||||
'blue': $ibo-color-blue-800,
|
||||
'cyan': $ibo-color-cyan-600,
|
||||
'green': $ibo-color-green-600,
|
||||
'orange' : $ibo-color-orange-600,
|
||||
'red': $ibo-color-red-600,
|
||||
'pink': $ibo-color-pink-600,
|
||||
) !default;
|
||||
|
||||
@each $sColor, $sColorValue in $ibo-panel-colors {
|
||||
.ibo-panel.ibo-is-#{$sColor} > .ibo-panel--body::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
|
||||
background-color: $sColorValue;
|
||||
content: "";
|
||||
|
||||
width: $ibo-panel--highlight--width;
|
||||
height: $ibo-panel--highlight--height;
|
||||
padding-bottom: $ibo-panel--highlight--padding-bottom;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rules */
|
||||
.ibo-panel + .ibo-panel {
|
||||
margin-top: $ibo-panel--spacing-top;
|
||||
}
|
||||
|
||||
.ibo-panel {
|
||||
--ibo-main-color: map-get($ibo-panel-colors, 'neutral'); /* --ibo-main-color is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
|
||||
|
||||
position: relative;
|
||||
|
||||
&.ibo-has-icon {
|
||||
@@ -227,6 +201,26 @@ $ibo-panel-colors: (
|
||||
overflow: hidden; /* To force highlight color to be cropped by the border radius */
|
||||
|
||||
@extend %ibo-font-size-150;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
|
||||
background-color: var(--ibo-main-color); /* Default value defined in .ibo-panel, can be overloaded by custom CSS classes */
|
||||
content: "";
|
||||
|
||||
width: $ibo-panel--highlight--width;
|
||||
height: $ibo-panel--highlight--height;
|
||||
padding-bottom: $ibo-panel--highlight--padding-bottom;
|
||||
}
|
||||
}
|
||||
|
||||
@each $sColor, $sColorValue in $ibo-panel-colors {
|
||||
.ibo-panel.ibo-is-#{$sColor} > .ibo-panel--body::before {
|
||||
background-color: $sColorValue;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-panel--collapsible-toggler {
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
@@ -91,9 +78,20 @@ $ibo-pill-states-colors: (
|
||||
|
||||
/* Rules */
|
||||
.ibo-pill {
|
||||
/* --ibo-main-color-xxx is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
|
||||
--ibo-main-color--100: map-get(map-get($ibo-pill-states-colors, 'neutral'), 'primary-color');
|
||||
--ibo-main-color--900: map-get(map-get($ibo-pill-states-colors, 'neutral'), 'secondary-color');
|
||||
|
||||
@extend %ibo-fully-centered-content;
|
||||
max-width: $ibo-pill--max-width;
|
||||
margin: $ibo-pill--margin;
|
||||
padding: $ibo-pill--padding;
|
||||
border-radius: $ibo-pill--border-radius;
|
||||
|
||||
color: var(--ibo-main-color--900);
|
||||
background-color: var(--ibo-main-color--100);
|
||||
|
||||
&:hover, &:active {
|
||||
color: inherit; /* Force color to stay as defined in pill instead of being overloaded by anchor's rules */
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-prop--apply--padding-left: 12px !default;
|
||||
$ibo-prop--cancel--padding-left: 7px !default;
|
||||
|
||||
@@ -13,9 +18,6 @@ $ibo-prop--apply--error--color: $ibo-color-grey-800 !default;
|
||||
.ibo-prop--apply{
|
||||
width: $ibo-prop--apply--width;
|
||||
padding-left: $ibo-prop--apply--padding-left;
|
||||
> span{
|
||||
@extend .ibo-is-green;
|
||||
}
|
||||
&.ui-state-error{
|
||||
&:after {
|
||||
color: $ibo-prop--apply--error--color;
|
||||
@@ -31,9 +33,6 @@ $ibo-prop--apply--error--color: $ibo-color-grey-800 !default;
|
||||
.ibo-prop--cancel{
|
||||
width: $ibo-prop--cancel--width;
|
||||
padding-left: $ibo-prop--cancel--padding-left;
|
||||
> span{
|
||||
@extend .ibo-is-red;
|
||||
}
|
||||
}
|
||||
.ibo-prop--apply, .ibo-prop--cancel{
|
||||
height: $ibo-prop--apply-cancel--height;
|
||||
@@ -42,5 +41,9 @@ $ibo-prop--apply--error--color: $ibo-color-grey-800 !default;
|
||||
height: $ibo-prop--apply-cancel--span--height;
|
||||
width: $ibo-prop--apply-cancel--span--width;
|
||||
text-align: center;
|
||||
> div{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
@@ -894,25 +894,23 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
}
|
||||
.sf_results_area {
|
||||
.ibo-datatable-panel.ibo-is-sticking {
|
||||
.ibo-panel--header {
|
||||
z-index: 0;
|
||||
}
|
||||
.ibo-datatable--toolbar {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
padding-bottom: 4px;
|
||||
background-color: $ibo-search-results-area--datatable-toolbar--background-color--is-sticking;
|
||||
border-left: $ibo-search-results-area--datatable-toolbar--border--is-sticking;
|
||||
border-right: $ibo-search-results-area--datatable-toolbar--border--is-sticking;
|
||||
}
|
||||
.dataTables_scrollHead {
|
||||
position: fixed !important; /* Important is required as the property is already set in the style attribute by the JS lib */
|
||||
z-index: 2;
|
||||
background-color: $ibo-search-results-area--datatable-scrollhead--background-color--is-sticking;
|
||||
border-left: $ibo-search-results-area--datatable-scrollhead--border--is-sticking !important; /* Unfortunately the !important is necessary to overload the lib style attribute */
|
||||
border-right: $ibo-search-results-area--datatable-scrollhead--border--is-sticking !important; /* Unfortunately the !important is necessary to overload the lib style attribute */
|
||||
}
|
||||
.ibo-datatable-panel.ibo-is-sticking {
|
||||
.ibo-panel--header {
|
||||
z-index: 0;
|
||||
}
|
||||
.ibo-datatable--toolbar {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
padding-bottom: 4px;
|
||||
background-color: $ibo-search-results-area--datatable-toolbar--background-color--is-sticking;
|
||||
border-left: $ibo-search-results-area--datatable-toolbar--border--is-sticking;
|
||||
border-right: $ibo-search-results-area--datatable-toolbar--border--is-sticking;
|
||||
}
|
||||
.dataTables_scrollHead {
|
||||
position: fixed !important; /* Important is required as the property is already set in the style attribute by the JS lib */
|
||||
z-index: 2;
|
||||
background-color: $ibo-search-results-area--datatable-scrollhead--background-color--is-sticking;
|
||||
border-left: $ibo-search-results-area--datatable-scrollhead--border--is-sticking !important; /* Unfortunately the !important is necessary to overload the lib style attribute */
|
||||
border-right: $ibo-search-results-area--datatable-scrollhead--border--is-sticking !important; /* Unfortunately the !important is necessary to overload the lib style attribute */
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* license http://opensource.org/licenses/AGPL-3.0
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-title--text-color: $ibo-color-grey-900 !default;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user