mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-08 11:18:44 +02:00
Compare commits
188 Commits
class_extr
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
587d7fcf72 | ||
|
|
f1735767c3 | ||
|
|
bfdc8a68e6 | ||
|
|
00735f0c54 | ||
|
|
882390e8d6 | ||
|
|
5d0da47f21 | ||
|
|
684eaac278 | ||
|
|
4eadff7f3b | ||
|
|
4ce8f70382 | ||
|
|
f66ce1c956 | ||
|
|
868eea9b43 | ||
|
|
802f9f3e08 | ||
|
|
70a8bdf427 | ||
|
|
38cda442e3 | ||
|
|
20c8b7c0ce | ||
|
|
b58a848cc9 | ||
|
|
5c5d98bb78 | ||
|
|
a08a9b43f3 | ||
|
|
d9433fead5 | ||
|
|
abd85ff4db | ||
|
|
81f328b26e | ||
|
|
9a2c8f10bf | ||
|
|
1a9e4bd5ad | ||
|
|
3cdadf3c6e | ||
|
|
36891e441b | ||
|
|
a6295f1b14 | ||
|
|
ba6b3da238 | ||
|
|
2674e9c47f | ||
|
|
e467ca83cf | ||
|
|
f7b73717b4 | ||
|
|
0d9b34a879 | ||
|
|
7791585387 | ||
|
|
a4a0b3c18c | ||
|
|
3406ca79de | ||
|
|
91ad01055e | ||
|
|
443fa60459 | ||
|
|
804cdffe42 | ||
|
|
63e40fc0a2 | ||
|
|
176bd51afb | ||
|
|
e8a1f8c3b6 | ||
|
|
5f4affc896 | ||
|
|
042fee2360 | ||
|
|
447e7d01d5 | ||
|
|
d4a9d1e831 | ||
|
|
be3726623f | ||
|
|
aae6d324f9 | ||
|
|
398b47d5d1 | ||
|
|
b85f4a5161 | ||
|
|
3c17b1bdea | ||
|
|
7f8ec25977 | ||
|
|
41f8437c23 | ||
|
|
df8b25d4b4 | ||
|
|
9cc80a8946 | ||
|
|
11afd23087 | ||
|
|
511dabe2b0 | ||
|
|
0c517f254c | ||
|
|
347663f8f7 | ||
|
|
c56c7a1f9d | ||
|
|
3d21ff1cd7 | ||
|
|
fb2f0f1447 | ||
|
|
4847bb563a | ||
|
|
8b664ff644 | ||
|
|
902a05cc84 | ||
|
|
b3223eb9b6 | ||
|
|
19d6052460 | ||
|
|
70eaa30e10 | ||
|
|
458a996c29 | ||
|
|
a6de103b4a | ||
|
|
9328f6d916 | ||
|
|
c61b21559c | ||
|
|
0d18572fbe | ||
|
|
9db21ab860 | ||
|
|
ed33238750 | ||
|
|
272678b8cd | ||
|
|
3a435eba7d | ||
|
|
170014e8f0 | ||
|
|
df05a4688e | ||
|
|
006f666089 | ||
|
|
960990d47d | ||
|
|
99d39732a5 | ||
|
|
5e916510fb | ||
|
|
2a16143e53 | ||
|
|
0be4f52b04 | ||
|
|
f7d41d3650 | ||
|
|
eabbe2f00b | ||
|
|
52e303cb37 | ||
|
|
58790bc352 | ||
|
|
0b19333cd7 | ||
|
|
da09c701cc | ||
|
|
7c8670b57c | ||
|
|
1c1f01aed5 | ||
|
|
5d6e2cc9f7 | ||
|
|
28db230697 | ||
|
|
4fe61cbdc7 | ||
|
|
3c5bf8a134 | ||
|
|
e2994b645b | ||
|
|
32ddf1c980 | ||
|
|
0f7540dec8 | ||
|
|
a36a7cc832 | ||
|
|
3dd1c11d3b | ||
|
|
9fca81cc32 | ||
|
|
9792358aea | ||
|
|
7bfa14a874 | ||
|
|
9236449b21 | ||
|
|
b3613b6c4b | ||
|
|
ab8e7bd15e | ||
|
|
307c308eb0 | ||
|
|
61e5536b50 | ||
|
|
104dd1970f | ||
|
|
884d64a42a | ||
|
|
44c0a025a8 | ||
|
|
929b8b9eca | ||
|
|
3b8e079cf1 | ||
|
|
36247ba0ee | ||
|
|
091d99b08f | ||
|
|
3c60a80f9b | ||
|
|
ae633111c0 | ||
|
|
52a1d8d626 | ||
|
|
3a64e3bb9e | ||
|
|
fc967c06ce | ||
|
|
d4821b7edc | ||
|
|
94a36c0066 | ||
|
|
62e09f1224 | ||
|
|
57a0b5691f | ||
|
|
f82389d156 | ||
|
|
9e21976424 | ||
|
|
f558093f5d | ||
|
|
5201a1ed3b | ||
|
|
dad39c3ebe | ||
|
|
29920bfeb7 | ||
|
|
2313ee2bbd | ||
|
|
22b0c431a0 | ||
|
|
499b3bca88 | ||
|
|
aede5ea7b8 | ||
|
|
da6c443a35 | ||
|
|
9c39efd9af | ||
|
|
d5f2303ed2 | ||
|
|
48e584503e | ||
|
|
454a1b26eb | ||
|
|
4853ca444e | ||
|
|
330539abd2 | ||
|
|
5357a0c060 | ||
|
|
fc22cce037 | ||
|
|
34c8a57814 | ||
|
|
b91e6c384a | ||
|
|
2247691e58 | ||
|
|
f014b43761 | ||
|
|
076d49abc2 | ||
|
|
9fd0ffd84e | ||
|
|
0f11fd9919 | ||
|
|
2b828f8a22 | ||
|
|
d2f67dcb3c | ||
|
|
d5706fcbef | ||
|
|
807f2a88bc | ||
|
|
9d3311e623 | ||
|
|
9bf2cb7e1d | ||
|
|
0134ead5dd | ||
|
|
54909520e9 | ||
|
|
d124f8ee58 | ||
|
|
3fdbcbc0fb | ||
|
|
a5296e11e1 | ||
|
|
3b62597092 | ||
|
|
b085147f23 | ||
|
|
38fccf85e3 | ||
|
|
c0a2771d4e | ||
|
|
6bd5a7b634 | ||
|
|
82b7ef86c7 | ||
|
|
f8cf14cbad | ||
|
|
a5dededfb4 | ||
|
|
4f878536a8 | ||
|
|
d937ec0350 | ||
|
|
1cdcaac3d0 | ||
|
|
985db46960 | ||
|
|
01adaadfad | ||
|
|
3f807a64bb | ||
|
|
1d4a155e8f | ||
|
|
643752f8e7 | ||
|
|
0e0c09c420 | ||
|
|
2b6fa8b381 | ||
|
|
7d2dc5e36a | ||
|
|
f87df8f28b | ||
|
|
cc9e64616f | ||
|
|
f34373be6d | ||
|
|
a39234f438 | ||
|
|
ac8937105d | ||
|
|
fb6f892244 | ||
|
|
0a04c83c7b | ||
|
|
cc8252bebf |
9
.doc/developers.md
Normal file
9
.doc/developers.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Developers
|
||||||
|
|
||||||
|
## PHP Code Styles
|
||||||
|
We use `PHP CS Fixer` to ensure code formating consistency across PHP codebase.
|
||||||
|
You can find the configuration and instructions to run it [here](../tests/php-code-style/README.md).
|
||||||
|
|
||||||
|
## PHP Static Analysis
|
||||||
|
We use `PHPStan` to ensure code quality and to detect potential bugs in our PHP codebase.
|
||||||
|
You can find the configuration and instructions to run it [here](../tests/php-static-analysis/README.md).
|
||||||
12
.github/workflows/action.yml
vendored
12
.github/workflows/action.yml
vendored
@@ -26,13 +26,23 @@ jobs:
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Add internal tag if member
|
- name: Add internal tag if member of the organization
|
||||||
if: env.is_member == 'true'
|
if: env.is_member == 'true'
|
||||||
run: |
|
run: |
|
||||||
curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/labels \
|
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/labels \
|
||||||
-d '{"labels":["internal"]}'
|
-d '{"labels":["internal"]}'
|
||||||
|
|
||||||
|
- name: Set PR author as assignee if member of the organization
|
||||||
|
if: env.is_member == 'true'
|
||||||
|
run: |
|
||||||
|
curl -L \
|
||||||
|
-X POST \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "Authorization: Bearer ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
||||||
|
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/assignees \
|
||||||
|
-d '{"assignees":["${{ github.event.pull_request.user.login }}"]}'
|
||||||
env:
|
env:
|
||||||
is_member: ${{ env.is_member }}
|
is_member: ${{ env.is_member }}
|
||||||
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -58,6 +58,9 @@ tests/*/vendor/*
|
|||||||
/tests/php-unit-tests/phpunit.xml
|
/tests/php-unit-tests/phpunit.xml
|
||||||
/tests/php-unit-tests/postbuild_integration.xml
|
/tests/php-unit-tests/postbuild_integration.xml
|
||||||
|
|
||||||
|
# PHP CS Fixer: Cache file
|
||||||
|
/.php-cs-fixer.cache
|
||||||
|
|
||||||
|
|
||||||
# Jetbrains
|
# Jetbrains
|
||||||
/.idea/**
|
/.idea/**
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ iTop development is sponsored, led, and supported by [Combodo][0].
|
|||||||
|
|
||||||
[0]: https://www.combodo.com
|
[0]: https://www.combodo.com
|
||||||
|
|
||||||
|
## Developers
|
||||||
|
|
||||||
|
You can find information and instructions about our quality tools and how to run them [here](.doc/developers.md).
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
|
|||||||
@@ -819,6 +819,7 @@ HTML
|
|||||||
foreach ($aNotificationClasses as $sNotifClass) {
|
foreach ($aNotificationClasses as $sNotifClass) {
|
||||||
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev WHERE Ev.object_id = :id AND Ev.object_class = :class");
|
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev WHERE Ev.object_id = :id AND Ev.object_class = :class");
|
||||||
$aNotifSearches[$sNotifClass]->SetInternalParams($aParams);
|
$aNotifSearches[$sNotifClass]->SetInternalParams($aParams);
|
||||||
|
$aNotifSearches[$sNotifClass]->AllowAllData();
|
||||||
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass], []);
|
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass], []);
|
||||||
$iNotifsCount += $oNotifSet->Count();
|
$iNotifsCount += $oNotifSet->Count();
|
||||||
}
|
}
|
||||||
@@ -832,6 +833,7 @@ HTML
|
|||||||
'menu' => false,
|
'menu' => false,
|
||||||
'panel_title' => MetaModel::GetName($sNotifClass),
|
'panel_title' => MetaModel::GetName($sNotifClass),
|
||||||
'panel_icon' => MetaModel::GetClassIcon($sNotifClass, false),
|
'panel_icon' => MetaModel::GetClassIcon($sNotifClass, false),
|
||||||
|
'display_unauthorized_objects' => true,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5632,7 +5634,7 @@ JS
|
|||||||
* @return void
|
* @return void
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
final public function AddAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', string $sReason = null): void
|
final public function AddAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', ?string $sReason = null): void
|
||||||
{
|
{
|
||||||
if (!isset($this->aAttributesFlags[$sTargetState])) {
|
if (!isset($this->aAttributesFlags[$sTargetState])) {
|
||||||
$this->aAttributesFlags[$sTargetState] = [];
|
$this->aAttributesFlags[$sTargetState] = [];
|
||||||
@@ -5655,7 +5657,7 @@ JS
|
|||||||
* @return void
|
* @return void
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
final public function ForceAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', string $sReason = null): void
|
final public function ForceAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', ?string $sReason = null): void
|
||||||
{
|
{
|
||||||
if (!isset($this->aAttributesFlags[$sTargetState])) {
|
if (!isset($this->aAttributesFlags[$sTargetState])) {
|
||||||
$this->aAttributesFlags[$sTargetState] = [];
|
$this->aAttributesFlags[$sTargetState] = [];
|
||||||
@@ -5696,7 +5698,7 @@ JS
|
|||||||
* @return void
|
* @return void
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
final public function AddInitialAttributeFlags(string $sAttCode, int $iFlags, string $sReason = null)
|
final public function AddInitialAttributeFlags(string $sAttCode, int $iFlags, ?string $sReason = null)
|
||||||
{
|
{
|
||||||
if (!isset($this->aInitialAttributesFlags)) {
|
if (!isset($this->aInitialAttributesFlags)) {
|
||||||
$this->aInitialAttributesFlags = [];
|
$this->aInitialAttributesFlags = [];
|
||||||
@@ -5718,7 +5720,7 @@ JS
|
|||||||
* @return void
|
* @return void
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
final public function ForceInitialAttributeFlags(string $sAttCode, int $iFlags, string $sReason = null)
|
final public function ForceInitialAttributeFlags(string $sAttCode, int $iFlags, ?string $sReason = null)
|
||||||
{
|
{
|
||||||
if (!isset($this->aInitialAttributesFlags)) {
|
if (!isset($this->aInitialAttributesFlags)) {
|
||||||
$this->aInitialAttributesFlags = [];
|
$this->aInitialAttributesFlags = [];
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\Dashboard\Layout\DashboardLayoutGrid;
|
|
||||||
use Combodo\iTop\Application\Dashlet\DashletFactory;
|
|
||||||
use Combodo\iTop\Application\Dashlet\Service\DashletService;
|
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
||||||
@@ -15,12 +12,9 @@ use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
|||||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
use Combodo\iTop\Application\WebPage\WebPage;
|
||||||
use Combodo\iTop\DesignDocument;
|
|
||||||
use Combodo\iTop\DesignElement;
|
|
||||||
use Combodo\iTop\PropertyType\PropertyTypeDesign;
|
|
||||||
use Combodo\iTop\Service\DependencyInjection\ServiceLocator;
|
|
||||||
|
|
||||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||||
|
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||||
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +24,7 @@ require_once(APPROOT.'core/modelreflection.class.inc.php');
|
|||||||
*/
|
*/
|
||||||
abstract class Dashboard
|
abstract class Dashboard
|
||||||
{
|
{
|
||||||
/** @var string $sTitle */
|
/** @var string $sTitle*/
|
||||||
protected $sTitle;
|
protected $sTitle;
|
||||||
/** @var bool $bAutoReload */
|
/** @var bool $bAutoReload */
|
||||||
protected $bAutoReload;
|
protected $bAutoReload;
|
||||||
@@ -40,7 +34,7 @@ abstract class Dashboard
|
|||||||
protected $sLayoutClass;
|
protected $sLayoutClass;
|
||||||
/** @var array $aWidgetsData */
|
/** @var array $aWidgetsData */
|
||||||
protected $aWidgetsData;
|
protected $aWidgetsData;
|
||||||
/** @var DesignElement|null $oDOMNode */
|
/** @var \DOMNode|null $oDOMNode */
|
||||||
protected $oDOMNode;
|
protected $oDOMNode;
|
||||||
/** @var string $sId */
|
/** @var string $sId */
|
||||||
protected $sId;
|
protected $sId;
|
||||||
@@ -49,11 +43,6 @@ abstract class Dashboard
|
|||||||
/** @var \ModelReflection $oMetaModel */
|
/** @var \ModelReflection $oMetaModel */
|
||||||
protected $oMetaModel;
|
protected $oMetaModel;
|
||||||
|
|
||||||
/** @var array Array of dashlets with position */
|
|
||||||
protected array $aGridDashlets = [];
|
|
||||||
|
|
||||||
protected $oDashletFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard constructor.
|
* Dashboard constructor.
|
||||||
*
|
*
|
||||||
@@ -68,7 +57,6 @@ abstract class Dashboard
|
|||||||
$this->aCells = [];
|
$this->aCells = [];
|
||||||
$this->oDOMNode = null;
|
$this->oDOMNode = null;
|
||||||
$this->sId = $sId;
|
$this->sId = $sId;
|
||||||
$this->oDashletFactory = DashletFactory::GetInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +68,7 @@ abstract class Dashboard
|
|||||||
{
|
{
|
||||||
$this->aCells = []; // reset the content of the dashboard
|
$this->aCells = []; // reset the content of the dashboard
|
||||||
set_error_handler(['Dashboard', 'ErrorHandler']);
|
set_error_handler(['Dashboard', 'ErrorHandler']);
|
||||||
$oDoc = new PropertyTypeDesign();
|
$oDoc = new DOMDocument();
|
||||||
$oDoc->loadXML($sXml);
|
$oDoc->loadXML($sXml);
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
$this->FromDOMDocument($oDoc);
|
$this->FromDOMDocument($oDoc);
|
||||||
@@ -89,15 +77,10 @@ abstract class Dashboard
|
|||||||
/**
|
/**
|
||||||
* @param \DOMDocument $oDoc
|
* @param \DOMDocument $oDoc
|
||||||
*/
|
*/
|
||||||
public function FromDOMDocument(DesignDocument $oDoc)
|
public function FromDOMDocument(DOMDocument $oDoc)
|
||||||
{
|
{
|
||||||
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
|
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
|
||||||
|
|
||||||
if ($this->oDOMNode->getElementsByTagName('cells')->count() === 0) {
|
|
||||||
$this->FromDOMDocumentV2($oDoc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0)) {
|
if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0)) {
|
||||||
$this->sLayoutClass = $oLayoutNode->textContent;
|
$this->sLayoutClass = $oLayoutNode->textContent;
|
||||||
} else {
|
} else {
|
||||||
@@ -138,7 +121,7 @@ abstract class Dashboard
|
|||||||
$aDashletOrder = [];
|
$aDashletOrder = [];
|
||||||
/** @var \DOMElement $oDomNode */
|
/** @var \DOMElement $oDomNode */
|
||||||
foreach ($oDashletList as $oDomNode) {
|
foreach ($oDashletList as $oDomNode) {
|
||||||
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
|
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
|
||||||
if ($oRank) {
|
if ($oRank) {
|
||||||
$iRank = (float)$oRank->textContent;
|
$iRank = (float)$oRank->textContent;
|
||||||
}
|
}
|
||||||
@@ -164,39 +147,7 @@ abstract class Dashboard
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \DOMDocument $oDoc
|
* @param \DOMElement $oDomNode
|
||||||
*/
|
|
||||||
public function FromDOMDocumentV2(DesignDocument $oDoc)
|
|
||||||
{
|
|
||||||
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
|
|
||||||
|
|
||||||
$this->sLayoutClass = DashboardLayoutGrid::class;
|
|
||||||
$this->sTitle = $this->oDOMNode->GetChildText('title', '');
|
|
||||||
|
|
||||||
$iRefresh = intval($this->oDOMNode->GetChildText('refresh', '0'));
|
|
||||||
|
|
||||||
$this->bAutoReload = $iRefresh > 0;
|
|
||||||
$this->iAutoReloadSec = $iRefresh;
|
|
||||||
|
|
||||||
$oDashletsNode = $this->oDOMNode->GetUniqueElement('pos_dashlets');
|
|
||||||
$oDashletList = $oDashletsNode->getElementsByTagName('pos_dashlet');
|
|
||||||
foreach ($oDashletList as $oPosDashletNode) {
|
|
||||||
$aGridDashlet = [];
|
|
||||||
$aGridDashlet['position_x'] = intval($oPosDashletNode->GetChildText('position_x', '0'));
|
|
||||||
$aGridDashlet['position_y'] = intval($oPosDashletNode->GetChildText('position_y', '0'));
|
|
||||||
$aGridDashlet['width'] = intval($oPosDashletNode->GetChildText('width', '2'));
|
|
||||||
$aGridDashlet['height'] = intval($oPosDashletNode->GetChildText('height', '1'));
|
|
||||||
$oDashletNode = $oPosDashletNode->GetUniqueElement('dashlet');
|
|
||||||
$sId = $oPosDashletNode->getAttribute('id');
|
|
||||||
$oDashlet = $this->InitDashletFromDOMNode($oDashletNode);
|
|
||||||
$oDashlet->SetID($sId);
|
|
||||||
$aGridDashlet['dashlet'] = $oDashlet;
|
|
||||||
$this->aGridDashlets[] = $aGridDashlet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DesignElement $oDomNode
|
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
@@ -209,7 +160,7 @@ abstract class Dashboard
|
|||||||
// Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
|
// Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
|
||||||
$sClass = static::GetDashletClassFromType($sDashletType);
|
$sClass = static::GetDashletClassFromType($sDashletType);
|
||||||
/** @var \Dashlet $oNewDashlet */
|
/** @var \Dashlet $oNewDashlet */
|
||||||
$oNewDashlet = $this->oDashletFactory->CreateDashlet($sClass, $sId);
|
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
|
||||||
$oNewDashlet->SetDashletType($sDashletType);
|
$oNewDashlet->SetDashletType($sDashletType);
|
||||||
$oNewDashlet->FromDOMNode($oDomNode);
|
$oNewDashlet->FromDOMNode($oDomNode);
|
||||||
|
|
||||||
@@ -253,31 +204,18 @@ abstract class Dashboard
|
|||||||
*/
|
*/
|
||||||
public function ToXml()
|
public function ToXml()
|
||||||
{
|
{
|
||||||
$oMainNode = $this->CreateEmptyDashboard();
|
$oDoc = new DOMDocument();
|
||||||
|
|
||||||
$this->ToDOMNode($oMainNode);
|
|
||||||
|
|
||||||
$sXml = $oMainNode->ownerDocument->saveXML();
|
|
||||||
|
|
||||||
return $sXml;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return DesignElement
|
|
||||||
* @throws \DOMException
|
|
||||||
*/
|
|
||||||
public function CreateEmptyDashboard(): DesignElement
|
|
||||||
{
|
|
||||||
$oDoc = new DesignDocument();
|
|
||||||
$oDoc->formatOutput = true; // indent (must be loaded with option LIBXML_NOBLANKS)
|
$oDoc->formatOutput = true; // indent (must be loaded with option LIBXML_NOBLANKS)
|
||||||
$oDoc->preserveWhiteSpace = true; // otherwise the formatOutput option would have no effect
|
$oDoc->preserveWhiteSpace = true; // otherwise the formatOutput option would have no effect
|
||||||
|
|
||||||
/** @var DesignElement $oMainNode */
|
|
||||||
$oMainNode = $oDoc->createElement('dashboard');
|
$oMainNode = $oDoc->createElement('dashboard');
|
||||||
$oMainNode->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
$oMainNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||||
$oDoc->appendChild($oMainNode);
|
$oDoc->appendChild($oMainNode);
|
||||||
|
|
||||||
return $oMainNode;
|
$this->ToDOMNode($oMainNode);
|
||||||
|
|
||||||
|
$sXml = $oDoc->saveXML();
|
||||||
|
return $sXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -341,7 +279,7 @@ abstract class Dashboard
|
|||||||
}
|
}
|
||||||
$this->sTitle = $aParams['title'];
|
$this->sTitle = $aParams['title'];
|
||||||
$this->bAutoReload = $aParams['auto_reload'] == 'true';
|
$this->bAutoReload = $aParams['auto_reload'] == 'true';
|
||||||
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$aParams['auto_reload_sec']);
|
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']);
|
||||||
|
|
||||||
foreach ($aParams['cells'] as $aCell) {
|
foreach ($aParams['cells'] as $aCell) {
|
||||||
$aCellDashlets = [];
|
$aCellDashlets = [];
|
||||||
@@ -349,7 +287,7 @@ abstract class Dashboard
|
|||||||
$sDashletClass = $aDashletParams['dashlet_class'];
|
$sDashletClass = $aDashletParams['dashlet_class'];
|
||||||
$sId = $aDashletParams['dashlet_id'];
|
$sId = $aDashletParams['dashlet_id'];
|
||||||
/** @var \Dashlet $oNewDashlet */
|
/** @var \Dashlet $oNewDashlet */
|
||||||
$oNewDashlet = $this->oDashletFactory->CreateDashlet($sDashletClass, $sId);
|
$oNewDashlet = new $sDashletClass($this->oMetaModel, $sId);
|
||||||
if (isset($aDashletParams['dashlet_type'])) {
|
if (isset($aDashletParams['dashlet_type'])) {
|
||||||
$oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
|
$oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
|
||||||
}
|
}
|
||||||
@@ -367,11 +305,7 @@ abstract class Dashboard
|
|||||||
|
|
||||||
public function Save()
|
public function Save()
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
public function PersistDashboard(string $sXml): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -569,7 +503,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
|
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
|
||||||
|
|
||||||
/** @var \DashboardLayout $oLayout */
|
/** @var \DashboardLayoutMultiCol $oLayout */
|
||||||
$oLayout = new $this->sLayoutClass();
|
$oLayout = new $this->sLayoutClass();
|
||||||
|
|
||||||
foreach ($this->aCells as $iCellIdx => $aDashlets) {
|
foreach ($this->aCells as $iCellIdx => $aDashlets) {
|
||||||
@@ -579,13 +513,7 @@ EOF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->aCells) > 0) {
|
$oDashboard = $oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||||
$aDashlets = $this->aCells;
|
|
||||||
} else {
|
|
||||||
$aDashlets = $this->aGridDashlets;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oDashboard = $oLayout->Render($oPage, $aDashlets, $bEditMode, $aExtraParams);
|
|
||||||
$oPage->AddUiBlock($oDashboard);
|
$oPage->AddUiBlock($oDashboard);
|
||||||
|
|
||||||
$bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
$bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
||||||
@@ -675,12 +603,29 @@ JS
|
|||||||
* Return an array of dashlets available for selection.
|
* Return an array of dashlets available for selection.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws \Combodo\iTop\Application\Dashlet\DashletException
|
* @throws \ReflectionException
|
||||||
* @throws \DOMFormatException
|
|
||||||
*/
|
*/
|
||||||
protected function GetAvailableDashlets(): array
|
protected function GetAvailableDashlets()
|
||||||
{
|
{
|
||||||
return DashletService::GetInstance()->GetAvailableDashlets();
|
$aDashlets = [];
|
||||||
|
|
||||||
|
foreach (get_declared_classes() as $sDashletClass) {
|
||||||
|
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instantiated.
|
||||||
|
if (is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, ['DashletUnknown', 'DashletProxy'])) {
|
||||||
|
$oReflection = new ReflectionClass($sDashletClass);
|
||||||
|
if (!$oReflection->isAbstract()) {
|
||||||
|
$aCallSpec = [$sDashletClass, 'IsVisible'];
|
||||||
|
$bVisible = call_user_func($aCallSpec);
|
||||||
|
if ($bVisible) {
|
||||||
|
$aCallSpec = [$sDashletClass, 'GetInfo'];
|
||||||
|
$aInfo = call_user_func($aCallSpec);
|
||||||
|
$aDashlets[$sDashletClass] = $aInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aDashlets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -695,7 +640,6 @@ JS
|
|||||||
$iNewId = max($iNewId, (int)$oDashlet->GetID());
|
$iNewId = max($iNewId, (int)$oDashlet->GetID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $iNewId + 1;
|
return $iNewId + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,7 +674,6 @@ JS
|
|||||||
if (is_subclass_of($sType, 'Dashlet')) {
|
if (is_subclass_of($sType, 'Dashlet')) {
|
||||||
return $sType;
|
return $sType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'DashletUnknown';
|
return 'DashletUnknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,8 +726,6 @@ class RuntimeDashboard extends Dashboard
|
|||||||
{
|
{
|
||||||
parent::__construct($sId);
|
parent::__construct($sId);
|
||||||
$this->oMetaModel = new ModelReflectionRuntime();
|
$this->oMetaModel = new ModelReflectionRuntime();
|
||||||
$this->oDashletFactory->SetModelReflectionRuntime($this->oMetaModel);
|
|
||||||
ServiceLocator::GetInstance()->RegisterService('ModelReflection', $this->oMetaModel);
|
|
||||||
$this->bCustomized = false;
|
$this->bCustomized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,7 +740,6 @@ class RuntimeDashboard extends Dashboard
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $bCustomized
|
* @param bool $bCustomized
|
||||||
*
|
|
||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
*/
|
*/
|
||||||
public function SetCustomFlag($bCustomized)
|
public function SetCustomFlag($bCustomized)
|
||||||
@@ -824,26 +764,6 @@ class RuntimeDashboard extends Dashboard
|
|||||||
public function Save()
|
public function Save()
|
||||||
{
|
{
|
||||||
$sXml = $this->ToXml();
|
$sXml = $this->ToXml();
|
||||||
|
|
||||||
return $this->PersistDashboard($sXml);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $sXml
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @throws \ArchivedObjectException
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \CoreWarning
|
|
||||||
* @throws \MissingQueryArgument
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \MySQLHasGoneAwayException
|
|
||||||
* @throws \OQLException
|
|
||||||
*/
|
|
||||||
public function PersistDashboard(string $sXml): bool
|
|
||||||
{
|
|
||||||
$oUDSearch = new DBObjectSearch('UserDashboard');
|
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||||
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||||
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
|
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
|
||||||
@@ -864,7 +784,6 @@ class RuntimeDashboard extends Dashboard
|
|||||||
utils::PushArchiveMode(false);
|
utils::PushArchiveMode(false);
|
||||||
$oUserDashboard->DBWrite();
|
$oUserDashboard->DBWrite();
|
||||||
utils::PopArchiveMode();
|
utils::PopArchiveMode();
|
||||||
|
|
||||||
return $bIsNew;
|
return $bIsNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1110,7 +1029,7 @@ EOF
|
|||||||
var dashboard = $('.ibo-dashboard#$sDivId')
|
var dashboard = $('.ibo-dashboard#$sDivId')
|
||||||
dashboard.block();
|
dashboard.block();
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||||
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
|
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: $sReloadURL },
|
||||||
function(data) {
|
function(data) {
|
||||||
dashboard.html(data);
|
dashboard.html(data);
|
||||||
dashboard.unblock();
|
dashboard.unblock();
|
||||||
@@ -1158,7 +1077,6 @@ JS
|
|||||||
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||||
|
|
||||||
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
||||||
$sActionEditId = "ibo-dashboard-menu-edit-{$sId}";
|
|
||||||
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
||||||
$sName = 'UI:Dashboard:Actions';
|
$sName = 'UI:Dashboard:Actions';
|
||||||
|
|
||||||
@@ -1172,21 +1090,6 @@ JS
|
|||||||
} else {
|
} else {
|
||||||
$oToolbar = $oDashboard->GetToolbar();
|
$oToolbar = $oDashboard->GetToolbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 3.3 Check if we need different action for custom dashboard creation / edition
|
|
||||||
$oActionEditButton = ButtonUIBlockFactory::MakeIconAction(
|
|
||||||
'fas fa-pen',
|
|
||||||
$this->HasCustomDashboard() ? Dict::S('UI:Dashboard:EditCustom') : Dict::S('UI:Dashboard:CreateCustom'),
|
|
||||||
$sActionEditId,
|
|
||||||
'',
|
|
||||||
false,
|
|
||||||
$sActionEditId
|
|
||||||
)
|
|
||||||
->AddCSSClass('ibo-top-bar--toolbar-dashboard-edit-button')
|
|
||||||
->AddCSSClass('ibo-action-button');
|
|
||||||
|
|
||||||
$oToolbar->AddSubBlock($oActionEditButton);
|
|
||||||
|
|
||||||
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S($sName), $sName, '', false, $sMenuTogglerId)
|
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S($sName), $sName, '', false, $sMenuTogglerId)
|
||||||
->AddCSSClass('ibo-top-bar--toolbar-dashboard-menu-toggler')
|
->AddCSSClass('ibo-top-bar--toolbar-dashboard-menu-toggler')
|
||||||
->AddCSSClass('ibo-action-button');
|
->AddCSSClass('ibo-action-button');
|
||||||
@@ -1196,8 +1099,8 @@ JS
|
|||||||
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
|
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
|
||||||
$sJSExtraParams = json_encode($aExtraParams);
|
$sJSExtraParams = json_encode($aExtraParams);
|
||||||
if ($this->HasCustomDashboard()) {
|
if ($this->HasCustomDashboard()) {
|
||||||
// $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||||
// $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||||
$oRevert = new JSPopupMenuItem(
|
$oRevert = new JSPopupMenuItem(
|
||||||
'UI:Dashboard:RevertConfirm',
|
'UI:Dashboard:RevertConfirm',
|
||||||
Dict::S('UI:Dashboard:DeleteCustom'),
|
Dict::S('UI:Dashboard:DeleteCustom'),
|
||||||
@@ -1205,8 +1108,8 @@ JS
|
|||||||
);
|
);
|
||||||
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
||||||
} else {
|
} else {
|
||||||
// $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||||
// $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
||||||
@@ -1320,7 +1223,7 @@ EOF
|
|||||||
$sId = json_encode($this->sId);
|
$sId = json_encode($this->sId);
|
||||||
$sLayoutClass = json_encode($this->sLayoutClass);
|
$sLayoutClass = json_encode($this->sLayoutClass);
|
||||||
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
|
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
|
||||||
$sAutoReloadSec = (string)$this->iAutoReloadSec;
|
$sAutoReloadSec = (string) $this->iAutoReloadSec;
|
||||||
$sTitle = json_encode($this->sTitle);
|
$sTitle = json_encode($this->sTitle);
|
||||||
$sFile = json_encode($this->GetDefinitionFile());
|
$sFile = json_encode($this->GetDefinitionFile());
|
||||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
|
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
|
||||||
@@ -1492,11 +1395,19 @@ JS
|
|||||||
|
|
||||||
// Get the list of possible dashlets that support a creation from
|
// Get the list of possible dashlets that support a creation from
|
||||||
// an OQL
|
// an OQL
|
||||||
$aAllDashlets = DashletService::GetInstance()->GetAvailableDashlets();
|
|
||||||
$aDashlets = [];
|
$aDashlets = [];
|
||||||
foreach ($aAllDashlets as $sDashletClass => $aInfo) {
|
foreach (get_declared_classes() as $sDashletClass) {
|
||||||
if ($aInfo['can_create_by_oql']) {
|
if (is_subclass_of($sDashletClass, 'Dashlet')) {
|
||||||
$aDashlets[$sDashletClass] = ['label' => $aInfo['label'], 'class' => $sDashletClass, 'icon' => $aInfo['icon']];
|
$oReflection = new ReflectionClass($sDashletClass);
|
||||||
|
if (!$oReflection->isAbstract()) {
|
||||||
|
$aCallSpec = [$sDashletClass, 'CanCreateFromOQL'];
|
||||||
|
$bShorcutMode = call_user_func($aCallSpec);
|
||||||
|
if ($bShorcutMode) {
|
||||||
|
$aCallSpec = [$sDashletClass, 'GetInfo'];
|
||||||
|
$aInfo = call_user_func($aCallSpec);
|
||||||
|
$aDashlets[$sDashletClass] = ['label' => $aInfo['label'], 'class' => $sDashletClass, 'icon' => $aInfo['icon']];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1506,7 +1417,7 @@ JS
|
|||||||
$oSubForm = new DesignerForm();
|
$oSubForm = new DesignerForm();
|
||||||
$oMetaModel = new ModelReflectionRuntime();
|
$oMetaModel = new ModelReflectionRuntime();
|
||||||
/** @var \Dashlet $oDashlet */
|
/** @var \Dashlet $oDashlet */
|
||||||
$oDashlet = DashletFactory::GetInstance()->CreateDashlet($sDashletClass, 0);
|
$oDashlet = new $sDashletClass($oMetaModel, 0);
|
||||||
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
|
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
|
||||||
|
|
||||||
$oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']);
|
$oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']);
|
||||||
@@ -1660,7 +1571,7 @@ JS
|
|||||||
*/
|
*/
|
||||||
private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams)
|
private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams)
|
||||||
{
|
{
|
||||||
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
|
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
|
||||||
if (!$bIsDashletWithListPref) {
|
if (!$bIsDashletWithListPref) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1708,7 +1619,6 @@ JS
|
|||||||
//on error, return default value
|
//on error, return default value
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataTableSettings::GetAppUserPreferenceKey($aClassAliases, $sDataTableId);
|
return DataTableSettings::GetAppUserPreferenceKey($aClassAliases, $sDataTableId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use Combodo\iTop\Application\WebPage\WebPage;
|
|||||||
*/
|
*/
|
||||||
abstract class DashboardLayout
|
abstract class DashboardLayout
|
||||||
{
|
{
|
||||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false, array $aExtraParams = []);
|
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $iCellIdx
|
* @param int $iCellIdx
|
||||||
@@ -43,8 +43,8 @@ abstract class DashboardLayout
|
|||||||
public static function GetInfo()
|
public static function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => '',
|
'label' => '',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
}
|
}
|
||||||
$idx++;
|
$idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aDashlets;
|
return $aDashlets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +94,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
}
|
}
|
||||||
$idx++;
|
$idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aCells;
|
return $aCells;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -111,8 +109,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||||
$aCells = $this->TrimCellsArray($aCells);
|
$aCells = $this->TrimCellsArray($aCells);
|
||||||
|
|
||||||
// TODO 3.3 Handle dashboard new format, convert old format if needed
|
$oDashboardLayout = new DashboardLayoutUIBlock();
|
||||||
$oDashboardLayout = new DashboardLayoutUIBlock($aExtraParams['dashboard_div_id']);
|
|
||||||
//$oPage->AddUiBlock($oDashboardLayout);
|
//$oPage->AddUiBlock($oDashboardLayout);
|
||||||
|
|
||||||
$iCellIdx = 0;
|
$iCellIdx = 0;
|
||||||
@@ -120,16 +117,15 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
|
|
||||||
//Js given by each dashlet to reload
|
//Js given by each dashlet to reload
|
||||||
$sJSReload = "";
|
$sJSReload = "";
|
||||||
$oDashboardGrid = new \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardGrid();
|
|
||||||
$oDashboardLayout->SetGrid($oDashboardGrid);
|
|
||||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||||
$oDashboardRow = new DashboardRow();
|
$oDashboardRow = new DashboardRow();
|
||||||
//$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||||
|
|
||||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||||
$oDashboardColumn = new DashboardColumn($bEditMode);
|
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||||
$oDashboardColumn->SetCellIndex($iCellIdx);
|
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||||
//$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||||
|
|
||||||
if (array_key_exists($iCellIdx, $aCells)) {
|
if (array_key_exists($iCellIdx, $aCells)) {
|
||||||
$aDashlets = $aCells[$iCellIdx];
|
$aDashlets = $aCells[$iCellIdx];
|
||||||
@@ -137,18 +133,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
/** @var \Dashlet $oDashlet */
|
/** @var \Dashlet $oDashlet */
|
||||||
foreach ($aDashlets as $oDashlet) {
|
foreach ($aDashlets as $oDashlet) {
|
||||||
if ($oDashlet::IsVisible()) {
|
if ($oDashlet::IsVisible()) {
|
||||||
$sDashletId = $oDashlet->GetID();
|
|
||||||
$sDashletClass = get_class($oDashlet);
|
|
||||||
$aDashletDenormalizedProperties = $oDashlet->GetDenormalizedProperties();
|
|
||||||
// $aDashletsInfo = $sDashletClass::GetInfo();
|
|
||||||
//
|
|
||||||
// // TODO 3.3 Gather real position and height/width if any.
|
|
||||||
// // Also set minimal height/width
|
|
||||||
// $iPositionX = null;
|
|
||||||
// $iPositionY = null;
|
|
||||||
// $iWidth = array_key_exists('preferred_width', $aDashletsInfo) ? $aDashletsInfo['preferred_width'] : 1;
|
|
||||||
// $iHeight = array_key_exists('preferred_height', $aDashletsInfo) ? $aDashletsInfo['preferred_height'] : 1;
|
|
||||||
// $oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $sDashletId, $sDashletClass, $aDashletDenormalizedProperties, $iPositionX, $iPositionY, $iWidth, $iHeight);
|
|
||||||
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +147,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 3.3 We can probably do better with the new dashboard
|
|
||||||
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||||
|
|
||||||
if ($bEditMode) { // Add one row for extensibility
|
if ($bEditMode) { // Add one row for extensibility
|
||||||
@@ -185,8 +168,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
*/
|
*/
|
||||||
public function GetDashletCoordinates($iCellIdx)
|
public function GetDashletCoordinates($iCellIdx)
|
||||||
{
|
{
|
||||||
$iColNumber = (int)$iCellIdx % $this->iNbCols;
|
$iColNumber = (int) $iCellIdx % $this->iNbCols;
|
||||||
$iRowNumber = (int)floor($iCellIdx / $this->iNbCols);
|
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
|
||||||
|
|
||||||
return [$iColNumber, $iRowNumber];
|
return [$iColNumber, $iRowNumber];
|
||||||
}
|
}
|
||||||
@@ -199,12 +182,11 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 1;
|
$this->iNbCols = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetInfo()
|
public static function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => 'One Column',
|
'label' => 'One Column',
|
||||||
'icon' => 'images/layout_1col.png',
|
'icon' => 'images/layout_1col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -217,12 +199,11 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 2;
|
$this->iNbCols = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetInfo()
|
public static function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => 'Two Columns',
|
'label' => 'Two Columns',
|
||||||
'icon' => 'images/layout_2col.png',
|
'icon' => 'images/layout_2col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -235,12 +216,11 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 3;
|
$this->iNbCols = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetInfo()
|
public static function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => 'Two Columns',
|
'label' => 'Two Columns',
|
||||||
'icon' => 'images/layout_3col.png',
|
'icon' => 'images/layout_3col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
2337
application/dashlet.class.inc.php
Normal file
2337
application/dashlet.class.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
|||||||
<class id="AbstractResource" _delta="define">
|
<class id="AbstractResource" _delta="define">
|
||||||
<parent>cmdbAbstractObject</parent>
|
<parent>cmdbAbstractObject</parent>
|
||||||
<properties>
|
<properties>
|
||||||
<comment>/* Resource access control abstraction. Can be inherited by abstract resource access control classes. Generally controlled using UR_ACTION_MODIFY access right. */</comment>
|
<comment>/* Resource access control abstraction. Can be herited by abstract resource access control classes. Generally controlled using UR_ACTION_MODIFY access right. */</comment>
|
||||||
<abstract>true</abstract>
|
<abstract>true</abstract>
|
||||||
</properties>
|
</properties>
|
||||||
<presentation/>
|
<presentation/>
|
||||||
@@ -851,295 +851,9 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
|
|||||||
</methods>
|
</methods>
|
||||||
</class>
|
</class>
|
||||||
</classes>
|
</classes>
|
||||||
<dashlets>
|
|
||||||
<dashlet id="DashletGroupByTable" _delta="define">
|
|
||||||
<label>UI:DashletGroupByTable:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-transaction-list-48.png</icon>
|
|
||||||
<description>UI:DashletGroupByTable:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>2</min_height>
|
|
||||||
<preferred_width>3</preferred_width>
|
|
||||||
<preferred_height>3</preferred_height>
|
|
||||||
<can_create_by_oql>true</can_create_by_oql>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletGroupByBars" _delta="define">
|
|
||||||
<label>UI:DashletGroupByBars:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-bar-chart-48.png</icon>
|
|
||||||
<description>UI:DashletGroupByBars:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>2</min_height>
|
|
||||||
<preferred_width>3</preferred_width>
|
|
||||||
<preferred_height>3</preferred_height>
|
|
||||||
<can_create_by_oql>true</can_create_by_oql>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletGroupByPie" _delta="define">
|
|
||||||
<label>UI:DashletGroupByPie:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-pie-chart-48.png</icon>
|
|
||||||
<description>UI:DashletGroupByPie:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>2</min_height>
|
|
||||||
<preferred_width>3</preferred_width>
|
|
||||||
<preferred_height>3</preferred_height>
|
|
||||||
<can_create_by_oql>true</can_create_by_oql>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletBadge" _delta="define">
|
|
||||||
<label>UI:DashletBadge:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-badge-48.png</icon>
|
|
||||||
<description>UI:DashletBadge:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>1</min_height>
|
|
||||||
<preferred_width>2</preferred_width>
|
|
||||||
<preferred_height>1</preferred_height>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletHeaderDynamic" _delta="define">
|
|
||||||
<label>UI:DashletHeaderDynamic:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-header-altered-48.png</icon>
|
|
||||||
<description>UI:DashletHeaderDynamic:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>1</min_height>
|
|
||||||
<preferred_width>4</preferred_width>
|
|
||||||
<preferred_height>3</preferred_height>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletHeaderStatic" _delta="define">
|
|
||||||
<label>UI:DashletHeaderStatic:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-header-48.png</icon>
|
|
||||||
<description>UI:DashletHeaderStatic:Description</description>
|
|
||||||
<min_width>4</min_width>
|
|
||||||
<min_height>1</min_height>
|
|
||||||
<preferred_width>4</preferred_width>
|
|
||||||
<preferred_height>1</preferred_height>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletObjectList" _delta="define">
|
|
||||||
<label>UI:DashletObjectList:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-list-48.png</icon>
|
|
||||||
<description>UI:DashletObjectList:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>1</min_height>
|
|
||||||
<preferred_width>4</preferred_width>
|
|
||||||
<preferred_height>3</preferred_height>
|
|
||||||
<can_create_by_oql>true</can_create_by_oql>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
<dashlet id="DashletPlainText" _delta="define">
|
|
||||||
<label>UI:DashletPlainText:Label</label>
|
|
||||||
<icon>images/dashlets/icons8-text-box-48.png</icon>
|
|
||||||
<description>UI:DashletPlainText:Description</description>
|
|
||||||
<min_width>2</min_width>
|
|
||||||
<min_height>1</min_height>
|
|
||||||
<preferred_width>2</preferred_width>
|
|
||||||
<preferred_height>1</preferred_height>
|
|
||||||
<configuration/>
|
|
||||||
</dashlet>
|
|
||||||
</dashlets>
|
|
||||||
<property_types _delta="define">
|
<property_types _delta="define">
|
||||||
<property_type id="Dashboard" xsi:type="Combodo-AbstractPropertyType"/>
|
|
||||||
<property_type id="DashboardGrid" xsi:type="Combodo-PropertyType">
|
|
||||||
<extends>Dashboard</extends>
|
|
||||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
|
||||||
<label>Dashboard</label>
|
|
||||||
<nodes>
|
|
||||||
<node id="title" xsi:type="Combodo-ValueType-String">
|
|
||||||
<label>UI:DashboardEdit:DashboardTitle</label>
|
|
||||||
</node>
|
|
||||||
<node id="refresh" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
|
||||||
<label>UI:DashboardEdit:AutoReload</label>
|
|
||||||
<values>
|
|
||||||
<value id="0">
|
|
||||||
<label>No auto-refresh</label>
|
|
||||||
</value>
|
|
||||||
<value id="30">
|
|
||||||
<label>Every 30 seconds</label>
|
|
||||||
</value>
|
|
||||||
<value id="60">
|
|
||||||
<label>Every 1 minute</label>
|
|
||||||
</value>
|
|
||||||
<value id="300">
|
|
||||||
<label>Every 5 minutes</label>
|
|
||||||
</value>
|
|
||||||
<value id="600">
|
|
||||||
<label>Every 10 minutes</label>
|
|
||||||
</value>
|
|
||||||
<value id="1800">
|
|
||||||
<label>Every 30 minutes</label>
|
|
||||||
</value>
|
|
||||||
<value id="3600">
|
|
||||||
<label>Every 1 hour</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
<node id="pos_dashlets" xsi:type="Combodo-ValueType-Collection">
|
|
||||||
<label>Dashlet List</label>
|
|
||||||
<xml-format xsi:type="Combodo-XMLFormat-CollectionWithId">
|
|
||||||
<tag-name>pos_dashlet</tag-name>
|
|
||||||
</xml-format>
|
|
||||||
<prototype>
|
|
||||||
<node id="position_x" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>X</label>
|
|
||||||
</node>
|
|
||||||
<node id="position_y" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>Y</label>
|
|
||||||
</node>
|
|
||||||
<node id="width" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>W</label>
|
|
||||||
</node>
|
|
||||||
<node id="height" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>H</label>
|
|
||||||
</node>
|
|
||||||
<node id="dashlet" xsi:type="Combodo-ValueType-Polymorphic">
|
|
||||||
<label>Dashlet</label>
|
|
||||||
<allowed-types>
|
|
||||||
<allowed-type>Dashlet</allowed-type>
|
|
||||||
</allowed-types>
|
|
||||||
</node>
|
|
||||||
</prototype>
|
|
||||||
</node>
|
|
||||||
</nodes>
|
|
||||||
</definition>
|
|
||||||
</property_type>
|
|
||||||
<property_type id="Dashlet" xsi:type="Combodo-AbstractPropertyType"/>
|
<property_type id="Dashlet" xsi:type="Combodo-AbstractPropertyType"/>
|
||||||
<property_type id="DashletGroupByTable" xsi:type="Combodo-PropertyType">
|
<property_type id="DashletGroupBy" xsi:type="Combodo-PropertyType">
|
||||||
<extends>Dashlet</extends>
|
|
||||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
|
||||||
<label>UI:DashletGroupBy:Title</label>
|
|
||||||
<nodes>
|
|
||||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Title</label>
|
|
||||||
</node>
|
|
||||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Query</label>
|
|
||||||
</node>
|
|
||||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttributeGroupBy">
|
|
||||||
<label>UI:DashletGroupBy:Prop-GroupBy</label>
|
|
||||||
<class>{{query.selected_class}}</class>
|
|
||||||
</node>
|
|
||||||
<node id="style" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
|
||||||
<label>UI:DashletGroupBy:Prop-Style</label>
|
|
||||||
<values>
|
|
||||||
<value id="bars">
|
|
||||||
<label>UI:DashletGroupByBars:Label</label>
|
|
||||||
</value>
|
|
||||||
<value id="pie">
|
|
||||||
<label>UI:DashletGroupByPie:Label</label>
|
|
||||||
</value>
|
|
||||||
<value id="table">
|
|
||||||
<label>UI:DashletGroupByTable:Label</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
<node id="aggregation_function" xsi:type="Combodo-ValueType-AggregateFunction">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Function</label>
|
|
||||||
<class>{{query.selected_class}}</class> <!-- pour savoir si il y a des attributs additionnables -->
|
|
||||||
</node>
|
|
||||||
<node id="aggregation_attribute" xsi:type="Combodo-ValueType-ClassAttribute">
|
|
||||||
<label>UI:DashletGroupBy:Prop-FunctionAttribute</label>
|
|
||||||
<relevance-condition>{{aggregation_function.value != 'count'}}</relevance-condition>
|
|
||||||
<class>{{query.selected_class}}</class>
|
|
||||||
<category>numeric</category>
|
|
||||||
</node>
|
|
||||||
<node id="order_by" xsi:type="Combodo-ValueType-ChoiceFromInput">
|
|
||||||
<label>UI:DashletGroupBy:Prop-OrderField</label>
|
|
||||||
<values>
|
|
||||||
<value id="attribute">
|
|
||||||
<label>{{aggregation_attribute.label}}</label>
|
|
||||||
</value>
|
|
||||||
<value id="function">
|
|
||||||
<label>{{aggregation_function.label}}</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
<node id="limit" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Limit</label>
|
|
||||||
<relevance-condition>{{order_by.value = 'function'}}</relevance-condition>
|
|
||||||
</node>
|
|
||||||
<node id="order_direction" xsi:type="Combodo-ValueType-Choice">
|
|
||||||
<label>UI:DashletGroupBy:Prop-OrderDirection</label>
|
|
||||||
<values>
|
|
||||||
<value id="asc">
|
|
||||||
<label>UI:DashletGroupBy:Order:asc</label>
|
|
||||||
</value>
|
|
||||||
<value id="desc">
|
|
||||||
<label>UI:DashletGroupBy:Order:desc</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
</nodes>
|
|
||||||
</definition>
|
|
||||||
</property_type>
|
|
||||||
<property_type id="DashletGroupByBars" xsi:type="Combodo-PropertyType">
|
|
||||||
<extends>Dashlet</extends>
|
|
||||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
|
||||||
<label>UI:DashletGroupBy:Title</label>
|
|
||||||
<nodes>
|
|
||||||
<node id="title" xsi:type="Combodo-ValueType-Label">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Title</label>
|
|
||||||
</node>
|
|
||||||
<node id="query" xsi:type="Combodo-ValueType-OQL">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Query</label>
|
|
||||||
</node>
|
|
||||||
<node id="group_by" xsi:type="Combodo-ValueType-ClassAttributeGroupBy">
|
|
||||||
<label>UI:DashletGroupBy:Prop-GroupBy</label>
|
|
||||||
<class>{{query.selected_class}}</class>
|
|
||||||
</node>
|
|
||||||
<node id="style" xsi:type="Combodo-ValueType-Choice"> <!-- Possible de le cacher, etc celui-ci nous met dedans -->
|
|
||||||
<label>UI:DashletGroupBy:Prop-Style</label>
|
|
||||||
<values>
|
|
||||||
<value id="bars">
|
|
||||||
<label>UI:DashletGroupByBars:Label</label>
|
|
||||||
</value>
|
|
||||||
<value id="pie">
|
|
||||||
<label>UI:DashletGroupByPie:Label</label>
|
|
||||||
</value>
|
|
||||||
<value id="table">
|
|
||||||
<label>UI:DashletGroupByTable:Label</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
<node id="aggregation_function" xsi:type="Combodo-ValueType-AggregateFunction">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Function</label>
|
|
||||||
<class>{{query.selected_class}}</class> <!-- pour savoir si il y a des attributs additionnables -->
|
|
||||||
</node>
|
|
||||||
<node id="aggregation_attribute" xsi:type="Combodo-ValueType-ClassAttribute">
|
|
||||||
<label>UI:DashletGroupBy:Prop-FunctionAttribute</label>
|
|
||||||
<relevance-condition>{{aggregation_function.value != 'count'}}</relevance-condition>
|
|
||||||
<class>{{query.selected_class}}</class>
|
|
||||||
<category>numeric</category>
|
|
||||||
</node>
|
|
||||||
<node id="order_by" xsi:type="Combodo-ValueType-ChoiceFromInput">
|
|
||||||
<label>UI:DashletGroupBy:Prop-OrderField</label>
|
|
||||||
<values>
|
|
||||||
<value id="attribute">
|
|
||||||
<label>{{aggregation_attribute.label}}</label>
|
|
||||||
</value>
|
|
||||||
<value id="function">
|
|
||||||
<label>{{aggregation_function.label}}</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
<node id="limit" xsi:type="Combodo-ValueType-Integer">
|
|
||||||
<label>UI:DashletGroupBy:Prop-Limit</label>
|
|
||||||
<relevance-condition>{{order_by.value = 'function'}}</relevance-condition>
|
|
||||||
</node>
|
|
||||||
<node id="order_direction" xsi:type="Combodo-ValueType-Choice">
|
|
||||||
<label>UI:DashletGroupBy:Prop-OrderDirection</label>
|
|
||||||
<values>
|
|
||||||
<value id="asc">
|
|
||||||
<label>UI:DashletGroupBy:Order:asc</label>
|
|
||||||
</value>
|
|
||||||
<value id="desc">
|
|
||||||
<label>UI:DashletGroupBy:Order:desc</label>
|
|
||||||
</value>
|
|
||||||
</values>
|
|
||||||
</node>
|
|
||||||
</nodes>
|
|
||||||
</definition>
|
|
||||||
</property_type>
|
|
||||||
<property_type id="DashletGroupByPie" xsi:type="Combodo-PropertyType">
|
|
||||||
<extends>Dashlet</extends>
|
<extends>Dashlet</extends>
|
||||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||||
<label>UI:DashletGroupBy:Title</label>
|
<label>UI:DashletGroupBy:Title</label>
|
||||||
|
|||||||
@@ -726,6 +726,10 @@ class DisplayBlock
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->m_oFilter->IsAllDataAllowed() && ($aExtraParams['display_unauthorized_objects'] ?? false) === true) {
|
||||||
|
$this->m_oFilter->AllowAllData();
|
||||||
|
}
|
||||||
|
|
||||||
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
|
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
|
||||||
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
|
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
|
||||||
}
|
}
|
||||||
@@ -1379,7 +1383,10 @@ JS
|
|||||||
|
|
||||||
// Check the classes that can be read (i.e authorized) by this user...
|
// Check the classes that can be read (i.e authorized) by this user...
|
||||||
foreach ($aClasses as $sAlias => $sClassName) {
|
foreach ($aClasses as $sAlias => $sClassName) {
|
||||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) {
|
if (
|
||||||
|
(UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) !== UR_ALLOWED_NO)
|
||||||
|
|| ($aExtraParams['display_unauthorized_objects'] ?? false) === true
|
||||||
|
) {
|
||||||
$aAuthorizedClasses[$sAlias] = $sClassName;
|
$aAuthorizedClasses[$sAlias] = $sClassName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Combodo\iTop\Application\Dashboard;
|
class ForgotPasswordApplicationException extends Exception
|
||||||
|
|
||||||
class DashboardException extends \Exception
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
10
application/exceptions/ForgotPasswordUserInputException.php
Normal file
10
application/exceptions/ForgotPasswordUserInputException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ForgotPasswordUserInputException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -243,15 +243,12 @@ class LoginTwigRenderer
|
|||||||
|
|
||||||
public function GetDefaultVars()
|
public function GetDefaultVars()
|
||||||
{
|
{
|
||||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
|
||||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||||
|
|
||||||
$aVars = [
|
$aVars = [
|
||||||
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
||||||
'aPluginFormData' => $this->GetPluginFormData(),
|
'aPluginFormData' => $this->GetPluginFormData(),
|
||||||
'sItopVersion' => ITOP_VERSION,
|
|
||||||
'sVersionShort' => $sVersionShort,
|
|
||||||
'sIconUrl' => $sIconUrl,
|
'sIconUrl' => $sIconUrl,
|
||||||
'sDisplayIcon' => $sDisplayIcon,
|
'sDisplayIcon' => $sDisplayIcon,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -221,15 +221,15 @@ class LoginWebPage extends NiceWebPage
|
|||||||
|
|
||||||
if ($oUser != null) {
|
if ($oUser != null) {
|
||||||
if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) {
|
if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) {
|
||||||
throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible'));
|
throw new ForgotPasswordUserInputException('External accounts do not allow password reset');
|
||||||
}
|
}
|
||||||
if (!$oUser->CanChangePassword()) {
|
if (!$oUser->CanChangePassword()) {
|
||||||
throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd'));
|
throw new ForgotPasswordUserInputException('The account does not allow password reset');
|
||||||
}
|
}
|
||||||
|
|
||||||
$sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed
|
$sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed
|
||||||
if ($sTo == '') {
|
if ($sTo == '') {
|
||||||
throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail'));
|
throw new ForgotPasswordUserInputException('Missing email address for this account');
|
||||||
}
|
}
|
||||||
|
|
||||||
// This token allows the user to change the password without knowing the previous one
|
// This token allows the user to change the password without knowing the previous one
|
||||||
@@ -255,17 +255,21 @@ class LoginWebPage extends NiceWebPage
|
|||||||
|
|
||||||
case EMAIL_SEND_ERROR:
|
case EMAIL_SEND_ERROR:
|
||||||
default:
|
default:
|
||||||
IssueLog::Error('Failed to send the email with the NEW password for '.$oUser->Get('friendlyname').': '.implode(', ', $aIssues));
|
throw new ForgotPasswordApplicationException('Failed to send the password reset email for '.$oUser->Get('friendlyname').': '.implode(', ', $aIssues));
|
||||||
throw new Exception(Dict::S('UI:ResetPwd-Error-Send'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oTwigContext = new LoginTwigRenderer();
|
} catch (ForgotPasswordApplicationException $e) {
|
||||||
$aVars = $oTwigContext->GetDefaultVars();
|
IssueLog::Error('Failed to process the forgot password request for user "'.$sAuthUser.'" [reason='.get_class($e).']: '.$e->getMessage());
|
||||||
$oTwigContext->Render($this, 'forgotpwdsent.html.twig', $aVars);
|
} catch (ForgotPasswordUserInputException $e) {
|
||||||
} catch (Exception $e) {
|
IssueLog::Info('Failed to process the forgot password request for user "'.$sAuthUser.'" [reason='.get_class($e).']: '.$e->getMessage());
|
||||||
$this->DisplayForgotPwdForm(true, $e->getMessage());
|
} catch (\Throwable $e) {
|
||||||
|
IssueLog::Error('Unexpected error while processing the forgot password request for user "'.$sAuthUser.'": '.$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$oTwigContext = new LoginTwigRenderer();
|
||||||
|
$aVars = $oTwigContext->GetDefaultVars();
|
||||||
|
$oTwigContext->Render($this, 'forgotpwdsent.html.twig', $aVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DisplayResetPwdForm($sErrorMessage = null)
|
public function DisplayResetPwdForm($sErrorMessage = null)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\PageContent\PageContentFactory;
|
|
||||||
use Combodo\iTop\Application\WebPage\ErrorPage;
|
use Combodo\iTop\Application\WebPage\ErrorPage;
|
||||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
use Combodo\iTop\Application\WebPage\WebPage;
|
||||||
@@ -1280,14 +1279,13 @@ class DashboardMenuNode extends MenuNode
|
|||||||
if ($oDashboard != null) {
|
if ($oDashboard != null) {
|
||||||
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
||||||
|
|
||||||
// TODO 3.3 this works for dashboard menu, what about other places ?
|
|
||||||
$oPageLayout = PageContentFactory::MakeForDashboard();
|
|
||||||
$oPage->SetContentLayout($oPageLayout, $oPage);
|
|
||||||
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
||||||
|
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
|
||||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||||
$aExtraParams['from_dashboard_page'] = true;
|
$aExtraParams['from_dashboard_page'] = true;
|
||||||
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
||||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||||
|
$oPage->add('</div>');
|
||||||
|
|
||||||
$bEdit = utils::ReadParam('edit', false);
|
$bEdit = utils::ReadParam('edit', false);
|
||||||
if ($bEdit) {
|
if ($bEdit) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ interface iNewsroomProvider
|
|||||||
* @param User $oUser The user for who to check if the provider is applicable.
|
* @param User $oUser The user for who to check if the provider is applicable.
|
||||||
* return bool
|
* return bool
|
||||||
*/
|
*/
|
||||||
public function IsApplicable(User $oUser = null);
|
public function IsApplicable(?User $oUser = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The human readable (localized) label for this provider
|
* The human readable (localized) label for this provider
|
||||||
@@ -139,7 +139,7 @@ abstract class NewsroomProviderBase implements iNewsroomProvider
|
|||||||
*/
|
*/
|
||||||
abstract public function GetViewAllURL();
|
abstract public function GetViewAllURL();
|
||||||
|
|
||||||
public function IsApplicable(User $oUser = null)
|
public function IsApplicable(?User $oUser = null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ abstract class Query extends cmdbAbstractObject
|
|||||||
* @return string|null
|
* @return string|null
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
abstract public function GetExportUrl(array $aValues = null): ?string;
|
abstract public function GetExportUrl(?array $aValues = null): ?string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update last export information.
|
* Update last export information.
|
||||||
@@ -227,7 +227,7 @@ class QueryOQL extends Query
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
public function GetExportUrl(array $aValues = null): ?string
|
public function GetExportUrl(?array $aValues = null): ?string
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// retrieve attributes
|
// retrieve attributes
|
||||||
|
|||||||
@@ -924,11 +924,6 @@ CSS;
|
|||||||
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp, $aImportsPaths)
|
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp, $aImportsPaths)
|
||||||
{
|
{
|
||||||
$aThemeParametersVariable = [];
|
$aThemeParametersVariable = [];
|
||||||
if (array_key_exists('variables', $aThemeParameters)) {
|
|
||||||
if (is_array($aThemeParameters['variables'])) {
|
|
||||||
$aThemeParametersVariable = array_merge([], $aThemeParameters['variables']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('variable_imports', $aThemeParameters)) {
|
if (array_key_exists('variable_imports', $aThemeParameters)) {
|
||||||
if (is_array($aThemeParameters['variable_imports'])) {
|
if (is_array($aThemeParameters['variable_imports'])) {
|
||||||
@@ -936,6 +931,14 @@ CSS;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Variables defined in theme XML have the priority over variables defined in XML imports files
|
||||||
|
// They're defined after so they overwrite previous parameters
|
||||||
|
if (array_key_exists('variables', $aThemeParameters)) {
|
||||||
|
if (is_array($aThemeParameters['variables'])) {
|
||||||
|
$aThemeParametersVariable = array_merge($aThemeParametersVariable, $aThemeParameters['variables']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
|
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
|
||||||
return $aThemeParametersVariable;
|
return $aThemeParametersVariable;
|
||||||
}
|
}
|
||||||
@@ -967,7 +970,9 @@ CSS;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array_map(function ($sVariableValue) { return ltrim($sVariableValue); }, $aVariablesResults);
|
array_map(function ($sVariableValue) {
|
||||||
|
return ltrim($sVariableValue);
|
||||||
|
}, $aVariablesResults);
|
||||||
return $aVariablesResults;
|
return $aVariablesResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ JS
|
|||||||
<<<HTML
|
<<<HTML
|
||||||
<form id="ObjectsAddForm_{$this->sInputid}">
|
<form id="ObjectsAddForm_{$this->sInputid}">
|
||||||
<div id="SearchResultsToAdd_{$this->sInputid}">
|
<div id="SearchResultsToAdd_{$this->sInputid}">
|
||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
<div style="border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ require_once(APPROOT.'/application/displayblock.class.inc.php');
|
|||||||
|
|
||||||
class UISearchFormForeignKeys
|
class UISearchFormForeignKeys
|
||||||
{
|
{
|
||||||
|
private $m_sRemoteClass;
|
||||||
|
private $m_iInputId;
|
||||||
|
|
||||||
public function __construct($sTargetClass, $iInputId = null)
|
public function __construct($sTargetClass, $iInputId = null)
|
||||||
{
|
{
|
||||||
$this->m_sRemoteClass = $sTargetClass;
|
$this->m_sRemoteClass = $sTargetClass;
|
||||||
@@ -40,7 +43,7 @@ class UISearchFormForeignKeys
|
|||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function ShowModalSearchForeignKeys($oPage, $sTitle)
|
public function ShowModalSearchForeignKeys($oPage)
|
||||||
{
|
{
|
||||||
|
|
||||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||||
@@ -60,52 +63,17 @@ class UISearchFormForeignKeys
|
|||||||
]
|
]
|
||||||
));
|
));
|
||||||
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sCancel = Dict::S('UI:Button:Cancel');
|
|
||||||
$sAdd = Dict::S('UI:Button:Add');
|
|
||||||
|
|
||||||
$oPage->add(
|
$oPage->add(
|
||||||
<<<HTML
|
<<<HTML
|
||||||
<form id="ObjectsAddForm_{$this->m_iInputId}">
|
<form id="ObjectsAddForm_{$this->m_iInputId}">
|
||||||
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;">
|
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;">
|
||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
<div style="border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
||||||
</form>
|
</form>
|
||||||
HTML
|
HTML
|
||||||
);
|
);
|
||||||
|
|
||||||
$oPage->add_ready_script(
|
|
||||||
<<<JS
|
|
||||||
$('#dlg_{$this->m_iInputId}').dialog({
|
|
||||||
width: $(window).width()*0.8,
|
|
||||||
height: $(window).height()*0.8,
|
|
||||||
autoOpen: false,
|
|
||||||
modal: true,
|
|
||||||
resizeStop: oForeignKeysWidget{$this->m_iInputId}.UpdateSizes,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: Dict.S('UI:Button:Cancel'),
|
|
||||||
class: "cancel ibo-is-alternative ibo-is-neutral",
|
|
||||||
click: function() {
|
|
||||||
$('#dlg_{$this->m_iInputId}').dialog('close');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: Dict.S('UI:Button:Add'),
|
|
||||||
id: 'btn_ok_{$this->m_iInputId}',
|
|
||||||
class: "ok ibo-is-regular ibo-is-primary",
|
|
||||||
click: function() {
|
|
||||||
oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
});
|
|
||||||
$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
|
|
||||||
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
|
|
||||||
$('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
|
|
||||||
JS
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
|
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
|
||||||
@@ -119,31 +87,4 @@ JS
|
|||||||
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
|
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for objects to be linked to the current object (i.e "remote" objects)
|
|
||||||
*
|
|
||||||
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
|
||||||
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of m_sRemoteClass
|
|
||||||
*
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function ListResultsSearchForeignKeys(WebPage $oP, $sRemoteClass = '')
|
|
||||||
{
|
|
||||||
if ($sRemoteClass != '') {
|
|
||||||
// assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass));
|
|
||||||
$oFilter = new DBObjectSearch($sRemoteClass);
|
|
||||||
} else {
|
|
||||||
// No remote class specified use the one defined in the linkedset
|
|
||||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
|
||||||
$oBlock->Display(
|
|
||||||
$oP,
|
|
||||||
"ResultsToAdd_{$this->m_iInputId}",
|
|
||||||
['menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}"]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ class utils
|
|||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public const ENUM_SANITIZATION_FILTER_VARIABLE_NAME = 'variable_name';
|
public const ENUM_SANITIZATION_FILTER_VARIABLE_NAME = 'variable_name';
|
||||||
|
/**
|
||||||
|
* @var string For module codes (e.g. `itop-portal-base`, `combodo-webhook-integration`, `some-module-code-x.y`, ...)
|
||||||
|
* @since 3.2.3 3.3.0 N°8554
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_MODULE_CODE = 'module_code';
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
* @since 2.7.10 3.0.0
|
* @since 2.7.10 3.0.0
|
||||||
@@ -181,6 +186,9 @@ class utils
|
|||||||
|
|
||||||
protected static function LoadParamFile($sParamFile)
|
protected static function LoadParamFile($sParamFile)
|
||||||
{
|
{
|
||||||
|
if (utils::RealPath($sParamFile, APPROOT) !== false) {
|
||||||
|
throw new Exception("File '".utils::HtmlEntities($sParamFile)."' should be outside iTop");
|
||||||
|
}
|
||||||
if (!file_exists($sParamFile)) {
|
if (!file_exists($sParamFile)) {
|
||||||
throw new Exception("Could not find the parameter file: '".utils::HtmlEntities($sParamFile)."'");
|
throw new Exception("Could not find the parameter file: '".utils::HtmlEntities($sParamFile)."'");
|
||||||
}
|
}
|
||||||
@@ -390,6 +398,7 @@ class utils
|
|||||||
* @since 2.7.10 N°6606 use the utils::ENUM_SANITIZATION_* const
|
* @since 2.7.10 N°6606 use the utils::ENUM_SANITIZATION_* const
|
||||||
* @since 2.7.10 N°6606 new case for ENUM_SANITIZATION_FILTER_PHP_CLASS
|
* @since 2.7.10 N°6606 new case for ENUM_SANITIZATION_FILTER_PHP_CLASS
|
||||||
* @since 3.2.1-1 N°8242 Allow value to be an array for every filter
|
* @since 3.2.1-1 N°8242 Allow value to be an array for every filter
|
||||||
|
* @since 3.2.3 3.3.0 N°8554 new case for ENUM_SANITIZATION_FILTER_MODULE_CODE
|
||||||
*
|
*
|
||||||
* @link https://www.php.net/manual/en/filter.filters.sanitize.php PHP sanitization filters
|
* @link https://www.php.net/manual/en/filter.filters.sanitize.php PHP sanitization filters
|
||||||
*/
|
*/
|
||||||
@@ -477,7 +486,7 @@ class utils
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// For XML / HTML node id selector
|
// For XML / HTML node selector
|
||||||
case static::ENUM_SANITIZATION_FILTER_ELEMENT_SELECTOR:
|
case static::ENUM_SANITIZATION_FILTER_ELEMENT_SELECTOR:
|
||||||
$retValue = filter_var(
|
$retValue = filter_var(
|
||||||
$value,
|
$value,
|
||||||
@@ -490,6 +499,15 @@ class utils
|
|||||||
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case static::ENUM_SANITIZATION_FILTER_MODULE_CODE:
|
||||||
|
// Module codes allow all alphabets letters, numbers, dash and dot characters
|
||||||
|
$retValue = filter_var(
|
||||||
|
$value,
|
||||||
|
FILTER_VALIDATE_REGEXP,
|
||||||
|
['options' => ['regexp' => '/^[\p{L}\d.-]+$/u']]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// For URL
|
// For URL
|
||||||
case static::ENUM_SANITIZATION_FILTER_URL:
|
case static::ENUM_SANITIZATION_FILTER_URL:
|
||||||
$retValue = filter_var($value, FILTER_SANITIZE_URL);
|
$retValue = filter_var($value, FILTER_SANITIZE_URL);
|
||||||
@@ -1284,7 +1302,7 @@ class utils
|
|||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function ExecITopScript(string $sScriptName, array $aArguments, string $sAuthUser = null, string $sAuthPwd = null)
|
public static function ExecITopScript(string $sScriptName, array $aArguments, ?string $sAuthUser = null, ?string $sAuthPwd = null)
|
||||||
{
|
{
|
||||||
$aDisabled = explode(', ', ini_get('disable_functions'));
|
$aDisabled = explode(', ', ini_get('disable_functions'));
|
||||||
if (in_array('exec', $aDisabled)) {
|
if (in_array('exec', $aDisabled)) {
|
||||||
@@ -1374,7 +1392,7 @@ class utils
|
|||||||
* @return string A path to a folder into which any module can store cache data
|
* @return string A path to a folder into which any module can store cache data
|
||||||
* The corresponding folder is created or cleaned upon code compilation
|
* The corresponding folder is created or cleaned upon code compilation
|
||||||
*/
|
*/
|
||||||
public static function GetCachePath(string $sEnvironment = null): string
|
public static function GetCachePath(?string $sEnvironment = null): string
|
||||||
{
|
{
|
||||||
if (is_null($sEnvironment)) {
|
if (is_null($sEnvironment)) {
|
||||||
$sEnvironment = MetaModel::GetEnvironment();
|
$sEnvironment = MetaModel::GetEnvironment();
|
||||||
@@ -1437,6 +1455,12 @@ class utils
|
|||||||
|
|
||||||
case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT:
|
case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT:
|
||||||
/** @var \DBObjectSet $param */
|
/** @var \DBObjectSet $param */
|
||||||
|
|
||||||
|
// Check if the user has the right to read the objects of this list, otherwise do not propose any action (eg. configure this list, export, etc.)
|
||||||
|
if (UserRights::IsActionAllowed($param->GetFilter()->GetClass(), UR_ACTION_READ, $param) !== UR_ALLOWED_YES) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$oAppContext = new ApplicationContext();
|
$oAppContext = new ApplicationContext();
|
||||||
$sContext = $oAppContext->GetForLink(true);
|
$sContext = $oAppContext->GetForLink(true);
|
||||||
$sDataTableId = is_null($sDataTableId) ? '' : $sDataTableId;
|
$sDataTableId = is_null($sDataTableId) ? '' : $sDataTableId;
|
||||||
@@ -2081,7 +2105,9 @@ SQL;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove any remaining nulls (for positions that weren't referenced)
|
// Remove any remaining nulls (for positions that weren't referenced)
|
||||||
$aReplacements = array_filter($aReplacements, static function ($val) { return $val !== null; });
|
$aReplacements = array_filter($aReplacements, static function ($val) {
|
||||||
|
return $val !== null;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// For non-positional, we need to map each position
|
// For non-positional, we need to map each position
|
||||||
$aReplacements = [];
|
$aReplacements = [];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"type": "project",
|
"type": "project",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.1.0 <8.4.0",
|
"php": ">=8.1.0 <8.5.0",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
@@ -12,38 +12,43 @@
|
|||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mysqli": "*",
|
"ext-mysqli": "*",
|
||||||
"ext-soap": "*",
|
"ext-soap": "*",
|
||||||
"apereo/phpcas": "~1.6.0",
|
"apereo/phpcas": "dev-master",
|
||||||
"firebase/php-jwt": "^6.4.0",
|
|
||||||
"guzzlehttp/guzzle": "^7.5.1",
|
"guzzlehttp/guzzle": "^7.5.1",
|
||||||
"league/oauth2-google": "^4.0.1",
|
"league/oauth2-google": "^4.0.1",
|
||||||
"nikic/php-parser": "dev-master",
|
"nikic/php-parser": "^4.14.0",
|
||||||
"pear/archive_tar": "~1.4.14",
|
"pear/archive_tar": "~1.4.14",
|
||||||
"pelago/emogrifier": "^7.2.0",
|
"pelago/emogrifier": "^7.2.0",
|
||||||
"psr/log": "^3.0.0",
|
"psr/log": "^3.0.0",
|
||||||
"scssphp/scssphp": "^1.12.1",
|
"scssphp/scssphp": "dev-combodo/1.x",
|
||||||
"soundasleep/html2text": "~2.1",
|
|
||||||
"symfony/console": "~6.4.0",
|
"symfony/console": "~6.4.0",
|
||||||
"symfony/dotenv": "~6.4.0",
|
"symfony/dotenv": "~6.4.0",
|
||||||
"symfony/form": "^6.4",
|
|
||||||
"symfony/framework-bundle": "~6.4.0",
|
"symfony/framework-bundle": "~6.4.0",
|
||||||
"symfony/http-foundation": "~6.4.0",
|
"symfony/http-foundation": "~6.4.0",
|
||||||
"symfony/http-kernel": "~6.4.0",
|
"symfony/http-kernel": "~6.4.0",
|
||||||
"symfony/mailer": "^6.4",
|
"symfony/runtime": "~6.4.0",
|
||||||
"symfony/security-csrf": "^6.4",
|
|
||||||
"symfony/twig-bundle": "~6.4.0",
|
"symfony/twig-bundle": "~6.4.0",
|
||||||
"symfony/validator" : "^6.4",
|
"symfony/var-dumper": "~6.4.0",
|
||||||
"symfony/yaml": "~6.4.0",
|
"symfony/yaml": "~6.4.0",
|
||||||
|
"symfony/mailer": "~6.4.0",
|
||||||
"tecnickcom/tcpdf": "^6.6.0",
|
"tecnickcom/tcpdf": "^6.6.0",
|
||||||
"thenetworg/oauth2-azure": "^2.0"
|
"thenetworg/oauth2-azure": "^2.0",
|
||||||
|
"soundasleep/html2text": "~2.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"symfony/debug-bundle": "~6.4.0",
|
||||||
"symfony/stopwatch": "~6.4.0",
|
"symfony/stopwatch": "~6.4.0",
|
||||||
"symfony/web-profiler-bundle": "~6.4.0"
|
"symfony/web-profiler-bundle": "~6.4.0"
|
||||||
},
|
},
|
||||||
"repositories": [{
|
"repositories": [
|
||||||
"type": "vcs",
|
{
|
||||||
"url": "https://github.com/Combodo/PHP-Parser"
|
"type": "vcs",
|
||||||
}],
|
"url": "https://github.com/EsupPortail/phpCAS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/combodo-itop-libs/scssphp"
|
||||||
|
}
|
||||||
|
],
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-libsodium": "Required to use the AttributeEncryptedString.",
|
"ext-libsodium": "Required to use the AttributeEncryptedString.",
|
||||||
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
|
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
|
||||||
@@ -63,7 +68,10 @@
|
|||||||
},
|
},
|
||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"classmap-authoritative": true,
|
"classmap-authoritative": true,
|
||||||
"platform-check": true
|
"platform-check": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"symfony/runtime": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"classmap": [
|
"classmap": [
|
||||||
@@ -72,6 +80,7 @@
|
|||||||
"sources"
|
"sources"
|
||||||
],
|
],
|
||||||
"exclude-from-classmap": [
|
"exclude-from-classmap": [
|
||||||
|
"application/twigextension.class.inc.php",
|
||||||
"core/oql/build/PHP/",
|
"core/oql/build/PHP/",
|
||||||
"core/apc-emulation.php",
|
"core/apc-emulation.php",
|
||||||
"application/startup.inc.php",
|
"application/startup.inc.php",
|
||||||
@@ -91,7 +100,7 @@
|
|||||||
"extra": {
|
"extra": {
|
||||||
"symfony": {
|
"symfony": {
|
||||||
"allow-contrib": false,
|
"allow-contrib": false,
|
||||||
"require": "6.4.*"
|
"require": "3.4.*"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"dotenv_path": "resources/symfony/.env"
|
"dotenv_path": "resources/symfony/.env"
|
||||||
|
|||||||
1308
composer.lock
generated
1308
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -234,10 +234,11 @@ abstract class Action extends cmdbAbstractObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
|
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
|
||||||
|
$oActionFilter->AllowAllData();
|
||||||
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
|
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
|
||||||
|
|
||||||
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
|
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
|
||||||
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle]);
|
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle, 'display_unauthorized_objects' => true]);
|
||||||
|
|
||||||
$oPage->AddUiBlock($oExecutionsListBlock);
|
$oPage->AddUiBlock($oExecutionsListBlock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
|||||||
* @param null $sAllowedValues : used for additional message that provides allowed values $sAllowedValues for current class
|
* @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
|
* @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);
|
parent::__construct(null, null, $sReason);
|
||||||
$this->sSerializedSearch = $sSerializedSearch;
|
$this->sSerializedSearch = $sSerializedSearch;
|
||||||
@@ -876,7 +876,7 @@ class BulkChange
|
|||||||
return $aResults;
|
return $aResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function CreateObject(&$aResult, $iRow, $aRowData, CMDBChange $oChange = null)
|
protected function CreateObject(&$aResult, $iRow, $aRowData, ?CMDBChange $oChange = null)
|
||||||
{
|
{
|
||||||
$oTargetObj = MetaModel::NewObject($this->m_sClass);
|
$oTargetObj = MetaModel::NewObject($this->m_sClass);
|
||||||
|
|
||||||
@@ -965,7 +965,7 @@ class BulkChange
|
|||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
* @throws \MySQLHasGoneAwayException
|
* @throws \MySQLHasGoneAwayException
|
||||||
*/
|
*/
|
||||||
protected function UpdateObject(&$aResult, $iRow, $oTargetObj, $aRowData, CMDBChange $oChange = null)
|
protected function UpdateObject(&$aResult, $iRow, $oTargetObj, $aRowData, ?CMDBChange $oChange = null)
|
||||||
{
|
{
|
||||||
$aResult[$iRow] = $this->PrepareObject($oTargetObj, $aRowData, $aErrors);
|
$aResult[$iRow] = $this->PrepareObject($oTargetObj, $aRowData, $aErrors);
|
||||||
|
|
||||||
@@ -1008,7 +1008,7 @@ class BulkChange
|
|||||||
*
|
*
|
||||||
* @throws \BulkChangeException
|
* @throws \BulkChangeException
|
||||||
*/
|
*/
|
||||||
protected function UpdateMissingObject(&$aResult, $iRow, $oTargetObj, CMDBChange $oChange = null)
|
protected function UpdateMissingObject(&$aResult, $iRow, $oTargetObj, ?CMDBChange $oChange = null)
|
||||||
{
|
{
|
||||||
$aResult[$iRow] = $this->PrepareMissingObject($oTargetObj, $aErrors);
|
$aResult[$iRow] = $this->PrepareMissingObject($oTargetObj, $aErrors);
|
||||||
|
|
||||||
@@ -1043,7 +1043,7 @@ class BulkChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Process(CMDBChange $oChange = null)
|
public function Process(?CMDBChange $oChange = null)
|
||||||
{
|
{
|
||||||
if ($oChange) {
|
if ($oChange) {
|
||||||
CMDBObject::SetCurrentChange($oChange);
|
CMDBObject::SetCurrentChange($oChange);
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ class Config
|
|||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'description' => 'Actions that are available as direct buttons next to the "Actions" menu',
|
'description' => 'Actions that are available as direct buttons next to the "Actions" menu',
|
||||||
// examples... not used
|
// examples... not used
|
||||||
'default' => 'UI:Menu:Modify,UI:Menu:New',
|
'default' => 'UI:Menu:Modify,UI:Menu:New,UI:Menu:impacts_down,UI:Menu:impacts_up',
|
||||||
'value' => 'UI:Menu:Modify',
|
'value' => 'UI:Menu:Modify',
|
||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => true,
|
'show_in_conf_sample' => true,
|
||||||
@@ -1613,7 +1613,7 @@ class Config
|
|||||||
'show_in_conf_sample' => false,
|
'show_in_conf_sample' => false,
|
||||||
],
|
],
|
||||||
'search_manual_submit' => [
|
'search_manual_submit' => [
|
||||||
'type' => 'array',
|
'type' => 'bool',
|
||||||
'description' => 'Force manual submit of search all requests',
|
'description' => 'Force manual submit of search all requests',
|
||||||
'default' => false,
|
'default' => false,
|
||||||
'value' => true,
|
'value' => true,
|
||||||
@@ -1740,6 +1740,14 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => false,
|
'show_in_conf_sample' => false,
|
||||||
],
|
],
|
||||||
|
'security.disable_joined_classes_filter' => [
|
||||||
|
'type' => 'bool',
|
||||||
|
'description' => 'If true, scope filters aren\'t applied to joined classes or union classes not directly listed in the SELECT clause.',
|
||||||
|
'default' => true,
|
||||||
|
'value' => true,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => false,
|
||||||
|
],
|
||||||
'security.hide_administrators' => [
|
'security.hide_administrators' => [
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
'description' => 'If true, non-administrator users will not be able to see the administrator accounts, the Administrator profile and the links between the administrator accounts and their profiles.',
|
'description' => 'If true, non-administrator users will not be able to see the administrator accounts, the Administrator profile and the links between the administrator accounts and their profiles.',
|
||||||
@@ -1748,6 +1756,14 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => false,
|
'show_in_conf_sample' => false,
|
||||||
],
|
],
|
||||||
|
'security.disable_exec_forced_login_for_all_enpoints' => [
|
||||||
|
'type' => 'bool',
|
||||||
|
'description' => 'If true, when no delegated authentication module is defined, no login will be forced on modules exec endpoints',
|
||||||
|
'default' => true,
|
||||||
|
'value' => true,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => false,
|
||||||
|
],
|
||||||
'behind_reverse_proxy' => [
|
'behind_reverse_proxy' => [
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)',
|
'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)',
|
||||||
@@ -1954,11 +1970,6 @@ class Config
|
|||||||
*/
|
*/
|
||||||
protected $m_sDefaultLanguage;
|
protected $m_sDefaultLanguage;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string Type of login process allowed: form|basic|url|external
|
|
||||||
*/
|
|
||||||
protected $m_sAllowedLoginTypes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Name of the PHP variable in which external authentication information is passed by the web server
|
* @var string Name of the PHP variable in which external authentication information is passed by the web server
|
||||||
*/
|
*/
|
||||||
@@ -2032,7 +2043,6 @@ class Config
|
|||||||
$this->m_iFastReloadInterval = DEFAULT_FAST_RELOAD_INTERVAL;
|
$this->m_iFastReloadInterval = DEFAULT_FAST_RELOAD_INTERVAL;
|
||||||
$this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED;
|
$this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED;
|
||||||
$this->m_sDefaultLanguage = 'EN US';
|
$this->m_sDefaultLanguage = 'EN US';
|
||||||
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
|
|
||||||
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
||||||
$this->m_aCharsets = [];
|
$this->m_aCharsets = [];
|
||||||
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
|
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
|
||||||
@@ -2179,7 +2189,6 @@ class Config
|
|||||||
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : [];
|
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : [];
|
||||||
|
|
||||||
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
||||||
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
|
|
||||||
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
||||||
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
|
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
|
||||||
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
|
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
|
||||||
@@ -2339,7 +2348,7 @@ class Config
|
|||||||
|
|
||||||
public function GetAllowedLoginTypes()
|
public function GetAllowedLoginTypes()
|
||||||
{
|
{
|
||||||
return explode('|', $this->m_sAllowedLoginTypes);
|
return explode('|', $this->m_aSettings['allowed_login_types']['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetExternalAuthenticationVariable()
|
public function GetExternalAuthenticationVariable()
|
||||||
@@ -2417,7 +2426,6 @@ class Config
|
|||||||
|
|
||||||
public function SetAllowedLoginTypes($aAllowedLoginTypes)
|
public function SetAllowedLoginTypes($aAllowedLoginTypes)
|
||||||
{
|
{
|
||||||
$this->m_sAllowedLoginTypes = implode('|', $aAllowedLoginTypes);
|
|
||||||
$this->Set('allowed_login_types', implode('|', $aAllowedLoginTypes));
|
$this->Set('allowed_login_types', implode('|', $aAllowedLoginTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2495,7 +2503,6 @@ class Config
|
|||||||
$aSettings['fast_reload_interval'] = $this->m_iFastReloadInterval;
|
$aSettings['fast_reload_interval'] = $this->m_iFastReloadInterval;
|
||||||
$aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired;
|
$aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired;
|
||||||
$aSettings['default_language'] = $this->m_sDefaultLanguage;
|
$aSettings['default_language'] = $this->m_sDefaultLanguage;
|
||||||
$aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes;
|
|
||||||
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
|
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
|
||||||
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
|
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
|
||||||
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
|
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
|
||||||
@@ -2599,7 +2606,6 @@ class Config
|
|||||||
// Old fashioned remaining values
|
// Old fashioned remaining values
|
||||||
$aOtherValues = [
|
$aOtherValues = [
|
||||||
'default_language' => $this->m_sDefaultLanguage,
|
'default_language' => $this->m_sDefaultLanguage,
|
||||||
'allowed_login_types' => $this->m_sAllowedLoginTypes,
|
|
||||||
'ext_auth_variable' => $this->m_sExtAuthVariable,
|
'ext_auth_variable' => $this->m_sExtAuthVariable,
|
||||||
'encryption_key' => $this->m_sEncryptionKey,
|
'encryption_key' => $this->m_sEncryptionKey,
|
||||||
'encryption_library' => $this->m_sEncryptionLibrary,
|
'encryption_library' => $this->m_sEncryptionLibrary,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\Helper\ExportHelper;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||||
@@ -13,7 +14,6 @@ use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory
|
|||||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory;
|
||||||
use Combodo\iTop\Application\Helper\ExportHelper;
|
|
||||||
use Combodo\iTop\Application\WebPage\Page;
|
use Combodo\iTop\Application\WebPage\Page;
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
use Combodo\iTop\Application\WebPage\WebPage;
|
||||||
|
|
||||||
@@ -55,6 +55,8 @@ class CSVBulkExport extends TabularBulkExport
|
|||||||
$this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('charset', 'UTF-8', true, 'raw_data'));
|
$this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('charset', 'UTF-8', true, 'raw_data'));
|
||||||
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
|
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
|
||||||
|
|
||||||
|
$this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER);
|
||||||
|
|
||||||
$sDateFormatRadio = utils::ReadParam('csv_date_format_radio', '');
|
$sDateFormatRadio = utils::ReadParam('csv_date_format_radio', '');
|
||||||
switch ($sDateFormatRadio) {
|
switch ($sDateFormatRadio) {
|
||||||
case 'default':
|
case 'default':
|
||||||
@@ -223,6 +225,10 @@ class CSVBulkExport extends TabularBulkExport
|
|||||||
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
|
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
|
||||||
$oFieldSetDate->AddSubBlock($oRadioCustom);
|
$oFieldSetDate->AddSubBlock($oRadioCustom);
|
||||||
|
|
||||||
|
$oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security'));
|
||||||
|
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity));
|
||||||
|
$oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport());
|
||||||
|
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#form_part_csv_options').on('preview_updated', function() { FormatDatesInPreview('csv', 'csv'); });
|
$('#form_part_csv_options').on('preview_updated', function() { FormatDatesInPreview('csv', 'csv'); });
|
||||||
@@ -264,6 +270,13 @@ EOF
|
|||||||
default:
|
default:
|
||||||
$sRet = trim($oObj->GetAsCSV($sAttCode), '"');
|
$sRet = trim($oObj->GetAsCSV($sAttCode), '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the option to ignore Excel sanitization is not set or explicitly set to false, apply sanitization
|
||||||
|
if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) {
|
||||||
|
return ExportHelper::SanitizeField($sRet, $this->aStatusInfo['text_qualifier'] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// The option to ignore Excel sanitization is explicitly set to true: return the raw value without sanitization
|
||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +350,12 @@ EOF
|
|||||||
$sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']);
|
$sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the option to ignore Excel sanitization is not set or absent, sanitize the field
|
||||||
|
if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) {
|
||||||
|
$sField = ExportHelper::SanitizeField($sField, $this->aStatusInfo['text_qualifier']);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->aStatusInfo['charset'] != 'UTF-8') {
|
if ($this->aStatusInfo['charset'] != 'UTF-8') {
|
||||||
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
|
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
|
||||||
// and thus to convert field by field and not the whole row or file at once (see ticket N°991)
|
// and thus to convert field by field and not the whole row or file at once (see ticket N°991)
|
||||||
|
|||||||
@@ -425,7 +425,7 @@
|
|||||||
</php_parent>
|
</php_parent>
|
||||||
<parent>cmdbAbstractObject</parent>
|
<parent>cmdbAbstractObject</parent>
|
||||||
<properties>
|
<properties>
|
||||||
<category>core/cmdb,view_in_gui</category>
|
<category>core/cmdb,grant_by_profile,silo</category>
|
||||||
<abstract>false</abstract>
|
<abstract>false</abstract>
|
||||||
<key_type>autoincrement</key_type>
|
<key_type>autoincrement</key_type>
|
||||||
<db_table>priv_event_newsroom</db_table>
|
<db_table>priv_event_newsroom</db_table>
|
||||||
@@ -904,7 +904,7 @@
|
|||||||
<!-- Generated by toolkit/export-class-to-meta.php -->
|
<!-- Generated by toolkit/export-class-to-meta.php -->
|
||||||
<parent>Event</parent>
|
<parent>Event</parent>
|
||||||
<properties>
|
<properties>
|
||||||
<category>core/cmdb,view_in_gui</category>
|
<category>core/cmdb,grant_by_profile,silo</category>
|
||||||
</properties>
|
</properties>
|
||||||
<fields>
|
<fields>
|
||||||
<field id="message" xsi:type="AttributeText"/>
|
<field id="message" xsi:type="AttributeText"/>
|
||||||
|
|||||||
@@ -2567,7 +2567,7 @@ abstract class DBObject implements iDisplay
|
|||||||
*
|
*
|
||||||
* @see \RestUtils::FindObjectFromKey for the same check in the REST endpoint
|
* @see \RestUtils::FindObjectFromKey for the same check in the REST endpoint
|
||||||
*/
|
*/
|
||||||
final public function CheckChangedExtKeysValues(callable $oIsObjectLoadableCallback = null)
|
final public function CheckChangedExtKeysValues(?callable $oIsObjectLoadableCallback = null)
|
||||||
{
|
{
|
||||||
if (is_null($oIsObjectLoadableCallback)) {
|
if (is_null($oIsObjectLoadableCallback)) {
|
||||||
$oIsObjectLoadableCallback = function ($sClass, $sId) {
|
$oIsObjectLoadableCallback = function ($sClass, $sId) {
|
||||||
@@ -3727,7 +3727,7 @@ abstract class DBObject implements iDisplay
|
|||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
* @throws \OQLException
|
* @throws \OQLException
|
||||||
*/
|
*/
|
||||||
private function ActivateOnObjectUpdateTriggers(?DBObject $oObject, array $aAttributes = null): void
|
private function ActivateOnObjectUpdateTriggers(?DBObject $oObject, ?array $aAttributes = null): void
|
||||||
{
|
{
|
||||||
if (is_null($oObject)) {
|
if (is_null($oObject)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1932,4 +1932,37 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
return $this->GetCriteria()->ListParameters();
|
return $this->GetCriteria()->ListParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
* @return DBObjectSearch
|
||||||
|
*/
|
||||||
|
protected function ApplyDataFilters(): DBObjectSearch
|
||||||
|
{
|
||||||
|
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oSearch = $this;
|
||||||
|
$aClassesToFilter = $this->GetSelectedClasses();
|
||||||
|
|
||||||
|
// Opt-in for joined classes filtering, otherwise only filter the selected class(es)
|
||||||
|
if (MetaModel::GetConfig()->Get('security.disable_joined_classes_filter') === false) {
|
||||||
|
$aClassesToFilter = $this->GetJoinedClasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply filter (this is similar to the one in DBSearch but the factorization could make it less readable)
|
||||||
|
foreach ($aClassesToFilter as $sClassAlias => $sClass) {
|
||||||
|
$oVisibleObjects = UserRights::GetSelectFilter($sClass, $this->GetModifierProperties('UserRightsGetSelectFilter'));
|
||||||
|
if ($oVisibleObjects === false) {
|
||||||
|
$oVisibleObjects = DBObjectSearch::FromEmptySet($sClass);
|
||||||
|
}
|
||||||
|
if (is_object($oVisibleObjects)) {
|
||||||
|
$oVisibleObjects->AllowAllData();
|
||||||
|
$oSearch = $oSearch->Filter($sClassAlias, $oVisibleObjects);
|
||||||
|
$oSearch->SetDataFiltered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $oSearch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ abstract class DBSearch
|
|||||||
*
|
*
|
||||||
* @throws OQLException
|
* @throws OQLException
|
||||||
*/
|
*/
|
||||||
public static function FromOQL($sQuery, $aParams = null, ModelReflection $oMetaModel = null)
|
public static function FromOQL($sQuery, $aParams = null, ?ModelReflection $oMetaModel = null)
|
||||||
{
|
{
|
||||||
if (empty($sQuery)) {
|
if (empty($sQuery)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -1048,21 +1048,7 @@ abstract class DBSearch
|
|||||||
*/
|
*/
|
||||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
|
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
|
||||||
{
|
{
|
||||||
$oSearch = $this;
|
$oSearch = $this->ApplyDataFilters();
|
||||||
if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered()) {
|
|
||||||
foreach ($this->GetSelectedClasses() as $sClassAlias => $sClass) {
|
|
||||||
$oVisibleObjects = UserRights::GetSelectFilter($sClass, $this->GetModifierProperties('UserRightsGetSelectFilter'));
|
|
||||||
if ($oVisibleObjects === false) {
|
|
||||||
// Make sure this is a valid search object, saying NO for all
|
|
||||||
$oVisibleObjects = DBObjectSearch::FromEmptySet($sClass);
|
|
||||||
}
|
|
||||||
if (is_object($oVisibleObjects)) {
|
|
||||||
$oVisibleObjects->AllowAllData();
|
|
||||||
$oSearch = $oSearch->Filter($sClassAlias, $oVisibleObjects);
|
|
||||||
$oSearch->SetDataFiltered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($aGroupByExpr)) {
|
if (is_array($aGroupByExpr)) {
|
||||||
foreach ($aGroupByExpr as $sAlias => $oGroupByExp) {
|
foreach ($aGroupByExpr as $sAlias => $oGroupByExp) {
|
||||||
@@ -1524,4 +1510,33 @@ abstract class DBSearch
|
|||||||
* @return array{\VariableExpression}
|
* @return array{\VariableExpression}
|
||||||
*/
|
*/
|
||||||
abstract public function GetExpectedArguments(): array;
|
abstract public function GetExpectedArguments(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply data filters to the search, if needed
|
||||||
|
*
|
||||||
|
* @return DBSearch
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
|
protected function ApplyDataFilters(): DBSearch
|
||||||
|
{
|
||||||
|
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oSearch = $this;
|
||||||
|
$aClassesToFilter = $this->GetSelectedClasses();
|
||||||
|
|
||||||
|
foreach ($aClassesToFilter as $sClassAlias => $sClass) {
|
||||||
|
$oVisibleObjects = UserRights::GetSelectFilter($sClass, $this->GetModifierProperties('UserRightsGetSelectFilter'));
|
||||||
|
if ($oVisibleObjects === false) {
|
||||||
|
$oVisibleObjects = DBObjectSearch::FromEmptySet($sClass);
|
||||||
|
}
|
||||||
|
if (is_object($oVisibleObjects)) {
|
||||||
|
$oVisibleObjects->AllowAllData();
|
||||||
|
$oSearch = $oSearch->Filter($sClassAlias, $oVisibleObjects);
|
||||||
|
$oSearch->SetDataFiltered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $oSearch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class DBUnionSearch extends DBSearch
|
|||||||
public function AllowAllData($bAllowAllData = true)
|
public function AllowAllData($bAllowAllData = true)
|
||||||
{
|
{
|
||||||
foreach ($this->aSearches as $oSearch) {
|
foreach ($this->aSearches as $oSearch) {
|
||||||
$oSearch->AllowAllData();
|
$oSearch->AllowAllData($bAllowAllData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,4 +673,30 @@ class DBUnionSearch extends DBSearch
|
|||||||
|
|
||||||
return $aVariableCriteria;
|
return $aVariableCriteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
* @return DBUnionSearch
|
||||||
|
*/
|
||||||
|
protected function ApplyDataFilters(): DBUnionSearch
|
||||||
|
{
|
||||||
|
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opt-in for joined classes filtering, otherwise fallback on DBSearch filtering
|
||||||
|
if (MetaModel::GetConfig()->Get('security.disable_joined_classes_filter') === true) {
|
||||||
|
return parent::ApplyDataFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply filters per sub-search
|
||||||
|
$aFilteredSearches = [];
|
||||||
|
foreach ($this->GetSearches() as $oSubSearch) {
|
||||||
|
// Recursively call ApplyDataFilters on sub-searches
|
||||||
|
$aFilteredSearches[] = $oSubSearch->ApplyDataFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
$oSearch = new DBUnionSearch($aFilteredSearches);
|
||||||
|
return $oSearch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ class DesignElement extends \DOMElement
|
|||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @since 3.1.2 3.2.0 N°6974
|
* @since 3.1.2 3.2.0 N°6974
|
||||||
*/
|
*/
|
||||||
public static function _FindNode(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null): ?DesignElement
|
public static function _FindNode(DOMNode $oParent, DesignElement $oRefNode, ?string $sSearchId = null): ?DesignElement
|
||||||
{
|
{
|
||||||
$oNodes = self::_FindNodes($oParent, $oRefNode, $sSearchId);
|
$oNodes = self::_FindNodes($oParent, $oRefNode, $sSearchId);
|
||||||
if ($oNodes instanceof DOMNodeList) {
|
if ($oNodes instanceof DOMNodeList) {
|
||||||
@@ -477,7 +477,7 @@ class DesignElement extends \DOMElement
|
|||||||
* @return \DOMNodeList|false|mixed
|
* @return \DOMNodeList|false|mixed
|
||||||
* @since 3.1.2 3.2.0 N°6974
|
* @since 3.1.2 3.2.0 N°6974
|
||||||
*/
|
*/
|
||||||
public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null)
|
public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, ?string $sSearchId = null)
|
||||||
{
|
{
|
||||||
if ($oParent instanceof DOMDocument) {
|
if ($oParent instanceof DOMDocument) {
|
||||||
$oDoc = $oParent->firstChild->ownerDocument;
|
$oDoc = $oParent->firstChild->ownerDocument;
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ class DisplayableGroupNode extends DisplayableNode
|
|||||||
$this->aObjects = [];
|
$this->aObjects = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddObject(DBObject $oObj = null)
|
public function AddObject(?DBObject $oObj = null)
|
||||||
{
|
{
|
||||||
if (is_object($oObj)) {
|
if (is_object($oObj)) {
|
||||||
$sPrevClass = $this->GetObjectClass();
|
$sPrevClass = $this->GetObjectClass();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Event extends DBObject implements iDisplay
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -120,7 +120,7 @@ class EventNotification extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -156,7 +156,7 @@ class EventNotificationEmail extends EventNotification
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -192,7 +192,7 @@ class EventIssue extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -286,7 +286,7 @@ class EventWebService extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -321,7 +321,7 @@ class EventRestService extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -356,7 +356,7 @@ class EventLoginUsage extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
@@ -394,7 +394,7 @@ class EventOnObject extends Event
|
|||||||
{
|
{
|
||||||
$aParams =
|
$aParams =
|
||||||
[
|
[
|
||||||
"category" => "core/cmdb,view_in_gui",
|
"category" => "core/cmdb,grant_by_profile,silo",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\Helper\ExportHelper;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory;
|
use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory;
|
||||||
use Combodo\iTop\Application\Helper\ExportHelper;
|
|
||||||
use Combodo\iTop\Application\WebPage\Page;
|
use Combodo\iTop\Application\WebPage\Page;
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
use Combodo\iTop\Application\WebPage\WebPage;
|
||||||
|
|
||||||
@@ -63,6 +63,8 @@ class ExcelBulkExport extends TabularBulkExport
|
|||||||
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
|
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
|
||||||
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
|
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function EnumFormParts()
|
public function EnumFormParts()
|
||||||
@@ -121,6 +123,10 @@ class ExcelBulkExport extends TabularBulkExport
|
|||||||
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
|
$oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox');
|
||||||
$oFieldSetDate->AddSubBlock($oRadioCustom);
|
$oFieldSetDate->AddSubBlock($oRadioCustom);
|
||||||
|
|
||||||
|
$oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security'));
|
||||||
|
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity));
|
||||||
|
$oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport());
|
||||||
|
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#form_part_xlsx_options').on('preview_updated', function() { FormatDatesInPreview('excel', 'xlsx'); });
|
$('#form_part_xlsx_options').on('preview_updated', function() { FormatDatesInPreview('excel', 'xlsx'); });
|
||||||
@@ -216,6 +222,12 @@ EOF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the option to ignore Excel sanitization is not set or absent, sanitize the field
|
||||||
|
if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) {
|
||||||
|
return ExportHelper::SanitizeField($sRet, '');
|
||||||
|
}
|
||||||
|
|
||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,13 +259,18 @@ class InlineImage extends DBObject
|
|||||||
* that refer to an InlineImage (detected via the attribute data-img-id="") so that
|
* that refer to an InlineImage (detected via the attribute data-img-id="") so that
|
||||||
* the URL is consistent with the current URL of the application.
|
* the URL is consistent with the current URL of the application.
|
||||||
*
|
*
|
||||||
* @param string $sHtml The HTML fragment to process
|
N°8681 * @param string|null $sHtml The HTML fragment to process
|
||||||
*
|
*
|
||||||
* @return string The modified HTML
|
* @return string The modified HTML
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @since 3.3.0 N°8681 Add type hint for parameters and return value
|
||||||
*/
|
*/
|
||||||
public static function FixUrls($sHtml)
|
public static function FixUrls(string|null $sHtml): string
|
||||||
{
|
{
|
||||||
|
// N°8681 - Ensure to have a string value
|
||||||
|
$sHtml = $sHtml ?? '';
|
||||||
|
|
||||||
$aNeedles = [];
|
$aNeedles = [];
|
||||||
$aReplacements = [];
|
$aReplacements = [];
|
||||||
// Find img tags with an attribute data-img-id
|
// Find img tags with an attribute data-img-id
|
||||||
@@ -293,6 +298,46 @@ class InlineImage extends DBObject
|
|||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace <img> tags with a data-img-id attribute by the actual image in base64 representation
|
||||||
|
* so that the image can be displayed even if the download URL is not accessible (e.g. in unauthenticated approval templates)
|
||||||
|
*
|
||||||
|
* @param string $sHtml The HTML fragment to process
|
||||||
|
*
|
||||||
|
* @return String The modified HTML
|
||||||
|
* @since 3.2.3
|
||||||
|
*/
|
||||||
|
public static function ReplaceInlineImagesWithBase64Representation(string $sHtml): String
|
||||||
|
{
|
||||||
|
return preg_replace_callback(
|
||||||
|
'/<img\s+[^>]*'.static::DOM_ATTR_ID.'="(\d+)"[^>]*>/i',
|
||||||
|
function ($matches) {
|
||||||
|
|
||||||
|
// Extract inline image ID from the tag
|
||||||
|
$id = $matches[1];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Retrieve inline image
|
||||||
|
$oInline = MetaModel::GetObject(InlineImage::class, $id, true, true);
|
||||||
|
$oOrmDocument = $oInline->Get('contents');
|
||||||
|
|
||||||
|
// Replace src image by the base64 representation
|
||||||
|
$sInlineImageAsBase64 = base64_encode($oOrmDocument->GetData());
|
||||||
|
$sDataUri = 'data:'.$oOrmDocument->GetMimeType().';base64,'.$sInlineImageAsBase64;
|
||||||
|
$sImage = preg_replace('/src=["\'][^"\']+["\']/', 'src="'.$sDataUri.'"', $matches[0]);
|
||||||
|
|
||||||
|
// Remove sensitive information (the image ID and secret) from the tag
|
||||||
|
$sImage = preg_replace('/'.static::DOM_ATTR_ID.'="\d+"\s+'.static::DOM_ATTR_SECRET.'="\w+"/', '', $sImage);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$sImage = '<img src="" alt="'.Dict::S('UI:MissingInlineImage').'">';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sImage;
|
||||||
|
},
|
||||||
|
$sHtml
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an extra attribute data-img-id for images which are based on an actual InlineImage
|
* Add an extra attribute data-img-id for images which are based on an actual InlineImage
|
||||||
* so that we can later reconstruct the full "src" URL when needed
|
* so that we can later reconstruct the full "src" URL when needed
|
||||||
@@ -389,7 +434,7 @@ JS
|
|||||||
* Resize an image so that it fits the maximum width/height defined in the config file
|
* Resize an image so that it fits the maximum width/height defined in the config file
|
||||||
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
|
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
|
||||||
* @return ormDocument The resampled image (or the original one if it already fit)
|
* @return ormDocument The resampled image (or the original one if it already fit)
|
||||||
* @deprecated Replaced by ormDocument::ResizeImageToFit
|
* @deprecated since 3.3.0 Replaced by ormDocument::ResizeImageToFit
|
||||||
*/
|
*/
|
||||||
public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null)
|
public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\EventRegister\ApplicationEvents;
|
||||||
use Combodo\iTop\Core\Kpi\KpiLogData;
|
use Combodo\iTop\Core\Kpi\KpiLogData;
|
||||||
|
use Combodo\iTop\Service\Events\EventService;
|
||||||
|
use Combodo\iTop\Service\Events\iEventServiceSetup;
|
||||||
use Combodo\iTop\Service\Module\ModuleService;
|
use Combodo\iTop\Service\Module\ModuleService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measures operations duration, memory usage, etc. (and some other KPIs)
|
* Measures operations duration, memory usage, etc. (and some other KPIs)
|
||||||
*/
|
*/
|
||||||
|
class ExecutionKPI implements iEventServiceSetup
|
||||||
class ExecutionKPI
|
|
||||||
{
|
{
|
||||||
protected static $m_bEnabled_Duration = false;
|
protected static $m_bEnabled_Duration = false;
|
||||||
protected static $m_bEnabled_Memory = false;
|
protected static $m_bEnabled_Memory = false;
|
||||||
@@ -23,15 +25,18 @@ class ExecutionKPI
|
|||||||
|
|
||||||
protected static $m_aStats = []; // Recurrent operations
|
protected static $m_aStats = []; // Recurrent operations
|
||||||
protected static $m_aExecData = []; // One shot operations
|
protected static $m_aExecData = []; // One shot operations
|
||||||
/**
|
/** @var true */
|
||||||
* @var array[ExecutionKPI]
|
private static bool $bMetamodelStarted = false;
|
||||||
*/
|
|
||||||
protected static $m_aExecutionStack = []; // embedded execution stats
|
|
||||||
|
|
||||||
|
private static ?float $fLastReportTime = null;
|
||||||
|
private static ?float $iLastReportMemory = null;
|
||||||
|
|
||||||
|
// For stats
|
||||||
protected $m_fStarted = null;
|
protected $m_fStarted = null;
|
||||||
protected $m_fChildrenDuration = 0; // Count embedded
|
|
||||||
protected $m_iInitialMemory = null;
|
protected $m_iInitialMemory = null;
|
||||||
|
|
||||||
|
private static array $aBootstrapOperations = [];
|
||||||
|
|
||||||
public static function EnableDuration($iLevel)
|
public static function EnableDuration($iLevel)
|
||||||
{
|
{
|
||||||
if ($iLevel > 0) {
|
if ($iLevel > 0) {
|
||||||
@@ -71,6 +76,7 @@ class ExecutionKPI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +103,7 @@ class ExecutionKPI
|
|||||||
$sFor = self::$m_sAllowedUser == '*' ? 'EVERYBODY' : "'".trim(self::$m_sAllowedUser)."'";
|
$sFor = self::$m_sAllowedUser == '*' ? 'EVERYBODY' : "'".trim(self::$m_sAllowedUser)."'";
|
||||||
$sSlowQueries = '';
|
$sSlowQueries = '';
|
||||||
if (self::$m_fSlowQueries > 0) {
|
if (self::$m_fSlowQueries > 0) {
|
||||||
$sSlowQueries = ". Slow Queries: ".self::$m_fSlowQueries."s";
|
$sSlowQueries = '. Slow Queries: '.self::$m_fSlowQueries.'s';
|
||||||
}
|
}
|
||||||
|
|
||||||
$aExtensions = [];
|
$aExtensions = [];
|
||||||
@@ -127,7 +133,7 @@ class ExecutionKPI
|
|||||||
$sRequest .= ' operation: '.$_POST['operation'];
|
$sRequest .= ' operation: '.$_POST['operation'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$fStop = MyHelpers::getmicrotime();
|
$fStop = microtime(true);
|
||||||
if (($fStop - $fItopStarted) > self::$m_fSlowQueries) {
|
if (($fStop - $fItopStarted) > self::$m_fSlowQueries) {
|
||||||
// Invoke extensions to log the KPI operation
|
// Invoke extensions to log the KPI operation
|
||||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||||
@@ -151,17 +157,17 @@ class ExecutionKPI
|
|||||||
|
|
||||||
$sTableStyle = 'background-color: #ccc; margin: 10px;';
|
$sTableStyle = 'background-color: #ccc; margin: 10px;';
|
||||||
|
|
||||||
$sHtml = "<hr/>";
|
$sHtml = '<hr/>';
|
||||||
$sHtml .= "<div style=\"background-color: grey; padding: 10px;\">";
|
$sHtml .= "<div style=\"background-color: grey; padding: 10px;\">";
|
||||||
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - $sRequest</h3>";
|
$sHtml .= "<h3><a name=\"".md5($sExecId)."\">KPIs</a> - $sRequest</h3>";
|
||||||
$oStarted = DateTime::createFromFormat('U.u', $fItopStarted);
|
$oStarted = DateTime::createFromFormat('U.u', $fItopStarted);
|
||||||
$sHtml .= '<p>'.$oStarted->format('Y-m-d H:i:s.u').'</p>';
|
$sHtml .= '<p>'.$oStarted->format('Y-m-d H:i:s.u').'</p>';
|
||||||
$sHtml .= "<p>log_kpi_user_id: ".UserRights::GetUserId()."</p>";
|
$sHtml .= '<p>log_kpi_user_id: '.UserRights::GetUserId().'</p>';
|
||||||
$sHtml .= "<div>";
|
$sHtml .= '<div>';
|
||||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||||
$sHtml .= "<thead>";
|
$sHtml .= '<thead>';
|
||||||
$sHtml .= " <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>";
|
$sHtml .= ' <th>Operation</th><th>Begin</th><th>End</th><th>Duration</th><th>Memory start</th><th>Memory end</th><th>Memory peak</th>';
|
||||||
$sHtml .= "</thead>";
|
$sHtml .= '</thead>';
|
||||||
foreach (self::$m_aExecData as $aOpStats) {
|
foreach (self::$m_aExecData as $aOpStats) {
|
||||||
$sOperation = $aOpStats['op'];
|
$sOperation = $aOpStats['op'];
|
||||||
$sBegin = round($aOpStats['time_begin'], 3);
|
$sBegin = round($aOpStats['time_begin'], 3);
|
||||||
@@ -180,12 +186,12 @@ class ExecutionKPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sHtml .= "<tr>";
|
$sHtml .= '<tr>';
|
||||||
$sHtml .= " <td>$sOperation</td><td>$sBegin</td><td>$sEnd</td><td>$sDuration</td><td>$sMemBegin</td><td>$sMemEnd</td><td>$sMemPeak</td>";
|
$sHtml .= " <td>$sOperation</td><td>$sBegin</td><td>$sEnd</td><td>$sDuration</td><td>$sMemBegin</td><td>$sMemEnd</td><td>$sMemPeak</td>";
|
||||||
$sHtml .= "</tr>";
|
$sHtml .= '</tr>';
|
||||||
}
|
}
|
||||||
$sHtml .= "</table>";
|
$sHtml .= '</table>';
|
||||||
$sHtml .= "</div>";
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$aConsolidatedStats = [];
|
$aConsolidatedStats = [];
|
||||||
foreach (self::$m_aStats as $sOperation => $aOpStats) {
|
foreach (self::$m_aStats as $sOperation => $aOpStats) {
|
||||||
@@ -208,20 +214,20 @@ class ExecutionKPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$aConsolidatedStats[$sOperation] = [
|
$aConsolidatedStats[$sOperation] = [
|
||||||
'count' => $iTotalOp,
|
'count' => $iTotalOp,
|
||||||
'duration' => $fTotalOp,
|
'duration' => $fTotalOp,
|
||||||
'min' => $fMinOp,
|
'min' => $fMinOp,
|
||||||
'max' => $fMaxOp,
|
'max' => $fMaxOp,
|
||||||
'avg' => $fTotalOp / $iTotalOp,
|
'avg' => $fTotalOp / $iTotalOp,
|
||||||
'max_args' => $sMaxOpArguments,
|
'max_args' => $sMaxOpArguments,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$sHtml .= "<div>";
|
$sHtml .= '<div>';
|
||||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||||
$sHtml .= "<thead>";
|
$sHtml .= '<thead>';
|
||||||
$sHtml .= " <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>";
|
$sHtml .= ' <th>Operation</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th><th>Avg</th>';
|
||||||
$sHtml .= "</thead>";
|
$sHtml .= '</thead>';
|
||||||
foreach ($aConsolidatedStats as $sOperation => $aOpStats) {
|
foreach ($aConsolidatedStats as $sOperation => $aOpStats) {
|
||||||
$sOperation = '<a href="#'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
$sOperation = '<a href="#'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||||
$sCount = $aOpStats['count'];
|
$sCount = $aOpStats['count'];
|
||||||
@@ -230,14 +236,14 @@ class ExecutionKPI
|
|||||||
$sMax = '<a href="#'.md5($sExecId.$aOpStats['max_args']).'">'.round($aOpStats['max'], 3).'</a>';
|
$sMax = '<a href="#'.md5($sExecId.$aOpStats['max_args']).'">'.round($aOpStats['max'], 3).'</a>';
|
||||||
$sAvg = round($aOpStats['avg'], 3);
|
$sAvg = round($aOpStats['avg'], 3);
|
||||||
|
|
||||||
$sHtml .= "<tr>";
|
$sHtml .= '<tr>';
|
||||||
$sHtml .= " <td>$sOperation</td><td>$sCount</td><td>$sDuration</td><td>$sMin</td><td>$sMax</td><td>$sAvg</td>";
|
$sHtml .= " <td>$sOperation</td><td>$sCount</td><td>$sDuration</td><td>$sMin</td><td>$sMax</td><td>$sAvg</td>";
|
||||||
$sHtml .= "</tr>";
|
$sHtml .= '</tr>';
|
||||||
}
|
}
|
||||||
$sHtml .= "</table>";
|
$sHtml .= '</table>';
|
||||||
$sHtml .= "</div>";
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$sHtml .= "</div>";
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$sHtml .= "<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>";
|
$sHtml .= "<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>";
|
||||||
|
|
||||||
@@ -287,18 +293,18 @@ class ExecutionKPI
|
|||||||
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
|
||||||
$sHtml .= "<h4>$sOperationHtml</h4>";
|
$sHtml .= "<h4>$sOperationHtml</h4>";
|
||||||
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
$sHtml .= "<table border=\"1\" style=\"$sTableStyle\">";
|
||||||
$sHtml .= "<thead>";
|
$sHtml .= '<thead>';
|
||||||
$sHtml .= " <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>";
|
$sHtml .= ' <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>';
|
||||||
$sHtml .= "</thead>";
|
$sHtml .= '</thead>';
|
||||||
$bDisplayHeader = false;
|
$bDisplayHeader = false;
|
||||||
}
|
}
|
||||||
$sHtml .= "<tr>";
|
$sHtml .= '<tr>';
|
||||||
$sHtml .= " <td>$sHtmlArguments</td><td>$iCountInter</td><td>$sTotalInter</td><td>$sMinInter</td><td>$sMaxInter</td>";
|
$sHtml .= " <td>$sHtmlArguments</td><td>$iCountInter</td><td>$sTotalInter</td><td>$sMinInter</td><td>$sMaxInter</td>";
|
||||||
$sHtml .= "</tr>";
|
$sHtml .= '</tr>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$bDisplayHeader) {
|
if (!$bDisplayHeader) {
|
||||||
$sHtml .= "</table>";
|
$sHtml .= '</table>';
|
||||||
$sHtml .= "<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>";
|
$sHtml .= "<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>";
|
||||||
}
|
}
|
||||||
self::Report($sHtml);
|
self::Report($sHtml);
|
||||||
@@ -333,39 +339,50 @@ class ExecutionKPI
|
|||||||
|
|
||||||
$aNewEntry = null;
|
$aNewEntry = null;
|
||||||
|
|
||||||
$fStarted = $this->m_fStarted;
|
if (is_null(static::$fLastReportTime)) {
|
||||||
$fStopped = $this->m_fStarted;
|
static::$fLastReportTime = $fItopStarted;
|
||||||
if (self::$m_bEnabled_Duration) {
|
|
||||||
$fStopped = MyHelpers::getmicrotime();
|
|
||||||
$aNewEntry = [
|
|
||||||
'op' => $sOperationDesc,
|
|
||||||
'time_begin' => $this->m_fStarted - $fItopStarted,
|
|
||||||
'time_end' => $fStopped - $fItopStarted,
|
|
||||||
];
|
|
||||||
// Reset for the next operation (if the object is recycled)
|
|
||||||
$this->m_fStarted = $fStopped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
|
if (is_null(static::$iLastReportMemory)) {
|
||||||
$iCurrentMemory = 0;
|
global $iItopInitialMemory;
|
||||||
$iPeakMemory = 0;
|
static::$iLastReportMemory = $iItopInitialMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fStarted = static::$fLastReportTime;
|
||||||
|
$fStopped = microtime(true);
|
||||||
|
if (self::$m_bEnabled_Duration) {
|
||||||
|
$aNewEntry = [
|
||||||
|
'op' => $sOperationDesc,
|
||||||
|
'time_begin' => $fStarted - $fItopStarted,
|
||||||
|
'time_end' => $fStopped - $fItopStarted,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
static::$fLastReportTime = $fStopped;
|
||||||
|
|
||||||
|
$iInitialMemory = static::$iLastReportMemory;
|
||||||
|
$iCurrentMemory = $iInitialMemory;
|
||||||
|
$iPeakMemory = $iInitialMemory;
|
||||||
if (self::$m_bEnabled_Memory) {
|
if (self::$m_bEnabled_Memory) {
|
||||||
$iCurrentMemory = self::memory_get_usage();
|
$iCurrentMemory = self::memory_get_usage();
|
||||||
if (is_null($aNewEntry)) {
|
if (is_null($aNewEntry)) {
|
||||||
$aNewEntry = ['op' => $sOperationDesc];
|
$aNewEntry = ['op' => $sOperationDesc];
|
||||||
}
|
}
|
||||||
$aNewEntry['mem_begin'] = $this->m_iInitialMemory;
|
$aNewEntry['mem_begin'] = $iInitialMemory;
|
||||||
$aNewEntry['mem_end'] = $iCurrentMemory;
|
$aNewEntry['mem_end'] = $iCurrentMemory;
|
||||||
$iPeakMemory = self::memory_get_peak_usage();
|
$iPeakMemory = self::memory_get_peak_usage();
|
||||||
$aNewEntry['mem_peak'] = $iPeakMemory;
|
$aNewEntry['mem_peak'] = $iPeakMemory;
|
||||||
// Reset for the next operation (if the object is recycled)
|
// Reset for the next operation (if the object is recycled)
|
||||||
$this->m_iInitialMemory = $iCurrentMemory;
|
static::$iLastReportMemory = $iCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
|
if (self::$m_bEnabled_Duration || self::$m_bEnabled_Memory) {
|
||||||
// Invoke extensions to log the KPI operation
|
$aCallstack = ['callstack' => $this->GetCallStack()];
|
||||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
if (static::$bMetamodelStarted) {
|
||||||
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
foreach (static::$aBootstrapOperations as $oLog) {
|
||||||
|
$this->LogOperation($oLog);
|
||||||
|
}
|
||||||
|
static::$aBootstrapOperations = [];
|
||||||
|
// Invoke extensions to log the KPI operation
|
||||||
$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
|
$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
|
||||||
$oKPILogData = new KpiLogData(
|
$oKPILogData = new KpiLogData(
|
||||||
KpiLogData::TYPE_REPORT,
|
KpiLogData::TYPE_REPORT,
|
||||||
@@ -376,9 +393,24 @@ class ExecutionKPI
|
|||||||
$sExtension,
|
$sExtension,
|
||||||
$iInitialMemory,
|
$iInitialMemory,
|
||||||
$iCurrentMemory,
|
$iCurrentMemory,
|
||||||
$iPeakMemory
|
$iPeakMemory,
|
||||||
|
$aCallstack
|
||||||
);
|
);
|
||||||
$oExtensionInstance->LogOperation($oKPILogData);
|
$this->LogOperation($oKPILogData);
|
||||||
|
} else {
|
||||||
|
$oKPILogData = new KpiLogData(
|
||||||
|
KpiLogData::TYPE_REPORT,
|
||||||
|
'Step',
|
||||||
|
$sOperationDesc,
|
||||||
|
$fStarted,
|
||||||
|
$fStopped,
|
||||||
|
'',
|
||||||
|
$iInitialMemory,
|
||||||
|
$iCurrentMemory,
|
||||||
|
$iPeakMemory,
|
||||||
|
$aCallstack
|
||||||
|
);
|
||||||
|
static::$aBootstrapOperations[] = $oKPILogData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,13 +420,21 @@ class ExecutionKPI
|
|||||||
$this->ResetCounters();
|
$this->ResetCounters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function LogOperation(KpiLogData $oKPILogData): void
|
||||||
|
{
|
||||||
|
/** @var \iKPILoggerExtension $oExtensionInstance */
|
||||||
|
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
||||||
|
$oExtensionInstance->LogOperation($oKPILogData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute statistics for a call to an extension
|
* Compute statistics for a call to an extension
|
||||||
* Note: not working in dev mode (with links to env-production)
|
* Note: not working in dev mode (with links to env-production)
|
||||||
*
|
*
|
||||||
* @param object|string $object object called
|
* @param object|string $object object called
|
||||||
* @param string $sMethod method called on the object
|
* @param string $sMethod method called on the object
|
||||||
* @param string $sMessage additional message
|
* @param string $sMessage additional message
|
||||||
*
|
*
|
||||||
* @return bool true if an extension was found for this object::method
|
* @return bool true if an extension was found for this object::method
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
@@ -423,21 +463,23 @@ class ExecutionKPI
|
|||||||
|
|
||||||
$fDuration = 0;
|
$fDuration = 0;
|
||||||
if (self::$m_bEnabled_Duration) {
|
if (self::$m_bEnabled_Duration) {
|
||||||
$fStopped = MyHelpers::getmicrotime();
|
$fStopped = microtime(true);
|
||||||
$fDuration = $fStopped - $this->m_fStarted;
|
$fDuration = $fStopped - $this->m_fStarted;
|
||||||
$aCallstack = [];
|
$aCallstack = [];
|
||||||
if (self::$m_bGenerateLegacyReport) {
|
if (self::$m_bGenerateLegacyReport) {
|
||||||
if (self::$m_bBlameCaller) {
|
if (self::$m_bBlameCaller) {
|
||||||
$aCallstack = MyHelpers::get_callstack(1);
|
$aCallstack = MyHelpers::get_callstack(1);
|
||||||
self::$m_aStats[$sOperation][$sArguments][] = [
|
self::$m_aStats[$sOperation][$sArguments][] = [
|
||||||
'time' => $fDuration,
|
'time' => $fDuration,
|
||||||
'callers' => $aCallstack,
|
'callers' => $aCallstack,
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
self::$m_aStats[$sOperation][$sArguments][] = [
|
self::$m_aStats[$sOperation][$sArguments][] = [
|
||||||
'time' => $fDuration,
|
'time' => $fDuration,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$aCallstack = ['callstack' => $this->GetCallStack()];
|
||||||
}
|
}
|
||||||
|
|
||||||
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
|
$iInitialMemory = is_null($this->m_iInitialMemory) ? 0 : $this->m_iInitialMemory;
|
||||||
@@ -448,33 +490,45 @@ class ExecutionKPI
|
|||||||
$iPeakMemory = self::memory_get_peak_usage();
|
$iPeakMemory = self::memory_get_peak_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke extensions to log the KPI operation
|
if (static::$bMetamodelStarted) {
|
||||||
/** @var \iKPILoggerExtension $oExtensionInstance */
|
foreach (static::$aBootstrapOperations as $oLog) {
|
||||||
foreach (MetaModel::EnumPlugins('iKPILoggerExtension') as $oExtensionInstance) {
|
$this->LogOperation($oLog);
|
||||||
//$sExtension = ModuleService::GetInstance()->GetModuleNameFromCallStack(1);
|
}
|
||||||
$sExtension = '';
|
static::$aBootstrapOperations = [];
|
||||||
$oKPILogData = new KpiLogData(
|
$oKPILogData = new KpiLogData(
|
||||||
KpiLogData::TYPE_STATS,
|
KpiLogData::TYPE_STATS,
|
||||||
$sOperation,
|
$sOperation,
|
||||||
$sArguments,
|
$sArguments,
|
||||||
$this->m_fStarted,
|
$this->m_fStarted,
|
||||||
$fStopped,
|
$fStopped,
|
||||||
$sExtension,
|
'',
|
||||||
$iInitialMemory,
|
$iInitialMemory,
|
||||||
$iCurrentMemory,
|
$iCurrentMemory,
|
||||||
$iPeakMemory,
|
$iPeakMemory,
|
||||||
$aCallstack
|
$aCallstack
|
||||||
);
|
);
|
||||||
$oExtensionInstance->LogOperation($oKPILogData);
|
$this->LogOperation($oKPILogData);
|
||||||
|
} else {
|
||||||
|
$oKPILogData = new KpiLogData(
|
||||||
|
KpiLogData::TYPE_STATS,
|
||||||
|
$sOperation,
|
||||||
|
$sArguments,
|
||||||
|
$this->m_fStarted,
|
||||||
|
$fStopped,
|
||||||
|
'',
|
||||||
|
$iInitialMemory,
|
||||||
|
$iCurrentMemory,
|
||||||
|
$iPeakMemory,
|
||||||
|
$aCallstack
|
||||||
|
);
|
||||||
|
static::$aBootstrapOperations[] = $oKPILogData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function ResetCounters()
|
protected function ResetCounters()
|
||||||
{
|
{
|
||||||
if (self::$m_bEnabled_Duration) {
|
$this->m_fStarted = microtime(true);
|
||||||
$this->m_fStarted = microtime(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self::$m_bEnabled_Memory) {
|
if (self::$m_bEnabled_Memory) {
|
||||||
$this->m_iInitialMemory = self::memory_get_usage();
|
$this->m_iInitialMemory = self::memory_get_usage();
|
||||||
@@ -503,7 +557,33 @@ class ExecutionKPI
|
|||||||
if (function_exists('memory_get_peak_usage')) {
|
if (function_exists('memory_get_peak_usage')) {
|
||||||
return memory_get_peak_usage($bRealUsage);
|
return memory_get_peak_usage($bRealUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PHP > 5.2.1 - this verb depends on a compilation option
|
// PHP > 5.2.1 - this verb depends on a compilation option
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ModuleHandlerApiInterface methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function OnMetaModelStarted()
|
||||||
|
{
|
||||||
|
static::$bMetamodelStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function RegisterEventsAndListeners()
|
||||||
|
{
|
||||||
|
EventService::RegisterListener(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED, [$this, 'OnMetaModelStarted']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function GetCallStack(): string
|
||||||
|
{
|
||||||
|
$aCallStack = MyHelpers::get_callstack(2);
|
||||||
|
$sCallStack = "Call stack:\n";
|
||||||
|
foreach ($aCallStack as $index => $aLine) {
|
||||||
|
$sCallStack .= "#$index ".$aLine['File'].'('.$aLine['Line'].'): '.$aLine['Function']."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sCallStack;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -691,7 +691,7 @@ abstract class LogAPI
|
|||||||
static::$m_oMockMetaModelConfig = $oMetaModelConfig;
|
static::$m_oMockMetaModelConfig = $oMetaModelConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function Exception(string $sMessage, throwable $oException, string $sChannel = null, array $aContext = []): void
|
public static function Exception(string $sMessage, throwable $oException, ?string $sChannel = null, array $aContext = []): void
|
||||||
{
|
{
|
||||||
$aErrorLogs = [];
|
$aErrorLogs = [];
|
||||||
$aErrorLogs[] = static::PrepareErrorLog($sMessage, $oException, $aContext);
|
$aErrorLogs[] = static::PrepareErrorLog($sMessage, $oException, $aContext);
|
||||||
|
|||||||
@@ -89,17 +89,9 @@ abstract class ModelReflection
|
|||||||
* @param string $defaultValue
|
* @param string $defaultValue
|
||||||
*
|
*
|
||||||
* @return \RunTimeIconSelectionField
|
* @return \RunTimeIconSelectionField
|
||||||
* @deprecated since 3.3.0 replaced by GetAvailableIcons
|
|
||||||
*/
|
*/
|
||||||
abstract public function GetIconSelectionField($sCode, $sLabel = '', $defaultValue = '');
|
abstract public function GetIconSelectionField($sCode, $sLabel = '', $defaultValue = '');
|
||||||
|
|
||||||
/**
|
|
||||||
* Find available icons for the current context
|
|
||||||
*
|
|
||||||
* @return array of ['value', 'label', 'icon'] where 'value' is the relative path on disk, 'label' the name to display and 'icon' is the URL to get the image
|
|
||||||
*/
|
|
||||||
abstract public function GetAvailableIcons(): array;
|
|
||||||
|
|
||||||
abstract public function GetRootClass($sClass);
|
abstract public function GetRootClass($sClass);
|
||||||
abstract public function EnumChildClasses($sClass, $iOption = ENUM_CHILD_CLASSES_EXCLUDETOP);
|
abstract public function EnumChildClasses($sClass, $iOption = ENUM_CHILD_CLASSES_EXCLUDETOP);
|
||||||
}
|
}
|
||||||
@@ -117,8 +109,6 @@ abstract class QueryReflection
|
|||||||
|
|
||||||
class ModelReflectionRuntime extends ModelReflection
|
class ModelReflectionRuntime extends ModelReflection
|
||||||
{
|
{
|
||||||
private static array $aAllIcons = [];
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -265,52 +255,6 @@ class ModelReflectionRuntime extends ModelReflection
|
|||||||
return new RunTimeIconSelectionField($sCode, $sLabel, $defaultValue);
|
return new RunTimeIconSelectionField($sCode, $sLabel, $defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetAvailableIcons(): array
|
|
||||||
{
|
|
||||||
$aFolderList = [
|
|
||||||
APPROOT.'env-'.utils::GetCurrentEnvironment() => utils::GetAbsoluteUrlModulesRoot(),
|
|
||||||
APPROOT.'images/icons' => utils::GetAbsoluteUrlAppRoot().'images/icons',
|
|
||||||
];
|
|
||||||
if (count(self::$aAllIcons) == 0) {
|
|
||||||
foreach ($aFolderList as $sFolderPath => $sUrlPrefix) {
|
|
||||||
$aIcons = self::FindIconsOnDisk($sFolderPath);
|
|
||||||
ksort($aIcons);
|
|
||||||
|
|
||||||
foreach ($aIcons as $sFilePath) {
|
|
||||||
self::$aAllIcons[] = ['value' => $sFilePath, 'label' => basename($sFilePath), 'icon' => $sUrlPrefix.$sFilePath];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$aAllIcons;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function FindIconsOnDisk(string $sBaseDir, string $sDir = '', array &$aFilesSpecs = []): array
|
|
||||||
{
|
|
||||||
$aResult = [];
|
|
||||||
// Populate automatically the list of icon files
|
|
||||||
if ($hDir = @opendir($sBaseDir.'/'.$sDir)) {
|
|
||||||
while (($sFile = readdir($hDir)) !== false) {
|
|
||||||
$aMatches = [];
|
|
||||||
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile)) {
|
|
||||||
$sDirSubPath = ($sDir == '') ? $sFile : $sDir.'/'.$sFile;
|
|
||||||
$aResult = array_merge($aResult, self::FindIconsOnDisk($sBaseDir, $sDirSubPath, $aFilesSpecs));
|
|
||||||
}
|
|
||||||
$sSize = filesize($sBaseDir.'/'.$sDir.'/'.$sFile);
|
|
||||||
if (isset($aFilesSpecs[$sFile]) && $aFilesSpecs[$sFile] == $sSize) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/\.(png|jpg|jpeg|gif|svg)$/i', $sFile, $aMatches)) { // png, jp(e)g, gif and svg are considered valid
|
|
||||||
$aResult[$sFile.'_'.$sDir] = $sDir.'/'.$sFile;
|
|
||||||
$aFilesSpecs[$sFile] = $sSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir($hDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetRootClass($sClass)
|
public function GetRootClass($sClass)
|
||||||
{
|
{
|
||||||
return MetaModel::GetRootClass($sClass);
|
return MetaModel::GetRootClass($sClass);
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ class ormCaseLog
|
|||||||
/**
|
/**
|
||||||
* Produces an HTML representation, aimed at being used within the iTop framework
|
* Produces an HTML representation, aimed at being used within the iTop framework
|
||||||
*/
|
*/
|
||||||
public function GetAsHTML(WebPage $oP = null, $bEditMode = false, $aTransfoHandler = null)
|
public function GetAsHTML(?WebPage $oP = null, $bEditMode = false, $aTransfoHandler = null)
|
||||||
{
|
{
|
||||||
$bPrintableVersion = (utils::ReadParam('printable', '0') == '1');
|
$bPrintableVersion = (utils::ReadParam('printable', '0') == '1');
|
||||||
|
|
||||||
|
|||||||
@@ -350,20 +350,22 @@ class ormDocument
|
|||||||
if (!is_object($oObj)) {
|
if (!is_object($oObj)) {
|
||||||
// If access to the document is not granted, check if the access to the host object is allowed
|
// If access to the document is not granted, check if the access to the host object is allowed
|
||||||
$oObj = MetaModel::GetObject($sClass, $id, false, true);
|
$oObj = MetaModel::GetObject($sClass, $id, false, true);
|
||||||
|
$bHasHostRights = false;
|
||||||
if ($oObj instanceof Attachment) {
|
if ($oObj instanceof Attachment) {
|
||||||
$sItemClass = $oObj->Get('item_class');
|
$sItemClass = $oObj->Get('item_class');
|
||||||
$sItemId = $oObj->Get('item_id');
|
$sItemId = $oObj->Get('item_id');
|
||||||
$oHost = MetaModel::GetObject($sItemClass, $sItemId, false, false);
|
$oHost = MetaModel::GetObject($sItemClass, $sItemId, false, false);
|
||||||
if (!is_object($oHost)) {
|
if (is_object($oHost)) {
|
||||||
$oObj = null;
|
$bHasHostRights = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_object($oObj)) {
|
|
||||||
|
// We could neither read the object nor get a host object matching our rights
|
||||||
|
if ($bHasHostRights !== true) {
|
||||||
throw new Exception("Invalid id ($id) for class '$sClass' - the object does not exist or you are not allowed to view it");
|
throw new Exception("Invalid id ($id) for class '$sClass' - the object does not exist or you are not allowed to view it");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (($sSecretField != null) && ($oObj->Get($sSecretField) != $sSecretValue)) {
|
if (($sSecretField != null) && !hash_equals($oObj->Get($sSecretField), $sSecretValue)) {
|
||||||
usleep(200);
|
|
||||||
throw new Exception("Invalid secret for class '$sClass' - the object does not exist or you are not allowed to view it");
|
throw new Exception("Invalid secret for class '$sClass' - the object does not exist or you are not allowed to view it");
|
||||||
}
|
}
|
||||||
/** @var \ormDocument $oDocument */
|
/** @var \ormDocument $oDocument */
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
* @param DBObjectSet|null $oOriginalSet
|
* @param DBObjectSet|null $oOriginalSet
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function __construct($sHostClass, $sAttCode, DBObjectSet $oOriginalSet = null)
|
public function __construct($sHostClass, $sAttCode, ?DBObjectSet $oOriginalSet = null)
|
||||||
{
|
{
|
||||||
$this->sHostClass = $sHostClass;
|
$this->sHostClass = $sHostClass;
|
||||||
$this->sAttCode = $sAttCode;
|
$this->sAttCode = $sAttCode;
|
||||||
@@ -470,17 +470,6 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
|| ($this->oOriginalSet->GetFilter()->ToOQL() == $oFellow->oOriginalSet->GetFilter()->ToOQL())) {
|
|| ($this->oOriginalSet->GetFilter()->ToOQL() == $oFellow->oOriginalSet->GetFilter()->ToOQL())) {
|
||||||
$bUpdateFromDelta = true;
|
$bUpdateFromDelta = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//@since 3.2.2 N°2364 - API : remove old linkedset persistance
|
|
||||||
/* Goo pattern to use:
|
|
||||||
* $oCISet = $oTicket->Get(‘functioncis_list’);
|
|
||||||
* $oCISet->AddItem(MetaModel::NewObject(‘lnkFunctionCIToTicket’, array(‘ci_id’=> 12345));
|
|
||||||
* $oCISet->RemoveItem(123456);
|
|
||||||
* $oTicket->Set(‘functionalcis_list’, $oCISet);
|
|
||||||
*/
|
|
||||||
if (!ContextTag::Check(ContextTag::TAG_SETUP)) {
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('old pattern - please get previous value of the linked set, modify it and set it back to the host object');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bUpdateFromDelta) {
|
if ($bUpdateFromDelta) {
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ class ormPassword
|
|||||||
$bResult = false;
|
$bResult = false;
|
||||||
$aInfo = password_get_info($this->m_sHashed);
|
$aInfo = password_get_info($this->m_sHashed);
|
||||||
if (is_null($aInfo["algo"]) || $aInfo["algo"] === 0) {
|
if (is_null($aInfo["algo"]) || $aInfo["algo"] === 0) {
|
||||||
//unknown, assume it's a legacy password
|
// - Unknown algorithm, assume it's a legacy password
|
||||||
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
|
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
|
||||||
$bResult = ($this->m_sHashed == $sHashedPwd);
|
$bResult = hash_equals($this->m_sHashed, $sHashedPwd);
|
||||||
} else {
|
} else {
|
||||||
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
|
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,3 +4,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@import "bulk-modify";
|
@import "bulk-modify";
|
||||||
|
@import "bulk-export";
|
||||||
|
|||||||
10
css/backoffice/application/bulk/_bulk-export.scss
Normal file
10
css/backoffice/application/bulk/_bulk-export.scss
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#form_part_csv_options:has(#ibo-sanitize-excel-export--input:checked), #form_part_xlsx_options:has(#ibo-sanitize-excel-export--input:checked){
|
||||||
|
#ibo-sanitize-excel-export--alert {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -75,26 +75,3 @@ collection-entry-element {
|
|||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-form-compact{
|
|
||||||
|
|
||||||
.ibo-field{
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
label{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
max-width: unset;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,9 +72,12 @@ $ibo-panel--icon--spacing--as-medallion--is-sticking: $ibo-panel--icon--spacing-
|
|||||||
$ibo-panel--icon--bottom--as-medallion--is-sticking: -12px !default;
|
$ibo-panel--icon--bottom--as-medallion--is-sticking: -12px !default;
|
||||||
$ibo-panel--icon--border--as-medallion--is-sticking: 1px $ibo-panel--base-border-style $ibo-panel--base-border-color !default;
|
$ibo-panel--icon--border--as-medallion--is-sticking: 1px $ibo-panel--base-border-style $ibo-panel--base-border-color !default;
|
||||||
|
|
||||||
$ibo-panel--icon-background--size--must-contain: contain !default;
|
$ibo-panel--icon-background--size--must-contain: contain !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-contain
|
||||||
$ibo-panel--icon-background--size--must-cover: cover !default;
|
$ibo-panel--icon-background--size--must-cover: cover !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-cover
|
||||||
$ibo-panel--icon-background--size--must-zoomout: 66.67% !default;
|
$ibo-panel--icon-background--size--must-zoomout: 66.67% !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-zoomout
|
||||||
|
$ibo-panel--icon-img--size--must-contain: $ibo-panel--icon-background--size--must-contain !default; // TODO remove when dealing with N°9317
|
||||||
|
$ibo-panel--icon-img--size--must-cover: $ibo-panel--icon-background--size--must-cover !default; // TODO remove when dealing with N°9317
|
||||||
|
$ibo-panel--icon-img--size--must-zoomout: $ibo-panel--icon-background--size--must-zoomout !default; // TODO remove when dealing with N°9317
|
||||||
|
|
||||||
$ibo-panel--title--font-size--is-sticking: $ibo-font-size-150 !default;
|
$ibo-panel--title--font-size--is-sticking: $ibo-font-size-150 !default;
|
||||||
$ibo-panel--title--color: $ibo-color-grey-900 !default;
|
$ibo-panel--title--color: $ibo-color-grey-900 !default;
|
||||||
@@ -179,24 +182,25 @@ $ibo-panel--is-selectable--body--after--font-size: $ibo-font-size-700 !default;
|
|||||||
min-height: $ibo-panel--icon--size;
|
min-height: $ibo-panel--icon--size;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-panel--icon-background {
|
.ibo-panel--icon-img, .ibo-panel--icon-background { // second class is deprecated, remove it when dealing with N°9317
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: $ibo-panel--icon-background--size--must-contain;
|
background-size: $ibo-panel--icon-img--size--must-contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-panel--icon-background--must-contain {
|
.ibo-panel--icon-img--must-contain, .ibo-panel--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-panel--icon-background--size--must-contain;
|
background-size: $ibo-panel--icon-img--size--must-contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-panel--icon-background--must-cover {
|
.ibo-panel--icon-img--must-cover, .ibo-panel--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-panel--icon-background--size--must-cover;
|
background-size: $ibo-panel--icon-img--size--must-cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-panel--icon-background--must-zoomout {
|
.ibo-panel--icon-img--must-zoomout, .ibo-panel--icon-background--must-zoomout { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-panel--icon-background--size--must-zoomout;
|
width: $ibo-panel--icon-img--size--must-zoomout;
|
||||||
|
height: $ibo-panel--icon-img--size--must-zoomout;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-panel--title {
|
.ibo-panel--title {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ $ibo-search-form-panel--more-criteria--color: $ibo-color-blue-grey-800 !default;
|
|||||||
$ibo-search-form-panel--more-criteria--background-color: $ibo-color-white-100 !default;
|
$ibo-search-form-panel--more-criteria--background-color: $ibo-color-white-100 !default;
|
||||||
$ibo-search-form-panel--more-criteria--icon--color: $ibo-color-primary-600 !default;
|
$ibo-search-form-panel--more-criteria--icon--color: $ibo-color-primary-600 !default;
|
||||||
$ibo-search-form-panel--more-criteria--border-color: $ibo-search-form-panel--criteria--border-color !default;
|
$ibo-search-form-panel--more-criteria--border-color: $ibo-search-form-panel--criteria--border-color !default;
|
||||||
|
// calc is redundant but avoid SCSS min() from being used instead of CSS min()
|
||||||
|
$ibo-search-form-panel--criteria--max-height: calc(min(#{$ibo-size-750}, 50vh)) !default;
|
||||||
|
|
||||||
$ibo-search-form-panel--items--hover--color: $ibo-color-grey-200 !default;
|
$ibo-search-form-panel--items--hover--color: $ibo-color-grey-200 !default;
|
||||||
|
|
||||||
@@ -278,9 +280,10 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sfc_form_group {
|
.sfc_form_group {
|
||||||
display: block;
|
display: flex;
|
||||||
margin-top: -1px;
|
flex-direction: column;
|
||||||
z-index: -1;
|
margin-top: -1px;
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,11 +349,15 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
|||||||
display: none;
|
display: none;
|
||||||
max-width: 450px;
|
max-width: 450px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-height: 520px;
|
max-height: $ibo-search-form-panel--criteria--max-height;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
.sfc_fg_operators {
|
.sfc_fg_operators {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
|
min-height: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
.sfc_fg_operator {
|
.sfc_fg_operator {
|
||||||
@@ -387,6 +394,9 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sfc_opc_multichoices {
|
.sfc_opc_multichoices {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
label > input {
|
label > input {
|
||||||
vertical-align: text-top;
|
vertical-align: text-top;
|
||||||
margin-left: $ibo-spacing-0;
|
margin-left: $ibo-spacing-0;
|
||||||
@@ -398,7 +408,6 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sfc_opc_mc_items_wrapper {
|
.sfc_opc_mc_items_wrapper {
|
||||||
max-height: 415px; /* Must be less than .sfc_form_group:max-height - .sfc_opc_mc_toggler:height - .sfc_opc_mc_filter:height */
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin: $ibo-spacing-0 -8px; /* Compensate .sfc_opc_multichoices side padding so the hover style can take the full with */
|
margin: $ibo-spacing-0 -8px; /* Compensate .sfc_opc_multichoices side padding so the hover style can take the full with */
|
||||||
|
|
||||||
@@ -560,8 +569,14 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
|||||||
&.search_form_criteria_enum {
|
&.search_form_criteria_enum {
|
||||||
.sfc_form_group {
|
.sfc_form_group {
|
||||||
.sfc_fg_operator_in {
|
.sfc_fg_operator_in {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
> label {
|
> label {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
line-height: initial;
|
line-height: initial;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ $ibo-title--icon--size: 90px !default;
|
|||||||
$ibo-title--icon--size-2: 80px !default;
|
$ibo-title--icon--size-2: 80px !default;
|
||||||
$ibo-title--icon--size-3: 70px !default;
|
$ibo-title--icon--size-3: 70px !default;
|
||||||
|
|
||||||
$ibo-title--icon-background--size--must-contain: contain !default;
|
$ibo-title--icon-background--size--must-contain: contain !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-contain
|
||||||
$ibo-title--icon-background--size--must-cover: cover !default;
|
$ibo-title--icon-background--size--must-cover: cover !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-cover
|
||||||
$ibo-title--icon-background--size--must-zoomout: 66.67% !default;
|
$ibo-title--icon-background--size--must-zoomout: 66.67% !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-zoomout
|
||||||
|
$ibo-title--icon-img--size--must-contain: $ibo-title--icon-background--size--must-contain !default; // TODO remove when dealing with N°9317
|
||||||
|
$ibo-title--icon-img--size--must-cover: $ibo-title--icon-background--size--must-cover !default; // TODO remove when dealing with N°9317
|
||||||
|
$ibo-title--icon-img--size--must-zoomout: $ibo-title--icon-background--size--must-zoomout !default; // TODO remove when dealing with N°9317
|
||||||
|
|
||||||
|
|
||||||
.ibo-title {
|
.ibo-title {
|
||||||
@@ -44,24 +47,23 @@ $ibo-title--icon-background--size--must-zoomout: 66.67% !default;
|
|||||||
min-height: $ibo-title--icon--size-3;
|
min-height: $ibo-title--icon--size-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-title--icon-background {
|
.ibo-title--icon-img, .ibo-title--icon-background { // second class is deprecated, remove it when dealing with N°9317
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-position: center;
|
object-position: center;
|
||||||
background-repeat: no-repeat;
|
background-size: $ibo-title--icon-img--size--must-contain;
|
||||||
background-size: $ibo-title--icon-background--size--must-contain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-title--icon-background--must-contain {
|
.ibo-title--icon-img--must-contain, .ibo-title--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-title--icon-background--size--must-contain;
|
background-size: $ibo-title--icon-img--size--must-contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-title--icon-background--must-cover {
|
.ibo-title--icon-img--must-cover, .ibo-title--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-title--icon-background--size--must-cover;
|
background-size: $ibo-title--icon-img--size--must-cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-title--icon-background--must-zoomout {
|
.ibo-title--icon-img--must-zoomout, .ibo-title--icon-background--must-zoomout { // second class is deprecated, remove it when dealing with N°9317
|
||||||
background-size: $ibo-title--icon-background--size--must-zoomout;
|
background-size: $ibo-title--icon-img--size--must-zoomout;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-title--for-object-details {
|
.ibo-title--for-object-details {
|
||||||
|
|||||||
@@ -19,10 +19,7 @@ $ibo-dashlet-blocker--height: 100% !default;
|
|||||||
.ibo-dashlet {
|
.ibo-dashlet {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: calc(#{$ibo-dashlet--width} - #{$ibo-dashlet--elements-spacing-x});
|
width: calc(#{$ibo-dashlet--width} - #{$ibo-dashlet--elements-spacing-x});
|
||||||
//margin: calc(#{$ibo-dashlet--elements-spacing-y} / 2) calc(#{$ibo-dashlet--elements-spacing-x} / 2);
|
margin: calc(#{$ibo-dashlet--elements-spacing-y} / 2) calc(#{$ibo-dashlet--elements-spacing-x} / 2);
|
||||||
|
|
||||||
height: 100% !important;
|
|
||||||
width: 100% !important;
|
|
||||||
|
|
||||||
&.dashlet-selected {
|
&.dashlet-selected {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -42,20 +39,3 @@ $ibo-dashlet-blocker--height: 100% !default;
|
|||||||
height: $ibo-dashlet-blocker--height;
|
height: $ibo-dashlet-blocker--height;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ibo-dashlet--actions {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1000;
|
|
||||||
top: 0px;
|
|
||||||
right: 0px;
|
|
||||||
display: none;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
background-color: $ibo-color-white-100;
|
|
||||||
@extend %ibo-elevation-100;
|
|
||||||
}
|
|
||||||
|
|
||||||
ibo-dashlet[data-edit-mode="edit"] {
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
@@ -54,31 +54,3 @@ $ibo-input-select-icon--menu--icon--margin-right: 10px !default;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ts-control > .ibo-input-select-icon--menu--item{
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
column-gap: 5px;
|
|
||||||
align-items: center;
|
|
||||||
padding: 5px 0;
|
|
||||||
|
|
||||||
> img{
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover{
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.ts-dropdown > .ts-dropdown-content > .ibo-input-select-icon--menu--item{
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
column-gap: 5px;
|
|
||||||
|
|
||||||
> img{
|
|
||||||
width: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,4 +15,3 @@
|
|||||||
@import "wizard-container/wizard-container";
|
@import "wizard-container/wizard-container";
|
||||||
@import "object/all";
|
@import "object/all";
|
||||||
@import "activity-panel/all";
|
@import "activity-panel/all";
|
||||||
@import "dashlet-panel/all";
|
|
||||||
|
|||||||
@@ -175,73 +175,3 @@ input:checked + .ibo-dashboard--slider:before {
|
|||||||
input:checked + .ibo-dashboard--slider:after {
|
input:checked + .ibo-dashboard--slider:after {
|
||||||
content: $ibo-dashboard--slider--before--content;
|
content: $ibo-dashboard--slider--before--content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 3.3 Cleanup variables
|
|
||||||
// TODO 3.3 Move to vendor what's from gridstack
|
|
||||||
|
|
||||||
|
|
||||||
.grid-stack {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard[data-edit-mode="edit"] .grid-stack{
|
|
||||||
background-size: calc(100% / 12) var(--gs-cell-height);
|
|
||||||
background-color: $ibo-color-white-100;
|
|
||||||
background-image: linear-gradient(to right, $ibo-color-white-200 8px, transparent 8px), linear-gradient(to bottom, $ibo-color-white-200 8px, transparent 8px);
|
|
||||||
--gs-item-margin-top: 8px;
|
|
||||||
--gs-item-margin-bottom: 0;
|
|
||||||
--gs-item-margin-right: 0;
|
|
||||||
--gs-item-margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ibo-dashboard[data-edit-mode="view"] {
|
|
||||||
.ibo-dashboard--form {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard--form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
height: 55px;
|
|
||||||
background-color: $ibo-color-blue-200;
|
|
||||||
margin: -16px -36px 24px -36px;
|
|
||||||
padding: 0 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard--form--inputs {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
|
|
||||||
@extend %common-font-ral-med-250;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard[data-edit-mode="edit"] ibo-dashlet:not([data-edit-mode="edit"]):hover .ibo-dashlet--actions {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard[data-edit-mode="error"] .grid-stack{
|
|
||||||
background-image: url($approot-relative + '/images/alpha-fatal-error.gif');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Our edit mode dashboard already has its own header, so we hide the standard one
|
|
||||||
#ibo-page-header:has(+ ibo-dashboard[data-edit-mode="edit"]) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashboard[data-edit-mode="edit"] .ibo-dashboard--grid:has(ibo-dashboard-grid-slot > ibo-dashlet[data-edit-mode="edit"]) .ibo-dashboard--grid--backdrop {
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
height: calc(100% + 24px);
|
|
||||||
// 36px is $ibo-page-container--elements-padding-x, handle variable resolution
|
|
||||||
width: calc(100% + 36px + 36px);
|
|
||||||
margin: -24px -#{36px} 0 -#{36px};
|
|
||||||
background-color: $ibo-color-grey-400;
|
|
||||||
z-index: 2;
|
|
||||||
opacity: 60%;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
@import "dashlet-entry";
|
|
||||||
@import "dashlet-panel";
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
// TODO 3.3 Cleanup variables
|
|
||||||
|
|
||||||
.ibo-dashlet-entry {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
|
|
||||||
border: 1px solid $ibo-color-grey-300;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 12px;
|
|
||||||
background-color: $ibo-color-grey-100;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $ibo-color-grey-200;
|
|
||||||
border-color: $ibo-color-grey-400;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: $ibo-color-grey-50;
|
|
||||||
border-color: $ibo-color-grey-500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-entry--icon {
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 36px;
|
|
||||||
width: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-entry--content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
overflow-x: hidden;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-entry--title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: $ibo-color-grey-900;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-entry--description {
|
|
||||||
font-size: 12px;
|
|
||||||
color: $ibo-color-grey-700;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// TODO 3.3 Cleanup variables
|
|
||||||
|
|
||||||
.ibo-dashlet-panel {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 326px;
|
|
||||||
background-color: $ibo-color-white-100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-panel--title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
height: 55px;
|
|
||||||
background-color: $ibo-color-white-200;
|
|
||||||
padding: 0 16px;
|
|
||||||
flex-grow: 0;
|
|
||||||
@extend %common-font-ral-med-300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-panel--entries, .ibo-dashlet-panel--form-container {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
padding: 16px;
|
|
||||||
gap: 12px;
|
|
||||||
&.ibo-is-hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-center-container:has(ibo-dashboard[data-edit-mode="view"]) .ibo-dashlet-panel{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-panel--form-container turbo-frame {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.ibo-dashlet-panel--form-container .ibo-form {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
> .form {
|
|
||||||
overflow: auto;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ibo-dashlet-panel--form-container--buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row !important;
|
|
||||||
justify-content: end;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
margin: 0 -16px -16px -16px;
|
|
||||||
padding: 0 16px;
|
|
||||||
min-height: 60px;
|
|
||||||
|
|
||||||
background-color: $ibo-color-grey-50;
|
|
||||||
border-top: solid 1px $ibo-color-grey-400;
|
|
||||||
}
|
|
||||||
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
$ibo-multi-column--margin-x: -$ibo-spacing-500 !default; /* This is to compensate columns padding and make the whole multicolumn align with the parent borders (cf. Bootstrap rows / cols) */
|
$ibo-multi-column--margin-x: -$ibo-spacing-500 !default; /* This is to compensate columns padding and make the whole multicolumn align with the parent borders (cf. Bootstrap rows / cols) */
|
||||||
$ibo-multi-column--margin-y: $ibo-spacing-0 !default;
|
$ibo-multi-column--margin-y: $ibo-spacing-0 !default;
|
||||||
|
$ibo-multi-column--row-gap: $ibo-spacing-800 !default;
|
||||||
|
|
||||||
.ibo-multi-column {
|
.ibo-multi-column {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin: $ibo-multi-column--margin-y $ibo-multi-column--margin-x;
|
margin: $ibo-multi-column--margin-y $ibo-multi-column--margin-x;
|
||||||
|
row-gap: $ibo-multi-column--row-gap;
|
||||||
}
|
}
|
||||||
2
css/backoffice/vendors/_selectize.scss
vendored
2
css/backoffice/vendors/_selectize.scss
vendored
@@ -29,7 +29,7 @@ $ibo-vendors-selectize--element--active--background: $ibo-color-blue-100 !defaul
|
|||||||
$ibo-vendors-selectize--element--active--color: $ibo-color-grey-900 !default;
|
$ibo-vendors-selectize--element--active--color: $ibo-color-grey-900 !default;
|
||||||
|
|
||||||
$ibo-vendors-selectize--dropdown--background-color: $ibo-vendors-selectize-input--background-color !default;
|
$ibo-vendors-selectize--dropdown--background-color: $ibo-vendors-selectize-input--background-color !default;
|
||||||
$ibo-vendors-selectize--dropdown--color: $ibo-vendors-selectize-input--color!default;
|
$ibo-vendors-selectize--dropdown--color: $ibo-vendors-selectize-input--color !default;
|
||||||
|
|
||||||
$ibo-vendors-selectize--header--padding-x: 8px !default;
|
$ibo-vendors-selectize--header--padding-x: 8px !default;
|
||||||
$ibo-vendors-selectize--header--padding-y: 5px !default;
|
$ibo-vendors-selectize--header--padding-y: 5px !default;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||||
<module_parameters>
|
<module_parameters>
|
||||||
<parameters id="authent-local" _delta="define">
|
<parameters id="authent-local" _delta="define">
|
||||||
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$</password_validation.pattern>
|
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{12,}$</password_validation.pattern>
|
||||||
<password_validation.message type="hash"/>
|
<password_validation.message type="hash"/>
|
||||||
</parameters>
|
</parameters>
|
||||||
</module_parameters>
|
</module_parameters>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Heslo nemůže uživatel změnit.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Heslo nemůže uživatel změnit.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Heslo bylo obnoveno',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Heslo bylo obnoveno',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Termín, kdy bylo heslo změneno',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Termín, kdy bylo heslo změneno',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Heslo musí obsahovat minimálně 8 znaků a musí obsahovat minimálně jedno velké písmeno, jedno malé písmeno, jedno číslo a speciální znak.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Heslo musí obsahovat minimálně 12 znaků a musí obsahovat minimálně jedno velké písmeno, jedno malé písmeno, jedno číslo a speciální znak.',
|
||||||
'UserLocal:password:expiration' => 'Níže uvedená pole vyžadují rozšíření',
|
'UserLocal:password:expiration' => 'Níže uvedená pole vyžadují rozšíření',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Nastavení exspirace "Jednorázového hesla" nelze u vlastního účtu uživatele.',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Nastavení exspirace "Jednorázového hesla" nelze u vlastního účtu uživatele.',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
'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.~~',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Letzte Passworterneuerung',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Letzte Passworterneuerung',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Letztes Änderungsdatum',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Letztes Änderungsdatum',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort entspricht nicht dem in den Konfigurationsregeln hinterlegten RegEx-Ausdruck',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort muss mindestens 12 Zeichen lang sein und Großbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten.',
|
||||||
'UserLocal:password:expiration' => 'Die folgenden Felder benötigen eine '.ITOP_APPLICATION_SHORT.' Erweiterung',
|
'UserLocal:password:expiration' => 'Die folgenden Felder benötigen eine '.ITOP_APPLICATION_SHORT.' Erweiterung',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Das setzen des Passwortablaufs auf "Einmalpasswort" ist für den eigenen Benutzer nicht erlaubt.',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Das setzen des Passwortablaufs auf "Einmalpasswort" ist für den eigenen Benutzer nicht erlaubt.',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Dict::Add('EN US', 'English', 'English', [
|
|||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed',
|
'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.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
|||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed',
|
'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.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'El usuario no puede cambiar la contraseña.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'El usuario no puede cambiar la contraseña.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Renovación de contraseña',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Renovación de contraseña',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Cuando fue el último cambio de contraseña',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Cuando fue el último cambio de contraseña',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La contraseña debe ser de al menos 8 caracteres e incluír mayúsculas, minúsculas, números y caracteres especiales.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La contraseña debe ser de al menos 12 caracteres e incluir mayúsculas, minúsculas, números y caracteres especiales.',
|
||||||
'UserLocal:password:expiration' => 'El siguiente campo requiere una extensión',
|
'UserLocal:password:expiration' => 'El siguiente campo requiere una extensión',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Configurar expiración de contraseña para "ontraseña de un solo uso" no está permitido para su propio Usuario',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Configurar expiración de contraseña para "ontraseña de un solo uso" no está permitido para su propio Usuario',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Mot de passe changé le',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Mot de passe changé le',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Dernière date à laquelle le mot de passe a été changé',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Dernière date à laquelle le mot de passe a été changé',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Le mot de passe doit contenir au moins 8 caractères, avec minuscule, majuscule, nombre et caractère spécial.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Le mot de passe doit contenir au moins 12 caractères, avec minuscule, majuscule, nombre et caractère spécial.',
|
||||||
'UserLocal:password:expiration' => 'Les champs ci-dessous nécessitent une extension',
|
'UserLocal:password:expiration' => 'Les champs ci-dessous nécessitent une extension',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impossible de mettre "Usage unique" comme validité du mot de passe pour son propre utilisateur.',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impossible de mettre "Usage unique" comme validité du mot de passe pour son propre utilisateur.',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'A felhasználó nem változtathat jelszót.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'A felhasználó nem változtathat jelszót.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Jelszó megújítás ideje',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Jelszó megújítás ideje',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'A jelszó legutóbbi módosításának időpontja',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'A jelszó legutóbbi módosításának időpontja',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'A jelszónak legalább 8 karakterből kell állnia, és tartalmaznia kell nagybetűket, kisbetűket, numerikus és speciális karaktereket.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'A jelszónak legalább 12 karakterből kell állnia, és tartalmaznia kell nagybetűket, kisbetűket, numerikus és speciális karaktereket.',
|
||||||
'UserLocal:password:expiration' => 'Az alábbi mezőkhöz egy bővítmény szükséges',
|
'UserLocal:password:expiration' => 'Az alábbi mezőkhöz egy bővítmény szükséges',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'A jelszó lejárati idejének beállítása "Egyszeri jelszóra" nem engedélyezett a saját Felhasználó számára.',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'A jelszó lejárati idejének beállítása "Egyszeri jelszóra" nem engedélyezett a saját Felhasználó számára.',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'La password non può essere cambiata dall\'utente.',
|
'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' => 'Rinnovo della password',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Quando è stata cambiata l\'ultima volta la 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.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'La password deve essere di almeno 12 caratteri e includere lettere maiuscole, minuscole, numeri e caratteri speciali.',
|
||||||
'UserLocal:password:expiration' => 'I campi sottostanti richiedono un\'estensione',
|
'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',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Impostare la scadenza della password su "Password monouso" non è consentito per il proprio utente',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
'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.~~',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'De gebruiker kan dit wachtwoord niet veranderen.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'De gebruiker kan dit wachtwoord niet veranderen.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Wachtwoord laatst aangepast',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Wachtwoord laatst aangepast',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Tijdstip waarop het wachtwoord het laatst aangepast werd.',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Tijdstip waarop het wachtwoord het laatst aangepast werd.',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Het wachtwoord bestaat uit minstens 8 tekens en bestaat uit een mix van minstens 1 hoofdletter, kleine letter, cijfer en speciaal teken.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Het wachtwoord bestaat uit minstens 12 tekens en bestaat uit een mix van minstens 1 hoofdletter, kleine letter, cijfer en speciaal teken.',
|
||||||
'UserLocal:password:expiration' => 'De velden hieronder vereisen een extensie.',
|
'UserLocal:password:expiration' => 'De velden hieronder vereisen een extensie.',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Je kan geen eenmalig wachtwoord instellen voor je eigen gebruiker.',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Je kan geen eenmalig wachtwoord instellen voor je eigen gebruiker.',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Hasło nie może być zmienione przez użytkownika.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Hasło nie może być zmienione przez użytkownika.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Odnowienie hasła',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Odnowienie hasła',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Kiedy ostatnio zmieniano hasło',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Kiedy ostatnio zmieniano hasło',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Hasło musi mieć co najmniej 8 znaków i zawierać duże, małe litery, cyfry i znaki specjalne.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Hasło musi mieć co najmniej 12 znaków i zawierać duże, małe litery, cyfry i znaki specjalne.',
|
||||||
'UserLocal:password:expiration' => 'Poniższe pola wymagają rozszerzenia',
|
'UserLocal:password:expiration' => 'Poniższe pola wymagają rozszerzenia',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Ustawienie wygaśnięcia hasła "Hasło jednorazowe" nie jest dozwolone dla własnego użytkownika',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Ustawienie wygaśnięcia hasła "Hasło jednorazowe" nie jest dozwolone dla własnego użytkownika',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Дата изменения пароля',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Дата изменения пароля',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'Когда пароль был изменен в последний раз',
|
'Class:UserLocal/Attribute:password_renewed_date+' => 'Когда пароль был изменен в последний раз',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Пароль должен содержать не менее 8 символов и включать прописные, строчные, числовые и специальные символы.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Пароль должен содержать не менее 12 символов и включать прописные, строчные, числовые и специальные символы.',
|
||||||
'UserLocal:password:expiration' => 'Поля требуют наличия доп. расширения',
|
'UserLocal:password:expiration' => 'Поля требуют наличия доп. расширения',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
'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.~~',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on~~',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed~~',
|
'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.~~',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 12 characters and include uppercase, lowercase, numeric and special characters.~~',
|
||||||
'UserLocal:password:expiration' => 'The fields below require an extension~~',
|
'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/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
|||||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '用户不允许修改密码.',
|
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '用户不允许修改密码.',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date' => '密码更新',
|
'Class:UserLocal/Attribute:password_renewed_date' => '密码更新',
|
||||||
'Class:UserLocal/Attribute:password_renewed_date+' => '上次修改密码的时间',
|
'Class:UserLocal/Attribute:password_renewed_date+' => '上次修改密码的时间',
|
||||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => '密码必须至少8个字符, 包含大小写, 数字和特殊字符.',
|
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => '密码必须至少12个字符, 包含大小写, 数字和特殊字符.',
|
||||||
'UserLocal:password:expiration' => '下面的区域需要插件扩展',
|
'UserLocal:password:expiration' => '下面的区域需要插件扩展',
|
||||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => '不允许用户为自己设置 "一次性密码" 的失效期限',
|
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => '不允许用户为自己设置 "一次性密码" 的失效期限',
|
||||||
]);
|
]);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -68,47 +68,47 @@ $ibo-color-information-900: #0f172a !default;
|
|||||||
$ibo-color-information-950: #020617 !default;
|
$ibo-color-information-950: #020617 !default;
|
||||||
|
|
||||||
|
|
||||||
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600;
|
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600 !default;
|
||||||
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600;
|
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600 !default;
|
||||||
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-yellow-700;
|
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-yellow-700 !default;
|
||||||
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700;
|
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700 !default;
|
||||||
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-failure-state-primary-color: $ibo-color-orange-800;
|
$ibo-lifecycle-failure-state-primary-color: $ibo-color-orange-800 !default;
|
||||||
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200;
|
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200 !default;
|
||||||
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700;
|
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700 !default;
|
||||||
|
|
||||||
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700;
|
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700 !default;
|
||||||
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-yellow-700;
|
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-yellow-700 !default;
|
||||||
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
|
|
||||||
$ibo-caselog-highlight-color-1: $ibo-color-blue-700;
|
$ibo-caselog-highlight-color-1: $ibo-color-blue-700 !default;
|
||||||
$ibo-caselog-highlight-color-2: $ibo-color-yellow-700;
|
$ibo-caselog-highlight-color-2: $ibo-color-yellow-700 !default;
|
||||||
$ibo-caselog-highlight-color-3: $ibo-color-information-600;
|
$ibo-caselog-highlight-color-3: $ibo-color-information-600 !default;
|
||||||
$ibo-caselog-highlight-color-4: $ibo-color-yellow-500;
|
$ibo-caselog-highlight-color-4: $ibo-color-yellow-500 !default;
|
||||||
$ibo-caselog-highlight-color-5: $ibo-color-blue-500;
|
$ibo-caselog-highlight-color-5: $ibo-color-blue-500 !default;
|
||||||
$ibo-caselog-highlight-color-6: $ibo-color-yellow-300;
|
$ibo-caselog-highlight-color-6: $ibo-color-yellow-300 !default;
|
||||||
$ibo-caselog-highlight-color-7: $ibo-color-blue-300;
|
$ibo-caselog-highlight-color-7: $ibo-color-blue-300 !default;
|
||||||
|
|
||||||
$ibo-input-wrapper--is-error--border-color: $ibo-color-warning-700;
|
$ibo-input-wrapper--is-error--border-color: $ibo-color-warning-700 !default;
|
||||||
$ibo-field-validation: $ibo-color-warning-800;
|
$ibo-field-validation: $ibo-color-warning-800 !default;
|
||||||
|
|
||||||
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-blue-400;
|
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-blue-400 !default;
|
||||||
|
|
||||||
$ibo-wizard-container--background-color: $ibo-color-information-200;
|
$ibo-wizard-container--background-color: $ibo-color-information-200 !default;
|
||||||
$ibo-wizard-container--border-color: $ibo-color-information-600;
|
$ibo-wizard-container--border-color: $ibo-color-information-600 !default;
|
||||||
|
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-danger-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-danger-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-danger-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-danger-500 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-500 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500 !default;
|
||||||
|
|
||||||
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-blue-600;
|
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-blue-600 !default;
|
||||||
@@ -32,47 +32,47 @@ $ibo-color-information-900: #0f172a !default;
|
|||||||
$ibo-color-information-950: #020617 !default;
|
$ibo-color-information-950: #020617 !default;
|
||||||
|
|
||||||
|
|
||||||
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600;
|
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600 !default;
|
||||||
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600;
|
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600 !default;
|
||||||
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-red-200;
|
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-red-200 !default;
|
||||||
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-red-800;
|
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-red-800 !default;
|
||||||
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700;
|
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700 !default;
|
||||||
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-failure-state-primary-color: $ibo-color-red-800;
|
$ibo-lifecycle-failure-state-primary-color: $ibo-color-red-800 !default;
|
||||||
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200;
|
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200 !default;
|
||||||
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700;
|
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700 !default;
|
||||||
|
|
||||||
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700;
|
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700 !default;
|
||||||
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-red-700;
|
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-red-700 !default;
|
||||||
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100;
|
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100 !default;
|
||||||
|
|
||||||
$ibo-caselog-highlight-color-1: $ibo-color-blue-700;
|
$ibo-caselog-highlight-color-1: $ibo-color-blue-700 !default;
|
||||||
$ibo-caselog-highlight-color-2: $ibo-color-red-700;
|
$ibo-caselog-highlight-color-2: $ibo-color-red-700 !default;
|
||||||
$ibo-caselog-highlight-color-3: $ibo-color-information-600;
|
$ibo-caselog-highlight-color-3: $ibo-color-information-600 !default;
|
||||||
$ibo-caselog-highlight-color-4: $ibo-color-red-500;
|
$ibo-caselog-highlight-color-4: $ibo-color-red-500 !default;
|
||||||
$ibo-caselog-highlight-color-5: $ibo-color-blue-500;
|
$ibo-caselog-highlight-color-5: $ibo-color-blue-500 !default;
|
||||||
$ibo-caselog-highlight-color-6: $ibo-color-red-300;
|
$ibo-caselog-highlight-color-6: $ibo-color-red-300 !default;
|
||||||
$ibo-caselog-highlight-color-7: $ibo-color-blue-300;
|
$ibo-caselog-highlight-color-7: $ibo-color-blue-300 !default;
|
||||||
|
|
||||||
$ibo-input-wrapper--is-error--border-color: $ibo-color-pink-700;
|
$ibo-input-wrapper--is-error--border-color: $ibo-color-pink-700 !default;
|
||||||
$ibo-field-validation: $ibo-color-pink-800;
|
$ibo-field-validation: $ibo-color-pink-800 !default;
|
||||||
|
|
||||||
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-pink-600;
|
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-pink-600 !default;
|
||||||
|
|
||||||
$ibo-wizard-container--background-color: $ibo-color-information-200;
|
$ibo-wizard-container--background-color: $ibo-color-information-200 !default;
|
||||||
$ibo-wizard-container--border-color: $ibo-color-information-600;
|
$ibo-wizard-container--border-color: $ibo-color-information-600 !default;
|
||||||
|
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-pink-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-pink-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-pink-600;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-pink-600 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-400;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-400 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100 !default;
|
||||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500;
|
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500 !default;
|
||||||
|
|
||||||
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-pink-500;
|
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-pink-500 !default;
|
||||||
@@ -10,22 +10,87 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Core\MetaModel\HierarchicalKey;
|
use Combodo\iTop\Core\MetaModel\HierarchicalKey;
|
||||||
|
use Combodo\iTop\DBTools\Enum\BinExitCode;
|
||||||
|
use Combodo\iTop\DBTools\Exception\AuthenticationException;
|
||||||
|
|
||||||
require_once('../../../approot.inc.php');
|
// env-xxx folders
|
||||||
|
if (file_exists(__DIR__.'/../../../approot.inc.php')) {
|
||||||
|
require_once __DIR__.'/../../../approot.inc.php';
|
||||||
|
}
|
||||||
|
// datamodel/2.x and data/xxx-modules folders
|
||||||
|
elseif (file_exists(__DIR__.'/../../../../approot.inc.php')) {
|
||||||
|
require_once __DIR__.'/../../../../approot.inc.php';
|
||||||
|
}
|
||||||
require_once APPROOT.'application/startup.inc.php';
|
require_once APPROOT.'application/startup.inc.php';
|
||||||
|
|
||||||
foreach (MetaModel::GetClasses() as $sClass) {
|
// Prepare output page
|
||||||
if (!MetaModel::HasTable($sClass)) {
|
$sPageTitle = "Database maintenance tools - Report";
|
||||||
continue;
|
$bIsModeCLI = utils::IsModeCLI();
|
||||||
}
|
if ($bIsModeCLI) {
|
||||||
|
$oP = new CLIPage($sPageTitle);
|
||||||
|
|
||||||
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
|
SetupUtils::CheckPhpAndExtensionsForCli($oP, BinExitCode::FATAL->value);
|
||||||
// Check (once) all the attributes that are hierarchical keys
|
} else {
|
||||||
if ((MetaModel::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef->IsHierarchicalKey()) {
|
$oP = new WebPage($sPageTitle);
|
||||||
echo "Rebuild hierarchical key $sAttCode from $sClass.\n";
|
|
||||||
HierarchicalKey::Rebuild($sClass, $sAttCode, $oAttDef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Done\n";
|
// Authentication logic
|
||||||
|
try {
|
||||||
|
utils::UseParamFile();
|
||||||
|
|
||||||
|
if ($bIsModeCLI) {
|
||||||
|
$sAuthUser = utils::ReadParam('auth_user', null, true, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||||
|
$sAuthPwd = utils::ReadParam('auth_pwd', null, true, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||||
|
if (utils::IsNullOrEmptyString($sAuthUser) || utils::IsNullOrEmptyString($sAuthPwd)) {
|
||||||
|
throw new AuthenticationException("Access credentials not provided, usage: php rebuildhk.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file_path>]");
|
||||||
|
}
|
||||||
|
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) {
|
||||||
|
UserRights::Login($sAuthUser);
|
||||||
|
} else {
|
||||||
|
throw new AuthenticationException("Access wrong credentials ('$sAuthUser')");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check user rights and prompt if needed
|
||||||
|
LoginWebPage::DoLoginEx(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UserRights::IsAdministrator()) {
|
||||||
|
throw new AuthenticationException("Access restricted to administrators");
|
||||||
|
}
|
||||||
|
} catch (AuthenticationException $oException) {
|
||||||
|
$oP->p($oException->getMessage());
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::ERROR->value);
|
||||||
|
} catch (Exception $oException) {
|
||||||
|
$oP->p("Error: ".$oException->GetMessage());
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::FATAL->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Business logic
|
||||||
|
try {
|
||||||
|
foreach (MetaModel::GetClasses() as $sClass) {
|
||||||
|
if (!MetaModel::HasTable($sClass)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
|
||||||
|
// Check (once) all the attributes that are hierarchical keys
|
||||||
|
if ((MetaModel::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef->IsHierarchicalKey()) {
|
||||||
|
$oP->p("Rebuild hierarchical key $sAttCode from $sClass.");
|
||||||
|
HierarchicalKey::Rebuild($sClass, $sAttCode, $oAttDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$oP->p("Done");
|
||||||
|
$oP->output();
|
||||||
|
} catch (AuthenticationException $oException) {
|
||||||
|
$oP->p($oException->getMessage());
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::ERROR->value);
|
||||||
|
} catch (Exception $oException) {
|
||||||
|
$oP->p("Error: ".$oException->GetMessage());
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::FATAL->value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,22 +5,93 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\DBTools\Enum\BinExitCode;
|
||||||
|
use Combodo\iTop\DBTools\Exception\AuthenticationException;
|
||||||
use Combodo\iTop\DBTools\Service\DBAnalyzerUtils;
|
use Combodo\iTop\DBTools\Service\DBAnalyzerUtils;
|
||||||
|
|
||||||
require_once('../../../approot.inc.php');
|
// env-xxx folders
|
||||||
require_once(APPROOT.'application/startup.inc.php');
|
if (file_exists(__DIR__.'/../../../approot.inc.php')) {
|
||||||
|
require_once __DIR__.'/../../../approot.inc.php';
|
||||||
require_once('../db_analyzer.class.inc.php');
|
}
|
||||||
require_once('../src/Service/DBAnalyzerUtils.php');
|
// datamodel/2.x and data/xxx-modules folders
|
||||||
|
elseif (file_exists(__DIR__.'/../../../../approot.inc.php')) {
|
||||||
$oDBAnalyzer = new DatabaseAnalyzer(0);
|
require_once __DIR__.'/../../../../approot.inc.php';
|
||||||
$aResults = $oDBAnalyzer->CheckIntegrity([]);
|
|
||||||
|
|
||||||
if (empty($aResults)) {
|
|
||||||
echo "Database OK\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sReportFile = DBAnalyzerUtils::GenerateReport($aResults);
|
require_once APPROOT.'application/startup.inc.php';
|
||||||
|
require_once APPROOT.'application/loginwebpage.class.inc.php';
|
||||||
|
|
||||||
echo "Report generated: {$sReportFile}.log\n";
|
require_once __DIR__.'/../db_analyzer.class.inc.php';
|
||||||
|
|
||||||
|
// Prepare output page
|
||||||
|
$sPageTitle = "Database maintenance tools - Report";
|
||||||
|
$bIsModeCLI = utils::IsModeCLI();
|
||||||
|
if ($bIsModeCLI) {
|
||||||
|
$oP = new CLIPage($sPageTitle);
|
||||||
|
|
||||||
|
SetupUtils::CheckPhpAndExtensionsForCli($oP, BinExitCode::FATAL->value);
|
||||||
|
} else {
|
||||||
|
$oP = new WebPage($sPageTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authentication logic
|
||||||
|
try {
|
||||||
|
utils::UseParamFile();
|
||||||
|
|
||||||
|
if ($bIsModeCLI) {
|
||||||
|
$sAuthUser = utils::ReadParam('auth_user', null, true, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||||
|
$sAuthPwd = utils::ReadParam('auth_pwd', null, true, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||||
|
if (utils::IsNullOrEmptyString($sAuthUser) || utils::IsNullOrEmptyString($sAuthPwd)) {
|
||||||
|
throw new AuthenticationException("Access credentials not provided, usage: php report.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file_path>]");
|
||||||
|
}
|
||||||
|
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) {
|
||||||
|
UserRights::Login($sAuthUser);
|
||||||
|
} else {
|
||||||
|
throw new AuthenticationException("Access wrong credentials ('$sAuthUser')");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check user rights and prompt if needed
|
||||||
|
LoginWebPage::DoLoginEx(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UserRights::IsAdministrator()) {
|
||||||
|
throw new AuthenticationException("Access restricted to administrators");
|
||||||
|
}
|
||||||
|
} catch (AuthenticationException $oException) {
|
||||||
|
$sExceptionMessage = $oP instanceof WebPage ? utils::EscapeHtml($oException->getMessage()) : $oException->getMessage();
|
||||||
|
$oP->p($sExceptionMessage);
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::ERROR->value);
|
||||||
|
} catch (Exception $oException) {
|
||||||
|
$sExceptionMessage = $oP instanceof WebPage ? utils::EscapeHtml($oException->getMessage()) : $oException->getMessage();
|
||||||
|
$oP->p("Error: ".$sExceptionMessage);
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::FATAL->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Business logic
|
||||||
|
try {
|
||||||
|
$oDBAnalyzer = new DatabaseAnalyzer(0);
|
||||||
|
$aResults = $oDBAnalyzer->CheckIntegrity([]);
|
||||||
|
|
||||||
|
if (empty($aResults)) {
|
||||||
|
$oP->p("Database OK");
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::SUCCESS->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sReportFile = DBAnalyzerUtils::GenerateReport($aResults);
|
||||||
|
|
||||||
|
$oP->p("Report generated: {$sReportFile}.log");
|
||||||
|
$oP->output();
|
||||||
|
} catch (AuthenticationException $oException) {
|
||||||
|
$sExceptionMessage = $oP instanceof WebPage ? utils::EscapeHtml($oException->getMessage()) : $oException->getMessage();
|
||||||
|
$oP->p($sExceptionMessage);
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::ERROR->value);
|
||||||
|
} catch (Exception $oException) {
|
||||||
|
$sExceptionMessage = $oP instanceof WebPage ? utils::EscapeHtml($oException->getMessage()) : $oException->getMessage();
|
||||||
|
$oP->p("Error: ".$sExceptionMessage);
|
||||||
|
$oP->output();
|
||||||
|
exit(BinExitCode::FATAL->value);
|
||||||
|
}
|
||||||
|
|||||||
9
datamodels/2.x/combodo-db-tools/composer.json
Normal file
9
datamodels/2.x/combodo-db-tools/composer.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "combodo/combodo-db-tools",
|
||||||
|
"license": "AGPL-3.0-only",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Combodo\\iTop\\DBTools\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
datamodels/2.x/combodo-db-tools/composer.lock
generated
Normal file
18
datamodels/2.x/combodo-db-tools/composer.lock
generated
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "38292b9b3a56c6c8776285a17c58034e",
|
||||||
|
"packages": [],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": {},
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": {},
|
||||||
|
"platform-dev": {},
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ SetupWebPage::AddModule(
|
|||||||
// Components
|
// Components
|
||||||
//
|
//
|
||||||
'datamodel' => [
|
'datamodel' => [
|
||||||
|
'vendor/autoload.php',
|
||||||
'src/Service/DBToolsUtils.php',
|
'src/Service/DBToolsUtils.php',
|
||||||
'src/Service/DBAnalyzerUtils.php',
|
'src/Service/DBAnalyzerUtils.php',
|
||||||
],
|
],
|
||||||
|
|||||||
18
datamodels/2.x/combodo-db-tools/src/Enum/BinExitCode.php
Normal file
18
datamodels/2.x/combodo-db-tools/src/Enum/BinExitCode.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Combodo\iTop\DBTools\Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for the exit codes of the bin scripts
|
||||||
|
*/
|
||||||
|
enum BinExitCode: int
|
||||||
|
{
|
||||||
|
case SUCCESS = 0;
|
||||||
|
case ERROR = -1;
|
||||||
|
case FATAL = -2;
|
||||||
|
}
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Combodo\iTop\Application\Dashlet;
|
namespace Combodo\iTop\DBTools\Exception;
|
||||||
|
|
||||||
class DashletException extends \Exception
|
class AuthenticationException extends \Exception
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
22
datamodels/2.x/combodo-db-tools/vendor/autoload.php
vendored
Normal file
22
datamodels/2.x/combodo-db-tools/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException($err);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInit38292b9b3a56c6c8776285a17c58034e::getLoader();
|
||||||
579
datamodels/2.x/combodo-db-tools/vendor/composer/ClassLoader.php
vendored
Normal file
579
datamodels/2.x/combodo-db-tools/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array<string, list<string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* List of PSR-0 prefixes
|
||||||
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, self>
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string> Array of classname => path
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $classMap Class to filename map
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return array<string, self>
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
378
datamodels/2.x/combodo-db-tools/vendor/composer/InstalledVersions.php
vendored
Normal file
378
datamodels/2.x/combodo-db-tools/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $installedIsLocalDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints((string) $constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
|
||||||
|
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||||
|
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||||
|
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||||
|
// all installed packages for example
|
||||||
|
self::$installedIsLocalDir = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
$copiedLocalDir = false;
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
$selfDir = strtr(__DIR__, '\\', '/');
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
$installed[] = $required;
|
||||||
|
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
self::$installed = $required;
|
||||||
|
self::$installedIsLocalDir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
$copiedLocalDir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2025 Alain Dumesny. v0.4.0 and older (c) 2014-2018 Pavel Reznikov, Dylan Weiss
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
furnished to do so, subject to the following conditions:
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
@@ -17,5 +16,6 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
15
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_classmap.php
vendored
Normal file
15
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Combodo\\iTop\\DBTools\\Enum\\BinExitCode' => $baseDir . '/src/Enum/BinExitCode.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Exception\\AuthenticationException' => $baseDir . '/src/Exception/AuthenticationException.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\BinUtils' => $baseDir . '/src/Service/BinUtils.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\DBAnalyzerUtils' => $baseDir . '/src/Service/DBAnalyzerUtils.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\DBToolsUtils' => $baseDir . '/src/Service/DBToolsUtils.php',
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
9
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
10
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_psr4.php
vendored
Normal file
10
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Combodo\\iTop\\DBTools\\' => array($baseDir . '/src'),
|
||||||
|
);
|
||||||
37
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_real.php
vendored
Normal file
37
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInit38292b9b3a56c6c8776285a17c58034e
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInit38292b9b3a56c6c8776285a17c58034e', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInit38292b9b3a56c6c8776285a17c58034e', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInit38292b9b3a56c6c8776285a17c58034e::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->setClassMapAuthoritative(true);
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_static.php
vendored
Normal file
41
datamodels/2.x/combodo-db-tools/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInit38292b9b3a56c6c8776285a17c58034e
|
||||||
|
{
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'C' =>
|
||||||
|
array (
|
||||||
|
'Combodo\\iTop\\DBTools\\' => 21,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'Combodo\\iTop\\DBTools\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/src',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Combodo\\iTop\\DBTools\\Enum\\BinExitCode' => __DIR__ . '/../..' . '/src/Enum/BinExitCode.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Exception\\AuthenticationException' => __DIR__ . '/../..' . '/src/Exception/AuthenticationException.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\BinUtils' => __DIR__ . '/../..' . '/src/Service/BinUtils.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\DBAnalyzerUtils' => __DIR__ . '/../..' . '/src/Service/DBAnalyzerUtils.php',
|
||||||
|
'Combodo\\iTop\\DBTools\\Service\\DBToolsUtils' => __DIR__ . '/../..' . '/src/Service/DBToolsUtils.php',
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInit38292b9b3a56c6c8776285a17c58034e::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInit38292b9b3a56c6c8776285a17c58034e::$prefixDirsPsr4;
|
||||||
|
$loader->classMap = ComposerStaticInit38292b9b3a56c6c8776285a17c58034e::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
datamodels/2.x/combodo-db-tools/vendor/composer/installed.json
vendored
Normal file
5
datamodels/2.x/combodo-db-tools/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"packages": [],
|
||||||
|
"dev": true,
|
||||||
|
"dev-package-names": []
|
||||||
|
}
|
||||||
23
datamodels/2.x/combodo-db-tools/vendor/composer/installed.php
vendored
Normal file
23
datamodels/2.x/combodo-db-tools/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => 'combodo/combodo-db-tools',
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'combodo/combodo-db-tools' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
@@ -71,6 +71,19 @@
|
|||||||
<module>itop-virtualization-mgmt</module>
|
<module>itop-virtualization-mgmt</module>
|
||||||
</modules>
|
</modules>
|
||||||
<default>true</default>
|
<default>true</default>
|
||||||
|
<sub_options>
|
||||||
|
<options type="array">
|
||||||
|
<choice>
|
||||||
|
<extension_code>itop-container-mgmt</extension_code>
|
||||||
|
<title>Containerization</title>
|
||||||
|
<description><![CDATA[Manage Container Images, Applications and Hosts]]></description>
|
||||||
|
<modules type="array">
|
||||||
|
<module>itop-container-mgmt</module>
|
||||||
|
</modules>
|
||||||
|
<default>false</default>
|
||||||
|
</choice>
|
||||||
|
</options>
|
||||||
|
</sub_options>
|
||||||
</choice>
|
</choice>
|
||||||
</options>
|
</options>
|
||||||
</step>
|
</step>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_S
|
|||||||
|
|
||||||
Dict::Add('EN US', 'English', 'English', [
|
Dict::Add('EN US', 'English', 'English', [
|
||||||
'Class:Attachment' => 'Attachment',
|
'Class:Attachment' => 'Attachment',
|
||||||
'Class:Attachment+' => '',
|
'Class:Attachment+' => 'File: text or image, linked to a single object. It can\'t be modified, only deleted. Attachment can\'t be created outside of its object edition.',
|
||||||
'Class:Attachment/Attribute:expire' => 'Expire',
|
'Class:Attachment/Attribute:expire' => 'Expire',
|
||||||
'Class:Attachment/Attribute:expire+' => '',
|
'Class:Attachment/Attribute:expire+' => '',
|
||||||
'Class:Attachment/Attribute:temp_id' => 'Temporary id',
|
'Class:Attachment/Attribute:temp_id' => 'Temporary id',
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user