Compare commits

..

55 Commits

Author SHA1 Message Date
Anne-Cath
c347b961b1 9622 - Error in the user story life cycle 2026-05-21 10:31:49 +02:00
Benjamin DALSASS
48e6203869 N°9044 - Application token and Impersonate (Log in as this user) 2026-05-13 11:14:58 +02:00
jf-cbd
ab6c50d52d 👷 Update action.yml 2026-05-07 16:24:40 +02:00
jf-cbd
51e7ef32dc 👷 Update action.yml 2026-05-07 16:23:11 +02:00
Molkobain
5ac675a587 Merge remote-tracking branch 'origin/support/3.2' into develop 2026-05-06 14:53:01 +02:00
Molkobain
769afb2715 Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-05-06 14:52:10 +02:00
Molkobain
b529a61bc5 Fix PHP code styles 2026-05-06 13:50:58 +02:00
v-dumas
c501280f53 N°7771 - Align Dataflow option with product-itop installation.xml 2026-05-06 11:55:25 +02:00
Vincent Dumas
e662370c32 N°7771 New module for DataFlow management (#905) 2026-05-06 11:28:21 +02:00
Molkobain
3c39c6d8d1 Merge remote-tracking branch 'origin/support/3.2' into develop 2026-05-06 11:19:30 +02:00
Molkobain
a7d0262b21 Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-05-06 11:18:36 +02:00
Molkobain
c56617abf5 N°8579 - Update PHPDoc 2026-05-06 10:55:39 +02:00
v-dumas
ff94639a61 N°9471 - Rack can contain Enclosure 2026-05-05 10:46:34 +02:00
Molkobain
7676115725 N°9584 - Fix "Unable to connect with STARTTLS" error when sending emails (#901)
* N°9584 - Fix "Unable to connect with STARTTLS" error when sending emails

* N°9584 - Refactor EMailSymfony transport to add unit tests
2026-05-05 09:51:09 +02:00
Molkobain
43ceaeb5a3 Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-05-04 16:42:30 +02:00
Håkon Harnes
7cac280b83 N°9574 - Fix CKEditor CSS displayed as part of the email message in Gmail (#898)
* fix(email): generate plain text before inlining HTML CSS

* N°9574 - Add unit tests

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2026-05-04 16:33:38 +02:00
Stephen Abello
8de5c2525b Merge branch 'support/3.2' into develop
# Conflicts:
#	css/setup.css
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.css
#	package-lock.json
2026-04-29 17:10:05 +02:00
Stephen Abello
de4ec9d9ce N°9128 - Update CKEditor5 to v48 (#896)
* N°9128 - Update CKEditor5 to v48

* Move some CSS vars to ckeditor, align variable overload in portal and backoffice

* Add specifics to 3.2 portal

* Update CKEditor5 build files

* Update scssphp with patched version that handles pseudo selectors and attribute selectors

* Update scssphp patched version to fix missing $this

* Fix translations specific language file import

* Remove unused maximize parameters

* Update CKEditor5 build files

* Fix font size/color for 3.2 portal

* Avoid CKEditor styles from bleeding into fields
2026-04-29 16:56:20 +02:00
Molkobain
ea35ad48d2 📝 Update itop-version-hisotry.md and fix README.md link 2026-04-29 16:49:11 +02:00
Molkobain
90b7c3ac6a Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	.doc/itop-version-history.md
2026-04-29 16:48:34 +02:00
Molkobain
8f2c990065 📝 Fix itop-version-history.md display due to new branch 2026-04-29 16:47:03 +02:00
Benjamin Dalsass
03437c3453 📝 Restore itop-version-history.md on support/3.2 branch 2026-04-29 16:37:38 +02:00
Purple Grape
1113788d84 N°9518 - fix 2 typo bug (#882) 2026-04-29 14:29:24 +02:00
Benjamin DALSASS
eee57b25fa N°8699 - attributedef.class.inc.php to PSR4
- fix CI failed
2026-04-29 09:54:16 +02:00
Benjamin Dalsass
7be19c713b N°8699 - attributedef.class.inc.php to PSR4 - fixs (#890) 2026-04-28 10:46:09 +02:00
Lenaick
befe294986 N°3472 - Refactor LDAP debug level handling to ensure proper logging during connection attempts (#892) 2026-04-27 14:26:38 +02:00
lenaick.moreira
d271dda54f N°9341 - Update Turbo third-party lib to v8.0.21 min. to fix security issue 2026-04-27 12:21:17 +02:00
Molkobain
04bb07fc59 Merge remote-tracking branch 'origin/support/3.2' into develop 2026-04-27 11:41:27 +02:00
Molkobain
33a51b47bf N°9549 - Fix emails with mime type different than text/plain or text/html are no longer displayed correctly (#895)
* N°9549 - Fix emails with mime type different than text/plain or text/html are no longer displayed correctly

* N°9549 - Fix mime type comparisons to use the primary mime type instead of the whole string
2026-04-27 11:31:56 +02:00
jf-cbd
1772a9f73b 📝 Improve issues template 2026-04-24 16:56:38 +02:00
jf-cbd
ed45c3bbb0 📝 Improve issues template 2026-04-24 15:18:03 +02:00
jf-cbd
a49ebd531e Make issues forms despite unformal rules (.tar.gz is supposed to be supported but is not, etc.) 2026-04-23 17:13:08 +02:00
Molkobain
c5ca5f9176 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	core/event.class.inc.php
2026-04-23 15:54:17 +02:00
Molkobain
e768cc1c0c N°9537 - Update "details" zlist on EventNotificationEmail to display cc and cci attributes 2026-04-23 15:49:30 +02:00
jf-cbd
12b1339542 Update CONTRIBUTING.md and reduce size of related picture 2026-04-23 14:57:26 +02:00
jf-cbd
278254c955 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	.github/pull_request_template.md
#	CONTRIBUTING.md
2026-04-23 14:43:38 +02:00
jf-cbd
f6741a6306 Update contributions guidelines (#888) 2026-04-23 13:48:23 +02:00
jf-cbd
19386191aa N°8397 - remove empty file (probably re-added by mistake in develop in a merge conflict) 2026-04-22 15:32:43 +02:00
Stephen Abello
d76752a988 N°9491 - Rename new enclosure icon 2026-04-22 14:11:56 +02:00
Vincent Dumas
8c2c4e5ff0 N°9491 - Add OS Family on OS Patch and OS Licence (#886)
* N°9492 - Add icon on OS Family, OS Version and IOS Version classes
* Change enclosure icon
* Update NL dictionnaries
  * Update datamodels/2.x/itop-config-mgmt/dictionaries/nl.dict.itop-config-mgmt.php
  * Update datamodels/2.x/itop-config-mgmt/dictionaries/nl.dict.itop-config-mgmt.php
  * Update datamodels/2.x/itop-config-mgmt/dictionaries/de.dict.itop-config-mgmt.php
  * Update datamodels/2.x/itop-config-mgmt/dictionaries/cs.dict.itop-config-mgmt.php
  * Update datamodels/2.x/itop-config-mgmt/dictionaries/da.dict.itop-config-mgmt.php
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
2026-04-22 09:56:12 +02:00
Stephen Abello
4bc28ea38a 💚 Fix CI by recompiling setup.css 2026-04-22 09:05:23 +02:00
jf-cbd
805087a01b N°9319 increase php min. version to 8.2 (#887)
* Update minimum PHP version to 8.2
* Fix previous wrong resolution of merge conflict
2026-04-20 14:47:44 +02:00
Stephen Abello
1ec8aca12d Remove ~~ from French dict entry 2026-04-20 10:23:03 +02:00
Molkobain
f439490bfc Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	approot.inc.php
#	core/config.class.inc.php
#	datamodels/2.x/authent-cas/module.authent-cas.php
#	datamodels/2.x/authent-external/module.authent-external.php
#	datamodels/2.x/authent-ldap/module.authent-ldap.php
#	datamodels/2.x/authent-local/module.authent-local.php
#	datamodels/2.x/combodo-backoffice-darkmoon-theme/module.combodo-backoffice-darkmoon-theme.php
#	datamodels/2.x/combodo-backoffice-fullmoon-high-contrast-theme/module.combodo-backoffice-fullmoon-high-contrast-theme.php
#	datamodels/2.x/combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/module.combodo-backoffice-fullmoon-protanopia-deuteranopia-theme.php
#	datamodels/2.x/combodo-backoffice-fullmoon-tritanopia-theme/module.combodo-backoffice-fullmoon-tritanopia-theme.php
#	datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/module.itop-attachments.php
#	datamodels/2.x/itop-backup/module.itop-backup.php
#	datamodels/2.x/itop-bridge-cmdb-services/module.itop-bridge-cmdb-services.php
#	datamodels/2.x/itop-bridge-cmdb-ticket/module.itop-bridge-cmdb-ticket.php
#	datamodels/2.x/itop-bridge-datacenter-mgmt-services/module.itop-bridge-datacenter-mgmt-services.php
#	datamodels/2.x/itop-bridge-endusers-devices-services/module.itop-bridge-endusers-devices-services.php
#	datamodels/2.x/itop-bridge-storage-mgmt-services/module.itop-bridge-storage-mgmt-services.php
#	datamodels/2.x/itop-bridge-virtualization-mgmt-services/module.itop-bridge-virtualization-mgmt-services.php
#	datamodels/2.x/itop-bridge-virtualization-storage/module.itop-bridge-virtualization-storage.php
#	datamodels/2.x/itop-change-mgmt-itil/module.itop-change-mgmt-itil.php
#	datamodels/2.x/itop-change-mgmt/module.itop-change-mgmt.php
#	datamodels/2.x/itop-config-mgmt/module.itop-config-mgmt.php
#	datamodels/2.x/itop-config/module.itop-config.php
#	datamodels/2.x/itop-core-update/module.itop-core-update.php
#	datamodels/2.x/itop-datacenter-mgmt/module.itop-datacenter-mgmt.php
#	datamodels/2.x/itop-endusers-devices/module.itop-endusers-devices.php
#	datamodels/2.x/itop-faq-light/module.itop-faq-light.php
#	datamodels/2.x/itop-files-information/module.itop-files-information.php
#	datamodels/2.x/itop-full-itil/module.itop-full-itil.php
#	datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
#	datamodels/2.x/itop-incident-mgmt-itil/module.itop-incident-mgmt-itil.php
#	datamodels/2.x/itop-knownerror-mgmt/module.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-oauth-client/module.itop-oauth-client.php
#	datamodels/2.x/itop-portal-base/module.itop-portal-base.php
#	datamodels/2.x/itop-portal/module.itop-portal.php
#	datamodels/2.x/itop-problem-mgmt/module.itop-problem-mgmt.php
#	datamodels/2.x/itop-profiles-itil/module.itop-profiles-itil.php
#	datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php
#	datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php
#	datamodels/2.x/itop-service-mgmt-provider/module.itop-service-mgmt-provider.php
#	datamodels/2.x/itop-service-mgmt/module.itop-service-mgmt.php
#	datamodels/2.x/itop-sla-computation/module.itop-sla-computation.php
#	datamodels/2.x/itop-storage-mgmt/module.itop-storage-mgmt.php
#	datamodels/2.x/itop-structure/module.itop-structure.php
#	datamodels/2.x/itop-themes-compat/module.itop-themes-compat.php
#	datamodels/2.x/itop-tickets/module.itop-tickets.php
#	datamodels/2.x/itop-virtualization-mgmt/module.itop-virtualization-mgmt.php
#	datamodels/2.x/itop-welcome-itil/module.itop-welcome-itil.php
#	datamodels/2.x/version.xml
2026-04-20 09:24:02 +02:00
Molkobain
39011faedd Update ITOP_VERSION constant version for 3.2.3 release 2026-04-20 09:17:18 +02:00
Stephen Abello
46f8f5faeb Update modules and constants version for 3.2.3 release 2026-04-17 15:24:10 +02:00
Stephen Abello
170d24d0ad Update licenses for 3.2.3 release 2026-04-17 15:17:55 +02:00
v-dumas
9683b8d96a N°9499 - Ticket ITIL: remove 'request type' from UserRequest details 2026-04-17 09:51:01 +02:00
Molkobain
a6171c896b Merge remote-tracking branch 'origin/support/3.2' into develop 2026-04-17 09:20:18 +02:00
Benjamin DALSASS
89231976f8 Revert N°8638 - Adapt mysqldump calls to follow iTop SSL configuration 2026-04-16 15:00:01 +02:00
Stephen Abello
4e24ac508d Merge branch 'support/3.2' into develop 2026-04-15 17:01:58 +02:00
Molkobain
e1c804139f 👥 Add Lénaick to the sample data, welcome! 🙌 2026-04-15 16:55:19 +02:00
Stephen Abello
f0a95cbb3d N°9447 - Harmonize title and panel logo rules 2026-04-15 16:49:52 +02:00
Stephen Abello
265acb4a1e Merge branch 'support/3.2' into develop
# Conflicts:
#	css/setup.css
2026-04-15 15:16:01 +02:00
Stephen Abello
30f720b9ad N°9447 - Setup logo is repeating vertically (#884) 2026-04-15 15:13:28 +02:00
656 changed files with 26241 additions and 33476 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

View File

@@ -7,7 +7,8 @@
'git4': 'grey',
'git5': 'grey',
'git6': 'grey',
'git7': 'grey'
'git7': 'grey',
'git8': 'grey'
}, 'gitGraph': {'showBranches': true,'mainBranchName': 'develop','rotateCommitLabel': true}} }%%
gitGraph
commit id: "2016-07-06" tag: "2.3.0" type: HIGHLIGHT
@@ -86,24 +87,25 @@ gitGraph
commit id: "2024-01-17a" tag: "2.7.10"
checkout support/3.0
commit id: "2024-01-17b" tag: "3.0.4"
checkout support/2.7
commit id: "2024-09-28" tag: "2.7.11"
checkout support/3.1
commit id: "2024-09-27" tag: "3.1.2"
checkout support/3.2
commit id: "2024-06-25" tag: "3.2.0-beta1" type: REVERSE
commit id: "2024-08-07" tag: "3.2.0"
commit id: "2024-09-13" tag: "3.2.0-2"
checkout support/3.1
commit id: "2024-09-27" tag: "3.1.2"
checkout support/2.7
commit id: "2024-09-28" tag: "2.7.11"
checkout support/2.7
commit id: "2025-02-25" tag: "2.7.12"
commit id: "2025-02-07a" tag: "2.7.12"
checkout support/3.1
commit id: "2025-02-25 " tag: "3.1.3"
commit id: "2025-02-07b" tag: "3.1.3"
checkout support/3.2
commit id: "2025-02-25 " tag: "3.2.1"
commit id: "2025-04-08" tag: "3.2.1-1"
commit id: "2025-08-19" tag: "3.2.2-1"
commit id: "2025-02-07c " tag: "3.2.1"
commit id: "2025-03-31 " tag: "3.2.1-1"
commit id: "2025-07-28 " tag: "3.2.2"
checkout support/2.7
commit id: "2025-10-07" tag: "2.7.13"
commit id: "2025-09-25" tag: "2.7.13"
checkout support/3.2
commit id: "2026-04-27 " tag: "3.2.3"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

60
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: "Bug report"
description: "Report a bug that you identified in iTop"
type: bug
body:
- type: markdown
attributes:
value: |
Please explain why you're creating this issue :
- Are you willing to create a PR for the bug fix ? If so, we'll indicate in the issue if we're interested in it.
- Then, please describe how to reproduce the issue.
- type: dropdown
id: willing_to_pr
attributes:
label: Are you willing to create (at a later stage) a PR for that?
options:
- 'Yes'
- 'No'
validations:
required: true
- type: input
id: itop_version
attributes:
label: iTop version
description: "Complete iTop version (e.g., 3.2.3)"
validations:
required: false
- type: input
id: php_version
attributes:
label: PHP version
description: "Complete PHP version (e.g., 8.4.20)"
validations:
required: false
- type: textarea
id: reproduction_steps
attributes:
label: Reproduction procedure
description: |
Please explain step by step how to reproduce the issue on a standard iTop Community.
If it requires a custom datamodel, provide the minimal XML delta to reproduce it.
placeholder: |
1. First go there
2. Then do that
3. ...
4. Finally, see that... (what is expected and what is actually happening)
validations:
required: false
- type: upload
id: additional_info
attributes:
label: Additional information (if needed)
description: "Add/drag and drop screenshots, logs or any files that can be relevant for your issue."
validations:
required: false
accept: ".png, .jpg, .jpeg, .gif, .webp, .log, .txt, .json, .csv, .xml, .zip"

47
.github/ISSUE_TEMPLATE/enhancement.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: "Enhancement suggestion"
description: "Suggest an improvement to iTop"
type: feature
body:
- type: markdown
attributes:
value: |
Please explain why you're creating this issue :
- Please describe what's your improvement proposition.
- Then tell us if you're willing to create a PR for this enhancement ? If so, we'll indicate in the issue if we're interested in it.
- type: textarea
id: enhancement_details
attributes:
label: Enhancement details
description: |
Please explain what you want to improve, and your proposition to make it better.
If it requires a custom datamodel, provide the minimal XML delta to reproduce it.
validations:
required: false
- type: input
id: itop_version
attributes:
label: iTop version (if appropriate)
description: "Complete iTop version (e.g., 3.2.3)"
validations:
required: false
- type: dropdown
id: willing_to_pr
attributes:
label: Are you willing to create (at a later stage) a PR for that?
options:
- 'Yes'
- 'No'
validations:
required: true
- type: upload
id: additional_info
attributes:
label: Additional information (if needed)
description: "Add/drag and drop screenshots, logs or any files that can be relevant for your issue."
validations:
required: false
accept: ".png, .jpg, .jpeg, .gif, .webp, .log, .txt, .json, .csv, .xml, .zip"

View File

@@ -1,83 +1,81 @@
<!--
IMPORTANT: Before creating your PR, please create an issue first to know if Combodo is interested in your contribution (not needed for translations PR).
Since we may refuse a PR, it's preferable to create an issue first, to avoid spending time coding something that won't be accepted.
IMPORTANT: Please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
Once you've done it, and we confirmed we're interested in it, please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
Any PRs not following the guidelines or with missing information will not be considered.
-->
## Base information
| Question | Answer
|---------------------------------------------------------------|--------
| Related to a SourceForge thread / Another PR / Combodo ticket? | <!-- Put the URL -->
| Type of change? | Bug fix / Enhancement / Translations
| Question | Answer
|----------------------------------------------------------------|--------
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |
| Type of change? | Bug fix / Enhancement / Translations
| Question | Answer |
|---------------------------------------------------------------------------------|--------------------------------------|
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |
| Type of change? | Bug fix / Enhancement / Translations |
## Symptom (bug) / Objective (enhancement)
<!--
If it's a bug
- Explain the symptom in details
- If possible put error messages, logs or screenshots (you can paste image directly in this editor).
If it's an enhancement
- Describe what is blocking you, what is the objective with as much details as possible.
- Describe what is blocking you, what is the objective with as many details as possible.
- Add screenshots if it's related to UI.
-->
## Reproduction procedure (bug)
<!--
Remove this section only if it's NOT a bug.
Otherwise, explain step by step how to reproduce the issue on a standard iTop Community.
Please explain step by step how to reproduce the issue on a standard iTop Community.
If it requires a custom datamodel, provide the minimal XML delta to reproduce it on a standard iTop Community.
-->
1. On iTop x.y.z <!-- Put complete iTop version (eg. 3.1.0-2) -->
2. With PHP x.y.z <!-- Put complete PHP version (eg. 8.1.24) -->
2. First go there
2. Then do that
3. ...
4. Finally, see that...
3. First go there
4. Then do that
5. ...
6. Finally, see that... (what is expected and what is actually happening)
## Reproduction procedure (enhancement - if needed)
<!--
Please explain how we can reproduce the feature/behavior you want to improve, and what's your proposition to make it better.
Add screenshots if it's related to UI.
If it requires a custom datamodel, provide the minimal XML delta to reproduce it on a standard iTop Community.
-->
## Cause (bug)
<!--
Remove this section only if it's NOT a bug.
Otherwise, explain what is the cause of the issue (where in the code and why)
-->
## Proposed solution (bug and enhancement)
<!--
Explain in details how you are proposing to solve this:
- What did you do in the code and why
- If you changed something in the UI, put before / after screenshots (you can paste image directly in this editor)
-->
## Checklist before requesting a review
<!--
Don't remove these lines, check them once done.
-->
- [ ] I have performed a self-review of my code
- [ ] I have tested all changes I made on an iTop instance
- [ ] I have added a unit test, otherwise I have explained why I couldn't
- [ ] Is the PR clear and detailed enough so anyone can understand digging in the code?
## Checklist of things to do before PR is ready to merge
<!--
Things that needs to be done in the PR before it can be considered as ready to be merged
Examples:
- Changes requested in the review
- Unit test to add
- Dictionary entries to translate
- ...
-->
- [ ] ...
- [ ] ...
- [ ] ...
- [ ] Is the PR clear and detailed enough so anyone can understand without digging in the code?

View File

@@ -1,9 +1,13 @@
name: Add PRs to Combodo PRs Dashboard
on:
pull_request_target:
pull_request:
types:
- opened
issues:
types:
- opened
workflow_call:
jobs:
add-to-project:
@@ -31,23 +35,22 @@ jobs:
run: |
curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/labels \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels \
-d '{"labels":["internal"]}'
- name: Set PR author as assignee if member of the organization
if: env.is_member == 'true'
if: env.is_member == 'true' && github.event_name == 'pull_request'
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/assignees \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/assignees \
-d '{"assignees":["${{ github.event.pull_request.user.login }}"]}'
env:
is_member: ${{ env.is_member }}
- name: Add PR to the appropriate project
uses: actions/add-to-project@v1.0.2
uses: actions/add-to-project@v2
with:
project-url: ${{ env.project_url }}
github-token: ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}

View File

@@ -4,30 +4,33 @@ You want to contribute to iTop? Many thanks to you! 🎉 👍
Here are some guidelines that will help us integrate your work!
## Contributions
### Subjects
You are welcome to create pull requests on any of those subjects:
* 🐛 bug fix
* 🌐 translation / i18n / l10n
* 🚸 enhancement
If you want to implement a **new feature**, please [create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) for review.
If you ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the ticket.
But before creating a PR, please [create a corresponding issue][itop-issues] for review.
We should review within two weeks, and get back to you to indicate if we're interested in your proposal or not.
If you don't create an issue, you won't know if we're interested in your contribution, and you may spend time coding something that won't be accepted.
If you ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the issue.
For all **security related subjects**, please see our [security policy](SECURITY.md).
All **datamodel modification** should be done in an extension. Beware that such change would
impact all existing customers, and could prevent them from
upgrading!
Combodo has a long experience of datamodel changes: they are very disruptive!
All **datamodel modification** should be done in an extension. Beware that such change would
impact all existing customers, and could prevent them from upgrading!
Combodo has a long experience of datamodel changes: they are very disruptive!
This is why we avoid them in iTop core, especially the changes on existing objects/fields.
If you have an idea you're sure would benefit to all of iTop users, you may
[create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) to submit it, but be warned that there are lots of good
If you have an idea you're sure would benefit to all of iTop users, you may
[create a corresponding issue][itop-issues] to submit it, but be warned that there are lots of good
reasons to refuse such changes.
### 📄 License and copyright
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file).
The iTop repository is divided in three parts: iTop (mainly PHP/JS/XML sources and dictionaries), images, and third-party libraries.
@@ -37,48 +40,33 @@ Anyhow, you are encouraged to signal your contribution by the mean of `@author`
If you want to use another license or keep the code ownership (copyright), you may [create an extension][wiki new ext].
[license.txt]: https://github.com/Combodo/iTop/blob/develop/license.txt
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
[itop-issues]: https://github.com/Combodo/iTop/issues
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
## 🔀 iTop branch model
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
we don't have a `master` branch anymore.
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since April 2020
we don't have a `master` branch anymore.
Here are the branches we use and their meaning :
Here are the branches we use and their meaning :
- `develop`: ongoing development version
- `release/*`: if present, that means we are working on a alpha/beta/rc version for shipping
- `support/*`: maintenance branches for older versions
For example, if no version is currently prepared for shipping we could have:
- `develop` containing future 3.1.0 version
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
- `develop` containing future 3.3.0 version
- `support/3.2`: 3.2.x maintenance version
In this example, when 3.1.0-beta is shipped that will become:
- `develop`: future 3.2.0 version
- `release/3.1.0`: 3.1.0-beta
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
And when 3.1.0 final will be out:
- `develop`: future 3.2.0 version
- `support/3.1`: 3.1.x maintenance version (will host developments for 3.1.1)
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
Also note that we have a "micro-version" concept : each of those versions have a very small amount of modifications. They are made from
`support/*` branches as well. For example 2.6.2-1 and 2.6.2-2 were made from the `support/2.6.2` branch.
And when 3.3.0 will be out:
- `develop`: future 3.4.0 version
- `support/3.3`: 3.3.x maintenance version (will host developments for 3.3.1)
- `support/3.2`: 3.2.x maintenance version
## Coding
@@ -92,12 +80,11 @@ A [dedicated page](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3A
2. Create a branch in this fork, based on the develop branch
3. Code !
Do create a dedicated branch for each modification you want to propose : if you don't it will be very hard to merge back your work !
Do create a dedicated branch for each modification you want to propose : if you don't, it will be very hard to merge back your work !
Most of the time you should based your developments on the develop branch.
Most of the time you should base your developments on the develop branch.
That may be different if you want to fix a bug, please use develop anyway and ask in your PR if rebase is possible.
### 🎨 PHP styleguide
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
@@ -106,7 +93,7 @@ Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acust
Please create tests that covers as much as possible the code you're submitting.
Our tests are located in the `test/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
Our tests are located in the `tests/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
### Git Commit Messages
@@ -138,14 +125,14 @@ When your code is working, please:
* Rebase your branch on our repo last commit,
* Create a pull request. _Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)_.
* 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))
- 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))
## 🙏 We are thankful
We are thankful for all your contributions to the iTop universe! As a thank you gift, we will send stickers to every iTop (& extensions) contributors!
We are thankful for all your contributions to the iTop universe! As a thank-you gift, we will send stickers to every iTop (& extensions) contributors!
We have one sticker per contribution type. You might get multiple stickers with one contribution though :)
@@ -159,6 +146,6 @@ We have one sticker per contribution type. You might get multiple stickers with
* Beta tester: Test and give feedback on beta releases
* Extension developer: Develop and publish an extension
Here is the design of each stickers for year 2024:
Here is the design of each sticker:
![iTop stickers 2025](.doc/contributing-guide/2025.contributing-stickers-side-by-side.png)
![iTop stickers](.doc/contributing-guide/contributing-stickers-side-by-side.png)

View File

@@ -53,7 +53,7 @@ iTop also offers mass import tools to help you become even more efficient.
[4]: https://www.itophub.io/wiki/page?id=latest:install:requirements
[5]: https://www.itophub.io/wiki
[6]: https://store.itophub.io/en_US/
[7]: itop-version-history.md
[7]: .doc/itop-version-history.md
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing

View File

@@ -16,5 +16,5 @@ require_once(APPROOT.'/application/audit.category.class.inc.php');
require_once(APPROOT.'/application/audit.domain.class.inc.php');
require_once(APPROOT.'/application/audit.rule.class.inc.php');
require_once(APPROOT.'/application/query.class.inc.php');
require_once(APPROOT.'/setup/moduleinstallation/moduleinstallation.class.inc.php');
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
require_once(APPROOT.'/application/utils.inc.php');

View File

@@ -1035,7 +1035,7 @@ HTML
// Add extra data for markup generation
// - Attribute code and AttributeDef. class
$val['attcode'] = $sAttCode;
$val['atttype'] = $sAttDefClass;
$val['atttype'] = $oAttDef->GetType();
$val['attlabel'] = $sAttLabel;
$val['attflags'] = ($bEditMode) ? $this->GetFormAttributeFlags($sAttCode) : OPT_ATT_READONLY;
@@ -3240,7 +3240,13 @@ EOF
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
if (is_array($aAllowedValues) && count($aAllowedValues) == 1) {
$aValues = array_keys($aAllowedValues);
$this->Set($sAttCode, $aValues[0]);
if ($oAttDef->IsLinkSet()) {
$oObjectSet = $this->Get($sAttCode);
$oObjectSet->AddItem(MetaModel::GetObject($oAttDef->GetLinkedClass(), $aValues[0]));
$this->Set($sAttCode, $oObjectSet);
} else {
$this->Set($sAttCode, $aValues[0]);
}
}
}
}
@@ -4495,7 +4501,7 @@ HTML;
$oDivField = FieldUIBlockFactory::MakeLarge("");
// UIContentBlockUIBlockFactory::MakeStandard(null,["field_container field_large"]);
$oDivField->AddDataAttribute("attribute-type", $sAttDefClass);
$oDivField->AddDataAttribute("attribute-type", $oAttDef->GetType());
$oDivField->AddDataAttribute("attribute-label", $sAttMetaDataLabel);
$oDivField->AddDataAttribute("attribute-flag-hidden", false);
$oDivField->AddDataAttribute("attribute-flag-read-only", false);
@@ -5064,10 +5070,10 @@ EOF
} else {
if (count($aObjects) == 1) {
$oObj = $aObjects[0];
$sSubtitle = Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink());
$sSubtitle = Dict::Format('UI:Delete:Confirm_Object', $oObj->GetHyperLink());
} else {
$sSubtitle = Dict::Format(
'UI:Delect:Confirm_Count_ObjectsOf_Class',
'UI:Delete:Confirm_Count_ObjectsOf_Class',
count($aObjects),
MetaModel::GetName($sClass)
);

View File

@@ -497,7 +497,7 @@ EOF
* @param array $aExtraParams
* @param bool $bCanEdit
*
* @return null|\Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
{

View File

@@ -1387,7 +1387,7 @@ class DesignerIconSelectionField extends DesignerFormField
public function AddAllowedValue($aValue)
{
// Add a null value to the list of allowed values
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues ?? [null]);
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues);
}
public function EnableUpload($sIconUploadUrl)
{

View File

@@ -284,7 +284,9 @@ class utils
}
// Read and record the value for switching the archive mode
$iCurrent = self::ReadParam('with-archive', $iDefault);
Session::Set('archive_mode', $iCurrent);
if (Session::IsInitialized()) {
Session::Set('archive_mode', $iCurrent);
}
// Read and use the value for the current page (web services)
$iCurrent = self::ReadParam('with_archive', $iCurrent, true);
self::$bPageMode = ($iCurrent == 1);
@@ -974,7 +976,7 @@ class utils
return self::$oConfig;
}
$sProductionEnvConfigPath = self::GetConfigFilePath(ITOP_DEFAULT_ENV);
$sProductionEnvConfigPath = self::GetConfigFilePath('production');
if (file_exists($sProductionEnvConfigPath)) {
$oProductionEnvDiskConfig = new Config($sProductionEnvConfigPath);
self::SetConfig($oProductionEnvDiskConfig);

View File

@@ -4,7 +4,7 @@
"type": "project",
"license": "AGPL-3.0-only",
"require": {
"php": ">=8.1.0 <8.5.0",
"php": ">=8.2.0 <8.5.0",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
@@ -15,18 +15,21 @@
"apereo/phpcas": "dev-master",
"guzzlehttp/guzzle": "^7.5.1",
"league/oauth2-google": "^4.0.1",
"nikic/php-parser": "^4.14.0",
"nikic/php-parser": "dev-master",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "^7.2.0",
"psr/log": "^3.0.0",
"scssphp/scssphp": "dev-combodo/1.x",
"symfony/console": "~6.4.0",
"symfony/dotenv": "~6.4.0",
"symfony/form": "^6.4",
"symfony/framework-bundle": "~6.4.0",
"symfony/http-foundation": "~6.4.0",
"symfony/http-kernel": "~6.4.0",
"symfony/runtime": "~6.4.0",
"symfony/security-csrf": "~6.4.0",
"symfony/twig-bundle": "~6.4.0",
"symfony/validator" : "~6.4.0",
"symfony/var-dumper": "~6.4.0",
"symfony/yaml": "~6.4.0",
"symfony/mailer": "~6.4.0",
@@ -40,6 +43,10 @@
"symfony/web-profiler-bundle": "~6.4.0"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/Combodo/PHP-Parser"
},
{
"type": "vcs",
"url": "https://github.com/EsupPortail/phpCAS"
@@ -60,7 +67,7 @@
},
"config": {
"platform": {
"php": "8.1.0"
"php": "8.2.0"
},
"vendor-dir": "lib",
"preferred-install": {
@@ -80,7 +87,6 @@
"sources"
],
"exclude-from-classmap": [
"application/twigextension.class.inc.php",
"core/oql/build/PHP/",
"core/apc-emulation.php",
"application/startup.inc.php",
@@ -100,7 +106,7 @@
"extra": {
"symfony": {
"allow-contrib": false,
"require": "3.4.*"
"require": "6.4.*"
},
"runtime": {
"dotenv_path": "resources/symfony/.env"

1249
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ MetaModel::IncludeModule('application/user.dashboard.class.inc.php');
MetaModel::IncludeModule('application/audit.rule.class.inc.php');
MetaModel::IncludeModule('application/audit.domain.class.inc.php');
MetaModel::IncludeModule('application/query.class.inc.php');
MetaModel::IncludeModule('setup/moduleinstallation/moduleinstallation.class.inc.php');
MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php');
MetaModel::IncludeModule('core/event.class.inc.php');
MetaModel::IncludeModule('core/action.class.inc.php');

View File

@@ -1579,8 +1579,6 @@ class CMDBSource
if (static::GetDBVendor() === static::ENUM_DB_VENDOR_MYSQL) {
//Mysql 5.7.0 and upper deprecated --ssl and uses --ssl-mode instead
return version_compare(static::GetDBVersion(), '5.7.11', '>=');
} elseif (static::GetDBVendor() === static::ENUM_DB_VENDOR_MARIADB) {
return version_compare(static::GetDBVersion(), '10.2.6', '>=');
}
return false;
}

View File

@@ -20,6 +20,9 @@
*
*/
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
@@ -1179,8 +1182,8 @@ class Config
'tracking_level_linked_set_default' => [
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'default' => LINKSET_TRACKING_NONE,
'value' => LINKSET_TRACKING_NONE,
'default' => LINKSET_TRACKING_LIST,
'value' => LINKSET_TRACKING_LIST,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
@@ -2752,13 +2755,14 @@ class Config
*
* @param array $aParamValues
* @param ?string $sModulesDir
* @param bool $bPreserveModuleSettings
*
* @return void The current object is modified directly
*
* @throws \Exception
* @throws \CoreException
*/
public function UpdateFromParams($aParamValues, $sModulesDir = null)
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
{
if (isset($aParamValues['application_path'])) {
$this->Set('app_root_url', $aParamValues['application_path']);
@@ -2806,10 +2810,7 @@ class Config
} else {
$aSelectedModules = null;
}
if (! is_null($sModulesDir)) {
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
}
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
if (isset($aParamValues['source_dir'])) {
$this->Set('source_dir', $aParamValues['source_dir']);
@@ -2827,13 +2828,17 @@ class Config
*
* @throws Exception
*/
public function UpdateIncludes(string $sModulesDir, $aSelectedModules = null)
public function UpdateIncludes($sModulesDir, $aSelectedModules = null)
{
if ($sModulesDir === null) {
return;
}
// Initialize the arrays below with default values for the application...
$oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values
$aAddOns = $oEmptyConfig->GetAddOns();
$aModules = ModuleDiscovery::GetModulesOrderedByDependencies([APPROOT.$sModulesDir]);
$aModules = ModuleDiscovery::GetAvailableModules([APPROOT.$sModulesDir]);
foreach ($aModules as $sModuleId => $aModuleInfo) {
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) {

View File

@@ -5108,8 +5108,8 @@ abstract class DBObject implements iDisplay
protected function GetReferencingObjectsForDeletion($bAllowAllData = false)
{
$aDependentObjects = [];
$aReferencingMe = MetaModel::EnumReferencingClasses(get_class($this));
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
$aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this));
foreach ($aRererencingMe as $sRemoteClass => $aExtKeys) {
/** @var \AttributeExternalKey $oExtKeyAttDef */
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
// skip if external key doesn't require the deletion cascading

View File

@@ -360,10 +360,10 @@ class DesignElement extends \DOMElement
* @param string $sTagName
* @param string|null $sDefault
*
* @return null|string
* @return string
* @throws \DOMFormatException
*/
public function GetChildText($sTagName, $sDefault = null): ?string
public function GetChildText($sTagName, $sDefault = null)
{
$sRet = $sDefault;
if ($oChild = $this->GetOptionalElement($sTagName)) {

View File

@@ -178,7 +178,7 @@ class EventNotificationEmail extends EventNotification
// Display lists
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_class', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments']); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['date', 'message', 'to', 'subject', 'attachments']); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', ['date', 'message', 'to', 'cc', 'bcc', 'subject', 'attachments']); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form

View File

@@ -22,8 +22,6 @@ use Combodo\iTop\Application\EventRegister\ApplicationEvents;
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Setup\ModuleDependency\Module;
use Combodo\iTop\Setup\ModuleDiscovery\ModuleFileReader;
require_once APPROOT.'core/modulehandler.class.inc.php';
require_once APPROOT.'core/querymodifier.class.inc.php';
@@ -130,7 +128,7 @@ abstract class MetaModel
/** @var array */
private static $m_aClassToFile = [];
/** @var string */
protected static $m_sEnvironment = ITOP_DEFAULT_ENV;
protected static $m_sEnvironment = 'production';
/**
* Objects currently created/updated.
@@ -464,43 +462,6 @@ abstract class MetaModel
return call_user_func([$sClass, 'GetClassDescription'], $sClass);
}
/**
* @param string $sClass
*
* @return string
* @throws \CoreException
*/
final public static function GetModuleName($sClass)
{
try {
$oReflectionClass = new ReflectionClass($sClass);
$sDir = realpath(dirname($oReflectionClass->getFileName()));
$sApproot = realpath(APPROOT);
while (($sDir !== $sApproot) && (str_contains($sDir, $sApproot))) {
$aFiles = glob("$sDir/module.*.php");
if (count($aFiles) > 1) {
return 'core';
}
if (count($aFiles) == 0) {
$sDir = realpath(dirname($sDir));
continue;
}
$sModuleFilePath = $aFiles[0];
$aModuleInfo = ModuleFileReader::GetInstance()->ReadModuleFileInformation($sModuleFilePath);
$sModuleId = $aModuleInfo[ModuleFileReader::MODULE_INFO_ID];
list($sModuleName, ) = ModuleDiscovery::GetModuleName($sModuleId);
return $sModuleName;
}
} catch (\Exception $e) {
throw new CoreException("Cannot find class module", ['class' => $sClass], '', $e);
}
return 'core';
}
/**
* @param string $sClass
*
@@ -5748,7 +5709,7 @@ abstract class MetaModel
* @throws \DictExceptionUnknownLanguage
* @throws \Exception
*/
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = ITOP_DEFAULT_ENV)
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = 'production')
{
// Startup on a new environment is not supported
static $bStarted = false;

View File

@@ -43,24 +43,24 @@ final class ormTagSet extends ormSet
/**
*
* @param array|null $aItems
* @param array $aTagCodes
*
* @throws \CoreException
* @throws \CoreUnexpectedValue when a code is invalid
*/
public function SetValues($aItems)
public function SetValues($aTagCodes)
{
if (is_null($aItems)) {
$aItems = [];
if (is_null($aTagCodes)) {
$aTagCodes = [];
}
if (!is_array($aItems)) {
throw new CoreUnexpectedValue("Wrong value {$aItems} for {$this->sClass}:{$this->sAttCode}");
if (!is_array($aTagCodes)) {
throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}");
}
$oTags = [];
$iCount = 0;
$bError = false;
foreach ($aItems as $sTagCode) {
foreach ($aTagCodes as $sTagCode) {
$iCount++;
if (($this->iLimit != 0) && ($iCount > $this->iLimit)) {
$bError = true;

View File

@@ -658,6 +658,16 @@ abstract class User extends cmdbAbstractObject
}
return false;
}
/**
* Allow a user to be impersonated by another one (generally an administrator) in order to troubleshoot rights issues.
*
* @return bool
*/
public function CanBeImpersonated(): bool
{
return true;
}
}
/**
@@ -1063,6 +1073,9 @@ class UserRights
$oUser = self::FindUser($sLogin);
if ($oUser) {
$bRet = true;
if (!$oUser->CanBeImpersonated()) {
throw new Exception($oUser->GetName().' cannot be impersonated');
}
if (is_null(self::$m_oRealUser)) {
// First impersonation
self::$m_oRealUser = self::$m_oUser;

View File

@@ -22,6 +22,4 @@
@import "medallion-with-blocklist";
@import "field-badge-within-datatable";
@import "jquery-blockui-within-dialog";
@import "jquery-blockui-within-datatable";
@import "badge-with-badge";
@import "extension-details-with-extension-details";
@import "jquery-blockui-within-datatable";

View File

@@ -1,10 +0,0 @@
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-badge--spacing-left--with-same-block: $ibo-spacing-200 !default;
.ibo-badge + .ibo-badge {
margin-left: $ibo-badge--spacing-left--with-same-block;
}

View File

@@ -1,11 +0,0 @@
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-extension-details--margin-top: $ibo-spacing-300 !default;
.ibo-extension-details + .ibo-extension-details,
.ibo-extension-details--information--description .ibo-extension-details {
margin-top: $ibo-extension-details--margin-top;
}

View File

@@ -33,5 +33,4 @@
@import "field-badge";
@import "file-select";
@import "medallion-icon";
@import "toast";
@import "badge";
@import "toast";

View File

@@ -1,41 +0,0 @@
$ibo-badge--padding-x : $ibo-spacing-200 !default;
$ibo-badge--padding-y : $ibo-spacing-100 !default;
$ibo-badge--border-radius : $ibo-border-radius-400 !default;
$ibo-badge-colors: (
'primary': ($ibo-color-primary-100, $ibo-color-primary-900),
'secondary': ($ibo-color-secondary-100, $ibo-color-secondary-900),
'neutral': ($ibo-color-secondary-100, $ibo-color-secondary-900),
'information': ($ibo-color-information-100, $ibo-color-information-900),
'success': ($ibo-color-success-100, $ibo-color-success-900),
'failure': ($ibo-color-danger-100, $ibo-color-danger-900),
'warning': ($ibo-color-warning-100,$ibo-color-warning-900),
'danger': ($ibo-color-danger-100,$ibo-color-danger-900),
'grey' : ($ibo-color-grey-100, $ibo-color-grey-900),
'blue-grey': ($ibo-color-blue-grey-100, $ibo-color-blue-grey-900),
'blue': ($ibo-color-blue-100, $ibo-color-blue-900),
'cyan': ($ibo-color-cyan-100, $ibo-color-cyan-900),
'green': ($ibo-color-green-100, $ibo-color-green-900),
'orange' : ($ibo-color-orange-100, $ibo-color-orange-900),
'red': ($ibo-color-red-100, $ibo-color-red-900),
'pink': ($ibo-color-pink-100, $ibo-color-pink-900),
) !default;
.ibo-badge {
display: inline-block;
white-space: nowrap;
padding : $ibo-badge--padding-y $ibo-badge--padding-x;
border-radius : $ibo-badge--border-radius;
@extend %ibo-font-ral-med-50;
@each $sColor, $aColorValues in $ibo-badge-colors {
$bg-color: nth($aColorValues, 1);
$text-color: nth($aColorValues, 2);
&.ibo-is-#{$sColor} {
background-color: $bg-color;
color: $text-color;
}
}
}

View File

@@ -185,16 +185,20 @@ $ibo-panel--is-selectable--body--after--font-size: $ibo-font-size-700 !default;
.ibo-panel--icon-img, .ibo-panel--icon-background { // second class is deprecated, remove it when dealing with N°9317
width: 100%;
height: 100%;
object-position: center;
object-fit: $ibo-panel--icon-img--size--must-contain;
background-position: center;
background-repeat: no-repeat;
background-size: $ibo-panel--icon-img--size--must-contain;
}
.ibo-panel--icon-img--must-contain, .ibo-panel--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
object-fit: $ibo-panel--icon-img--size--must-contain;
background-size: $ibo-panel--icon-img--size--must-contain;
}
.ibo-panel--icon-img--must-cover, .ibo-panel--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
object-fit: $ibo-panel--icon-img--size--must-cover;
background-size: $ibo-panel--icon-img--size--must-cover;
}

View File

@@ -247,7 +247,8 @@ $ibo-quick-create--compartment--placeholder-hint--text-color: $ibo-color-grey-70
&:hover {
cursor: pointer;
@extend a;
color: $ibo-hyperlink-color--on-hover;
text-decoration: $ibo-hyperlink-text-decoration--on-hover;
}
.highlight {

View File

@@ -51,19 +51,23 @@ $ibo-title--icon-img--size--must-zoomout: $ibo-title--icon-background--size--mus
width: 100%;
height: 100%;
object-position: center;
object-fit: $ibo-title--icon-img--size--must-contain;
background-size: $ibo-title--icon-img--size--must-contain;
}
.ibo-title--icon-img--must-contain, .ibo-title--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
object-fit: $ibo-title--icon-img--size--must-contain;
background-size: $ibo-title--icon-img--size--must-contain;
}
.ibo-title--icon-img--must-cover, .ibo-title--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
object-fit: $ibo-title--icon-img--size--must-cover;
background-size: $ibo-title--icon-img--size--must-cover;
}
.ibo-title--icon-img--must-zoomout, .ibo-title--icon-background--must-zoomout { // second class is deprecated, remove it when dealing with N°9317
background-size: $ibo-title--icon-img--size--must-zoomout;
width: $ibo-title--icon-img--size--must-zoomout;
height: $ibo-title--icon-img--size--must-zoomout;
}
.ibo-title--for-object-details {

View File

@@ -8,7 +8,6 @@ $ibo-toggler--wrapper--height: 20px !default;
$ibo-toggler--slider--border-radius: $ibo-border-radius-900 !default;
$ibo-toggler--slider--background-color: $ibo-color-secondary-600 !default;
$ibo-toggler--slider--disabled--background-color: $ibo-color-secondary-200 !default;
$ibo-toggler--slider--before--left: 3px !default;
$ibo-toggler--slider--before--bottom: 3px !default;
@@ -18,7 +17,6 @@ $ibo-toggler--slider--before--border-radius: $ibo-border-radius-full !default;
$ibo-toggler--slider--before--background-color: $ibo-color-grey-100 !default;
$ibo-toggler--slider--checked--background-color: $ibo-color-primary-600 !default;
$ibo-toggler--slider--checked-disabled--background-color: $ibo-color-primary-200 !default;
$ibo-toggler--slider--focus--box-shadow: 0 0 1px $ibo-color-primary-600 !default;
$ibo-toggler--label--margin-left: 4px !default;
@@ -63,13 +61,6 @@ $ibo-toggler--label--margin-left: 4px !default;
background-color: $ibo-toggler--slider--checked--background-color;
}
.ibo-toggler--wrapper input:disabled + .ibo-toggler--slider {
background-color: $ibo-toggler--slider--disabled--background-color;
}
.ibo-toggler--wrapper input:checked:disabled + .ibo-toggler--slider {
background-color: $ibo-toggler--slider--checked-disabled--background-color;
}
input:focus + .ibo-toggler--slider {
box-shadow: $ibo-toggler--slider--focus--box-shadow;
}

View File

@@ -15,4 +15,3 @@
@import "wizard-container/wizard-container";
@import "object/all";
@import "activity-panel/all";
@import "extension/all";

View File

@@ -1 +0,0 @@
@import "extension-details";

View File

@@ -1,65 +0,0 @@
$ibo-extension-details--information--metadata--padding: $ibo-spacing-200 !default;
$ibo-extension-details--information--metadata--delimiter: "-" !default;
$ibo-extension-details--information--metadata--color: $ibo-color-grey-700 !default;
$ibo-extension-details--actions--button--padding-y: 3px !default;
$ibo-extension-details--actions--button--padding-x: $ibo-button--padding-x !default;
.ibo-extension-details {
display: inline-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
}
.ibo-extension-details--information {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.ibo-extension-details--actions {
display: flex;
}
.ibo-extension-details--information--label {
@extend %ibo-font-ral-med-150;
}
.ibo-extension-details--information--metadata {
@extend %ibo-font-ral-med-100;
color: $ibo-extension-details--information--metadata--color;
}
.ibo-extension-details--information--description {
@extend %ibo-font-ral-med-100;
}
.ibo-extension-details--information--metadata span + span:before {
content: $ibo-extension-details--information--metadata--delimiter;
padding-left: $ibo-extension-details--information--metadata--padding;
padding-right: $ibo-extension-details--information--metadata--padding;
}
//ibo-extension-details can have other ibo-extension-details inside its ibo-extension-details--information--description in the setup. We need to only affect direct children
.ibo-extension-details:has(>.ibo-extension-details--actions input:is([type="checkbox"], [type="radio"]):checked){
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.unchecked {
display: none;
}
}
//Merging the two lines below with :is([type="checkbox"], [type="radio"]) will generate a warning in scss compiler
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="checkbox"]:not(:checked)),
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="radio"]:not(:checked)) {
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.checked {
display: none;
}
}
.ibo-extension-details--actions > button {
padding: $ibo-extension-details--actions--button--padding-y $ibo-extension-details--actions--button--padding-x;
}
.ibo-extension-details--actions:has(.toggler-install:not(:disabled)) .ibo-popover-menu--section a[data-resource-id="force_uninstall"] {
display: none;
}

View File

@@ -3,9 +3,29 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-datamodel-viewer--viewer-empty--width: max(20%, #{$ibo-size-700}) !default;
$ibo-datamodel-viewer--parent--spacer--padding-y: $ibo-spacing-0 !default;
$ibo-datamodel-viewer--parent--spacer--padding-x: $ibo-spacing-300 !default;
$ibo-datamodel-viewer--breadcrumb--margin: $ibo-spacing-200 0 !default;
$ibo-datamodel-viewer--classname--font-family: monospace !default;
$ibo-datamodel-viewer--classname--color: $ibo-color-blue-grey-600 !default;
$ibo-datamodel-viewer--tag--category--color: $ibo-color-blue-grey-800 !default;
$ibo-datamodel-viewer--tag--category--icon--color: $ibo-color-blue-grey-600 !default;
$ibo-datamodel-viewer--abstract-class-icon--margin-right: $ibo-spacing-300 !default;
$ibo-datamodel-viewer--abstract-class-icon--after--content: 'A' !default;
$ibo-datamodel-viewer--abstract-class-icon--after--width: 15px !default;
$ibo-datamodel-viewer--abstract-class-icon--after--height: 15px !default;
$ibo-datamodel-viewer--abstract-class-icon--after--line-height: 14px !default;
$ibo-datamodel-viewer--abstract-class-icon--after--border-radius: 50% !default;
$ibo-datamodel-viewer--abstract-class-icon--after--border: 1px solid $ibo-color-cyan-500 !default;
$ibo-datamodel-viewer--abstract-class-icon--after--color: $ibo-color-white-100 !default;
$ibo-datamodel-viewer--abstract-class-icon--after--background-color: $ibo-color-cyan-500 !default;
$ibo-datamodel-viewer--classes-list--selectize-input--background-color: $ibo-color-white-100 !default;
$ibo-datamodel-viewer--classes-list--selectize-input--color: $ibo-color-grey-800 !default;
$ibo-datamodel-viewer--classes-list--selectize-input--border-color: $ibo-color-grey-500 !default;
@@ -16,8 +36,9 @@ $ibo-datamodel-viewer--origin-cell--diameter: 8px !default;
$ibo-datamodel-viewer--origin-cell--border-radius: $ibo-border-radius-full !default;
$ibo-datamodel-viewer--classes-list--height: 100% !default;
$ibo-datamodel-viewer--classes-list--width: 350px !default;
$ibo-datamodel-viewer--classes-list--width: $ibo-size-700 !default;
$ibo-datamodel-viewer--classes-list--padding-left: $ibo-spacing-600 !default;
$ibo-datamodel-viewer--classes-list--padding-top: $ibo-spacing-300 !default;
$ibo-datamodel-viewer--lifecycle--code--color: $ibo-color-grey-700 !default;
$ibo-datamodel-viewer--lifecycle--stimuli--color: $ibo-color-blue-900 !default;
@@ -45,6 +66,56 @@ $ibo-datamodel-viewer--lifecycle-image--margin-bottom: $ibo-spacing-500 !default
.ibo-panel--subtitle{
@extend %ibo-font-ral-nor-150;
}
.ibo-datamodel-viewer--empty{
display: flex;
flex-direction: column;
align-items: center;
svg{
width: $ibo-datamodel-viewer--viewer-empty--width;
}
}
}
.ibo-datamodel-viewer--empty--text {
@extend %ibo-font-ral-med-400
}
.ibo-datamodel-viewer--breadcrumb{
@extend %ibo-font-ral-med-150;
margin: $ibo-datamodel-viewer--breadcrumb--margin;
.ibo-button{
text-transform: none; // unset uppercase
}
}
.ibo-datamodel-viewer--classname{
color: $ibo-datamodel-viewer--classname--color;
@extend %ibo-font-code-100;
}
.ibo-datamodel-viewer--tag--category{
color: $ibo-datamodel-viewer--tag--category--color;
.ibo-object-details--tag-icon{
color:$ibo-datamodel-viewer--tag--category--icon--color;
}
}
.ibo-datamodel-viewer--icon--abstract{
&:after{
content: $ibo-datamodel-viewer--abstract-class-icon--after--content;
display: inline-flex;
justify-content: center;
align-items: center;
width: $ibo-datamodel-viewer--abstract-class-icon--after--width;
height: $ibo-datamodel-viewer--abstract-class-icon--after--height;
line-height: $ibo-datamodel-viewer--abstract-class-icon--after--line-height;
border-radius: $ibo-datamodel-viewer--abstract-class-icon--after--border-radius;
border: $ibo-datamodel-viewer--abstract-class-icon--after--border;
color: $ibo-datamodel-viewer--abstract-class-icon--after--color;
background-color: $ibo-datamodel-viewer--abstract-class-icon--after--background-color;
@extend %ibo-font-ral-bol-50;
}
}
.ibo-datamodel-viewer--parent--spacer{
@@ -80,6 +151,7 @@ $ibo-datamodel-viewer--lifecycle-image--margin-bottom: $ibo-spacing-500 !default
height: $ibo-datamodel-viewer--classes-list--height;
width: $ibo-datamodel-viewer--classes-list--width;
padding-left: $ibo-datamodel-viewer--classes-list--padding-left;
padding-top: $ibo-datamodel-viewer--classes-list--padding-top;
overflow-y: scroll;
}

View File

@@ -28,6 +28,15 @@ $ibo-vendors-ckeditor--ck-mentions--item--padding-x: $ibo-spacing-300 !default;
$ibo-vendors-ckeditor--ck-mentions--item--padding-y: $ibo-spacing-200 !default;
/* CSS3 variables */
:root {
--ck-content-font-family: inherit;
--ck-content-font-color: inherit;
--ck-content-font-size: inherit;
--ck-content-line-height: inherit;
--ck-content-word-break: inherit;
--ck-content-overflow-wrap: inherit;
}
.ck {
--ck-color-list-button-on-background: #{$ibo-vendors-ckeditor--ck-color-list-button-on-background};
--ck-color-list-button-on-background-focus: #{$ibo-vendors-ckeditor--ck-color-list-button-on-background-focus};

File diff suppressed because one or more lines are too long

View File

@@ -316,34 +316,29 @@ fieldset {
background-color: #F7FAFC;
padding: 10px;
.wiz-choice{
&:not(:checked) ~ label .checked{
&:checked ~ .description {
#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked),
#itop-ticket-mgmt-itil-enhanced-portal:not(:checked) {
~ .description::after {
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
display: block;
margin-top: 0.5em;
font-weight: bold;
color: $legacy-portal-removal-text-color;
}
}
}
&:not(:checked) ~ label .setup-extension-tag.checked{
display:none;
}
&:checked ~ label .unchecked{
&:checked ~ label .setup-extension-tag.unchecked{
display:none;
}
}
}
.ibo-extension-details:has(>.ibo-extension-details--actions>input:checked) {
.ibo-extension-details:has(#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked), #itop-ticket-mgmt-itil-enhanced-portal:not(:checked)) {
.ibo-extension-details--information--description::after {
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
display: block;
margin-top: 0.5em;
font-weight: bold;
color: $legacy-portal-removal-text-color;
}
}
}
.ibo-extension-details--information--metadata{
color: $ibo-color-grey-800;
}
.choice-disabled {
color: $ibo-color-grey-700;
}
body {
font-size: 1.17rem;
@@ -527,12 +522,10 @@ body {
}
}
.ibo-setup-summary-title, .ibo-setup-summary-title:visited, .ibo-setup-summary-title:hover {
font-size: $ibo-font-size-150;
color: inherit;
.ibo-setup-summary-title {
font-size: $ibo-font-size-150;
}
#ibo-setup-licenses--components-list {
background-color: $ibo-color-white-200;
padding: 12px;
@@ -612,7 +605,6 @@ body {
color:#a00000;
}
.setup-extension-tag {
display: inline-flex;
background-color: grey;
border-radius: 8px;
padding-left: 3px;
@@ -638,21 +630,6 @@ body {
}
}
.ibo-extension-details {
align-items: flex-start;
}
.ibo-extension-details--actions input{
margin:0.2em 0.5em;
width: 12px;
}
:not(.ibo-badge) ~ .ibo-badge{
margin-left:0.5em;
}
.ibo-extension-details--information--label i{
font-size : 0.9em;
margin-left:0.3em;
}
.setup--wizard-choice--label + .setup--wizard-choice--more-info {
margin-left: 0.5rem;
}
@@ -704,6 +681,9 @@ body {
overflow: auto;
text-align: center;
}
#installation_progress {
display: none;
}
#fresh_content{
border: 0;
min-height: 300px;

View File

@@ -97,18 +97,19 @@
$bDebug = isset($aServerParams['debug']) ? $aServerParams['debug'] : false;
}
if (array_key_exists(LDAP_OPT_DEBUG_LEVEL, $aOptions))
{
// Set debug level before trying to connect, so that debug info appear in the PHP error log if ldap_connect goes wrong
$bRet = ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, $aOptions[LDAP_OPT_DEBUG_LEVEL]);
$this->LogInfo($bDebug, "ldap_set_option('LDAP_OPT_DEBUG_LEVEL', '{$aOptions[LDAP_OPT_DEBUG_LEVEL]}') returned ".($bRet ? 'true' : 'false'));
}
$hDS = @ldap_connect($sURI);
if ($hDS === false)
{
$this->LogIssue($bDebug, "ldap_authentication: can not connect to the LDAP server '$sURI'. Check the configuration file config-itop.php.");
return false;
}
if (array_key_exists(LDAP_OPT_DEBUG_LEVEL, $aOptions))
{
// Set debug level before trying to connect, so that debug info appear in the PHP error log if ldap_connect goes wrong
$bRet = ldap_set_option($hDS, LDAP_OPT_DEBUG_LEVEL, $aOptions[LDAP_OPT_DEBUG_LEVEL]);
$this->LogInfo($bDebug, "ldap_set_option('LDAP_OPT_DEBUG_LEVEL', '{$aOptions[LDAP_OPT_DEBUG_LEVEL]}') returned ".($bRet ? 'true' : 'false'));
}
foreach($aOptions as $name => $value)
{
$bRet = ldap_set_option($hDS, $name, $value);

View File

@@ -1,9 +0,0 @@
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/*
* CSS of the template page
*/

View File

@@ -1,9 +0,0 @@
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/*
* Javascript file loaded in template page
*/

View File

@@ -1,17 +0,0 @@
{
"config": {
"classmap-authoritative": true
},
"autoload": {
"psr-4": {
"Combodo\\iTop\\DataFeatureRemoval\\": "src",
"": "src/NoNamespace"
}
},
"name": "combodo/combodo-data-feature-removal",
"type": "itop-extension",
"description": "iTop Data Feature Removal",
"require": {
"composer-runtime-api": "^2.0"
}
}

View File

@@ -1,20 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b862a55cbf5448fb99f0905a4db6529b",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"composer-runtime-api": "^2.0"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
}

View File

@@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
<classes>
<class id="DataFeatureRemovalBackgroundOperation" _delta="define">
<properties>
<category>bizmodel,searchable</category>
<abstract>false</abstract>
<db_table>datafeatureremovalbackgroundoperation</db_table>
<style>
<icon>
<fileref ref="icons8-electricity_643cf7fd7a024968679dc0c35a710a03"/>
</icon>
<main_color>#0000ff</main_color>
</style>
<naming>
<attributes/>
</naming>
<reconciliation>
<attributes/>
</reconciliation>
<uniqueness_rules>
<rule id="list_of_classes">
<attributes>
<attribute id="classes"/>
</attributes>
<filter><![CDATA[]]></filter>
<disabled>false</disabled>
<is_blocking>true</is_blocking>
</rule>
</uniqueness_rules>
</properties>
<fields>
<field id="creation_date" xsi:type="AttributeDateTime">
<sql>creation_date</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
<dependencies/>
<tracking_level>all</tracking_level>
</field>
<field id="features_code" xsi:type="AttributeText">
<sql>features_code</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
<validation_pattern/>
<width/>
<height/>
<dependencies/>
<tracking_level>all</tracking_level>
</field>
<field id="classes" xsi:type="AttributeText">
<sql>classes</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
<validation_pattern/>
<width/>
<height/>
<dependencies/>
<tracking_level>all</tracking_level>
</field>
</fields>
<methods/>
<presentation>
<list>
<items>
<item id="creation_date">
<rank>10</rank>
</item>
<item id="features_code">
<rank>20</rank>
</item>
<item id="classes">
<rank>30</rank>
</item>
</items>
</list>
<search>
<items/>
</search>
<details>
<items>
<item id="creation_date">
<rank>10</rank>
</item>
<item id="features_code">
<rank>20</rank>
</item>
<item id="classes">
<rank>30</rank>
</item>
</items>
</details>
</presentation>
<parent>cmdbAbstractObject</parent>
</class>
</classes>
<dictionaries>
<dictionary id="EN US">
<entries>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Name" _delta="define"><![CDATA[]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/ComplementaryName" _delta="define"><![CDATA[]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation" _delta="define"><![CDATA[DataFeatureRemovalBackgroundOperation]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation+" _delta="define"><![CDATA[]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:creation_date" _delta="define"><![CDATA[Creation date]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:creation_date+" _delta="define"><![CDATA[]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:features_code" _delta="define"><![CDATA[Features code]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:features_code+" _delta="define"><![CDATA[]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:classes" _delta="define"><![CDATA[Classes]]></entry>
<entry id="Class:DataFeatureRemovalBackgroundOperation/Attribute:classes+" _delta="define"><![CDATA[]]></entry>
</entries>
</dictionary>
</dictionaries>
<files>
<file id="icons8-electricity_643cf7fd7a024968679dc0c35a710a03" xsi:type="File" _delta="define_if_not_exists">
<name>images/icons/icons8-electricity.svg</name>
<mime_type>image/svg+xml</mime_type>
<data>PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciICB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PHBhdGggZmlsbD0iIzM3YzZkMCIgZD0iTTI2LjQ1MTIsMzdsNy43NzY0Ni0xNS41NTI5MWExLDEsMCwwLDAtLjg5NDM1LTEuNDQ3MjJMMjIuOTUxMiwxOS45OTkyNWw2LjMzNi0xMy41NzYzNUExLDEsMCwwLDAsMjguMzgxLDVIMjIuNTk2MzlhMSwxLDAsMCwwLS45MTExMS41ODc4M2wtOC41OTUyNCwxOUExLDEsMCwwLDAsMTQuMDAxMTUsMjZoMTAuNDVsLTUuNSwxMVoiLz48cGF0aCBmaWxsPSIjMzdjNmQwIiBkPSJNMTYuMjIyODYsMzdIMjkuODY0NzFhLjU1NzM1LjU1NzM1LDAsMCwxLC4zNTgxNSwxTDE5Ljk2LDQ0LjM2N2ExLjAzMzY0LDEuMDMzNjQsMCwwLDEtMS40OTEyMS0uNDI1ODZMMTUuNzIyODYsMzcuNzVBLjUwNDUuNTA0NSwwLDAsMSwxNi4yMjI4NiwzN1oiLz48L3N2Zz4=</data>
</file>
</files>
<menus>
<menu id="DataFeatureRemovalMenu" xsi:type="WebPageMenuNode" _delta="define">
<rank>30</rank>
<parent>SystemTools</parent>
<url>$pages/exec.php?exec_module=combodo-data-feature-removal&amp;exec_page=index.php&amp;c[menu]=DataFeatureRemovalMenu</url>
<enable_admin_only>1</enable_admin_only>
</menu>
</menus>
<module_parameters>
<parameters id="combodo-data-feature-removal">
<max_count_estimation_for_safe_cleanup>100</max_count_estimation_for_safe_cleanup>
</parameters>
</module_parameters>
</itop_design>

View File

@@ -1,60 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* Localized data
*/
Dict::Add('EN US', 'English', 'English', [
'Menu:DataFeatureRemovalMenu' => 'Features Removal',
'combodo-data-feature-removal/Operation:Main/Title' => 'Features Removal',
'DataFeatureRemoval:Main:Title' => 'Features Removal',
'DataFeatureRemoval:Main:SubTitle' => 'Prepare features you want to enable/disable in a future setup',
'DataFeatureRemoval:Failure:Title' => 'Feature dry removal errors',
'DataFeatureRemoval:Helper:Title' => 'Enable or disable features that are installed in your iTop.',
'DataFeatureRemoval:Helper:Desc1' => 'It will prepare the setup step that proceeds to feature enabling or disabling.',
'DataFeatureRemoval:Helper:Desc2' => 'Analyze if there are any data or dependency preventing you from enabling/disabling a feature.',
'DataFeatureRemoval:Features:Title' => 'Features',
'DataFeatureRemoval:Analysis:Title' => 'Analysis result',
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing',
'DataFeatureRemoval:Analysis:Ok' => "No data to cleanup",
'DataFeatureRemoval:DeletionPlan:Title' => 'Deletion plan',
'DataFeatureRemoval:DeletionPlan:SubTitle' => '%1$s rows to clean before continuing',
'DataFeatureRemoval:DoDeletion:Title' => 'Do deletion',
'DataFeatureRemoval:DoDeletion:SubTitle' => 'Remove all the entries from the database',
'DataFeatureRemoval:DeletionPlan:ToManyOperations' => 'Too many entries to clean',
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove',
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Feature name',
'DataFeatureRemoval:Table:Analysis:Module' => 'Module name',
'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence',
'UI:Button:Analyze' => 'Analyze',
'UI:Button:ModifyChoices' => 'Modify Choices',
'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup',
'UI:Button:PlanDeletion' => 'Prepare deletion plan',
'UI:Button:DoDeletion' => 'Delete data',
'UI:Button:DoAsyncDeletion' => 'Do asynchronous deletion',
'UI:Button:BackToMain' => 'Back to Feature Removal',
'UI:Button:Setup' => 'Back to setup',
'UI:Action:ForceUninstall' => 'Force uninstall',
'UI:Action:MoreInfo' => 'More information',
'DataFeatureRemoval:Table:Empty' => 'No data to remove',
'DataFeatureRemoval:Column:Class' => 'Class',
'DataFeatureRemoval:Column:DeleteCount' => 'Entries to delete',
'DataFeatureRemoval:Column:UpdateCount' => 'Entries to update',
'DataFeatureRemoval:Column:Issue' => 'Issue',
'DataFeatureRemoval:Column:DeletedCount' => 'Deleted entries',
'DataFeatureRemoval:Column:UpdatedCount' => 'Updated entries',
]);

View File

@@ -1,60 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* Localized data
*/
Dict::Add('FR FR', 'French', 'Français', [
'Menu:DataFeatureRemovalMenu' => 'Suppression de fonctionnalités',
'combodo-data-feature-removal/Operation:Main/Title' => 'Suppression de fonctionnalités',
'DataFeatureRemoval:Main:Title' => 'Suppression de fonctionnalités',
'DataFeatureRemoval:Main:SubTitle' => 'Préparez les fonctionnalités que vous souhaitez activer ou désactiver lors dune prochaine configuration',
'DataFeatureRemoval:Failure:Title' => 'Erreurs lors de la simulation de suppression de fonctionnalités',
'DataFeatureRemoval:Helper:Title' => 'Activez ou désactivez les fonctionnalités installées dans votre iTop.',
'DataFeatureRemoval:Helper:Desc1' => 'Cette étape prépare lassistant de configuration à activer ou désactiver des fonctionnalités.',
'DataFeatureRemoval:Helper:Desc2' => 'Analyse si des données ou des dépendances empêchent lactivation ou la désactivation dune fonctionnalité.',
'DataFeatureRemoval:Features:Title' => 'Fonctionnalités',
'DataFeatureRemoval:Analysis:Title' => 'Résultat de lanalyse',
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s élément(s) à nettoyer avant de poursuivre',
'DataFeatureRemoval:Analysis:Ok' => "Aucune donnée à nettoyer",
'DataFeatureRemoval:DeletionPlan:Title' => 'Plan de suppression',
'DataFeatureRemoval:DeletionPlan:SubTitle' => '%1$s ligne(s) à nettoyer avant de poursuivre',
'DataFeatureRemoval:DoDeletion:Title' => 'Exécuter la suppression',
'DataFeatureRemoval:DoDeletion:SubTitle' => 'Supprime toutes les entrées de la base de données',
'DataFeatureRemoval:DeletionPlan:ToManyOperations' => 'Trop dentrées à nettoyer',
'DataFeatureRemoval:Table:Analysis:ClassName' => 'Élément à supprimer',
'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Fonctionnalité',
'DataFeatureRemoval:Table:Analysis:Module' => 'Module',
'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence',
'UI:Button:Analyze' => 'Analyser',
'UI:Button:ModifyChoices' => 'Modifier les choix',
'UI:Button:AnalyzeAndSetup' => 'Analyser et ouvrir lassistant de configuration',
'UI:Button:PlanDeletion' => 'Préparer le plan de suppression',
'UI:Button:DoAsyncDeletion' => 'Lancer la suppression en tâche de fond',
'UI:Button:DoDeletion' => 'Supprimer les données',
'UI:Button:BackToMain' => 'Retour à la suppression de fonctionnalités',
'UI:Button:Setup' => 'Retour à lassistant de configuration',
'UI:Action:ForceUninstall' => 'Forcer la désinstallation',
'UI:Action:MoreInfo' => 'Plus dinformations',
'DataFeatureRemoval:Table:Empty' => 'Aucune donnée à supprimer',
'DataFeatureRemoval:Column:Class' => 'Classe',
'DataFeatureRemoval:Column:DeleteCount' => 'Entrées à supprimer',
'DataFeatureRemoval:Column:UpdateCount' => 'Entrées à mettre à jour',
'DataFeatureRemoval:Column:Issue' => 'Problème',
'DataFeatureRemoval:Column:DeletedCount' => 'Entrées supprimées',
'DataFeatureRemoval:Column:UpdatedCount' => 'Entrées mises à jour',
]);

View File

@@ -1,20 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval;
use Combodo\iTop\DataFeatureRemoval\Controller\DataFeatureRemovalController;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
require_once(APPROOT.'application/startup.inc.php');
DataFeatureRemovalLog::Enable();
$oController = new DataFeatureRemovalController(MODULESROOT.DataFeatureRemovalHelper::MODULE_NAME.'/templates', DataFeatureRemovalHelper::MODULE_NAME);
$oController->SetDefaultOperation('Main');
$oController->HandleOperation();

View File

@@ -1,16 +0,0 @@
<?php
// PHP Data Model definition file
// WARNING - WARNING - WARNING
// DO NOT EDIT THIS FILE (unless you know what you are doing)
//
// If you provide a datamodel.xxxx.xml file with your module,
// this file WILL BE overwritten by the compilation of the
// module (during the setup) if the datamodel.xxxx.xml file
// contains the definition of new classes or menus.
//
// The recommended way to define new classes (for iTop 2.0 and later) is via the XML definition.
// This file remains in the module's template only for the cases where there is:
// - either no new class or menu defined in the XML file
// - or no XML file at all supplied by the module

View File

@@ -1,281 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Controller;
require_once APPROOT.'setup/feature_removal/SetupAudit.php';
require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
use Combodo\iTop\Application\TwigBase\Controller\Controller;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalConfig;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Service\BackgroundOperationService;
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
use Combodo\iTop\DataFeatureRemoval\Service\DeletionPlanService;
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
use Dict;
use Exception;
use IssueLog;
use MetaModel;
use utils;
class DataFeatureRemovalController extends Controller
{
private array $aSelectedExtensionsForCheck = [];
private array $aCountClassesToCleanup = [];
private array $aAnalysisDataTable = [];
private int $iCount = 0;
public function OperationMain($sErrorMessage = null): void
{
$aParams = [];
$this->ReadRemovedExtensions();
$this->AddAnalyzeParams();
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aExtensions'] = $this->GetExtensionsTable();
$aParams['aExtensionsCode'] = $this->aSelectedExtensionsForCheck;
$aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable;
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
$aParams['bHasData'] = $this->iCount > 0;
$aParams['sSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup';
$aParams['iCount'] = $this->iCount;
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
$aParams['bAnalysisOk'] = (count($this->aCountClassesToCleanup) > 0) && ($this->iCount === 0);
$this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css');
$this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js');
$this->m_sOperation = "Main";
$this->DisplayPage($aParams);
}
public function AddAnalyzeParams(): void
{
$aData = [];
$aColumns = [];
$this->iCount = 0;
foreach ($this->aCountClassesToCleanup as $sClass => $iCount) {
$sModuleName = MetaModel::GetModuleName($sClass);
$aExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetIncludingExtensions($sModuleName);
$sExtensions = implode(' ', $aExtensions);
$aColumns = ['ClassName','FeatureName','Module','Occurrence'];
$aData[] = [$sClass,$sExtensions,$sModuleName,$iCount];
$this->iCount += $iCount;
}
$this->aAnalysisDataTable = $this->GetTableData('Analysis', $aColumns, $aData);
}
public function OperationAnalyze(): void
{
$this->ReadRemovedExtensions();
$this->m_sOperation = 'Main';
try {
if (count($this->aSelectedExtensionsForCheck) > 0) {
$this->Analyze();
}
$this->OperationMain();
} catch (Exception $e) {
IssueLog::Error(__METHOD__, null, ['stack' => $e->getTraceAsString(), 'exception' => $e->getMessage()]);
$this->OperationMain($e->getMessage());
}
}
private function Analyze(): void
{
$sSourceEnv = MetaModel::GetEnvironment();
$oDryRemovalRuntimeEnvironment = new DryRemovalRuntimeEnvironment($sSourceEnv, $this->aSelectedExtensionsForCheck);
$oDryRemovalRuntimeEnvironment->CompileFrom($sSourceEnv);
$oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = $oSetupAudit->RunDataAudit();
IssueLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
$this->aCountClassesToCleanup = $aGetRemovedClasses;
}
public function OperationDeletionPlan(): void
{
$aParams = [];
$this->ValidateTransactionId();
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
$aDeletionPlanSummaryEntities = DeletionPlanService::GetInstance()->GetDeletionPlanSummary($aClasses);
$aColumns = ['Class', 'DeleteCount' , 'UpdateCount', 'Issue'];
$aRows = [];
$iQueryCount = 0;
foreach ($aDeletionPlanSummaryEntities as $oDeletionPlanSummaryEntity) {
$aRows[] = [
$oDeletionPlanSummaryEntity->sClass,
$oDeletionPlanSummaryEntity->iDeleteCount,
$oDeletionPlanSummaryEntity->iUpdateCount,
$oDeletionPlanSummaryEntity->sIssue ?? '',
];
$iQueryCount += $oDeletionPlanSummaryEntity->iDeleteCount;
$iQueryCount += $oDeletionPlanSummaryEntity->iUpdateCount;
}
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aDeletionPlanSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows);
$aParams['aClasses'] = $aClasses;
$aParams['aExtensionsCode'] = utils::ReadPostedParam('aExtensionsCode', []);
$aParams['iQueryCount'] = $iQueryCount;
$aParams['bDeletionPossible'] = ($iQueryCount <= DataFeatureRemovalConfig::GetInstance()->Get('max_count_estimation_for_safe_cleanup', 100));
$this->DisplayPage($aParams);
}
public function OperationDoDeletion(): void
{
$aParams = [];
$this->ValidateTransactionId();
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
$sDeletionButtonValue = utils::ReadPostedParam('btn_deletion', null);
$bAsynchronous = ('async_deletion' === $sDeletionButtonValue);
if ($bAsynchronous) {
BackgroundOperationService::GetInstance()->CreateOperation(utils::ReadPostedParam('aExtensionsCode', []), $aClasses);
$this->OperationMain();
return;
}
$aDeletionExecutionSummary = DeletionPlanService::GetInstance()->ExecuteDeletionPlan($aClasses);
$aColumns = ['Class', 'DeletedCount' , 'UpdatedCount'];
$aRows = [];
foreach ($aDeletionExecutionSummary as $oDeletionExecutionSummaryEntity) {
$aRows[] = [
$oDeletionExecutionSummaryEntity->sClass,
$oDeletionExecutionSummaryEntity->iDeleteCount,
$oDeletionExecutionSummaryEntity->iUpdateCount,
];
}
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aDeletionExecutionSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows);
$this->DisplayPage($aParams);
}
/**
* Get installed extensions from disk
*
* @return array structure for twig datatable
*/
private function GetExtensionsTable(): array
{
$aExtensions = [];
$aColumns = ['', 'Version', 'Name', 'Code'];
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
/** @var \iTopExtension $oExtension */
$bCleanupOngoing = BackgroundOperationService::GetInstance()->IsExtensionBeingCleaned($sCode);
$sChecked = '';
$sDisabledHtml = '';
$sLabel = $oExtension->sLabel;
if ($bCleanupOngoing) {
$sDisabledHtml = 'disabled=""';
$sLabel .= <<<HTML
&nbsp; <span class="ibo-spinner ibo-is-inline ibo-spinner ibo-block" data-role="ibo-spinner"><i class="ibo-spinner--icon fas fa-sync-alt fa-spin" aria-hidden="true"/></span>
HTML;
;
} elseif ($oExtension->bRemovedFromDisk) {
$sDisabledHtml = 'disabled=""';
$sChecked = 'checked';
} elseif (in_array($sCode, $this->aSelectedExtensionsForCheck)) {
$sChecked = 'checked';
}
$sVersion = $oExtension->sVersion;
$sIdEnable = "aExtensions[$sCode][enable]";
$aExtensions[] = [
<<<HTML
<input type="checkbox" $sDisabledHtml class="extension_check" $sChecked id="$sIdEnable" name="$sIdEnable"/>
HTML,
$sVersion,
$sLabel,
$sCode,
];
}
return $this->GetTableData('Extensions', $aColumns, $aExtensions);
}
private function GetTableData(string $sTableName, array $aColumns, array $aData): array
{
if (empty($aData)) {
return [
'Type' => 'Table',
'Columns' => [['label' => '']],
'Data' => [[ Dict::S('DataFeatureRemoval:Table:Empty')]],
];
}
$aNewColumns = [];
foreach ($aColumns as $sColumn) {
$aNewColumns[] = ['label' => Dict::S("DataFeatureRemoval:Table:$sTableName:$sColumn", Dict::S("DataFeatureRemoval:Column:$sColumn", $sColumn))];
}
$aColumns = $aNewColumns;
return [
'Type' => 'Table',
'Columns' => $aColumns,
'Data' => $aData,
];
}
/**
* @return void
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
*/
private function ValidateTransactionId(): void
{
if (empty($_POST)) {
return;
}
$sTransactionId = utils::ReadPostedParam('transaction_id', null, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID);
IssueLog::Debug(__FUNCTION__.": Transaction [$sTransactionId]");
if (empty($sTransactionId) || !utils::IsTransactionValid($sTransactionId, false)) {
throw new DataFeatureRemovalException(Dict::S("iTopUpdate:Error:InvalidToken"));
}
}
/**
* @return array
*/
public function ReadRemovedExtensions(): array
{
if (count($this->aSelectedExtensionsForCheck) > 0) {
return $this->aSelectedExtensionsForCheck;
}
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []);
foreach ($aSelectedExtensionsFromUI as $sCode => $aData) {
$sValue = $aData['enable'] ?? 'off';
if (($sValue) === 'on') {
$this->aSelectedExtensionsForCheck[] = $sCode;
}
}
// Add source removed to check
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
if ($oExtension->bRemovedFromDisk) {
$this->aSelectedExtensionsForCheck[] = $sCode;
}
}
return $this->aSelectedExtensionsForCheck;
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace Combodo\iTop\DataFeatureRemoval\Entity;
class DeletionPlanSummaryEntity
{
public string $sClass;
/**
* @var int : DEL_MANUAL|DEL_AUTO|DEL_SILENT|DEL_MOVEUP|DEL_NONE
* @see \AttributeDefinition DEL_xxx
*/
public int $iMode = 0;
public ?string $sIssue = null;
public int $iUpdateCount = 0;
public int $iDeleteCount = 0;
/**
* @param string $sClass
*/
public function __construct(string $sClass)
{
$this->sClass = $sClass;
}
}

View File

@@ -1,71 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Helper;
use Config;
use MetaModel;
use utils;
class DataFeatureRemovalConfig
{
private static DataFeatureRemovalConfig $oInstance;
protected function __construct()
{
}
final public static function GetInstance(): DataFeatureRemovalConfig
{
if (!isset(static::$oInstance)) {
static::$oInstance = new DataFeatureRemovalConfig();
}
return static::$oInstance;
}
public function Get(string $sParamName, $default = null)
{
return MetaModel::GetModuleSetting(DataFeatureRemovalHelper::MODULE_NAME, $sParamName, $default);
}
public function GetBoolean(string $sParamName, $default = null): bool
{
$res = $this->Get($sParamName, $default);
return boolval($res);
}
public function IsEnabled(): bool
{
return $this->GetBoolean('enable', false);
}
public function Set(string $sParamName, $value)
{
$oConfig = utils::GetConfig();
$oConfig->SetModuleSetting(DataFeatureRemovalHelper::MODULE_NAME, $sParamName, $value);
}
/**
* @param \Config|null $oConfig
*
* @return void
* @throws \ConfigException
* @throws \CoreException
*/
public function SaveItopConfiguration(Config $oConfig = null)
{
if (is_null($oConfig)) {
$oConfig = utils::GetConfig();
}
$sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php';
@chmod($sConfigFile, 0770); // Allow overwriting the file
$oConfig->WriteToFile($sConfigFile);
@chmod($sConfigFile, 0444); // Read-only
}
}

View File

@@ -1,30 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Helper;
use Exception;
use Throwable;
class DataFeatureRemovalException extends Exception
{
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null, array $aContext = [])
{
if (!is_null($previous)) {
$sStack = $previous->getTraceAsString();
$sError = $previous->getMessage();
} else {
$sStack = $this->getTraceAsString();
$sError = '';
}
$aContext['error'] = $sError;
$aContext['stack'] = $sStack;
DataFeatureRemovalLog::Error($message, null, $aContext);
parent::__construct($message, $code, $previous);
}
}

View File

@@ -1,23 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Helper;
class DataFeatureRemovalHelper
{
public const MODULE_NAME = 'combodo-data-feature-removal';
public static function IsTimeLimitExceeded(int $iUnixTimeLimit): bool
{
if ($iUnixTimeLimit === 0) {
//no time limit
return false;
}
return (time() > $iUnixTimeLimit);
}
}

View File

@@ -1,25 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Helper;
use LogAPI;
class DataFeatureRemovalLog extends LogAPI
{
public const CHANNEL_DEFAULT = 'DataFeatureRemoval';
protected static $m_oFileLog = null;
public static function Enable($sTargetFile = null)
{
if (empty($sTargetFile)) {
$sTargetFile = APPROOT.'log/error.log';
}
parent::Enable($sTargetFile);
}
}

View File

@@ -1,48 +0,0 @@
<?php
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalConfig;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Service\BackgroundOperationService;
use Combodo\iTop\DataFeatureRemoval\Service\DeletionPlanService;
class DataFeatureRemovalBackgroundTask implements iBackgroundProcess
{
/**
* @inheritDoc
*/
public function GetPeriodicity()
{
return DataFeatureRemovalConfig::GetInstance()->Get('cron_periodicity_in_s', 10);
}
/**
* @inheritDoc
*/
public function Process($iUnixTimeLimit)
{
$iCount = 0;
while ($oBackgroundOperation = BackgroundOperationService::GetInstance()->GetNext()) {
$aClasses = BackgroundOperationService::GetInstance()->GetClasses($oBackgroundOperation);
$aRes = DeletionPlanService::GetInstance()->ExecuteDeletionPlan($aClasses, $iUnixTimeLimit);
IssueLog::Info(__METHOD__, null, $aRes);
IssueLog::Debug(__METHOD__, null, [
'$iUnixTimeLimit' => $iUnixTimeLimit,
'time' => time(),
'timeout reached' => DataFeatureRemovalHelper::IsTimeLimitExceeded($iUnixTimeLimit),
]);
if (DataFeatureRemovalHelper::IsTimeLimitExceeded($iUnixTimeLimit)) {
//timeout reached
return "Handled $iCount operations.";
}
//execution finished before timeout: nothing left to remove
$oBackgroundOperation->DBDelete();
$iCount++;
}
return "Handled $iCount operations.";
}
}

View File

@@ -1,105 +0,0 @@
<?php
namespace Combodo\iTop\DataFeatureRemoval\Service;
use DataFeatureRemovalBackgroundOperation;
use DBObjectSet;
use DBSearch;
use MetaModel;
class BackgroundOperationService
{
private static BackgroundOperationService $oInstance;
protected function __construct()
{
}
final public static function GetInstance(): BackgroundOperationService
{
if (!isset(self::$oInstance)) {
self::$oInstance = new BackgroundOperationService();
}
return self::$oInstance;
}
final public static function SetInstance(?BackgroundOperationService $oInstance): void
{
static::$oInstance = $oInstance;
}
/**
* @return \DataFeatureRemovalBackgroundOperation
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
*/
public function GetNext(): ?DataFeatureRemovalBackgroundOperation
{
$sOQL = <<<OQL
SELECT DataFeatureRemovalBackgroundOperation
OQL;
$oSet = new DBObjectSet(DBSearch::FromOQL($sOQL), ['creation_date' => true]);
/** @var DataFeatureRemovalBackgroundOperation $oDBObject */
$oDBObject = $oSet->Fetch();
return $oDBObject;
}
/**
* @param array $aExtensionsCodes
* @param array $aClasses
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function CreateOperation(array $aExtensionsCodes, array $aClasses): void
{
sort($aExtensionsCodes);
sort($aClasses);
$aValues = [
'creation_date' => time(),
'features_code' => '|'.implode('|', $aExtensionsCodes).'|',
'classes' => implode(',', $aClasses),
];
$oObj = MetaModel::NewObject('DataFeatureRemovalBackgroundOperation', $aValues);
$oObj->DBWrite();
}
/**
* @param string $sExtensionCode
* @return bool
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function IsExtensionBeingCleaned(string $sExtensionCode): bool
{
$sOQL = <<<OQL
SELECT DataFeatureRemovalBackgroundOperation WHERE features_code LIKE '%|$sExtensionCode|%'
OQL;
$oSet = new DBObjectSet(DBSearch::FromOQL($sOQL));
return $oSet->Count() > 0;
}
/**
* @param \DataFeatureRemovalBackgroundOperation $oBackgroundOperation
* @return array
*/
public function GetClasses(DataFeatureRemovalBackgroundOperation $oBackgroundOperation): array
{
return explode(',', $oBackgroundOperation->Get('classes'));
}
}

View File

@@ -1,80 +0,0 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\DataFeatureRemoval\Service;
use iTopExtension;
use iTopExtensionsMap;
use MetaModel;
class DataFeatureRemoverExtensionService
{
private static DataFeatureRemoverExtensionService $oInstance;
private array $aItopExtensions = [];
private array $aIncludingExtensionsByModuleName = [];
protected function __construct()
{
}
final public static function GetInstance(): DataFeatureRemoverExtensionService
{
if (!isset(self::$oInstance)) {
self::$oInstance = new DataFeatureRemoverExtensionService();
}
return self::$oInstance;
}
final public static function SetInstance(?DataFeatureRemoverExtensionService $oInstance): void
{
self::$oInstance = $oInstance;
}
/**
* @param string $sModuleName
*
* @return array
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
*/
public function GetIncludingExtensions(string $sModuleName): array
{
if (count($this->aIncludingExtensionsByModuleName) === 0) {
foreach ($this->ReadItopExtensions() as $oExtension) {
$aModuleNames = $oExtension->aModules;
if (is_array($aModuleNames) && count($aModuleNames) > 0) {
foreach ($aModuleNames as $sModule) {
$aExtensions = $this->aIncludingExtensionsByModuleName[$sModule] ?? [];
$aExtensions[] = $oExtension->sLabel.'/'.$oExtension->sVersion;
$this->aIncludingExtensionsByModuleName[$sModule] = $aExtensions;
}
}
}
}
return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
}
/**
* @return iTopExtension[]
*/
public function ReadItopExtensions(): array
{
if (count($this->aItopExtensions) === 0) {
$oExtensionsMap = new iTopExtensionsMap();
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
$this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true);
uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
});
}
return $this->aItopExtensions;
}
}

View File

@@ -1,212 +0,0 @@
<?php
namespace Combodo\iTop\DataFeatureRemoval\Service;
use CMDBSource;
use Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use DBObjectSearch;
use DeletionPlan;
use MetaModel;
class DeletionPlanService
{
private static DeletionPlanService $oInstance;
public int $iExecutionCount = 0;
protected function __construct()
{
}
final public static function GetInstance(): DeletionPlanService
{
if (!isset(self::$oInstance)) {
self::$oInstance = new DeletionPlanService();
}
return self::$oInstance;
}
final public static function SetInstance(?DeletionPlanService $oInstance): void
{
self::$oInstance = $oInstance;
}
/**
* Get a summary of the deletion plan computed for the classes.
* The result is used for display
*
* @param array|null $aClasses
*
* @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity>
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function GetDeletionPlanSummary(?array $aClasses): array
{
$aSummary = [];
if (is_null($aClasses)) {
return $aSummary;
}
$oDeletionPlan = $this->GetDeletionPlan($aClasses);
foreach ($oDeletionPlan->ListUpdates() as $sClass => $aUpdates) {
$oDeletionPlanSummaryEntity = new DeletionPlanSummaryEntity($sClass);
$oDeletionPlanSummaryEntity->iUpdateCount = count($aUpdates);
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
}
foreach ($oDeletionPlan->ListDeletes() as $sClass => $aDeletes) {
$oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass);
$oDeletionPlanSummaryEntity->iDeleteCount = count($aDeletes);
$aDelete = array_shift($aDeletes);
$oDeletionPlanSummaryEntity->iMode = $aDelete['mode'];
$oDeletionPlanSummaryEntity->sIssue = $aDelete['issue'] ?? null;
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
}
return $aSummary;
}
/**
* @param string $sClass
*
* @return \DBObject[]
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \Exception
*/
private function GetAllObjects(string $sClass): array
{
$oFilter = new DBObjectSearch($sClass);
$oFilter->AllowAllData();
$oSet = new \DBObjectSet($oFilter);
return $oSet->ToArray();
}
/**
* @since 3.3.0
* @param array $aClasses
* @param int $iUnixTimeLimit : max execution time in seconds since Epoch before stopping deletion. by default: no limit (ie remove all without stop)
* @param int $iMaxExecutionCount : max execution count before stopping deletion. by default: no limit (ie remove all without stop)
*
* @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity>
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function ExecuteDeletionPlan(array $aClasses, int $iUnixTimeLimit = 0, int $iMaxExecutionCount = -1): array
{
$oDeletionPlan = $this->GetDeletionPlan($aClasses);
if (count($oDeletionPlan->GetIssues()) > 0) {
throw new DataFeatureRemovalException("Deletion Plan cannot be executed due to issues");
}
$this->iExecutionCount = 0;
$aSummary = [];
foreach ($oDeletionPlan->ListUpdates() as $sClass => $aToUpdate) {
$oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass);
foreach ($aToUpdate as $aData) {
if ($this->IsTimeLimitExceeded($iUnixTimeLimit, $iMaxExecutionCount)) {
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
return $aSummary;
}
$this->iExecutionCount++;
$oToUpdate = $aData['to_reset'];
/** @var \DBObject $oToUpdate */
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) {
$oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
}
$oToUpdate->DBUpdate();
$oDeletionPlanSummaryEntity->iUpdateCount++;
}
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
}
foreach ($oDeletionPlan->ListDeletes() as $sClass => $aDeletes) {
$oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass);
foreach ($aDeletes as $sId => $aDelete) {
if ($this->IsTimeLimitExceeded($iUnixTimeLimit, $iMaxExecutionCount)) {
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
return $aSummary;
}
$this->iExecutionCount++;
try {
CMDBSource::Query('START TRANSACTION');
// Delete any existing change tracking about the current object
$oFilter = new DBObjectSearch('CMDBChangeOp');
$oFilter->AddCondition('objclass', $sClass, '=');
$oFilter->AddCondition('objkey', $sId, '=');
MetaModel::PurgeData($oFilter);
// Delete the entry
$aClassesToRemove = array_merge(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL), MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false));
foreach ($aClassesToRemove as $sParentClass) {
$oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id");
$sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]);
CMDBSource::DeleteFrom($sQuery);
}
CMDBSource::Query('COMMIT');
} catch (\Exception $e) {
\IssueLog::Exception(__METHOD__.": Cleanup failed", $e);
CMDBSource::Query('ROLLBACK');
throw $e;
}
$oDeletionPlanSummaryEntity->iDeleteCount++;
}
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
}
return $aSummary;
}
/**
* Get a deletion plan for all the objects of the classes
*
* @param array $aClasses array of class names to clean
*
* @return \DeletionPlan
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function GetDeletionPlan(array $aClasses): DeletionPlan
{
$oDeletionPlan = new DeletionPlan();
foreach ($aClasses as $sClass) {
$aObjects = $this->GetAllObjects($sClass);
foreach ($aObjects as $oObject) {
$oObject->CheckToDelete($oDeletionPlan);
}
}
return $oDeletionPlan;
}
public function IsTimeLimitExceeded(int $iUnixTimeLimit, int $iMaxExecutionCount = -1): bool
{
if (($iMaxExecutionCount !== -1) && ($iMaxExecutionCount <= $this->iExecutionCount)) {
return true;
}
return DataFeatureRemovalHelper::IsTimeLimitExceeded($iUnixTimeLimit);
}
}

View File

@@ -1,35 +0,0 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:DeletionPlan:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:DeletionPlan:SubTitle'|dict_format(iQueryCount) } %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIPanel %}
{% if bDeletionPossible %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% for sKey, sCode in aExtensionsCode %}
{% UIInput ForHidden { sName:"aExtensionsCode[" ~ sKey ~ "]", sValue:sCode } %}
{% endfor %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoAsyncDeletion'|dict_s, sName:'btn_deletion', sId:'btn_async_deletion', sValue: 'async_deletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{{ 'DataFeatureRemoval:DeletionPlan:ToManyOperations'|dict_s }}
{% endif %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}

View File

@@ -1,14 +0,0 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:DoDeletion:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:DoDeletion:SubTitle'|dict_s } %}
{% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %}
{% EndUIPanel %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back_to_main', sId:'btn_back_to_main', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}

View File

@@ -1,24 +0,0 @@
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% if bHasData %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:SubTitle'|dict_format(iCount) } %}
{% UIDataTable ForForm { sRef:'aAnalysisDataTable', aColumns:aAnalysisDataTable.Columns, aData:aAnalysisDataTable.Data} %}{% EndUIDataTable %}
{% EndUIPanel %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DeletionPlan'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% for sKey, sCode in aExtensionsCode %}
{% UIInput ForHidden { sName:"aExtensionsCode[" ~ sKey ~ "]", sValue:sCode } %}
{% endfor %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:PlanDeletion'|dict_s, sName:'btn_plandeletion', sId:'btn_plandeletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% endif %}

View File

@@ -1,16 +0,0 @@
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIForm Standard {} %}
{% UIInput ForHidden {sName:'operation', sValue:'Analyze'} %}
{% UIInput ForHidden {sName:'transaction_id', sValue:sTransactionId} %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Features:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aExtensions', aColumns:aExtensions.Columns, aData:aExtensions.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Analyze'|dict_s, sName:'btn_apply', sId:'btn_apply', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}

View File

@@ -1,37 +0,0 @@
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{# Usable variables: #}
{# * sTitle => page title #}
{# * sMessage => success message #}
{# * sError => error message #}
{# DataFeatureRemoval #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:Main:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Main:SubTitle'|dict_s } %}
{% UIAlert ForInformation { sTitle:'DataFeatureRemoval:Helper:Title'|dict_s } %}
{{ 'DataFeatureRemoval:Helper:Desc1'|dict_s }}<BR>
{{ 'DataFeatureRemoval:Helper:Desc2'|dict_s }}
{% EndUIAlert %}
{% if null != DataFeatureRemovalErrorMessage %}
<div id="feature_removal_error_msg_div" style="display:block">
{% UIAlert ForFailure { sTitle:'DataFeatureRemoval:Failure:Title'|dict_s, sId: 'feature_removal_error_msg', sContent:DataFeatureRemovalErrorMessage } %}
{% EndUIAlert %}
</div>
{% endif %}
{% include 'Features.html.twig' %}
{% include 'ExtensionRemovalData.html.twig' %}
{% if bAnalysisOk %}
{{ "DataFeatureRemoval:Analysis:Ok"|dict_s }}
{% UIToolbar ForButton {} %}
<a href="{{ sSetupUrl }}">
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Setup'|dict_s, sName:'btn_setup', sId:'btn_setup', bIsSubmit:false} %}
</a>
{% EndUIToolbar %}
{% endif %}
{% EndUIPanel %}

View File

@@ -1,25 +0,0 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464::getLoader();

View File

@@ -1,579 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var string|null */
private $apcuPrefix;
/**
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return list<string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
$paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@@ -1,19 +0,0 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => $baseDir . '/src/Controller/DataFeatureRemovalController.php',
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanSummaryEntity' => $baseDir . '/src/Entity/DeletionPlanSummaryEntity.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => $baseDir . '/src/Helper/DataFeatureRemovalConfig.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => $baseDir . '/src/Helper/DataFeatureRemovalException.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => $baseDir . '/src/Helper/DataFeatureRemovalHelper.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => $baseDir . '/src/Helper/DataFeatureRemovalLog.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\BackgroundOperationService' => $baseDir . '/src/Service/BackgroundOperationService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Service/DataFeatureRemoverExtensionService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DeletionPlanService' => $baseDir . '/src/Service/DeletionPlanService.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -1,9 +0,0 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -1,11 +0,0 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Combodo\\iTop\\DataFeatureRemoval\\' => array($baseDir . '/src'),
'' => array($baseDir . '/src/NoNamespace'),
);

View File

@@ -1,37 +0,0 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4f96a7199e2c0d90e547333758b26464::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
return $loader;
}
}

View File

@@ -1,50 +0,0 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit4f96a7199e2c0d90e547333758b26464
{
public static $prefixLengthsPsr4 = array (
'C' =>
array (
'Combodo\\iTop\\DataFeatureRemoval\\' => 32,
),
);
public static $prefixDirsPsr4 = array (
'Combodo\\iTop\\DataFeatureRemoval\\' =>
array (
0 => __DIR__ . '/../..' . '/src',
),
);
public static $fallbackDirsPsr4 = array (
0 => __DIR__ . '/../..' . '/src/NoNamespace',
);
public static $classMap = array (
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php',
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanSummaryEntity' => __DIR__ . '/../..' . '/src/Entity/DeletionPlanSummaryEntity.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalConfig.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalException.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalHelper.php',
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalLog.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\BackgroundOperationService' => __DIR__ . '/../..' . '/src/Service/BackgroundOperationService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Service/DataFeatureRemoverExtensionService.php',
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DeletionPlanService' => __DIR__ . '/../..' . '/src/Service/DeletionPlanService.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$prefixDirsPsr4;
$loader->fallbackDirsPsr4 = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$fallbackDirsPsr4;
$loader->classMap = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -10,7 +10,6 @@ namespace Combodo\iTop\DBTools\Service;
use CMDBSource;
use DBObjectSearch;
use DBObjectSet;
use IssueLog;
class DBToolsUtils
{

View File

@@ -54,6 +54,15 @@
</modules>
<default>true</default>
</choice>
<choice>
<extension_code>itop-flow-map</extension_code>
<title>Application Data Flows</title>
<description>Modelize flows between your applications, with impacts analysis</description>
<modules type="array">
<module>itop-flow-map</module>
</modules>
<default>true</default>
</choice>
<choice>
<extension_code>itop-config-mgmt-storage</extension_code>
<title>Storage Devices</title>
@@ -80,11 +89,20 @@
<modules type="array">
<module>itop-container-mgmt</module>
</modules>
<default>false</default>
<default>true</default>
</choice>
</options>
</sub_options>
</choice>
<choice>
<extension_code>itop-flow-map</extension_code>
<title>Data flow</title>
<description>Map data flows between applications</description>
<modules type="array">
<module>itop-flow-map</module>
</modules>
<default>false</default>
</choice>
</options>
</step>
<step>
@@ -232,7 +250,7 @@
<choice>
<extension_code>itop-problem-mgmt</extension_code>
<title>Problem Management</title>
<description>Select this option to track "Problems" in iTop.</description>
<description>Select this option track "Problems" in iTop.</description>
<modules type="array">
<module>itop-problem-mgmt</module>
</modules>

View File

@@ -131,7 +131,7 @@ try {
$oPage = new JsonPage();
$oPage->SetOutputDataOnly(true);
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
if ($oRestoreMutex->IsLocked()) {
DisplayErrorAndDie($oPage, '<p>'.Dict::S('bkp-restore-running').'</p>');
@@ -156,7 +156,7 @@ try {
require_once(APPROOT.'/setup/backup.class.inc.php');
require_once(__DIR__.'/dbrestore.class.inc.php');
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
try {
set_time_limit(0);

View File

@@ -97,7 +97,7 @@ class DBRestore extends DBBackup
*
* @uses \RunTimeEnvironment::CompileFrom()
*/
public function RestoreFromCompressedBackup($sFile, $sEnvironment = ITOP_DEFAULT_ENV)
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
{
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
IssueLog::Info("Backup Restore - Acquiring the LOCK 'restore.$sEnvironment'");

View File

@@ -126,7 +126,7 @@ function ExecuteMainOperation($oP)
if (MetaModel::GetConfig()->Get('demo_mode')) {
$oP->p("Sorry, iTop is in demonstration mode: the feature is disabled");
} else {
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
$oRestore->RestoreFromCompressedBackup($sBackupFile, $sEnvironment);
}
}

