mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-16 22:44:13 +01:00
Compare commits
189 Commits
feature/70
...
faf/improv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
470ccd72f5 | ||
|
|
2d5cd7042a | ||
|
|
7b01108c91 | ||
|
|
3b9ca4ad18 | ||
|
|
59129bc3ce | ||
|
|
eddc750ca8 | ||
|
|
f3abe1ff13 | ||
|
|
473cf004b6 | ||
|
|
90a5a7a9a7 | ||
|
|
5574952033 | ||
|
|
1a8de82be5 | ||
|
|
d15a0a0070 | ||
|
|
76167a3d54 | ||
|
|
46273dfc12 | ||
|
|
24f1cf8ca1 | ||
|
|
2a5337d84c | ||
|
|
fbe7f559d2 | ||
|
|
c8810708ef | ||
|
|
e8c11f38d2 | ||
|
|
1394bc221d | ||
|
|
baa05ba8d4 | ||
|
|
e7b493dafa | ||
|
|
940833a66f | ||
|
|
2b172d6e19 | ||
|
|
69677954b4 | ||
|
|
9c35cddfc0 | ||
|
|
86bf6ba0b0 | ||
|
|
82e19f6eca | ||
|
|
8f1d8b1dc2 | ||
|
|
b67057c863 | ||
|
|
0546a7b82b | ||
|
|
3d360e99da | ||
|
|
3cc3f0e4ff | ||
|
|
b6230ed486 | ||
|
|
123dfd8dd3 | ||
|
|
e9bd76f2cd | ||
|
|
47f7dfeb47 | ||
|
|
405919f204 | ||
|
|
b7f43ba22b | ||
|
|
b813a32225 | ||
|
|
b13e0c92a5 | ||
|
|
a6e5f95ff4 | ||
|
|
2e5f0b064c | ||
|
|
a9f6e86381 | ||
|
|
c6548ace61 | ||
|
|
aa81c94dad | ||
|
|
478afb88e3 | ||
|
|
7c17957ec7 | ||
|
|
ba0a585256 | ||
|
|
f41f2a063d | ||
|
|
d7e9ae1a77 | ||
|
|
dd6a138ea1 | ||
|
|
b6caa51552 | ||
|
|
8a67ceff57 | ||
|
|
095c94a917 | ||
|
|
102a4a0c75 | ||
|
|
f6fec506b1 | ||
|
|
829d82dfe3 | ||
|
|
5fdf8d7687 | ||
|
|
1ddf8b419a | ||
|
|
7d0801f74f | ||
|
|
3b9f281afd | ||
|
|
c718fcf176 | ||
|
|
bcba666483 | ||
|
|
ec465174f7 | ||
|
|
2982911df7 | ||
|
|
9f675fef02 | ||
|
|
c7cb7c0b68 | ||
|
|
68f229f91c | ||
|
|
1d106eb33a | ||
|
|
31bd763b90 | ||
|
|
5c12151c26 | ||
|
|
ceba1ad1e9 | ||
|
|
efe5f004a1 | ||
|
|
b716a3965c | ||
|
|
15fa495458 | ||
|
|
1dfb2e0a1a | ||
|
|
d775658980 | ||
|
|
2bd40bef47 | ||
|
|
961315cf34 | ||
|
|
67d43c19ec | ||
|
|
2695aeb64b | ||
|
|
95fef002a6 | ||
|
|
9777ac1a5c | ||
|
|
9e24447835 | ||
|
|
296250b20f | ||
|
|
38601bf0cf | ||
|
|
9f46aad80a | ||
|
|
ba0020fa63 | ||
|
|
1e83f2eb60 | ||
|
|
dd27a3ebb4 | ||
|
|
54439ad529 | ||
|
|
a492f7a664 | ||
|
|
85a49262e9 | ||
|
|
2c61ac4949 | ||
|
|
8f7bf00551 | ||
|
|
0483cea226 | ||
|
|
922a842e96 | ||
|
|
955d04252e | ||
|
|
95c4a93f2e | ||
|
|
e4f068a518 | ||
|
|
c020de59a7 | ||
|
|
85dac470aa | ||
|
|
3c2350961d | ||
|
|
391c78ae42 | ||
|
|
aa53de467d | ||
|
|
bc6efc99ed | ||
|
|
bb3ab76205 | ||
|
|
0b1bdfff55 | ||
|
|
77c0cdf5aa | ||
|
|
af9fb74c54 | ||
|
|
5d6c4939f6 | ||
|
|
41eb927480 | ||
|
|
5663c61e51 | ||
|
|
bec5e250a5 | ||
|
|
51d0d16a11 | ||
|
|
9fe45e9472 | ||
|
|
78133418d7 | ||
|
|
8275de8fa7 | ||
|
|
ba7c154e84 | ||
|
|
d2b0140fa4 | ||
|
|
5c4ba74237 | ||
|
|
848528567e | ||
|
|
b0634c9fbc | ||
|
|
7f4b50ca7f | ||
|
|
fabeea8dba | ||
|
|
c951a33646 | ||
|
|
e7687a0fe6 | ||
|
|
5dd5986b88 | ||
|
|
8f250e82f4 | ||
|
|
ed694b09b0 | ||
|
|
3e0ca6a70a | ||
|
|
3b08ed5f51 | ||
|
|
41dcb26283 | ||
|
|
d4879b9bd8 | ||
|
|
87856fe382 | ||
|
|
205a37a879 | ||
|
|
e830c90314 | ||
|
|
5308b49cd2 | ||
|
|
216ea34a3c | ||
|
|
0a9c5250f8 | ||
|
|
0e91c75dc2 | ||
|
|
cf996dda0b | ||
|
|
21638e6a9e | ||
|
|
272d6e9b66 | ||
|
|
87b08669d7 | ||
|
|
de86682562 | ||
|
|
25c2e34eed | ||
|
|
e92b006f70 | ||
|
|
962eb08e40 | ||
|
|
6342e0065a | ||
|
|
ac44ffcdff | ||
|
|
dfb5a4875a | ||
|
|
ddce3058be | ||
|
|
9235c395b4 | ||
|
|
e1296105f9 | ||
|
|
38cdcf4f61 | ||
|
|
5623decdb3 | ||
|
|
0f39ea8ac7 | ||
|
|
f3d3ec6ef7 | ||
|
|
fde01d5004 | ||
|
|
71d9710322 | ||
|
|
7a5ce8cd6b | ||
|
|
18deb79068 | ||
|
|
16b3e62587 | ||
|
|
6c1edadc55 | ||
|
|
8928a87b14 | ||
|
|
8eca200023 | ||
|
|
865b6d14f0 | ||
|
|
b63af9b919 | ||
|
|
4d4cdf9e60 | ||
|
|
3868d57d28 | ||
|
|
1b3a2c8470 | ||
|
|
618d8e6468 | ||
|
|
53a2a7a8e2 | ||
|
|
9a26c37ffd | ||
|
|
1e3ef6846d | ||
|
|
31225b9e23 | ||
|
|
436b6808b5 | ||
|
|
cc5e105d7f | ||
|
|
7f62bd61e3 | ||
|
|
aecc34a78b | ||
|
|
72bbc31cd9 | ||
|
|
f54d1273c9 | ||
|
|
01a955a16f | ||
|
|
ed99433448 | ||
|
|
669e6f93fa | ||
|
|
a5aac0caad | ||
|
|
31e29506fa |
83
.github/pull_request_template.md
vendored
Normal file
83
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<!--
|
||||
|
||||
IMPORTANT: Please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
|
||||
|
||||
Any PRs not following the guidelines or with missing information will not be considered.
|
||||
|
||||
-->
|
||||
|
||||
## Base information
|
||||
| Question | Answer
|
||||
|---------------------------------------------------------------|--------
|
||||
| Related to a SourceForge thead / Another PR / Combodo ticket? | <!-- Put the URL -->
|
||||
| Type of change? | Bug fix / Enhancement / Translations
|
||||
|
||||
|
||||
## Symptom (bug) / Objective (enhancement)
|
||||
<!--
|
||||
If it's a bug
|
||||
- Explain the symptom in details
|
||||
- If possible put error messages, logs or screenshots (you can paste image directly in this editor).
|
||||
|
||||
If it's an enhancement
|
||||
- Describe what is blocking you, what is the objective with as much details as possible.
|
||||
- Add screenshots if it's related to UI.
|
||||
-->
|
||||
|
||||
|
||||
## Reproduction procedure (bug)
|
||||
<!--
|
||||
Remove this section only if it's NOT a bug.
|
||||
|
||||
Otherwise, explain step by step how to reproduce the issue on a standard iTop Community.
|
||||
|
||||
If it requires a custom datamodel, provide the minimal XML delta to reproduce it on a standard iTop Community.
|
||||
-->
|
||||
|
||||
1. On iTop x.y.z <!-- Put complete iTop version (eg. 3.1.0-2) -->
|
||||
2. With PHP x.y.z <!-- Put complete PHP version (eg. 8.1.24) -->
|
||||
2. First go there
|
||||
2. Then do that
|
||||
3. ...
|
||||
4. Finally, see that...
|
||||
|
||||
|
||||
## Cause (bug)
|
||||
<!--
|
||||
Remove this section only if it's NOT a bug.
|
||||
|
||||
Otherwise, explain what is the cause of the issue (where in the code and why)
|
||||
-->
|
||||
|
||||
|
||||
## Proposed solution (bug and enhancement)
|
||||
<!--
|
||||
Explain in details how you are proposing to solve this:
|
||||
- What did you do in the code and why
|
||||
- If you changed something in the UI, put before / after screenshots (you can paste image directly in this editor)
|
||||
-->
|
||||
|
||||
|
||||
## Checklist before requesting a review
|
||||
<!--
|
||||
Don't remove these lines, check them once done.
|
||||
-->
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have tested all changes I made on an iTop instance
|
||||
- [ ] I have added a unit test, otherwise I have explained why I couldn't
|
||||
- [ ] Is the PR clear and detailled enough so anyone can understand digging in the code?
|
||||
|
||||
## Checklist of things to do before PR is ready to merge
|
||||
<!--
|
||||
Things that needs to be done in the PR before it can be considered as ready to be merged
|
||||
|
||||
Examples:
|
||||
- Changes requested in the review
|
||||
- Unit test to add
|
||||
- Dictionary entries to translate
|
||||
- ...
|
||||
-->
|
||||
|
||||
- [ ] ...
|
||||
- [ ] ...
|
||||
- [ ] ...
|
||||
@@ -22,13 +22,13 @@ $iElapsed = time() - $iBeginTime;
|
||||
|
||||
if (count($aFailedCommands))
|
||||
{
|
||||
fwrite(STDERR, "\nafterBuild execution failed! (in ${iElapsed}s)\n");
|
||||
fwrite(STDERR, "\nafterBuild execution failed! (in {$iElapsed}s)\n");
|
||||
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
echo "\nDone (${iElapsed}s)\n";
|
||||
echo "\nDone ({$iElapsed}s)\n";
|
||||
exit(0);
|
||||
|
||||
/**
|
||||
@@ -74,7 +74,7 @@ function ExecCommand($cmd) {
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "| elapsed:${iElapsed}s \n";
|
||||
echo "| elapsed:{$iElapsed}s \n";
|
||||
}
|
||||
|
||||
if (!empty($stderr))
|
||||
|
||||
56
.make/composer/tcpdf/tcpdfDefaultFontsToKeepInItop.txt
Normal file
56
.make/composer/tcpdf/tcpdfDefaultFontsToKeepInItop.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
courier.php
|
||||
courierb.php
|
||||
courierbi.php
|
||||
courieri.php
|
||||
dejavusans.ctg.z
|
||||
dejavusans.php
|
||||
dejavusans.z
|
||||
dejavusansb.ctg.z
|
||||
dejavusansb.php
|
||||
dejavusansb.z
|
||||
dejavusansbi.ctg.z
|
||||
dejavusansbi.php
|
||||
dejavusansbi.z
|
||||
dejavusanscondensed.ctg.z
|
||||
dejavusanscondensed.php
|
||||
dejavusanscondensed.z
|
||||
dejavusanscondensedb.ctg.z
|
||||
dejavusanscondensedb.php
|
||||
dejavusanscondensedb.z
|
||||
dejavusanscondensedbi.ctg.z
|
||||
dejavusanscondensedbi.php
|
||||
dejavusanscondensedbi.z
|
||||
dejavusanscondensedi.ctg.z
|
||||
dejavusanscondensedi.php
|
||||
dejavusanscondensedi.z
|
||||
dejavusansextralight.ctg.z
|
||||
dejavusansextralight.php
|
||||
dejavusansextralight.z
|
||||
dejavusansi.ctg.z
|
||||
dejavusansi.php
|
||||
dejavusansi.z
|
||||
dejavusansmono.ctg.z
|
||||
dejavusansmono.php
|
||||
dejavusansmono.z
|
||||
dejavusansmonob.ctg.z
|
||||
dejavusansmonob.php
|
||||
dejavusansmonob.z
|
||||
dejavusansmonobi.ctg.z
|
||||
dejavusansmonobi.php
|
||||
dejavusansmonobi.z
|
||||
dejavusansmonoi.ctg.z
|
||||
dejavusansmonoi.php
|
||||
dejavusansmonoi.z
|
||||
droidsansfallback.ctg.z
|
||||
droidsansfallback.php
|
||||
droidsansfallback.z
|
||||
helvetica.php
|
||||
helveticab.php
|
||||
helveticabi.php
|
||||
helveticai.php
|
||||
symbol.php
|
||||
times.php
|
||||
timesb.php
|
||||
timesbi.php
|
||||
timesi.php
|
||||
zapfdingbats.php
|
||||
101
.make/composer/tcpdf/tcpdfUpdateFonts.php
Normal file
101
.make/composer/tcpdf/tcpdfUpdateFonts.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* This script will copy custom fonts in the TCPDF lib fonts directory.
|
||||
* If you need to add other files :
|
||||
* - add the corresponding files in this script directory
|
||||
* - modify this script to copy also your files
|
||||
*
|
||||
* @since 2.7.0 N°1947 add DroidSansFallback font (see also PR #49 in the links below)
|
||||
* @since 2.7.0 N°2435 TCPPDF lib forked and added in composer.json (at that time the lib was announced as deprecated and rewritten in tecnickcom/tc-lib-pdf)
|
||||
* @since 3.2.0 N°7175 switch back to TCPDF original lib (which is finally still maintained, tecnickcom/tc-lib-pdf us still under dev), script creation to keep custom DroidSansFallback font
|
||||
*
|
||||
* @link https://github.com/Combodo/iTop/pull/49 add DroidSansFallback font
|
||||
* @link https://github.com/tecnickcom/TCPDF?tab=readme-ov-file#note TCPDF is in support only mode
|
||||
*/
|
||||
|
||||
$sItopRootFolder = realpath(__DIR__ . "/../../../");
|
||||
$sCurrentScriptFileName = basename(__FILE__);
|
||||
|
||||
|
||||
require_once ("$sItopRootFolder/lib/autoload.php");
|
||||
|
||||
|
||||
$sTcPdfRootFolder = $sItopRootFolder.'/lib/tecnickcom/tcpdf';
|
||||
if (false === file_exists($sTcPdfRootFolder)) {
|
||||
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
|
||||
return;
|
||||
}
|
||||
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/Fonts/';
|
||||
|
||||
|
||||
/**
|
||||
* 1) Cleaning up the fonts directory to keep only the ones we want in iTop
|
||||
*/
|
||||
echo $sCurrentScriptFileName.": ---1) Cleaning up the fonts files\n";
|
||||
$aTcpdfDefaultFontsToKeepInItop = file(__DIR__.'/tcpdfDefaultFontsToKeepInItop.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
|
||||
$aTcpdfFontsDirContent = scandir($sTcPdfFontsFolder);
|
||||
foreach ($aTcpdfFontsDirContent as $sTcpdfFontResourceName) {
|
||||
if ($sTcpdfFontResourceName === '.') {
|
||||
continue;
|
||||
}
|
||||
if ($sTcpdfFontResourceName === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_array($sTcpdfFontResourceName, $aTcpdfDefaultFontsToKeepInItop, true)) {
|
||||
echo $sCurrentScriptFileName.": Removing $sTcpdfFontResourceName !\n";
|
||||
|
||||
$sTcpdfFontResourceFullPath = $sTcPdfFontsFolder.$sTcpdfFontResourceName;
|
||||
if (is_file($sTcpdfFontResourceFullPath)) {
|
||||
unlink($sTcpdfFontResourceFullPath);
|
||||
} elseif (is_dir($sTcpdfFontResourceFullPath)) {
|
||||
rrmdir($sTcpdfFontResourceFullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 2) Then adding the DroidSansFallback font (useful for CJK data for example)
|
||||
*/
|
||||
echo $sCurrentScriptFileName.": ---2) Copying font files to TCPDF ($sTcPdfFontsFolder)...\n";
|
||||
$aFontFilesToCopy = glob(__DIR__.'\droidsansfallback.*');
|
||||
foreach ($aFontFilesToCopy as $sFontFileToCopy) {
|
||||
$sFontFileName = basename($sFontFileToCopy);
|
||||
echo $sCurrentScriptFileName.': copying '.$sFontFileName."\n";
|
||||
copy($sFontFileToCopy, $sTcPdfFontsFolder.$sFontFileName);
|
||||
}
|
||||
echo $sCurrentScriptFileName.": Done !\n";
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Recursively delete a directory and its content
|
||||
*
|
||||
* @param $sDirToRemovePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function rrmdir($sDirToRemovePath):void
|
||||
{
|
||||
if (is_dir($sDirToRemovePath)) {
|
||||
$objects = scandir($sDirToRemovePath);
|
||||
foreach ($objects as $object) {
|
||||
if ($object != "." && $object != "..") {
|
||||
if (filetype($sDirToRemovePath."/".$object) == "dir") {
|
||||
rrmdir($sDirToRemovePath."/".$object);
|
||||
} else {
|
||||
unlink($sDirToRemovePath."/".$object);
|
||||
}
|
||||
}
|
||||
}
|
||||
reset($objects);
|
||||
rmdir($sDirToRemovePath);
|
||||
}
|
||||
}
|
||||
@@ -1274,8 +1274,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
||||
*/
|
||||
public function GetNorthPaneHtml(iTopWebPage $oPage)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -1284,8 +1282,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
||||
*/
|
||||
public function GetSouthPaneHtml(iTopWebPage $oPage)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -1294,8 +1290,6 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
||||
*/
|
||||
public function GetBannerHtml(iTopWebPage $oPage)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "application, grant_by_profile",
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
|
||||
@@ -137,6 +137,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
/** @var string */
|
||||
public const ENUM_INPUT_TYPE_TAGSET = 'tagset';
|
||||
/** @var string */
|
||||
public const ENUM_INPUT_TYPE_TAGSET_LINKEDSET = 'tagset_linkedset';
|
||||
/** @var string */
|
||||
public const ENUM_INPUT_TYPE_RADIO = 'radio';
|
||||
/** @var string */
|
||||
public const ENUM_INPUT_TYPE_CHECKBOX = 'checkbox';
|
||||
@@ -2362,6 +2364,7 @@ EOF
|
||||
|
||||
case 'LinkedSet':
|
||||
if ($oAttDef->GetDisplayStyle() === LINKSET_DISPLAY_STYLE_PROPERTY) {
|
||||
$sInputType = self::ENUM_INPUT_TYPE_TAGSET_LINKEDSET;
|
||||
if (array_key_exists('bulk_context', $aArgs)) {
|
||||
$oTagSetBlock = LinkSetUIBlockFactory::MakeForBulkLinkSet($iId, $oAttDef, $value, $sWizardHelperJsVarName, $aArgs['bulk_context']);
|
||||
} else {
|
||||
@@ -3589,16 +3592,26 @@ EOF
|
||||
$oPage->add_ready_script(InlineImage::EnableCKEditorImageUpload($this, $sTempId));
|
||||
} else {
|
||||
//we can directly apply the stimuli
|
||||
$sExceptionMessage = null;
|
||||
try {
|
||||
$bApplyStimulus = $this->ApplyStimulus($sStimulus); // will write the object in the DB
|
||||
if (!$bApplyStimulus) {
|
||||
throw new ApplicationException(Dict::S('UI:FailedToApplyStimuli'));
|
||||
} else {
|
||||
}
|
||||
catch (Exception $oException) {
|
||||
// Catch any exception happening during the stimulus
|
||||
$bApplyStimulus = false;
|
||||
$sExceptionMessage = ($oException instanceof CoreCannotSaveObjectException) ? $oException->getHtmlMessage() : $oException->getMessage();
|
||||
}
|
||||
finally {
|
||||
if ($sOwnershipToken !== null) {
|
||||
// Release the concurrent lock, if any
|
||||
iTopOwnershipLock::ReleaseLock($sClass, $iKey, $sOwnershipToken);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!$bApplyStimulus) {
|
||||
// Throw an application oriented exception if necessary
|
||||
throw new ApplicationException($sExceptionMessage ?? Dict::S('UI:FailedToApplyStimuli'));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -304,8 +304,8 @@
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_BEFORE_APPLY_STIMULUS" _delta="define">
|
||||
<description>A stimulus is about to be applied to an object</description>
|
||||
<event id="EVENT_ENUM_TRANSITIONS" _delta="define">
|
||||
<description>Manage the allowed transitions in current object state. The only action allowed is to deny transitions with DBObject::DenyTransition()</description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -314,89 +314,9 @@
|
||||
<description>The object where the stimulus is targeted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus">
|
||||
<description>Current stimulus applied</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="previous_state">
|
||||
<description>Object previous state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="new_state">
|
||||
<description>Object new state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="save_object">
|
||||
<description>The object must be saved in the database</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_AFTER_APPLY_STIMULUS" _delta="define">
|
||||
<description>A stimulus has been applied to an object</description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object where the stimulus is targeted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus">
|
||||
<description>Current stimulus applied</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="previous_state">
|
||||
<description>Object previous state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="new_state">
|
||||
<description>Object new state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="save_object">
|
||||
<description>The object is asked to be saved in the database</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_APPLY_STIMULUS_FAILED" _delta="define">
|
||||
<description>A stimulus has failed</description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="action">
|
||||
<description>The action that failed to apply the stimulus</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="object">
|
||||
<description>The object where the stimulus is targeted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus">
|
||||
<description>Current stimulus applied</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="previous_state">
|
||||
<description>Object previous state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="new_state">
|
||||
<description>Object new state</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="save_object">
|
||||
<description>The object must be saved in the database</description>
|
||||
<type>boolean</type>
|
||||
<event_datum id="allowed_stimuli">
|
||||
<description>The list of available stimuli in the current state</description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
|
||||
@@ -82,7 +82,7 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
|
||||
protected static $m_sLoginFailedMessage = '';
|
||||
|
||||
|
||||
public function __construct($sTitle = null)
|
||||
{
|
||||
if ($sTitle === null) {
|
||||
@@ -101,6 +101,15 @@ class LoginWebPage extends NiceWebPage
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function GetFaviconAbsoluteUrl()
|
||||
{
|
||||
return Branding::GetLoginFavIconAbsoluteUrl();
|
||||
}
|
||||
|
||||
public static function SetLoginFailedMessage($sMessage)
|
||||
{
|
||||
self::$m_sLoginFailedMessage = $sMessage;
|
||||
@@ -910,13 +919,13 @@ class LoginWebPage extends NiceWebPage
|
||||
$aAllProfiles = array();
|
||||
while ($oProfile = $oProfilesSet->Fetch())
|
||||
{
|
||||
$aAllProfiles[strtolower($oProfile->GetName())] = $oProfile->GetKey();
|
||||
$aAllProfiles[mb_strtolower($oProfile->GetName())] = $oProfile->GetKey();
|
||||
}
|
||||
|
||||
$aProfiles = array();
|
||||
foreach ($aRequestedProfiles as $sRequestedProfile)
|
||||
{
|
||||
$sRequestedProfile = strtolower($sRequestedProfile);
|
||||
$sRequestedProfile = mb_strtolower($sRequestedProfile);
|
||||
if (isset($aAllProfiles[$sRequestedProfile]))
|
||||
{
|
||||
$aProfiles[] = $aAllProfiles[$sRequestedProfile];
|
||||
|
||||
@@ -536,7 +536,7 @@ CSS;
|
||||
if (static::HasImageExtension($sImg)
|
||||
&& ! array_key_exists($sImg, $aImages))
|
||||
{
|
||||
$sFilePath = realpath($sImg);
|
||||
$sFilePath = utils::RealPath($sImg, APPROOT);
|
||||
if ($sFilePath !== false) {
|
||||
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
|
||||
$aImages[$sImg] = $sFilePathWithSlashes;
|
||||
@@ -544,7 +544,7 @@ CSS;
|
||||
}
|
||||
|
||||
$sCanonicalPath = static::CanonicalizePath($sTargetThemeFolderPath.'/'.$sImg);
|
||||
$sFilePath = realpath($sCanonicalPath);
|
||||
$sFilePath = utils::RealPath($sCanonicalPath, APPROOT);
|
||||
if ($sFilePath !== false) {
|
||||
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
|
||||
$aImages[$sImg] = $sFilePathWithSlashes;
|
||||
|
||||
@@ -72,15 +72,16 @@ class UIHTMLEditorWidget
|
||||
// To change the default settings of the editor,
|
||||
// a) edit the file /js/ckeditor/config.js
|
||||
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
||||
$sJSDefineWidth = '';
|
||||
$aConfig = utils::GetCkeditorPref();
|
||||
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
|
||||
if ($sWidthSpec != '')
|
||||
{
|
||||
$aConfig['width'] = $sWidthSpec;
|
||||
if ($sWidthSpec != '') {
|
||||
/*N°6543 - the function min allow to keep text inside the column when width is defined*/
|
||||
$aConfig['width'] = "min($sWidthSpec,100%)";
|
||||
$sJSDefineWidth = '$("#cke_'.$iId.' iframe").contents().find("body").css("width", "'.$sWidthSpec.'")';
|
||||
}
|
||||
$sHeightSpec = addslashes(trim($this->m_oAttDef->GetHeight()));
|
||||
if ($sHeightSpec != '')
|
||||
{
|
||||
if ($sHeightSpec != '') {
|
||||
$aConfig['height'] = $sHeightSpec;
|
||||
}
|
||||
$sConfigJS = json_encode($aConfig);
|
||||
@@ -111,6 +112,7 @@ $('#$iId').on('update', function(evt){
|
||||
else
|
||||
{
|
||||
oMe.data('ckeditorInstance').setReadOnly(oMe.prop('disabled'));
|
||||
$sJSDefineWidth
|
||||
}
|
||||
};
|
||||
setTimeout(delayedSetReadOnly, 50);
|
||||
|
||||
@@ -23,6 +23,7 @@ use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Hook\iKeyboardShortcut;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Service\Module\ModuleService;
|
||||
use Combodo\iTop\Test\UnitTest\Application\utilsTest;
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
use ScssPhp\ScssPhp\OutputStyle;
|
||||
use ScssPhp\ScssPhp\ValueConverter;
|
||||
@@ -167,7 +168,11 @@ class utils
|
||||
|
||||
private static $iNextId = 0;
|
||||
|
||||
private static $m_sAppRootUrl = null;
|
||||
/**
|
||||
* @var ?string
|
||||
* @used-by GetAbsoluteUrlAppRoot
|
||||
*/
|
||||
private static $sAbsoluteUrlAppRootCache = null;
|
||||
|
||||
protected static function LoadParamFile($sParamFile)
|
||||
{
|
||||
@@ -1037,28 +1042,27 @@ class utils
|
||||
return $bTrustProxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute URL to the application root path
|
||||
*
|
||||
* @param bool $bForceTrustProxy
|
||||
*
|
||||
* @return string The absolute URL to the application root, without the first slash
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 2.7.4 $bForceTrustProxy param added
|
||||
*/
|
||||
/**
|
||||
* Returns the absolute URL to the application root path
|
||||
*
|
||||
* @param bool $bForceTrustProxy
|
||||
*
|
||||
* @return string The absolute URL to the application root, without the first slash
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 2.7.4 $bForceTrustProxy param added
|
||||
*/
|
||||
public static function GetAbsoluteUrlAppRoot($bForceTrustProxy = false)
|
||||
{
|
||||
$sUrl = static::$m_sAppRootUrl;
|
||||
if ($sUrl === null || $bForceTrustProxy)
|
||||
if (static::$sAbsoluteUrlAppRootCache === null || $bForceTrustProxy)
|
||||
{
|
||||
$sUrl = self::GetConfig()->Get('app_root_url');
|
||||
if ($sUrl == '')
|
||||
static::$sAbsoluteUrlAppRootCache = self::GetConfig()->Get('app_root_url');
|
||||
if (static::$sAbsoluteUrlAppRootCache == '')
|
||||
{
|
||||
$sUrl = self::GetDefaultUrlAppRoot($bForceTrustProxy);
|
||||
static::$sAbsoluteUrlAppRootCache = self::GetDefaultUrlAppRoot($bForceTrustProxy);
|
||||
}
|
||||
elseif (strpos($sUrl, SERVER_NAME_PLACEHOLDER) > -1)
|
||||
elseif (strpos(static::$sAbsoluteUrlAppRootCache, SERVER_NAME_PLACEHOLDER) > -1)
|
||||
{
|
||||
if (isset($_SERVER['SERVER_NAME']))
|
||||
{
|
||||
@@ -1069,11 +1073,10 @@ class utils
|
||||
// CLI mode ?
|
||||
$sServerName = php_uname('n');
|
||||
}
|
||||
$sUrl = str_replace(SERVER_NAME_PLACEHOLDER, $sServerName, $sUrl);
|
||||
static::$sAbsoluteUrlAppRootCache = str_replace(SERVER_NAME_PLACEHOLDER, $sServerName, static::$sAbsoluteUrlAppRootCache);
|
||||
}
|
||||
static::$m_sAppRootUrl = $sUrl;
|
||||
}
|
||||
return static::$m_sAppRootUrl;
|
||||
return static::$sAbsoluteUrlAppRootCache;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "project",
|
||||
"license": "AGPL-3.0-only",
|
||||
"require": {
|
||||
"php": ">=8.1.0 <8.2.0",
|
||||
"php": ">=8.1.0 <8.4.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
@@ -13,31 +13,32 @@
|
||||
"ext-mysqli": "*",
|
||||
"ext-soap": "*",
|
||||
"apereo/phpcas": "~1.6.0",
|
||||
"combodo/tcpdf": "~6.4.4",
|
||||
"firebase/php-jwt": "~6.4.0",
|
||||
"firebase/php-jwt": "^6.4.0",
|
||||
"guzzlehttp/guzzle": "^7.5.1",
|
||||
"laminas/laminas-mail": "^2.11",
|
||||
"laminas/laminas-servicemanager": "^3.5",
|
||||
"league/oauth2-google": "^3.0",
|
||||
"nikic/php-parser": "~4.14.0",
|
||||
"league/oauth2-google": "^4.0.1",
|
||||
"nikic/php-parser": "^4.14.0",
|
||||
"pear/archive_tar": "~1.4.14",
|
||||
"pelago/emogrifier": "^6.0.0",
|
||||
"scssphp/scssphp": "^1.10.3",
|
||||
"pelago/emogrifier": "^7.2.0",
|
||||
"psr/log": "^3.0.0",
|
||||
"scssphp/scssphp": "^1.12.1",
|
||||
"symfony/console": "~6.4.0",
|
||||
"symfony/dotenv": "~6.4.0",
|
||||
"symfony/framework-bundle": "~6.4.0",
|
||||
"symfony/var-dumper": "~6.4.0",
|
||||
"symfony/runtime": "~6.4.0",
|
||||
"symfony/http-foundation": "~6.4.0",
|
||||
"symfony/http-kernel": "~6.4.0",
|
||||
"symfony/runtime": "~6.4.0",
|
||||
"symfony/twig-bundle": "~6.4.0",
|
||||
"symfony/var-dumper": "~6.4.0",
|
||||
"symfony/yaml": "~6.4.0",
|
||||
"tecnickcom/tcpdf": "^6.6.0",
|
||||
"thenetworg/oauth2-azure": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/debug-bundle": "~6.4.0",
|
||||
"symfony/stopwatch": "~6.4.0",
|
||||
"symfony/web-profiler-bundle": "~6.4.0",
|
||||
"symfony/debug-bundle": "~6.4.0"
|
||||
"symfony/web-profiler-bundle": "~6.4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Required to use the AttributeEncryptedString.",
|
||||
@@ -96,8 +97,9 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": ["@rmDeniedTestDir"],
|
||||
"post-update-cmd": ["@rmDeniedTestDir"],
|
||||
"rmDeniedTestDir": "@php .make/composer/rmDeniedTestDir.php"
|
||||
"post-install-cmd": ["@rmDeniedTestDir", "@tcpdfCustomFonts"],
|
||||
"post-update-cmd": ["@rmDeniedTestDir", "@tcpdfCustomFonts"],
|
||||
"rmDeniedTestDir": "@php .make/composer/rmDeniedTestDir.php",
|
||||
"tcpdfCustomFonts": "@php .make/composer/tcpdf/tcpdfUpdateFonts.php"
|
||||
}
|
||||
}
|
||||
|
||||
771
composer.lock
generated
771
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -521,6 +521,6 @@ class Str
|
||||
|
||||
public static function islowcase($sString)
|
||||
{
|
||||
return (strtolower($sString) == $sString);
|
||||
return (mb_strtolower($sString) == $sString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Service\Notification\NotificationsRepository;
|
||||
use Combodo\iTop\Service\Notification\NotificationsService;
|
||||
use Combodo\iTop\Service\Router\Router;
|
||||
|
||||
/**
|
||||
* Persistent classes (internal): user defined actions
|
||||
@@ -77,6 +81,7 @@ abstract class Action extends cmdbAbstractObject
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list",
|
||||
array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "action_id", "ext_key_to_remote" => "trigger_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => array(), "display_style" => 'property')));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("asynchronous", array("allowed_values" => new ValueSetEnum(['use_global_setting' => 'Use global settings','yes' => 'Yes' ,'no' => 'No']), "sql" => "asynchronous", "default_value" => 'use_global_setting', "is_null_allowed" => false, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
// - Attributes to be displayed for the complete details
|
||||
@@ -168,6 +173,100 @@ abstract class Action extends cmdbAbstractObject
|
||||
$this->m_aCheckWarnings[] = Dict::S('Action:WarningNoTriggerLinked');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0 N°5472 method creation
|
||||
*/
|
||||
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, false);
|
||||
|
||||
if ($oPage instanceof iTopWebPage) {
|
||||
$this->GenerateLastExecutionsTab($oPage, $bEditMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0 N°5472 method creation
|
||||
*/
|
||||
protected function GenerateLastExecutionsTab(iTopWebPage $oPage, $bEditMode)
|
||||
{
|
||||
$oRouter = Router::GetInstance();
|
||||
$sActionLastExecutionsPageUrl = $oRouter->GenerateUrl('notifications.action.last_executions_tab', ['action_id' => $this->GetKey()]);
|
||||
$oPage->AddAjaxTab('action_errors', $sActionLastExecutionsPageUrl, false, Dict::S('Action:last_executions_tab'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \InvalidConfigParamException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \ReflectionException
|
||||
* @since 3.2.0 N°5472 method creation
|
||||
*/
|
||||
public function GetLastExecutionsTabContent(WebPage $oPage): void
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$sLastExecutionDaysConfigParamName = 'notifications.last_executions_days';
|
||||
$iLastExecutionDays = $oConfig->Get($sLastExecutionDaysConfigParamName);
|
||||
|
||||
if ($iLastExecutionDays < 0) {
|
||||
throw new InvalidConfigParamException("Invalid value for {$sLastExecutionDaysConfigParamName} config parameter. Param desc: " . $oConfig->GetDescription($sLastExecutionDaysConfigParamName));
|
||||
}
|
||||
|
||||
$sActionQueryOql = 'SELECT EventNotification WHERE action_id = :action_id';
|
||||
$aActionQueryParams = ['action_id' => $this->GetKey()];
|
||||
if ($iLastExecutionDays > 0) {
|
||||
$sActionQueryOql .= ' AND date > DATE_SUB(NOW(), INTERVAL :days DAY)';
|
||||
$aActionQueryParams['days'] = $iLastExecutionDays;
|
||||
$sActionQueryLimit = Dict::Format('Action:last_executions_tab_limit_days', $iLastExecutionDays);
|
||||
} else {
|
||||
$sActionQueryLimit = Dict::S('Action:last_executions_tab_limit_none');
|
||||
}
|
||||
|
||||
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
|
||||
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
|
||||
|
||||
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
|
||||
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle]);
|
||||
|
||||
$oPage->AddUiBlock($oExecutionsListBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be overloaded by the children classes to return the value of their global asynchronous setting (eg. `email_asynchronous` for `\ActionEmail`, `prefer_asynchronous` for `\ActionWebhook`, ...)
|
||||
*
|
||||
* @return bool true if the global setting for this kind of action if to be executed asynchronously, false otherwise.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static function GetAsynchronousGlobalSetting(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool true if that action instance should be executed asynchronously, otherwise false
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function IsAsynchronous(): bool
|
||||
{
|
||||
$sAsynchronous = $this->Get('asynchronous');
|
||||
if ($sAsynchronous === 'use_global_setting') {
|
||||
return static::GetAsynchronousGlobalSetting();
|
||||
}
|
||||
return $sAsynchronous === 'yes';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,6 +384,7 @@ class ActionEmail extends ActionNotification
|
||||
"db_table" => "priv_action_email",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-mailing.svg'),
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
@@ -321,6 +421,7 @@ class ActionEmail extends ActionNotification
|
||||
),
|
||||
'fieldset:ActionEmail:trigger' => array(
|
||||
0 => 'trigger_list',
|
||||
1 => 'asynchronous'
|
||||
),
|
||||
),
|
||||
'col:col2' => array(
|
||||
@@ -355,27 +456,33 @@ class ActionEmail extends ActionNotification
|
||||
protected $m_aMailErrors; //array of strings explaining the issue
|
||||
|
||||
/**
|
||||
* Return a the list of emails as a string, or a detailed error description
|
||||
* Return the list of emails as a string, or a detailed error description
|
||||
*
|
||||
* @param string $sRecipAttCode
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return string
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
protected function FindRecipients($sRecipAttCode, $aArgs)
|
||||
{
|
||||
$oTrigger = $aArgs['trigger->object()'] ?? null;
|
||||
$sOQL = $this->Get($sRecipAttCode);
|
||||
if (strlen($sOQL) === 0) return '';
|
||||
if (utils::IsNullOrEmptyString($sOQL)) return '';
|
||||
|
||||
try
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
if ($this->Get('ignore_notify') === 'no') {
|
||||
// In theory it is possible to notify *any* kind of object,
|
||||
// In theory, it is possible to notify *any* kind of object,
|
||||
// as long as there is an email attribute in the class
|
||||
// So let's not assume that the selected class is a Person
|
||||
$sFirstSelectedClass = $oSearch->GetClass();
|
||||
@@ -408,16 +515,29 @@ class ActionEmail extends ActionNotification
|
||||
return "The objects of the class '$sClass' do not have any email attribute";
|
||||
}
|
||||
|
||||
if($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
|
||||
$aArgs['trigger_id'] = $oTrigger->GetKey();
|
||||
$aArgs['action_id'] = $this->GetKey();
|
||||
|
||||
$sSubscribedContactsOQL = NotificationsRepository::GetInstance()->GetSearchOQLContactUnsubscribedByTriggerAndAction();
|
||||
$sSubscribedContactsOQL->ApplyParameters($aArgs);
|
||||
$sAlias = $oSearch->GetClassAlias();
|
||||
$oSearch->AddConditionExpression(Expression::FromOQL("`$sAlias`.id NOT IN ($sSubscribedContactsOQL)"));
|
||||
}
|
||||
|
||||
$oSet = new DBObjectSet($oSearch, array() /* order */, $aArgs);
|
||||
$aRecipients = array();
|
||||
while ($oObj = $oSet->Fetch())
|
||||
{
|
||||
$sAddress = trim($oObj->Get($sEmailAttCode));
|
||||
if (strlen($sAddress) > 0)
|
||||
if (utils::IsNotNullOrEmptyString($sAddress))
|
||||
{
|
||||
$aRecipients[] = $sAddress;
|
||||
$this->m_iRecipients++;
|
||||
}
|
||||
if ($oTrigger !== null && in_array('Contact', MetaModel::EnumParentClasses($sClass, ENUM_CHILD_CLASSES_ALL), true)) {
|
||||
NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oObj);
|
||||
}
|
||||
}
|
||||
return implode(', ', $aRecipients);
|
||||
}
|
||||
@@ -537,7 +657,7 @@ class ActionEmail extends ActionNotification
|
||||
else
|
||||
{
|
||||
$aErrors = [];
|
||||
$iRes = $oEmail->Send($aErrors, false, $oLog); // allow asynchronous mode
|
||||
$iRes = $oEmail->Send($aErrors, $this->IsAsynchronous() ? Email::ENUM_SEND_FORCE_ASYNCHRONOUS : Email::ENUM_SEND_FORCE_SYNCHRONOUS, $oLog);
|
||||
switch ($iRes)
|
||||
{
|
||||
case EMAIL_SEND_OK:
|
||||
@@ -566,8 +686,17 @@ class ActionEmail extends ActionNotification
|
||||
* @param \EventNotification $oLog
|
||||
*
|
||||
* @return array
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @since 3.1.0 N°918
|
||||
*/
|
||||
protected function PrepareMessageContent($aContextArgs, &$oLog): array
|
||||
@@ -646,9 +775,7 @@ class ActionEmail extends ActionNotification
|
||||
$oLog->Set('body', HTMLSanitizer::Sanitize($aMessageContent['body']));
|
||||
}
|
||||
}
|
||||
$sStyles = file_get_contents(APPROOT.'css/email.css');
|
||||
$sStyles .= MetaModel::GetConfig()->Get('email_css');
|
||||
|
||||
|
||||
if ($this->IsBeingTested()) {
|
||||
$sTestBody = $aMessageContent['body'];
|
||||
$sTestBody .= "<div style=\"border: dashed;\">\n";
|
||||
@@ -677,10 +804,11 @@ class ActionEmail extends ActionNotification
|
||||
if (isset($aContextArgs['attachments']))
|
||||
{
|
||||
$aAttachmentReport = array();
|
||||
/** @var \ormDocument $oDocument */
|
||||
foreach($aContextArgs['attachments'] as $oDocument)
|
||||
{
|
||||
$aMessageContent['attachments'][] = ['data' => $oDocument->GetData(), 'filename' => $oDocument->GetFileName(), 'mime_type' => $oDocument->GetMimeType()];
|
||||
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData()));
|
||||
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData() ?? ''));
|
||||
}
|
||||
$oLog->Set('attachments', $aAttachmentReport);
|
||||
}
|
||||
@@ -790,4 +918,13 @@ class ActionEmail extends ActionNotification
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static function GetAsynchronousGlobalSetting(): bool
|
||||
{
|
||||
return utils::GetConfig()->Get('email_asynchronous');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,31 @@ function apc_delete($key)
|
||||
return $bRet1 || $bRet2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if APCu emulation key exists
|
||||
*
|
||||
* @param string|string[] $keys A string, or an array of strings, that contain keys.
|
||||
*
|
||||
* @return bool|string[] Returns TRUE if the key exists, otherwise FALSE
|
||||
* Or if an array was passed to keys, then an array is returned that
|
||||
* contains all existing keys, or an empty array if none exist.
|
||||
* @since 3.2.0 N°7068
|
||||
*/
|
||||
function apc_exists($keys)
|
||||
{
|
||||
if (is_array($keys)) {
|
||||
$aExistingKeys = [];
|
||||
foreach ($keys as $sKey) {
|
||||
if (apcFile::ExistsOneFile($sKey)) {
|
||||
$aExistingKeys[] = $sKey;
|
||||
}
|
||||
}
|
||||
return $aExistingKeys;
|
||||
} else {
|
||||
return apcFile::ExistsOneFile($keys);
|
||||
}
|
||||
}
|
||||
|
||||
class apcFile
|
||||
{
|
||||
// Check only once per request
|
||||
@@ -183,6 +208,16 @@ class apcFile
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cache key exists
|
||||
* @param $sKey
|
||||
* @return bool
|
||||
* @since 3.2.0 N°7068
|
||||
*/
|
||||
static public function ExistsOneFile($sKey) {
|
||||
return is_file(self::GetCacheFileName('-' . $sKey)) || is_file(self::GetCacheFileName($sKey));
|
||||
}
|
||||
|
||||
/** Get one cache entry content.
|
||||
* @param $sKey
|
||||
* @return bool|mixed
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Service\Notification\Event\EventiTopNotificationService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -457,3 +458,87 @@ class AsyncSendEmail extends AsyncTask
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An async notification to be sent to iTop users
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class AsyncSendiTopNotifications extends AsyncTask {
|
||||
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "created",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_async_send_itop_notifications",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeText("recipients", array("allowed_values"=>null, "sql"=>"recipients", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "allowed_values"=>null, "sql"=>"action_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "allowed_values"=>null, "sql"=>"trigger_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("title", array("allowed_values"=>null, "sql"=>"title", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values"=>null, "sql"=>"object_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("object_class", array("allowed_values"=>null, "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("url", array("allowed_values"=>null, "sql"=>"url", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function AddToQueue(int $iActionId, int $iTriggerId, array $aRecipients, string $sMessage, string $sTitle, string $sUrl, int $iObjectId, ?string $sObjectClass): void
|
||||
{
|
||||
$oNew = new static();
|
||||
$oNew->Set('action_id', $iActionId);
|
||||
$oNew->Set('trigger_id', $iTriggerId);
|
||||
$oNew->Set('recipients', json_encode($aRecipients));
|
||||
$oNew->Set('message', $sMessage);
|
||||
$oNew->Set('title', $sTitle);
|
||||
$oNew->Set('url', $sUrl);
|
||||
$oNew->Set('object_id', $iObjectId);
|
||||
$oNew->Set('object_class', $sObjectClass);
|
||||
$oNew->SetCurrentDate('date');
|
||||
|
||||
$oNew->DBInsert();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function DoProcess()
|
||||
{
|
||||
$oAction = MetaModel::GetObject('Action', $this->Get('action_id'));
|
||||
$iTriggerId = $this->Get('trigger_id');
|
||||
$aRecipients = json_decode($this->Get('recipients'));
|
||||
$sMessage = $this->Get('message');
|
||||
$sTitle = $this->Get('title');
|
||||
$sUrl = $this->Get('url');
|
||||
$iObjectId = $this->Get('object_id');
|
||||
$sObjectClass = $this->Get('object_class');
|
||||
$sDate = $this->Get('date');
|
||||
|
||||
foreach ($aRecipients as $iRecipientId)
|
||||
{
|
||||
$oEvent = EventiTopNotificationService::MakeEventFromAction($oAction, $iRecipientId, $iTriggerId, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass, $sDate);
|
||||
$oEvent->DBInsertNoReload();
|
||||
}
|
||||
|
||||
return "Sent";
|
||||
}
|
||||
}
|
||||
@@ -3062,6 +3062,11 @@ class AttributeObjectKey extends AttributeDBFieldVoid
|
||||
return ((int) $proposedValue) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @param int|DBObject $proposedValue Object key or valid ({@see MetaModel::IsValidObject()}) datamodel object
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -3074,7 +3079,6 @@ class AttributeObjectKey extends AttributeDBFieldVoid
|
||||
}
|
||||
if (MetaModel::IsValidObject($proposedValue))
|
||||
{
|
||||
/** @var \DBObject $proposedValue */
|
||||
return $proposedValue->GetKey();
|
||||
}
|
||||
|
||||
@@ -3506,7 +3510,7 @@ class AttributeBoolean extends AttributeInteger
|
||||
$sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null,
|
||||
$sAttributeQualifier = null
|
||||
) {
|
||||
$sInput = strtolower(trim($sProposedValue));
|
||||
$sInput = mb_strtolower(trim($sProposedValue));
|
||||
if ($bLocalizedValue)
|
||||
{
|
||||
switch ($sInput)
|
||||
@@ -4531,7 +4535,6 @@ class AttributeText extends AttributeString
|
||||
$sStyle = '';
|
||||
if (count($aStyles) > 0)
|
||||
{
|
||||
$aStyles[] = 'overflow:auto';
|
||||
$sStyle = 'style="'.implode(';', $aStyles).'"';
|
||||
}
|
||||
|
||||
@@ -6511,6 +6514,11 @@ class AttributeDateTime extends AttributeDBField
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @param int|string $proposedValue timestamp ({@see DateTime::getTimestamp()) or date as string, following the {@see GetInternalFormat} format.
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -8300,9 +8308,9 @@ class AttributeBlob extends AttributeDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Users can provide the document from an URL (including an URL on iTop itself)
|
||||
* for CSV import. Administrators can even provide the path to a local file
|
||||
* {@inheritDoc}
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param string $proposedValue Can be an URL (including an URL to iTop itself), or a local path (CSV import)
|
||||
*
|
||||
* @see AttributeDefinition::MakeRealValue()
|
||||
*/
|
||||
@@ -8543,7 +8551,7 @@ class AttributeBlob extends AttributeDefinition
|
||||
$sFingerprint = '';
|
||||
if ($value instanceOf ormDocument)
|
||||
{
|
||||
$sFingerprint = md5($value->GetData());
|
||||
$sFingerprint = $value->GetSignature();
|
||||
}
|
||||
|
||||
return $sFingerprint;
|
||||
@@ -8654,6 +8662,20 @@ class AttributeImage extends AttributeBlob
|
||||
parent::__construct($sCode, $aParams);
|
||||
}
|
||||
|
||||
public function Get($sParamName)
|
||||
{
|
||||
$oParamValue = parent::Get($sParamName);
|
||||
|
||||
if ($sParamName === 'default_image') {
|
||||
/** @noinspection NestedPositiveIfStatementsInspection */
|
||||
if (!empty($oParamValue)) {
|
||||
return utils::GetAbsoluteUrlModulesRoot() . $oParamValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $oParamValue;
|
||||
}
|
||||
|
||||
public function GetEditClass()
|
||||
{
|
||||
return "Image";
|
||||
|
||||
@@ -163,7 +163,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
* @param null $sAllowedValues : used for additional message that provides allowed values $sAllowedValues for current class
|
||||
* @param string|null $sAllowedValuesSearch : used to search all allowed values
|
||||
*/
|
||||
public function __construct($sSerializedSearch, $sReason, $sClass=null, $sAllowedValues=null, string $sAllowedValuesSearch=null)
|
||||
public function __construct($sSerializedSearch, $sReason, $sClass = null, $sAllowedValues = null, string $sAllowedValuesSearch = null)
|
||||
{
|
||||
parent::__construct(null, null, $sReason);
|
||||
$this->sSerializedSearch = $sSerializedSearch;
|
||||
@@ -198,7 +198,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
public function GetSearchLinkUrl()
|
||||
{
|
||||
return sprintf("UI.php?operation=search&filter=%s",
|
||||
rawurlencode($this->sSerializedSearch)
|
||||
rawurlencode($this->sSerializedSearch ?? "")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
public function GetAllowedValuesLinkUrl(): ?string
|
||||
{
|
||||
return sprintf("UI.php?operation=search&filter=%s",
|
||||
rawurlencode($this->sAllowedValuesSearch)
|
||||
rawurlencode($this->sAllowedValuesSearch ?? "")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,7 @@ class CellStatus_Ambiguous extends CellStatus_Issue
|
||||
public function GetSearchLinkUrl()
|
||||
{
|
||||
return sprintf("UI.php?operation=search&filter=%s",
|
||||
rawurlencode($this->sSerializedSearch)
|
||||
rawurlencode($this->sSerializedSearch ?? "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ abstract class CMDBObject extends DBObject
|
||||
$oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this)));
|
||||
$oMyChangeOp->Set("objkey", $objkey);
|
||||
$oMyChangeOp->Set("fclass", get_class($this));
|
||||
$oMyChangeOp->Set("fname", substr($this->GetRawName(), 0, 255)); // Protect against very long friendly names
|
||||
$oMyChangeOp->SetTrim("fname", $this->GetRawName()); // Protect against very long friendly names
|
||||
$iId = $oMyChangeOp->DBInsertNoReload();
|
||||
}
|
||||
|
||||
|
||||
@@ -447,14 +447,14 @@ class Config
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'export_pdf_font' => [ // @since 2.7.0 PR #49 / N°1947
|
||||
'type' => 'string',
|
||||
'description' => 'Font used when generating a PDF file',
|
||||
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
|
||||
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
|
||||
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
'type' => 'string',
|
||||
'description' => 'Font used when generating a PDF file',
|
||||
'default' => 'DejaVuSans', // DejaVuSans is a UTF-8 Unicode font, embedded in the TCPPDF lib we're using
|
||||
// Standard PDF fonts like helvetica or times newroman are NOT Unicode
|
||||
// A new DroidSansFallback can be used to improve CJK support (se PR #49)
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'access_mode' => [
|
||||
'type' => 'integer',
|
||||
@@ -1119,6 +1119,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'purge_data.max_chunk_size' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Maximum number of items deleted per loop. Used in function MetaModel::PurgeData',
|
||||
'default' => 1000,
|
||||
'value' => 1000,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'max_history_length' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Maximum length of the history table (in the "History" tab on each object) before it gets truncated. Latest modifications are displayed first.',
|
||||
@@ -1324,9 +1332,9 @@ class Config
|
||||
'draft_attachments_lifetime' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Lifetime (in seconds) of drafts\' attachments and inline images: after this duration, the garbage collector will delete them.',
|
||||
'default' => 86400,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'default' => 86400,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'date_and_time_format' => [
|
||||
@@ -1611,6 +1619,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'notifications.itop.send_asynchronously' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true then iTop notifications will be sent asynchronously',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'notifications.itop.newsroom_cache_time' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Duration in min between each fetch for notifications in newsroom',
|
||||
@@ -1619,6 +1635,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'notifications.last_executions_days' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Number of days to display in the Action\'s last executions tab (0 means no limit)',
|
||||
'default' => 30 + 31, // 2 months
|
||||
'value' => 61,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'regenerate_session_id_enabled' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true then session id will be regenerated on each login, to prevent session fixation.',
|
||||
@@ -1874,6 +1898,7 @@ class Config
|
||||
* @var integer Number of seconds between two reloads of the display (standard)
|
||||
*/
|
||||
protected $m_iStandardReloadInterval;
|
||||
|
||||
/**
|
||||
* @var integer Number of seconds between two reloads of the display (fast)
|
||||
*/
|
||||
@@ -2545,9 +2570,9 @@ class Config
|
||||
|
||||
// Old fashioned integer settings
|
||||
$aIntValues = array(
|
||||
'fast_reload_interval' => $this->m_iFastReloadInterval,
|
||||
'max_display_limit' => $this->m_iMaxDisplayLimit,
|
||||
'min_display_limit' => $this->m_iMinDisplayLimit,
|
||||
'fast_reload_interval' => $this->m_iFastReloadInterval,
|
||||
'max_display_limit' => $this->m_iMaxDisplayLimit,
|
||||
'min_display_limit' => $this->m_iMinDisplayLimit,
|
||||
'standard_reload_interval' => $this->m_iStandardReloadInterval,
|
||||
);
|
||||
foreach ($aIntValues as $sKey => $iValue)
|
||||
|
||||
@@ -1,6 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="lnkActionNotificationToContact" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<category>core/cmdb,application</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_lnk_action_notif_to_contact</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="action_id"/>
|
||||
<attribute id="contact_id"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<uniqueness_rules>
|
||||
<rule>
|
||||
<attributes>
|
||||
<attribute id="action_id"/>
|
||||
<attribute id="contact_id"/>
|
||||
<attribute id="trigger_id"/>
|
||||
</attributes>
|
||||
<filter/>
|
||||
<disabled>false</disabled>
|
||||
<is_blocking>true</is_blocking>
|
||||
</rule>
|
||||
</uniqueness_rules>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="action_id" xsi:type="AttributeExternalKey">
|
||||
<sql>action_id</sql>
|
||||
<target_class>ActionNotification</target_class>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="contact_id" xsi:type="AttributeExternalKey">
|
||||
<sql>contact_id</sql>
|
||||
<target_class>Contact</target_class>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="trigger_id" xsi:type="AttributeExternalKey">
|
||||
<sql>trigger_id</sql>
|
||||
<target_class>Trigger</target_class>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="subscribed" xsi:type="AttributeBoolean">
|
||||
<sql>subscribed</sql>
|
||||
<default_value>true</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="col:col1">
|
||||
<items>
|
||||
<item id="fieldset:lnkActionNotificationToContact:content">
|
||||
<items>
|
||||
<item id="action_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="title">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<list>
|
||||
<items>
|
||||
<item id="action_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="title">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ActioniTopNotification" _delta="define">
|
||||
<php_parent>
|
||||
<name>ActionNotification</name>
|
||||
@@ -15,9 +106,12 @@
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="title"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<style>
|
||||
<icon>../../images/icons/icons8-notification.svg</icon>
|
||||
</style>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="title" xsi:type="AttributeString">
|
||||
@@ -38,7 +132,7 @@
|
||||
<display_max_height>96</display_max_height>
|
||||
<storage_max_width>256</storage_max_width>
|
||||
<storage_max_height>256</storage_max_height>
|
||||
<default_image>null</default_image>
|
||||
<default_image />
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<sql>priority</sql>
|
||||
@@ -94,6 +188,16 @@
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="fieldset:ActioniTopNotification:trigger">
|
||||
<items>
|
||||
<item id="trigger_list">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="asynchronous">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
@@ -152,29 +256,62 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function DoExecute($oTrigger, $aContextArgs)
|
||||
public function DoExecute($oTrigger, $aContextArgs)
|
||||
{
|
||||
$oRecipientsSearch = DBObjectSearch::FromOQL($this->Get('recipients'));
|
||||
$oRecipientsSearch->AllowAllData();
|
||||
$oRecipientsSet = new DBObjectSet($oRecipientsSearch);
|
||||
$bIsAsync = $this->IsAsynchronous();
|
||||
[$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage();
|
||||
while ($oRecipient = $oRecipientsSet->Fetch()) {
|
||||
$oEvent = new EventiTopNotification();
|
||||
$oEvent->Set('title', MetaModel::ApplyParams($this->Get('title'), $aContextArgs));
|
||||
$oEvent->Set('message', MetaModel::ApplyParams($this->Get('message'), $aContextArgs));
|
||||
$oIcon = !$this->Get('icon')->IsEmpty() ? $this->Get('icon') : MetaModel::GetAttributeDef('EventiTopNotification', 'icon')->MakeRealValue(Combodo\iTop\Application\Branding::GetCompactMainLogoAbsoluteUrl(), $oEvent);
|
||||
$oEvent->Set('icon', $oIcon);
|
||||
$oEvent->Set('priority', $this->Get('priority'));
|
||||
$oEvent->Set('contact_id', $oRecipient->GetKey());
|
||||
$oEvent->Set('trigger_id', $oTrigger->GetKey());
|
||||
$oEvent->Set('action_id', $this->GetKey());
|
||||
$iObjectId = array_key_exists('this->object()', $aContextArgs) ? $aContextArgs['this->object()']->GetKey() : 0;
|
||||
$oEvent->Set('object_id', $iObjectId);
|
||||
$oEvent->Set('url', MetaModel::ApplyParams($this->Get('url'), $aContextArgs));
|
||||
$oEvent->DBInsertNoReload();
|
||||
|
||||
if($bIsAsync === true){
|
||||
$aRecipients = [];
|
||||
}
|
||||
|
||||
$sMessage = MetaModel::ApplyParams($this->Get('message'), $aContextArgs);
|
||||
$sTitle = MetaModel::ApplyParams($this->Get('title'), $aContextArgs);
|
||||
$sUrl = MetaModel::ApplyParams($this->Get('url'), $aContextArgs);
|
||||
$iObjectId = 0;
|
||||
$sObjectClass = null;
|
||||
if (array_key_exists('this->object()', $aContextArgs)) {
|
||||
$iObjectId = $aContextArgs['this->object()']->GetKey();
|
||||
$sObjectClass = get_class($aContextArgs['this->object()']);
|
||||
}
|
||||
|
||||
while ($oRecipient = $oRecipientsSet->Fetch()) {
|
||||
// Skip recipients that have no users
|
||||
if (get_class($oRecipient) === Person::class && UserRights::GetUserFromPerson($oRecipient) === null) {
|
||||
continue;
|
||||
}
|
||||
if (!\Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->IsSubscribed($oTrigger, $this, $oRecipient)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if($bIsAsync === true) {
|
||||
$aRecipients[] = $oRecipient->GetKey();
|
||||
} else {
|
||||
$oEvent = Combodo\iTop\Service\Notification\Event\EventiTopNotificationService::MakeEventFromAction($this, $oRecipient->GetKey(), $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
$oEvent->DBInsertNoReload();
|
||||
}
|
||||
|
||||
\Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oRecipient);
|
||||
}
|
||||
if ($bIsAsync === true) {
|
||||
AsyncSendiTopNotifications::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipients, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
}
|
||||
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAsynchronousGlobalSetting">
|
||||
<comment></comment>
|
||||
<static>true</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public static function GetAsynchronousGlobalSetting(): bool
|
||||
{
|
||||
return utils::GetConfig()->Get('notifications.itop.send_asynchronously');
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
@@ -207,7 +344,7 @@
|
||||
<sql>icon</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<default_image>null</default_image>
|
||||
<default_image />
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<sql>priority</sql>
|
||||
@@ -259,7 +396,18 @@
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation/>
|
||||
<presentation>
|
||||
<summary>
|
||||
<items>
|
||||
<item id="date">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="message">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</summary>
|
||||
</presentation>
|
||||
<methods/>
|
||||
</class>
|
||||
</classes>
|
||||
|
||||
@@ -210,6 +210,7 @@ abstract class DBObject implements iDisplay
|
||||
const MAX_UPDATE_LOOP_COUNT = 10;
|
||||
|
||||
private $aEventListeners = [];
|
||||
private array $aAllowedTransitions = [];
|
||||
|
||||
/**
|
||||
* DBObject constructor.
|
||||
@@ -608,11 +609,10 @@ abstract class DBObject implements iDisplay
|
||||
* Attributes setter
|
||||
*
|
||||
* Set $sAttCode to $value.
|
||||
* The value must be valid according to the type of attribute.
|
||||
* The value must be valid according to the type of attribute : see the different {@see AttributeDefinition::MakeRealValue()} implementations
|
||||
* The value will not be recorded into the DB until DBObject::DBWrite() is called.
|
||||
*
|
||||
* @api
|
||||
* @see DBWrite()
|
||||
*
|
||||
* @param string $sAttCode
|
||||
* @param mixed $value
|
||||
@@ -620,6 +620,8 @@ abstract class DBObject implements iDisplay
|
||||
* @return bool
|
||||
* @throws CoreException
|
||||
* @throws CoreUnexpectedValue
|
||||
*
|
||||
* @see DBWrite()
|
||||
*/
|
||||
public function Set($sAttCode, $value)
|
||||
{
|
||||
@@ -2355,6 +2357,8 @@ abstract class DBObject implements iDisplay
|
||||
$oUniquenessQuery->AddConditionForInOperatorUsingParam('finalclass', $aChildClassesWithRuleDisabled, false);
|
||||
}
|
||||
|
||||
$oUniquenessQuery->AllowAllData();
|
||||
|
||||
return $oUniquenessQuery;
|
||||
}
|
||||
|
||||
@@ -4401,9 +4405,32 @@ abstract class DBObject implements iDisplay
|
||||
]);
|
||||
}
|
||||
|
||||
$this->aAllowedTransitions = $aSortedTransitions;
|
||||
$this->FireEvent(EVENT_ENUM_TRANSITIONS, ['allowed_stimuli' => array_keys($aSortedTransitions)]);
|
||||
$aSortedTransitions = $this->aAllowedTransitions;
|
||||
$this->aAllowedTransitions = [];
|
||||
|
||||
return $aSortedTransitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a transition for a specific stimulus.
|
||||
* This is only usable by EVENT_ENUM_TRANSITIONS listeners in order
|
||||
* to manage the allowed transitions in the current object state.
|
||||
*
|
||||
* @param string $sStimulus
|
||||
*
|
||||
* @return void
|
||||
* @api
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public function DenyTransition(string $sStimulus): void
|
||||
{
|
||||
if (isset($this->aAllowedTransitions[$sStimulus])) {
|
||||
unset($this->aAllowedTransitions[$sStimulus]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to reset a stop-watch
|
||||
* Suitable for use as a lifecycle action
|
||||
@@ -4489,14 +4516,6 @@ abstract class DBObject implements iDisplay
|
||||
$sNewState = $aTransitionDef['target_state'];
|
||||
$this->Set($sStateAttCode, $sNewState);
|
||||
|
||||
$aEventData = [
|
||||
'stimulus' => $sStimulusCode,
|
||||
'previous_state' => $sPreviousState,
|
||||
'new_state' => $sNewState,
|
||||
'save_object' => !$bDoNotWrite,
|
||||
];
|
||||
$this->FireEvent(EVENT_DB_BEFORE_APPLY_STIMULUS, $aEventData);
|
||||
|
||||
// $aTransitionDef is an
|
||||
// array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
|
||||
|
||||
@@ -4581,8 +4600,6 @@ abstract class DBObject implements iDisplay
|
||||
if (!$bDoNotWrite) {
|
||||
$this->DBWrite();
|
||||
}
|
||||
|
||||
$this->FireEvent(EVENT_DB_AFTER_APPLY_STIMULUS, $aEventData);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4591,8 +4608,6 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
$this->m_aCurrValues[$sAttCode] = $aBackupValues[$sAttCode];
|
||||
}
|
||||
$aEventData['action'] = $sActionDesc;
|
||||
$this->FireEvent(EVENT_DB_APPLY_STIMULUS_FAILED, $aEventData);
|
||||
}
|
||||
return $bSuccess;
|
||||
}
|
||||
@@ -4729,7 +4744,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
}
|
||||
$oDate->modify($sModifier);
|
||||
$this->Set($sAttCode, $oDate->format('Y-m-d H:i:s'));
|
||||
$this->Set($sAttCode, $oDate->getTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,102 @@
|
||||
|
||||
/** @internal Dev hack for disabling some query build optimizations (Folding/Merging) */
|
||||
define('ENABLE_OPT', true);
|
||||
class DBSharedSearch extends DBObjectSearch {
|
||||
|
||||
public function MakeSelectQuery($aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulSQL = true)
|
||||
{
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
// and make sure that the ordering columns are going to be selected
|
||||
//
|
||||
$sClass = $this->GetClass();
|
||||
$sClassAlias = $this->GetClassAlias();
|
||||
$aOrderSpec = array();
|
||||
foreach ($aOrderBy as $sFieldAlias => $bAscending)
|
||||
{
|
||||
if (!is_bool($bAscending))
|
||||
{
|
||||
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
|
||||
}
|
||||
|
||||
$iDotPos = strpos($sFieldAlias, '.');
|
||||
if ($iDotPos === false)
|
||||
{
|
||||
$sAttClass = $sClass;
|
||||
$sAttClassAlias = $sClassAlias;
|
||||
$sAttCode = $sFieldAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAttClassAlias = substr($sFieldAlias, 0, $iDotPos);
|
||||
$sAttClass = $this->GetClassName($sAttClassAlias);
|
||||
$sAttCode = substr($sFieldAlias, $iDotPos + 1);
|
||||
}
|
||||
|
||||
if ($sAttCode != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sAttCode, MetaModel::GetAttributesList($sAttClass));
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sAttClass, $sAttCode);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sAttClassAlias) as $sSQLExpression)
|
||||
{
|
||||
$aOrderSpec[$sSQLExpression] = $bAscending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderSpec['`'.$sAttClassAlias.$sAttCode.'`'] = $bAscending;
|
||||
}
|
||||
|
||||
// Make sure that the columns used for sorting are present in the loaded columns
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sAttClassAlias][$sAttCode]))
|
||||
{
|
||||
$aAttToLoad[$sAttClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sAttClass, $sAttCode);
|
||||
}
|
||||
}
|
||||
/*******START difference with MakeSelectQuery **************/
|
||||
$sClass = key($aAttToLoad);
|
||||
$sKey = $aAttToLoad[$sClass][0];
|
||||
$oObjId = new FieldExpression($sKey, $sClass);
|
||||
|
||||
$oSQLQuery = $this->GetSQLQuery($aOrderBy, $aArgs, [], $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, null, [$oObjId] );
|
||||
/********END difference with MakeSelectQuery*************/
|
||||
|
||||
if ($this->m_bNoContextParameters)
|
||||
{
|
||||
// Only internal parameters
|
||||
$aScalarArgs = $this->GetInternalParams();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The complete list of arguments will include magic arguments (e.g. current_user->attcode)
|
||||
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
|
||||
}
|
||||
try
|
||||
{
|
||||
$sRes = $oSQLQuery->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, $bBeautifulSQL);
|
||||
if ($sClassAlias == '_itop_')
|
||||
{
|
||||
IssueLog::Info('SQL Query (_itop_): '.$sRes);
|
||||
}
|
||||
}
|
||||
catch (MissingQueryArgument $e)
|
||||
{
|
||||
// Add some information...
|
||||
$e->addInfo('OQL', $this->ToOQL());
|
||||
throw $e;
|
||||
}
|
||||
$this->AddQueryTraceSelect($oSQLQuery->GetSourceOQL(), $aOrderBy, $aScalarArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sRes);
|
||||
return $sRes;
|
||||
}
|
||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
|
||||
{
|
||||
$oSQLQuery = parent::GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr, $aSelectExpr);
|
||||
|
||||
$oSQLQuery->SetSelect($aSelectExpr);
|
||||
return $oSQLQuery;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* A search over a DBObject
|
||||
*
|
||||
@@ -909,15 +1004,15 @@ class DBObjectSearch extends DBSearch
|
||||
*/
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
{
|
||||
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
|
||||
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
|
||||
{
|
||||
throw new CoreWarning("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}'");
|
||||
}
|
||||
$oAttExtKey = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode);
|
||||
if(!MetaModel::IsSameFamilyBranch($oFilter->GetClass(), $oAttExtKey->GetTargetClass()))
|
||||
{
|
||||
throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
|
||||
}
|
||||
throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
|
||||
}
|
||||
if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !($oAttExtKey instanceof AttributeHierarchicalKey))
|
||||
{
|
||||
throw new CoreException("The specified tree operator $iOperatorCode is not applicable to the key '{$this->GetClass()}::$sExtKeyAttCode', which is not a HierarchicalKey");
|
||||
@@ -1616,6 +1711,10 @@ class DBObjectSearch extends DBSearch
|
||||
{
|
||||
return NestedQueryExpression::FromOQLObjectQuery($oExpression->GetOQLObjectQuery());
|
||||
}
|
||||
elseif ($oExpression instanceof SharedQueryExpression)
|
||||
{
|
||||
return SharedQueryExpression::FromOQLObjectQuery($oExpression->GetOQLObjectQuery());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CoreException('Unknown expression type', array('class'=>get_class($oExpression), 'query'=>$sQuery));
|
||||
|
||||
@@ -851,11 +851,11 @@ abstract class DBSearch
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($aColumns) == 0)
|
||||
{
|
||||
$aColumns = array_keys(MetaModel::ListAttributeDefs($this->GetClass()));
|
||||
// Add the standard id (as first column)
|
||||
array_unshift($aColumns, 'id');
|
||||
if (count($aColumns) == 0)
|
||||
{
|
||||
$aColumns = array_keys(MetaModel::ListAttributeDefs($this->GetClass()));
|
||||
// Add the standard id (as first column)
|
||||
array_unshift($aColumns, 'id');
|
||||
}
|
||||
|
||||
$aQueryCols = CMDBSource::GetColumns($resQuery, $sSQL);
|
||||
@@ -885,6 +885,55 @@ abstract class DBSearch
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a column ($sAttCode) from the specified class ($sClassAlias - default main class) of the DBsearch object and gives the result as an array
|
||||
* @param string $sAttCode
|
||||
* @param string|null $sClassAlias
|
||||
*
|
||||
* @return array
|
||||
* @throws ConfigException
|
||||
* @throws CoreException
|
||||
* @throws MissingQueryArgument
|
||||
* @throws MySQLException
|
||||
* @throws MySQLHasGoneAwayException
|
||||
*/
|
||||
public function SelectAttributeToArray(string $sAttCode, ?string $sClassAlias = null):array
|
||||
{
|
||||
if(is_null($sClassAlias)) {
|
||||
$sClassAlias = $this->GetClassAlias();
|
||||
}
|
||||
|
||||
$sClass = $this->GetClass();
|
||||
if($sAttCode === 'id'){
|
||||
$aAttToLoad[$sClassAlias]=[];
|
||||
} else {
|
||||
$aAttToLoad[$sClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
}
|
||||
|
||||
$sSQL = $this->MakeSelectQuery([], [], $aAttToLoad);
|
||||
$resQuery = CMDBSource::Query($sSQL);
|
||||
if (!$resQuery)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$sColName = $sClassAlias.$sAttCode;
|
||||
|
||||
$aRes = [];
|
||||
while ($aRow = CMDBSource::FetchArray($resQuery))
|
||||
{
|
||||
$aMappedRow = array();
|
||||
if($sAttCode === 'id') {
|
||||
$aMappedRow[$sAttCode] = $aRow[$sColName];
|
||||
} else {
|
||||
$aMappedRow[$sAttCode] = $aAttToLoad[$sClassAlias][$sAttCode]->FromSQLToValue($aRow, $sColName);
|
||||
}
|
||||
$aRes[] = $aMappedRow;
|
||||
}
|
||||
CMDBSource::FreeResult($resQuery);
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Construction of the SQL queries
|
||||
|
||||
@@ -64,16 +64,22 @@ class DesignDocument extends DOMDocument
|
||||
/**
|
||||
* Overload of the standard API
|
||||
*
|
||||
* @param $filename
|
||||
* @param string $filename
|
||||
* @param int $options
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function load($filename, $options = null)
|
||||
public function load(string $filename, int $options = 0): bool
|
||||
{
|
||||
libxml_clear_errors();
|
||||
if (parent::load($filename, LIBXML_NOBLANKS) === false) {
|
||||
$aErrors = libxml_get_errors();
|
||||
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,7 @@ class DisplayableNode extends GraphNode
|
||||
{
|
||||
public $x;
|
||||
public $y;
|
||||
public bool $bFiltered;
|
||||
|
||||
/**
|
||||
* Create a new node inside a graph
|
||||
|
||||
@@ -1090,6 +1090,11 @@ class DeadLockLog extends LogAPI
|
||||
*/
|
||||
class DeprecatedCallsLog extends LogAPI
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.2.0 N°4897
|
||||
*/
|
||||
public const ENUM_CHANNEL_PHP_API = 'deprecated-php-api';
|
||||
public const ENUM_CHANNEL_PHP_METHOD = 'deprecated-php-method';
|
||||
/**
|
||||
* @var string
|
||||
@@ -1283,6 +1288,35 @@ class DeprecatedCallsLog extends LogAPI
|
||||
static::Warning($sMessage, static::ENUM_CHANNEL_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sImplementationClass Class implementing the deprecated API
|
||||
* @param string $sDeprecatedApi Class name of the deprecated API
|
||||
* @param string $sDeprecatedMethod Method name of the deprecated API
|
||||
* @param string|null $sAdditionalMessage Additional message, mostly used to explain what API to use instead
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0 N°4897
|
||||
*/
|
||||
public static function NotifyDeprecatedPhpApi(string $sImplementationClass, string $sDeprecatedApi, string $sDeprecatedMethod, ?string $sAdditionalMessage = null): void
|
||||
{
|
||||
try {
|
||||
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_API)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ConfigException $oException) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sMessage = "Implementation of {$sDeprecatedApi}::{$sDeprecatedMethod}() in class {$sImplementationClass}";
|
||||
|
||||
if (!is_null($sAdditionalMessage)) {
|
||||
$sMessage .= " : $sAdditionalMessage";
|
||||
}
|
||||
|
||||
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_API);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sAdditionalMessage
|
||||
*
|
||||
|
||||
@@ -6846,18 +6846,6 @@ abstract class MetaModel
|
||||
$sClass = $aRow[$sClassAlias."finalclass"];
|
||||
}
|
||||
|
||||
// if an object is already being updated, then this method will return this object instead of recreating a new one.
|
||||
// At this point the method DBUpdate of a new object with the same class and id won't do anything due to reentrance protection,
|
||||
// so to ensure that the potential modifications are correctly saved, the object currently being updated is returned.
|
||||
// DBUpdate() method then will take care that all the modifications will be saved.
|
||||
if (array_key_exists($sClassAlias.'id', $aRow)) {
|
||||
$iKey = $aRow[$sClassAlias."id"];
|
||||
$oObject = self::GetReentranceObject($sClass, $iKey);
|
||||
if ($oObject !== false) {
|
||||
return $oObject;
|
||||
}
|
||||
}
|
||||
|
||||
return new $sClass($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
|
||||
}
|
||||
|
||||
@@ -7180,32 +7168,45 @@ abstract class MetaModel
|
||||
*/
|
||||
public static function PurgeData($oFilter)
|
||||
{
|
||||
$iMaxChunkSize = MetaModel::GetConfig()->Get('purge_data.max_chunk_size');
|
||||
$sTargetClass = $oFilter->GetClass();
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
$oSet->OptimizeColumnLoad(array($sTargetClass => array('finalclass')));
|
||||
$aIdToClass = $oSet->GetColumnAsArray('finalclass', true);
|
||||
$iNbIdsDeleted = 0;
|
||||
$bExecuteQuery = true;
|
||||
|
||||
$aIds = array_keys($aIdToClass);
|
||||
if (count($aIds) > 0)
|
||||
{
|
||||
$aQuotedIds = CMDBSource::Quote($aIds);
|
||||
$sIdList = implode(',', $aQuotedIds);
|
||||
$aTargetClasses = array_merge(
|
||||
self::EnumChildClasses($sTargetClass, ENUM_CHILD_CLASSES_ALL),
|
||||
self::EnumParentClasses($sTargetClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)
|
||||
);
|
||||
foreach($aTargetClasses as $sSomeClass)
|
||||
{
|
||||
$sTable = MetaModel::DBGetTable($sSomeClass);
|
||||
$sPKField = MetaModel::DBGetKey($sSomeClass);
|
||||
// This loop allows you to delete objects in batches of $iMaxChunkSize elements
|
||||
while ($bExecuteQuery) {
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
$oSet->SetLimit($iMaxChunkSize);
|
||||
$oSet->OptimizeColumnLoad(array($sTargetClass => array('finalclass')));
|
||||
$aIdToClass = $oSet->GetColumnAsArray('finalclass', true);
|
||||
|
||||
$sDeleteSQL = "DELETE FROM `$sTable` WHERE `$sPKField` IN ($sIdList)";
|
||||
CMDBSource::DeleteFrom($sDeleteSQL);
|
||||
$aIds = array_keys($aIdToClass);
|
||||
$iNbIds = count($aIds);
|
||||
if ($iNbIds > 0) {
|
||||
$aQuotedIds = CMDBSource::Quote($aIds);
|
||||
$sIdList = implode(',', $aQuotedIds);
|
||||
$aTargetClasses = array_merge(
|
||||
self::EnumChildClasses($sTargetClass, ENUM_CHILD_CLASSES_ALL),
|
||||
self::EnumParentClasses($sTargetClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)
|
||||
);
|
||||
foreach ($aTargetClasses as $sSomeClass) {
|
||||
$sTable = MetaModel::DBGetTable($sSomeClass);
|
||||
$sPKField = MetaModel::DBGetKey($sSomeClass);
|
||||
|
||||
$sDeleteSQL = "DELETE FROM `$sTable` WHERE `$sPKField` IN ($sIdList)";
|
||||
CMDBSource::DeleteFrom($sDeleteSQL);
|
||||
}
|
||||
$iNbIdsDeleted += $iNbIds;
|
||||
}
|
||||
|
||||
// stop loop if query returned fewer objects than $iMaxChunkSize. In this case, all objects have been deleted.
|
||||
if ($iNbIds < $iMaxChunkSize) {
|
||||
$bExecuteQuery = false;
|
||||
}
|
||||
}
|
||||
return count($aIds);
|
||||
}
|
||||
|
||||
return $iNbIdsDeleted;
|
||||
}
|
||||
// Links
|
||||
//
|
||||
//
|
||||
|
||||
@@ -739,7 +739,7 @@ class PHP_ParserGenerator
|
||||
while (isset($errmsg[$restart]) && $errmsg[$restart] == ' ') {
|
||||
$restart++;
|
||||
}
|
||||
printf("%s%.${end}s\n", $prefix, $errmsg);
|
||||
printf("%s%.{$end}s\n", $prefix, $errmsg);
|
||||
$errmsg = substr($errmsg, $restart);
|
||||
}
|
||||
}
|
||||
@@ -771,7 +771,7 @@ class PHP_ParserGenerator
|
||||
for ($j = $i; $j < $this->nsymbol; $j += $skip) {
|
||||
$sp = $this->symbols[$j];
|
||||
//assert( sp->index==j );
|
||||
printf(" %3d %-${maxlen}.${maxlen}s", $j, $sp->name);
|
||||
printf(" %3d %-{$maxlen}.{$maxlen}s", $j, $sp->name);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
@@ -231,19 +231,19 @@ class PHP_ParserGenerator_Action
|
||||
switch ($this->type)
|
||||
{
|
||||
case self::SHIFT:
|
||||
fprintf($fp, "%${indent}s shift %d", $this->sp->name, $this->x->statenum);
|
||||
fprintf($fp, "%{$indent}s shift %d", $this->sp->name, $this->x->statenum);
|
||||
break;
|
||||
case self::REDUCE:
|
||||
fprintf($fp, "%${indent}s reduce %d", $this->sp->name, $this->x->index);
|
||||
fprintf($fp, "%{$indent}s reduce %d", $this->sp->name, $this->x->index);
|
||||
break;
|
||||
case self::ACCEPT:
|
||||
fprintf($fp, "%${indent}s accept", $this->sp->name);
|
||||
fprintf($fp, "%{$indent}s accept", $this->sp->name);
|
||||
break;
|
||||
case self::ERROR:
|
||||
fprintf($fp, "%${indent}s error", $this->sp->name);
|
||||
fprintf($fp, "%{$indent}s error", $this->sp->name);
|
||||
break;
|
||||
case self::CONFLICT:
|
||||
fprintf($fp, "%${indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index);
|
||||
fprintf($fp, "%{$indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index);
|
||||
break;
|
||||
case self::SH_RESOLVED:
|
||||
case self::RD_RESOLVED:
|
||||
|
||||
@@ -170,7 +170,7 @@ class ormCaseLog {
|
||||
}
|
||||
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1))
|
||||
if ($iPos < (utils::StrLen($this->m_sLog) - 1))
|
||||
{
|
||||
$sTextEntry = substr($this->m_sLog, $iPos);
|
||||
|
||||
@@ -293,7 +293,7 @@ class ormCaseLog {
|
||||
}
|
||||
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1)) {
|
||||
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
|
||||
$sTextEntry = substr($this->m_sLog, $iPos);
|
||||
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
|
||||
|
||||
@@ -374,7 +374,7 @@ class ormCaseLog {
|
||||
}
|
||||
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1)) {
|
||||
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
|
||||
$sTextEntry = substr($this->m_sLog, $iPos);
|
||||
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
|
||||
|
||||
@@ -468,7 +468,7 @@ class ormCaseLog {
|
||||
$oBlock->AddSubBlock($oCollapsibleBlock);
|
||||
}
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1)) {
|
||||
if ($iPos < (utils::StrLen($this->m_sLog) - 1)) {
|
||||
// In this case the format is always "text"
|
||||
$sTextEntry = substr($this->m_sLog, $iPos);
|
||||
$sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", utils::EscapeHtml($sTextEntry));
|
||||
|
||||
@@ -344,6 +344,6 @@ class ormDocument
|
||||
*/
|
||||
public function GetSignature(): string
|
||||
{
|
||||
return md5($this->GetData());
|
||||
return md5($this->GetData() ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +53,10 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
MetaModel::Init_AddAttribute(new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags, true), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12)));
|
||||
// "complement" is a computed field, fed by Trigger sub-classes, in general in ComputeValues method, for eg. the TriggerOnObject fed it with target_class info
|
||||
MetaModel::Init_AddAttribute(new AttributeString("complement", array("allowed_values" => null, "sql" => "complement", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", array("allowed_values" => new ValueSetEnum('allow_no_channel,force_at_least_one_channel,force_all_channels'), "sql" => "subscription_policy", "default_value" => 'allow_no_channel', "is_null_allowed" => false, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'action_list', 'complement')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'subscription_policy', 'action_list', 'complement')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'complement')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
|
||||
@@ -111,19 +112,31 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
return;
|
||||
}
|
||||
|
||||
$aContextArgs['trigger->object()'] = $this;
|
||||
|
||||
// Find the related actions
|
||||
$oLinkedActions = $this->Get('action_list');
|
||||
while ($oLink = $oLinkedActions->Fetch())
|
||||
{
|
||||
/** @var \DBObject $oLink */
|
||||
$iActionId = $oLink->Get('action_id');
|
||||
/** @var \Action $oAction */
|
||||
$oAction = MetaModel::GetObject('Action', $iActionId);
|
||||
if ($oAction->IsActive())
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oAction->DoExecute($this, $aContextArgs);
|
||||
$oKPI->ComputeStatsForExtension($oAction, 'DoExecute');
|
||||
|
||||
// Order actions as expected
|
||||
$aActionListOrdered = [];
|
||||
while ($oLink = $oLinkedActions->Fetch()) {
|
||||
$aActionListOrdered[(int) $oLink->Get('order')][] = $oLink;
|
||||
}
|
||||
ksort($aActionListOrdered);
|
||||
|
||||
// Execute actions
|
||||
foreach ($aActionListOrdered as $aActionSubList) {
|
||||
foreach ($aActionSubList as $oLink) /** @var \DBObject $oLink */ {
|
||||
/** @var \DBObject $oLink */
|
||||
$iActionId = $oLink->Get('action_id');
|
||||
/** @var \Action $oAction */
|
||||
$oAction = MetaModel::GetObject('Action', $iActionId);
|
||||
if ($oAction->IsActive()) {
|
||||
$oKPI = new ExecutionKPI();
|
||||
$aContextArgs['action->object()'] = $oAction;
|
||||
$oAction->DoExecute($this, $aContextArgs);
|
||||
$oKPI->ComputeStatsForExtension($oAction, 'DoExecute');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,7 +451,7 @@ class TriggerOnStateEnter extends TriggerOnStateChange
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
|
||||
@@ -471,7 +484,7 @@ class TriggerOnStateLeave extends TriggerOnStateChange
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
|
||||
@@ -504,7 +517,7 @@ class TriggerOnObjectCreate extends TriggerOnObject
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
|
||||
@@ -537,7 +550,7 @@ class TriggerOnObjectDelete extends TriggerOnObject
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
|
||||
@@ -572,7 +585,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
||||
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', array("allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => array('target_class'))));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
|
||||
@@ -668,7 +681,7 @@ class TriggerOnObjectMention extends TriggerOnObject
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("mentioned_filter", array("allowed_values" => null, "sql" => "mentioned_filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'mentioned_filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'mentioned_filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
|
||||
|
||||
@@ -162,7 +162,7 @@ abstract class UserRightsAddOnAPI
|
||||
$oSearchSharers->AllowAllData();
|
||||
$oSearchSharers->AddCondition_ReferencedBy($oShareSearch, 'sharing_org_id');
|
||||
$aSharers = array();
|
||||
foreach($oSearchSharers->ToDataArray(array('id')) as $aRow)
|
||||
foreach($oSearchSharers->SelectAttributeToArray('id') as $aRow)
|
||||
{
|
||||
$aSharers[] = $aRow['id'];
|
||||
}
|
||||
@@ -180,23 +180,17 @@ abstract class UserRightsAddOnAPI
|
||||
$sShareClass = $aShareProperties['share_class'];
|
||||
$sShareAttCode = $aShareProperties['attcode'];
|
||||
|
||||
$oSearchShares = new DBObjectSearch($sShareClass);
|
||||
$oSearchShares->AllowAllData();
|
||||
$oSearchShares = new DBSharedSearch($sShareClass);
|
||||
$oSearchShares->AllowAllData();
|
||||
|
||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
|
||||
$oOrgField = new FieldExpression('org_id', $sShareClass);
|
||||
$oSearchShares->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr));
|
||||
$aShared = array();
|
||||
foreach($oSearchShares->ToDataArray(array($sShareAttCode)) as $aRow)
|
||||
{
|
||||
$aShared[] = $aRow[$sShareAttCode];
|
||||
}
|
||||
if (count($aShared) > 0)
|
||||
{
|
||||
$oObjId = new FieldExpression('id', $sClass);
|
||||
$oSharedIdList = ListExpression::FromScalars($aShared);
|
||||
$oFilter->MergeConditionExpression(new BinaryExpression($oObjId, 'IN', $oSharedIdList));
|
||||
}
|
||||
|
||||
$oNested = SharedQueryExpression::FromOQLObjectQuery($oSearchShares, [$sShareClass =>[$sShareAttCode]]);
|
||||
$oObjId = new FieldExpression('id', $sClass);
|
||||
$oFilter->MergeConditionExpression(new BinaryExpression($oObjId, 'IN', $oNested));
|
||||
|
||||
}
|
||||
} // if HasSharing
|
||||
|
||||
|
||||
@@ -49,3 +49,63 @@
|
||||
.ibo-navigation-menu.ibo-is-active .ibo-navigation-menu--drawer{
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
// Toggler legacy CSS that has somehow been added to iTop 3.0 and that is now used by some extensions
|
||||
// Round Toggle
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: $ibo-color-secondary-600;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: $ibo-color-secondary-300;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: $ibo-color-primary-600;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px $ibo-color-primary-600;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(14.5px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
@@ -11,10 +11,6 @@ $ibo-scrollbar--scrollbar-thumb-background-color: $ibo-color-grey-300 !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-border: none !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-border-radius: $ibo-border-radius-500 !default;
|
||||
|
||||
$ibo-hyperlink-color: $ibo-color-primary-700 !default;
|
||||
$ibo-hyperlink-color--on-hover: $ibo-color-primary-800 !default;
|
||||
$ibo-hyperlink-color--on-active: $ibo-color-primary-900 !default;
|
||||
|
||||
$ibo-svg-illustration--fill: $ibo-color-primary-500 !default;
|
||||
|
||||
$ibo-content-block--background-color: $ibo-color-white-100 !default;
|
||||
@@ -29,10 +25,6 @@ $ibo-content-block--border: 1px solid $ibo-color-grey-400 !default;
|
||||
--ibo-scrollbar--scrollbar-thumb-background-color: #{$ibo-scrollbar--scrollbar-thumb-background-color};
|
||||
--ibo-scrollbar--scrollbar-thumb-border: #{$ibo-scrollbar--scrollbar-thumb-border};
|
||||
--ibo-scrollbar--scrollbar-thumb-border-radius: #{$ibo-scrollbar--scrollbar-thumb-border-radius};
|
||||
|
||||
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
|
||||
--ibo-hyperlink-color--on-hover: #{$ibo-hyperlink-color--on-hover};
|
||||
--ibo-hyperlink-color--on-active: #{$ibo-hyperlink-color--on-active};
|
||||
}
|
||||
|
||||
/* Box sizing reset */
|
||||
@@ -73,17 +65,19 @@ html{
|
||||
/* Hyperlinks reset, ensure that they are of the right color and without decoration everywhere (of course this can be overloaded in some components) */
|
||||
a{
|
||||
color: var(--ibo-hyperlink-color);
|
||||
text-decoration: none;
|
||||
text-decoration: var(--ibo-hyperlink-text-decoration);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:visited{
|
||||
text-decoration: none;
|
||||
text-decoration: var(--ibo-hyperlink-text-decoration);
|
||||
}
|
||||
&:hover{
|
||||
color: var(--ibo-hyperlink-color--on-hover);
|
||||
text-decoration: var(--ibo-hyperlink-text-decoration--on-hover);
|
||||
}
|
||||
&:active{
|
||||
color: var(--ibo-hyperlink-color--on-active);
|
||||
text-decoration: var(--ibo-hyperlink-text-decoration--on-active);
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ $ibo-alert-colors: (
|
||||
$bg-color: nth($aColorValues, 1);
|
||||
$highlight-color: nth($aColorValues, 2);
|
||||
$text-color: nth($aColorValues, 3);
|
||||
.ibo-alert.ibo-is-#{$sColor} {
|
||||
%ibo-alert-#{$sColor}, .ibo-alert.ibo-is-#{$sColor} {
|
||||
background-color: $bg-color;
|
||||
color: $text-color;
|
||||
a {
|
||||
|
||||
@@ -32,4 +32,5 @@
|
||||
@import "search-form";
|
||||
@import "field-badge";
|
||||
@import "file-select";
|
||||
@import "medallion-icon";
|
||||
@import "medallion-icon";
|
||||
@import "toast";
|
||||
@@ -80,16 +80,29 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*N°6543 - We need the rule to keep text inside the column when width is defined*/
|
||||
&[data-attribute-type="AttributeHtml"],
|
||||
&[data-attribute-type="AttributeText"] {
|
||||
&[data-attribute-flag-read-only="true"] {
|
||||
display: grid;
|
||||
|
||||
> .ibo-field--value {
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Large field = Label on top, value below */
|
||||
.ibo-field-large {
|
||||
display: block;
|
||||
/* Large field = Label on top, value below */
|
||||
.ibo-field-large {
|
||||
display: block;
|
||||
|
||||
.ibo-field--label {
|
||||
position: relative; /* Necessary for fullscreen toggler */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ibo-field--label {
|
||||
position: relative; /* Necessary for fullscreen toggler */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: initial;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -36,31 +36,30 @@ $ibo-popover-menu--item--no-message--image--svg--padding : 15px !default;
|
||||
#ibo-navigation-menu--notifications-menu {
|
||||
flex-flow: column;
|
||||
min-width: $ibo-navigation-menu--notifications-menu--min-width;
|
||||
.ibo-navigation-menu--notifications--messages-section{
|
||||
.ibo-navigation-menu--notifications--messages-section {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.ibo-navigation-menu--notifications--show-all-messages, .ibo-navigation-menu--notifications-dismiss-all, .ibo-navigation-menu--notifications-show-all-multiple{
|
||||
.ibo-navigation-menu--notifications--show-all-messages, .ibo-navigation-menu--notifications-dismiss-all, .ibo-navigation-menu--notifications-show-all-multiple {
|
||||
overflow-x: inherit;
|
||||
text-align: center;
|
||||
min-height: 45px;
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications--item--image{
|
||||
.ibo-navigation-menu--notifications--item--image {
|
||||
max-width: $ibo-navigation-menu--notifications--item--image--max-width;
|
||||
max-height: $ibo-navigation-menu--notifications--item--image--max-height;
|
||||
margin: $ibo-navigation-menu--notifications--item--image--margin-y $ibo-navigation-menu--notifications--item--image--margin-x;
|
||||
border-radius: $ibo-navigation-menu--notifications--item--image--border-radius;
|
||||
}
|
||||
|
||||
img.ibo-navigation-menu--notifications--item--image[src=""]{
|
||||
.ibo-navigation-menu--notifications--item--image[src=""] {
|
||||
display: none;
|
||||
}
|
||||
img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-navigation-menu--notifications--item--image
|
||||
{
|
||||
.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ .ibo-navigation-menu--notifications--item--image {
|
||||
display: none;
|
||||
}
|
||||
.ibo-navigation-menu--notifications--item--bottom-text{
|
||||
.ibo-navigation-menu--notifications--item--bottom-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -68,18 +67,23 @@ img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-naviga
|
||||
align-self: center;
|
||||
margin-left: $ibo-navigation-menu--notifications--item--bottom-text--margin-left;
|
||||
}
|
||||
.ibo-navigation-menu--notifications--item--content{
|
||||
.ibo-navigation-menu--notifications--item--content {
|
||||
padding: $ibo-navigation-menu--notifications--item--content--padding-y $ibo-navigation-menu--notifications--item--content--padding-x;
|
||||
img{
|
||||
|
||||
img {
|
||||
max-height: $ibo-navigation-menu--notifications--item--content--img--max-height;
|
||||
padding: $ibo-navigation-menu--notifications--item--content--img--padding;
|
||||
}
|
||||
}
|
||||
.ibo-navigation-menu--notifications-item{
|
||||
.ibo-navigation-menu--notifications-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.ibo-navigation-menu--notifications--item--content a {
|
||||
@extend %ibo-hyperlink-forced-colors;
|
||||
}
|
||||
}
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator{
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator {
|
||||
width: $ibo-navigation-menu--notifications--item--new-message-indicator--width;
|
||||
height: $ibo-navigation-menu--notifications--item--new-message-indicator--height;
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--background-color;
|
||||
@@ -87,22 +91,22 @@ img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-naviga
|
||||
margin-top: $ibo-navigation-menu--notifications--item--new-message-indicator--margin-top;
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu{
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator{
|
||||
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu {
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator {
|
||||
display: inline-block;
|
||||
margin-right: $ibo-navigation-menu--notifications-show-all-multiple--ibo-popover-menu--indicator--margin-right;
|
||||
}
|
||||
.ibo-navigation-menu--notifications-show-all-multiple--counter{
|
||||
.ibo-navigation-menu--notifications-show-all-multiple--counter {
|
||||
@extend %ibo-font-weight-600;
|
||||
}
|
||||
}
|
||||
.ibo-navigation-menu--notifications-dismiss-all--icon{
|
||||
.ibo-navigation-menu--notifications-dismiss-all--icon {
|
||||
margin: $ibo-navigation-menu--notifications-dismiss-all--icon--margin;
|
||||
}
|
||||
.ibo-popover-menu--item--no-message{
|
||||
.ibo-popover-menu--item--no-message {
|
||||
text-align: center;
|
||||
}
|
||||
.ibo-popover-menu--item--no-message--image>svg{
|
||||
.ibo-popover-menu--item--no-message--image > svg {
|
||||
display: flex;
|
||||
width: $ibo-popover-menu--item--no-message--image--svg--width;
|
||||
height: $ibo-popover-menu--item--no-message--image--svg--height;
|
||||
|
||||
@@ -85,6 +85,9 @@ $ibo-panel--collapsible-toggler--margin-right: $ibo-spacing-300 !default;
|
||||
$ibo-panel--collapsible-toggler--font-size: $ibo-font-size-250 !default;
|
||||
$ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
|
||||
|
||||
$ibo-panel--is-selectable--body--after--z-index: $ibo-panel--header--z-index + 1 !default;
|
||||
$ibo-panel--is-selectable--body--after--font-size: $ibo-font-size-700 !default;
|
||||
|
||||
/* Rules */
|
||||
.ibo-panel {
|
||||
--ibo-main-color: #{map-get($ibo-panel-colors, 'neutral')}; /* --ibo-main-color is to allow overload from custom dynamic value from the DM. The overload will be done through an additional CSS class of a particular DM class or DM attribute */
|
||||
@@ -128,6 +131,30 @@ $ibo-panel--collapsible-toggler--color: $ibo-color-grey-700 !default;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.ibo-is-selectable .ibo-panel--body::after {
|
||||
@include ibo-selectable;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: $ibo-panel--is-selectable--body--after--z-index;
|
||||
font-size: $ibo-panel--is-selectable--body--after--font-size;
|
||||
}
|
||||
&.ibo-is-selectable:hover .ibo-panel--body::after {
|
||||
@include ibo-selectable-hover;
|
||||
display: flex;
|
||||
}
|
||||
&.ibo-is-selected .ibo-panel--body::after {
|
||||
@include ibo-selected;
|
||||
display: flex;
|
||||
}
|
||||
&.ibo-is-selected:hover .ibo-panel--body::after {
|
||||
@include ibo-selected-hover;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-panel--header {
|
||||
|
||||
62
css/backoffice/components/_toast.scss
Normal file
62
css/backoffice/components/_toast.scss
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
$ibo-toast--padding-y: $ibo-spacing-400 !default;
|
||||
$ibo-toast--padding-right: $ibo-spacing-300 !default;
|
||||
$ibo-toast--padding-left: $ibo-spacing-500 !default;
|
||||
$ibo-toast--border-radius: $ibo-border-radius-300 !default;
|
||||
$ibo-toast--box-shadow: $ibo-elevation-200 !default;
|
||||
$ibo-toast--max-width: calc(50% - 20px) !default;
|
||||
|
||||
@keyframes decreaseHighlight {
|
||||
0% {
|
||||
height: 100%;
|
||||
}
|
||||
8%{
|
||||
border-radius: 0 0 0 3px;
|
||||
}
|
||||
100% {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-toast {
|
||||
display: inline-flex;
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
|
||||
max-width: $ibo-toast--max-width ;
|
||||
padding: $ibo-toast--padding-y $ibo-toast--padding-right $ibo-toast--padding-y $ibo-toast--padding-left;
|
||||
border-radius: $ibo-toast--border-radius;
|
||||
|
||||
box-shadow: $ibo-toast--box-shadow;
|
||||
transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
z-index: 2147483647;
|
||||
&::before {
|
||||
@include ibo-vertical-highlight;
|
||||
top: initial;
|
||||
bottom: 0;
|
||||
border-radius: $ibo-toast--border-radius 0 0 $ibo-toast--border-radius;
|
||||
}
|
||||
&.ibo-is-auto-closeable::before{
|
||||
animation: decreaseHighlight 5s linear forwards;
|
||||
}
|
||||
&:hover::before {
|
||||
animation: none; /* Pause animation on hover */
|
||||
}
|
||||
&.ibo-is-error{
|
||||
@extend %ibo-alert-danger;
|
||||
}
|
||||
&.ibo-is-warning{
|
||||
@extend %ibo-alert-warning;
|
||||
}
|
||||
&.ibo-is-success{
|
||||
@extend %ibo-alert-success;
|
||||
}
|
||||
&.ibo-is-information{
|
||||
@extend %ibo-alert-information;
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,13 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
|
||||
.ibo-datatable--row-actions-toolbar{
|
||||
justify-content: end;
|
||||
}
|
||||
/* N°6543 - We need the rule to keep text inside the column when width is defined */
|
||||
> [data-attribute-type="AttributeHtml"],
|
||||
> [data-attribute-type="AttributeText"] {
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ $ibo-datatableconfig--settings-panel--option--margin-right: $ibo-spacing-200 !de
|
||||
}
|
||||
.ibo-datatableconfig--attributes-panel--per-page--input{
|
||||
margin: $ibo-datatableconfig--attributes-panel--per-page--input--margin-y $ibo-datatableconfig--attributes-panel--per-page--input--margin-x;
|
||||
max-width: 4em;
|
||||
@extend .ibo-input;
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.ibo-datatableconfig--settings-panel .ibo-panel--body{
|
||||
|
||||
@@ -16,3 +16,4 @@
|
||||
@import "input-one-way-password";
|
||||
@import "input-set";
|
||||
@import "input-text";
|
||||
@import "input-toggler";
|
||||
|
||||
@@ -224,7 +224,11 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
margin-right: $ibo-input-select--autocomplete-item-image--margin-right;
|
||||
background-color: $ibo-input-select--autocomplete-item-image--background-color;
|
||||
border: $ibo-input-select--autocomplete-item-image--border;
|
||||
|
||||
&.ibo-is-not-medallion{
|
||||
border: unset;
|
||||
border-radius: 0;
|
||||
background-color: unset;
|
||||
}
|
||||
@extend %ibo-fully-centered-content;
|
||||
}
|
||||
|
||||
|
||||
72
css/backoffice/components/input/_input-toggler.scss
Normal file
72
css/backoffice/components/input/_input-toggler.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-toggler--wrapper--width: 36px !default;
|
||||
$ibo-toggler--wrapper--height: 20px !default;
|
||||
|
||||
$ibo-toggler--slider--border-radius: $ibo-border-radius-900 !default;
|
||||
$ibo-toggler--slider--background-color: $ibo-color-secondary-600 !default;
|
||||
|
||||
$ibo-toggler--slider--before--height: 15px !default;
|
||||
$ibo-toggler--slider--before--width: 15px !default;
|
||||
$ibo-toggler--slider--before--border-radius: $ibo-border-radius-full !default;
|
||||
$ibo-toggler--slider--before--background-color: $ibo-color-grey-100 !default;
|
||||
|
||||
$ibo-toggler--slider--checked--background-color: $ibo-color-primary-600 !default;
|
||||
$ibo-toggler--slider--focus--box-shadow: 0 0 1px $ibo-color-primary-600 !default;
|
||||
|
||||
$ibo-toggler--label--margin-left: 4px !default;
|
||||
|
||||
|
||||
.ibo-toggler--wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: $ibo-toggler--wrapper--width;
|
||||
height: $ibo-toggler--wrapper--height;
|
||||
vertical-align: baseline;
|
||||
.ibo-toggler {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-toggler--slider{
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: $ibo-toggler--slider--border-radius;
|
||||
background-color: $ibo-toggler--slider--background-color;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.ibo-toggler--slider:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
height: $ibo-toggler--slider--before--height;
|
||||
width: $ibo-toggler--slider--before--width;
|
||||
border-radius: $ibo-toggler--slider--before--border-radius;
|
||||
background-color: $ibo-toggler--slider--before--background-color;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.ibo-toggler--wrapper input:checked + .ibo-toggler--slider {
|
||||
background-color: $ibo-toggler--slider--checked--background-color;
|
||||
}
|
||||
|
||||
input:focus + .ibo-toggler--slider {
|
||||
box-shadow: $ibo-toggler--slider--focus--box-shadow;
|
||||
}
|
||||
|
||||
input:checked + .ibo-toggler--slider:before {
|
||||
transform: translateX(14.5px);
|
||||
}
|
||||
|
||||
label ~ .ibo-toggler--wrapper {
|
||||
margin-left: $ibo-toggler--label--margin-left;
|
||||
}
|
||||
@@ -62,63 +62,4 @@ $ibo-top-bar--toolbar-dashboard-title--max-width: 350px !default;
|
||||
@extend %ibo-full-height-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Round Toggle
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: $ibo-color-secondary-600;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: $ibo-color-secondary-300;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: $ibo-color-primary-600;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px $ibo-color-primary-600;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(14.5px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 7px;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-object-summary--header--margin-y: $ibo-panel--highlight--height!default;
|
||||
$ibo-object-summary--header--margin-top: $ibo-panel--highlight--height!default;
|
||||
$ibo-object-summary--header--margin-bottom: $ibo-spacing-0!default;
|
||||
$ibo-object-summary--header--margin-x: $ibo-spacing-0 !default;
|
||||
|
||||
$ibo-object-summary--header--padding-y: $ibo-spacing-300 !default;
|
||||
@@ -51,7 +52,7 @@ $ibo-object-summary--content--attributes--code--padding-right: $ibo-spacing-500
|
||||
}
|
||||
|
||||
.ibo-object-summary--header{
|
||||
margin: $ibo-object-summary--header--margin-y $ibo-object-summary--header--margin-x;
|
||||
margin: $ibo-object-summary--header--margin-top $ibo-object-summary--header--margin-x $ibo-object-summary--header--margin-bottom $ibo-object-summary--header--margin-x;
|
||||
padding: $ibo-object-summary--header--padding-y $ibo-object-summary--header--padding-x;
|
||||
background-color: $ibo-object-summary--header--background-color;
|
||||
border-bottom: $ibo-object-summary--header--border;
|
||||
|
||||
@@ -15,4 +15,6 @@
|
||||
@import "global-search";
|
||||
@import "run-query";
|
||||
@import "welcome-popup";
|
||||
@import "oauth.wizard";
|
||||
@import "oauth.wizard";
|
||||
@import "notifications";
|
||||
@import "notifications-center";
|
||||
18
css/backoffice/pages/_notifications-center.scss
Normal file
18
css/backoffice/pages/_notifications-center.scss
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
$ibo-input-select--notification-item--mixed-value--color: $ibo-color-primary-800 !default;
|
||||
$ibo-input-select--notification-item--mixed-value--margin-left: 4px !default;
|
||||
|
||||
.ibo-input-select--notification-item {
|
||||
display: flex !important; // override selectize default display with a stronger rule
|
||||
flex-direction: row;
|
||||
@extend .ibo-input-select--autocomplete-item
|
||||
}
|
||||
|
||||
.ibo-input-select--notification-item--mixed-value{
|
||||
font-size: $ibo-font-size-100;
|
||||
color: $ibo-input-select--notification-item--mixed-value--color;
|
||||
margin-left: $ibo-input-select--notification-item--mixed-value--margin-left;
|
||||
}
|
||||
66
css/backoffice/pages/_notifications.scss
Normal file
66
css/backoffice/pages/_notifications.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-notifications--view-all--container--grid-gap: $ibo-spacing-600 !default;
|
||||
$ibo-notifications--view-all--container--object-summary--panel--body--max-height: unset !default;
|
||||
|
||||
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-red-600 !default;
|
||||
$ibo-notifications--view-all--item--read--highlight--background-color: $ibo-color-grey-200 !default;
|
||||
|
||||
$ibo-notifications--view-all--container--large--grid-template-columns: repeat(3, 1fr) !default;
|
||||
$ibo-notifications--view-all--container--medium--grid-template-columns: repeat(2, 1fr) !default;
|
||||
$ibo-notifications--view-all--container--small--grid-template-columns: repeat(1, 1fr) !default;
|
||||
|
||||
$ibo-notifications--view-all--empty--margin-top: $ibo-spacing-950 !default;
|
||||
$ibo-notifications--view-all--empty--svg--max-width: 30% !default;
|
||||
|
||||
.ibo-notifications--view-all--container{
|
||||
display: grid;
|
||||
grid-gap: $ibo-notifications--view-all--container--grid-gap;
|
||||
.ibo-object-summary .ibo-panel--title{
|
||||
font-size: $ibo-font-size-250;
|
||||
}
|
||||
.ibo-object-summary > .ibo-panel--body{
|
||||
box-shadow: none;
|
||||
max-height: $ibo-notifications--view-all--container--object-summary--panel--body--max-height;
|
||||
}
|
||||
.ibo-object-summary + .ibo-object-summary{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
grid-template-columns: $ibo-notifications--view-all--container--small--grid-template-columns;
|
||||
}
|
||||
@include desktop {
|
||||
grid-template-columns: $ibo-notifications--view-all--container--medium--grid-template-columns;
|
||||
}
|
||||
@include fullhd {
|
||||
grid-template-columns: $ibo-notifications--view-all--container--large--grid-template-columns; }
|
||||
}
|
||||
.ibo-notifications--view-all--toolbar {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.ibo-notifications--view-all--toggler {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.ibo-notifications--view-all--item--read .ibo-panel--body::before{
|
||||
background-color: $ibo-notifications--view-all--item--read--highlight--background-color;
|
||||
}
|
||||
.ibo-notifications--view-all--item--unread .ibo-panel--body::before{
|
||||
background-color: $ibo-notifications--view-all--item--unread--highlight--background-color;
|
||||
}
|
||||
|
||||
.ibo-notifications--view-all--empty {
|
||||
@extend %ibo-fully-centered-content;
|
||||
flex-direction: column;
|
||||
margin-top: $ibo-notifications--view-all--empty--margin-top;
|
||||
|
||||
svg {
|
||||
max-width: $ibo-notifications--view-all--empty--svg--max-width;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,23 @@ $ibo-has-description--font-size: 0.7em !default; /* Font size is em on purpose a
|
||||
$ibo-is-code--background-color: $ibo-color-white-200 !default;
|
||||
$ibo-is-code--padding: 1.25rem 1.5rem !default;
|
||||
|
||||
$ibo-hyperlink-color: $ibo-color-primary-700 !default;
|
||||
$ibo-hyperlink-text-decoration: none !default;
|
||||
$ibo-hyperlink-color--on-hover: $ibo-color-primary-800 !default;
|
||||
$ibo-hyperlink-text-decoration--on-hover: $ibo-hyperlink-text-decoration !default;
|
||||
$ibo-hyperlink-color--on-active: $ibo-color-primary-900 !default;
|
||||
$ibo-hyperlink-text-decoration--on-active: $ibo-hyperlink-text-decoration !default;
|
||||
|
||||
/* CSS variables */
|
||||
:root{
|
||||
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
|
||||
--ibo-hyperlink-text-decoration: #{$ibo-hyperlink-text-decoration};
|
||||
--ibo-hyperlink-color--on-hover: #{$ibo-hyperlink-color--on-hover};
|
||||
--ibo-hyperlink-text-decoration--on-hover: #{$ibo-hyperlink-text-decoration--on-hover};
|
||||
--ibo-hyperlink-color--on-active: #{$ibo-hyperlink-color--on-active};
|
||||
--ibo-hyperlink-text-decoration--on-active: #{$ibo-hyperlink-text-decoration--on-active};
|
||||
}
|
||||
|
||||
/* Rules */
|
||||
%ibo-text-truncated-with-ellipsis {
|
||||
white-space: nowrap;
|
||||
@@ -32,6 +49,20 @@ $ibo-is-code--padding: 1.25rem 1.5rem !default;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
/* Use this when you want the hyperlink to be of the color of its container's text instead of the global hyperlink color */
|
||||
%ibo-hyperlink-forced-colors {
|
||||
color: $ibo-hyperlink-color;
|
||||
text-decoration: $ibo-hyperlink-text-decoration;
|
||||
|
||||
&:hover {
|
||||
color: $ibo-hyperlink-color--on-hover;
|
||||
text-decoration: $ibo-hyperlink-text-decoration--on-hover;
|
||||
}
|
||||
&:active {
|
||||
color: $ibo-hyperlink-color--on-active;
|
||||
text-decoration: $ibo-hyperlink-text-decoration--on-active;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-is-broken-hyperlink {
|
||||
text-decoration: line-through;
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "highlight";
|
||||
@import "highlight";
|
||||
@import "selectable";
|
||||
40
css/backoffice/utils/mixins/_selectable.scss
Normal file
40
css/backoffice/utils/mixins/_selectable.scss
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-selectable--background-color: transparent !default;
|
||||
|
||||
$ibo-selectable--hover--color: $ibo-color-grey-100 !default;
|
||||
$ibo-selectable--hover--background-color: $ibo-color-grey-600 !default;
|
||||
$ibo-selectable--hover--background-opacity: 0.6 !default;
|
||||
|
||||
$ibo-selected--color: $ibo-color-grey-100 !default;
|
||||
$ibo-selected--background-color: $ibo-color-grey-900 !default;
|
||||
$ibo-selected--background-opacity: 0.5 !default;
|
||||
|
||||
$ibo-selected--hover--background-color: $ibo-color-grey-700 !default;
|
||||
$ibo-selected--hover--background-opacity: 0.5 !default;
|
||||
@mixin ibo-selectable {
|
||||
content: ' ';
|
||||
@extend %fa-solid-base;
|
||||
background-color: $ibo-selectable--background-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
@mixin ibo-selectable-hover {
|
||||
@extend %fa-regular-base;
|
||||
content: '\f058';
|
||||
color: $ibo-selectable--hover--color;
|
||||
background-color: transparentize($ibo-selectable--hover--background-color, $ibo-selectable--hover--background-opacity);
|
||||
}
|
||||
|
||||
@mixin ibo-selected {
|
||||
@extend %fa-solid-base;
|
||||
content: '\f058';
|
||||
color: $ibo-selected--color;
|
||||
background-color: transparentize($ibo-selected--background-color, $ibo-selected--background-opacity);
|
||||
}
|
||||
|
||||
@mixin ibo-selected-hover {
|
||||
background-color: transparentize($ibo-selected--hover--background-color, $ibo-selected--hover--background-opacity);
|
||||
}
|
||||
@@ -13,6 +13,7 @@ $ibo-spacing-600: $ibo-size-300 !default;
|
||||
$ibo-spacing-700: $ibo-size-350 !default;
|
||||
$ibo-spacing-800: $ibo-size-400 !default;
|
||||
$ibo-spacing-900: $ibo-size-450 !default;
|
||||
$ibo-spacing-950: $ibo-size-500 !default;
|
||||
|
||||
:root{
|
||||
--ibo-spacing-0: #{$ibo-size-0};
|
||||
|
||||
@@ -15,6 +15,9 @@ $ibo-font-size-400: 2rem !default; /* 24px */
|
||||
$ibo-font-size-450: 2.5rem !default; /* 30px */
|
||||
$ibo-font-size-500: 3rem !default; /* 36px */
|
||||
$ibo-font-size-550: 4rem !default; /* 48px */
|
||||
$ibo-font-size-600: 5rem !default; /* 60px */
|
||||
$ibo-font-size-650: 6rem !default; /* 72px */
|
||||
$ibo-font-size-700: 7rem !default; /* 84px */
|
||||
|
||||
/* Value Common weight name (https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) */
|
||||
$ibo-font-weight-100: 100 !default; /* 100 Thin (Harline) */
|
||||
|
||||
3
css/backoffice/vendors/_all.scss
vendored
3
css/backoffice/vendors/_all.scss
vendored
@@ -17,4 +17,5 @@
|
||||
@import "jquery-treeview";
|
||||
@import "jquery-blockui";
|
||||
@import "magnific-popup";
|
||||
@import "selectize";
|
||||
@import "selectize";
|
||||
@import "toastify";
|
||||
76
css/backoffice/vendors/_toastify.scss
vendored
Normal file
76
css/backoffice/vendors/_toastify.scss
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
|
||||
$ibo-vendors-toastify--right--right: $ibo-spacing-500 !default;
|
||||
$ibo-vendors-toastify--left--left: $ibo-spacing-500 !default;
|
||||
$ibo-vendors-toastify--top--top: -150px !default;
|
||||
$ibo-vendors-toastify--bottom--bottom: -150px !default;
|
||||
|
||||
$ibo-vendors-toastify--close--background: transparent !default;
|
||||
$ibo-vendors-toastify--close--padding: 0 !default;
|
||||
$ibo-vendors-toastify--close--margin-left: $ibo-spacing-300 !default;
|
||||
|
||||
.toastify.on {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
background: $ibo-vendors-toastify--close--background;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
padding: $ibo-vendors-toastify--close--padding;
|
||||
margin-left: $ibo-vendors-toastify--close--margin-left;
|
||||
}
|
||||
|
||||
.toastify-right {
|
||||
right: $ibo-vendors-toastify--right--right;
|
||||
}
|
||||
|
||||
.toastify-left {
|
||||
left: $ibo-vendors-toastify--left--left;
|
||||
}
|
||||
|
||||
.toastify-top {
|
||||
top: $ibo-vendors-toastify--top--top;
|
||||
}
|
||||
|
||||
.toastify-bottom {
|
||||
bottom: $ibo-vendors-toastify--bottom--bottom;
|
||||
}
|
||||
|
||||
.toastify-rounded {
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.toastify-avatar {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
margin: -7px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.toastify-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
max-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 360px) {
|
||||
.toastify-right, .toastify-left {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
Tabs - additional IE specific bug fixes
|
||||
|
||||
Recommended usage (Conditional Comments):
|
||||
<!--[if lte IE 7]>
|
||||
<link rel="stylesheet" href="tabs_ie.css" type="text/css" media="projection, screen" />
|
||||
<![endif]-->
|
||||
|
||||
*/
|
||||
.tabs-nav { /* auto clear */
|
||||
display: inline-block;
|
||||
}
|
||||
.tabs-nav .tabs-disabled a {
|
||||
filter: alpha(opacity=40);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'CAS:Error:UserNotAllowed' => 'User not allowed~~',
|
||||
'CAS:Login:SignIn' => 'Sign in with CAS~~',
|
||||
'CAS:Login:SignInTooltip' => 'Click here to authenticate yourself with the CAS server~~',
|
||||
'CAS:Error:UserNotAllowed' => 'Utente non autorizzato',
|
||||
'CAS:Login:SignIn' => 'Accedi con CAS',
|
||||
'CAS:Login:SignInTooltip' => 'Clicca qui per autenticarti con il server CAS',
|
||||
));
|
||||
|
||||
@@ -18,7 +18,7 @@ class CASLogger implements LoggerInterface
|
||||
CASLog::Enable($sDebugFile);
|
||||
}
|
||||
|
||||
const LEVEL_COMPAT = [
|
||||
public const LEVEL_COMPAT = [
|
||||
LogLevel::EMERGENCY => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::ALERT => LogAPI::LEVEL_ERROR,
|
||||
LogLevel::CRITICAL => LogAPI::LEVEL_ERROR,
|
||||
@@ -29,51 +29,51 @@ class CASLogger implements LoggerInterface
|
||||
LogLevel::DEBUG => LogAPI::LEVEL_DEBUG,
|
||||
];
|
||||
|
||||
public function emergency($message, array $context = array())
|
||||
public function emergency($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function alert($message, array $context = array())
|
||||
public function alert($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function critical($message, array $context = array())
|
||||
public function critical($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function error($message, array $context = array())
|
||||
public function error($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
IssueLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function warning($message, array $context = array())
|
||||
public function warning($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Warning('WARNING: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function notice($message, array $context = array())
|
||||
public function notice($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Info('NOTICE: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function info($message, array $context = array())
|
||||
public function info($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Info('INFO: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function debug($message, array $context = array())
|
||||
public function debug($message, array $context = array()):void
|
||||
{
|
||||
CASLog::Debug('DEBUG: '.$message, CASLog::CHANNEL_DEFAULT, $context);
|
||||
}
|
||||
|
||||
public function log($level, $message, array $context = array())
|
||||
public function log($level, $message, array $context = array()):void
|
||||
{
|
||||
$sLevel = self::LEVEL_COMPAT[$level] ?? LogAPI::LEVEL_ERROR;
|
||||
CASLog::Log($sLevel, strtoupper($level).": $message", CASLog::CHANNEL_DEFAULT, $context);
|
||||
|
||||
@@ -488,7 +488,7 @@ class CASUserProvisioning
|
||||
$aAllProfiles = array();
|
||||
while($oProfile = $oProfilesSet->Fetch())
|
||||
{
|
||||
$aAllProfiles[strtolower($oProfile->GetName())] = $oProfile->GetKey();
|
||||
$aAllProfiles[mb_strtolower($oProfile->GetName())] = $oProfile->GetKey();
|
||||
}
|
||||
|
||||
// Translate the CAS/LDAP group names into iTop profile names
|
||||
@@ -498,9 +498,9 @@ class CASUserProvisioning
|
||||
{
|
||||
if (preg_match($sPattern, $sGroupName, $aMatches))
|
||||
{
|
||||
if (array_key_exists(strtolower($aMatches[1]), $aAllProfiles))
|
||||
if (array_key_exists(mb_strtolower($aMatches[1]), $aAllProfiles))
|
||||
{
|
||||
$aProfiles[] = $aAllProfiles[strtolower($aMatches[1])];
|
||||
$aProfiles[] = $aAllProfiles[mb_strtolower($aMatches[1])];
|
||||
phpCAS::log("Info: Adding the profile '{$aMatches[1]}' from CAS.");
|
||||
}
|
||||
else
|
||||
@@ -522,10 +522,10 @@ class CASUserProvisioning
|
||||
$aCASDefaultProfiles = explode(';', $sCASDefaultProfiles);
|
||||
foreach($aCASDefaultProfiles as $sDefaultProfileName)
|
||||
{
|
||||
if (array_key_exists(strtolower($sDefaultProfileName), $aAllProfiles))
|
||||
if (array_key_exists(mb_strtolower($sDefaultProfileName), $aAllProfiles))
|
||||
{
|
||||
$aProfiles[] = $aAllProfiles[strtolower($sDefaultProfileName)];
|
||||
phpCAS::log("Info: Adding the default profile '".$aAllProfiles[strtolower($sDefaultProfileName)]."' from CAS.");
|
||||
$aProfiles[] = $aAllProfiles[mb_strtolower($sDefaultProfileName)];
|
||||
phpCAS::log("Info: Adding the default profile '".$aAllProfiles[mb_strtolower($sDefaultProfileName)]."' from CAS.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:UserLDAP' => 'Utente LDAP',
|
||||
'Class:UserLDAP+' => 'Utente autenticato da LDAP',
|
||||
'UserLDAP:server' => 'LDAP specifics~~',
|
||||
'UserLDAP:server' => 'Specifiche LDAP',
|
||||
));
|
||||
|
||||
@@ -50,7 +50,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
|
||||
@@ -35,7 +35,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
|
||||
@@ -37,20 +37,20 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:UserLocal' => 'Utente '.ITOP_APPLICATION_SHORT,
|
||||
'Class:UserLocal+' => 'Utente autenticato da '.ITOP_APPLICATION_SHORT,
|
||||
'Class:UserLocal/Attribute:password' => 'Password',
|
||||
'Class:UserLocal/Attribute:password+' => 'user authentication string',
|
||||
'Class:UserLocal/Attribute:expiration' => 'Password expiration~~',
|
||||
'Class:UserLocal/Attribute:expiration+' => 'Password expiration status (requires an extension to have an effect)~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire' => 'Can expire~~',
|
||||
'Class:UserLocal/Attribute:password+' => 'stringa di autenticazione utente',
|
||||
'Class:UserLocal/Attribute:expiration' => 'Scadenza della password',
|
||||
'Class:UserLocal/Attribute:expiration+' => 'Stato della scadenza della password (richiede un\'estensione per avere effetto)',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire' => 'Può scadere',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire' => 'Never expire~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire' => 'Non scade',
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire' => 'Expired~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire' => 'Scaduta',
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'Password monouso',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'La password non può essere cambiata dall\'utente.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Rinnovo della password',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Quando è stata cambiata l\'ultima volta la password',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La password deve essere di almeno 8 caratteri e includere lettere maiuscole, minuscole, numeri e caratteri speciali.',
|
||||
'UserLocal:password:expiration' => 'I campi sottostanti richiedono un\'estensione',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impostare la scadenza della password su "Password monouso" non è consentito per il proprio utente',
|
||||
));
|
||||
|
||||
@@ -35,7 +35,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
|
||||
@@ -47,7 +47,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
|
||||
@@ -49,7 +49,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password~~',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewal~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'theme:darkmoon' => 'Dark moon~~',
|
||||
));
|
||||
'theme:darkmoon' => 'Luna scura',
|
||||
));
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// Database inconsistencies
|
||||
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'DB Tools~~',
|
||||
'Menu:DBToolsMenu' => 'Database integrity~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:Title' => 'Database integrity check~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// Database inconsistencies
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'DB Tools~~',
|
||||
'Menu:DBToolsMenu' => 'Database integrity~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:Title' => 'Database integrity check~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -50,7 +50,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Árva rekord a `%1$s` -ban, kell hogy legyen megfelelője a `%2$s` táblázatban',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => 'Érvénytelen a %1$s külső kulcs (oszlop: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Hiányzik a %1$s külső külcs (oszlop: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => '%1$s értéke érvénytelen (oszlop: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => '%1$s értéke érvénytelen (oszlop: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Néhány felhasználónak egyáltalán nincs fiókja',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Sérült a `%1$s` hierarchikus kulcs',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Lekérési hiba a `%1$s` -nál, %2$d bejegyzés lekérve / %3$d megszámlálva',
|
||||
|
||||
@@ -23,65 +23,65 @@
|
||||
// Database inconsistencies
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'DB Tools~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
'DBTools:Error' => 'Error~~',
|
||||
'DBTools:Count' => 'Count~~',
|
||||
'DBTools:SQLquery' => 'SQL query~~',
|
||||
'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~',
|
||||
'DBTools:SQLresult' => 'SQL result~~',
|
||||
'DBTools:NoError' => 'The database is OK~~',
|
||||
'DBTools:HideIds' => 'Error List~~',
|
||||
'DBTools:ShowIds' => 'Detailed view~~',
|
||||
'DBTools:ShowReport' => 'Report~~',
|
||||
'DBTools:IntegrityCheck' => 'Integrity check~~',
|
||||
'DBTools:FetchCheck' => 'Fetch Check (long)~~',
|
||||
'DBTools:SelectAnalysisType' => 'Select analysis type~~',
|
||||
'DBTools:Analyze' => 'Analyze~~',
|
||||
'DBTools:Details' => 'Show Details~~',
|
||||
'DBTools:ShowAll' => 'Show All Errors~~',
|
||||
'DBTools:Inconsistencies' => 'Database inconsistencies~~',
|
||||
'DBTools:DetailedErrorTitle' => '%2$s error(s) in class %1$s: %3$s~~',
|
||||
'DBTools:DetailedErrorLimit' => 'List limited to %1$s errors~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Broken hierarchical key `%1$s`~~',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~',
|
||||
'DBAnalyzer-Integrity-FinalClass' => 'Field `%2$s`.`%1$s` must have the same value as `%3$s`.`%1$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'Menu:DBToolsMenu' => 'Strumenti DB',
|
||||
'DBTools:Class' => 'Classe',
|
||||
'DBTools:Title' => 'Strumenti di Manutenzione del Database',
|
||||
'DBTools:ErrorsFound' => 'Errori Trovati',
|
||||
'DBTools:Indication' => 'Importante: dopo aver corretto gli errori nel database dovrai eseguire nuovamente l\'analisi poiché verranno generati nuovi errori di coerenza',
|
||||
'DBTools:Disclaimer' => 'AVVERTENZA: EFFETTUA UN BACKUP DEL DATABASE PRIMA DI ESEGUIRE LE CORREZIONI',
|
||||
'DBTools:Error' => 'Errore',
|
||||
'DBTools:Count' => 'Conteggio',
|
||||
'DBTools:SQLquery' => 'Query SQL',
|
||||
'DBTools:FixitSQLquery' => 'Query SQL per la Correzione (indicazione)',
|
||||
'DBTools:SQLresult' => 'Risultato SQL',
|
||||
'DBTools:NoError' => 'Il database è OK',
|
||||
'DBTools:HideIds' => 'Elenco Errori',
|
||||
'DBTools:ShowIds' => 'Vista Dettagliata',
|
||||
'DBTools:ShowReport' => 'Rapporto',
|
||||
'DBTools:IntegrityCheck' => 'Controllo di Integrità',
|
||||
'DBTools:FetchCheck' => 'Controllo di Recupero (lungo)',
|
||||
'DBTools:SelectAnalysisType' => 'Seleziona tipo di analisi',
|
||||
'DBTools:Analyze' => 'Analizza',
|
||||
'DBTools:Details' => 'Mostra Dettagli',
|
||||
'DBTools:ShowAll' => 'Mostra Tutti gli Errori',
|
||||
'DBTools:Inconsistencies' => 'Incoerenze del Database',
|
||||
'DBTools:DetailedErrorTitle' => '%2$s errore(i) nella classe %1$s: %3$s',
|
||||
'DBTools:DetailedErrorLimit' => 'Elenco limitato a %1$s errori',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Record orfano in `%1$s`, dovrebbe avere una controparte nella tabella `%2$s`',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => 'Chiave esterna non valida %1$s (colonna: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Chiave esterna mancante %1$s (colonna: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Valore non valido per %1$s (colonna: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Alcuni account utente non hanno alcun profilo',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Chiave gerarchica non valida `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Errore di conteggio di recupero in `%1$s`, %2$d voci recuperate / %3$d conteggiate',
|
||||
'DBAnalyzer-Integrity-FinalClass' => 'Il campo `%2$s`.`%1$s` deve avere lo stesso valore di `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Il campo `%2$s`.`%1$s` deve contenere una classe valida',
|
||||
));
|
||||
|
||||
// Database Info
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'DBTools:DatabaseInfo' => 'Database Information~~',
|
||||
'DBTools:DatabaseInfo' => 'Informazioni Database',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
'DBTools:Size' => 'Size~~',
|
||||
));
|
||||
|
||||
// Lost attachments
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'DBTools:LostAttachments' => 'Lost attachments~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~',
|
||||
'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~',
|
||||
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~',
|
||||
'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~'
|
||||
'DBTools:LostAttachments' => 'Allegati Persi',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Qui puoi cercare nel tuo database gli allegati persi o mal posizionati. Questo NON è uno strumento di recupero dati, non recupera dati cancellati.',
|
||||
'DBTools:LostAttachments:Button:Analyze' => 'Analizza',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Ripristina',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'Questa azione non può essere annullata, conferma di voler ripristinare i file selezionati.',
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Attendere prego...',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'Prima di tutto, cerca gli allegati persi o mal posizionati analizzando il database.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Risultati dell\'analisi:',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Ottimo! Sembra che tutto sia al posto giusto.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Alcuni allegati (%1$d) sembrano essere mal posizionati. Dai un\'occhiata alla seguente lista e seleziona quelli che vorresti spostare.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Nome del file',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Posizione attuale',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Sposta in...',
|
||||
'DBTools:LostAttachments:Step:RestoreResults' => 'Risultati del ripristino:',
|
||||
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d allegati sono stati ripristinati.',
|
||||
'DBTools:LostAttachments:StoredAsInlineImage' => 'Salvato come immagine in linea',
|
||||
'DBTools:LostAttachments:History' => 'Allegato "%1$s" ripristinato con gli strumenti DB',
|
||||
));
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// Database inconsistencies
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'DB Tools~~',
|
||||
'Menu:DBToolsMenu' => 'Database integrity~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:Title' => 'Database integrity check~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -12,7 +12,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'Инструменты БД',
|
||||
'DBTools:Class' => 'Класс',
|
||||
'DBTools:Title' => 'Инструменты обслуживания базы данных~~',
|
||||
'DBTools:Title' => 'Инструменты обслуживания базы данных',
|
||||
'DBTools:ErrorsFound' => 'Найденные ошибки',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -25,7 +25,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'Database integrity~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:Title' => 'Database integrity check~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// Database inconsistencies
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'DB Tools~~',
|
||||
'Menu:DBToolsMenu' => 'Database integrity~~',
|
||||
'DBTools:Class' => 'Class~~',
|
||||
'DBTools:Title' => 'Database Maintenance Tools~~',
|
||||
'DBTools:Title' => 'Database integrity check~~',
|
||||
'DBTools:ErrorsFound' => 'Errors Found~~',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated~~',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES~~',
|
||||
|
||||
@@ -53,7 +53,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'DBAnalyzer-Integrity-InvalidValue' => '无效的值%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => '一些用户账号没有角色',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => '损坏的层级链 `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已~~',
|
||||
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已',
|
||||
'DBAnalyzer-Integrity-FinalClass' => '字段 `%2$s`.`%1$s` 必须是相同的值, 而不是 `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => '字段 `%2$s`.`%1$s` 必须包含一个有效的类型',
|
||||
));
|
||||
|
||||
@@ -93,12 +93,12 @@
|
||||
<target_class>User</target_class>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="contact_id" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>user_id</extkey_attcode>
|
||||
<target_attcode>contactid</target_attcode>
|
||||
<dependencies>
|
||||
<attribute id="user_id"/>
|
||||
</dependencies>
|
||||
<field id="contact_id" xsi:type="AttributeExternalKey">
|
||||
<sql>contact_id</sql>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<target_class>Person</target_class>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
</fields>
|
||||
<methods>
|
||||
@@ -110,8 +110,14 @@
|
||||
public function DBInsertNoReload()
|
||||
{
|
||||
$this->SetCurrentDateIfNull('creation_date');
|
||||
$this->SetIfNull('user_id', CMDBChange::GetCurrentUserId());
|
||||
$iUserId = CMDBChange::GetCurrentUserId();
|
||||
if(utils::IsNotNullOrEmptyString($iUserId)){
|
||||
$this->SetIfNull('user_id', $iUserId);
|
||||
|
||||
// Get Contact from user
|
||||
$oUser = MetaModel::GetObject('User', $iUserId);
|
||||
$this->SetIfNull('contact_id', $oUser->Get('contactid'));
|
||||
}
|
||||
return parent::DBInsertNoReload();
|
||||
}
|
||||
]]></code>
|
||||
@@ -263,16 +269,15 @@
|
||||
<description>An attachment has been added to an object</description>
|
||||
<replaces>Attachment::AfterUpdate</replaces>
|
||||
<sources>
|
||||
<source id="Attachment">Attachment</source>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The attachment updated</description>
|
||||
<description>The object where the attachment is added</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="target_object">
|
||||
<description>The object to which the attachment is linked</description>
|
||||
<event_datum id="attachment">
|
||||
<description>The attachment added to the objet</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
@@ -285,16 +290,15 @@
|
||||
<description>An attachment has been removed from an object</description>
|
||||
<replaces>Attachment::AfterUpdate</replaces>
|
||||
<sources>
|
||||
<source id="Attachment">Attachment</source>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The attachment updated</description>
|
||||
<description>The object where the attachment is removed</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="target_object">
|
||||
<description>The object to which the attachment is linked</description>
|
||||
<event_datum id="attachment">
|
||||
<description>The attachment removed</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
|
||||
@@ -21,26 +21,26 @@
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Attachments:TabTitle_Count' => 'Attachments (%1$d)~~',
|
||||
'Attachments:EmptyTabTitle' => 'Attachments~~',
|
||||
'Attachments:FieldsetTitle' => 'Attachments~~',
|
||||
'Attachments:DeleteBtn' => 'Delete~~',
|
||||
'Attachments:History_File_Added' => 'Attachment %1$s added.~~',
|
||||
'Attachments:History_File_Removed' => 'Attachment %1$s removed.~~',
|
||||
'Attachments:AddAttachment' => 'Add attachment: ~~',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'File upload in NOT allowed on this system.~~',
|
||||
'Attachment:Max_Go' => '(Maximum file size: %1$s Go)~~',
|
||||
'Attachment:Max_Mo' => '(Maximum file size: %1$s Mo)~~',
|
||||
'Attachment:Max_Ko' => '(Maximum file size: %1$s Ko)~~',
|
||||
'Attachments:NoAttachment' => 'No attachment. ~~',
|
||||
'Attachments:PreviewNotAvailable' => 'Preview not available for this type of attachment.~~',
|
||||
'Attachments:Error:FileTooLarge' => 'File is too large to be uploaded. %1$s~~',
|
||||
'Attachments:Error:UploadedFileEmpty' => 'The received file is empty and cannot be attached.
|
||||
Either you have pushed an empty file,
|
||||
or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_SHORT.' server disk is full.~~',
|
||||
'Attachments:Render:Icons' => 'Display as icons~~',
|
||||
'Attachments:Render:Table' => 'Display as list~~',
|
||||
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area~~',
|
||||
'Attachments:TabTitle_Count' => 'Allegati (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Allegati',
|
||||
'Attachments:FieldsetTitle' => 'Allegati',
|
||||
'Attachments:DeleteBtn' => 'Elimina',
|
||||
'Attachments:History_File_Added' => 'Allegato %1$s aggiunto.',
|
||||
'Attachments:History_File_Removed' => 'Allegato %1$s rimosso.',
|
||||
'Attachments:AddAttachment' => 'Aggiungi allegato: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'Caricamento file NON consentito su questo sistema.',
|
||||
'Attachment:Max_Go' => '(Dimensione massima del file: %1$s GB)',
|
||||
'Attachment:Max_Mo' => '(Dimensione massima del file: %1$s MB)',
|
||||
'Attachment:Max_Ko' => '(Dimensione massima del file: %1$s KB)',
|
||||
'Attachments:NoAttachment' => 'Nessun allegato. ',
|
||||
'Attachments:PreviewNotAvailable' => 'Anteprima non disponibile per questo tipo di allegato.',
|
||||
'Attachments:Error:FileTooLarge' => 'Il file è troppo grande per essere caricato. %1$s',
|
||||
'Attachments:Error:UploadedFileEmpty' => 'Il file ricevuto è vuoto e non può essere allegato.
|
||||
O hai inviato un file vuoto,
|
||||
o chiedi al tuo amministratore di '.ITOP_APPLICATION_SHORT.' se il disco del server '.ITOP_APPLICATION_SHORT.' è pieno.',
|
||||
'Attachments:Render:Icons' => 'Visualizza come icone',
|
||||
'Attachments:Render:Table' => 'Visualizza come lista',
|
||||
'UI:Attachments:DropYourFileHint' => 'Rilascia i file ovunque in quest\'area',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -48,42 +48,42 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:Attachment' => 'Attachment~~',
|
||||
'Class:Attachment' => 'Allegato',
|
||||
'Class:Attachment+' => '~~',
|
||||
'Class:Attachment/Attribute:expire' => 'Expire~~',
|
||||
'Class:Attachment/Attribute:expire' => 'Scadenza',
|
||||
'Class:Attachment/Attribute:expire+' => '~~',
|
||||
'Class:Attachment/Attribute:temp_id' => 'Temporary id~~',
|
||||
'Class:Attachment/Attribute:temp_id' => 'ID temporaneo',
|
||||
'Class:Attachment/Attribute:temp_id+' => '~~',
|
||||
'Class:Attachment/Attribute:item_class' => 'Item class~~',
|
||||
'Class:Attachment/Attribute:item_class' => 'Classe dell\'oggetto',
|
||||
'Class:Attachment/Attribute:item_class+' => '~~',
|
||||
'Class:Attachment/Attribute:item_id' => 'Item~~',
|
||||
'Class:Attachment/Attribute:item_id' => 'Oggetto',
|
||||
'Class:Attachment/Attribute:item_id+' => '~~',
|
||||
'Class:Attachment/Attribute:item_org_id' => 'Item organization~~',
|
||||
'Class:Attachment/Attribute:item_org_id' => 'Organizzazione dell\'oggetto',
|
||||
'Class:Attachment/Attribute:item_org_id+' => '~~',
|
||||
'Class:Attachment/Attribute:contents' => 'Contents~~',
|
||||
'Class:Attachment/Attribute:contents' => 'Contenuti',
|
||||
'Class:Attachment/Attribute:contents+' => '~~',
|
||||
));
|
||||
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Attachments:File:Thumbnail' => 'Icon~~',
|
||||
'Attachments:File:Name' => 'File name~~',
|
||||
'Attachments:File:Date' => 'Upload date~~',
|
||||
'Attachments:File:Uploader' => 'Uploaded by~~',
|
||||
'Attachments:File:Size' => 'Size~~',
|
||||
'Attachments:File:MimeType' => 'Type~~',
|
||||
'Attachments:File:DownloadsCount' => 'Downloads~~',
|
||||
'Attachments:File:Thumbnail' => 'Icona',
|
||||
'Attachments:File:Name' => 'Nome del file',
|
||||
'Attachments:File:Date' => 'Data di caricamento',
|
||||
'Attachments:File:Uploader' => 'Caricato da',
|
||||
'Attachments:File:Size' => 'Dimensione',
|
||||
'Attachments:File:MimeType' => 'Tipo',
|
||||
'Attachments:File:DownloadsCount' => 'Download',
|
||||
));
|
||||
//
|
||||
// Class: Attachment
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:Attachment/Attribute:creation_date' => 'Creation date~~',
|
||||
'Class:Attachment/Attribute:creation_date' => 'Data di creazione',
|
||||
'Class:Attachment/Attribute:creation_date+' => '~~',
|
||||
'Class:Attachment/Attribute:user_id' => 'User id~~',
|
||||
'Class:Attachment/Attribute:user_id' => 'ID utente',
|
||||
'Class:Attachment/Attribute:user_id+' => '~~',
|
||||
'Class:Attachment/Attribute:contact_id' => 'Contact id~~',
|
||||
'Class:Attachment/Attribute:contact_id' => 'ID contatto',
|
||||
'Class:Attachment/Attribute:contact_id+' => '~~',
|
||||
));
|
||||
|
||||
@@ -92,6 +92,6 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)~~',
|
||||
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class~~',
|
||||
'Class:TriggerOnAttachmentDownload' => 'Trigger (al download di un allegato dell\'oggetto)',
|
||||
'Class:TriggerOnAttachmentDownload+' => 'Trigger al download di un allegato di un oggetto di [una sottoclasse di] la classe data',
|
||||
));
|
||||
|
||||
@@ -29,9 +29,9 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'Attachments:History_File_Removed' => 'Attachment %1$s removed.~~',
|
||||
'Attachments:AddAttachment' => 'Add attachment: ~~',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'File upload in NOT allowed on this system.~~',
|
||||
'Attachment:Max_Go' => '(Maximum file size: %1$s Go)~~',
|
||||
'Attachment:Max_Mo' => '(Maximum file size: %1$s Mo)~~',
|
||||
'Attachment:Max_Ko' => '(Maximum file size: %1$s Ko)~~',
|
||||
'Attachment:Max_Go' => '(Maximum file size: %1$s GB)~~',
|
||||
'Attachment:Max_Mo' => '(Maximum file size: %1$s MB)~~',
|
||||
'Attachment:Max_Ko' => '(Maximum file size: %1$s KB)~~',
|
||||
'Attachments:NoAttachment' => 'No attachment. ~~',
|
||||
'Attachments:PreviewNotAvailable' => 'Preview not available for this type of attachment.~~',
|
||||
'Attachments:Error:FileTooLarge' => 'File is too large to be uploaded. %1$s~~',
|
||||
|
||||
@@ -264,7 +264,6 @@ class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExt
|
||||
else
|
||||
{
|
||||
$oAttachmentsRenderer->RenderViewAttachmentsList();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,8 +292,8 @@ class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExt
|
||||
// Remove attachments that are no longer attached to the current object
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentIds))
|
||||
{
|
||||
$aData = ['target_object' => $oObject];
|
||||
$oAttachment->FireEvent(EVENT_REMOVE_ATTACHMENT_FROM_OBJECT, $aData);
|
||||
$aData = ['attachment' => $oAttachment];
|
||||
$oObject->FireEvent(EVENT_REMOVE_ATTACHMENT_FROM_OBJECT, $aData);
|
||||
$oAttachment->DBDelete();
|
||||
$aActions[] = self::GetActionChangeOp($oAttachment, false /* false => deletion */);
|
||||
}
|
||||
@@ -322,8 +321,8 @@ class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExt
|
||||
$oAttachment->DBUpdate();
|
||||
// temporary attachment confirmed, list it in the history
|
||||
$aActions[] = self::GetActionChangeOp($oAttachment, true /* true => creation */);
|
||||
$aData = ['target_object' => $oObject];
|
||||
$oAttachment->FireEvent(EVENT_ADD_ATTACHMENT_TO_OBJECT, $aData);
|
||||
$aData = ['attachment' => $oAttachment];
|
||||
$oObject->FireEvent(EVENT_ADD_ATTACHMENT_TO_OBJECT, $aData);
|
||||
}
|
||||
}
|
||||
if (count($aActions) > 0)
|
||||
|
||||
@@ -194,14 +194,25 @@ SQL;
|
||||
|
||||
$oContainer = MetaModel::GetObject($oAttachment->Get('item_class'), $oAttachment->Get('item_id'), false /* must be found */, true /* allow all data */);
|
||||
|
||||
if ($oContainer)
|
||||
{
|
||||
if ($oContainer) {
|
||||
$oAttachment->SetItem($oContainer, true /*updateonchange*/);
|
||||
$iUpdated++;
|
||||
}
|
||||
}
|
||||
|
||||
SetupLog::Info("Initializing attachment/item_org_id - $iUpdated records have been adjusted");
|
||||
|
||||
if (MetaModel::GetAttributeDef('Attachment', 'contact_id') instanceof AttributeExternalKey) {
|
||||
SetupLog::Info("Upgrading itop-attachment from '$sPreviousVersion' to '$sCurrentVersion'. Starting with 3.2.0, contact_id will be added into the DB...");
|
||||
$sUserTableName = MetaModel::DBGetTable('User');
|
||||
$sUserFieldContactId = MetaModel::GetAttributeDef('User', 'contactid')->Get('sql');
|
||||
$sAttachmentFieldUserId = MetaModel::GetAttributeDef('Attachment', 'user_id')->Get('sql');
|
||||
$sAttachmentFieldContactId = MetaModel::GetAttributeDef('Attachment', 'contact_id')->Get('sql');
|
||||
$sAddContactId = "UPDATE `$sTableName` att, `$sUserTableName` us SET att.`$sAttachmentFieldContactId` = us.`$sUserFieldContactId` WHERE att.`$sAttachmentFieldUserId` = us.id AND att.`$sAttachmentFieldContactId` = 0";
|
||||
|
||||
CMDBSource::Query($sAddContactId);
|
||||
$iNbProcessed = CMDBSource::AffectedRows();
|
||||
SetupLog::Info("| | ".$iNbProcessed." attachment processed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', array(
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...~~',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...~~',
|
||||
'Menu:BackupStatus' => 'Scheduled Backups~~',
|
||||
'bkp-status-title' => 'Scheduled Backups~~',
|
||||
'Menu:BackupStatus' => 'Backups~~',
|
||||
'bkp-status-title' => 'Backups~~',
|
||||
'bkp-status-checks' => 'Settings and checks~~',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s~~',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.~~',
|
||||
@@ -46,7 +46,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
|
||||
'bkp-status-backups-auto' => 'Scheduled backups~~',
|
||||
'bkp-status-backups-manual' => 'Manual backups~~',
|
||||
'bkp-status-backups-none' => 'No backup yet~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s.~~',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-button-backup-now' => 'Backup now!~~',
|
||||
'bkp-button-restore-now' => 'Restore!~~',
|
||||
|
||||
@@ -21,38 +21,36 @@
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...~~',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...~~',
|
||||
'Menu:BackupStatus' => 'Scheduled backups~~',
|
||||
'bkp-status-title' => 'Scheduled Backups~~',
|
||||
'bkp-status-checks' => 'Settings and checks~~',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s~~',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.~~',
|
||||
'bkp-mysqldump-issue' => 'mysqldump could not be executed (retcode=%1$d): Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir~~',
|
||||
'bkp-missing-dir' => 'The target directory <code>%1$s</code> could not be found~~',
|
||||
'bkp-free-disk-space' => '<b>%1$s free</b> in <code>%2$s</code>~~',
|
||||
'bkp-dir-not-writeable' => '%1$s is not writeable~~',
|
||||
'bkp-wrong-format-spec' => 'The current specification to format the file names is wrong (%1$s). A default specification will apply: %2$s~~',
|
||||
'bkp-name-sample' => 'Backup files are named depending on DB identifiers, date and time. Example: %1$s~~',
|
||||
'bkp-week-days' => 'Backups will occur <b>every %1$s at %2$s</b>~~',
|
||||
'bkp-retention' => 'At most <b>%1$d backup files will be kept</b> in the target directory.~~',
|
||||
'bkp-next-to-delete' => 'Will be deleted when the next backup occurs (see the setting "retention_count")~~',
|
||||
'bkp-table-file' => 'File~~',
|
||||
'bkp-table-file+' => 'Only files having the extension .zip are considered as being backup files~~',
|
||||
'bkp-table-size' => 'Size~~',
|
||||
'bkp-table-size+' => '~~',
|
||||
'bkp-table-actions' => 'Actions~~',
|
||||
'bkp-table-actions+' => '~~',
|
||||
'bkp-status-backups-auto' => 'Scheduled backups~~',
|
||||
'bkp-status-backups-manual' => 'Manual backups~~',
|
||||
'bkp-status-backups-none' => 'No backup yet~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s~~',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-button-backup-now' => 'Backup now!~~',
|
||||
'bkp-button-restore-now' => 'Restore!~~',
|
||||
'bkp-confirm-backup' => 'Please confirm that you do request the backup to occur right now.~~',
|
||||
'bkp-confirm-restore' => 'Please confirm that you do want to restore the backup %1$s.~~',
|
||||
'bkp-wait-backup' => 'Please wait for the backup to complete...~~',
|
||||
'bkp-wait-restore' => 'Please wait for the restore to complete...~~',
|
||||
'bkp-success-restore' => 'Restore successfully completed.~~',
|
||||
'bkp-backup-running' => 'Un backup è in corso. Attendere prego...',
|
||||
'bkp-restore-running' => 'Un ripristino è in corso. Attendere prego...',
|
||||
'Menu:BackupStatus' => 'Backup programmati',
|
||||
'bkp-status-title' => 'Backup Programmati',
|
||||
'bkp-status-checks' => 'Impostazioni e controlli',
|
||||
'bkp-mysqldump-ok' => 'mysqldump è presente: %1$s',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump non trovato: %1$s - Assicurarsi che sia installato e nel percorso, o modificare il file di configurazione per regolare mysql_bindir.',
|
||||
'bkp-mysqldump-issue' => 'mysqldump non può essere eseguito (codice di ritorno=%1$d): Assicurarsi che sia installato e nel percorso, o modificare il file di configurazione per regolare mysql_bindir',
|
||||
'bkp-missing-dir' => 'La directory di destinazione <code>%1$s</code> non è stata trovata',
|
||||
'bkp-free-disk-space' => '<b>%1$s libero</b> in <code>%2$s</code>',
|
||||
'bkp-dir-not-writeable' => '%1$s non è scrivibile',
|
||||
'bkp-wrong-format-spec' => 'La specifica attuale per formattare i nomi dei file è sbagliata (%1$s). Verrà applicata una specifica predefinita: %2$s',
|
||||
'bkp-name-sample' => 'I file di backup sono denominati in base agli identificatori del DB, data e ora. Esempio: %1$s',
|
||||
'bkp-week-days' => 'I backup avverranno <b>ogni %1$s alle %2$s</b>',
|
||||
'bkp-retention' => 'Al massimo <b>%1$d file di backup saranno mantenuti</b> nella directory di destinazione.',
|
||||
'bkp-next-to-delete' => 'Sarà cancellato al prossimo avvenimento del backup (vedi impostazione "retention_count")',
|
||||
'bkp-table-file' => 'File',
|
||||
'bkp-table-file+' => 'Solo i file con estensione .zip sono considerati file di backup',
|
||||
'bkp-table-size' => 'Dimensione',
|
||||
'bkp-table-actions' => 'Azioni',
|
||||
'bkp-status-backups-auto' => 'Backup programmati',
|
||||
'bkp-status-backups-manual' => 'Backup manuali',
|
||||
'bkp-status-backups-none' => 'Nessun backup finora',
|
||||
'bkp-next-backup' => 'Il prossimo backup avverrà il <b>%1$s</b> (%2$s) alle %3$s',
|
||||
'bkp-next-backup-unknown' => 'Il prossimo backup <b>non è ancora programmato</b>.',
|
||||
'bkp-button-backup-now' => 'Esegui backup ora!',
|
||||
'bkp-button-restore-now' => 'Ripristina!',
|
||||
'bkp-confirm-backup' => 'Confermare di voler eseguire il backup ora.',
|
||||
'bkp-confirm-restore' => 'Confermare di voler ripristinare il backup %1$s.',
|
||||
'bkp-wait-backup' => 'Attendere il completamento del backup...',
|
||||
'bkp-wait-restore' => 'Attendere il completamento del ripristino...',
|
||||
'bkp-success-restore' => 'Ripristino completato con successo.',
|
||||
));
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...~~',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...~~',
|
||||
'Menu:BackupStatus' => 'Scheduled backups~~',
|
||||
'bkp-status-title' => 'Scheduled Backups~~',
|
||||
'Menu:BackupStatus' => 'Backups~~',
|
||||
'bkp-status-title' => 'Backups~~',
|
||||
'bkp-status-checks' => 'Settings and checks~~',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s~~',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.~~',
|
||||
@@ -46,7 +46,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'bkp-status-backups-auto' => 'Scheduled backups~~',
|
||||
'bkp-status-backups-manual' => 'Manual backups~~',
|
||||
'bkp-status-backups-none' => 'No backup yet~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s.~~',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-button-backup-now' => 'Backup now!~~',
|
||||
'bkp-button-restore-now' => 'Restore!~~',
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...~~',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...~~',
|
||||
'Menu:BackupStatus' => 'Scheduled Backups~~',
|
||||
'bkp-status-title' => 'Scheduled Backups~~',
|
||||
'Menu:BackupStatus' => 'Backups~~',
|
||||
'bkp-status-title' => 'Backups~~',
|
||||
'bkp-status-checks' => 'Settings and checks~~',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s~~',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.~~',
|
||||
@@ -46,7 +46,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'bkp-status-backups-auto' => 'Scheduled backups~~',
|
||||
'bkp-status-backups-manual' => 'Manual backups~~',
|
||||
'bkp-status-backups-none' => 'No backup yet~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s.~~',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-button-backup-now' => 'Backup now!~~',
|
||||
'bkp-button-restore-now' => 'Restore!~~',
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...~~',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...~~',
|
||||
'Menu:BackupStatus' => 'Scheduled Backups~~',
|
||||
'bkp-status-title' => 'Scheduled Backups~~',
|
||||
'Menu:BackupStatus' => 'Backups~~',
|
||||
'bkp-status-title' => 'Backups~~',
|
||||
'bkp-status-checks' => 'Settings and checks~~',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s~~',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.~~',
|
||||
@@ -46,7 +46,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'bkp-status-backups-auto' => 'Scheduled backups~~',
|
||||
'bkp-status-backups-manual' => 'Manual backups~~',
|
||||
'bkp-status-backups-none' => 'No backup yet~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s~~',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s.~~',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-button-backup-now' => 'Backup now!~~',
|
||||
'bkp-button-restore-now' => 'Restore!~~',
|
||||
|
||||
@@ -31,16 +31,16 @@
|
||||
// Class: lnkFunctionalCIToProviderContract
|
||||
//
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:lnkFunctionalCIToProviderContract' => 'Link FunctionalCI / ProviderContract~~',
|
||||
'Class:lnkFunctionalCIToProviderContract' => 'Link FunctionalCI / ProviderContract',
|
||||
'Class:lnkFunctionalCIToProviderContract+' => '~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Name' => '%1$s / %2$s~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => 'Provider contract~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Name' => '%1$s / %2$s',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => 'Contratto Fornitore',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name' => 'Provider contract Name~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name' => 'Nome Fornitore Contratto',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name+' => '~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id' => 'CI~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id' => 'CI',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name' => 'CI Name~~',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name' => 'Nome CI',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name+' => '~~',
|
||||
));
|
||||
|
||||
@@ -49,16 +49,16 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:lnkFunctionalCIToService' => 'Link FunctionalCI / Service~~',
|
||||
'Class:lnkFunctionalCIToService' => 'Link FunctionalCI / Service',
|
||||
'Class:lnkFunctionalCIToService+' => '~~',
|
||||
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_id' => 'Service~~',
|
||||
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_id' => 'Servizio',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name' => 'Service Name~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name' => 'Nome Servizio',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name+' => '~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_id' => 'CI~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_id' => 'CI',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name' => 'CI Name~~',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name' => 'Nome CI ',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name+' => '~~',
|
||||
));
|
||||
|
||||
@@ -67,10 +67,10 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:FunctionalCI/Attribute:providercontracts_list' => 'Provider contracts~~',
|
||||
'Class:FunctionalCI/Attribute:providercontracts_list+' => 'All the provider contracts for this configuration item~~',
|
||||
'Class:FunctionalCI/Attribute:services_list' => 'Services~~',
|
||||
'Class:FunctionalCI/Attribute:services_list+' => 'All the services impacted by this configuration item~~',
|
||||
'Class:FunctionalCI/Attribute:providercontracts_list' => 'Contratti fornitori',
|
||||
'Class:FunctionalCI/Attribute:providercontracts_list+' => 'Tutti i contratti del fornitore per questo elemento di configurazione',
|
||||
'Class:FunctionalCI/Attribute:services_list' => 'Servizi',
|
||||
'Class:FunctionalCI/Attribute:services_list+' => 'Tutti i servizi impattati da questo elemento di configurazione',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -78,8 +78,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
//
|
||||
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:Document/Attribute:contracts_list' => 'Contracts~~',
|
||||
'Class:Document/Attribute:contracts_list+' => 'All the contracts linked to this document~~',
|
||||
'Class:Document/Attribute:services_list' => 'Services~~',
|
||||
'Class:Document/Attribute:services_list+' => 'All the services linked to this document~~',
|
||||
));
|
||||
'Class:Document/Attribute:contracts_list' => 'Contratti',
|
||||
'Class:Document/Attribute:contracts_list+' => 'Tutti i contratti collegati a questo documento',
|
||||
'Class:Document/Attribute:services_list' => 'Servizi',
|
||||
'Class:Document/Attribute:services_list+' => 'Tutti i servizi collegati a questo documento',
|
||||
));
|
||||
|
||||
@@ -32,24 +32,17 @@
|
||||
//
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:lnkFunctionalCIToTicket' => 'Link FunctionalCI / Ticket~~',
|
||||
'Class:lnkFunctionalCIToTicket+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Name' => '%1$s / %2$s~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id' => 'Ticket~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref' => 'Ref~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title' => 'Ticket title~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref' => 'Rif',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title' => 'Titolo del Ticket',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id' => 'CI~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_name' => 'CI Name~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_name+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact' => 'Impact (text)~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact+' => '~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code' => 'Impact~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:manual' => 'Added manually~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:computed' => 'Computed~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => 'Not impacted~~',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_name' => 'Nome CI',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact' => 'Impatto (testo',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code' => 'Impatto',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:manual' => 'Aggiunto manualmente',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:computed' => 'Calcolato',
|
||||
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => 'Non impattato',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -57,5 +50,5 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
//
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:FunctionalCI/Attribute:tickets_list' => 'Tickets~~',
|
||||
'Class:FunctionalCI/Attribute:tickets_list+' => 'All the tickets for this configuration item~~',
|
||||
'Class:FunctionalCI/Attribute:tickets_list+' => 'Tutti i ticket per questo elemento di configurazione',
|
||||
));
|
||||
|
||||
@@ -38,11 +38,11 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Menu:MyChanges' => 'Modifiche assegnate a me',
|
||||
'Menu:MyChanges+' => 'Modifiche assegnato a me (come Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Evoluzioni',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days~~',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days~~',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Changes by status for the last 7 days~~',
|
||||
'Tickets:Related:OpenChanges' => 'Open changes~~',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes (72h)~~',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Numero di cambiamenti negli ultimi 7 giorni',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Cambiamenti per dominio negli ultimi 7 giorni',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Cambiamenti per stato negli ultimi 7 giorni',
|
||||
'Tickets:Related:OpenChanges' => 'Cambiamenti aperti',
|
||||
'Tickets:Related:RecentChanges' => 'Cambiamenti recenti (72h)',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
@@ -119,21 +119,18 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:Change/Attribute:outage/Value:yes+' => '',
|
||||
'Class:Change/Attribute:fallback' => 'Piano alternativo',
|
||||
'Class:Change/Attribute:fallback+' => '',
|
||||
'Class:Change/Attribute:parent_id' => 'Parent change~~',
|
||||
'Class:Change/Attribute:parent_id+' => '~~',
|
||||
'Class:Change/Attribute:parent_name' => 'Parent change Ref~~',
|
||||
'Class:Change/Attribute:parent_name+' => '~~',
|
||||
'Class:Change/Attribute:related_request_list' => 'Related requests~~',
|
||||
'Class:Change/Attribute:related_request_list+' => 'All the user requests linked to this change~~',
|
||||
'Class:Change/Attribute:related_problems_list' => 'Related problems~~',
|
||||
'Class:Change/Attribute:related_problems_list+' => 'All the problems linked to this change~~',
|
||||
'Class:Change/Attribute:related_incident_list' => 'Related incidents~~',
|
||||
'Class:Change/Attribute:related_incident_list+' => 'All the incidents linked to this change~~',
|
||||
'Class:Change/Attribute:child_changes_list' => 'Child changes~~',
|
||||
'Class:Change/Attribute:child_changes_list+' => 'All the sub changes linked to this change~~',
|
||||
'Class:Change/Attribute:parent_id_friendlyname' => 'Parent friendly name~~',
|
||||
'Class:Change/Attribute:parent_id_friendlyname+' => '~~',
|
||||
'Class:Change/Attribute:parent_id_finalclass_recall' => 'Change type~~',
|
||||
'Class:Change/Attribute:parent_id' => 'Cambiamento padre',
|
||||
'Class:Change/Attribute:parent_name' => 'Rif. cambiamento padre',
|
||||
'Class:Change/Attribute:related_request_list' => 'Richieste correlate',
|
||||
'Class:Change/Attribute:related_request_list+' => 'Tutte le richieste utente collegate a questo cambiamento',
|
||||
'Class:Change/Attribute:related_problems_list' => 'Problemi correlati',
|
||||
'Class:Change/Attribute:related_problems_list+' => 'Tutti i problemi collegati a questo cambiamento',
|
||||
'Class:Change/Attribute:related_incident_list' => 'Incidenti correlati',
|
||||
'Class:Change/Attribute:related_incident_list+' => 'Tutti gli incidenti collegati a questo cambiamento',
|
||||
'Class:Change/Attribute:child_changes_list' => 'Cambiamenti figli',
|
||||
'Class:Change/Attribute:child_changes_list+' => 'Tutti i cambiamenti secondari collegati a questo cambiamento',
|
||||
'Class:Change/Attribute:parent_id_friendlyname' => 'Nome amichevole del cambiamento padre',
|
||||
'Class:Change/Attribute:parent_id_finalclass_recall' => 'Tipo di cambiamento',
|
||||
'Class:Change/Attribute:parent_id_finalclass_recall+' => '~~',
|
||||
'Class:Change/Stimulus:ev_validate' => 'Convalida',
|
||||
'Class:Change/Stimulus:ev_validate+' => '',
|
||||
|
||||
@@ -37,13 +37,13 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Menu:Changes' => 'Modifiche aperte',
|
||||
'Menu:Changes+' => 'Tutte le Modifiche aperte',
|
||||
'Menu:MyChanges' => 'Modifiche assegnate a me',
|
||||
'Menu:MyChanges+' => 'Modifiche assegnato a me (come Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes by category for the last 7 days~~',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days~~',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days~~',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Changes by status for the last 7 days~~',
|
||||
'Tickets:Related:OpenChanges' => 'Open changes~~',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes (72h)~~',
|
||||
'Menu:MyChanges+' => 'Modifiche assegnato a me (come operatore)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Cambiamenti per categoria negli ultimi 7 giorni',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Numero di cambiamenti negli ultimi 7 giorni',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Cambiamenti per dominio negli ultimi 7 giorni',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Cambiamenti per stato negli ultimi 7 giorni',
|
||||
'Tickets:Related:OpenChanges' => 'Cambiamenti aperti',
|
||||
'Tickets:Related:RecentChanges' => 'Cambiamenti recenti (72h)',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
@@ -80,43 +80,25 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:Change/Attribute:status/Value:closed+' => '',
|
||||
'Class:Change/Attribute:category' => 'Category~~',
|
||||
'Class:Change/Attribute:category+' => '~~',
|
||||
'Class:Change/Attribute:category/Value:application' => 'application~~',
|
||||
'Class:Change/Attribute:category/Value:application+' => 'application~~',
|
||||
'Class:Change/Attribute:category/Value:hardware' => 'hardware~~',
|
||||
'Class:Change/Attribute:category/Value:hardware+' => 'hardware~~',
|
||||
'Class:Change/Attribute:category/Value:network' => 'network~~',
|
||||
'Class:Change/Attribute:category/Value:network+' => 'network~~',
|
||||
'Class:Change/Attribute:category/Value:other' => 'other~~',
|
||||
'Class:Change/Attribute:category/Value:other+' => 'other~~',
|
||||
'Class:Change/Attribute:category/Value:software' => 'software~~',
|
||||
'Class:Change/Attribute:category/Value:software+' => 'software~~',
|
||||
'Class:Change/Attribute:category/Value:system' => 'system~~',
|
||||
'Class:Change/Attribute:category/Value:system+' => 'system~~',
|
||||
'Class:Change/Attribute:reject_reason' => 'Reject reason~~',
|
||||
'Class:Change/Attribute:reject_reason+' => '~~',
|
||||
'Class:Change/Attribute:changemanager_id' => 'Change manager~~',
|
||||
'Class:Change/Attribute:changemanager_id+' => '~~',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Change manager email~~',
|
||||
'Class:Change/Attribute:changemanager_email+' => '~~',
|
||||
'Class:Change/Attribute:parent_id' => 'Parent change~~',
|
||||
'Class:Change/Attribute:parent_id+' => '~~',
|
||||
'Class:Change/Attribute:parent_name' => 'Parent change ref~~',
|
||||
'Class:Change/Attribute:parent_name+' => '~~',
|
||||
'Class:Change/Attribute:creation_date' => 'Creato',
|
||||
'Class:Change/Attribute:creation_date+' => '~~',
|
||||
'Class:Change/Attribute:approval_date' => 'Approval date~~',
|
||||
'Class:Change/Attribute:approval_date+' => '~~',
|
||||
'Class:Change/Attribute:fallback_plan' => 'Fallback plan~~',
|
||||
'Class:Change/Attribute:fallback_plan+' => '~~',
|
||||
'Class:Change/Attribute:related_request_list' => 'Related requests~~',
|
||||
'Class:Change/Attribute:related_request_list+' => 'All the user requests linked to this change~~',
|
||||
'Class:Change/Attribute:related_incident_list' => 'Related incidents~~',
|
||||
'Class:Change/Attribute:related_incident_list+' => 'All the incidents linked to this change~~',
|
||||
'Class:Change/Attribute:related_problems_list' => 'Related problems~~',
|
||||
'Class:Change/Attribute:related_problems_list+' => 'All the problems linked to this change~~',
|
||||
'Class:Change/Attribute:child_changes_list' => 'Child changes~~',
|
||||
'Class:Change/Attribute:child_changes_list+' => 'All the sub changes linked to this change~~',
|
||||
'Class:Change/Attribute:parent_id_friendlyname' => 'Parent change friendly name~~',
|
||||
'Class:Change/Attribute:category/Value:application' => 'applicazione',
|
||||
'Class:Change/Attribute:category/Value:hardware' => 'hardware',
|
||||
'Class:Change/Attribute:category/Value:network' => 'rete',
|
||||
'Class:Change/Attribute:category/Value:other' => 'altro',
|
||||
'Class:Change/Attribute:category/Value:software' => 'software',
|
||||
'Class:Change/Attribute:category/Value:system' => 'sistema',
|
||||
'Class:Change/Attribute:reject_reason' => 'Motivo del rifiuto',
|
||||
'Class:Change/Attribute:changemanager_id' => 'Gestore del cambiamento',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Email del gestore del cambiamento',
|
||||
'Class:Change/Attribute:parent_id' => 'Cambiamento genitore',
|
||||
'Class:Change/Attribute:parent_name' => 'Rif. del cambiamento genitore',
|
||||
'Class:Change/Attribute:creation_date' => 'Data di creazione',
|
||||
'Class:Change/Attribute:approval_date' => 'Data di approvazione',
|
||||
'Class:Change/Attribute:fallback_plan' => 'Piano di fallback',
|
||||
'Class:Change/Attribute:related_request_list' => 'Richieste correlate',
|
||||
'Class:Change/Attribute:related_incident_list' => 'Incidenti correlati',
|
||||
'Class:Change/Attribute:related_problems_list' => 'Problemi correlati',
|
||||
'Class:Change/Attribute:child_changes_list' => 'Cambiamenti figli',
|
||||
'Class:Change/Attribute:parent_id_friendlyname' => 'Nome del cambiamento genitore',
|
||||
'Class:Change/Attribute:parent_id_friendlyname+' => '~~',
|
||||
'Class:Change/Stimulus:ev_assign' => 'Assegna',
|
||||
'Class:Change/Stimulus:ev_assign+' => '~~',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user