Compare commits

..

86 Commits

Author SHA1 Message Date
Molkobain
be699b4358 🔖 Increase version number to 3.1.1 2023-11-28 19:56:14 +01:00
Eric Espie
ed12495ec5 N°6228 - Fix Unit tests due to logs added in CRUD 2023-11-28 15:16:48 +01:00
Stephen Abello
d79bbca8ce N°6874 - Make unit test more robust 2023-11-28 11:27:19 +01:00
Eric Espie
ad8922861b N°6531 - Fix refactor 2023-11-27 14:49:27 +01:00
odain
57671f336c N°6901 - Enable tracking of iTop active sessions (monitoring) 2023-11-27 12:34:19 +01:00
Stephen Abello
fdf48b8338 N°6874 - Add unit test 2023-11-27 12:15:07 +01:00
Stephen Abello
f0ea97850b Fix LogFile type emails 2023-11-27 12:14:33 +01:00
Stephen Abello
9b1cdd3581 N°6874 - Fix encoding issue in out-going emails 2023-11-27 10:37:13 +01:00
Molkobain
2d96cf34d4 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.css
2023-11-24 17:25:11 +01:00
Molkobain
bed1db9c51 N°938 - Update compiled portal stylesheet in minified version 2023-11-24 17:07:02 +01:00
Molkobain
7e3e8e43a8 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.css
#	datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig
2023-11-24 16:45:04 +01:00
Molkobain
7b59df216b N°7005 - Fix portal stylesheets not being re-compiled when outdated
Stylesheets should remain as a relative path in the portal configuration, only when consumed by the TWIG should they become URLs