View File

@@ -4197,6 +4197,10 @@
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_MANUAL</on_target_delete>
</field>
<field id="osfamily_id" xsi:type="AttributeExternalField">
<extkey_attcode>osversion_id</extkey_attcode>
<target_attcode>osfamily_id</target_attcode>
</field>
<field id="osversion_name" xsi:type="AttributeExternalField">
<extkey_attcode>osversion_id</extkey_attcode>
<target_attcode>name</target_attcode>
@@ -4218,9 +4222,12 @@
</item>
<item id="fieldset:Software:moreinfo">
<items>
<item id="osversion_id">
<item id="osfamily_id">
<rank>10</rank>
</item>
<item id="osversion_id">
<rank>20</rank>
</item>
</items>
<rank>20</rank>
</item>
@@ -4665,6 +4672,10 @@
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_MANUAL</on_target_delete>
</field>
<field id="osfamily_id" xsi:type="AttributeExternalField">
<extkey_attcode>osversion_id</extkey_attcode>
<target_attcode>osfamily_id</target_attcode>
</field>
<field id="osversion_name" xsi:type="AttributeExternalField">
<extkey_attcode>osversion_id</extkey_attcode>
<target_attcode>name</target_attcode>
@@ -4704,6 +4715,9 @@
<item id="fieldset:ConfigMgmt:moreinfo">
<rank>20</rank>
<items>
<item id="osfamily_id">
<rank>10</rank>
</item>
<item id="osversion_id">
<rank>30</rank>
</item>
@@ -5107,7 +5121,7 @@
</complementary_attributes>
</naming>
<style>
<icon/>
<icon>images/icons8-os-version-software.svg</icon>
</style>
<reconciliation>
<attributes>
@@ -5218,7 +5232,7 @@
<image_attribute>logo</image_attribute>
</fields_semantic>
<style>
<icon/>
<icon>images/icons8-os-family-software.svg</icon>
</style>
<reconciliation>
<attributes>
@@ -5694,7 +5708,7 @@
</attributes>
</naming>
<style>
<icon/>
<icon>images/icons8-ios-version-software.svg</icon>
</style>
<reconciliation>
<attributes>
@@ -8338,6 +8352,22 @@
<title>Menu:ConfigManagement:SWAndApps</title>
<icon>../images/icons/icons8-software.svg</icon>
</dashlet>
<dashlet id="Software" xsi:type="DashletBadge">
<rank>0.1</rank>
<class>Software</class>
</dashlet>
<dashlet id="OSFamily" xsi:type="DashletBadge">
<rank>0.2</rank>
<class>OSFamily</class>
</dashlet>
<dashlet id="OSVersion" xsi:type="DashletBadge">
<rank>0.3</rank>
<class>OSVersion</class>
</dashlet>
<dashlet id="IOSVersion" xsi:type="DashletBadge">
<rank>0.4</rank>
<class>IOSVersion</class>
</dashlet>
<dashlet id="5" xsi:type="DashletBadge">
<rank>1</rank>
<class>Middleware</class>