Note that if not absolute, URLs will be append to ITOP/pages/
2023-11-24 16:40:58 +01:00
Molkobain
cb5eab812e N°938 - Update compiled portal stylesheet 2023-11-24 16:22:36 +01:00
Anne-Cath
675affb7f2 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.scss
2023-11-24 15:21:39 +01:00
Anne-Cath
484a0bb6b6 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2023-11-24 15:19:05 +01:00
Anne-Catherine
c9b73a7fe2 N°938 - Improve print of portal object page and portal dashboard page (#537)
N°938 - Improve print of portal object page and portal dashboard page
2023-11-24 15:17:42 +01:00
Pierre Goiffon
9266458cba Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-23 15:55:33 +01:00
Pierre Goiffon
6f1de11c59 N°6976 Fix DeprecatedCallsLog error handler never set (#576)
Caused by N°6274 (disabling error handler when running phpunit)
There is now a test testing the handler is really fixed when not in the phpunit context
Also a TRACE log is made on setting the handler
2023-11-23 15:54:10 +01:00
Molkobain
a18f50615a Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#    pages/exec.php
2023-11-23 15:07:11 +01:00
Molkobain
e02b6ee14a Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2023-11-23 14:25:16 +01:00
Anne-Catherine
0d388cb3e7 N°3465 - Fix attachment file name hardcoded to "uploaded-file" when imported from CSV import (#533)
N°3465 - Fix attachment file name hardcoded to "uploaded-file" when imported from CSV import
2023-11-23 14:15:59 +01:00
Anne-Catherine
5283df5ae9 N°3767 - Impact analysis: Display filtering box on CIs list and groups (#473)
N°3767 - Impact analysis: Display filtering box on CIs list and groups
2023-11-23 14:06:10 +01:00
Eric Espie
8e0d6d1f00 N°6228 - Refactor after review 2023-11-23 11:14:37 +01:00
Eric Espie
f72d8f4955 N°6531 - Trigger on Update on n-n fields not working when object updated in pop-up 2023-11-23 11:14:37 +01:00
Pierre Goiffon
ea845dc6eb N°6228 - CheckToWrite() propagation to target objects based on with_php_constraint property 2023-11-23 11:14:37 +01:00
Molkobain
3b2da39469 N°6989 - Security hardening 2023-11-22 18:02:50 +01:00
odain-cbd
9a59bc7890 N°6901 - Enable tracking of iTop active sessions (monitoring) (#568)
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
Co-authored-by: Romain Quetiez <romain.quetiez@combodo.com>
2023-11-22 17:46:00 +01:00
odain
88008b3925 Merge branch 'support/3.0' into support/3.1 2023-11-22 12:31:02 +01:00
odain
8484bee269 N°6949 - Run subset of itop core unit tests after the setup when validating a module github code 2023-11-22 11:16:03 +01:00
odain
c5b43f3157 Merge branch 'support/2.7' into support/3.0 2023-11-22 11:10:06 +01:00
odain
fc22d91232 N°6949 - Run subset of itop core unit tests after the setup when validating a module github code 2023-11-22 10:14:58 +01:00
Pierre Goiffon
cfe73699cf N°6967 Deprecate DBDeleteTracked_Internal methods 2023-11-21 18:05:29 +01:00
Pierre Goiffon
fa830bdd7f N°6966 Deprecate DBCloneTracked and DBCloneTracked_Internal methods 2023-11-21 18:04:05 +01:00
Pierre Goiffon
2c1df77f4d Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-21 11:01:31 +01:00
Pierre Goiffon
3068a6a360 N°6951 Fix autoloader 2023-11-21 11:01:16 +01:00
Stephen Abello
47e7c35c2b Merge branch 'support/3.0' into support/3.1
# Conflicts:
#	dictionaries/cs.dictionary.itop.core.php
#	dictionaries/da.dictionary.itop.core.php
#	dictionaries/de.dictionary.itop.core.php
#	dictionaries/es_cr.dictionary.itop.core.php
#	dictionaries/hu.dictionary.itop.core.php
#	dictionaries/it.dictionary.itop.core.php
#	dictionaries/ja.dictionary.itop.core.php
#	dictionaries/nl.dictionary.itop.core.php
#	dictionaries/pl.dictionary.itop.core.php
#	dictionaries/pt_br.dictionary.itop.core.php
#	dictionaries/ru.dictionary.itop.core.php
#	dictionaries/sk.dictionary.itop.core.php
#	dictionaries/tr.dictionary.itop.core.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
#	sources/Application/Helper/ExportHelper.php
2023-11-21 10:24:29 +01:00
Stephen Abello
083a0b79bf N°6951 - Security hardening 2023-11-21 10:08:46 +01:00
Stephen Abello
e22220b4fe Merge branch 'support/2.7' into support/3.0
# Conflicts:
#	core/csvbulkexport.class.inc.php
#	core/excelbulkexport.class.inc.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_files.php
#	lib/composer/autoload_real.php
#	lib/composer/autoload_static.php
2023-11-21 09:47:14 +01:00
Stephen Abello
b10bcb976d N°6951 - Security hardening 2023-11-21 09:42:11 +01:00
Pierre Goiffon
a2181b3478 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-21 09:25:21 +01:00
Pierre Goiffon
154a20b757 💡 Fix ItopCustomDatamodelTestCase since phpdoc
See https://docs.phpdoc.org/guide/references/phpdoc/tags/since.html#since
2023-11-21 09:21:30 +01:00
Pierre Goiffon
79c24dfc96 N°6975 Fix ItopCustomDatamodelTestCase removing symlinks flag (#574) 2023-11-21 09:20:11 +01:00
Molkobain
403c369ea0 N°6963 - Update comment 2023-11-20 09:20:09 +01:00
Molkobain
d5875047fa N°6963 - Update PHP min version prerequisite (8.1) for next iTop version (3.2.0) 2023-11-17 10:25:22 +01:00
Molkobain
6955f74c97 N°5281 - Fix methods name case 2023-11-17 08:48:51 +01:00
Molkobain
6bf9ce3237 Merge remote-tracking branch 'origin/release/designer-lot-3' into support/3.1 2023-11-16 16:33:17 +01:00
Molkobain
5726f9f81a N°6960 - Fix \MFDocument::GetNodes() adding a predicate on last expression only instead of the whole XPath 2023-11-16 16:31:47 +01:00
Pierre Goiffon
be93b41363 N°6458 Fix failing tests due to ItopDataTestCase modifications 2023-11-16 15:43:11 +01:00
Pierre Goiffon
d33d82bcd8 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-16 15:35:52 +01:00
Pierre Goiffon
b9d960e89e N°6458 Fix ItopDataTestCase::$bIsUsingSilo visibility 2023-11-16 15:35:04 +01:00
Pierre Goiffon
8540ec644a N°6458 Improve ItopDataTestCase tests speed
What was measured :
- 1'54 with previous code (always doing a reset in tearDown)
- 1'44 without any ResetMetaModelQueyCacheGetObject call (but 3 tests are failing)
- 1'44 with new optin mechanism + don't call Logoff if no current user logged
2023-11-16 15:23:18 +01:00
Pierre Goiffon
5b19593ede 📝 README tests : add prerequisites 2023-11-16 14:38:15 +01:00
Pierre Goiffon
57b70e48bd Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-16 12:02:20 +01:00
Pierre Goiffon
0915081f50 ItopDataTestCase fix cached SQL queries with silo 2023-11-16 11:57:29 +01:00
Pierre Goiffon
7798df0d53 Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php
2023-11-16 11:29:31 +01:00
Pierre Goiffon
a23d629e31 ItopDataTestCase fix using non existing EventService (added in 3.1.0) 2023-11-16 11:23:07 +01:00
Pierre Goiffon
47ccd7589f Fix TriggerTest relying on hardcoded admin user id 2023-11-16 11:16:59 +01:00
Pierre Goiffon
7521fc3006 N°6458 Tests : remove processIsolation
Was caused by cached User instances in UserRights + same login for each created User objects instances
2023-11-16 10:56:47 +01:00
Pierre Goiffon
8f61c02cbe N°6458 Fix portal errors 2023-11-16 09:23:19 +01:00
Pierre Goiffon
e3e8b25cfc Merge remote-tracking branch 'origin/support/3.0' into support/3.1
# Conflicts:
#	core/dbobject.class.php
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
#	lib/composer/autoload_files.php
#	lib/composer/autoload_real.php
#	lib/composer/autoload_static.php
#	pages/UI.php
#	tests/php-unit-tests/unitary-tests/core/DBObjectTest.php
2023-11-15 15:31:56 +01:00
Pierre Goiffon
c955fe00b7 Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts:
#	application/cmdbabstract.class.inc.php
#	application/utils.inc.php
#	core/coreexception.class.inc.php
#	core/userrights.class.inc.php
#	datamodels/2.x/itop-portal-base/portal/src/Form/ObjectFormManager.php
#	tests/php-unit-tests/README.md
#	tests/php-unit-tests/unitary-tests/core/DBObjectTest.php
2023-11-15 15:03:04 +01:00
Pierre Goiffon
5a43448644 N°6458 Security hardening 2023-11-15 11:14:07 +01:00
Pierre Goiffon
f5a0b4bf8e Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-13 16:27:34 +01:00
Pierre Goiffon
a2b9583379 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2023-11-13 16:25:53 +01:00
Pierre Goiffon
77409eed99 🎨 DBObject small phpdoc fixes 2023-11-13 16:25:37 +01:00
Molkobain
eb7c971091 N°6948 - Upgrade "symfony/twig-bridge" to v5.4.31 2023-11-13 15:17:52 +01:00
Eric Espie
4d5a704d9a N°6062 - Fix unit tests 2023-11-13 15:14:29 +01:00
Eric Espie
b758113752 N°6436 - Integrate Performance Audit pre requisite (log events for extensions) 2023-11-13 15:02:54 +01:00
Stephen Abello
5465287089 Merge branch 'support/3.0' into support/3.1 2023-11-13 11:21:21 +01:00
Stephen Abello
09be84f69d N°6908 - Security hardening 2023-11-13 11:19:02 +01:00
Romain Quetiez
3b987f97eb Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-10 16:15:08 +01:00
Romain Quetiez
d9bdcfeae3 N°6658 - Fix regression: do not reset current user's profile cache 2023-11-10 15:57:08 +01:00
Pierre Goiffon
8df7c22464 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-10 15:21:10 +01:00
Pierre Goiffon
d725ba3d84 N°6765 Avoid behat scenario loading issues on portal modal (#569)
- New CombodoJsActivity API
- Replace existing calls in NiceWebPage (ready scripts)
- Add calls in ready block in portal object create template (used in both create and edit)
2023-11-10 15:10:37 +01:00
Molkobain
2d8ecd465b N°6903 - Fix crash when emptying file attribute (eg. picture of a contact) 2023-11-09 18:17:35 +01:00
Molkobain
34ba4fa0ce N°6917 - Security hardening 2023-11-09 16:43:37 +01:00
Molkobain
08d22219f4 Merge remote-tracking branch 'origin/support/3.0' into support/3.1 2023-11-08 14:59:56 +01:00
Molkobain
8a3d81c430 Merge remote-tracking branch 'origin/support/2.7' into support/3.0 2023-11-08 14:59:06 +01:00
Anne-Catherine
83a70daf68 N°6887 - Fix excessive OQL requests to display user's grant matrix (#564)
* N°6887 - Fix excessive OQL requests to display user's grant matrix

* N°6887 - Rename variable and add PHPDoc

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2023-11-08 14:57:28 +01:00
Molkobain
d5a8a3bb09 N°4756 - Fix PHPDoc 2023-11-07 12:00:19 +01:00
jf-cbd
eaeb114754 N°6852 - Use "email_default_sender_address" when "forgot_password_from" config param is empty 2023-11-06 10:47:40 +01:00
Molkobain
cfd32581b7 N°6861 - Add PHPDoc and return type hint 2023-11-03 09:20:15 +01:00
vdumas
85a6bd0a05 Typo in EN Dictionary - Allowed orgs class name 2023-11-02 17:43:48 +01:00
Stephen Abello
92cd1e3f19 N°6861 - Display warning message when creating/editing a mandatory blob in modal depending on edition mode and blob value 2023-11-02 14:58:46 +01:00
Stephen Abello
b54022e2ad N°6385 - Move Linkset flags and edit_when logic from UIBlock to DisplayBareRelations 2023-11-02 10:16:35 +01:00
odain-cbd
eaa80c5396 N°6824 - Notification with current_contact placeholder trigger hundred of email sent (#562)
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
Co-authored-by: Romain Quetiez <romain.quetiez@combodo.com>
2023-10-31 16:17:57 +01:00
271 changed files with 4388 additions and 2289 deletions

View File

@@ -68,8 +68,6 @@ gitGraph
branch support/3.1 order: 840
checkout support/3.1
commit id: "2023-08-09" tag: "3.1.0-2"
checkout support/2.7
commit id: "2023-08-10" tag: "2.7.9"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

View File

@@ -140,7 +140,7 @@ When your code is working, please:
* Pull request description: mind to add all the information useful to understand why you're suggesting this modification and anything necessary to dive into your work. Especially:
- Bugfixes: exact steps to reproduce the bug (given/when/then), description of the bug cause and what solution is implemented
- Enhancements: use cases, implementation details if needed
* Mind to check the "[Allow edits from maintainers](https://docs.github.com/en/github-ae@latest/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)" option ! (note that if you are working with an org fork, this option [won't be available](https://github.com/orgs/community/discussions/5634))
* Mind to check the "[Allow edits from maintainers](https://docs.github.com/en/github-ae@latest/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)" option !
## 🙏 We are thankful

View File

@@ -90,7 +90,6 @@ We would like to give a special thank you 🤗 to the people from the community
- Dvořák, Lukáš
- Goethals, Stefan
- Gumble, David
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
- Khamit, Shamil
- Kincel, Martin
@@ -108,7 +107,6 @@ We would like to give a special thank you 🤗 to the people from the community
- Rudner, Björn (a.k.a [@rudnerbjoern](https://github.com/rudnerbjoern))
- Seki, Shoji
- Shilov, Vladimir
- Stetina, Pavel (a.k.a [@Stetinac](https://github.com/Stetinac))
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
- Tulio, Marco
- Turrubiates, Miguel

View File

@@ -446,6 +446,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
UR_ACTION_BULK_DELETE => 'bd',
);
/**
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
*/
private $aUsersProfilesList = [];
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
{
@@ -758,8 +764,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
$sAction = self::$m_aActionCodes[$iActionCode];
$bStatus = null;
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
// Call the API of UserRights because it caches the list for us
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
if (!is_null($bGrant))
@@ -885,11 +895,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: this code is VERY close to the code of IsActionAllowed()
$iUser = $oUser->GetKey();
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
// Note: The object set is ignored because it was interesting to optimize for huge data sets
// and acceptable to consider only the root class of the object set
$bStatus = null;
// Call the API of UserRights because it caches the list for us
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
if (!is_null($bGrant))
@@ -918,8 +933,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
}
/**
* Find out which attribute is corresponding the the dimension 'owner org'
* returns null if no such attribute has been found (no filtering should occur)
* @param string $sClass
* @return string|null Find out which attribute is corresponding the dimension 'owner org'
* returns null if no such attribute has been found (no filtering should occur)
*/
public static function GetOwnerOrganizationAttCode($sClass)
{

View File

@@ -580,10 +580,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
/**
* Read and cache organizations allowed to the given user
*
* @param $oUser
* @param $sClass (not used here but can be used in overloads)
* @param User $oUser
* @param string $sClass (not used here but can be used in overloads)
*
* @return array
* @return array keys of the User allowed org
* @throws \CoreException
* @throws \Exception
*/

View File

@@ -335,7 +335,6 @@ abstract class AbstractPreferencesExtension implements iPreferencesExtension
* A recommended pattern is to cache data by the mean of static members.
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method
* @package UIExtensibilityAPI
*/
interface iApplicationUIExtension
@@ -487,7 +486,6 @@ interface iApplicationUIExtension
* @api
* @package UIExtensibilityAPI
* @since 2.7.0
* @deprecated
*/
abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
{
@@ -560,6 +558,7 @@ abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
* or through the GUI.
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method. More details on each method PHPDoc.
* @package ORMExtensibilityAPI
*/
interface iApplicationObjectExtension
@@ -574,6 +573,7 @@ interface iApplicationObjectExtension
* Otherwise, the answer is definitively "yes, the object has changed".
*
* @api
* @deprecated 3.1.0 N°4756 No alternative available, this API was unstable and is abandoned
* @param \cmdbAbstractObject $oObject The target object
*
* @return boolean True if something has changed for the target object
@@ -587,6 +587,7 @@ interface iApplicationObjectExtension
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_WRITE event instead
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
@@ -601,6 +602,7 @@ interface iApplicationObjectExtension
* Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled.
*
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_DELETE event instead
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
@@ -617,6 +619,7 @@ interface iApplicationObjectExtension
* * {@see DBObject::Get()} : for a given attribute the new value that was persisted
*
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
@@ -633,6 +636,7 @@ interface iApplicationObjectExtension
* The method is called right <b>after</b> the object has been written to the database.
*
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
@@ -647,6 +651,7 @@ interface iApplicationObjectExtension
* The method is called right <b>before</b> the object will be deleted from the database.
*
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_DELETE event instead
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
@@ -660,6 +665,7 @@ interface iApplicationObjectExtension
* Extend this class instead of iApplicationObjectExtension if you don't need to overload all methods
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method
* @package ORMExtensibilityAPI
* @since 2.7.0
*/
@@ -2009,6 +2015,8 @@ class RestUtils
*
* @return DBObject The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
*
* @see DBObject::CheckChangedExtKeysValues() generic method to check that we can access the linked object isn't used in that use case because values can be literal, OQL, friendlyname
*/
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
{

View File

@@ -746,7 +746,9 @@ HTML
$aArgs = array('this' => $this);
$sEditWhen = $oAttDef->GetEditWhen();
$bIsEditableBasedOnEditWhen = ($sEditWhen === LINKSET_EDITWHEN_ALWAYS || $sEditWhen === LINKSET_EDITWHEN_ON_HOST_EDITION);
// Calculate if edit_when allows to edit based on current $bEditMode
$bIsEditableBasedOnEditWhen = ($sEditWhen === LINKSET_EDITWHEN_ALWAYS) ||
($bEditMode ? $sEditWhen === LINKSET_EDITWHEN_ON_HOST_EDITION : $sEditWhen === LINKSET_EDITWHEN_ON_HOST_DISPLAY);
$bReadOnly = ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE)) || !$bIsEditableBasedOnEditWhen;
if ($bEditMode && (!$bReadOnly)) {
@@ -758,9 +760,9 @@ HTML
$oPage->add($sHTMLValue);
} else {
if ($oAttDef->IsIndirect()) {
$oBlockLinkSetViewTable = new BlockIndirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef);
$oBlockLinkSetViewTable = new BlockIndirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly);
} else {
$oBlockLinkSetViewTable = new BlockDirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef);
$oBlockLinkSetViewTable = new BlockDirectLinkSetViewTable($oPage, $this, $sClass, $sAttCode, $oAttDef, $bReadOnly);
}
$oPage->AddUiBlock($oBlockLinkSetViewTable);
}
@@ -4542,7 +4544,7 @@ HTML;
return $res;
}
public function PostInsertActions(): void
protected function PostInsertActions(): void
{
parent::PostInsertActions();
@@ -4566,6 +4568,9 @@ HTML;
InlineImage::FinalizeInlineImages($this);
}
/**
* @deprecated 3.1.1 3.2.0 N°6966 We will have only one DBClone method in the future
*/
protected function DBCloneTracked_Internal($newKey = null)
{
/** @var cmdbAbstractObject $oNewObj */
@@ -4605,7 +4610,7 @@ HTML;
return $res;
}
public function PostUpdateActions(array $aChanges): void
protected function PostUpdateActions(array $aChanges): void
{
parent::PostUpdateActions($aChanges);
@@ -4654,7 +4659,10 @@ HTML;
return $oDeletionPlan;
}
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
/**
* @deprecated 3.1.1 3.2.0 N°6967 We will have only one DBDelete method in the future
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
// Invoke extensions before the deletion (the deletion will do some cleanup and we might loose some information
/** @var \iApplicationObjectExtension $oExtensionInstance */
@@ -5346,7 +5354,7 @@ EOF
$aErrors = $oObj->UpdateObjectFromPostedForm('');
$bResult = (count($aErrors) == 0);
if ($bResult) {
list($bResult, $aErrors) = $oObj->CheckToWrite();
[$bResult, $aErrors] = $oObj->CheckToWrite();
}
if ($bPreview) {
$sStatus = $bResult ? Dict::S('UI:BulkModifyStatusOk') : Dict::S('UI:BulkModifyStatusError');
@@ -5363,6 +5371,11 @@ EOF
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrorsToDisplay)).'</p>',
);
if ($bResult && (!$bPreview)) {
// doing the check will load multiple times same objects :/
// but it shouldn't cost too much on execution time
// user can mitigate by selecting less extkeys/lnk to set and/or less objects to update 🤷‍♂️
$oObj->CheckChangedExtKeysValues();
$oObj->DBUpdate();
}
}
@@ -5945,42 +5958,56 @@ JS
}
/**
* If the passed object is an instance of a link class, then will register each remote object for modification using {@see static::RegisterObjectAwaitingEventDbLinksChanged()}
* Possibility for linked classes to be notified of current class modification
*
* If an external key was modified, register also the previous object that was linked previously.
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Exception
* @uses static::RegisterObjectAwaitingEventDbLinksChanged()
*
* @since 3.1.0 N°5906
* @throws ArchivedObjectException
* @throws CoreException
* @throws Exception
*
* @since 3.1.0 N°5906 method creation
* @since 3.1.1 3.2.0 N°6228 now just notify attributes having `with_php_computation`
*/
final protected function NotifyAttachedObjectsOnLinkClassModification(): void
{
$sClass = get_class($this);
if (false === MetaModel::IsLinkClass($sClass)) {
return;
}
// previous values in case of link change
$aPreviousValues = $this->ListPreviousValuesForUpdatedAttributes();
$sClass = get_class($this);
$aClassExtKeyAttCodes = MetaModel::GetAttributesList($sClass, [AttributeExternalKey::class]);
foreach ($aClassExtKeyAttCodes as $sExternalKeyAttCode) {
/** @var AttributeExternalKey $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($sClass, $sExternalKeyAttCode);
$aLnkClassExternalKeys = MetaModel::GetAttributesList($sClass, [AttributeExternalKey::class]);
foreach ($aLnkClassExternalKeys as $sExternalKeyAttCode) {
/** @var \AttributeExternalKey $oExternalKeyAttDef */
$oExternalKeyAttDef = MetaModel::GetAttributeDef($sClass, $sExternalKeyAttCode);
$sRemoteClassName = $oExternalKeyAttDef->GetTargetClass();
$sRemoteObjectId = $this->Get($sExternalKeyAttCode);
if ($sRemoteObjectId > 0) {
self::RegisterObjectAwaitingEventDbLinksChanged($sRemoteClassName, $sRemoteObjectId);
if (false === $this->DoesTargetObjectHavePhpComputation($oAttDef)) {
continue;
}
$sPreviousRemoteObjectId = $aPreviousValues[$sExternalKeyAttCode] ?? 0;
if ($sPreviousRemoteObjectId > 0) {
self::RegisterObjectAwaitingEventDbLinksChanged($sRemoteClassName, $sPreviousRemoteObjectId);
$sTargetObjectId = $this->Get($sExternalKeyAttCode);
if ($sTargetObjectId > 0) {
self::RegisterObjectAwaitingEventDbLinksChanged($oAttDef->GetTargetClass(), $sTargetObjectId);
}
$sPreviousTargetObjectId = $aPreviousValues[$sExternalKeyAttCode] ?? 0;
if ($sPreviousTargetObjectId > 0) {
self::RegisterObjectAwaitingEventDbLinksChanged($oAttDef->GetTargetClass(), $sPreviousTargetObjectId);
}
}
}
private function DoesTargetObjectHavePhpComputation(AttributeExternalKey $oAttDef): bool
{
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink) || false === $oAttDefMirrorLink->HasPHPComputation()){
return false;
}
return true;
}
/**
* Register one object for later EVENT_DB_LINKS_CHANGED event.
*

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="AbstractResource" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -514,18 +514,10 @@
<description>The object containing the document</description>
<type>DBObject</type>
</event_datum>
<event_datum id="att_code">
<description>The optional object attribute code hosting the document</description>
<type>string</type>
</event_datum>
<event_datum id="document">
<description>The document downloaded</description>
<type>ormDocument</type>
</event_datum>
<event_datum id="content_disposition">
<description>The content disposition of the document ("inline" or "attachment")</description>
<type>string</type>
</event_datum>
<event_datum id="debug_info">
<description>Debug string</description>
<type>string</type>

View File

@@ -0,0 +1,36 @@
<?php
/**
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458 object creation
*/
class InvalidExternalKeyValueException extends CoreUnexpectedValue
{
private const ENUM_PARAMS_OBJECT = 'current_object';
private const ENUM_PARAMS_ATTCODE = 'attcode';
private const ENUM_PARAMS_ATTVALUE = 'attvalue';
private const ENUM_PARAMS_USER = 'current_user';
public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null)
{
$aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject) . '::' . $oObject->GetKey();
$aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode;
$aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode);
$oCurrentUser = UserRights::GetUserObject();
if (false === is_null($oCurrentUser)) {
$aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser) . '::' . $oCurrentUser->GetKey();
}
parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious);
}
public function GetAttCode(): string
{
return $this->getContextData()[self::ENUM_PARAMS_ATTCODE];
}
public function GetAttValue(): string
{
return $this->getContextData()[self::ENUM_PARAMS_ATTVALUE];
}
}

View File

@@ -248,6 +248,7 @@ class LoginWebPage extends NiceWebPage
$oEmail = new Email();
$oEmail->SetRecipientTO($sTo);
$sFrom = MetaModel::GetConfig()->Get('forgot_password_from');
$sFrom = utils::IsNullOrEmptyString($sFrom) ? MetaModel::GetConfig()->Get('email_default_sender_address') : $sFrom;
$oEmail->SetRecipientFrom($sFrom);
$oEmail->SetSubject(Dict::S('UI:ResetPwd-EmailSubject', $oUser->Get('login')));
$sResetUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=reset_pwd&auth_user='.urlencode($oUser->Get('login')).'&token='.urlencode($sToken);

View File

@@ -103,7 +103,7 @@ class ApplicationMenu
{
self::$sFavoriteSiloQuery = $sOQL;
}
/**
* Get the query used to limit the list of displayed organizations in the drop-down menu
* @return string The OQL query returning a list of Organization objects
@@ -536,7 +536,7 @@ EOF
return -1;
}
/**
* Retrieves the currently active menu (if any, otherwise the first menu is the default)
* @return string The Id of the currently active menu
@@ -544,7 +544,7 @@ EOF
public static function GetActiveNodeId()
{
$oAppContext = new ApplicationContext();
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
if ($sMenuId === null)
{
$sMenuId = self::GetDefaultMenuId();
@@ -654,7 +654,7 @@ abstract class MenuNode
/**
* Stimulus to check: if the user can 'apply' this stimulus, then she/he can see this menu
*/
*/
protected $m_aEnableStimuli;
/**
@@ -814,7 +814,7 @@ abstract class MenuNode
{
return false;
}
/**
* Add a limiting display condition for the same menu node. The conditions will be combined with a AND
* @param $oMenuNode MenuNode Another definition of the same menu node, with potentially different access restriction
@@ -987,7 +987,7 @@ class TemplateMenuNode extends MenuNode
* @var string
*/
protected $sTemplateFile;
/**
* Create a menu item based on a custom template and inserts it into the application's main menu
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
@@ -1058,7 +1058,7 @@ class OQLMenuNode extends MenuNode
* @var bool|null
*/
protected $bSearchFormOpen;
/**
* Extra parameters to be passed to the display block to fine tune its appearence
*/
@@ -1091,7 +1091,7 @@ class OQLMenuNode extends MenuNode
// Enhancement: we could set as the "enable" condition that the user has enough rights to "read" the objects
// of the class specified by the OQL...
}
/**
* Set some extra parameters to be passed to the display block to fine tune its appearence
* @param array $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
@@ -1111,7 +1111,7 @@ class OQLMenuNode extends MenuNode
*/
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
ContextTag::AddContext(ContextTag::TAG_OBJECT_SEARCH);
$oTag = new ContextTag(ContextTag::TAG_OBJECT_SEARCH);
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
OQLMenuNode::RenderOQLSearch
(
@@ -1120,7 +1120,7 @@ class OQLMenuNode extends MenuNode
'Menu_'.$this->GetMenuId(),
$this->bSearch, // Search pane
$this->bSearchFormOpen, // Search open
$oPage,
$oPage,
array_merge($this->m_aParams, $aExtraParams),
true
);
@@ -1354,10 +1354,10 @@ class NewObjectMenuNode extends MenuNode
{
// Enable this menu, only if the current user has enough rights to create such an object, or an object of
// any child class
$aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
$bActionIsAllowed = false;
foreach($aSubClasses as $sCandidateClass)
{
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
@@ -1366,7 +1366,7 @@ class NewObjectMenuNode extends MenuNode
break; // Enough for now
}
}
return $bActionIsAllowed;
return $bActionIsAllowed;
}
/**
@@ -1508,7 +1508,7 @@ class DashboardMenuNode extends MenuNode
throw new Exception("Error: failed to load dashboard file: '{$this->sDashboardFile}'");
}
}
}
/**
@@ -1549,7 +1549,7 @@ class ShortcutContainerMenuNode extends MenuNode
$sName = $this->GetMenuId().'_'.$oShortcut->GetKey();
new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++);
}
// Complete the tree
//
parent::PopulateChildMenus();

View File

@@ -976,7 +976,7 @@ HTML
FormHelper::DisableAttributeBlobInputs($this->sTargetClass, $aFormExtraParams);
if(FormHelper::HasMandatoryAttributeBlobInputs($oNewObj)){
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal());
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE));
}
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), $aFormExtraParams);

View File

@@ -145,7 +145,7 @@ JS
FormHelper::DisableAttributeBlobInputs($sRealClass, $aFormExtraParams);
if(FormHelper::HasMandatoryAttributeBlobInputs($oObj)){
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal());
$oPage->AddUiBlock(FormHelper::GetAlertForMandatoryAttributeBlobInputsInModal(FormHelper::ENUM_MANDATORY_BLOB_MODE_CREATE));
}
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, array(), $aFormExtraParams);

View File

@@ -2499,15 +2499,17 @@ SQL;
$aHeaders = static::ParseHeaders($http_response_header);
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
// Compute the file extension from the MIME Type
foreach($aKnownExtensions as $sExtValue => $sMime)
{
if ($sMime === $sMimeType)
{
foreach ($aKnownExtensions as $sExtValue => $sMime) {
if ($sMime === $sMimeType) {
$sExtension = '.'.$sExtValue;
break;
}
}
}
$sPathName = pathinfo($sPath, PATHINFO_FILENAME);
if (utils::IsNotNullOrEmptyString($sPathName)) {
$sFileName = $sPathName;
}
$sFileName .= $sExtension;
}
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
@@ -3029,6 +3031,7 @@ HTML;
*
* @return bool if string null or empty
* @since 3.0.2 N°5302
* @since 2.7.10 N°6458 add method in the 2.7 branch
*/
public static function IsNullOrEmptyString(?string $sString): bool
{
@@ -3044,6 +3047,7 @@ HTML;
*
* @return bool if string is not null and not empty
* @since 3.0.2 N°5302
* @since 2.7.10 N°6458 add method in the 2.7 branch
*/
public static function IsNotNullOrEmptyString(?string $sString): bool
{

View File

@@ -11,7 +11,7 @@ define('APPCONF', APPROOT.'conf/');
*
* @see ITOP_CORE_VERSION to get full iTop core version
*/
define('ITOP_DESIGN_LATEST_VERSION', '3.2');
define('ITOP_DESIGN_LATEST_VERSION', '3.1');
/**
* Constant containing the iTop core version, whatever application was built
@@ -23,11 +23,13 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.2');
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '3.2.0');
define('ITOP_CORE_VERSION', '3.1.1');
/**
* @since 3.0.4 N°6274 Allow to test if PHPUnit is currently running. Starting with PHPUnit 9.5 we'll be able to replace it with $GLOBALS['phpunit_version']
* @var string
* @since 3.0.4 3.1.0 3.2.0 N°6274 Allow to test if PHPUnit is currently running. Starting with PHPUnit 9.5 we'll be able to replace it with $GLOBALS['phpunit_version']
* @since 3.0.4 3.1.1 3.2.0 N°6976 Fix constant name (DeprecatedCallsLog error handler was never set)
*/
define('ITOP_PHPUNIT_RUNNING_CONSTANT_NAME', 'ITOP_PHPUNIT_RUNNING');
const ITOP_PHPUNIT_RUNNING_CONSTANT_NAME = 'ITOP_PHPUNIT_RUNNING';
require_once APPROOT.'bootstrap.inc.php';

22
composer.lock generated
View File

@@ -4476,16 +4476,16 @@
},
{
"name": "symfony/twig-bridge",
"version": "v5.4.11",
"version": "v5.4.31",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bridge.git",
"reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8"
"reference": "fc6ee0a3b672ea12ca1f26592d257bfc7f4ee942"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/63b8a50d48c9fe3d04e77307d4f1771dd848baa8",
"reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8",
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/fc6ee0a3b672ea12ca1f26592d257bfc7f4ee942",
"reference": "fc6ee0a3b672ea12ca1f26592d257bfc7f4ee942",
"shasum": ""
},
"require": {
@@ -4498,22 +4498,22 @@
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/console": "<5.3",
"symfony/form": "<5.3",
"symfony/form": "<5.4.21|>=6,<6.2.7",
"symfony/http-foundation": "<5.3",
"symfony/http-kernel": "<4.4",
"symfony/translation": "<5.2",
"symfony/workflow": "<5.2"
},
"require-dev": {
"doctrine/annotations": "^1.12",
"egulias/email-validator": "^2.1.10|^3",
"doctrine/annotations": "^1.12|^2",
"egulias/email-validator": "^2.1.10|^3|^4",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/asset": "^4.4|^5.0|^6.0",
"symfony/console": "^5.3|^6.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/finder": "^4.4|^5.0|^6.0",
"symfony/form": "^5.3|^6.0",
"symfony/form": "^5.4.21|^6.2.7",
"symfony/http-foundation": "^5.3|^6.0",
"symfony/http-kernel": "^4.4|^5.0|^6.0",
"symfony/intl": "^4.4|^5.0|^6.0",
@@ -4577,7 +4577,7 @@
"description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/twig-bridge/tree/v5.4.11"
"source": "https://github.com/symfony/twig-bridge/tree/v5.4.31"
},
"funding": [
{
@@ -4593,7 +4593,7 @@
"type": "tidelift"
}
],
"time": "2022-07-20T13:00:38+00:00"
"time": "2023-11-09T21:19:08+00:00"
},
{
"name": "symfony/twig-bundle",
@@ -5276,5 +5276,5 @@
"platform-overrides": {
"php": "7.4.0"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

View File

@@ -1739,11 +1739,20 @@ class AttributeLinkedSet extends AttributeDefinition
* @return bool true if Attribute has constraints
* @since 3.1.0 N°6228
*/
public function GetHasConstraint()
public function HasPHPConstraint(): bool
{
return $this->GetOptional('with_php_constraint', false);
}
/**
* @return bool true if Attribute has computation (DB_LINKS_CHANGED event propagation, `with_php_computation` attribute xml property), false otherwise
* @since 3.1.1 3.2.0 N°6228
*/
public function HasPHPComputation(): bool
{
return $this->GetOptional('with_php_computation', false);
}
public function GetLinkedClass()
{
return $this->Get('linked_class');
@@ -8599,7 +8608,7 @@ class AttributeBlob extends AttributeDefinition
public function RecordAttChange(DBObject $oObject, $original, $value): void
{
// N°6502 Don't record history if only the download count has changed
if ($original->EqualsExceptDownloadsCount($value)) {
if ((null !== $original) && (null !== $value) && $original->EqualsExceptDownloadsCount($value)) {
return;
}
@@ -13211,10 +13220,8 @@ class AttributeCustomFields extends AttributeDefinition
// In that case we need additional keys : see \TemplateFieldsHandler::DoBuildForm
$aRequestTemplateValues = $proposedValue->GetValues();
if (false === array_key_exists('current_template_id', $aRequestTemplateValues)) {
$oCurrentValue = $oHostObject->Get($this->GetCode());
if(is_object($oCurrentValue)){
$aRequestTemplateValues = array_merge($oCurrentValue->GetValues(), $aRequestTemplateValues);
}
$aRequestTemplateValues['current_template_id'] = $aRequestTemplateValues['template_id'];
$aRequestTemplateValues['current_template_data'] = $aRequestTemplateValues['template_data'];
$proposedValue = new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRequestTemplateValues);
}
}

View File

@@ -438,7 +438,8 @@ abstract class CMDBObject extends DBObject
}
/**
* @deprecated 3.1.0 N°5232 not used
* @deprecated 3.1.0 N°5232 N°6966 simply use {@see DBObject::DBClone()} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*/
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
{
@@ -446,6 +447,9 @@ abstract class CMDBObject extends DBObject
$this->DBCloneTracked_Internal($newKey);
}
/**
* @deprecated 3.1.1 3.2.0 N°6966 We will have only one DBClone method in the future
*/
protected function DBCloneTracked_Internal($newKey = null)
{
$newKey = parent::DBClone($newKey);
@@ -470,23 +474,13 @@ abstract class CMDBObject extends DBObject
public function DBDelete(&$oDeletionPlan = null)
{
$this->LogCRUDEnter(__METHOD__);
$oDeletionPlan = $this->DBDeleteTracked_Internal($oDeletionPlan);
$oDeletionPlan = parent::DBDelete($oDeletionPlan);
$this->LogCRUDExit(__METHOD__);
return $oDeletionPlan;
}
/**
* @param null $oDeletionPlan
*
* @return \DeletionPlan|null
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @deprecated 3.1.1 3.2.0 N°6967 We will have only one DBDelete method in the future
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{

View File

@@ -3,7 +3,7 @@
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -380,7 +380,7 @@ class CMDBSource
public static function GetDBVendor()
{
$sDBVendor = static::ENUM_DB_VENDOR_MYSQL;
$sVersionComment = static::GetServerVariable('version') . ' - ' . static::GetServerVariable('version_comment');
if(preg_match('/mariadb/i', $sVersionComment) === 1)
{
@@ -390,7 +390,7 @@ class CMDBSource
{
$sDBVendor = static::ENUM_DB_VENDOR_PERCONA;
}
return $sDBVendor;
}
@@ -934,7 +934,7 @@ class CMDBSource
{
throw new MySQLException('Failed to issue SQL query', array('query' => $sSql));
}
while ($aRow = $oResult->fetch_array($iMode))
{
$aData[] = $aRow;
@@ -1088,7 +1088,7 @@ class CMDBSource
if (!array_key_exists($iKey, $aTableInfo["Fields"])) return false;
$aFieldData = $aTableInfo["Fields"][$iKey];
if (!array_key_exists("Key", $aFieldData)) return false;
return ($aFieldData["Key"] == "PRI");
return ($aFieldData["Key"] == "PRI");
}
public static function IsAutoIncrement($sTable, $sField)
@@ -1099,7 +1099,7 @@ class CMDBSource
$aFieldData = $aTableInfo["Fields"][$sField];
if (!array_key_exists("Extra", $aFieldData)) return false;
//MyHelpers::debug_breakpoint($aFieldData);
return (strstr($aFieldData["Extra"], "auto_increment"));
return (strstr($aFieldData["Extra"], "auto_increment"));
}
public static function IsField($sTable, $sField)
@@ -1366,13 +1366,13 @@ class CMDBSource
public static function GetTableFieldsList($sTable)
{
assert(!empty($sTable));
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return array(); // #@# or an error ?
return array_keys($aTableInfo["Fields"]);
}
// Cache the information about existing tables, and their fields
private static $m_aTablesInfo = array();
private static function _TablesInfoCacheReset($sTableName = null)
@@ -1505,7 +1505,7 @@ class CMDBSource
{
throw new MySQLException('Failed to issue SQL query', array('query' => $sSql));
}
$aRows = array();
while ($aRow = $oResult->fetch_array(MYSQLI_ASSOC))
{
@@ -1514,7 +1514,7 @@ class CMDBSource
$oResult->free();
return $aRows;
}
/**
* Returns the value of the specified server variable
* @param string $sVarName Name of the server variable
@@ -1530,7 +1530,7 @@ class CMDBSource
/**
* Returns the privileges of the current user
* @return string privileges in a raw format
*/
*/
public static function GetRawPrivileges()
{
try
@@ -1556,8 +1556,8 @@ class CMDBSource
/**
* Determine the slave status of the server
* @return bool true if the server is slave
*/
* @return bool true if the server is slave
*/
public static function IsSlaveServer()
{
try

View File

@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
*
* @see ITOP_CORE_VERSION to get iTop core version
*/
define('ITOP_VERSION', '3.2.0-dev');
define('ITOP_VERSION', '3.1.1-dev');
define('ITOP_VERSION_NAME', 'Fullmoon');
define('ITOP_REVISION', 'svn');
@@ -1193,6 +1193,30 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'sessions_tracking.enabled' => [
'type' => 'bool',
'description' => 'Whether or not the whole mechanism to track active sessions is enabled. See PHP session.gc_maxlifetime setting to configure session expiration.',
'default' => false,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'sessions_tracking.gc_threshold' => [
'type' => 'integer',
'description' => 'fallback in case cron is not active: probability in percent that session files are cleanup during any itop request (100 means always)',
'default' => 1,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'sessions_tracking.gc_duration_in_seconds' => [
'type' => 'integer',
'description' => 'fallback in case cron is not active: when a cleanup is triggered cleanup duration will not exceed this duration (in seconds).',
'default' => 1,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'transaction_storage' => [
'type' => 'string',
'description' => 'The type of mechanism to use for storing the unique identifiers for transactions (Session|File).',

View File

@@ -12,6 +12,7 @@ use Combodo\iTop\Application\UI\Base\Component\Input\SelectUIBlockFactory;
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\MultiColumnUIBlockFactory;
use Combodo\iTop\Application\Helper\ExportHelper;
/**
* Bulk export: CSV export
@@ -114,6 +115,7 @@ class CSVBulkExport extends TabularBulkExport
case 'csv_options':
$oPanel = PanelUIBlockFactory::MakeNeutral(Dict::S('Core:BulkExport:CSVOptions'));
$oPanel->AddSubBlock(ExportHelper::GetAlertForExcelMaliciousInjection());
$oMulticolumn = MultiColumnUIBlockFactory::MakeStandard();
$oPanel->AddSubBlock($oMulticolumn);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<user_rights>
<profiles>
<profile id="1024" _delta="define">
@@ -282,13 +282,8 @@
<field id="obj_attcode" xsi:type="AttributeString"/>
</fields>
</class>
<class id="DefaultWorkingTimeComputer" _delta="define">
<interfaces>
<interface id="iWorkingTimeComputer"/>
</interfaces>
</class>
</classes>
<attribute_properties_definition _delta="define">
<attribute_properties_definition _delta="define">
<properties>
<property id="sql">
<php_param>sql</php_param>
@@ -507,6 +502,12 @@
<type>boolean</type>
<default>false</default>
</property>
<property id="with_php_computation">
<php_param>with_php_computation</php_param>
<mandatory>false</mandatory>
<type>boolean</type>
<default>false</default>
</property>
<property id="create_temporary_object">
<php_param>create_temporary_object</php_param>
<mandatory>false</mandatory>

View File

@@ -9,6 +9,7 @@ use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventException;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Service\Events\EventServiceLog;
use Combodo\iTop\Service\Module\ModuleService;
use Combodo\iTop\Service\TemporaryObjects\TemporaryObjectManager;
/**
@@ -186,12 +187,13 @@ abstract class DBObject implements iDisplay
protected $m_oLinkHostObject = null;
/**
* @var array List all the CRUD stack in progress
*
* The array contains instances of
* ['type' => 'type of CRUD operation (INSERT, UPDATE, DELETE)',
* 'class' => 'class of the object in the CRUD process',
* 'id' => 'id of the object in the CRUD process']
* @var array{array{
* type: string,
* class: string,
* id: string,
* }} List all the CRUD stack in progress, with :
* - type: CRUD operation (INSERT, UPDATE, DELETE)',
* - class: class of the object in the CRUD process, leaf (object finalclass) if we have a hierarchy
*
* @since 3.1.0 N°5906
*/
@@ -2410,7 +2412,6 @@ abstract class DBObject implements iDisplay
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*
*/
public function DoCheckToWrite()
{
@@ -2462,7 +2463,130 @@ abstract class DBObject implements iDisplay
}
/**
*
* Trigger onObjectUpdate on the target object when an object pointed by a LinkSet is modified, added or removed
*
* @since 3.1.1 3.2.0 N°6531 method creation
*/
final protected function ActivateOnObjectUpdateTriggersForTargetObjects(): void
{
$aPreviousValues = $this->ListPreviousValuesForUpdatedAttributes();
$aClassExtKeyAttCodes = MetaModel::GetAttributesList(get_class($this), [AttributeExternalKey::class]);
foreach ($aClassExtKeyAttCodes as $sExtKeyWithMirrorLinkAttCode) {
/** @var AttributeExternalKey $oExtKeyWithMirrorLinkAttDef */
$oExtKeyWithMirrorLinkAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyWithMirrorLinkAttCode);
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oExtKeyWithMirrorLinkAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink)) {
// No LinkSet pointing to me
continue;
}
$sAttCodeMirrorLink = $oAttDefMirrorLink->GetCode();
$sTargetObjectClass = $oExtKeyWithMirrorLinkAttDef->GetTargetClass();
if (array_key_exists($sExtKeyWithMirrorLinkAttCode, $aPreviousValues)) {
// need to update old target also
$sPreviousTargetObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $sPreviousTargetObjectKey);
$this->ActivateOnObjectUpdateTriggers($oPreviousTargetObject, [$sAttCodeMirrorLink]);
}
// we need to update remote with current lnk instance
$oTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $this->Get($sExtKeyWithMirrorLinkAttCode));
$this->ActivateOnObjectUpdateTriggers($oTargetObject, [$sAttCodeMirrorLink]);
}
}
final static protected function GetObjectIfNotInCRUDStack($sClass, $sKey)
{
if (DBObject::IsObjectCurrentlyInCrud($sClass, $sKey)) {
return null;
}
return MetaModel::GetObject($sClass, $sKey, false);
}
/**
* Cascade CheckToWrite to Target Objects With LinkSet Pointing To Me
* @since 3.1.1 3.2.0 N°6228 method creation
*/
final protected function CheckToWriteForTargetObjects(bool $bIsCheckToDelete = false): void
{
$aChanges = $this->ListChanges();
$aClassExtKeyAttCodes = MetaModel::GetAttributesList(get_class($this), [AttributeExternalKey::class]);
foreach ($aClassExtKeyAttCodes as $sExtKeyWithMirrorLinkAttCode) {
/** @var AttributeExternalKey $oExtKeyWithMirrorLinkAttDef */
$oExtKeyWithMirrorLinkAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyWithMirrorLinkAttCode);
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oExtKeyWithMirrorLinkAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink) || (false === $oAttDefMirrorLink->HasPHPConstraint())) {
continue;
}
$sAttCodeMirrorLink = $oAttDefMirrorLink->GetCode();
$sTargetObjectClass = $oExtKeyWithMirrorLinkAttDef->GetTargetClass();
$oTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $this->Get($sExtKeyWithMirrorLinkAttCode));
if ($this->IsNew()) {
$this->CheckToWriteForSingleTargetObject_Internal('add', $oTargetObject, $sAttCodeMirrorLink, false);
} else if ($bIsCheckToDelete) {
$this->CheckToWriteForSingleTargetObject_Internal('remove', $oTargetObject, $sAttCodeMirrorLink, true);
} else {
if (array_key_exists($sExtKeyWithMirrorLinkAttCode, $aChanges)) {
// need to update remote old + new
$aPreviousValues = $this->ListPreviousValuesForUpdatedAttributes();
$sPreviousTargetObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $sPreviousTargetObjectKey);
$this->CheckToWriteForSingleTargetObject_Internal('remove', $oPreviousTargetObject, $sAttCodeMirrorLink, false);
$this->CheckToWriteForSingleTargetObject_Internal('add', $oTargetObject, $sAttCodeMirrorLink, false);
} else {
$this->CheckToWriteForSingleTargetObject_Internal('modify', $oTargetObject, $sAttCodeMirrorLink, false); // we need to update remote with current lnk instance
}
}
}
}
private function CheckToWriteForSingleTargetObject_Internal(string $sAction, ?DBObject $oTargetObject, string $sAttCodeMirrorLink, bool $bIsCheckToDelete): void
{
if (is_null($oTargetObject)) {
return;
}
$this->LogCRUDDebug(__METHOD__, "action: $sAction ".get_class($oTargetObject).'::'.$oTargetObject->GetKey()." ($sAttCodeMirrorLink)");
/** @var \ormLinkSet $oTargetValue */
$oTargetValue = $oTargetObject->Get($sAttCodeMirrorLink);
switch ($sAction) {
case 'add':
$oTargetValue->AddItem($this);
break;
case 'remove':
$oTargetValue->RemoveItem($this->GetKey());
break;
case 'modify':
$oTargetValue->ModifyItem($this);
break;
}
$oTargetObject->Set($sAttCodeMirrorLink, $oTargetValue);
[$bCheckStatus, $aCheckIssues, $bSecurityIssue] = $oTargetObject->CheckToWrite();
if (false === $bCheckStatus) {
if ($bIsCheckToDelete) {
$this->m_aDeleteIssues = array_merge($this->m_aDeleteIssues ?? [], $aCheckIssues);
} else {
$this->m_aCheckIssues = array_merge($this->m_aCheckIssues ?? [], $aCheckIssues);
}
$this->m_bSecurityIssue = $this->m_bSecurityIssue || $bSecurityIssue;
}
$aTargetCheckWarnings = $oTargetObject->GetCheckWarnings();
if (is_array($aTargetCheckWarnings)) {
$this->m_aCheckWarnings = array_merge($this->m_aCheckWarnings ?? [], $aTargetCheckWarnings);
}
}
/**
* @api
* @api-advanced
*
@@ -2478,14 +2602,14 @@ abstract class DBObject implements iDisplay
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*
*/
public final function CheckToWrite($bDoComputeValues = true)
final public function CheckToWrite($bDoComputeValues = true)
{
if (MetaModel::SkipCheckToWrite())
{
return array(true, array());
}
if (is_null($this->m_bCheckStatus))
{
$this->m_aCheckIssues = array();
@@ -2502,6 +2626,9 @@ abstract class DBObject implements iDisplay
$oKPI = new ExecutionKPI();
$this->DoCheckToWrite();
$oKPI->ComputeStatsForExtension($this, 'DoCheckToWrite');
$this->CheckToWriteForTargetObjects();
if (count($this->m_aCheckIssues) == 0)
{
$this->m_bCheckStatus = true;
@@ -2511,15 +2638,93 @@ abstract class DBObject implements iDisplay
$this->m_bCheckStatus = false;
}
}
return array($this->m_bCheckStatus, $this->m_aCheckIssues, $this->m_bSecurityIssue);
}
/**
* Checks for extkey attributes values. This will throw exception on non-existing as well as non-accessible objects (silo, scopes).
* That's why the test is done for all users including Administrators
*
* Note that due to perf issues, this isn't called directly by the ORM, but has to be called by consumers when possible.
*
* @param callable(string, string):bool|null $oIsObjectLoadableCallback Override to check if object is accessible.
* Parameters are object class and key
* Return value should be false if cannot access object, true otherwise
* @return void
*
* @throws ArchivedObjectException
* @throws CoreException if cannot get object attdef list
* @throws CoreUnexpectedValue
* @throws InvalidExternalKeyValueException
* @throws MySQLException
* @throws SecurityException if one extkey is pointing to an invalid value
*
* @link https://github.com/Combodo/iTop/security/advisories/GHSA-245j-66p9-pwmh
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458
*
* @see \RestUtils::FindObjectFromKey for the same check in the REST endpoint
*/
final public function CheckChangedExtKeysValues(callable $oIsObjectLoadableCallback = null)
{
if (is_null($oIsObjectLoadableCallback)) {
$oIsObjectLoadableCallback = function ($sClass, $sId) {
$oRemoteObject = MetaModel::GetObject($sClass, $sId, false);
if (is_null($oRemoteObject)) {
return false;
}
return true;
};
}
$aChanges = $this->ListChanges();
$aAttCodesChanged = array_keys($aChanges);
foreach ($aAttCodesChanged as $sAttDefCode) {
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttDefCode);
if ($oAttDef instanceof AttributeLinkedSetIndirect) {
/** @var ormLinkSet $oOrmSet */
$oOrmSet = $this->Get($sAttDefCode);
while ($oLnk = $oOrmSet->Fetch()) {
$oLnk->CheckChangedExtKeysValues($oIsObjectLoadableCallback);
}
continue;
}
/** @noinspection PhpConditionCheckedByNextConditionInspection */
/** @noinspection NotOptimalIfConditionsInspection */
if (($oAttDef instanceof AttributeHierarchicalKey) || ($oAttDef instanceof AttributeExternalKey)) {
$sRemoteObjectClass = $oAttDef->GetTargetClass();
$sRemoteObjectKey = $this->Get($sAttDefCode);
} else if ($oAttDef instanceof AttributeObjectKey) {
$sRemoteObjectClassAttCode = $oAttDef->Get('class_attcode');
$sRemoteObjectClass = $this->Get($sRemoteObjectClassAttCode);
$sRemoteObjectKey = $this->Get($sAttDefCode);
} else {
continue;
}
/** @noinspection NotOptimalIfConditionsInspection */
/** @noinspection TypeUnsafeComparisonInspection */
if (utils::IsNullOrEmptyString($sRemoteObjectClass)
|| utils::IsNullOrEmptyString($sRemoteObjectKey)
|| ($sRemoteObjectKey == 0) // non-strict comparison as we might have bad surprises
) {
continue;
}
if (false === $oIsObjectLoadableCallback($sRemoteObjectClass, $sRemoteObjectKey)) {
throw new InvalidExternalKeyValueException($this, $sAttDefCode);
}
}
}
/**
* Check if it is allowed to delete the existing object from the database
*
* an array of displayable error is added in {@see DBObject::$m_aDeleteIssues}
*
* @internal
* @internal
*
* @param \DeletionPlan $oDeletionPlan
*
@@ -2584,8 +2789,15 @@ abstract class DBObject implements iDisplay
*/
public function CheckToDelete(&$oDeletionPlan)
{
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
$this->AddCurrentObjectInCrudStack('DELETE');
try {
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
}
finally {
$this->RemoveCurrentObjectInCrudStack();
}
return (!$oDeletionPlan->FoundStopper());
}
@@ -2636,7 +2848,7 @@ abstract class DBObject implements iDisplay
{
// The value is a scalar, the comparison must be 100% strict
if($this->m_aOrigValues[$sAtt] !== $proposedValue)
{
{
//echo "$sAtt:<pre>\n";
//var_dump($this->m_aOrigValues[$sAtt]);
//var_dump($proposedValue);
@@ -2657,11 +2869,11 @@ abstract class DBObject implements iDisplay
* @api
* @api-advanced
*
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
* @return array attname => currentvalue List the attributes that have been changed using {@see DBObject::Set()}.
* @return array attcode => currentvalue List the attributes that have been changed using {@see DBObject::Set()}.
* Reset during {@see DBObject::DBUpdate()}
* @throws Exception
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
* @uses m_aCurrValues
*/
public function ListChanges()
@@ -2758,7 +2970,7 @@ abstract class DBObject implements iDisplay
/**
* Used only by insert, Meant to be overloaded
*
*
* @overwritable-hook You can extend this method in order to provide your own logic.
*/
protected function OnObjectKeyReady()
@@ -2866,7 +3078,7 @@ abstract class DBObject implements iDisplay
// fields in first array, values in the second
$aFieldsToWrite = array();
$aValuesToWrite = array();
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
@@ -2875,7 +3087,7 @@ abstract class DBObject implements iDisplay
}
$aHierarchicalKeys = array();
foreach(MetaModel::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef) {
// Skip this attribute if not defined in this table
if ((!MetaModel::IsAttributeOrigin($sTableClass, $sAttCode) && !$oAttDef->CopyOnAllTables())
@@ -2885,7 +3097,7 @@ abstract class DBObject implements iDisplay
$aAttColumns = $oAttDef->GetSQLValues($this->m_aCurrValues[$sAttCode]);
foreach($aAttColumns as $sColumn => $sValue)
{
$aFieldsToWrite[] = "`$sColumn`";
$aFieldsToWrite[] = "`$sColumn`";
$aValuesToWrite[] = CMDBSource::Quote($sValue);
}
if ($oAttDef->IsHierarchicalKey())
@@ -2909,7 +3121,7 @@ abstract class DBObject implements iDisplay
self::$m_aBulkInsertCols[$sClass][$sTable] = implode(', ', $aFieldsToWrite);
}
self::$m_aBulkInsertItems[$sClass][$sTable][] = '('.implode (', ', $aValuesToWrite).')';
$iNewKey = 999999; // TODO - compute next id....
}
else
@@ -2994,7 +3206,7 @@ abstract class DBObject implements iDisplay
// fields in first array, values in the second
$aFieldsToWrite = array();
$aValuesToWrite = array();
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
@@ -3029,7 +3241,7 @@ abstract class DBObject implements iDisplay
$aAttColumns = $oAttDef->GetSQLValues($value);
foreach($aAttColumns as $sColumn => $sValue)
{
$aFieldsToWrite[] = "`$sColumn`";
$aFieldsToWrite[] = "`$sColumn`";
$aValuesToWrite[] = CMDBSource::Quote($sValue);
}
if ($oAttDef->IsHierarchicalKey())
@@ -3100,6 +3312,8 @@ abstract class DBObject implements iDisplay
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*
* @see DBWrite
*/
public function DBInsertNoReload()
{
@@ -3137,7 +3351,7 @@ abstract class DBObject implements iDisplay
}
}
list($bRes, $aIssues) = $this->CheckToWrite(false);
[$bRes, $aIssues] = $this->CheckToWrite(false);
if (!$bRes) {
throw new CoreCannotSaveObjectException(array('issues' => $aIssues, 'class' => get_class($this), 'id' => $this->GetKey()));
}
@@ -3258,7 +3472,7 @@ abstract class DBObject implements iDisplay
* @throws \MySQLException
* @throws \OQLException
*/
public function PostInsertActions(): void
protected function PostInsertActions(): void
{
$this->FireEventAfterWrite([], true);
$oKPI = new ExecutionKPI();
@@ -3282,6 +3496,9 @@ abstract class DBObject implements iDisplay
// - TriggerOnObjectMention
$this->ActivateOnMentionTriggers(true);
// - Trigger for object pointing to the current object
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
}
/**
@@ -3309,7 +3526,7 @@ abstract class DBObject implements iDisplay
$this->RecordObjCreation();
return $ret;
}
/**
* This function is automatically called after cloning an object with the "clone" PHP language construct
* The purpose of this method is to reset the appropriate attributes of the object in
@@ -3328,13 +3545,13 @@ abstract class DBObject implements iDisplay
* Update an object in DB
*
* @api
* @see DBObject::DBWrite()
*
* @return int object key
*
* @throws \CoreException
* @throws \CoreCannotSaveObjectException if CheckToWrite() returns issues
* @throws \Exception
*
* @see DBObject::DBWrite()
*/
public function DBUpdate()
{
@@ -3377,7 +3594,7 @@ abstract class DBObject implements iDisplay
return $this->m_iKey;
}
list($bRes, $aIssues) = $this->CheckToWrite(false);
[$bRes, $aIssues] = $this->CheckToWrite(false);
if (!$bRes) {
throw new CoreCannotSaveObjectException(['issues' => $aIssues, 'class' => $sClass, 'id' => $this->GetKey()]);
}
@@ -3574,7 +3791,7 @@ abstract class DBObject implements iDisplay
* @throws \MySQLException
* @throws \OQLException
*/
public function PostUpdateActions(array $aChanges): void
protected function PostUpdateActions(array $aChanges): void
{
$this->FireEventAfterWrite($aChanges, false);
$oKPI = new ExecutionKPI();
@@ -3582,20 +3799,10 @@ abstract class DBObject implements iDisplay
$oKPI->ComputeStatsForExtension($this, 'AfterUpdate');
// - TriggerOnObjectUpdate
$aClassList = MetaModel::EnumParentClasses(get_class($this), ENUM_PARENT_CLASSES_ALL);
$aParams = array('class_list' => $aClassList);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)'),
array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
$oTrigger->DoActivate($this->ToArgs());
}
catch (Exception $e) {
$oTrigger->LogException($e, $this);
utils::EnrichRaisedException($oTrigger, $e);
}
}
$this->ActivateOnObjectUpdateTriggers($this);
// - Trigger for object pointing to the current object
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
$sClass = get_class($this);
if (MetaModel::HasLifecycle($sClass))
@@ -3641,6 +3848,37 @@ abstract class DBObject implements iDisplay
$this->ActivateOnMentionTriggers(false, $aChanges);
}
/**
* @param \DBObject $oObject
* @param array|null $aAttributes
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
*/
private function ActivateOnObjectUpdateTriggers(?DBObject $oObject, array $aAttributes = null): void
{
if (is_null($oObject)) {
return;
}
// - TriggerOnObjectUpdate
$aClassList = MetaModel::EnumParentClasses(get_class($oObject), ENUM_PARENT_CLASSES_ALL);
$aParams = array('class_list' => $aClassList);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)'),
array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
$oTrigger->DoActivateForSpecificAttributes($oObject->ToArgs(), $aAttributes);
}
catch (Exception $e) {
$oTrigger->LogException($e, $oObject);
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
/**
* Increment attribute with specified value.
@@ -3786,13 +4024,18 @@ abstract class DBObject implements iDisplay
/**
* Make the current changes persistent - clever wrapper for Insert or Update
*
* @api
*
* @api
*
* @return int
*
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
*
* @throws ArchivedObjectException
* @throws CoreCannotSaveObjectException
* @throws CoreException
* @throws CoreUnexpectedValue
* @throws CoreWarning
* @throws MySQLException
* @throws OQLException
*/
public function DBWrite()
{
@@ -3839,6 +4082,8 @@ abstract class DBObject implements iDisplay
*/
protected function DBDeleteSingleObject()
{
$this->LogCRUDEnter(__METHOD__);
if (MetaModel::DBIsReadOnly())
{
$this->LogCRUDExit(__METHOD__, 'DB is read-only');
@@ -3959,8 +4204,11 @@ abstract class DBObject implements iDisplay
$this->AfterDelete();
$oKPI->ComputeStatsForExtension($this, 'AfterDelete');
// - Trigger for object pointing to the current object
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
$this->m_bIsInDB = false;
$this->LogCRUDExit(__METHOD__);
// Fix for N°926: do NOT reset m_iKey as it can be used to have it for reporting purposes (see the REST service to delete
// objects, reported as bug N°926)
// Thought the key is not reset, using DBInsert or DBWrite will create an object having the same characteristics and a new ID. DBUpdate is protected
@@ -3972,7 +4220,7 @@ abstract class DBObject implements iDisplay
* First, checks if the object can be deleted regarding database integrity.
* If the answer is yes, it performs any required cleanup (delete other objects or reset external keys) in addition to the object
* deletion.
*
*
* @api
*
* @param \DeletionPlan $oDeletionPlan Do not use: aims at dealing with recursion
@@ -3991,74 +4239,65 @@ abstract class DBObject implements iDisplay
public function DBDelete(&$oDeletionPlan = null)
{
$this->LogCRUDEnter(__METHOD__);
try {
static $iLoopTimeLimit = null;
if ($iLoopTimeLimit == null) {
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
}
if (is_null($oDeletionPlan)) {
$oDeletionPlan = new DeletionPlan();
}
static $iLoopTimeLimit = null;
if ($iLoopTimeLimit == null)
{
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
}
if (is_null($oDeletionPlan))
{
$oDeletionPlan = new DeletionPlan();
}
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
if ($oDeletionPlan->FoundStopper())
{
$aIssues = $oDeletionPlan->GetIssues();
$this->LogCRUDError(__METHOD__, ' Errors: '.implode(', ', $aIssues));
throw new DeleteException('Found issue(s)', array('target_class' => get_class($this), 'target_id' => $this->GetKey(), 'issues' => implode(', ', $aIssues)));
}
if (false === $this->CheckToDelete($oDeletionPlan)) {
$aIssues = $oDeletionPlan->GetIssues();
$this->LogCRUDError(__METHOD__, ' Errors: '.implode(', ', $aIssues));
throw new DeleteException('Found issue(s)', array('target_class' => get_class($this), 'target_id' => $this->GetKey(), 'issues' => implode(', ', $aIssues)));
}
// Getting and setting time limit are not symetric:
// www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time');
// Getting and setting time limit are not symmetric:
// www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time');
foreach ($oDeletionPlan->ListDeletes() as $sClass => $aToDelete)
{
foreach ($aToDelete as $iId => $aData)
{
/** @var \DBObject $oToDelete */
$oToDelete = $aData['to_delete'];
// The deletion based on a deletion plan should not be done for each object if the deletion plan is common (Trac #457)
// because for each object we would try to update all the preceding ones... that are already deleted
// A better approach would be to change the API to apply the DBDelete on the deletion plan itself... just once
// As a temporary fix: delete only the objects that are still to be deleted...
if ($oToDelete->m_bIsInDB)
{
set_time_limit(intval($iLoopTimeLimit));
foreach ($oDeletionPlan->ListDeletes() as $sClass => $aToDelete) {
foreach ($aToDelete as $iId => $aData) {
/** @var \DBObject $oToDelete */
$oToDelete = $aData['to_delete'];
// The deletion based on a deletion plan should not be done for each object if the deletion plan is common (Trac #457)
// because for each object we would try to update all the preceding ones... that are already deleted
// A better approach would be to change the API to apply the DBDelete on the deletion plan itself... just once
// As a temporary fix: delete only the objects that are still to be deleted...
if ($oToDelete->m_bIsInDB) {
set_time_limit(intval($iLoopTimeLimit));
$oToDelete->AddCurrentObjectInCrudStack('DELETE');
try {
$oToDelete->DBDeleteSingleObject();
}
finally {
$oToDelete->RemoveCurrentObjectInCrudStack();
$oToDelete->AddCurrentObjectInCrudStack('DELETE');
try {
$oToDelete->DBDeleteSingleObject();
}
finally {
$oToDelete->RemoveCurrentObjectInCrudStack();
}
}
}
}
}
foreach ($oDeletionPlan->ListUpdates() as $sClass => $aToUpdate)
{
foreach ($aToUpdate as $aData)
{
$oToUpdate = $aData['to_reset'];
/** @var \DBObject $oToUpdate */
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef)
{
$oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
set_time_limit(intval($iLoopTimeLimit));
$oToUpdate->DBUpdate();
foreach ($oDeletionPlan->ListUpdates() as $sClass => $aToUpdate) {
foreach ($aToUpdate as $aData) {
$oToUpdate = $aData['to_reset'];
/** @var \DBObject $oToUpdate */
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) {
$oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
set_time_limit(intval($iLoopTimeLimit));
$oToUpdate->DBUpdate();
}
}
}
set_time_limit(intval($iPreviousTimeLimit));
} finally {
$this->LogCRUDExit(__METHOD__);
}
set_time_limit(intval($iPreviousTimeLimit));
$this->LogCRUDExit(__METHOD__);
return $oDeletionPlan;
}
@@ -4365,7 +4604,7 @@ abstract class DBObject implements iDisplay
*
* @api
*
*/
*/
public function Reset($sAttCode)
{
$this->Set($sAttCode, $this->GetDefaultValue($sAttCode));
@@ -4377,7 +4616,7 @@ abstract class DBObject implements iDisplay
* Suitable for use as a lifecycle action
*
* @api
*/
*/
public function Copy($sDestAttCode, $sSourceAttCode)
{
$oTypeValueToCopy = MetaModel::GetAttributeDef(get_class($this), $sSourceAttCode);
@@ -4707,7 +4946,7 @@ abstract class DBObject implements iDisplay
{
throw new CoreException("Unknown attribute '$sExtKeyAttCode' for the class ".get_class($this));
}
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
if (!$oKeyAttDef instanceof AttributeExternalKey)
{
@@ -4725,14 +4964,14 @@ abstract class DBObject implements iDisplay
$ret = $oRemoteObj->GetForTemplate($sRemoteAttCode);
}
}
else
else
{
switch($sPlaceholderAttCode)
{
case 'id':
$ret = $this->GetKey();
break;
case 'name()':
$ret = $this->GetName();
break;
@@ -4919,7 +5158,7 @@ abstract class DBObject implements iDisplay
if ($oOwner)
{
$sLinkSetOwnerClass = get_class($oOwner);
$oMyChangeOp = MetaModel::NewObject($sChangeOpClass);
$oMyChangeOp->Set("objclass", $sLinkSetOwnerClass);
$oMyChangeOp->Set("objkey", $iLinkSetOwnerId);
@@ -4946,7 +5185,7 @@ abstract class DBObject implements iDisplay
{
/** @var \AttributeLinkedSet $oLinkSet */
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_LIST) == 0) continue;
$iLinkSetOwnerId = $this->Get($sExtKeyAttCode);
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, 'CMDBChangeOpSetAttributeLinksAddRemove');
if ($oMyChangeOp)
@@ -5164,8 +5403,9 @@ abstract class DBObject implements iDisplay
$this->m_aDeleteIssues = array(); // Ok
$this->FireEventCheckToDelete($oDeletionPlan);
$this->DoCheckToDelete($oDeletionPlan);
$this->CheckToWriteForTargetObjects(true);
$oDeletionPlan->SetDeletionIssues($this, $this->m_aDeleteIssues, $this->m_bSecurityIssue);
$aDependentObjects = $this->GetReferencingObjects(true /* allow all data */);
// Getting and setting time limit are not symmetric:
@@ -5347,7 +5587,7 @@ abstract class DBObject implements iDisplay
$aSynchroClasses[] = $sTarget;
}
}
foreach($aSynchroClasses as $sClass)
{
if ($this instanceof $sClass)
@@ -6154,6 +6394,18 @@ abstract class DBObject implements iDisplay
$this->m_aCheckWarnings[] = $sWarning;
}
/**
*
* @api
*
* @return string[]|null
* @since 3.1.1 3.2.0
*/
public function GetCheckWarnings(): ?array
{
return $this->m_aCheckWarnings;
}
/**
* @api
*
@@ -6285,7 +6537,10 @@ abstract class DBObject implements iDisplay
}
}
finally {
$oKPI->ComputeStats('FireEvent', $sEvent);
if (!$oKPI->ComputeStatsForExtension($this, $sCallback, "Event: $sEvent")) {
$sSignature = ModuleService::GetInstance()->GetModuleMethodSignature($this, $sCallback);
$oKPI->ComputeStats('FireEvent', "$sEvent callback: $sSignature");
}
}
}
if (!is_null($oFirstException)) {
@@ -6398,9 +6653,10 @@ abstract class DBObject implements iDisplay
// during insert key is reset from -1 to null
// so we need to handle null values (will give empty string after conversion)
$sConvertedId = (string)$sId;
$oRootClass = MetaModel::GetRootClass($sClass);
foreach (self::$m_aCrudStack as $aCrudStackEntry) {
if (($sClass === $aCrudStackEntry['class'])
if (($oRootClass === $aCrudStackEntry['class'])
&& ($sConvertedId === $aCrudStackEntry['id'])) {
return true;
}
@@ -6415,12 +6671,14 @@ abstract class DBObject implements iDisplay
* @param string $sClass
*
* @return bool
* @throws \CoreException
* @since 3.1.0 N°5609
*/
final public static function IsClassCurrentlyInCrud(string $sClass): bool
{
$sRootClass = MetaModel::GetRootClass($sClass);
foreach (self::$m_aCrudStack as $aCrudStackEntry) {
if ($sClass === $aCrudStackEntry['class']) {
if ($sRootClass === $aCrudStackEntry['class']) {
return true;
}
}
@@ -6438,9 +6696,11 @@ abstract class DBObject implements iDisplay
*/
private function AddCurrentObjectInCrudStack(string $sCrudType): void
{
$this->LogCRUDDebug(__METHOD__);
$sRootClass = MetaModel::GetRootClass(get_class($this));
self::$m_aCrudStack[] = [
'type' => $sCrudType,
'class' => get_class($this),
'class' => $sRootClass,
'id' => (string)$this->GetKey(), // GetKey() doesn't have type hinting, so forcing type to avoid getting an int
];
}
@@ -6454,6 +6714,7 @@ abstract class DBObject implements iDisplay
*/
private function UpdateCurrentObjectInCrudStack(): void
{
$this->LogCRUDDebug(__METHOD__);
$aCurrentCrudStack = array_pop(self::$m_aCrudStack);
$aCurrentCrudStack['id'] = (string)$this->GetKey();
self::$m_aCrudStack[] = $aCurrentCrudStack;
@@ -6467,7 +6728,8 @@ abstract class DBObject implements iDisplay
*/
private function RemoveCurrentObjectInCrudStack(): void
{
array_pop(self::$m_aCrudStack);
$aRemoved = array_pop(self::$m_aCrudStack);
$this->LogCRUDDebug(__METHOD__, $aRemoved['class'].':'.$aRemoved['id']);
}
/**

View File

@@ -16,8 +16,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\Helper\WebResourcesHelper;
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
use Combodo\iTop\Application\UI\Base\Component\MedallionIcon\MedallionIcon;
use Combodo\iTop\Application\UI\Base\Component\Panel\Panel;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
use Combodo\iTop\Renderer\BlockRenderer;
/**
@@ -1412,6 +1415,8 @@ class DisplayableGraph extends SimpleGraph
/**
* Display the graph inside the given page, with the "filter" drawer above it
*
* @deprecated 3.1.1 3.2.0 N°3767 Use \DisplayableGraph::DisplayFilterBox() and \DisplayableGraph::DisplayGraph() instead
*
* @param WebPage $oP
* @param array $aResults
* @param string $sRelation
@@ -1425,10 +1430,35 @@ class DisplayableGraph extends SimpleGraph
*
* @throws \CoreException
* @throws \DictExceptionMissingString
*
*/
function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array(), bool $bLazyLoading = false)
{
list($aExcludedByClass, $aAdditionalContexts) = $this->DisplayFiltering($sContextKey, $aContextParams, $aExcludedObjects, $oP, $aResults, $bLazyLoading);
$oP->AddSubBlock($this->DisplayFilterBox($oP, $aResults, $bLazyLoading));
$this->DisplayGraph($oP, $sRelation, $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams, $bLazyLoading);
}
/**
* Display only the graph inside the given page, with the parameters of filter box draw with DisplayFilterBox
*
* @param WebPage $oP
* @param string $sRelation
* @param ApplicationContext $oAppContext
* @param array $aExcludedObjects
* @param string $sObjClass
* @param int $iObjKey
* @param string $sContextKey
* @param array $aContextParams
* @param bool $bLazyLoading
*
* @throws \CoreException
* @throws \DictExceptionMissingString
*
* @since 3.1.1 3.2.0 N°3767
*/
function DisplayGraph(WebPage $oP, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array(), bool $bLazyLoading = false): void
{
list($aExcludedByClass, $aAdditionalContexts) = $this->GetFilteringData($sContextKey, $aContextParams, $aExcludedObjects);
$iGroupingThreshold = utils::ReadParam('g', 5);
@@ -1513,12 +1543,10 @@ class DisplayableGraph extends SimpleGraph
$oP->add_ready_script(" $('#$sId').simple_graph(".json_encode($aParams).");");
} else {
$oP->add_script("function Load(){var aExcluded = []; $('input[name^=excluded]').each( function() {if (!$(this).prop('checked')) { aExcluded.push($(this).val()); }} ); var params= $.extend(".json_encode($aParams).", {excluded_classes: aExcluded}); $('#$sId').simple_graph(params);}");
$oP->add_ready_script("$('#impacted_objects_lists').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');$('#impacted_groups').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');");
$oP->add_ready_script("$('#graph').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');$('#impacted_objects_lists').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');$('#impacted_groups').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');");
}
}
catch(Exception $e)
{
catch (Exception $e) {
$oP->add('<div>'.$e->getMessage().'</div>');
}
$oP->add_script(
@@ -1563,23 +1591,41 @@ EOF
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*
* @deprecated 3.1.1 3.2.0 N°3767 Use \DisplayableGraph::DisplayFilterBox() and \DisplayableGraph::GetFilteringData() instead
*/
public function DisplayFiltering(string $sContextKey, array $aContextParams, array $aExcludedObjects, WebPage $oP, array $aResults, bool $bLazyLoading = false): array
{
$aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
$aExcludedByClass = array();
foreach ($aExcludedObjects as $oObj) {
if (!array_key_exists(get_class($oObj), $aExcludedByClass)) {
$aExcludedByClass[get_class($oObj)] = array();
}
$aExcludedByClass[get_class($oObj)][] = $oObj->GetKey();
}
$oP->Add($this->DisplayFilterBox($oP, $aResults, $bLazyLoading));
return $this->GetFilteringData($sContextKey, $aContextParams, $aExcludedObjects);
}
/**
* @param \WebPage $oP
* @param array $aResults
* @param bool $bLazyLoading
*
* @return UIContentBlock
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \ReflectionException
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*
* @since 3.1.1 3.2.0 N°3767
*/
public function DisplayFilterBox(WebPage $oP, array $aResults, bool $bLazyLoading = false): UIContentBlock
{
$sSftShort = Dict::S('UI:ElementsDisplayed');
$oP->add("<div class=\"not-printable\">\n");
$oBlock = UIContentBlockUIBlockFactory::MakeStandard(null, ['not-printable']);
$oUiSearchBlock = new Panel($sSftShort, [], Panel::ENUM_COLOR_SCHEME_CYAN, 'dh_flash');
$oUiSearchBlock->SetCSSClasses(["ibo-search-form-panel", "display_block"]);
$oUiSearchBlock->SetIsCollapsible(true);
$oUiHtmlBlock = new Combodo\iTop\Application\UI\Base\Component\Html\Html(
$oUiSearchBlock->SetCSSClasses(["ibo-search-form-panel", "display_block"])
->SetIsCollapsible(true);
$oUiHtmlBlock = new Html(
<<<EOF
<div id="ds_flash" class="search_box ibo-display-graph--search-box">
@@ -1626,11 +1672,23 @@ EOF
$oUiHtmlBlock->AddHtml("<button type=\"button\" id=\"ReloadMovieBtn\" class=\"ibo-button ibo-is-neutral ibo-is-regular\" onClick=\"$sOnCLick\">".Dict::S('UI:Button:Refresh')."</button></div></form>");
}
$oUiHtmlBlock->AddHtml("</div>\n");
$oUiHtmlBlock->AddHtml("</div>\n"); // class="not-printable"
$oUiSearchBlock->AddSubBlock($oUiHtmlBlock);
$oP->AddUiBlock($oUiSearchBlock);
$oBlock->AddSubBlock($oUiSearchBlock);
return $oBlock;
}
public function GetFilteringData(string $sContextKey, array $aContextParams, array $aExcludedObjects): array
{
$aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
$aExcludedByClass = array();
foreach ($aExcludedObjects as $oObj) {
if (!array_key_exists(get_class($oObj), $aExcludedByClass)) {
$aExcludedByClass[get_class($oObj)] = array();
}
$aExcludedByClass[get_class($oObj)][] = $oObj->GetKey();
}
$aAdditionalContexts = array();
foreach ($aContextDefs as $sKey => $aDefinition) {
$aAdditionalContexts[] = array('key' => $sKey, 'label' => Dict::S($aDefinition['dict']), 'oql' => $aDefinition['oql'], 'default' => (array_key_exists('default', $aDefinition) && ($aDefinition['default'] == 'yes')));

View File

@@ -10,6 +10,7 @@ use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
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\MultiColumnUIBlockFactory;
use Combodo\iTop\Application\Helper\ExportHelper;
require_once(APPROOT.'application/xlsxwriter.class.php');
@@ -82,6 +83,7 @@ class ExcelBulkExport extends TabularBulkExport
case 'xlsx_options':
$oPanel = PanelUIBlockFactory::MakeNeutral(Dict::S('Core:BulkExport:XLSXOptions'));
$oPanel->AddSubBlock(ExportHelper::GetAlertForExcelMaliciousInjection());
$oMulticolumn = MultiColumnUIBlockFactory::MakeStandard();
$oPanel->AddSubBlock($oMulticolumn);

View File

@@ -3,6 +3,7 @@
* @copyright Copyright (C) 2010-2023 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Combodo\iTop\Core\Kpi\KpiLogData;
use Combodo\iTop\Service\Module\ModuleService;
@@ -404,16 +405,31 @@ class ExecutionKPI
$this->ResetCounters();
}
public function ComputeStatsForExtension($object, $sMethod)
/**
* Compute statistics for a call to an extension
* Note: not working in dev mode (with links to env-production)
*
* @param object|string $object object called
* @param string $sMethod method called on the object
* @param string $sMessage additional message
*
* @return bool true if an extension was found for this object::method
* @throws \ReflectionException
*/
public function ComputeStatsForExtension($object, string $sMethod, string $sMessage = ''): bool
{
if (!self::IsEnabled()) {
return;
return true;
}
$sSignature = ModuleService::GetInstance()->GetModuleMethodSignature($object, $sMethod);
if (utils::StartsWith($sSignature, '[')) {
$this->ComputeStats('Extension', $sSignature);
$this->ComputeStats('Extension', "$sSignature $sMessage");
return true;
}
return false;
}
public function ComputeStats($sOperation, $sArguments)

View File

@@ -3,7 +3,7 @@
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -576,6 +576,11 @@ class LogChannels
public const DATATABLE = 'Datatable';
public const DEADLOCK = 'DeadLock';
/**
* @var string Everything related to PHP sessions tracking
* @since 3.1.1 3.2.0 N°6901
*/
public const SESSIONTRACKER = 'SessionTracker';
/**
* @var string Everything related to the datamodel CRUD
@@ -1138,9 +1143,13 @@ class DeprecatedCallsLog extends LogAPI
parent::Enable($sTargetFile);
if (
(false === defined('ITOP_PHPUNIT_RUNNING_CONSTANT_NAME'))
(
(false === defined(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME))
|| (defined(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME) && (constant(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME) !== true))
)
&& static::IsLogLevelEnabledSafe(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_LIBMETHOD)
) {
IssueLog::Trace('Setting '.static::class.' error handler to catch DEPRECATED', static::ENUM_CHANNEL_PHP_LIBMETHOD);
set_error_handler([static::class, 'DeprecatedNoticesErrorHandler'], E_DEPRECATED | E_USER_DEPRECATED);
}
}

View File

@@ -1241,7 +1241,7 @@ abstract class MetaModel
}
$sTable = self::DBGetTable($sClass);
// Could be completed later with all the classes that are using a given table
// Could be completed later with all the classes that are using a given table
if (!array_key_exists($sTable, $aTables)) {
$aTables[$sTable] = array();
}
@@ -1445,8 +1445,10 @@ abstract class MetaModel
*
* @return AttributeDefinition[]
* @throws \CoreException
*
* @see GetAttributesList for attcode list
*/
final static public function ListAttributeDefs($sClass)
final public static function ListAttributeDefs($sClass)
{
self::_check_subclass($sClass);
return self::$m_aAttribDefs[$sClass];
@@ -1459,8 +1461,10 @@ abstract class MetaModel
* @param string[] $aDesiredAttTypes Array of AttributeDefinition classes to filter the list on
* @param string|null $sListCode If provided, attributes will be limited to those in this zlist
*
* @return array
* @return string[] list of attcodes
* @throws \CoreException
*
* @see ListAttributeDefs to get AttributeDefinition array instead
*/
final public static function GetAttributesList(string $sClass, array $aDesiredAttTypes = [], ?string $sListCode = null)
{
@@ -3522,7 +3526,7 @@ abstract class MetaModel
}
// Set the "host class" as soon as possible, since HierarchicalKeys use it for their 'target class' as well
// and this needs to be know early (for Init_IsKnowClass 19 lines below)
// and this needs to be know early (for Init_IsKnowClass 19 lines below)
$oAtt->SetHostClass($sTargetClass);
// Some attributes could refer to a class
@@ -3564,7 +3568,7 @@ abstract class MetaModel
self::$m_aAttribDefs[$sTargetClass][$oAtt->GetCode()] = $oAtt;
self::$m_aAttribOrigins[$sTargetClass][$oAtt->GetCode()] = $sTargetClass;
// Note: it looks redundant to put targetclass there, but a mix occurs when inheritance is used
// Note: it looks redundant to put targetclass there, but a mix occurs when inheritance is used
}
/**
@@ -3764,7 +3768,7 @@ abstract class MetaModel
self::$m_aStimuli[$sTargetClass][$oStimulus->GetCode()] = $oStimulus;
// I wanted to simplify the syntax of the declaration of objects in the biz model
// Therefore, the reference to the host class is set there
// Therefore, the reference to the host class is set there
$oStimulus->SetHostClass($sTargetClass);
}
@@ -4219,40 +4223,77 @@ abstract class MetaModel
}
else
{
$aCurrentUser = array();
$aCurrentContact = array();
$aCurrentUser = [];
$aCurrentContact = [];
foreach ($aExpectedArgs as $expression)
{
$aName = explode('->', $expression->GetName());
if ($aName[0] == 'current_contact_id') {
$aPlaceholders['current_contact_id'] = UserRights::GetContactId();
}
if ($aName[0] == 'current_user') {
} else if ($aName[0] == 'current_user') {
array_push($aCurrentUser, $aName[1]);
}
if ($aName[0] == 'current_contact') {
} else if ($aName[0] == 'current_contact') {
array_push($aCurrentContact, $aName[1]);
}
}
if (count($aCurrentUser) > 0) {
$oUser = UserRights::GetUserObject();
$aPlaceholders['current_user->object()'] = $oUser;
foreach ($aCurrentUser as $sField) {
$aPlaceholders['current_user->'.$sField] = $oUser->Get($sField);
}
static::FillObjectPlaceholders($aPlaceholders, 'current_user', UserRights::GetUserObject(), $aCurrentUser);
}
if (count($aCurrentContact) > 0) {
$oPerson = UserRights::GetContactObject();
$aPlaceholders['current_contact->object()'] = $oPerson;
foreach ($aCurrentContact as $sField) {
$aPlaceholders['current_contact->'.$sField] = $oPerson->Get($sField);
}
static::FillObjectPlaceholders($aPlaceholders, 'current_contact', UserRights::GetContactObject(), $aCurrentContact);
}
}
return $aPlaceholders;
}
/**
* @since 3.1.1 N°6824
* @param array $aPlaceholders
* @param string $sPlaceHolderPrefix
* @param ?\DBObject $oObject
* @param array $aCurrentUser
*
* @return void
*
*/
private static function FillObjectPlaceholders(array &$aPlaceholders, string $sPlaceHolderPrefix, ?\DBObject $oObject, array $aCurrentUser) : void {
$sPlaceHolderKey = $sPlaceHolderPrefix."->object()";
if (is_null($oObject)){
$aContext = [
"current_user_id" => UserRights::GetUserId(),
"null object type" => $sPlaceHolderPrefix,
"fields" => $aCurrentUser,
];
IssueLog::Warning("Unresolved placeholders due to null object in current context", null,
$aContext);
$aPlaceholders[$sPlaceHolderKey] = \Dict::Format("Core:Placeholder:CannotBeResolved", $sPlaceHolderKey);
foreach ($aCurrentUser as $sField) {
$sPlaceHolderKey = $sPlaceHolderPrefix . "->$sField";
$aPlaceholders[$sPlaceHolderKey] = \Dict::Format("Core:Placeholder:CannotBeResolved", $sPlaceHolderKey);
}
} else {
$aPlaceholders[$sPlaceHolderKey] = $oObject;
foreach ($aCurrentUser as $sField) {
$sPlaceHolderKey = $sPlaceHolderPrefix . "->$sField";
if (false === MetaModel::IsValidAttCode(get_class($oObject), $sField)){
$aContext = [
"current_user_id" => UserRights::GetUserId(),
"obj_class" => get_class($oObject),
"placeholder" => $sPlaceHolderKey,
"invalid_field" => $sField,
];
IssueLog::Warning("Unresolved placeholder due to invalid attribute", null,
$aContext);
$aPlaceholders[$sPlaceHolderKey] = \Dict::Format("Core:Placeholder:CannotBeResolved", $sPlaceHolderKey);
continue;
}
$aPlaceholders[$sPlaceHolderKey] = $oObject->Get($sField);
}
}
}
/**
* @param \DBSearch $oFilter
*
@@ -5114,7 +5155,7 @@ abstract class MetaModel
*/
protected static function DBCreateTables($aCallback = null)
{
list($aErrors, $aSugFix, $aCondensedQueries) = self::DBCheckFormat();
[$aErrors, $aSugFix, $aCondensedQueries] = self::DBCheckFormat();
//$sSQL = implode('; ', $aCondensedQueries); Does not work - multiple queries not allowed
foreach($aCondensedQueries as $sQuery)
@@ -5136,7 +5177,7 @@ abstract class MetaModel
*/
protected static function DBCreateViews()
{
list($aErrors, $aSugFix) = self::DBCheckViews();
[$aErrors, $aSugFix] = self::DBCheckViews();
foreach($aSugFix as $sClass => $aTarget)
{
@@ -6479,7 +6520,7 @@ abstract class MetaModel
$aCache['m_aExtensionClassNames'] = self::$m_aExtensionClassNames;
$aCache['m_Category2Class'] = self::$m_Category2Class;
$aCache['m_aRootClasses'] = self::$m_aRootClasses; // array of "classname" => "rootclass"
$aCache['m_aParentClasses'] = self::$m_aParentClasses; // array of ("classname" => array of "parentclass")
$aCache['m_aParentClasses'] = self::$m_aParentClasses; // array of ("classname" => array of "parentclass")
$aCache['m_aChildClasses'] = self::$m_aChildClasses; // array of ("classname" => array of "childclass")
$aCache['m_aClassParams'] = self::$m_aClassParams; // array of ("classname" => array of class information)
$aCache['m_aAttribDefs'] = self::$m_aAttribDefs; // array of ("classname" => array of attributes)
@@ -6885,6 +6926,22 @@ abstract class MetaModel
return $iCount === 1;
}
public static function GetFinalClassName(string $sClass, int $iKey): string
{
if (MetaModel::IsStandaloneClass($sClass)) {
return $sClass;
}
$sRootClass = MetaModel::GetRootClass($sClass);
$sTable = MetaModel::DBGetTable($sRootClass);
$sKeyCol = MetaModel::DBGetKey($sRootClass);
$sEscapedKey = CMDBSource::Quote($iKey);
$sFinalClassField = Metamodel::DBGetClassField($sRootClass);
$sQuery = "SELECT `{$sFinalClassField}` FROM `{$sTable}` WHERE `{$sKeyCol}` = {$sEscapedKey}";
return CMDBSource::QueryToScalar($sQuery);
}
/**
* Search for the specified class and id. If the object is archived it will be returned anyway (this is for pre-2.4
* module compatibility, see N.1108)

View File

@@ -68,6 +68,8 @@ class PDFBulkExport extends HTMLBulkExport
//page format
$oSelectFormat = SelectUIBlockFactory::MakeForSelectWithLabel("page_size", Dict::S('Core:BulkExport:PDFPageSize'));
$oSelectFormat->SetIsLabelBefore(false);
//$oSelectFormat->AddCSSClass('ibo-input-checkbox');
$oFieldSetFormat->AddSubBlock($oSelectFormat);
$aPossibleFormat = ['A3', 'A4', 'Letter'];
@@ -77,7 +79,10 @@ class PDFBulkExport extends HTMLBulkExport
}
$oFieldSetFormat->AddSubBlock(new Html('</br>'));
$oSelectOrientation = SelectUIBlockFactory::MakeForSelectWithLabel("page_orientation", Dict::S('Core:BulkExport:PDFPageOrientation'));
$oSelectOrientation = SelectUIBlockFactory::MakeForSelectWithLabel("page_orientation",
Dict::S('Core:BulkExport:PDFPageOrientation'));
$oSelectOrientation->SetIsLabelBefore(false);
//$oSelectOrientation->AddCSSClass('ibo-input-checkbox');
$oFieldSetFormat->AddSubBlock($oSelectOrientation);
$aPossibleOrientation = ['P', 'L'];

View File

@@ -256,6 +256,38 @@ abstract class TriggerOnObject extends Trigger
}
}
/**
* Activate trigger based on attribute list given instead of changed attributes
*
* @param array $aContextArgs
* @param array|null $aAttributes if null default to changed attributes
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @since 3.1.1 3.2.0 N°6228
*/
public function DoActivateForSpecificAttributes(array $aContextArgs, ?array $aAttributes)
{
if (isset($aContextArgs['this->object()']))
{
/** @var \DBObject $oObject */
$oObject = $aContextArgs['this->object()'];
if (is_null($aAttributes)) {
$aChanges = $oObject->ListPreviousValuesForUpdatedAttributes();
} else {
$aChanges = array_fill_keys($aAttributes, true);
}
if (false === $this->IsTargetObject($oObject->GetKey(), $aChanges)) {
return;
}
}
parent::DoActivate($aContextArgs);
}
/**
* @param $iObjectId
* @param array $aChanges

View File

@@ -856,6 +856,8 @@ class UserRights
}
/**
* Set the current user (as part of the login process)
*
* @param string $sLogin Login of the concerned user
* @param string $sAuthentication
*
@@ -865,8 +867,6 @@ class UserRights
*/
public static function Login($sLogin, $sAuthentication = 'any')
{
static::Logoff();
$oUser = self::FindUser($sLogin, $sAuthentication);
if (is_null($oUser))
{
@@ -885,6 +885,8 @@ class UserRights
}
/**
* Reset current user and cleanup associated SESSION data
*
* @return void
* @since 3.0.4 3.1.1 3.2.0
*/
@@ -1119,9 +1121,7 @@ class UserRights
}
/**
* Return the current user login or an empty string if nobody connected.
*
* @return string
* @return string connected {@see User} login field value, otherwise empty string
*/
public static function GetUser()
{
@@ -1569,9 +1569,9 @@ class UserRights
/**
* @param string $sClass
* @param int $iActionCode
* @param \DBObjectSet $oInstanceSet
* @param \User $oUser
* @param int $iActionCode see UR_ACTION_* constants
* @param DBObjectSet $oInstanceSet
* @param User $oUser
*
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO|UR_ALLOWED_DEPENDS)
* @throws \CoreException

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants>
</constants>
<classes>

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/3.2.0',
'authent-cas/3.1.1',
array(
// Identification
//

View File

@@ -27,7 +27,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/3.2.0',
'authent-external/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="UserLDAP" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/3.2.0',
'authent-ldap/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<module_parameters>
<parameters id="authent-local" _delta="define">
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$</password_validation.pattern>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/3.2.0',
'authent-local/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<branding>
<themes>
<theme id="darkmoon" _delta="define">

View File

@@ -21,5 +21,5 @@
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'theme:darkmoon' => 'Dark moon',
));
'theme:darkmoon' => 'Dark moon~~',
));

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-darkmoon-theme/3.2.0',
'combodo-backoffice-darkmoon-theme/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="DBToolsMenu" xsi:type="WebPageMenuNode" _delta="define">
<rank>30</rank>

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-db-tools/3.2.0',
'combodo-db-tools/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Attachment" _delta="define">
<parent>DBObject</parent>

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-attachments/3.2.0',
'itop-attachments/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="BackupStatus" xsi:type="WebPageMenuNode" _delta="define">
<rank>50</rank>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-backup/3.2.0',
'itop-backup/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="lnkFunctionalCIToProviderContract" _delta="define">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-cmdb-services/3.2.0',
'itop-bridge-cmdb-services/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="lnkFunctionalCIToTicket" _delta="define">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-cmdb-ticket/3.2.0',
'itop-bridge-cmdb-ticket/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="Rack" _delta="must_exist">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-datacenter-mgmt-services/3.2.0',
'itop-bridge-datacenter-mgmt-services/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="Phone" _delta="must_exist">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-endusers-devices-services/3.2.0',
'itop-bridge-endusers-devices-services/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="SANSwitch" _delta="must_exist">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-storage-mgmt-services/3.2.0',
'itop-bridge-storage-mgmt-services/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants/>
<classes>
<class id="Hypervisor" _delta="must_exist">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-mgmt-services/3.2.0',
'itop-bridge-virtualization-mgmt-services/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="lnkVirtualDeviceToVolume" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-storage/3.2.0',
'itop-bridge-virtualization-storage/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Change" _delta="define">
<parent>Ticket</parent>
@@ -21,7 +21,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
@@ -49,12 +49,20 @@
<value id="approved">approved
<code>approved</code>
<rank>60</rank>
<style><main_color>$ibo-lifecycle-success-state-primary-color</main_color><complementary_color>$ibo-lifecycle-success-state-secondary-color</complementary_color><decoration_classes>fas fa-user-check</decoration_classes></style>
<style>
<main_color>$ibo-lifecycle-success-state-primary-color</main_color>
<complementary_color>$ibo-lifecycle-success-state-secondary-color</complementary_color>
<decoration_classes>fas fa-user-check</decoration_classes>
</style>
</value>
<value id="assigned">assigned
<code>assigned</code>
<rank>40</rank>
<style><main_color>$ibo-lifecycle-neutral-state-primary-color</main_color><complementary_color>$ibo-lifecycle-neutral-state-secondary-color</complementary_color><decoration_classes/></style>
<style>
<main_color>$ibo-lifecycle-neutral-state-primary-color</main_color>
<complementary_color>$ibo-lifecycle-neutral-state-secondary-color</complementary_color>
<decoration_classes/>
</style>
</value>
<value id="closed">
<code>closed</code>
@@ -1288,7 +1296,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2089,7 +2097,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3095,7 +3103,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3793,7 +3801,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<style>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt-itil/3.2.0',
'itop-change-mgmt-itil/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Change" _delta="define">
<parent>Ticket</parent>
@@ -21,7 +21,7 @@
<attribute id="ref"/>
</attributes>
<complementary_attributes>
<attribute id="title"/>
<attribute id="title"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt/3.2.0',
'itop-change-mgmt/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="FunctionalCI" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -15,7 +15,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -272,7 +272,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
@@ -530,8 +530,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -702,8 +702,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -992,8 +992,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="networkdevicetype_name"/>
<attribute id="organization_name"></attribute>
<attribute id="networkdevicetype_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -1293,8 +1293,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -1621,7 +1621,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
@@ -1797,7 +1797,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
@@ -1943,7 +1943,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>
@@ -2145,7 +2145,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2299,7 +2299,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2453,7 +2453,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2607,7 +2607,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2740,7 +2740,7 @@
<attribute id="system_name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -2872,8 +2872,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="middleware_name"/>
<attribute id="organization_name"></attribute>
<attribute id="middleware_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3011,8 +3011,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="dbserver_name"/>
<attribute id="organization_name"></attribute>
<attribute id="dbserver_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3148,8 +3148,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="webserver_name"/>
<attribute id="organization_name"></attribute>
<attribute id="webserver_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3304,8 +3304,8 @@
<attribute id="version"/>
</attributes>
<complementary_attributes>
<attribute id="vendor"/>
<attribute id="type"/>
<attribute id="vendor"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -3782,7 +3782,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -4260,6 +4260,7 @@
<rank>70</rank>
</item>
</items>
</summary>
</presentation>
</class>
@@ -4371,7 +4372,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="osfamily_name"/>
<attribute id="osfamily_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -4560,8 +4561,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="brand_name"/>
<attribute id="type"/>
<attribute id="brand_name"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -5424,8 +5425,8 @@
<attribute id="ip_mask"/>
</attributes>
<complementary_attributes>
<attribute id="org_name"/>
<attribute id="subnet_name"/>
<attribute id="org_name"></attribute>
<attribute id="subnet_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -5648,7 +5649,7 @@
<attribute id="vlan_tag"/>
</attributes>
<complementary_attributes>
<attribute id="org_name"/>
<attribute id="org_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -5941,7 +5942,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="ipaddress"/>
<attribute id="ipaddress"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -6830,8 +6831,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="owner_name"/>
<attribute id="type"/>
<attribute id="owner_name"></attribute>
<attribute id="type"></attribute>
</complementary_attributes>
</naming>
<fields_semantic>

View File

@@ -28,17 +28,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Relation:impacts/Description' => 'Prvky ovlivněné objektem',
'Relation:impacts/DownStream' => 'Dopad na',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Závislost na',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
'Relation:impacts/Description' => 'Prvky ovlivněné objektem',
'Relation:impacts/DownStream' => 'Dopad na',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Závislost na',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
// Legacy entries
'Relation:depends on/Description' => 'Prvky ovlivňující objekt',
'Relation:depends on/DownStream' => 'Závislost na',
'Relation:depends on/UpStream' => 'Dopad na',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Závislost na',
'Relation:depends on/UpStream' => 'Dopad na',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -21,17 +21,18 @@
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Relation:impacts/Description' => 'Elementer berørt af ...',
'Relation:impacts/DownStream' => 'Påvrikning ...',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Afhænger af ...',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
'Relation:impacts/Description' => 'Elementer berørt af ...',
'Relation:impacts/DownStream' => 'Påvrikning ...',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Afhænger af ...',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
// Legacy entries
'Relation:depends on/Description' => 'Elementer, som afhænger af dette element',
'Relation:depends on/DownStream' => 'Afhænger af ...',
'Relation:depends on/UpStream' => 'Påvirker ...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Afhænger af ...',
'Relation:depends on/UpStream' => 'Påvirker ...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -23,18 +23,18 @@
*
*/
Dict::Add('DE DE', 'German', 'Deutsch', array(
'Relation:impacts/Description' => 'Elemente betroffen von',
'Relation:impacts/DownStream' => 'Auswirkung ...',
'Relation:impacts/DownStream+' => 'Elemente betroffen von',
'Relation:impacts/UpStream' => 'Hängt ab von ...',
'Relation:impacts/UpStream+' => 'Betroffene Elemente',
'Relation:impacts/Description' => 'Elemente betroffen von',
'Relation:impacts/DownStream' => 'Auswirkung ...',
'Relation:impacts/DownStream+' => 'Elemente betroffen von',
'Relation:impacts/UpStream' => 'Hängt ab von ...',
'Relation:impacts/UpStream+' => 'Betroffene Elemente',
// Legacy entries
'Relation:depends on/Description' => 'Elemente, von denen dieses Element abhängt.',
'Relation:depends on/DownStream' => 'Hängt ab von ...',
'Relation:depends on/UpStream' => 'Wirkt auf ...',
'Relation:impacts/LoadData' => 'Daten laden',
'Relation:impacts/FilteredData' => 'Daten sind über den Tab "Grafische Ansicht" gefiltert',
'Relation:impacts/NoFilteredData' => 'Bitte wählen Sie Objekte im Tab "Grafische Ansicht"',
'Relation:depends on/DownStream' => 'Hängt ab von ...',
'Relation:depends on/UpStream' => 'Wirkt auf ...',
'Relation:impacts/LoadData' => 'Daten laden',
'Relation:impacts/FilteredData' => 'Daten sind über den Tab "Grafische Ansicht" gefiltert',
'Relation:impacts/NoFilteredData' => 'Bitte wählen Sie Objekte ~~',
));

View File

@@ -27,17 +27,18 @@
//
Dict::Add('EN US', 'English', 'English', array(
'Relation:impacts/Description' => 'Elements impacted by',
'Relation:impacts/DownStream' => 'Impacts...',
'Relation:impacts/DownStream+' => 'Elements impacted by',
'Relation:impacts/UpStream' => 'Depends on......',
'Relation:impacts/UpStream+' => 'Elements impacting',
'Relation:impacts/Description' => 'Elements impacted by',
'Relation:impacts/DownStream' => 'Impacts...',
'Relation:impacts/DownStream+' => 'Elements impacted by',
'Relation:impacts/UpStream' => 'Depends on......',
'Relation:impacts/UpStream+' => 'Elements impacting',
// Legacy entries
'Relation:depends on/Description' => 'Elements impacting',
'Relation:depends on/DownStream' => 'Depends on...',
'Relation:depends on/UpStream' => 'Impacts...',
'Relation:depends on/DownStream' => 'Depends on...',
'Relation:depends on/UpStream' => 'Impacts...',
'Relation:impacts/LoadData' => 'Load data',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag',
'Relation:impacts/NoFilteredData' => 'please select objects and load data',
'Relation:impacts/FilteredData' => 'Filtered data',
));

View File

@@ -27,17 +27,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Relation:impacts/Description' => 'Elementos Impactados por',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/DownStream+' => 'Elementos Impactados por',
'Relation:impacts/UpStream' => 'Depende de...',
'Relation:impacts/UpStream+' => 'Elementos de los cuales depende',
'Relation:impacts/Description' => 'Elementos Impactados por',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/DownStream+' => 'Elementos Impactados por',
'Relation:impacts/UpStream' => 'Depende de...',
'Relation:impacts/UpStream+' => 'Elementos de los cuales depende',
// Legacy entries
'Relation:depends on/Description' => 'Elementos de los cuales depende',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -23,17 +23,18 @@
// Class: Organization
//
Dict::Add('FR FR', 'French', 'Français', array(
'Relation:impacts/Description' => 'Eléments impactés par',
'Relation:impacts/DownStream' => 'Impacte...',
'Relation:impacts/DownStream+' => 'Eléments impactés par',
'Relation:impacts/UpStream' => 'Dépend de...',
'Relation:impacts/UpStream+' => 'Eléments dont dépend',
'Relation:impacts/Description' => 'Eléments impactés par',
'Relation:impacts/DownStream' => 'Impacte...',
'Relation:impacts/DownStream+' => 'Eléments impactés par',
'Relation:impacts/UpStream' => 'Dépend de...',
'Relation:impacts/UpStream+' => 'Eléments dont dépend',
// Legacy entries
'Relation:depends on/Description' => 'Eléments dont dépend',
'Relation:depends on/DownStream' => 'Dépend de...',
'Relation:depends on/UpStream' => 'Impacte...',
'Relation:impacts/LoadData' => 'Charger les données',
'Relation:impacts/NoFilteredData' => 'Veuillez sélectionner des objets dans l\'onglet Graph',
'Relation:depends on/DownStream' => 'Dépend de...',
'Relation:depends on/UpStream' => 'Impacte...',
'Relation:impacts/LoadData' => 'Charger les données',
'Relation:impacts/NoFilteredData' => 'Veuillez sélectionner des objets et lancer le chargement des données',
'Relation:impacts/FilteredData' => 'Données filtrées',
));

View File

@@ -20,17 +20,18 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Relation:impacts/Description' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/DownStream' => 'Hatás',
'Relation:impacts/DownStream+' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/UpStream' => 'Függőségek',
'Relation:impacts/UpStream+' => 'Konfigurációs elemtől függnek',
'Relation:impacts/Description' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/DownStream' => 'Hatás',
'Relation:impacts/DownStream+' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/UpStream' => 'Függőségek',
'Relation:impacts/UpStream+' => 'Konfigurációs elemtől függnek',
// Legacy entries
'Relation:depends on/Description' => 'Konfigurációs elemtől függnek',
'Relation:depends on/DownStream' => 'Függőségek',
'Relation:depends on/UpStream' => 'Hatások',
'Relation:impacts/LoadData' => 'Adat betöltés',
'Relation:impacts/NoFilteredData' => 'kérjük, válassza ki az objektumokat a grafikus nézetben',
'Relation:depends on/DownStream' => 'Függőségek',
'Relation:depends on/UpStream' => 'Hatások',
'Relation:impacts/LoadData' => 'Adat betöltés',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -20,17 +20,18 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Relation:impacts/Description' => 'Elementi impattati da...',
'Relation:impacts/DownStream' => 'Impatto...',
'Relation:impacts/DownStream+' => 'Elementi impattati da...',
'Relation:impacts/UpStream' => 'Dipende da...',
'Relation:impacts/UpStream+' => 'Elementi di questo elemento dipende da',
'Relation:impacts/Description' => 'Elementi impattati da...',
'Relation:impacts/DownStream' => 'Impatto...',
'Relation:impacts/DownStream+' => 'Elementi impattati da...',
'Relation:impacts/UpStream' => 'Dipende da...',
'Relation:impacts/UpStream+' => 'Elementi di questo elemento dipende da',
// Legacy entries
'Relation:depends on/Description' => 'Elementi di questo elemento dipende da',
'Relation:depends on/DownStream' => 'Dipende da...',
'Relation:depends on/UpStream' => 'Impatto...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Dipende da...',
'Relation:depends on/UpStream' => 'Impatto...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -20,17 +20,18 @@
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Relation:impacts/Description' => 'インパクトを受ける要素',
'Relation:impacts/DownStream' => 'インパクト...',
'Relation:impacts/DownStream+' => 'インパクトを受ける要素',
'Relation:impacts/UpStream' => '依存...',
'Relation:impacts/UpStream+' => 'この要素が依存している要素',
'Relation:impacts/Description' => 'インパクトを受ける要素',
'Relation:impacts/DownStream' => 'インパクト...',
'Relation:impacts/DownStream+' => 'インパクトを受ける要素',
'Relation:impacts/UpStream' => '依存...',
'Relation:impacts/UpStream+' => 'この要素が依存している要素',
// Legacy entries
'Relation:depends on/Description' => 'この要素が依存している要素',
'Relation:depends on/DownStream' => '依存...',
'Relation:depends on/UpStream' => 'インパクト...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => '依存...',
'Relation:depends on/UpStream' => 'インパクト...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -32,17 +32,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Relation:impacts/Description' => 'Elementen met impact van',
'Relation:impacts/DownStream' => 'Impact op...',
'Relation:impacts/DownStream+' => 'Elementen geïmpacteerd door',
'Relation:impacts/UpStream' => 'Is afhankelijk van...',
'Relation:impacts/UpStream+' => 'Elementen met impact op',
'Relation:impacts/Description' => 'Elementen met impact van',
'Relation:impacts/DownStream' => 'Impact op...',
'Relation:impacts/DownStream+' => 'Elementen geïmpacteerd door',
'Relation:impacts/UpStream' => 'Is afhankelijk van...',
'Relation:impacts/UpStream+' => 'Elementen met impact op',
// Legacy entries
'Relation:depends on/Description' => 'Elementen afhankelijk van',
'Relation:depends on/DownStream' => 'Is afhankelijk van...',
'Relation:depends on/UpStream' => 'Impact op...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Is afhankelijk van...',
'Relation:depends on/UpStream' => 'Impact op...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -25,17 +25,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('PL PL', 'Polish', 'Polski', array(
'Relation:impacts/Description' => 'Elementy, na które ma wpływ',
'Relation:impacts/DownStream' => 'Wpływa na...',
'Relation:impacts/DownStream+' => 'Elementy, na które ma wpływ',
'Relation:impacts/UpStream' => 'Zależy od......',
'Relation:impacts/UpStream+' => 'Elementy wpływające',
'Relation:impacts/Description' => 'Elementy, na które ma wpływ',
'Relation:impacts/DownStream' => 'Wpływa na...',
'Relation:impacts/DownStream+' => 'Elementy, na które ma wpływ',
'Relation:impacts/UpStream' => 'Zależy od......',
'Relation:impacts/UpStream+' => 'Elementy wpływające',
// Legacy entries
'Relation:depends on/Description' => 'Elementy wpływające',
'Relation:depends on/DownStream' => 'Zależy od...',
'Relation:depends on/UpStream' => 'Wpływa na...',
'Relation:impacts/LoadData' => 'Załaduj dane',
'Relation:impacts/NoFilteredData' => 'proszę wybrać obiekty w widoku graficznym',
'Relation:depends on/DownStream' => 'Zależy od...',
'Relation:depends on/UpStream' => 'Wpływa na...',
'Relation:impacts/LoadData' => 'Załaduj dane',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -26,17 +26,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Relation:impacts/Description' => 'Elementos impactados por',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/DownStream+' => 'Elementos impactados por',
'Relation:impacts/UpStream' => 'Depende de...',
'Relation:impacts/UpStream+' => 'Elementos estes, que dependem deste elemento',
'Relation:impacts/Description' => 'Elementos impactados por',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/DownStream+' => 'Elementos impactados por',
'Relation:impacts/UpStream' => 'Depende de...',
'Relation:impacts/UpStream+' => 'Elementos estes, que dependem deste elemento',
// Legacy entries
'Relation:depends on/Description' => 'Elementos estes, que dependem deste elemento',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -13,17 +13,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('RU RU', 'Russian', 'Русский', array(
'Relation:impacts/Description' => 'Элементы, на которые влияет',
'Relation:impacts/DownStream' => 'Влияет на...',
'Relation:impacts/DownStream+' => 'Элементы, на которые влияет',
'Relation:impacts/UpStream' => 'Зависит от...',
'Relation:impacts/UpStream+' => 'Элементы, от которых зависит',
'Relation:impacts/Description' => 'Элементы, на которые влияет',
'Relation:impacts/DownStream' => 'Влияет на...',
'Relation:impacts/DownStream+' => 'Элементы, на которые влияет',
'Relation:impacts/UpStream' => 'Зависит от...',
'Relation:impacts/UpStream+' => 'Элементы, от которых зависит',
// Legacy entries
'Relation:depends on/Description' => 'Элементы, от которых зависит',
'Relation:depends on/DownStream' => 'Зависит от...',
'Relation:depends on/UpStream' => 'Влияет на...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Зависит от...',
'Relation:depends on/UpStream' => 'Влияет на...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -25,17 +25,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Relation:impacts/Description' => 'Prvky zasiahnuté',
'Relation:impacts/DownStream' => 'Impacts...~~',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Depends on......~~',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
'Relation:impacts/Description' => 'Prvky zasiahnuté',
'Relation:impacts/DownStream' => 'Impacts...~~',
'Relation:impacts/DownStream+' => 'Elements impacted by~~',
'Relation:impacts/UpStream' => 'Depends on......~~',
'Relation:impacts/UpStream+' => 'Elements impacting~~',
// Legacy entries
'Relation:depends on/Description' => 'Prvky, od ktorých závisí tento prvok',
'Relation:depends on/DownStream' => 'Depends on...~~',
'Relation:depends on/UpStream' => 'Impacts...~~',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Depends on...~~',
'Relation:depends on/UpStream' => 'Impacts...~~',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -27,17 +27,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Relation:impacts/Description' => 'Etkilenen kalemler',
'Relation:impacts/DownStream' => 'Etkiler...',
'Relation:impacts/DownStream+' => 'Etkilenen kalemler',
'Relation:impacts/UpStream' => 'Bağımlı olanlar...',
'Relation:impacts/UpStream+' => 'Bu kaleme bağımlı olan kalemler',
'Relation:impacts/Description' => 'Etkilenen kalemler',
'Relation:impacts/DownStream' => 'Etkiler...',
'Relation:impacts/DownStream+' => 'Etkilenen kalemler',
'Relation:impacts/UpStream' => 'Bağımlı olanlar...',
'Relation:impacts/UpStream+' => 'Bu kaleme bağımlı olan kalemler',
// Legacy entries
'Relation:depends on/Description' => 'Bu kaleme bağımlı olan kalemler',
'Relation:depends on/DownStream' => 'Bağımlı olanlar...',
'Relation:depends on/UpStream' => 'Etkiledikleri...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => 'Bağımlı olanlar...',
'Relation:depends on/UpStream' => 'Etkiledikleri...',
'Relation:impacts/LoadData' => 'Load data~~',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -25,17 +25,18 @@
//////////////////////////////////////////////////////////////////////
//
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Relation:impacts/Description' => '被影响的元素',
'Relation:impacts/DownStream' => '影响...',
'Relation:impacts/DownStream+' => '被影响的元素',
'Relation:impacts/UpStream' => '依赖于...',
'Relation:impacts/UpStream+' => '此元素依赖的元素...',
'Relation:impacts/Description' => '被影响的元素',
'Relation:impacts/DownStream' => '影响...',
'Relation:impacts/DownStream+' => '被影响的元素',
'Relation:impacts/UpStream' => '依赖于...',
'Relation:impacts/UpStream+' => '此元素依赖的元素...',
// Legacy entries
'Relation:depends on/Description' => '此元素依赖的元素...',
'Relation:depends on/DownStream' => '依赖于...',
'Relation:depends on/UpStream' => '影响...',
'Relation:impacts/LoadData' => '加载数据',
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
'Relation:depends on/DownStream' => '依赖于...',
'Relation:depends on/UpStream' => '影响...',
'Relation:impacts/LoadData' => '加载数据',
'Relation:impacts/NoFilteredData' => 'please select objects and load data~~',
'Relation:impacts/FilteredData' => 'Filtered data~~',
));

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config-mgmt/3.2.0',
'itop-config-mgmt/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="ConfigEditor" xsi:type="WebPageMenuNode" _delta="define">
<rank>10</rank>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config/3.2.0',
'itop-config/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="iTopUpdate" xsi:type="WebPageMenuNode" _delta="define">
<rank>60</rank>

View File

@@ -68,47 +68,47 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'iTopUpdate:UI:CanCoreUpdate:Failed' => 'Fájlrendszer ellenőrzése sikertelen',
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Az alkalmazás frissíthető',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Az alkalmazás nem frissíthető: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Figyelem: alkalmazás frissítés sikertelen lehet: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>SNéhány módosított fájlt észleltünk</b>, a részleges frissítés nem hajtható végre.</br>Kövesse a <a target="_blank" href="%2$s"> eljárást</a> az iTop manuális frissítéséhez. Az alkalmazás frissítéséhez a <a href="%1$s">setup</a> parancsot kell használnia.',
'iTopUpdate:UI:CheckInProgress' => 'Kérjük, várjon az integritás ellenőrzés alatt',
'iTopUpdate:UI:SetupLaunch' => 'Launch '.ITOP_APPLICATION_SHORT.' Setup~~',
'iTopUpdate:UI:SetupLaunchConfirm' => 'This will launch '.ITOP_APPLICATION_SHORT.' setup, are you sure?~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Figyelem: alkalmazás frissítés sikertelen lehet: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>SNéhány módosított fájlt észleltünk</b>, a részleges frissítés nem hajtható végre.</br>Kövesse a <a target="_blank" href="%2$s"> eljárást</a> az iTop manuális frissítéséhez. Az alkalmazás frissítéséhez a <a href="%1$s">setup</a> parancsot kell használnia.',
'iTopUpdate:UI:CheckInProgress' => 'Kérjük, várjon az integritás ellenőrzés alatt',
'iTopUpdate:UI:SetupLaunch' => 'Launch '.ITOP_APPLICATION_SHORT.' Setup~~',
'iTopUpdate:UI:SetupLaunchConfirm' => 'This will launch '.ITOP_APPLICATION_SHORT.' setup, are you sure?~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Készen állunk',
'iTopUpdate:UI:SetupMessage:EnterMaintenance' => 'Karbantartási módba lépés',
'iTopUpdate:UI:SetupMessage:Backup' => 'Adatbázis biztonsági mentése',
'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Alkalmazás fájlok archiválása',
'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Új fájlverziók másolása',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Alkalmazásfrissítés ellenőrzése',
'iTopUpdate:UI:SetupMessage:Compile' => 'Az alkalmazás és az adatbázis frissítése',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Adatbázis frissítés',
'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Kilépés a karbantartási módból',
'iTopUpdate:UI:SetupMessage:UpdateDone' => 'A frissítés befejeződött',
'iTopUpdate:UI:SetupMessage:Ready' => 'Készen állunk',
'iTopUpdate:UI:SetupMessage:EnterMaintenance' => 'Karbantartási módba lépés',
'iTopUpdate:UI:SetupMessage:Backup' => 'Adatbázis biztonsági mentése',
'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Alkalmazás fájlok archiválása',
'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Új fájlverziók másolása',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Alkalmazásfrissítés ellenőrzése',
'iTopUpdate:UI:SetupMessage:Compile' => 'Az alkalmazás és az adatbázis frissítése',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Adatbázis frissítés',
'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Kilépés a karbantartási módból',
'iTopUpdate:UI:SetupMessage:UpdateDone' => 'A frissítés befejeződött',
// Errors
'iTopUpdate:Error:MissingFunction' => 'Lehetetlen elindítani a frissítést, hiányzó funkció',
'iTopUpdate:Error:MissingFile' => 'Hiányzó fájl: %1$s',
'iTopUpdate:Error:CorruptedFile' => 'A %1$s fájl sérült',
'iTopUpdate:Error:BadFileFormat' => 'A frissítési fájl nem zip fájl',
'iTopUpdate:Error:BadFileContent' => 'A frissítési fájl nem alkalmazás archívum',
'iTopUpdate:Error:BadItopProduct' => 'A frissítési fájl nem kompatibilis az alkalmazással',
'iTopUpdate:Error:Copy' => 'Hiba: \'%1$s\' nem másolható \'%2$s\' -ba',
'iTopUpdate:Error:FileNotFound' => 'Nincs meg a fájl',
'iTopUpdate:Error:NoFile' => 'Nincs fájl megadva',
'iTopUpdate:Error:InvalidToken' => 'Érvénytelen token',
'iTopUpdate:Error:UpdateFailed' => 'Frissítés sikertelen',
'iTopUpdate:Error:FileUploadMaxSizeTooSmall' => 'A feltöltés maximális mérete túl kicsinek tűnik a frissítéshez. Kérjük, módosítsa a PHP konfigurációt.',
'iTopUpdate:UI:RestoreArchive' => 'Visszaállíthatja az alkalmazást a \'%1$s\' archívumból',
'iTopUpdate:UI:RestoreBackup' => 'Visszaállíthatja az adatbázist a \'%1$s\' archívumból',
'iTopUpdate:UI:UpdateDone' => 'Frissítés sikeres',
'Menu:iTopUpdate' => 'Alkalmazás frissítés',
'Menu:iTopUpdate+' => 'Alkalmazás frissítés',
'iTopUpdate:Error:MissingFunction' => 'Lehetetlen elindítani a frissítést, hiányzó funkció',
'iTopUpdate:Error:MissingFile' => 'Hiányzó fájl: %1$s',
'iTopUpdate:Error:CorruptedFile' => 'A %1$s fájl sérült',
'iTopUpdate:Error:BadFileFormat' => 'A frissítési fájl nem zip fájl',
'iTopUpdate:Error:BadFileContent' => 'A frissítési fájl nem alkalmazás archívum',
'iTopUpdate:Error:BadItopProduct' => 'A frissítési fájl nem kompatibilis az alkalmazással',
'iTopUpdate:Error:Copy' => 'Hiba: \'%1$s\' nem másolható \'%2$s\' -ba',
'iTopUpdate:Error:FileNotFound' => 'Nincs meg a fájl',
'iTopUpdate:Error:NoFile' => 'Nincs fájl megadva',
'iTopUpdate:Error:InvalidToken' => 'Érvénytelen token',
'iTopUpdate:Error:UpdateFailed' => 'Frissítés sikertelen',
'iTopUpdate:Error:FileUploadMaxSizeTooSmall' => 'A feltöltés maximális mérete túl kicsinek tűnik a frissítéshez. Kérjük, módosítsa a PHP konfigurációt.',
'iTopUpdate:UI:RestoreArchive' => 'Visszaállíthatja az alkalmazást a \'%1$s\' archívumból',
'iTopUpdate:UI:RestoreBackup' => 'Visszaállíthatja az adatbázist a \'%1$s\' archívumból',
'iTopUpdate:UI:UpdateDone' => 'Frissítés sikeres',
'Menu:iTopUpdate' => 'Alkalmazás frissítés',
'Menu:iTopUpdate+' => 'Alkalmazás frissítés',
// Missing itop entries
// Missing itop entries
'Class:ModuleInstallation/Attribute:installed' => 'Telepítve ',
'Class:ModuleInstallation/Attribute:name' => 'Név',
'Class:ModuleInstallation/Attribute:version' => 'Verzió',
'Class:ModuleInstallation/Attribute:name' => 'Név',
'Class:ModuleInstallation/Attribute:version' => 'Verzió',
'Class:ModuleInstallation/Attribute:comment' => 'Megjegyzés',
));

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-core-update/3.2.0',
'itop-core-update/3.1.1',
[
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Rack" _delta="define">
<parent>PhysicalDevice</parent>
@@ -15,7 +15,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
@@ -213,7 +213,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
<attribute id="rack_name"/>
</complementary_attributes>
@@ -419,7 +419,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
@@ -585,7 +585,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
</complementary_attributes>
</naming>
@@ -754,7 +754,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"/>
<attribute id="rack_name"/>
<attribute id="powerstart_name"/>

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-datacenter-mgmt/3.2.0',
'itop-datacenter-mgmt/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="TelephonyCI" _delta="define">
<parent>PhysicalDevice</parent>
@@ -15,7 +15,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
@@ -173,7 +173,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
@@ -343,7 +343,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
@@ -533,7 +533,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
<attribute id="phonenumber"/>
</complementary_attributes>
</naming>
@@ -703,7 +703,7 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="organization_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -869,8 +869,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -1139,8 +1139,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>
@@ -1339,8 +1339,8 @@
<attribute id="name"/>
</attributes>
<complementary_attributes>
<attribute id="organization_name"/>
<attribute id="location_name"/>
<attribute id="organization_name"></attribute>
<attribute id="location_name"></attribute>
</complementary_attributes>
</naming>
<style>

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-endusers-devices/3.2.0',
'itop-endusers-devices/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="FAQ" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-faq-light/3.2.0',
'itop-faq-light/3.1.1',
array(
// Identification
//

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
</itop_design>

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-files-information/3.2.0',
'itop-files-information/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Ticket">
<methods>

View File

@@ -6,7 +6,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-full-itil/3.2.0',
'itop-full-itil/3.1.1',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants>
</constants>
<classes>

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-hub-connector/3.2.0',
'itop-hub-connector/3.1.1',
array(
// Identification
//

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