View File

@@ -948,6 +948,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Všechna zařízení, kde je tato záplata (patch) instalována',
'Class:OSPatch/Attribute:osversion_id' => 'Verze OS',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Název verze OS',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1012,6 +1014,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'Verze OS',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'Název verze OS',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuální stroje (VM)',

View File

@@ -947,6 +947,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'All the systems where this patch is installed~~',
'Class:OSPatch/Attribute:osversion_id' => 'OS Version',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'OS versionsnavn',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1011,6 +1013,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'OS-Version',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'OS versionsnavn',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuelle Maskiner',

View File

@@ -947,6 +947,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Alle Systeme, auf denen dieser Patch installiert ist',
'Class:OSPatch/Attribute:osversion_id' => 'OS Version',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'OS-Versionsname',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1011,6 +1013,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'OS-Version',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'OS-Versionsname',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuelle Maschinen',

View File

@@ -167,7 +167,7 @@ Dict::Add('EN US', 'English', 'English', [
Dict::Add('EN US', 'English', 'English', [
'Class:Rack' => 'Rack',
'Class:Rack+' => 'A physical cabinet for Datacenter Devices and Chassis.',
'Class:Rack+' => 'A physical cabinet for Datacenter Devices and Enclosures.',
'Class:Rack/ComplementaryName' => '%1$s - %2$s',
'Class:Rack/Attribute:nb_u' => 'Rack units',
'Class:Rack/Attribute:nb_u+' => '',
@@ -963,6 +963,8 @@ Dict::Add('EN US', 'English', 'English', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'All the systems where this patch is installed',
'Class:OSPatch/Attribute:osversion_id' => 'OS version',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'OS version name',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1027,6 +1029,8 @@ Dict::Add('EN US', 'English', 'English', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'OS version',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family',
'Class:OSLicence/Attribute:osfamily_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'OS version name',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtual machines',

View File

@@ -945,6 +945,8 @@ Dict::Add('EN GB', 'British English', 'British English', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'All the systems where this patch is installed',
'Class:OSPatch/Attribute:osversion_id' => 'OS version',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'OS version name',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('EN GB', 'British English', 'British English', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'OS version',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'OS version name',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtual machines',

View File

@@ -943,7 +943,9 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:OSPatch/Attribute:functionalcis_list' => 'Dispositivos',
'Class:OSPatch/Attribute:functionalcis_list+' => 'Dispositivos',
'Class:OSPatch/Attribute:osversion_id' => 'Versión de SO',
'Class:OSPatch/Attribute:osversion_id+' => 'Versión de SO',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Versión de SO',
'Class:OSPatch/Attribute:osversion_name+' => 'Versión de SO',
]);
@@ -1008,6 +1010,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'Versión de SO',
'Class:OSLicence/Attribute:osversion_id+' => 'Versión de SO',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '',
'Class:OSLicence/Attribute:osversion_name' => 'Versión de SO',
'Class:OSLicence/Attribute:osversion_name+' => 'Versión de SO',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Máquinas Virtuales',

View File

@@ -1068,6 +1068,8 @@ Dict::Add('FR FR', 'French', 'Français', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Tous les systèmes où ce patch est installé',
'Class:OSPatch/Attribute:osversion_id' => 'Version OS',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'Famille d\'OS',
'Class:OSPatch/Attribute:osfamily_id+' => 'Déduite de la version d\'OS sélectionnée',
'Class:OSPatch/Attribute:osversion_name' => 'Nom Version OS',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1143,6 +1145,8 @@ Dict::Add('FR FR', 'French', 'Français', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'Version OS',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'Famille d\'OS',
'Class:OSLicence/Attribute:osfamily_id+' => 'Déduite de la version d\'OS sélectionnée',
'Class:OSLicence/Attribute:osversion_name' => 'Nom Version OS',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Machines virtuelles',

View File

@@ -36,23 +36,6 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
// Class:<class_name>/UniquenessRule:<rule_code>
// Class:<class_name>/UniquenessRule:<rule_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
// Class:<class_name>/UniquenessRule:<rule_code>
// Class:<class_name>/UniquenessRule:<rule_code>+
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -946,6 +929,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Rendszerek, amelyekre telepítve lett ez az OS javítócsomag',
'Class:OSPatch/Attribute:osversion_id' => 'OS verzió',
'Class:OSPatch/Attribute:osversion_id+' => '~~',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '~~',
'Class:OSPatch/Attribute:osversion_name' => 'OS verzió név',
'Class:OSPatch/Attribute:osversion_name+' => '~~',
]);
@@ -1010,6 +995,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'OS verzió',
'Class:OSLicence/Attribute:osversion_id+' => '~~',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'OS verzió név',
'Class:OSLicence/Attribute:osversion_name+' => '~~',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuális gépek',

View File

@@ -946,6 +946,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Tutti i sistemi in cui questa patch è installata',
'Class:OSPatch/Attribute:osversion_id' => 'Versione del Sistema Operativo',
'Class:OSPatch/Attribute:osversion_id+' => '~~',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '~~',
'Class:OSPatch/Attribute:osversion_name' => 'Nome della Versione del Sistema Operativo',
'Class:OSPatch/Attribute:osversion_name+' => '~~',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'Versione del sistema operativo',
'Class:OSLicence/Attribute:osversion_id+' => '~~',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Nome della versione del sistema operativo',
'Class:OSLicence/Attribute:osversion_name+' => '~~',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Macchine virtuali',

View File

@@ -946,6 +946,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'All the systems where this patch is installed~~',
'Class:OSPatch/Attribute:osversion_id' => 'OSバージョン',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'OSバージョン名',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'OSバージョン',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'OSバージョン名',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => '仮想マシン',

View File

@@ -948,6 +948,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Alle systemen waarop deze patch is geïnstalleerd',
'Class:OSPatch/Attribute:osversion_id' => 'Versie besturingssysteem',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'Soort besturingssysteem',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Naam versie besturingssysteem',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1012,6 +1014,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'Versie besturingssysteem',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'Soort besturingssysteem',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Naam versie bestandssysteem',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuele machines',

View File

@@ -946,6 +946,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Wszystkie systemy, w których jest zainstalowana ta poprawka',
'Class:OSPatch/Attribute:osversion_id' => 'Wersja OS',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Nazwa wersji OS',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => 'Wersja OS',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Nazwa wersji OS',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Maszyny wirtualne',

View File

@@ -946,6 +946,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Todos os sistemas onde essa Atualização de SO está instalada',
'Class:OSPatch/Attribute:osversion_id' => 'Versão do SO',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Nome da versão do SO',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'Versão do SO',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Nome da versão do SO',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Máquinas virtuais (VMs)',

View File

@@ -947,6 +947,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Все системы, где установлен этот патч',
'Class:OSPatch/Attribute:osversion_id' => 'Версия ОС',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => 'Версия ОС',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1011,6 +1013,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'Версия ОС',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Версия ОС',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Виртуальные машины',

View File

@@ -946,6 +946,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'All the systems where this patch is installed~~',
'Class:OSPatch/Attribute:osversion_id' => 'Verzia OS',
'Class:OSPatch/Attribute:osversion_id+' => '~~',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '~~',
'Class:OSPatch/Attribute:osversion_name' => 'Názov OS verzie',
'Class:OSPatch/Attribute:osversion_name+' => '~~',
]);
@@ -1010,6 +1012,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'Verzia OS',
'Class:OSLicence/Attribute:osversion_id+' => '~~',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'Názov OS verzie',
'Class:OSLicence/Attribute:osversion_name+' => '~~',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Virtuálne zariadenia',

View File

@@ -947,6 +947,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Class:OSPatch/Attribute:functionalcis_list+' => 'Bu yamanın kurulduğu tüm sistemler',
'Class:OSPatch/Attribute:osversion_id' => 'OS Sürümü',
'Class:OSPatch/Attribute:osversion_id+' => '~~',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '~~',
'Class:OSPatch/Attribute:osversion_name' => 'OS Sürüm Adı',
'Class:OSPatch/Attribute:osversion_name+' => '~~',
]);
@@ -1011,6 +1013,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s~~',
'Class:OSLicence/Attribute:osversion_id' => 'OS Sürümü',
'Class:OSLicence/Attribute:osversion_id+' => '~~',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => 'OS Sürüm Adı',
'Class:OSLicence/Attribute:osversion_name+' => '~~',
'Class:OSLicence/Attribute:virtualmachines_list' => 'Sanal Makineler',

View File

@@ -963,6 +963,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:OSPatch/Attribute:functionalcis_list+' => '已安装此补丁的所有系统',
'Class:OSPatch/Attribute:osversion_id' => '操作系统版本',
'Class:OSPatch/Attribute:osversion_id+' => '',
'Class:OSPatch/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSPatch/Attribute:osfamily_id+' => '',
'Class:OSPatch/Attribute:osversion_name' => '名称',
'Class:OSPatch/Attribute:osversion_name+' => '',
]);
@@ -1027,6 +1029,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:OSLicence/ComplementaryName' => '%1$s - %2$s',
'Class:OSLicence/Attribute:osversion_id' => '操作系统版本',
'Class:OSLicence/Attribute:osversion_id+' => '',
'Class:OSLicence/Attribute:osfamily_id' => 'OS Family~~',
'Class:OSLicence/Attribute:osfamily_id+' => '~~',
'Class:OSLicence/Attribute:osversion_name' => '名称',
'Class:OSLicence/Attribute:osversion_name+' => '',
'Class:OSLicence/Attribute:virtualmachines_list' => '虚拟机',

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 48 48"
width="240px"
height="240px"
version="1.1"
id="svg8"
sodipodi:docname="icons8-ios-version-software.svg"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true"
inkscape:zoom="4.7666667"
inkscape:cx="64.405594"
inkscape:cy="137.83217"
inkscape:window-width="2560"
inkscape:window-height="1360"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<sodipodi:guide
position="24.038024,7.4691871"
orientation="1,0"
id="guide8"
inkscape:locked="false" />
<sodipodi:guide
position="17.329983,10.650049"
orientation="0,-1"
id="guide9"
inkscape:locked="false" />
</sodipodi:namedview>
<linearGradient
id="SVGID_1_"
x1="23.855"
x2="23.983"
y1="4.908"
y2="17.227"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#7dd8f3"
id="stop1" />
<stop
offset="1"
stop-color="#45b0d0"
id="stop2" />
</linearGradient>
<circle
cx="24"
cy="18.9"
r="15"
fill="url(#SVGID_1_)"
id="circle2" />
<linearGradient
id="SVGID_2_"
x1="18.175"
x2="29.825"
y1="19.021"
y2="19.021"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#3079d6"
id="stop3" />
<stop
offset="1"
stop-color="#297cd2"
id="stop4" />
</linearGradient>
<circle
cx="24"
cy="19"
r="5.8"
fill="url(#SVGID_2_)"
id="circle4" />
<circle
cx="24"
cy="19"
r="2.3"
fill="#fff"
id="circle5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.3,0-0.6,0-0.9H9C9,18.3,9,18.6,9,18.9z"
opacity=".05"
id="path5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.1,0-0.2,0-0.4H9C9,18.6,9,18.7,9,18.9z"
opacity=".07"
id="path6" />
<linearGradient
id="SVGID_3_"
x1="16.786"
x2="30.174"
y1="-440.286"
y2="-472.232"
gradientTransform="matrix(1 0 0 -1 0 -426)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#eba84b"
id="stop6" />
<stop
offset="1"
stop-color="#d97218"
id="stop7" />
</linearGradient>
<path
fill="url(#SVGID_3_)"
d="M41,44H7c-0.6,0-1-0.5-1-1V20c0-0.6,0.4-1,1-1h34c0.6,0,1,0.4,1,1v23C42,43.5,41.5,44,41,44z"
id="path7" />
<path
fill="#633412"
d="M20,23h8c0.6,0,1,0.4,1,1l0,0c0,0.6-0.4,1-1,1h-8c-0.6,0-1-0.4-1-1l0,0C19,23.4,19.4,23,20,23z"
id="path8" />
<g
opacity="0.05"
id="g4"
style="display:inline"
transform="matrix(0.71297721,0,0,0.71297721,5.7848117,15.025827)">
<path
d="m 23.884,17.895 c -1.408,-1.526 -3.274,-2.3 -5.546,-2.3 -2.431,0 -4.395,0.794 -5.838,2.359 -1.422,1.543 -2.144,3.607 -2.144,6.136 0,2.374 0.71,4.343 2.111,5.853 1.421,1.531 3.32,2.308 5.644,2.308 2.365,0 4.292,-0.787 5.727,-2.338 1.417,-1.53 2.136,-3.605 2.136,-6.168 0,-2.379 -0.703,-4.347 -2.09,-5.85 z m -3.309,9.273 c -0.599,0.699 -1.378,1.025 -2.454,1.025 -0.987,0 -1.729,-0.343 -2.333,-1.078 -0.636,-0.775 -0.959,-1.843 -0.959,-3.173 0,-1.334 0.332,-2.405 0.987,-3.185 0.629,-0.748 1.393,-1.097 2.404,-1.097 1.048,0 1.804,0.324 2.379,1.021 0.606,0.734 0.914,1.841 0.914,3.289 -0.001,1.396 -0.317,2.472 -0.938,3.198 z"
id="path3" />
<path
d="m 36.615,25.494 v 0 c -0.241,-0.519 -0.571,-0.995 -0.981,-1.419 -0.387,-0.397 -0.834,-0.762 -1.331,-1.081 -0.472,-0.306 -0.967,-0.592 -1.542,-0.888 -0.464,-0.203 -0.873,-0.391 -1.229,-0.569 -0.305,-0.15 -0.564,-0.306 -0.771,-0.46 -0.144,-0.108 -0.249,-0.22 -0.313,-0.333 -0.042,-0.074 -0.065,-0.186 -0.065,-0.322 0,-0.162 0.039,-0.235 0.069,-0.276 0.085,-0.118 0.193,-0.212 0.338,-0.292 0.18,-0.1 0.394,-0.173 0.633,-0.22 0.286,-0.054 0.574,-0.081 0.858,-0.081 1.046,0 1.894,0.229 2.522,0.683 0.308,0.219 0.706,0.249 1.039,0.078 0.336,-0.173 0.544,-0.514 0.544,-0.891 v -2.324 c 0,-0.384 -0.213,-0.728 -0.557,-0.896 -0.826,-0.408 -2.031,-0.607 -3.687,-0.607 -0.733,0 -1.459,0.088 -2.159,0.262 -0.733,0.182 -1.4,0.466 -1.98,0.845 -0.613,0.397 -1.116,0.913 -1.496,1.532 -0.396,0.647 -0.596,1.407 -0.596,2.258 0,0.676 0.116,1.285 0.345,1.813 0.221,0.509 0.53,0.973 0.917,1.376 0.355,0.372 0.782,0.717 1.268,1.027 0.436,0.277 0.906,0.549 1.467,0.848 0.442,0.201 0.857,0.395 1.245,0.58 0.338,0.161 0.634,0.331 0.878,0.503 0.185,0.131 0.325,0.269 0.417,0.408 0.034,0.052 0.079,0.143 0.079,0.328 0,0.34 -0.116,0.488 -0.291,0.607 -0.214,0.146 -0.674,0.32 -1.646,0.32 -0.226,0 -0.48,-0.024 -0.755,-0.073 -0.292,-0.052 -0.586,-0.125 -0.874,-0.219 -0.286,-0.093 -0.554,-0.205 -0.798,-0.334 -0.223,-0.117 -0.415,-0.248 -0.57,-0.39 -0.295,-0.268 -0.72,-0.337 -1.077,-0.174 -0.361,0.16 -0.595,0.519 -0.595,0.914 v 2.423 c 0,0.345 0.174,0.661 0.466,0.846 0.274,0.173 0.618,0.323 1.019,0.445 0.357,0.11 0.737,0.203 1.134,0.279 0.393,0.076 0.778,0.133 1.147,0.17 0.388,0.041 0.715,0.061 0.981,0.061 0.784,0 1.538,-0.077 2.239,-0.23 0.751,-0.162 1.429,-0.433 2.017,-0.804 0.625,-0.394 1.131,-0.913 1.502,-1.546 0.382,-0.65 0.574,-1.432 0.574,-2.327 0,-0.677 -0.129,-1.3 -0.385,-1.85 z"
id="path4" />
</g>
<g
opacity="0.07"
id="g6"
style="display:inline"
transform="matrix(0.71297721,0,0,0.71297721,5.7848117,15.025827)">
<path
d="m 18.338,16.095 c -2.285,0 -4.125,0.739 -5.47,2.198 -1.334,1.447 -2.011,3.397 -2.011,5.797 0,2.243 0.666,4.099 1.978,5.513 1.322,1.425 3.097,2.147 5.277,2.147 2.219,0 4.023,-0.732 5.36,-2.178 1.329,-1.435 2.003,-3.396 2.003,-5.828 0,-2.247 -0.658,-4.102 -1.958,-5.511 -1.31,-1.419 -3.052,-2.138 -5.179,-2.138 z m 3.674,7.877 c 0,1.518 -0.355,2.702 -1.057,3.521 -0.691,0.808 -1.618,1.2 -2.834,1.2 -1.133,0 -2.022,-0.412 -2.719,-1.261 -0.712,-0.867 -1.073,-2.041 -1.073,-3.49 0,-1.454 0.372,-2.635 1.104,-3.507 0.721,-0.857 1.633,-1.274 2.787,-1.274 1.192,0 2.096,0.394 2.764,1.203 0.682,0.826 1.028,2.04 1.028,3.608 z"
id="path5-3" />
<path
d="m 36.162,25.704 c -0.217,-0.467 -0.515,-0.897 -0.886,-1.28 -0.361,-0.371 -0.78,-0.711 -1.244,-1.01 -0.448,-0.29 -0.933,-0.571 -1.471,-0.85 -0.473,-0.207 -0.889,-0.398 -1.25,-0.579 -0.334,-0.165 -0.621,-0.337 -0.85,-0.509 -0.198,-0.149 -0.348,-0.312 -0.446,-0.483 -0.087,-0.151 -0.131,-0.344 -0.131,-0.571 0,-0.23 0.053,-0.416 0.163,-0.568 0.128,-0.178 0.293,-0.321 0.503,-0.438 0.226,-0.124 0.489,-0.216 0.781,-0.272 0.316,-0.06 0.636,-0.09 0.951,-0.09 1.153,0 2.099,0.261 2.813,0.775 0.153,0.109 0.354,0.125 0.52,0.04 0.167,-0.086 0.272,-0.258 0.272,-0.445 V 17.1 c 0,-0.19 -0.108,-0.364 -0.278,-0.448 -0.755,-0.374 -1.889,-0.556 -3.465,-0.556 -0.692,0 -1.378,0.083 -2.039,0.247 -0.678,0.168 -1.293,0.43 -1.829,0.778 -0.551,0.357 -1.002,0.82 -1.341,1.374 -0.347,0.568 -0.523,1.24 -0.523,1.997 0,0.606 0.102,1.149 0.303,1.613 0.197,0.453 0.472,0.867 0.82,1.229 0.33,0.345 0.725,0.664 1.175,0.951 0.425,0.271 0.885,0.536 1.406,0.814 0.445,0.203 0.862,0.397 1.252,0.584 0.364,0.174 0.684,0.357 0.951,0.546 0.236,0.167 0.42,0.35 0.547,0.543 0.108,0.165 0.161,0.362 0.161,0.602 0,0.46 -0.162,0.784 -0.509,1.021 -0.396,0.271 -1.045,0.407 -1.928,0.407 -0.255,0 -0.539,-0.027 -0.842,-0.081 -0.313,-0.056 -0.631,-0.135 -0.941,-0.235 -0.312,-0.102 -0.606,-0.225 -0.876,-0.367 -0.26,-0.137 -0.486,-0.292 -0.673,-0.462 -0.146,-0.133 -0.357,-0.169 -0.539,-0.087 -0.181,0.08 -0.297,0.259 -0.297,0.457 v 2.423 c 0,0.172 0.088,0.331 0.233,0.423 0.235,0.148 0.539,0.28 0.901,0.391 0.34,0.105 0.702,0.193 1.081,0.266 0.377,0.073 0.748,0.128 1.105,0.164 0.367,0.039 0.676,0.058 0.929,0.058 0.747,0 1.465,-0.073 2.133,-0.219 0.693,-0.15 1.317,-0.398 1.856,-0.738 0.557,-0.351 1.007,-0.813 1.337,-1.376 0.334,-0.57 0.503,-1.269 0.503,-2.073 0,-0.607 -0.114,-1.158 -0.338,-1.642 z"
id="path6-6" />
</g>
<path
fill="#ffffff"
d="m 18.697543,37.306366 c -1.457325,0 -2.624468,-0.47199 -3.500718,-1.417397 -0.876962,-0.944696 -1.315442,-2.173869 -1.315442,-3.68752 0,-1.6263 0.446322,-2.923206 1.339684,-3.891429 0.893359,-0.968223 2.106133,-1.452335 3.638321,-1.452335 1.419538,0 2.563153,0.469852 3.430135,1.41027 0.86698,0.940417 1.301182,2.168876 1.301182,3.687518 0,1.649829 -0.444183,2.954577 -1.332554,3.912818 -0.888368,0.958955 -2.075476,1.438075 -3.560608,1.438075 z m 0.077,-8.97567 c -0.926159,0 -1.679064,0.345081 -2.259426,1.035956 -0.581077,0.691588 -0.870545,1.600634 -0.870545,2.729278 0,1.123651 0.282338,2.027706 0.84559,2.714304 0.563967,0.686596 1.301898,1.029538 2.213795,1.029538 0.968223,0 1.731822,-0.326543 2.291509,-0.980343 0.558973,-0.653087 0.839174,-1.567837 0.839174,-2.74211 0,-1.208496 -0.271645,-2.141071 -0.81422,-2.799149 -0.543289,-0.658078 -1.291915,-0.987474 -2.245877,-0.987474 z"
id="path7-7"
style="display:inline;stroke-width:0.712977" />
<path
fill="#ffffff"
d="m 24.979585,36.735273 v -1.727544 c 0.155429,0.140455 0.339378,0.268078 0.553271,0.380728 0.213893,0.112651 0.44062,0.207476 0.68018,0.285193 0.23956,0.07771 0.479833,0.137604 0.719394,0.179669 0.23956,0.04207 0.460584,0.06345 0.663069,0.06345 0.705134,0 1.230599,-0.117641 1.575678,-0.352923 0.345795,-0.235283 0.518337,-0.575373 0.518337,-1.02241 0,-0.240273 -0.05775,-0.447749 -0.172542,-0.623855 -0.115502,-0.176104 -0.276634,-0.337237 -0.482685,-0.482684 -0.206764,-0.146161 -0.449889,-0.285905 -0.730088,-0.419943 -0.280201,-0.134042 -0.579651,-0.27307 -0.899065,-0.419231 -0.342942,-0.183237 -0.662356,-0.369323 -0.958955,-0.556836 -0.295885,-0.188225 -0.553269,-0.396415 -0.772154,-0.623855 -0.218884,-0.228153 -0.389999,-0.485537 -0.514769,-0.772153 -0.124772,-0.286618 -0.186801,-0.623143 -0.186801,-1.008151 0,-0.474843 0.106947,-0.887656 0.320841,-1.237728 0.213893,-0.349359 0.496231,-0.63954 0.846304,-0.866981 0.350072,-0.228152 0.748626,-0.397128 1.19495,-0.50764 0.446322,-0.110511 0.902628,-0.16541 1.367489,-0.16541 1.057346,0 1.828075,0.11978 2.312185,0.35934 v 1.656959 c -0.573234,-0.413527 -1.311163,-0.620289 -2.213792,-0.620289 -0.24883,0 -0.496946,0.02352 -0.743637,0.07059 -0.246691,0.04706 -0.467713,0.124771 -0.663069,0.23243 -0.195357,0.108374 -0.353636,0.24669 -0.475555,0.416379 -0.122632,0.168976 -0.183236,0.372889 -0.183236,0.613161 0,0.225301 0.04706,0.421369 0.14117,0.585354 0.09411,0.164698 0.231718,0.315137 0.412101,0.451314 0.180383,0.136179 0.402119,0.268793 0.663069,0.397842 0.260949,0.129761 0.562538,0.268792 0.906193,0.419944 0.352211,0.183236 0.685171,0.375738 0.997456,0.578224 0.312997,0.201773 0.587493,0.425648 0.824914,0.669486 0.237423,0.244551 0.425647,0.516195 0.563966,0.81422 0.13903,0.29945 0.208189,0.638827 0.208189,1.019557 0,0.511918 -0.103382,0.944694 -0.310145,1.296906 -0.206765,0.352923 -0.485537,0.639541 -0.83561,0.860563 -0.35007,0.22031 -0.752904,0.38073 -1.209209,0.479121 -0.455593,0.0991 -0.937565,0.147585 -1.445206,0.147585 -0.169688,0 -0.377165,-0.01282 -0.623854,-0.0385 -0.24669,-0.02568 -0.499797,-0.06274 -0.757896,-0.112652 -0.258098,-0.04919 -0.502648,-0.109085 -0.73294,-0.179668 -0.231003,-0.06987 -0.416379,-0.150439 -0.557548,-0.239562 z"
id="path8-5"
style="display:inline;stroke-width:0.712977" />
<text
xml:space="preserve"
style="font-size:7.01985px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.674702"
y="41.839462"
id="text19"><tspan
sodipodi:role="line"
id="tspan19"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.01985px;font-family:Futura-Medium;-inkscape-font-specification:Futura-Medium;stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.674702"
y="41.839462">x.y</tspan></text>
<text
xml:space="preserve"
style="font-size:7.01985px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.675184"
y="41.839504"
id="text19-7"><tspan
sodipodi:role="line"
id="tspan19-2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.01985px;font-family:Futura-Medium;-inkscape-font-specification:Futura-Medium;stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.675184"
y="41.839504">x.y</tspan></text>
<text
xml:space="preserve"
style="font-size:13.8667px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="9.1199589"
y="37.324699"
id="text19-5"><tspan
sodipodi:role="line"
id="tspan19-6"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:13.8667px;font-family:'Adwaita Sans';-inkscape-font-specification:'Adwaita Sans Semi-Bold';stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="9.1199589"
y="37.324699">I</tspan></text>
<text
xml:space="preserve"
style="font-size:13.8667px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="9.1539106"
y="37.267509"
id="text19-7-2"><tspan
sodipodi:role="line"
id="tspan19-2-9"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:13.8667px;font-family:'Adwaita Sans';-inkscape-font-specification:'Adwaita Sans Semi-Bold';stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="9.1539106"
y="37.267509">I</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 48 48"
width="240px"
height="240px"
version="1.1"
id="svg8"
sodipodi:docname="icons8-os-family-software.svg"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true"
inkscape:zoom="4.7666667"
inkscape:cx="91.993007"
inkscape:cy="189.44056"
inkscape:window-width="2560"
inkscape:window-height="1360"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<sodipodi:guide
position="24.038024,7.4691871"
orientation="1,0"
id="guide8"
inkscape:locked="false" />
</sodipodi:namedview>
<linearGradient
id="SVGID_1_"
x1="23.855"
x2="23.983"
y1="4.908"
y2="17.227"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#7dd8f3"
id="stop1" />
<stop
offset="1"
stop-color="#45b0d0"
id="stop2" />
</linearGradient>
<circle
cx="24"
cy="18.9"
r="15"
fill="url(#SVGID_1_)"
id="circle2" />
<linearGradient
id="SVGID_2_"
x1="18.175"
x2="29.825"
y1="19.021"
y2="19.021"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#3079d6"
id="stop3" />
<stop
offset="1"
stop-color="#297cd2"
id="stop4" />
</linearGradient>
<circle
cx="24"
cy="19"
r="5.8"
fill="url(#SVGID_2_)"
id="circle4" />
<circle
cx="24"
cy="19"
r="2.3"
fill="#fff"
id="circle5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.3,0-0.6,0-0.9H9C9,18.3,9,18.6,9,18.9z"
opacity=".05"
id="path5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.1,0-0.2,0-0.4H9C9,18.6,9,18.7,9,18.9z"
opacity=".07"
id="path6" />
<linearGradient
id="SVGID_3_"
x1="16.786"
x2="30.174"
y1="-440.286"
y2="-472.232"
gradientTransform="matrix(1 0 0 -1 0 -426)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#eba84b"
id="stop6" />
<stop
offset="1"
stop-color="#d97218"
id="stop7" />
</linearGradient>
<path
fill="url(#SVGID_3_)"
d="M41,44H7c-0.6,0-1-0.5-1-1V20c0-0.6,0.4-1,1-1h34c0.6,0,1,0.4,1,1v23C42,43.5,41.5,44,41,44z"
id="path7" />
<path
fill="#633412"
d="M20,23h8c0.6,0,1,0.4,1,1l0,0c0,0.6-0.4,1-1,1h-8c-0.6,0-1-0.4-1-1l0,0C19,23.4,19.4,23,20,23z"
id="path8" />
<g
opacity="0.05"
id="g4"
style="display:inline"
transform="matrix(0.8851155,0,0,0.8851155,3.0134076,13.351562)">
<path
d="m 23.884,17.895 c -1.408,-1.526 -3.274,-2.3 -5.546,-2.3 -2.431,0 -4.395,0.794 -5.838,2.359 -1.422,1.543 -2.144,3.607 -2.144,6.136 0,2.374 0.71,4.343 2.111,5.853 1.421,1.531 3.32,2.308 5.644,2.308 2.365,0 4.292,-0.787 5.727,-2.338 1.417,-1.53 2.136,-3.605 2.136,-6.168 0,-2.379 -0.703,-4.347 -2.09,-5.85 z m -3.309,9.273 c -0.599,0.699 -1.378,1.025 -2.454,1.025 -0.987,0 -1.729,-0.343 -2.333,-1.078 -0.636,-0.775 -0.959,-1.843 -0.959,-3.173 0,-1.334 0.332,-2.405 0.987,-3.185 0.629,-0.748 1.393,-1.097 2.404,-1.097 1.048,0 1.804,0.324 2.379,1.021 0.606,0.734 0.914,1.841 0.914,3.289 -0.001,1.396 -0.317,2.472 -0.938,3.198 z"
id="path3" />
<path
d="m 36.615,25.494 v 0 c -0.241,-0.519 -0.571,-0.995 -0.981,-1.419 -0.387,-0.397 -0.834,-0.762 -1.331,-1.081 -0.472,-0.306 -0.967,-0.592 -1.542,-0.888 -0.464,-0.203 -0.873,-0.391 -1.229,-0.569 -0.305,-0.15 -0.564,-0.306 -0.771,-0.46 -0.144,-0.108 -0.249,-0.22 -0.313,-0.333 -0.042,-0.074 -0.065,-0.186 -0.065,-0.322 0,-0.162 0.039,-0.235 0.069,-0.276 0.085,-0.118 0.193,-0.212 0.338,-0.292 0.18,-0.1 0.394,-0.173 0.633,-0.22 0.286,-0.054 0.574,-0.081 0.858,-0.081 1.046,0 1.894,0.229 2.522,0.683 0.308,0.219 0.706,0.249 1.039,0.078 0.336,-0.173 0.544,-0.514 0.544,-0.891 v -2.324 c 0,-0.384 -0.213,-0.728 -0.557,-0.896 -0.826,-0.408 -2.031,-0.607 -3.687,-0.607 -0.733,0 -1.459,0.088 -2.159,0.262 -0.733,0.182 -1.4,0.466 -1.98,0.845 -0.613,0.397 -1.116,0.913 -1.496,1.532 -0.396,0.647 -0.596,1.407 -0.596,2.258 0,0.676 0.116,1.285 0.345,1.813 0.221,0.509 0.53,0.973 0.917,1.376 0.355,0.372 0.782,0.717 1.268,1.027 0.436,0.277 0.906,0.549 1.467,0.848 0.442,0.201 0.857,0.395 1.245,0.58 0.338,0.161 0.634,0.331 0.878,0.503 0.185,0.131 0.325,0.269 0.417,0.408 0.034,0.052 0.079,0.143 0.079,0.328 0,0.34 -0.116,0.488 -0.291,0.607 -0.214,0.146 -0.674,0.32 -1.646,0.32 -0.226,0 -0.48,-0.024 -0.755,-0.073 -0.292,-0.052 -0.586,-0.125 -0.874,-0.219 -0.286,-0.093 -0.554,-0.205 -0.798,-0.334 -0.223,-0.117 -0.415,-0.248 -0.57,-0.39 -0.295,-0.268 -0.72,-0.337 -1.077,-0.174 -0.361,0.16 -0.595,0.519 -0.595,0.914 v 2.423 c 0,0.345 0.174,0.661 0.466,0.846 0.274,0.173 0.618,0.323 1.019,0.445 0.357,0.11 0.737,0.203 1.134,0.279 0.393,0.076 0.778,0.133 1.147,0.17 0.388,0.041 0.715,0.061 0.981,0.061 0.784,0 1.538,-0.077 2.239,-0.23 0.751,-0.162 1.429,-0.433 2.017,-0.804 0.625,-0.394 1.131,-0.913 1.502,-1.546 0.382,-0.65 0.574,-1.432 0.574,-2.327 0,-0.677 -0.129,-1.3 -0.385,-1.85 z"
id="path4" />
</g>
<g
opacity="0.07"
id="g6"
style="display:inline"
transform="matrix(0.8851155,0,0,0.8851155,3.0134076,13.351562)">
<path
d="m 18.338,16.095 c -2.285,0 -4.125,0.739 -5.47,2.198 -1.334,1.447 -2.011,3.397 -2.011,5.797 0,2.243 0.666,4.099 1.978,5.513 1.322,1.425 3.097,2.147 5.277,2.147 2.219,0 4.023,-0.732 5.36,-2.178 1.329,-1.435 2.003,-3.396 2.003,-5.828 0,-2.247 -0.658,-4.102 -1.958,-5.511 -1.31,-1.419 -3.052,-2.138 -5.179,-2.138 z m 3.674,7.877 c 0,1.518 -0.355,2.702 -1.057,3.521 -0.691,0.808 -1.618,1.2 -2.834,1.2 -1.133,0 -2.022,-0.412 -2.719,-1.261 -0.712,-0.867 -1.073,-2.041 -1.073,-3.49 0,-1.454 0.372,-2.635 1.104,-3.507 0.721,-0.857 1.633,-1.274 2.787,-1.274 1.192,0 2.096,0.394 2.764,1.203 0.682,0.826 1.028,2.04 1.028,3.608 z"
id="path5-3" />
<path
d="m 36.162,25.704 c -0.217,-0.467 -0.515,-0.897 -0.886,-1.28 -0.361,-0.371 -0.78,-0.711 -1.244,-1.01 -0.448,-0.29 -0.933,-0.571 -1.471,-0.85 -0.473,-0.207 -0.889,-0.398 -1.25,-0.579 -0.334,-0.165 -0.621,-0.337 -0.85,-0.509 -0.198,-0.149 -0.348,-0.312 -0.446,-0.483 -0.087,-0.151 -0.131,-0.344 -0.131,-0.571 0,-0.23 0.053,-0.416 0.163,-0.568 0.128,-0.178 0.293,-0.321 0.503,-0.438 0.226,-0.124 0.489,-0.216 0.781,-0.272 0.316,-0.06 0.636,-0.09 0.951,-0.09 1.153,0 2.099,0.261 2.813,0.775 0.153,0.109 0.354,0.125 0.52,0.04 0.167,-0.086 0.272,-0.258 0.272,-0.445 V 17.1 c 0,-0.19 -0.108,-0.364 -0.278,-0.448 -0.755,-0.374 -1.889,-0.556 -3.465,-0.556 -0.692,0 -1.378,0.083 -2.039,0.247 -0.678,0.168 -1.293,0.43 -1.829,0.778 -0.551,0.357 -1.002,0.82 -1.341,1.374 -0.347,0.568 -0.523,1.24 -0.523,1.997 0,0.606 0.102,1.149 0.303,1.613 0.197,0.453 0.472,0.867 0.82,1.229 0.33,0.345 0.725,0.664 1.175,0.951 0.425,0.271 0.885,0.536 1.406,0.814 0.445,0.203 0.862,0.397 1.252,0.584 0.364,0.174 0.684,0.357 0.951,0.546 0.236,0.167 0.42,0.35 0.547,0.543 0.108,0.165 0.161,0.362 0.161,0.602 0,0.46 -0.162,0.784 -0.509,1.021 -0.396,0.271 -1.045,0.407 -1.928,0.407 -0.255,0 -0.539,-0.027 -0.842,-0.081 -0.313,-0.056 -0.631,-0.135 -0.941,-0.235 -0.312,-0.102 -0.606,-0.225 -0.876,-0.367 -0.26,-0.137 -0.486,-0.292 -0.673,-0.462 -0.146,-0.133 -0.357,-0.169 -0.539,-0.087 -0.181,0.08 -0.297,0.259 -0.297,0.457 v 2.423 c 0,0.172 0.088,0.331 0.233,0.423 0.235,0.148 0.539,0.28 0.901,0.391 0.34,0.105 0.702,0.193 1.081,0.266 0.377,0.073 0.748,0.128 1.105,0.164 0.367,0.039 0.676,0.058 0.929,0.058 0.747,0 1.465,-0.073 2.133,-0.219 0.693,-0.15 1.317,-0.398 1.856,-0.738 0.557,-0.351 1.007,-0.813 1.337,-1.376 0.334,-0.57 0.503,-1.269 0.503,-2.073 0,-0.607 -0.114,-1.158 -0.338,-1.642 z"
id="path6-6" />
</g>
<path
fill="#ffffff"
d="m 19.043737,41.011422 c -1.809176,0 -3.258109,-0.585946 -4.345917,-1.759608 -1.088692,-1.172779 -1.633038,-2.698718 -1.633038,-4.577819 0,-2.018948 0.554082,-3.628973 1.663133,-4.83096 1.109048,-1.201986 2.614629,-1.802981 4.516743,-1.802981 1.762265,0 3.18199,0.583292 4.258291,1.75076 1.076301,1.167467 1.615335,2.692521 1.615335,4.577817 0,2.048157 -0.551426,3.667918 -1.654281,4.857513 -1.102852,1.190482 -2.57657,1.785278 -4.420266,1.785278 z m 0.09559,-11.142718 c -1.149767,0 -2.08445,0.428395 -2.804933,1.286073 -0.721369,0.858562 -1.080726,1.987084 -1.080726,3.388222 0,1.394942 0.350506,2.517268 1.049747,3.369635 0.700128,0.852365 1.616222,1.278106 2.748285,1.278106 1.201986,0 2.149945,-0.405383 2.84476,-1.217034 0.69393,-0.810765 1.041782,-1.946368 1.041782,-3.404153 0,-1.500271 -0.33723,-2.658003 -1.010803,-3.474964 -0.674458,-0.816962 -1.603829,-1.225885 -2.788112,-1.225885 z"
id="path7-7"
style="display:inline;stroke-width:0.885115" />
<path
fill="#ffffff"
d="m 26.842489,40.302446 v -2.144635 c 0.192955,0.174367 0.421316,0.332803 0.686851,0.47265 0.265534,0.139849 0.547001,0.257569 0.844399,0.354048 0.297399,0.09647 0.595683,0.170827 0.893082,0.223048 0.297398,0.05222 0.571785,0.07877 0.823158,0.07877 0.875379,0 1.527709,-0.146045 1.956104,-0.438132 0.429282,-0.292089 0.64348,-0.714289 0.64348,-1.269256 0,-0.298284 -0.07169,-0.555853 -0.214198,-0.774477 -0.14339,-0.218622 -0.343425,-0.418658 -0.599224,-0.599221 -0.256683,-0.181449 -0.558507,-0.354932 -0.906357,-0.521333 -0.347852,-0.166403 -0.719599,-0.338999 -1.116131,-0.520448 -0.425741,-0.227476 -0.822273,-0.458491 -1.190481,-0.691276 -0.367323,-0.233669 -0.686849,-0.492123 -0.95858,-0.774475 -0.271731,-0.283238 -0.484158,-0.602764 -0.639053,-0.95858 -0.154896,-0.355817 -0.231901,-0.773592 -0.231901,-1.251554 0,-0.589488 0.132768,-1.101969 0.398303,-1.53656 0.265535,-0.433707 0.616039,-0.793948 1.050632,-1.076301 0.434593,-0.283237 0.929371,-0.493009 1.483454,-0.630203 0.554081,-0.137192 1.120555,-0.205346 1.69765,-0.205346 1.312627,0 2.269438,0.148699 2.87043,0.446098 v 2.057009 c -0.711633,-0.513368 -1.627726,-0.77005 -2.748282,-0.77005 -0.308906,0 -0.616926,0.0292 -0.923177,0.08763 -0.306251,0.05843 -0.580635,0.154895 -0.823157,0.288547 -0.242523,0.134538 -0.439018,0.30625 -0.590372,0.516907 -0.15224,0.209773 -0.227476,0.462917 -0.227476,0.761201 0,0.279697 0.05842,0.523102 0.175254,0.726679 0.116836,0.204462 0.287663,0.391222 0.511597,0.560277 0.223934,0.169058 0.499205,0.33369 0.823157,0.493896 0.323952,0.16109 0.698356,0.333688 1.124982,0.521333 0.437247,0.227475 0.850596,0.466455 1.238277,0.717828 0.388566,0.250488 0.729335,0.528414 1.024077,0.831124 0.294746,0.303594 0.528414,0.640824 0.700128,1.010802 0.172597,0.371747 0.258454,0.793063 0.258454,1.265714 0,0.635514 -0.128343,1.172778 -0.385026,1.610026 -0.256684,0.438132 -0.602763,0.793949 -1.037356,1.068334 -0.43459,0.273501 -0.934681,0.472652 -1.501155,0.594798 -0.56559,0.123031 -1.163928,0.183218 -1.79413,0.183218 -0.210657,0 -0.468227,-0.01592 -0.774475,-0.0478 -0.30625,-0.03187 -0.620466,-0.07789 -0.940879,-0.139849 -0.320412,-0.06107 -0.624006,-0.135423 -0.909899,-0.223048 -0.286776,-0.08675 -0.516907,-0.18676 -0.69216,-0.297399 z"
id="path8-5"
style="display:inline;stroke-width:0.885115" />
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 48 48"
width="240px"
height="240px"
version="1.1"
id="svg8"
sodipodi:docname="icons8-os-version-software.svg"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true"
inkscape:zoom="3.3705423"
inkscape:cx="-18.988042"
inkscape:cy="175.04601"
inkscape:window-width="2560"
inkscape:window-height="1360"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<sodipodi:guide
position="24.038024,7.4691871"
orientation="1,0"
id="guide8"
inkscape:locked="false" />
</sodipodi:namedview>
<linearGradient
id="SVGID_1_"
x1="23.855"
x2="23.983"
y1="4.908"
y2="17.227"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#7dd8f3"
id="stop1" />
<stop
offset="1"
stop-color="#45b0d0"
id="stop2" />
</linearGradient>
<circle
cx="24"
cy="18.9"
r="15"
fill="url(#SVGID_1_)"
id="circle2" />
<linearGradient
id="SVGID_2_"
x1="18.175"
x2="29.825"
y1="19.021"
y2="19.021"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#3079d6"
id="stop3" />
<stop
offset="1"
stop-color="#297cd2"
id="stop4" />
</linearGradient>
<circle
cx="24"
cy="19"
r="5.8"
fill="url(#SVGID_2_)"
id="circle4" />
<circle
cx="24"
cy="19"
r="2.3"
fill="#fff"
id="circle5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.3,0-0.6,0-0.9H9C9,18.3,9,18.6,9,18.9z"
opacity=".05"
id="path5" />
<path
d="M9,18.9c0,8.3,6.7,15,15,15s15-6.7,15-15c0-0.1,0-0.2,0-0.4H9C9,18.6,9,18.7,9,18.9z"
opacity=".07"
id="path6" />
<linearGradient
id="SVGID_3_"
x1="16.786"
x2="30.174"
y1="-440.286"
y2="-472.232"
gradientTransform="matrix(1 0 0 -1 0 -426)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#eba84b"
id="stop6" />
<stop
offset="1"
stop-color="#d97218"
id="stop7" />
</linearGradient>
<path
fill="url(#SVGID_3_)"
d="M41,44H7c-0.6,0-1-0.5-1-1V20c0-0.6,0.4-1,1-1h34c0.6,0,1,0.4,1,1v23C42,43.5,41.5,44,41,44z"
id="path7" />
<path
fill="#633412"
d="M20,23h8c0.6,0,1,0.4,1,1l0,0c0,0.6-0.4,1-1,1h-8c-0.6,0-1-0.4-1-1l0,0C19,23.4,19.4,23,20,23z"
id="path8" />
<g
opacity="0.05"
id="g4"
style="display:inline"
transform="matrix(0.71297721,0,0,0.71297721,5.7848117,15.025827)">
<path
d="m 23.884,17.895 c -1.408,-1.526 -3.274,-2.3 -5.546,-2.3 -2.431,0 -4.395,0.794 -5.838,2.359 -1.422,1.543 -2.144,3.607 -2.144,6.136 0,2.374 0.71,4.343 2.111,5.853 1.421,1.531 3.32,2.308 5.644,2.308 2.365,0 4.292,-0.787 5.727,-2.338 1.417,-1.53 2.136,-3.605 2.136,-6.168 0,-2.379 -0.703,-4.347 -2.09,-5.85 z m -3.309,9.273 c -0.599,0.699 -1.378,1.025 -2.454,1.025 -0.987,0 -1.729,-0.343 -2.333,-1.078 -0.636,-0.775 -0.959,-1.843 -0.959,-3.173 0,-1.334 0.332,-2.405 0.987,-3.185 0.629,-0.748 1.393,-1.097 2.404,-1.097 1.048,0 1.804,0.324 2.379,1.021 0.606,0.734 0.914,1.841 0.914,3.289 -0.001,1.396 -0.317,2.472 -0.938,3.198 z"
id="path3" />
<path
d="m 36.615,25.494 v 0 c -0.241,-0.519 -0.571,-0.995 -0.981,-1.419 -0.387,-0.397 -0.834,-0.762 -1.331,-1.081 -0.472,-0.306 -0.967,-0.592 -1.542,-0.888 -0.464,-0.203 -0.873,-0.391 -1.229,-0.569 -0.305,-0.15 -0.564,-0.306 -0.771,-0.46 -0.144,-0.108 -0.249,-0.22 -0.313,-0.333 -0.042,-0.074 -0.065,-0.186 -0.065,-0.322 0,-0.162 0.039,-0.235 0.069,-0.276 0.085,-0.118 0.193,-0.212 0.338,-0.292 0.18,-0.1 0.394,-0.173 0.633,-0.22 0.286,-0.054 0.574,-0.081 0.858,-0.081 1.046,0 1.894,0.229 2.522,0.683 0.308,0.219 0.706,0.249 1.039,0.078 0.336,-0.173 0.544,-0.514 0.544,-0.891 v -2.324 c 0,-0.384 -0.213,-0.728 -0.557,-0.896 -0.826,-0.408 -2.031,-0.607 -3.687,-0.607 -0.733,0 -1.459,0.088 -2.159,0.262 -0.733,0.182 -1.4,0.466 -1.98,0.845 -0.613,0.397 -1.116,0.913 -1.496,1.532 -0.396,0.647 -0.596,1.407 -0.596,2.258 0,0.676 0.116,1.285 0.345,1.813 0.221,0.509 0.53,0.973 0.917,1.376 0.355,0.372 0.782,0.717 1.268,1.027 0.436,0.277 0.906,0.549 1.467,0.848 0.442,0.201 0.857,0.395 1.245,0.58 0.338,0.161 0.634,0.331 0.878,0.503 0.185,0.131 0.325,0.269 0.417,0.408 0.034,0.052 0.079,0.143 0.079,0.328 0,0.34 -0.116,0.488 -0.291,0.607 -0.214,0.146 -0.674,0.32 -1.646,0.32 -0.226,0 -0.48,-0.024 -0.755,-0.073 -0.292,-0.052 -0.586,-0.125 -0.874,-0.219 -0.286,-0.093 -0.554,-0.205 -0.798,-0.334 -0.223,-0.117 -0.415,-0.248 -0.57,-0.39 -0.295,-0.268 -0.72,-0.337 -1.077,-0.174 -0.361,0.16 -0.595,0.519 -0.595,0.914 v 2.423 c 0,0.345 0.174,0.661 0.466,0.846 0.274,0.173 0.618,0.323 1.019,0.445 0.357,0.11 0.737,0.203 1.134,0.279 0.393,0.076 0.778,0.133 1.147,0.17 0.388,0.041 0.715,0.061 0.981,0.061 0.784,0 1.538,-0.077 2.239,-0.23 0.751,-0.162 1.429,-0.433 2.017,-0.804 0.625,-0.394 1.131,-0.913 1.502,-1.546 0.382,-0.65 0.574,-1.432 0.574,-2.327 0,-0.677 -0.129,-1.3 -0.385,-1.85 z"
id="path4" />
</g>
<g
opacity="0.07"
id="g6"
style="display:inline"
transform="matrix(0.71297721,0,0,0.71297721,5.7848117,15.025827)">
<path
d="m 18.338,16.095 c -2.285,0 -4.125,0.739 -5.47,2.198 -1.334,1.447 -2.011,3.397 -2.011,5.797 0,2.243 0.666,4.099 1.978,5.513 1.322,1.425 3.097,2.147 5.277,2.147 2.219,0 4.023,-0.732 5.36,-2.178 1.329,-1.435 2.003,-3.396 2.003,-5.828 0,-2.247 -0.658,-4.102 -1.958,-5.511 -1.31,-1.419 -3.052,-2.138 -5.179,-2.138 z m 3.674,7.877 c 0,1.518 -0.355,2.702 -1.057,3.521 -0.691,0.808 -1.618,1.2 -2.834,1.2 -1.133,0 -2.022,-0.412 -2.719,-1.261 -0.712,-0.867 -1.073,-2.041 -1.073,-3.49 0,-1.454 0.372,-2.635 1.104,-3.507 0.721,-0.857 1.633,-1.274 2.787,-1.274 1.192,0 2.096,0.394 2.764,1.203 0.682,0.826 1.028,2.04 1.028,3.608 z"
id="path5-3" />
<path
d="m 36.162,25.704 c -0.217,-0.467 -0.515,-0.897 -0.886,-1.28 -0.361,-0.371 -0.78,-0.711 -1.244,-1.01 -0.448,-0.29 -0.933,-0.571 -1.471,-0.85 -0.473,-0.207 -0.889,-0.398 -1.25,-0.579 -0.334,-0.165 -0.621,-0.337 -0.85,-0.509 -0.198,-0.149 -0.348,-0.312 -0.446,-0.483 -0.087,-0.151 -0.131,-0.344 -0.131,-0.571 0,-0.23 0.053,-0.416 0.163,-0.568 0.128,-0.178 0.293,-0.321 0.503,-0.438 0.226,-0.124 0.489,-0.216 0.781,-0.272 0.316,-0.06 0.636,-0.09 0.951,-0.09 1.153,0 2.099,0.261 2.813,0.775 0.153,0.109 0.354,0.125 0.52,0.04 0.167,-0.086 0.272,-0.258 0.272,-0.445 V 17.1 c 0,-0.19 -0.108,-0.364 -0.278,-0.448 -0.755,-0.374 -1.889,-0.556 -3.465,-0.556 -0.692,0 -1.378,0.083 -2.039,0.247 -0.678,0.168 -1.293,0.43 -1.829,0.778 -0.551,0.357 -1.002,0.82 -1.341,1.374 -0.347,0.568 -0.523,1.24 -0.523,1.997 0,0.606 0.102,1.149 0.303,1.613 0.197,0.453 0.472,0.867 0.82,1.229 0.33,0.345 0.725,0.664 1.175,0.951 0.425,0.271 0.885,0.536 1.406,0.814 0.445,0.203 0.862,0.397 1.252,0.584 0.364,0.174 0.684,0.357 0.951,0.546 0.236,0.167 0.42,0.35 0.547,0.543 0.108,0.165 0.161,0.362 0.161,0.602 0,0.46 -0.162,0.784 -0.509,1.021 -0.396,0.271 -1.045,0.407 -1.928,0.407 -0.255,0 -0.539,-0.027 -0.842,-0.081 -0.313,-0.056 -0.631,-0.135 -0.941,-0.235 -0.312,-0.102 -0.606,-0.225 -0.876,-0.367 -0.26,-0.137 -0.486,-0.292 -0.673,-0.462 -0.146,-0.133 -0.357,-0.169 -0.539,-0.087 -0.181,0.08 -0.297,0.259 -0.297,0.457 v 2.423 c 0,0.172 0.088,0.331 0.233,0.423 0.235,0.148 0.539,0.28 0.901,0.391 0.34,0.105 0.702,0.193 1.081,0.266 0.377,0.073 0.748,0.128 1.105,0.164 0.367,0.039 0.676,0.058 0.929,0.058 0.747,0 1.465,-0.073 2.133,-0.219 0.693,-0.15 1.317,-0.398 1.856,-0.738 0.557,-0.351 1.007,-0.813 1.337,-1.376 0.334,-0.57 0.503,-1.269 0.503,-2.073 0,-0.607 -0.114,-1.158 -0.338,-1.642 z"
id="path6-6" />
</g>
<path
fill="#ffffff"
d="m 18.697543,37.306366 c -1.457325,0 -2.624468,-0.47199 -3.500718,-1.417397 -0.876962,-0.944696 -1.315442,-2.173869 -1.315442,-3.68752 0,-1.6263 0.446322,-2.923206 1.339684,-3.891429 0.893359,-0.968223 2.106133,-1.452335 3.638321,-1.452335 1.419538,0 2.563153,0.469852 3.430135,1.41027 0.86698,0.940417 1.301182,2.168876 1.301182,3.687518 0,1.649829 -0.444183,2.954577 -1.332554,3.912818 -0.888368,0.958955 -2.075476,1.438075 -3.560608,1.438075 z m 0.077,-8.97567 c -0.926159,0 -1.679064,0.345081 -2.259426,1.035956 -0.581077,0.691588 -0.870545,1.600634 -0.870545,2.729278 0,1.123651 0.282338,2.027706 0.84559,2.714304 0.563967,0.686596 1.301898,1.029538 2.213795,1.029538 0.968223,0 1.731822,-0.326543 2.291509,-0.980343 0.558973,-0.653087 0.839174,-1.567837 0.839174,-2.74211 0,-1.208496 -0.271645,-2.141071 -0.81422,-2.799149 -0.543289,-0.658078 -1.291915,-0.987474 -2.245877,-0.987474 z"
id="path7-7"
style="display:inline;stroke-width:0.712977" />
<path
fill="#ffffff"
d="m 24.979585,36.735273 v -1.727544 c 0.155429,0.140455 0.339378,0.268078 0.553271,0.380728 0.213893,0.112651 0.44062,0.207476 0.68018,0.285193 0.23956,0.07771 0.479833,0.137604 0.719394,0.179669 0.23956,0.04207 0.460584,0.06345 0.663069,0.06345 0.705134,0 1.230599,-0.117641 1.575678,-0.352923 0.345795,-0.235283 0.518337,-0.575373 0.518337,-1.02241 0,-0.240273 -0.05775,-0.447749 -0.172542,-0.623855 -0.115502,-0.176104 -0.276634,-0.337237 -0.482685,-0.482684 -0.206764,-0.146161 -0.449889,-0.285905 -0.730088,-0.419943 -0.280201,-0.134042 -0.579651,-0.27307 -0.899065,-0.419231 -0.342942,-0.183237 -0.662356,-0.369323 -0.958955,-0.556836 -0.295885,-0.188225 -0.553269,-0.396415 -0.772154,-0.623855 -0.218884,-0.228153 -0.389999,-0.485537 -0.514769,-0.772153 -0.124772,-0.286618 -0.186801,-0.623143 -0.186801,-1.008151 0,-0.474843 0.106947,-0.887656 0.320841,-1.237728 0.213893,-0.349359 0.496231,-0.63954 0.846304,-0.866981 0.350072,-0.228152 0.748626,-0.397128 1.19495,-0.50764 0.446322,-0.110511 0.902628,-0.16541 1.367489,-0.16541 1.057346,0 1.828075,0.11978 2.312185,0.35934 v 1.656959 c -0.573234,-0.413527 -1.311163,-0.620289 -2.213792,-0.620289 -0.24883,0 -0.496946,0.02352 -0.743637,0.07059 -0.246691,0.04706 -0.467713,0.124771 -0.663069,0.23243 -0.195357,0.108374 -0.353636,0.24669 -0.475555,0.416379 -0.122632,0.168976 -0.183236,0.372889 -0.183236,0.613161 0,0.225301 0.04706,0.421369 0.14117,0.585354 0.09411,0.164698 0.231718,0.315137 0.412101,0.451314 0.180383,0.136179 0.402119,0.268793 0.663069,0.397842 0.260949,0.129761 0.562538,0.268792 0.906193,0.419944 0.352211,0.183236 0.685171,0.375738 0.997456,0.578224 0.312997,0.201773 0.587493,0.425648 0.824914,0.669486 0.237423,0.244551 0.425647,0.516195 0.563966,0.81422 0.13903,0.29945 0.208189,0.638827 0.208189,1.019557 0,0.511918 -0.103382,0.944694 -0.310145,1.296906 -0.206765,0.352923 -0.485537,0.639541 -0.83561,0.860563 -0.35007,0.22031 -0.752904,0.38073 -1.209209,0.479121 -0.455593,0.0991 -0.937565,0.147585 -1.445206,0.147585 -0.169688,0 -0.377165,-0.01282 -0.623854,-0.0385 -0.24669,-0.02568 -0.499797,-0.06274 -0.757896,-0.112652 -0.258098,-0.04919 -0.502648,-0.109085 -0.73294,-0.179668 -0.231003,-0.06987 -0.416379,-0.150439 -0.557548,-0.239562 z"
id="path8-5"
style="display:inline;stroke-width:0.712977" />
<text
xml:space="preserve"
style="font-size:7.01985px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.674702"
y="41.839462"
id="text19"><tspan
sodipodi:role="line"
id="tspan19"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.01985px;font-family:Futura-Medium;-inkscape-font-specification:Futura-Medium;stroke:#000000;stroke-width:0.61415;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.674702"
y="41.839462">x.y</tspan></text>
<text
xml:space="preserve"
style="font-size:7.01985px;writing-mode:lr-tb;direction:ltr;display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.675184"
y="41.839504"
id="text19-7"><tspan
sodipodi:role="line"
id="tspan19-2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.01985px;font-family:Futura-Medium;-inkscape-font-specification:Futura-Medium;stroke:#000000;stroke-width:1.14064;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:0.0516633;paint-order:stroke fill markers"
x="29.675184"
y="41.839504">x.y</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -44,8 +44,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
'iTopUpdate:UI:Setup' => ITOP_APPLICATION_SHORT.' Setup~~',
'iTopUpdate:UI:History' => 'Versions History~~',
'iTopUpdate:UI:Progress' => 'Progress of the upgrade~~',
'iTopUpdate:UI:Backup:Label' => 'Záložní soubory a databáze',
'iTopUpdate:UI:Backup:Warning' => 'Backup is not recommended due to limited available disk space~~',
'iTopUpdate:UI:DoBackup:Label' => 'Záložní soubory a databáze',
'iTopUpdate:UI:DoBackup:Warning' => 'Backup is not recommended due to limited available disk space~~',
'iTopUpdate:UI:DiskFreeSpace' => 'Volné místo',
'iTopUpdate:UI:ItopDiskSpace' => ITOP_APPLICATION_SHORT.' disk space~~',
'iTopUpdate:UI:DBDiskSpace' => 'Prostor obsazený Databází',

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