Compare commits
264 Commits
faf/cron_m
...
feature/94
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1979e7f66 | ||
|
|
109aa03901 | ||
|
|
80813dba22 | ||
|
|
da282e6c24 | ||
|
|
c4eaeeeb5f | ||
|
|
e605b147d3 | ||
|
|
bfcff9b9c8 | ||
|
|
cd9a755162 | ||
|
|
841ea9bb11 | ||
|
|
4582256f01 | ||
|
|
8de5c2525b | ||
|
|
de4ec9d9ce | ||
|
|
ea35ad48d2 | ||
|
|
90b7c3ac6a | ||
|
|
8f2c990065 | ||
|
|
03437c3453 | ||
|
|
1113788d84 | ||
|
|
0fc7434794 | ||
|
|
eee57b25fa | ||
|
|
7be19c713b | ||
|
|
42fdffe25b | ||
|
|
309f8f8727 | ||
|
|
16108a80fc | ||
|
|
befe294986 | ||
|
|
d271dda54f | ||
|
|
04bb07fc59 | ||
|
|
33a51b47bf | ||
|
|
7e0e357713 | ||
|
|
1772a9f73b | ||
|
|
ed45c3bbb0 | ||
|
|
d358c41c24 | ||
|
|
a49ebd531e | ||
|
|
c5ca5f9176 | ||
|
|
e768cc1c0c | ||
|
|
12b1339542 | ||
|
|
278254c955 | ||
|
|
d0ddb35f8d | ||
|
|
f6741a6306 | ||
|
|
fc2cb86122 | ||
|
|
467d2755ca | ||
|
|
19386191aa | ||
|
|
d76752a988 | ||
|
|
8c2c4e5ff0 | ||
|
|
4bc28ea38a | ||
|
|
de0e94800a | ||
|
|
3b0832781a | ||
|
|
900bd6956a | ||
|
|
848d869954 | ||
|
|
020d720140 | ||
|
|
dc8f186443 | ||
|
|
805087a01b | ||
|
|
423807d32a | ||
|
|
1ec8aca12d | ||
|
|
f439490bfc | ||
|
|
39011faedd | ||
|
|
7819620013 | ||
|
|
0fb15e72d4 | ||
|
|
46f8f5faeb | ||
|
|
170d24d0ad | ||
|
|
0b6e7d3258 | ||
|
|
8088fdc322 | ||
|
|
d3dbe7b231 | ||
|
|
f05d98aba8 | ||
|
|
9683b8d96a | ||
|
|
a6171c896b | ||
|
|
999e4de7f1 | ||
|
|
327c1572a4 | ||
|
|
89231976f8 | ||
|
|
16cdc80778 | ||
|
|
962a8e68b3 | ||
|
|
d61742dffb | ||
|
|
9f15385545 | ||
|
|
751ad846a4 | ||
|
|
f3b55a648e | ||
|
|
4e24ac508d | ||
|
|
e1c804139f | ||
|
|
f0a95cbb3d | ||
|
|
265acb4a1e | ||
|
|
30f720b9ad | ||
|
|
5ff640dfe7 | ||
|
|
662d6e3fb4 | ||
|
|
cbafcccde5 | ||
|
|
7573b1bfba | ||
|
|
1992c7e7c1 | ||
|
|
87dd003a6d | ||
|
|
4dbaaad2b9 | ||
|
|
2fe49fbff4 | ||
|
|
7201bef8db | ||
|
|
af01ff9e62 | ||
|
|
e7e7664cb8 | ||
|
|
ab1290dfd0 | ||
|
|
68d14c4de6 | ||
|
|
a96e1c286d | ||
|
|
1222507205 | ||
|
|
b799be3cb7 | ||
|
|
bcf1bb003c | ||
|
|
d000d93b19 | ||
|
|
83a67dff96 | ||
|
|
79270950ee | ||
|
|
9f25635a64 | ||
|
|
18b91df58d | ||
|
|
b133f52d83 | ||
|
|
e28addfd6d | ||
|
|
2ec0931896 | ||
|
|
ca30645d36 | ||
|
|
bd14a84677 | ||
|
|
ad0234a94f | ||
|
|
611f1e66f2 | ||
|
|
82a20c54a9 | ||
|
|
d36f68e3b0 | ||
|
|
9ca0dd643f | ||
|
|
e27aca728c | ||
|
|
c3824f421b | ||
|
|
ecc07f4575 | ||
|
|
bcf2123df0 | ||
|
|
8dca03f557 | ||
|
|
2129007512 | ||
|
|
14d01b89a7 | ||
|
|
e2bda81414 | ||
|
|
6b7d306006 | ||
|
|
40feabb866 | ||
|
|
e17eaa7430 | ||
|
|
deeee08e8c | ||
|
|
b7b01c94e7 | ||
|
|
ba29a41d98 | ||
|
|
073d4f15f5 | ||
|
|
91915f001b | ||
|
|
9b7c7c0b48 | ||
|
|
85b20f34a3 | ||
|
|
7a153c3698 | ||
|
|
1be0e61971 | ||
|
|
d53433e62d | ||
|
|
51f4dd7948 | ||
|
|
d2384bb274 | ||
|
|
cedc1ec711 | ||
|
|
9cb2d78b48 | ||
|
|
9c32e29e77 | ||
|
|
c6dd16549c | ||
|
|
f2b15554bb | ||
|
|
6bd34dc73e | ||
|
|
4afe06d370 | ||
|
|
9dc3c56689 | ||
|
|
effd35c3e6 | ||
|
|
587d7fcf72 | ||
|
|
f1735767c3 | ||
|
|
bfdc8a68e6 | ||
|
|
00735f0c54 | ||
|
|
882390e8d6 | ||
|
|
5d0da47f21 | ||
|
|
684eaac278 | ||
|
|
4eadff7f3b | ||
|
|
4ce8f70382 | ||
|
|
f66ce1c956 | ||
|
|
868eea9b43 | ||
|
|
802f9f3e08 | ||
|
|
70a8bdf427 | ||
|
|
38cda442e3 | ||
|
|
20c8b7c0ce | ||
|
|
b58a848cc9 | ||
|
|
5c5d98bb78 | ||
|
|
a08a9b43f3 | ||
|
|
d9433fead5 | ||
|
|
abd85ff4db | ||
|
|
81f328b26e | ||
|
|
9a2c8f10bf | ||
|
|
3cdadf3c6e | ||
|
|
358c4383f8 | ||
|
|
890db04fa3 | ||
|
|
e1e2da2881 | ||
|
|
cb47ea4316 | ||
|
|
a3e8abe520 | ||
|
|
48e58f4323 | ||
|
|
337ccbb921 | ||
|
|
34930a93cb | ||
|
|
5f731d9f97 | ||
|
|
9b7fd7b398 | ||
|
|
e0eee6798d | ||
|
|
a8f1b6ea35 | ||
|
|
d49a50da5b | ||
|
|
6a34fb9a15 | ||
|
|
3befe469e8 | ||
|
|
add7e7a677 | ||
|
|
f80a074135 | ||
|
|
113e3bc110 | ||
|
|
c20c4644b1 | ||
|
|
b77a0e3297 | ||
|
|
a237b32115 | ||
|
|
681abc84b9 | ||
|
|
7775cfeccc | ||
|
|
222e08e29b | ||
|
|
773501baed | ||
|
|
150094341f | ||
|
|
e1215733e9 | ||
|
|
2b2e431d0a | ||
|
|
98312d1c15 | ||
|
|
fc08bed218 | ||
|
|
eb01828f06 | ||
|
|
4c0b54a0f7 | ||
|
|
8074643231 | ||
|
|
1fb264e630 | ||
|
|
2bfafeffe6 | ||
|
|
324a68df32 | ||
|
|
14c3dafa4d | ||
|
|
7e78bd8519 | ||
|
|
54aa56c5a8 | ||
|
|
62bd1b8f49 | ||
|
|
b5e95f297c | ||
|
|
f89cb71f61 | ||
|
|
b30ff8b832 | ||
|
|
5254a83327 | ||
|
|
b1f49a1568 | ||
|
|
336898da98 | ||
|
|
84803abd36 | ||
|
|
9370c83a69 | ||
|
|
f7dfeafa3f | ||
|
|
5b4030a95f | ||
|
|
fe6ba35ada | ||
|
|
789c4bb5ea | ||
|
|
f5f5334e5f | ||
|
|
51f0eea8e3 | ||
|
|
875b2f1f29 | ||
|
|
36fc0fb0ea | ||
|
|
4f9a4dcfa5 | ||
|
|
dfc6189cef | ||
|
|
ad33453860 | ||
|
|
f787cf0950 | ||
|
|
cf7a193f7b | ||
|
|
8bbd1ab621 | ||
|
|
20ae350286 | ||
|
|
df9d69c70f | ||
|
|
ba09c624f0 | ||
|
|
7611a0e5c8 | ||
|
|
19e60ea628 | ||
|
|
5aaae3ad9c | ||
|
|
3b6ead1307 | ||
|
|
4678684ce6 | ||
|
|
c008483625 | ||
|
|
bfef10d636 | ||
|
|
d84959ce6c | ||
|
|
b230623a32 | ||
|
|
375c1f3a73 | ||
|
|
ab7a737512 | ||
|
|
371819f13f | ||
|
|
56cb3cae4f | ||
|
|
11b985aaa7 | ||
|
|
59fe11b96e | ||
|
|
55b03941e8 | ||
|
|
2fcd224ffd | ||
|
|
b26e0c8a90 | ||
|
|
b967fb7f20 | ||
|
|
195038c941 | ||
|
|
9a8d87e2b5 | ||
|
|
385302c44c | ||
|
|
b563f113d0 | ||
|
|
715d9d3b1c | ||
|
|
7a6c2bc6a4 | ||
|
|
8919184ef9 | ||
|
|
7bfaebe4db | ||
|
|
8e10cf9b72 | ||
|
|
9f3d7d2c36 | ||
|
|
ae980e365d | ||
|
|
a2b01b3ed4 | ||
|
|
9cdc707bc5 | ||
|
|
76178c16b8 |
|
Before Width: | Height: | Size: 1.5 MiB |
BIN
.doc/contributing-guide/contributing-stickers-side-by-side.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
@@ -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
@@ -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
@@ -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"
|
||||
66
.github/pull_request_template.md
vendored
@@ -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?
|
||||
@@ -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:
|
||||
|
||||

|
||||

|
||||
@@ -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
|
||||
|
||||
@@ -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.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation/moduleinstallation.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4495,7 +4495,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 +5064,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)
|
||||
);
|
||||
|
||||
@@ -497,7 +497,7 @@ EOF
|
||||
* @param array $aExtraParams
|
||||
* @param bool $bCanEdit
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
|
||||
* @return null|\Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
$this->aAllowedValues = array_merge([$aValue], $this->aAllowedValues ?? [null]);
|
||||
}
|
||||
public function EnableUpload($sIconUploadUrl)
|
||||
{
|
||||
|
||||
@@ -75,13 +75,10 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function GetAuthUser()
|
||||
{
|
||||
$sExtAuthVar = MetaModel::GetConfig()->GetExternalAuthenticationVariable(); // In which variable is the info passed ?
|
||||
eval('$sAuthUser = isset('.$sExtAuthVar.') ? '.$sExtAuthVar.' : false;'); // Retrieve the value
|
||||
/** @var string $sAuthUser */
|
||||
return $sAuthUser; // Retrieve the value
|
||||
return MetaModel::GetConfig()->GetExternalAuthenticationVariable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,12 +1423,21 @@ class ShortcutMenuNode extends MenuNode
|
||||
public function GetHyperlink($aExtraParams)
|
||||
{
|
||||
$sContext = $this->oShortcut->Get('context');
|
||||
$aContext = unserialize($sContext);
|
||||
if (isset($aContext['menu'])) {
|
||||
unset($aContext['menu']);
|
||||
}
|
||||
foreach ($aContext as $sArgName => $sArgValue) {
|
||||
$aExtraParams[$sArgName] = $sArgValue;
|
||||
try {
|
||||
$aContext = utils::Unserialize($sContext);
|
||||
if (isset($aContext['menu'])) {
|
||||
unset($aContext['menu']);
|
||||
}
|
||||
foreach ($aContext as $sArgName => $sArgValue) {
|
||||
$aExtraParams[$sArgName] = $sArgValue;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Warning("User shortcut corrupted, delete the shortcut", LogChannels::CONSOLE, [
|
||||
'shortcut_name' => $this->oShortcut->GetName(),
|
||||
'root_cause' => $e->getMessage(),
|
||||
]);
|
||||
// delete the shortcut
|
||||
$this->oShortcut->DBDelete();
|
||||
}
|
||||
return parent::GetHyperlink($aExtraParams);
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ JS
|
||||
<<<HTML
|
||||
<form id="ObjectsAddForm_{$this->sInputid}">
|
||||
<div id="SearchResultsToAdd_{$this->sInputid}">
|
||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
<div style="border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
</div>
|
||||
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
||||
</form>
|
||||
|
||||
@@ -68,7 +68,7 @@ class UISearchFormForeignKeys
|
||||
<<<HTML
|
||||
<form id="ObjectsAddForm_{$this->m_iInputId}">
|
||||
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;height:100%;overflow:auto;padding:0;border:0;">
|
||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
<div style="border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
</div>
|
||||
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
||||
</form>
|
||||
|
||||
@@ -284,9 +284,7 @@ class utils
|
||||
}
|
||||
// Read and record the value for switching the archive mode
|
||||
$iCurrent = self::ReadParam('with-archive', $iDefault);
|
||||
if (Session::IsInitialized()) {
|
||||
Session::Set('archive_mode', $iCurrent);
|
||||
}
|
||||
Session::Set('archive_mode', $iCurrent);
|
||||
// Read and use the value for the current page (web services)
|
||||
$iCurrent = self::ReadParam('with_archive', $iCurrent, true);
|
||||
self::$bPageMode = ($iCurrent == 1);
|
||||
@@ -976,7 +974,7 @@ class utils
|
||||
return self::$oConfig;
|
||||
}
|
||||
|
||||
$sProductionEnvConfigPath = self::GetConfigFilePath('production');
|
||||
$sProductionEnvConfigPath = self::GetConfigFilePath(ITOP_DEFAULT_ENV);
|
||||
if (file_exists($sProductionEnvConfigPath)) {
|
||||
$oProductionEnvDiskConfig = new Config($sProductionEnvConfigPath);
|
||||
self::SetConfig($oProductionEnvDiskConfig);
|
||||
@@ -3146,4 +3144,76 @@ TXT
|
||||
|
||||
return $aTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP unserialize encapsulation, allow throwing exception when not allowed object class is detected (for security hardening)
|
||||
*
|
||||
* @param string $data data to unserialize
|
||||
* @param array $aOptions PHP @unserialise options
|
||||
* @param bool $bThrowNotAllowedObjectClassException flag to throw exception
|
||||
*
|
||||
* @return mixed PHP @unserialise return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function Unserialize(string $data, array $aOptions = ['allowed_classes' => false], bool $bThrowNotAllowedObjectClassException = true): mixed
|
||||
{
|
||||
$data = unserialize($data, $aOptions);
|
||||
|
||||
if ($bThrowNotAllowedObjectClassException) {
|
||||
try {
|
||||
self::AssertNoIncompleteClassDetected($data);
|
||||
} catch (Exception $e) {
|
||||
throw new CoreException('Unserialization failed because an incomplete class was detected.', [], '', $e);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that data provided doesn't contain any incomplete class.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function AssertNoIncompleteClassDetected(mixed $data): void
|
||||
{
|
||||
if (is_object($data)) {
|
||||
if ($data instanceof __PHP_Incomplete_Class) {
|
||||
throw new Exception('__PHP_Incomplete_Class_Name object detected');
|
||||
}
|
||||
foreach (get_object_vars($data) as $property) {
|
||||
self::AssertNoIncompleteClassDetected($property);
|
||||
}
|
||||
} elseif (is_array($data)) {
|
||||
foreach ($data as $value) {
|
||||
self::AssertNoIncompleteClassDetected($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read memory limit from the php.ini file
|
||||
*
|
||||
* @return int Memory limit in bytes
|
||||
*/
|
||||
public static function GetMemoryLimit(): int
|
||||
{
|
||||
$sLimit = ini_get('memory_limit');
|
||||
if ($sLimit == '-1') {
|
||||
return 128 * 1048576;
|
||||
}
|
||||
switch (substr($sLimit, -1)) {
|
||||
case 'M':
|
||||
case 'm':
|
||||
return (int)$sLimit * 1048576;
|
||||
case 'K':
|
||||
case 'k':
|
||||
return (int)$sLimit * 1024;
|
||||
case 'G':
|
||||
case 'g':
|
||||
return (int)$sLimit * 1073741824;
|
||||
default:
|
||||
return (int)$sLimit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.class.inc.php');
|
||||
MetaModel::IncludeModule('setup/moduleinstallation/moduleinstallation.class.inc.php');
|
||||
|
||||
MetaModel::IncludeModule('core/event.class.inc.php');
|
||||
MetaModel::IncludeModule('core/action.class.inc.php');
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
|
||||
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
|
||||
|
||||
define('ITOP_APPLICATION', 'iTop');
|
||||
define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||
|
||||
@@ -78,6 +75,7 @@ define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']');
|
||||
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible)
|
||||
define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later
|
||||
define('DEFAULT_HASH_ALGO', PASSWORD_DEFAULT);
|
||||
|
||||
/**
|
||||
* Config
|
||||
* configuration data (this class cannot not be localized, because it is responsible for loading the dictionaries)
|
||||
@@ -871,6 +869,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'ext_auth_variable' => [
|
||||
'type' => 'string',
|
||||
'description' => 'External authentication expression (allowed: $_SERVER[\'key\'], $_COOKIE[\'key\'], $_REQUEST[\'key\'], getallheaders()[\'Header-Name\'])',
|
||||
'default' => '$_SERVER[\'REMOTE_USER\']',
|
||||
'value' => '$_SERVER[\'REMOTE_USER\']',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'login_debug' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'Activate the login FSM debug',
|
||||
@@ -1173,8 +1179,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_LIST,
|
||||
'value' => LINKSET_TRACKING_LIST,
|
||||
'default' => LINKSET_TRACKING_NONE,
|
||||
'value' => LINKSET_TRACKING_NONE,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
@@ -1613,7 +1619,7 @@ class Config
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'search_manual_submit' => [
|
||||
'type' => 'array',
|
||||
'type' => 'bool',
|
||||
'description' => 'Force manual submit of search all requests',
|
||||
'default' => false,
|
||||
'value' => true,
|
||||
@@ -1756,11 +1762,11 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'security.force_login_when_no_delegated_authentication_endpoints_list' => [
|
||||
'security.disable_exec_forced_login_for_all_enpoints' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, when no execution policy is defined, the user will be forced to log in (instead of being automatically logged in with the default profile)',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'description' => 'If true, when no delegated authentication module is defined, no login will be forced on modules exec endpoints',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
@@ -1970,11 +1976,6 @@ class Config
|
||||
*/
|
||||
protected $m_sDefaultLanguage;
|
||||
|
||||
/**
|
||||
* @var string Name of the PHP variable in which external authentication information is passed by the web server
|
||||
*/
|
||||
protected $m_sExtAuthVariable;
|
||||
|
||||
/**
|
||||
* @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value
|
||||
* unless you want to import a database from another iTop instance, in which case you must use
|
||||
@@ -2043,7 +2044,6 @@ class Config
|
||||
$this->m_iFastReloadInterval = DEFAULT_FAST_RELOAD_INTERVAL;
|
||||
$this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED;
|
||||
$this->m_sDefaultLanguage = 'EN US';
|
||||
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_aCharsets = [];
|
||||
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
|
||||
$this->m_iPasswordHashAlgo = DEFAULT_HASH_ALGO;
|
||||
@@ -2189,7 +2189,6 @@ class Config
|
||||
$this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : [];
|
||||
|
||||
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
||||
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
|
||||
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
|
||||
$this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : [];
|
||||
@@ -2351,9 +2350,73 @@ class Config
|
||||
return explode('|', $this->m_aSettings['allowed_login_types']['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
* @since 3.2.3 return the parsed value instead of an unsecured variable name
|
||||
*/
|
||||
public function GetExternalAuthenticationVariable()
|
||||
{
|
||||
return $this->m_sExtAuthVariable;
|
||||
$sExpression = $this->Get('ext_auth_variable');
|
||||
$aParsed = $this->ParseExternalAuthVariableExpression($sExpression);
|
||||
if ($aParsed === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sKey = $aParsed['key'];
|
||||
switch ($aParsed['type']) {
|
||||
case 'server':
|
||||
return $_SERVER[$sKey] ?? false;
|
||||
case 'cookie':
|
||||
return $_COOKIE[$sKey] ?? false;
|
||||
case 'request':
|
||||
return $_REQUEST[$sKey] ?? false;
|
||||
case 'header':
|
||||
if (!function_exists('getallheaders')) {
|
||||
return false;
|
||||
}
|
||||
$aHeaders = getallheaders();
|
||||
if (!is_array($aHeaders)) {
|
||||
return false;
|
||||
}
|
||||
return $aHeaders[$sKey] ?? false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sExpression
|
||||
* @return array|null
|
||||
*/
|
||||
private function ParseExternalAuthVariableExpression($sExpression)
|
||||
{
|
||||
// If it's a configuration parameter it's probably already trimmed, but just in case
|
||||
$sExpression = trim((string) $sExpression);
|
||||
if ($sExpression === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Match $_SERVER/$_COOKIE/$_REQUEST['key'] with optional whitespace and single/double quotes.
|
||||
if (preg_match('/^\$_(SERVER|COOKIE|REQUEST)\s*\[\s*(["\'])\s*([^"\']+)\2\s*\]\s*$/', $sExpression, $aMatches) === 1) {
|
||||
$sContext = strtoupper($aMatches[1]);
|
||||
$sKey = $aMatches[3];
|
||||
return [
|
||||
'type' => strtolower($sContext),
|
||||
'key' => $sKey,
|
||||
'normalized' => '$_'.$sContext.'[\''.$sKey.'\']',
|
||||
];
|
||||
}
|
||||
|
||||
// Match getallheaders()['Header-Name'] in a case-insensitive way.
|
||||
if (preg_match('/^getallheaders\(\)\s*\[\s*(["\'])\s*([^"\']+)\1\s*\]\s*$/i', $sExpression, $aMatches) === 1) {
|
||||
$sKey = $aMatches[2];
|
||||
return [
|
||||
'type' => 'header',
|
||||
'key' => $sKey,
|
||||
'normalized' => 'getallheaders()[\''.$sKey.'\']',
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function GetCSVImportCharsets()
|
||||
@@ -2449,7 +2512,7 @@ class Config
|
||||
|
||||
public function SetExternalAuthenticationVariable($sExtAuthVariable)
|
||||
{
|
||||
$this->m_sExtAuthVariable = $sExtAuthVariable;
|
||||
$this->Set('ext_auth_variable', $sExtAuthVariable);
|
||||
}
|
||||
|
||||
public function SetEncryptionKey($sKey)
|
||||
@@ -2503,7 +2566,6 @@ class Config
|
||||
$aSettings['fast_reload_interval'] = $this->m_iFastReloadInterval;
|
||||
$aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired;
|
||||
$aSettings['default_language'] = $this->m_sDefaultLanguage;
|
||||
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
|
||||
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
|
||||
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
|
||||
$aSettings['csv_import_charsets'] = $this->m_aCharsets;
|
||||
@@ -2606,7 +2668,6 @@ class Config
|
||||
// Old fashioned remaining values
|
||||
$aOtherValues = [
|
||||
'default_language' => $this->m_sDefaultLanguage,
|
||||
'ext_auth_variable' => $this->m_sExtAuthVariable,
|
||||
'encryption_key' => $this->m_sEncryptionKey,
|
||||
'encryption_library' => $this->m_sEncryptionLibrary,
|
||||
'csv_import_charsets' => $this->m_aCharsets,
|
||||
@@ -2691,14 +2752,13 @@ 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, $bPreserveModuleSettings = false)
|
||||
public function UpdateFromParams($aParamValues, $sModulesDir = null)
|
||||
{
|
||||
if (isset($aParamValues['application_path'])) {
|
||||
$this->Set('app_root_url', $aParamValues['application_path']);
|
||||
@@ -2746,7 +2806,10 @@ class Config
|
||||
} else {
|
||||
$aSelectedModules = null;
|
||||
}
|
||||
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
|
||||
|
||||
if (! is_null($sModulesDir)) {
|
||||
$this->UpdateIncludes($sModulesDir, $aSelectedModules);
|
||||
}
|
||||
|
||||
if (isset($aParamValues['source_dir'])) {
|
||||
$this->Set('source_dir', $aParamValues['source_dir']);
|
||||
@@ -2764,17 +2827,13 @@ class Config
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function UpdateIncludes($sModulesDir, $aSelectedModules = null)
|
||||
public function UpdateIncludes(string $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::GetAvailableModules([APPROOT.$sModulesDir]);
|
||||
$aModules = ModuleDiscovery::GetModulesOrderedByDependencies([APPROOT.$sModulesDir]);
|
||||
foreach ($aModules as $sModuleId => $aModuleInfo) {
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) {
|
||||
|
||||
@@ -5108,8 +5108,8 @@ abstract class DBObject implements iDisplay
|
||||
protected function GetReferencingObjectsForDeletion($bAllowAllData = false)
|
||||
{
|
||||
$aDependentObjects = [];
|
||||
$aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this));
|
||||
foreach ($aRererencingMe as $sRemoteClass => $aExtKeys) {
|
||||
$aReferencingMe = MetaModel::EnumReferencingClasses(get_class($this));
|
||||
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
|
||||
/** @var \AttributeExternalKey $oExtKeyAttDef */
|
||||
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
|
||||
// skip if external key doesn't require the deletion cascading
|
||||
|
||||
@@ -360,10 +360,10 @@ class DesignElement extends \DOMElement
|
||||
* @param string $sTagName
|
||||
* @param string|null $sDefault
|
||||
*
|
||||
* @return string
|
||||
* @return null|string
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function GetChildText($sTagName, $sDefault = null)
|
||||
public function GetChildText($sTagName, $sDefault = null): ?string
|
||||
{
|
||||
$sRet = $sDefault;
|
||||
if ($oChild = $this->GetOptionalElement($sTagName)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,6 +22,8 @@ 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';
|
||||
@@ -128,7 +130,7 @@ abstract class MetaModel
|
||||
/** @var array */
|
||||
private static $m_aClassToFile = [];
|
||||
/** @var string */
|
||||
protected static $m_sEnvironment = 'production';
|
||||
protected static $m_sEnvironment = ITOP_DEFAULT_ENV;
|
||||
|
||||
/**
|
||||
* Objects currently created/updated.
|
||||
@@ -462,6 +464,43 @@ 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
|
||||
*
|
||||
@@ -5709,7 +5748,7 @@ abstract class MetaModel
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = 'production')
|
||||
public static function Startup($config, $bModelOnly = false, $bAllowCache = true, $bTraceSourceFiles = false, $sEnvironment = ITOP_DEFAULT_ENV)
|
||||
{
|
||||
// Startup on a new environment is not supported
|
||||
static $bStarted = false;
|
||||
|
||||
@@ -43,24 +43,24 @@ final class ormTagSet extends ormSet
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $aTagCodes
|
||||
* @param array|null $aItems
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue when a code is invalid
|
||||
*/
|
||||
public function SetValues($aTagCodes)
|
||||
public function SetValues($aItems)
|
||||
{
|
||||
if (is_null($aTagCodes)) {
|
||||
$aTagCodes = [];
|
||||
if (is_null($aItems)) {
|
||||
$aItems = [];
|
||||
}
|
||||
if (!is_array($aTagCodes)) {
|
||||
throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}");
|
||||
if (!is_array($aItems)) {
|
||||
throw new CoreUnexpectedValue("Wrong value {$aItems} for {$this->sClass}:{$this->sAttCode}");
|
||||
}
|
||||
|
||||
$oTags = [];
|
||||
$iCount = 0;
|
||||
$bError = false;
|
||||
foreach ($aTagCodes as $sTagCode) {
|
||||
foreach ($aItems as $sTagCode) {
|
||||
$iCount++;
|
||||
if (($this->iLimit != 0) && ($iCount > $this->iLimit)) {
|
||||
$bError = true;
|
||||
|
||||
@@ -1182,7 +1182,7 @@ class UserRights
|
||||
return self::$m_oUser->GetKey();
|
||||
} else {
|
||||
// find the id out of the login string
|
||||
$oUser = self::FindUser($sLogin);
|
||||
$oUser = self::FindUser($sLogin, bAllowDisabledUsers: true);
|
||||
if (is_null($oUser)) {
|
||||
return null;
|
||||
}
|
||||
@@ -1375,7 +1375,7 @@ class UserRights
|
||||
if (empty($sLogin)) {
|
||||
$oUser = self::$m_oUser;
|
||||
} else {
|
||||
$oUser = self::FindUser($sLogin);
|
||||
$oUser = self::FindUser($sLogin, bAllowDisabledUsers: true);
|
||||
}
|
||||
if (is_null($oUser)) {
|
||||
return '';
|
||||
|
||||
@@ -56,6 +56,8 @@ $ibo-shame--slider--is-round--border-radius: 20px !default;
|
||||
$ibo-shame--slider--is-round--before--border-radius: 7px !default;
|
||||
|
||||
|
||||
$ibo-blockquote--color: $ibo-body-text-color !default;
|
||||
|
||||
// N°2847 - Recolor svg illustrations with iTop's primary color
|
||||
.ibo-svg-illustration--container > svg *[fill="#6c63ff"]{
|
||||
fill: $ibo-svg-illustration--fill;
|
||||
@@ -126,3 +128,11 @@ input:checked + .slider:before {
|
||||
.slider.round:before {
|
||||
border-radius: $ibo-shame--slider--is-round--before--border-radius;
|
||||
}
|
||||
|
||||
/*
|
||||
Bulma sets blockquote background color through a variable, it affects ckeditor and html display.
|
||||
This rule is needed harmonize the blockquote text color in both contexts.
|
||||
*/
|
||||
.ibo-is-html-content blockquote {
|
||||
color: $ibo-blockquote--color;
|
||||
}
|
||||
@@ -22,4 +22,6 @@
|
||||
@import "medallion-with-blocklist";
|
||||
@import "field-badge-within-datatable";
|
||||
@import "jquery-blockui-within-dialog";
|
||||
@import "jquery-blockui-within-datatable";
|
||||
@import "jquery-blockui-within-datatable";
|
||||
@import "badge-with-badge";
|
||||
@import "extension-details-with-extension-details";
|
||||
10
css/backoffice/blocks-integrations/_badge-with-badge.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @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;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* @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;
|
||||
}
|
||||
@@ -33,4 +33,5 @@
|
||||
@import "field-badge";
|
||||
@import "file-select";
|
||||
@import "medallion-icon";
|
||||
@import "toast";
|
||||
@import "toast";
|
||||
@import "badge";
|
||||
41
css/backoffice/components/_badge.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -21,6 +21,8 @@ $ibo-search-form-panel--more-criteria--color: $ibo-color-blue-grey-800 !default;
|
||||
$ibo-search-form-panel--more-criteria--background-color: $ibo-color-white-100 !default;
|
||||
$ibo-search-form-panel--more-criteria--icon--color: $ibo-color-primary-600 !default;
|
||||
$ibo-search-form-panel--more-criteria--border-color: $ibo-search-form-panel--criteria--border-color !default;
|
||||
// calc is redundant but avoid SCSS min() from being used instead of CSS min()
|
||||
$ibo-search-form-panel--criteria--max-height: calc(min(#{$ibo-size-750}, 50vh)) !default;
|
||||
|
||||
$ibo-search-form-panel--items--hover--color: $ibo-color-grey-200 !default;
|
||||
|
||||
@@ -278,9 +280,10 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
}
|
||||
|
||||
.sfc_form_group {
|
||||
display: block;
|
||||
margin-top: -1px;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: -1px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,11 +349,15 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
display: none;
|
||||
max-width: 450px;
|
||||
width: max-content;
|
||||
max-height: 520px;
|
||||
max-height: $ibo-search-form-panel--criteria--max-height;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
|
||||
.sfc_fg_operators {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
font-size: 12px;
|
||||
|
||||
.sfc_fg_operator {
|
||||
@@ -387,6 +394,9 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
}
|
||||
|
||||
.sfc_opc_multichoices {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
label > input {
|
||||
vertical-align: text-top;
|
||||
margin-left: $ibo-spacing-0;
|
||||
@@ -398,7 +408,6 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
}
|
||||
|
||||
.sfc_opc_mc_items_wrapper {
|
||||
max-height: 415px; /* Must be less than .sfc_form_group:max-height - .sfc_opc_mc_toggler:height - .sfc_opc_mc_filter:height */
|
||||
overflow-y: auto;
|
||||
margin: $ibo-spacing-0 -8px; /* Compensate .sfc_opc_multichoices side padding so the hover style can take the full with */
|
||||
|
||||
@@ -560,8 +569,14 @@ $ibo-search-results-area--datatable-scrollhead--border--is-sticking: $ibo-search
|
||||
&.search_form_criteria_enum {
|
||||
.sfc_form_group {
|
||||
.sfc_fg_operator_in {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
> label {
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
line-height: initial;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -203,8 +203,9 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
}
|
||||
|
||||
// N°7982 Default selectize stylesheet override
|
||||
// N°9468 Dropdown content needs to be a few pixel shorter than the dropdown itself to avoid double scrollbar
|
||||
.selectize-dropdown-content{
|
||||
max-height: $ibo-input-select-selectize--dropdown--max-height;
|
||||
max-height: calc(#{$ibo-input-select-selectize--dropdown--max-height} - 4px);
|
||||
}
|
||||
|
||||
.selectize-dropdown.ui-menu .ui-state-active {
|
||||
|
||||
@@ -8,6 +8,7 @@ $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;
|
||||
@@ -17,6 +18,7 @@ $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;
|
||||
@@ -61,6 +63,13 @@ $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;
|
||||
}
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
@import "wizard-container/wizard-container";
|
||||
@import "object/all";
|
||||
@import "activity-panel/all";
|
||||
@import "extension/all";
|
||||
1
css/backoffice/layout/extension/_all.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import "extension-details";
|
||||
65
css/backoffice/layout/extension/_extension-details.scss
Normal file
@@ -0,0 +1,65 @@
|
||||
$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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ $text-strong: inherit !default;
|
||||
* See https://bulma.io/documentation/elements/content/
|
||||
*/
|
||||
$content-block-margin-bottom: 0 !default;
|
||||
$content-blockquote-background-color: $ibo-color-grey-200 !default;
|
||||
|
||||
/* Table: Reset style as much as possible to match rich text editor preview, which is the browser's default stylesheet.
|
||||
* As there is no way to avoid bulma rules, we simply make them invalid by setting an invalid variable value, the rules will then be ignored by the browser.
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -316,29 +316,34 @@ fieldset {
|
||||
background-color: #F7FAFC;
|
||||
padding: 10px;
|
||||
.wiz-choice{
|
||||
&: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{
|
||||
&:not(:checked) ~ label .checked{
|
||||
display:none;
|
||||
}
|
||||
&:checked ~ label .setup-extension-tag.unchecked{
|
||||
&:checked ~ label .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;
|
||||
@@ -522,10 +527,12 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-setup-summary-title {
|
||||
font-size: $ibo-font-size-150;
|
||||
.ibo-setup-summary-title, .ibo-setup-summary-title:visited, .ibo-setup-summary-title:hover {
|
||||
font-size: $ibo-font-size-150;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
#ibo-setup-licenses--components-list {
|
||||
background-color: $ibo-color-white-200;
|
||||
padding: 12px;
|
||||
@@ -605,6 +612,7 @@ body {
|
||||
color:#a00000;
|
||||
}
|
||||
.setup-extension-tag {
|
||||
display: inline-flex;
|
||||
background-color: grey;
|
||||
border-radius: 8px;
|
||||
padding-left: 3px;
|
||||
@@ -630,6 +638,21 @@ 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;
|
||||
}
|
||||
@@ -681,9 +704,6 @@ body {
|
||||
overflow: auto;
|
||||
text-align: center;
|
||||
}
|
||||
#installation_progress {
|
||||
display: none;
|
||||
}
|
||||
#fresh_content{
|
||||
border: 0;
|
||||
min-height: 300px;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -76,6 +76,7 @@ $text-strong: inherit !default;
|
||||
$code: $ibo-color-primary-400 !default;
|
||||
$code-background: $ibo-color-grey-700 !default;
|
||||
$pre-background: $ibo-color-grey-600 !default;
|
||||
$content-blockquote-background-color: $ibo-color-grey-600 !default;
|
||||
|
||||
$ibo-scrollbar--scrollbar-track-background-color: $ibo-color-grey-700 !default;
|
||||
$ibo-scrollbar--scrollbar-thumb-background-color: $ibo-color-grey-900 !default;
|
||||
@@ -198,6 +199,7 @@ $ibo-input-select--action-button--color: $ibo-input-select-wrapper--after--color
|
||||
$ibo-input-select-selectize--item--active--text-color: $ibo-color-grey-100 !default;
|
||||
$ibo-input-select-selectize--item--active--background-color: $ibo-color-grey-500 !default;
|
||||
$ibo-input-select--autocomplete-item-image--background-color: $ibo-color-grey-800 !default;
|
||||
$ibo-input-date--button--color: $ibo-input-select--action-button--color;
|
||||
$ibo-vendors-selectize-input--color: $ibo-body-text-color !default;
|
||||
$ibo-vendors-selectize-input--background-color: $ibo-input--background-color !default;
|
||||
$ibo-vendors-selectize--input--border-color: $ibo-input--border-color !default;
|
||||
@@ -245,6 +247,11 @@ $ibo-vendors-datatables--row-highlight--colors:('red': ($ibo-color-red-700),'dan
|
||||
|
||||
$ibo-vendors-jqueryui--ui-dialog--background-color: $ibo-color-grey-800 !default;
|
||||
$ibo-vendors-jqueryui--ui-dialog-titlebar--border-bottom: solid 1px $ibo-color-grey-500 !default;
|
||||
$ibo-vendors-jqueryui--ui-datepicker--background-color: $ibo-color-grey-700 !default;
|
||||
$ibo-vendors-jqueryui--ui-datepicker-days--color: $ibo-color-primary-200 !default;
|
||||
$ibo-vendors-jqueryui--ui-datepicker-days--highlight--background-color: $ibo-color-primary-800 !default;
|
||||
$ibo-vendors-jqueryui--ui-datepicker-days--hover--background-color: $ibo-color-primary-500 !default;
|
||||
$ibo-vendors-jqueryui--ui-datepicker-days--active--background-color: $ibo-color-primary-700 !default;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* CSS of the template page
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Javascript file loaded in template page
|
||||
*/
|
||||
|
||||
16
datamodels/2.x/combodo-data-feature-removal/composer.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"config": {
|
||||
"classmap-authoritative": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Combodo\\iTop\\DataFeatureRemoval\\": "src"
|
||||
}
|
||||
},
|
||||
"name": "combodo/combodo-data-feature-removal",
|
||||
"type": "itop-extension",
|
||||
"description": "iTop Data Feature Removal",
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0"
|
||||
}
|
||||
}
|
||||
20
datamodels/2.x/combodo-data-feature-removal/composer.lock
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"_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"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<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&exec_page=index.php&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>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?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: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:Error:Issues' => 'Some objects must be deleted manually prior to cleanup',
|
||||
|
||||
'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: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:IssueCount' => 'Issues found preventing automatic cleanup',
|
||||
|
||||
'DataFeatureRemoval:Column:DeletedCount' => 'Deleted entries',
|
||||
'DataFeatureRemoval:Column:UpdatedCount' => 'Updated entries',
|
||||
]);
|
||||
@@ -0,0 +1,58 @@
|
||||
<?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 d’une 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 l’assistant de configuration à activer ou désactiver des fonctionnalités.',
|
||||
'DataFeatureRemoval:Helper:Desc2' => 'Analyse si des données ou des dépendances empêchent l’activation ou la désactivation d’une fonctionnalité.',
|
||||
|
||||
'DataFeatureRemoval:Features:Title' => 'Fonctionnalités',
|
||||
'DataFeatureRemoval:Analysis:Title' => 'Résultat de l’analyse',
|
||||
'DataFeatureRemoval:Analysis:SubTitle' => '%1$s élément(s) à nettoyer avant de poursuivre',
|
||||
|
||||
'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:Error:Issues' => 'Certains objets doivent être supprimés manuellement avant le nettoyage',
|
||||
|
||||
'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 l’assistant de configuration',
|
||||
'UI:Button:PlanDeletion' => 'Préparer le plan de suppression',
|
||||
'UI:Button:DoDeletion' => 'Supprimer les données',
|
||||
'UI:Button:BackToMain' => 'Retour à la suppression de fonctionnalités',
|
||||
'UI:Button:Setup' => 'Retour à l’assistant de configuration',
|
||||
|
||||
'UI:Action:ForceUninstall' => 'Forcer la désinstallation',
|
||||
'UI:Action:MoreInfo' => 'Plus d’informations',
|
||||
|
||||
'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:IssueCount' => 'Problèmes empêchant le nettoyage automatique',
|
||||
|
||||
'DataFeatureRemoval:Column:DeletedCount' => 'Entrées supprimées',
|
||||
'DataFeatureRemoval:Column:UpdatedCount' => 'Entrées mises à jour',
|
||||
]);
|
||||
20
datamodels/2.x/combodo-data-feature-removal/index.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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();
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-data-feature-removal/3.3.0',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
'label' => 'iTop Data Feature Removal',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => [
|
||||
|
||||
],
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => [
|
||||
'vendor/autoload.php',
|
||||
'model.combodo-data-feature-removal.php', // Contains the PHP code generated by the "compilation" of datamodel.combodo-data-feature-removal.xml
|
||||
],
|
||||
'webservice' => [],
|
||||
'data.struct' => [
|
||||
// add your 'structure' definition XML files here,
|
||||
],
|
||||
'data.sample' => [
|
||||
// add your sample data XML files here,
|
||||
],
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => [
|
||||
// Module specific settings go here, if any
|
||||
],
|
||||
]
|
||||
);
|
||||
@@ -0,0 +1,307 @@
|
||||
<?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\DataCleanupService;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use SetupUtils;
|
||||
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['aAnalysisDataTable'] = $this->aAnalysisDataTable;
|
||||
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
|
||||
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
|
||||
$aParams['bHasData'] = $this->iCount > 0;
|
||||
$aParams['sSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup';
|
||||
$aParams['iCount'] = $this->iCount;
|
||||
|
||||
$this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css');
|
||||
$this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js');
|
||||
$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 OperationAnalysisResult(): void
|
||||
{
|
||||
$aParams = [];
|
||||
|
||||
if (SetupUtils::IsSessionSetupTokenValid()) {
|
||||
//from setup wizard/mtp
|
||||
SetupUtils::EraseSetupToken();
|
||||
} else {
|
||||
//from same module
|
||||
$this->ValidateTransactionId();
|
||||
}
|
||||
|
||||
$sSourceEnv = MetaModel::GetEnvironment();
|
||||
$oSetupAudit = new SetupAudit($sSourceEnv);
|
||||
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
|
||||
IssueLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
|
||||
|
||||
$oDataCleanupService = new DataCleanupService();
|
||||
$aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aGetRemovedClasses);
|
||||
$aColumns = ['Class', 'DeleteCount' , 'UpdateCount', 'IssueCount'];
|
||||
$aRows = [];
|
||||
$iQueryCount = 0;
|
||||
$bHasIssues = false;
|
||||
foreach ($aDeletionPlanSummaryEntities as $oDeletionPlanSummaryEntity) {
|
||||
$aRows[] = [
|
||||
$oDeletionPlanSummaryEntity->sClass,
|
||||
$oDeletionPlanSummaryEntity->iDeleteCount,
|
||||
$oDeletionPlanSummaryEntity->iUpdateCount,
|
||||
$oDeletionPlanSummaryEntity->iIssueCount,
|
||||
];
|
||||
$bHasIssues |= ($oDeletionPlanSummaryEntity->iIssueCount !== 0);
|
||||
$iQueryCount += $oDeletionPlanSummaryEntity->iDeleteCount;
|
||||
$iQueryCount += $oDeletionPlanSummaryEntity->iUpdateCount;
|
||||
}
|
||||
|
||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||
$aParams['aDeletionPlanSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows);
|
||||
$aParams['aClasses'] = $aGetRemovedClasses;
|
||||
$aParams['iQueryCount'] = $iQueryCount;
|
||||
$aParams['bDeletionPossible'] = !$bHasIssues;
|
||||
|
||||
$this->DisplayPage($aParams);
|
||||
}
|
||||
|
||||
public function OperationDeletionPlan(): void
|
||||
{
|
||||
$aParams = [];
|
||||
$this->ValidateTransactionId();
|
||||
|
||||
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
|
||||
$oDataCleanupService = new DataCleanupService();
|
||||
$aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aClasses);
|
||||
$aColumns = ['Class', 'DeleteCount' , 'UpdateCount', 'IssueCount'];
|
||||
$aRows = [];
|
||||
$iQueryCount = 0;
|
||||
$bHasIssues = false;
|
||||
foreach ($aDeletionPlanSummaryEntities as $oDeletionPlanSummaryEntity) {
|
||||
$aRows[] = [
|
||||
$oDeletionPlanSummaryEntity->sClass,
|
||||
$oDeletionPlanSummaryEntity->iDeleteCount,
|
||||
$oDeletionPlanSummaryEntity->iUpdateCount,
|
||||
$oDeletionPlanSummaryEntity->iIssueCount,
|
||||
];
|
||||
$bHasIssues |= ($oDeletionPlanSummaryEntity->iIssueCount !== 0);
|
||||
$iQueryCount += $oDeletionPlanSummaryEntity->iDeleteCount;
|
||||
$iQueryCount += $oDeletionPlanSummaryEntity->iUpdateCount;
|
||||
}
|
||||
|
||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||
$aParams['aDeletionPlanSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows);
|
||||
$aParams['aClasses'] = $aClasses;
|
||||
$aParams['iQueryCount'] = $iQueryCount;
|
||||
$aParams['bDeletionPossible'] = !$bHasIssues;
|
||||
|
||||
$this->DisplayPage($aParams);
|
||||
}
|
||||
|
||||
public function OperationDoDeletion(): void
|
||||
{
|
||||
$aParams = [];
|
||||
$this->ValidateTransactionId();
|
||||
|
||||
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
|
||||
$oDataCleanupService = new DataCleanupService();
|
||||
$aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($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 */
|
||||
|
||||
$sChecked = '';
|
||||
$sDisabledHtml = '';
|
||||
if ($oExtension->bRemovedFromDisk) {
|
||||
$sDisabledHtml = 'disabled=""';
|
||||
$sChecked = 'checked';
|
||||
} elseif (in_array($sCode, $this->aSelectedExtensionsForCheck)) {
|
||||
$sChecked = 'checked';
|
||||
}
|
||||
|
||||
$sLabel = $oExtension->sLabel;
|
||||
$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 void
|
||||
*/
|
||||
public function ReadRemovedExtensions(): void
|
||||
{
|
||||
if (count($this->aSelectedExtensionsForCheck) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Entity;
|
||||
|
||||
class DataCleanupSummaryEntity
|
||||
{
|
||||
public string $sClass;
|
||||
public int $iIssueCount = 0;
|
||||
public int $iUpdateCount = 0;
|
||||
public int $iDeleteCount = 0;
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*/
|
||||
public function __construct(string $sClass)
|
||||
{
|
||||
$this->sClass = $sClass;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Helper;
|
||||
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class DataFeatureRemovalConfig
|
||||
{
|
||||
private static DataFeatureRemovalConfig $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): DataFeatureRemovalConfig
|
||||
{
|
||||
if (!isset(self::$oInstance)) {
|
||||
self::$oInstance = new DataFeatureRemovalConfig();
|
||||
}
|
||||
|
||||
return self::$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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?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';
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service;
|
||||
|
||||
use CMDBObjectSet;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
|
||||
use Combodo\iTop\Service\Limits\ExecutionLimits;
|
||||
use DBObject;
|
||||
use DBObjectSearch;
|
||||
use MetaModel;
|
||||
|
||||
class DataCleanupService
|
||||
{
|
||||
private array $aVisited = [];
|
||||
private iObjectService $oObjectService;
|
||||
private ExecutionLimits $oExecutionLimits;
|
||||
|
||||
public function __construct(int $iMaxExecutionTime = 30, int $iMaxMemoryPercent = 80)
|
||||
{
|
||||
DataFeatureRemovalLog::Enable();
|
||||
$this->oExecutionLimits = new ExecutionLimits($iMaxExecutionTime, $iMaxMemoryPercent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\DataCleanupSummaryEntity>
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
|
||||
*/
|
||||
public function GetCleanupSummary(?array $aClasses): array
|
||||
{
|
||||
return $this->ExecuteCleanup($aClasses ?? [], oObjectService: new ObjectServiceSummary());
|
||||
}
|
||||
|
||||
private function GetNextObjectToDelete(array $aClasses): ?DBObject
|
||||
{
|
||||
foreach ($aClasses as $sClass) {
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
$oFilter->AllowAllData();
|
||||
$oSet = new \DBObjectSet($oFilter);
|
||||
while ($oObject = $oSet->Fetch()) {
|
||||
if (!$this->IsVisited($oObject)) {
|
||||
return $oObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aClasses
|
||||
* @param \Combodo\iTop\DataFeatureRemoval\Service\iObjectService|null $oObjectService
|
||||
*
|
||||
* @return array execution summary
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function ExecuteCleanup(array $aClasses, ?iObjectService $oObjectService = null): array
|
||||
{
|
||||
$this->oObjectService = $oObjectService ?? new ObjectService();
|
||||
|
||||
$this->aVisited = [];
|
||||
|
||||
while ($oObject = $this->GetNextObjectToDelete($aClasses)) {
|
||||
if ($this->RecursiveDeletion($oObject) === false) {
|
||||
// Timeout, stop here
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $this->oObjectService->GetSummary();
|
||||
|
||||
}
|
||||
|
||||
private function MarkObjectAsVisited(DBObject $oObject): void
|
||||
{
|
||||
$sClass = get_class($oObject);
|
||||
$sId = $oObject->GetKey();
|
||||
$sKey = "$sClass-$sId";
|
||||
$this->aVisited[$sKey] = true;
|
||||
}
|
||||
|
||||
private function IsVisited(DBObject $oObject): bool
|
||||
{
|
||||
$sClass = get_class($oObject);
|
||||
$sId = $oObject->GetKey();
|
||||
$sKey = "$sClass-$sId";
|
||||
|
||||
$bRes = $this->aVisited[$sKey] ?? false;
|
||||
DataFeatureRemovalLog::Debug('Checking if object is visited', null, [$sKey, $bRes]);
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \DBObject $oObjectToClean
|
||||
*
|
||||
* @return bool true if deletion is complete, false in case of timeout or memory limit reached
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
private function RecursiveDeletion(DBObject $oObjectToClean): bool
|
||||
{
|
||||
$this->MarkObjectAsVisited($oObjectToClean);
|
||||
$sClass = get_class($oObjectToClean);
|
||||
|
||||
$aReferencingMe = MetaModel::EnumReferencingClasses($sClass);
|
||||
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
|
||||
/** @var \AttributeExternalKey $oExtKeyAttDef */
|
||||
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
|
||||
// skip if this external key is behind an external field
|
||||
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$oSearch = new DBObjectSearch($sRemoteClass);
|
||||
$oSearch->AddCondition($sExtKeyAttCode, $oObjectToClean->GetKey(), '=');
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new CMDBObjectSet($oSearch);
|
||||
$oSet->OptimizeColumnLoad([$sRemoteClass => [$oExtKeyAttDef->GetCode()]]);
|
||||
/** @var DBObject $oDependentObj */
|
||||
while ($oDependentObj = $oSet->Fetch()) {
|
||||
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
|
||||
if ($iDeletePropagationOption == DEL_MANUAL) {
|
||||
$this->oObjectService->SetIssue(get_class($oDependentObj));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($oExtKeyAttDef->IsNullAllowed()) {
|
||||
// Optional external key, list to reset
|
||||
if (($iDeletePropagationOption == DEL_MOVEUP) && ($oExtKeyAttDef->IsHierarchicalKey())) {
|
||||
// Move the child up one level i.e. set the same parent as the current object
|
||||
$iParentId = $oObjectToClean->Get($oExtKeyAttDef->GetCode());
|
||||
$this->oObjectService->Update($oDependentObj, $oExtKeyAttDef->GetCode(), $iParentId);
|
||||
} else {
|
||||
$this->oObjectService->Update($oDependentObj, $oExtKeyAttDef->GetCode(), 0);
|
||||
}
|
||||
if ($this->oExecutionLimits->ShouldStopExecution()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Propagate deletion only if not visited
|
||||
if ($this->IsVisited($oDependentObj)) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->RecursiveDeletion($oDependentObj)) {
|
||||
// Timeout
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->oObjectService->Delete($sClass, $oObjectToClean->GetKey());
|
||||
|
||||
if ($this->oExecutionLimits->ShouldStopExecution()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service;
|
||||
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
|
||||
use DBObject;
|
||||
use DBObjectSearch;
|
||||
use MetaModel;
|
||||
|
||||
class ObjectService extends ObjectServiceSummary
|
||||
{
|
||||
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
|
||||
{
|
||||
$oToUpdate->Set($sAttCode, $value);
|
||||
$oToUpdate->DBUpdate();
|
||||
parent::Update($oToUpdate, $sAttCode, $value);
|
||||
}
|
||||
|
||||
public function Delete(string $sClass, string $sId): void
|
||||
{
|
||||
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) {
|
||||
/** @var DBObjectSearch $oFilter */
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id");
|
||||
$sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]);
|
||||
CMDBSource::DeleteFrom($sQuery);
|
||||
}
|
||||
|
||||
CMDBSource::Query('COMMIT');
|
||||
parent::Delete($sClass, $sId);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DataFeatureRemovalLog::Exception(__METHOD__.': Cleanup failed', $e);
|
||||
CMDBSource::Query('ROLLBACK');
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetIssue(string $sClass): void
|
||||
{
|
||||
throw new DataFeatureRemovalException('Deletion Plan cannot be executed due to issues');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service;
|
||||
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
|
||||
use DBObject;
|
||||
|
||||
/**
|
||||
* Manage operation summary instead of doing the actual update or delete
|
||||
*
|
||||
* The summary is an array [class => DeletionPlanSummaryEntity]
|
||||
*/
|
||||
class ObjectServiceSummary implements iObjectService
|
||||
{
|
||||
private array $aSummary = [];
|
||||
|
||||
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
|
||||
{
|
||||
$sClass = get_class($oToUpdate);
|
||||
DataFeatureRemovalLog::Info('Update object', null, ['class' => $sClass, 'id' => $oToUpdate->GetKey(), 'code' => $sAttCode, 'value' => "$value"]);
|
||||
if (! array_key_exists($sClass, $this->aSummary)) {
|
||||
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
|
||||
}
|
||||
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
|
||||
$oDeletionPlanSummaryEntity->iUpdateCount++;
|
||||
}
|
||||
|
||||
public function Delete(string $sClass, string $sId): void
|
||||
{
|
||||
DataFeatureRemovalLog::Info('Delete object', null, ['class' => $sClass, 'id' => $sId]);
|
||||
if (!array_key_exists($sClass, $this->aSummary)) {
|
||||
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
|
||||
}
|
||||
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
|
||||
$oDeletionPlanSummaryEntity->iDeleteCount++;
|
||||
}
|
||||
|
||||
public function SetIssue(string $sClass): void
|
||||
{
|
||||
DataFeatureRemovalLog::Info('Issue on object', null, ['class' => $sClass]);
|
||||
if (!array_key_exists($sClass, $this->aSummary)) {
|
||||
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
|
||||
}
|
||||
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
|
||||
$oDeletionPlanSummaryEntity->iIssueCount++;
|
||||
}
|
||||
|
||||
public function GetSummary(): array
|
||||
{
|
||||
return $this->aSummary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service;
|
||||
|
||||
use DBObject;
|
||||
|
||||
interface iObjectService
|
||||
{
|
||||
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void;
|
||||
|
||||
public function Delete(string $sClass, string $sId): void;
|
||||
|
||||
public function SetIssue(string $sClass): void;
|
||||
|
||||
public function GetSummary(): array;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{# @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 %}
|
||||
{% UIToolbar ForButton {} %}
|
||||
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
|
||||
{% EndUIToolbar %}
|
||||
{% EndUIForm %}
|
||||
{% else %}
|
||||
{{ 'DataFeatureRemoval:DeletionPlan:Error:Issues'|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 %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{# @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 %}
|
||||
{% UIToolbar ForButton {} %}
|
||||
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
|
||||
{% EndUIToolbar %}
|
||||
{% EndUIForm %}
|
||||
{% else %}
|
||||
{{ 'DataFeatureRemoval:DeletionPlan:Error:Issues'|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 %}
|
||||
@@ -0,0 +1,14 @@
|
||||
{# @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 %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{# @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 %}
|
||||
{% UIToolbar ForButton {} %}
|
||||
{% UIButton ForPrimaryAction {sLabel:'UI:Button:PlanDeletion'|dict_s, sName:'btn_plandeletion', sId:'btn_plandeletion', bIsSubmit:true} %}
|
||||
{% EndUIToolbar %}
|
||||
{% EndUIForm %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,16 @@
|
||||
{# @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 %}
|
||||
@@ -0,0 +1,35 @@
|
||||
{# @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 not bHasData %}
|
||||
{% 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 %}
|
||||
22
datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit4f96a7199e2c0d90e547333758b26464::getLoader();
|
||||
579
datamodels/2.x/combodo-data-feature-removal/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
396
datamodels/2.x/combodo-data-feature-removal/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||
* @internal
|
||||
*/
|
||||
private static $selfDir = null;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private static $installedIsLocalDir;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
|
||||
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||
// all installed packages for example
|
||||
self::$installedIsLocalDir = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getSelfDir()
|
||||
{
|
||||
if (self::$selfDir === null) {
|
||||
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||
}
|
||||
|
||||
return self::$selfDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
$selfDir = self::getSelfDir();
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||
self::$installed = $required;
|
||||
self::$installedIsLocalDir = true;
|
||||
}
|
||||
}
|
||||
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
datamodels/2.x/combodo-data-feature-removal/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
21
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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\\DataCleanupSummaryEntity' => $baseDir . '/src/Entity/DataCleanupSummaryEntity.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\\DataCleanupService' => $baseDir . '/src/Service/DataCleanupService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Service/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => $baseDir . '/src/Service/ObjectService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => $baseDir . '/src/Service/ObjectServiceSummary.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => $baseDir . '/src/Service/iObjectService.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
9
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
10
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\' => array($baseDir . '/src'),
|
||||
);
|
||||
37
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
47
datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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 $classMap = array (
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DataCleanupSummaryEntity' => __DIR__ . '/../..' . '/src/Entity/DataCleanupSummaryEntity.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\\DataCleanupService' => __DIR__ . '/../..' . '/src/Service/DataCleanupService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Service/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => __DIR__ . '/../..' . '/src/Service/ObjectService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => __DIR__ . '/../..' . '/src/Service/ObjectServiceSummary.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => __DIR__ . '/../..' . '/src/Service/iObjectService.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->classMap = ComposerStaticInit4f96a7199e2c0d90e547333758b26464::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
5
datamodels/2.x/combodo-data-feature-removal/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"packages": [],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
23
datamodels/2.x/combodo-data-feature-removal/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'combodo/combodo-data-feature-removal',
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '19bbf6759bb4f6f5814d9ec1b0b5514208efc0b2',
|
||||
'type' => 'itop-extension',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'combodo/combodo-data-feature-removal' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '19bbf6759bb4f6f5814d9ec1b0b5514208efc0b2',
|
||||
'type' => 'itop-extension',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -10,6 +10,7 @@ namespace Combodo\iTop\DBTools\Service;
|
||||
use CMDBSource;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use IssueLog;
|
||||
|
||||
class DBToolsUtils
|
||||
{
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
<choice>
|
||||
<extension_code>itop-problem-mgmt</extension_code>
|
||||
<title>Problem Management</title>
|
||||
<description>Select this option track "Problems" in iTop.</description>
|
||||
<description>Select this option to track "Problems" in iTop.</description>
|
||||
<modules type="array">
|
||||
<module>itop-problem-mgmt</module>
|
||||
</modules>
|
||||
|
||||
@@ -131,7 +131,7 @@ try {
|
||||
$oPage = new JsonPage();
|
||||
$oPage->SetOutputDataOnly(true);
|
||||
|
||||
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
|
||||
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, 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', 'production', false, 'raw_data');
|
||||
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
|
||||
try {
|
||||
set_time_limit(0);
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class DBRestore extends DBBackup
|
||||
*
|
||||
* @uses \RunTimeEnvironment::CompileFrom()
|
||||
*/
|
||||
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
|
||||
public function RestoreFromCompressedBackup($sFile, $sEnvironment = ITOP_DEFAULT_ENV)
|
||||
{
|
||||
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
|
||||
IssueLog::Info("Backup Restore - Acquiring the LOCK 'restore.$sEnvironment'");
|
||||
|
||||
@@ -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', 'production', false, 'raw_data');
|
||||
$sEnvironment = utils::ReadParam('environment', ITOP_DEFAULT_ENV, false, 'raw_data');
|
||||
$oRestore->RestoreFromCompressedBackup($sBackupFile, $sEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
43
datamodels/2.x/itop-config-mgmt/assets/img/icon-acer.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="acer"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="83"
|
||||
height="83"
|
||||
viewBox="0 0 83 83"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="icon-acer.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:svg="http://www.w3.org/2000/svg"><svg:defs
|
||||
id="defs1" /><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="true"
|
||||
inkscape:zoom="10.483071"
|
||||
inkscape:cx="75.78886"
|
||||
inkscape:cy="35.676568"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="acer"><sodipodi:guide
|
||||
position="40.307919,41.220214"
|
||||
orientation="0,-1"
|
||||
id="guide1"
|
||||
inkscape:locked="false" /></sodipodi:namedview>
|
||||
<svg:path
|
||||
id="acer-logo"
|
||||
style="fill:#80c343"
|
||||
d="m 82.85,32.760893 c -0.29,-0.42 -0.62,-0.7 -2.04,-0.81 -0.37,-0.03 -1.6,-0.07 -3.66,-0.07 -5.42,0 -9.1,1.65 -10.98,4.91 0.52,-3.28 -2.67,-4.92 -9.55,-4.92 -8.09,0 -13.14,3.27 -15.15,9.81 -0.74,1.91 -0.82,4.02 -0.23,5.98 l -1.91,0.13 c -1.49,0.11 -3.46,0.22 -4.66,0.22 -2.96,0 -4.8,-0.5 -5.51,-1.5 -0.64,-0.9 -0.57,-2.56 0.17,-4.98 1.23,-4.02 4.29,-5.82 9.18,-5.82 2.53,0 5,0.27 5,0.27 0.3,-0.05 0.51,-0.33 0.46,-0.64 0,-0.01 0,-0.02 -0.01,-0.03 l -0.05,-0.38 -0.17,-1.35 c -0.11,-0.89 -0.77,-1.41 -1.97,-1.57 -1.1,-0.07 -1.91,-0.13 -3.12,-0.13 h -0.07 c -6.39,0.01 -10.84,2.12 -13.36,6.32 0.92,-4.21 -2.04,-6.32 -8.87,-6.32 -2.73,-0.05 -5.46,0.06 -8.18,0.33 -1.03,-0.03 -1.96,0.61 -2.33,1.57 l -0.54,1.73 c -0.1,0.32 0.05,0.48 0.46,0.48 h 0.01 c 0.3,-0.04 1.46,-0.15 3.44,-0.31 2.62,-0.21 4.55,-0.32 5.83,-0.32 3.77,0 5.35,0.95 4.76,2.84 -0.11,0.4 -0.44,0.71 -0.85,0.78 -3.56,0.59 -6.39,1.02 -8.48,1.28 -5.89,0.75 -9.29,2.59 -10.2,5.52 -1.25,4.03 1.89,6.04 9.44,6.04 3.17,0.04 6.34,-0.18 9.48,-0.65 1.47,-0.25 2.22,-0.63 2.51,-1.58 l 1.41,-4.49 c -0.15,4.49 2.99,6.75 9.41,6.75 2.23,0.04 4.45,-0.06 6.66,-0.31 1.32,-0.23 1.95,-0.52 2.24,-1.51 l 0.28,-1.41 c 1.37,2.14 4.37,3.21 9.01,3.21 4.89,0 7.74,-0.14 8.55,-0.41 0.57,-0.12 1.04,-0.52 1.25,-1.06 0.03,-0.09 0.05,-0.19 0.06,-0.28 l 0.59,-1.91 c 0.1,-0.33 -0.05,-0.49 -0.45,-0.48 l -3.13,0.15 c -2.09,0.12 -3.72,0.18 -4.9,0.17 -1.54,0.08 -3.08,-0.07 -4.58,-0.46 -1.2,-0.41 -1.94,-1.61 -1.77,-2.86 l 9.91,-1.27 c 4.44,-0.57 7.42,-1.94 8.92,-4.12 l -3.37,11.73 c -0.07,0.18 -0.04,0.38 0.07,0.53 0.18,0.17 0.41,0.25 0.65,0.22 h 4.1 c 0.47,0.07 0.93,-0.22 1.06,-0.68 l 3.62,-12.67 c 0.48,-1.67 2,-2.48 4.67,-2.48 2.41,0 4.22,0.02 5.38,0.07 0.03,0 0.06,0 0.09,0 0.39,0 0.74,-0.26 0.84,-0.63 l 0.63,-1.74 c 0.15,-0.3 0.12,-0.63 -0.05,-0.89 m -66.12,15.24 c -1.83,0.23 -3.68,0.33 -5.52,0.3 -4.17,0 -5.99,-0.84 -5.46,-2.53 0.38,-1.21 1.47,-1.94 3.28,-2.19 l 9.48,-1.28 z m 43.83,-10.27 c -0.4,1.3 -2.25,2.19 -5.56,2.67 l -7.9,1.13 0.2,-0.65 c 0.39,-1.74 1.37,-3.28 2.79,-4.37 1.2,-0.77 3.15,-1.16 5.86,-1.16 3.56,0 5.1,0.8 4.61,2.38" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
124
datamodels/2.x/itop-config-mgmt/assets/img/icon-cisco.svg
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="108"
|
||||
height="108"
|
||||
viewBox="0 0 108 108"
|
||||
role="img"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="icon-cisco.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"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="true"
|
||||
inkscape:zoom="6.8229602"
|
||||
inkscape:cx="48.879078"
|
||||
inkscape:cy="51.737075"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg11">
|
||||
<sodipodi:guide
|
||||
position="16.939587,53.376303"
|
||||
orientation="0,-1"
|
||||
id="guide11"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<title
|
||||
id="fw-c-header__logo-title">Cisco.com France</title>
|
||||
<defs
|
||||
id="defs1">
|
||||
<path
|
||||
d="m 0,22.769 a 2.348,2.348 0 0 0 3.935,1.545 c 0.434,-0.403 0.7,-0.955 0.744,-1.545 v -5.2 a 2.34,2.34 0 0 0 -4.679,0 v 5.2"
|
||||
id="bar_short"
|
||||
class="bar" />
|
||||
<path
|
||||
d="m 12.95,22.769 a 2.349,2.349 0 0 0 2.34,2.171 2.346,2.346 0 0 0 2.339,-2.171 V 11.112 a 2.341,2.341 0 0 0 -4.679,0 V 22.77"
|
||||
id="bar_tall"
|
||||
class="bar" />
|
||||
<path
|
||||
d="m 25.832,27.464 a 2.345,2.345 0 0 0 4.678,0 V 2.249 a 2.342,2.342 0 0 0 -4.678,0 v 25.215"
|
||||
id="bar_grande"
|
||||
class="bar" />
|
||||
<path
|
||||
d="m 24.026,56.277 v -5.002 l -0.098,0.043 a 9.253,9.253 0 0 1 -3.605,0.915 5.303,5.303 0 0 1 -3.63,-1.07 4.644,4.644 0 0 1 -1.58,-2.244 5.395,5.395 0 0 1 -0.106,-3 4.6,4.6 0 0 1 1.609,-2.566 4.823,4.823 0 0 1 2.528,-1.09 8.332,8.332 0 0 1 4.774,0.895 l 0.108,0.056 v -5.03 l -0.228,-0.061 a 12.78,12.78 0 0 0 -4.552,-0.596 10.534,10.534 0 0 0 -4.065,0.93 9.29,9.29 0 0 0 -3.329,2.572 10.014,10.014 0 0 0 -0.182,12.18 9.546,9.546 0 0 0 5.292,3.403 c 2.211,0.538 4.528,0.456 6.697,-0.234 l 0.367,-0.101"
|
||||
id="cisco_c" />
|
||||
</defs>
|
||||
<g
|
||||
fill="#02c8ff"
|
||||
fill-rule="evenodd"
|
||||
id="g11"
|
||||
transform="translate(-0.09466859,26.234946)">
|
||||
<use
|
||||
href="#cisco_c"
|
||||
id="use1" />
|
||||
<use
|
||||
href="#cisco_c"
|
||||
x="49.5"
|
||||
id="use2" />
|
||||
<path
|
||||
d="m 41.69,52.125 -0.019,4.308 0.315,0.054 c 0.989,0.185 1.987,0.313 2.99,0.385 a 18.1,18.1 0 0 0 2.642,0.051 c 0.842,-0.06 1.675,-0.218 2.48,-0.468 a 6.862,6.862 0 0 0 2.573,-1.371 5.19,5.19 0 0 0 1.498,-2.148 5.912,5.912 0 0 0 -0.03,-4.324 4.852,4.852 0 0 0 -1.343,-1.862 5.568,5.568 0 0 0 -1.97,-1.147 l -3.25,-1.206 a 1.742,1.742 0 0 1 -0.887,-0.845 1.107,1.107 0 0 1 0.036,-0.986 1.29,1.29 0 0 1 0.217,-0.291 1.75,1.75 0 0 1 0.48,-0.347 c 0.363,-0.18 0.755,-0.293 1.158,-0.337 a 6.76,6.76 0 0 1 2.072,0.022 c 0.81,0.088 1.613,0.231 2.402,0.43 l 0.168,0.037 v -3.974 l -0.31,-0.067 a 21.14,21.14 0 0 0 -2.444,-0.435 12.545,12.545 0 0 0 -3.213,-0.014 6.945,6.945 0 0 0 -3.699,1.488 4.908,4.908 0 0 0 -1.58,2.178 5.984,5.984 0 0 0 -0.003,4.05 c 0.242,0.65 0.63,1.237 1.136,1.714 0.437,0.422 0.932,0.78 1.47,1.065 0.708,0.38 1.458,0.675 2.235,0.878 0.257,0.077 0.512,0.158 0.766,0.243 l 0.385,0.141 0.11,0.045 c 0.38,0.136 0.726,0.35 1.018,0.628 0.202,0.19 0.358,0.423 0.455,0.683 0.06,0.237 0.061,0.485 0.003,0.723 a 1.536,1.536 0 0 1 -0.744,0.892 3.691,3.691 0 0 1 -1.239,0.387 9,9 0 0 1 -1.92,0.097 21.973,21.973 0 0 1 -2.507,-0.334 c -0.433,-0.09 -0.864,-0.19 -1.291,-0.303 z m -11.144,4.482 h 4.73 V 37.846 h -4.73 z M 85.305,43.386 a 4.934,4.934 0 1 1 6.157,7.711 4.934,4.934 0 0 1 -6.157,-7.71 m -6.867,3.848 a 9.87,9.87 0 0 0 12.002,9.485 9.629,9.629 0 0 0 3.157,-17.729 9.934,9.934 0 0 0 -15.16,8.244"
|
||||
id="path2" />
|
||||
<use
|
||||
href="#bar_short"
|
||||
x="0"
|
||||
id="use3" />
|
||||
<use
|
||||
href="#bar_tall"
|
||||
x="0"
|
||||
id="use4" />
|
||||
<use
|
||||
href="#bar_grande"
|
||||
x="0"
|
||||
id="use5" />
|
||||
<use
|
||||
href="#bar_tall"
|
||||
x="25.875"
|
||||
id="use6" />
|
||||
<use
|
||||
href="#bar_short"
|
||||
x="51.75"
|
||||
id="use7" />
|
||||
<use
|
||||
href="#bar_tall"
|
||||
x="51.75"
|
||||
id="use8" />
|
||||
<use
|
||||
href="#bar_grande"
|
||||
x="51.75"
|
||||
id="use9" />
|
||||
<use
|
||||
href="#bar_tall"
|
||||
x="77.625"
|
||||
id="use10" />
|
||||
<use
|
||||
href="#bar_short"
|
||||
x="103.375"
|
||||
id="use11" />
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata11">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>Cisco.com France</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
56
datamodels/2.x/itop-config-mgmt/assets/img/icon-hpe.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 29.5.1, SVG Export Plug-In . SVG Version: 9.03 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.0"
|
||||
id="katman_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 630 630"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="icon-hpe.svg"
|
||||
width="630"
|
||||
height="630"
|
||||
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="defs2" /><sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="true"
|
||||
inkscape:zoom="0.6905515"
|
||||
inkscape:cx="-217.94175"
|
||||
inkscape:cy="275.1424"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="katman_1"><sodipodi:guide
|
||||
position="197.66244,314.48848"
|
||||
orientation="0,-1"
|
||||
id="guide2"
|
||||
inkscape:locked="false" /></sodipodi:namedview>
|
||||
<style
|
||||
type="text/css"
|
||||
id="style1">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:36;}
|
||||
.st1{fill:none;stroke:#03A883;stroke-width:36;}
|
||||
</style>
|
||||
<path
|
||||
class="st0"
|
||||
d="m 18.511987,405.93012 v -180 m 154.000003,180 v -180 m -154.000003,89 H 155.51199 m 95,91 v -180 m 0,18 h 102 c 27.6,0 50,22.4 50,50 0,27.6 -22.4,50 -50,50 h -102 m 222,-67 v -33 h 158"
|
||||
id="path1" />
|
||||
<path
|
||||
class="st1"
|
||||
d="m 630.51199,387.93012 h -158 v -76 h 158"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 231 231"
|
||||
preserveAspectRatio="xMinYMid"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
xml:space="preserve"
|
||||
width="231"
|
||||
height="231"
|
||||
sodipodi:docname="icon-oracle-linux.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"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="true"
|
||||
inkscape:zoom="7.5332891"
|
||||
inkscape:cx="107.05815"
|
||||
inkscape:cy="90.796993"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"><sodipodi:guide
|
||||
position="41.763589,115.468"
|
||||
orientation="0,-1"
|
||||
id="guide1"
|
||||
inkscape:locked="false" /></sodipodi:namedview><defs
|
||||
id="defs8"><rect
|
||||
x="-138.24641"
|
||||
y="81.567238"
|
||||
width="382.3674"
|
||||
height="240.21156"
|
||||
id="rect495" /><rect
|
||||
x="-17.612623"
|
||||
y="104.35898"
|
||||
width="171.05238"
|
||||
height="197.31444"
|
||||
id="rect291" /></defs><g
|
||||
id="g1407"
|
||||
transform="translate(0.61321542,76.835533)"><path
|
||||
d="m 99.59,19.52 h 15.24 L 106.78,6.52 91.98,30 h -6.73 l 18,-28.17 a 4.29,4.29 0 0 1 7,-0.05 L 128.3,30 h -6.73 l -3.17,-5.25 h -15.42 l -3.36,-5.23 m 69.93,5.23 V 0.28 h -5.72 v 26.88 a 2.76,2.76 0 0 0 0.85,2 2.89,2.89 0 0 0 2.08,0.87 h 26 l 3.39,-5.25 h -26.63 m -94.54,-4.4 a 10.05,10.05 0 0 0 0,-20.1 h -25 V 30 h 5.71 V 5.54 h 18.94 a 4.81,4.81 0 0 1 0,9.62 H 58.52 L 75.58,30 h 8.29 L 72.41,20.38 h 2.57 M 14.86,30 h 17.27 a 14.86,14.86 0 0 0 0,-29.71 H 14.86 a 14.86,14.86 0 1 0 0,29.71 m 16.88,-5.23 h -16.5 a 9.62,9.62 0 0 1 0,-19.23 h 16.5 a 9.62,9.62 0 1 1 0,19.23 M 140.23,30 h 17.63 l 3.34,-5.23 h -20.58 a 9.62,9.62 0 1 1 0,-19.23 h 16.75 l 3.38,-5.25 h -20.52 a 14.86,14.86 0 1 0 0,29.71 m 69.87,-5.23 a 9.62,9.62 0 0 1 -9.26,-7 h 24.42 l 3.36,-5.24 h -27.78 a 9.61,9.61 0 0 1 9.26,-7 h 16.76 l 3.35,-5.25 h -20.5 a 14.86,14.86 0 0 0 0,29.71 h 17.63 l 3.35,-5.23 h -20.6"
|
||||
style="fill:#c74634"
|
||||
id="path2" /><path
|
||||
id="rect749"
|
||||
style="fill:#c74634;fill-opacity:1;stroke-width:5.2519;stroke-linecap:square;paint-order:stroke fill markers"
|
||||
d="m 25.391517,47.930871 h 4.980863 v 3.830025 h -4.980863 z m 61.5008,18.557061 -7.24,-10.240002 h 4.96 l 4.64,7.080002 h 0.24 l 4.76,-7.080002 h 4.72 l -7.28,10.160002 7.64,10.88 h -4.96 l -5.08,-7.72 h -0.24 l -5.12,7.72 h -4.72 z m -21.599998,11.28 q -6.68,0 -6.68,-7.24 V 56.24793 h 4.12 v 13.760002 q 0,2.36 1.04,3.32 1.08,0.92 3.12,0.92 1.4,0 2.6,-0.68 1.2,-0.72 1.88,-2 0.72,-1.28 0.72,-2.96 V 56.24793 h 4.12 v 21.040002 h -3.32 l -0.4,-2.8 h -0.28 q -1.16,1.6 -2.92,2.44 -1.76,0.84 -4,0.84 z M 35.81232,56.24793 h 3.320001 l 0.4,2.800002 h 0.28 q 1.12,-1.600002 2.88,-2.440002 1.8,-0.84 4.04,-0.84 6.68,0 6.68,7.240002 v 14.28 h -4.12 v -13.76 q 0,-2.36 -1.08,-3.28 -1.04,-0.96 -3.08,-0.96 -1.4,0 -2.6,0.72 -1.2,0.68 -1.92,1.96 -0.68,1.28 -0.68,2.96 v 12.36 H 35.81232 Z M 3.61239,47.930871 h 4.44 v 25.517061 h 14.28 v 3.84 h -18.72 z M 26.256768,59.46395 V 77.287932 H 30.37238 V 56.275464 h -6.387612 v 1.825681 z" /></g></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
52
datamodels/2.x/itop-config-mgmt/assets/img/icon-sony.svg
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 1280 1280"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="icon-sony.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
width="1280"
|
||||
height="1280"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.63418639"
|
||||
inkscape:cx="-462.79769"
|
||||
inkscape:cy="225.48576"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4"
|
||||
showguides="true">
|
||||
<sodipodi:guide
|
||||
position="173.37108,641.89024"
|
||||
orientation="0,-1"
|
||||
id="guide1"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<svg:defs
|
||||
id="defs1" />
|
||||
<svg:g
|
||||
id="Layer_2">
|
||||
<svg:g
|
||||
id="g4"
|
||||
inkscape:label="logo">
|
||||
<svg:path
|
||||
d="m 456.0129,751.74687 c -46.41279,0 -89.42079,-13.82399 -118.09279,-39.60319 a 96.895989,96.895989 0 0 1 -32.12799,-73.19039 98.329588,98.329588 0 0 1 32.12799,-72.9344 c 26.624,-24.19199 73.728,-39.55199 118.09279,-39.55199 49.07519,0 88.37119,12.3648 118.39999,39.60319 a 97.407989,97.407989 0 0 1 31.69279,72.8832 101.52959,101.52959 0 0 1 -31.69279,73.19039 c -27.9808,25.9328 -71.9104,39.60319 -118.39999,39.60319 v -29.64479 c 24.6016,0 47.43679,-8.4992 63.38559,-24.3712 15.9488,-15.872 23.1936,-35.1232 23.1936,-58.87999 0,-22.6816 -7.9616,-43.8784 -23.1936,-58.88 -15.744,-15.48799 -39.11679,-24.21759 -63.38559,-24.21759 -24.2688,0 -47.74399,8.6528 -63.48799,24.21759 -15.1808,15.0272 -23.04,36.3008 -23.04,58.88 a 82.35519,82.35519 0 0 0 23.04,58.87999 c 15.744,15.6928 39.06559,24.3712 63.48799,24.3712 z M 117.12014,526.4669 c -24.806392,0 -52.991989,4.6592 -76.799986,15.36 C 18.099355,551.7597 1.575e-4,567.70849 1.575e-4,594.15329 a 54.220794,54.220794 0 0 0 14.7199985,37.2736 c 6.425599,5.9392 16.793599,16.0256 43.878396,21.9648 12.108798,2.55999 37.990395,6.68159 63.769588,9.39519 25.7792,2.7136 50.7648,5.12 61.0048,7.8592 8.1408,2.0736 21.83679,4.8896 21.83679,20.2496 0,15.36 -14.41279,19.968 -16.92159,20.9664 -2.5088,0.9984 -19.8144,8.9344 -50.8928,8.9344 a 216.42237,216.42237 0 0 1 -60.59519,-10.4192 c -11.596799,-4.1472 -23.756797,-9.6 -35.097596,-23.4496 a 40.268795,40.268795 0 0 1 -7.295999,-22.2208 H 6.2465567 v 78.84799 H 37.529754 v -10.67519 a 4.4543995,4.4543995 0 0 1 6.7584,-3.84 246.42557,246.42557 0 0 0 45.772794,14.79679 c 16.435202,3.4304 27.059192,5.9136 47.487992,5.9136 a 202.62398,202.62398 0 0 0 63.6416,-8.9856 111.07839,111.07839 0 0 0 37.81119,-18.66239 51.814394,51.814394 0 0 0 20.24959,-41.4976 58.060793,58.060793 0 0 0 -16.35839,-40.80639 72.012792,72.012792 0 0 0 -20.1728,-13.7984 148.60798,148.60798 0 0 0 -24.88319,-8.6784 c -16.2304,-3.968 -52.6848,-8.9344 -70.1184,-10.6752 -18.27839,-1.8944 -49.99679,-4.5312 -62.668789,-8.448 -3.839999,-1.2032 -11.673599,-4.9152 -11.673599,-14.0032 0,-6.4768 3.584,-11.9552 10.649599,-16.384 C 75.26415,560.7709 97.945747,556.3933 121.60014,556.3933 a 166.98878,166.98878 0 0 1 66.7136,13.03039 72.857591,72.857591 0 0 1 15.87199,9.472 47.718394,47.718394 0 0 1 15.6416,26.1632 h 25.2672 V 536.4253 h -28.16 v 7.9616 c 0,2.56 -2.56,5.9392 -7.68,3.1488 -12.69759,-6.6048 -48.38399,-20.8896 -92.13439,-21.0688 z m 618.21433,12.5952 137.62558,124.18558 -1.408,-83.60959 c -0.1536,-10.9824 -2.1504,-15.56479 -14.0288,-15.56479 h -25.85599 v -25.0112 h 117.75998 v 25.0112 h -25.26719 c -12.0832,0 -12.8,3.89119 -13.0048,15.56479 l 2.1248,159.76959 h -40.32 L 714.41927,597.94209 v 100.37759 c 0.128,10.9312 0.64,16.0768 11.8784,16.0768 h 28.16 v 25.0112 H 639.02728 v -25.0112 h 27.0336 c 10.08639,0 9.67679,-9.6256 9.67679,-16.64 V 580.58529 c 0,-7.68 -1.0752,-16.48639 -16.89599,-16.48639 h -21.9136 V 539.0621 Z M 1083.776,714.34528 a 55.859193,55.859193 0 0 0 6.9632,-0.4352 8.627199,8.627199 0 0 0 5.4272,-4.8128 28.006397,28.006397 0 0 0 0.5376,-5.4016 v -39.552 c 0,-1.3312 0,-1.3568 -1.6896,-3.456 -1.6896,-2.0992 -72.0896,-81.91999 -75.2896,-85.50399 -3.9936,-4.352 -11.008,-11.08479 -21.6832,-11.08479 h -24.44796 v -25.0368 h 137.98396 v 24.9856 h -16.64 c -3.84,0 -6.4,3.66079 -3.1232,7.67999 0,0 46.4384,55.552 46.8736,56.1408 0.4352,0.5888 0.8192,0.7168 1.408,0.1792 0.5888,-0.5376 47.5904,-55.808 47.9488,-56.32 a 4.7871994,4.7871994 0 0 0 -4.096,-7.67999 h -17.0752 V 539.0621 H 1280 v 25.0368 h -25.2672 c -9.1648,0 -12.8,1.68959 -19.7888,9.47199 l -76.16,86.88639 a 5.3759994,5.3759994 0 0 0 -0.9216,3.6864 v 39.5264 a 28.159997,28.159997 0 0 0 0.5632,5.4016 8.524799,8.524799 0 0 0 5.4016,4.8128 50.611194,50.611194 0 0 0 6.912,0.4352 h 25.8304 v 25.0368 h -137.2672 v -25.0368 z"
|
||||
id="path1"
|
||||
fill="#000000"
|
||||
style="stroke-width:2.56" />
|
||||
</svg:g>
|
||||
</svg:g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,281 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 96 96"
|
||||
width="96"
|
||||
height="96"
|
||||
version="1.1"
|
||||
id="svg25"
|
||||
sodipodi:docname="icons8-acess-point-3.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="defs25" />
|
||||
<sodipodi:namedview
|
||||
id="namedview25"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="true"
|
||||
inkscape:zoom="2.0255663"
|
||||
inkscape:cx="-53.071578"
|
||||
inkscape:cy="-106.14316"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg25">
|
||||
<sodipodi:guide
|
||||
position="-127.86548,48.359002"
|
||||
orientation="0,-1"
|
||||
id="guide25"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="47.76442,140.92571"
|
||||
orientation="1,0"
|
||||
id="guide26"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="44.611364,71.852727"
|
||||
orientation="1,0"
|
||||
id="guide27"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<linearGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXa"
|
||||
x1="34.117001"
|
||||
x2="33.909"
|
||||
y1="30.451"
|
||||
y2="11.826"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#737b80"
|
||||
id="stop1" />
|
||||
<stop
|
||||
offset=".714"
|
||||
stop-color="#737b80"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset=".756"
|
||||
stop-color="#737b80"
|
||||
id="stop3" />
|
||||
<stop
|
||||
offset=".863"
|
||||
stop-color="#656c71"
|
||||
id="stop4" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#575c61"
|
||||
id="stop5" />
|
||||
</linearGradient>
|
||||
<path
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXa)"
|
||||
d="m 63.464964,82.168622 c -0.210059,0 -0.42454,-0.03096 -0.636811,-0.09287 -1.169694,-0.351572 -1.83525,-1.58318 -1.483677,-2.752875 L 74.611348,35.09997 c 0.351573,-1.169696 1.585392,-1.835252 2.752877,-1.483679 1.169696,0.351571 1.83525,1.583179 1.483677,2.752876 L 65.581031,80.592076 c -0.285238,0.959638 -1.163063,1.576547 -2.116067,1.576546 z"
|
||||
id="path5"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXa);stroke-width:2.21115" />
|
||||
<linearGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXb"
|
||||
x1="14.121"
|
||||
x2="13.913"
|
||||
y1="30.719"
|
||||
y2="12.094"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#737b80"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset=".773"
|
||||
stop-color="#737b80"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#575c61"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
<path
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXb)"
|
||||
d="m 32.508927,82.168622 c -0.950793,0 -1.828617,-0.619122 -2.118278,-1.576548 L 17.123777,36.369165 c -0.351573,-1.169696 0.313983,-2.401304 1.483679,-2.752876 1.167483,-0.344938 2.401305,0.313984 2.752875,1.483679 l 13.266874,44.22291 c 0.351572,1.169696 -0.313982,2.401304 -1.483679,2.752875 -0.21227,0.06191 -0.42454,0.09287 -0.634599,0.09287 z"
|
||||
id="path8"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXb);stroke-width:2.21115" />
|
||||
<linearGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXc"
|
||||
x1="24"
|
||||
x2="24"
|
||||
y1="14.614"
|
||||
y2="-2.0710001"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#899198"
|
||||
id="stop9" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#787e85"
|
||||
id="stop10" />
|
||||
</linearGradient>
|
||||
<path
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXc)"
|
||||
d="M 85.576419,88.802058 H 10.397473 c -2.4433136,0 -4.4222888,-1.978974 -4.4222888,-4.42229 V 68.901749 c 0,-2.443315 1.9789752,-4.422291 4.4222888,-4.422291 h 75.178946 c 2.443316,0 4.422291,1.978976 4.422291,4.422291 v 15.478019 c 0,2.443316 -1.978975,4.42229 -4.422291,4.42229 z"
|
||||
id="path10"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXc);stroke-width:2.21115" />
|
||||
<rect
|
||||
width="75.178947"
|
||||
height="15.478019"
|
||||
x="10.397472"
|
||||
y="68.901749"
|
||||
fill="#737b80"
|
||||
id="rect10"
|
||||
style="stroke-width:2.21115" />
|
||||
<radialGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXd"
|
||||
cx="36.5"
|
||||
cy="11.39"
|
||||
r="2.5"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset=".582"
|
||||
stop-opacity=".2"
|
||||
id="stop11" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop12" />
|
||||
</radialGradient>
|
||||
<circle
|
||||
cx="75.626282"
|
||||
cy="76.640755"
|
||||
r="5.5278635"
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXd)"
|
||||
id="circle12"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXd);stroke-width:2.21115" />
|
||||
<radialGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXe"
|
||||
cx="30.5"
|
||||
cy="11.39"
|
||||
r="2.5"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset=".582"
|
||||
stop-opacity=".2"
|
||||
id="stop13" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop14" />
|
||||
</radialGradient>
|
||||
<circle
|
||||
cx="62.359394"
|
||||
cy="76.640755"
|
||||
r="5.5278635"
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXe)"
|
||||
id="circle14"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXe);stroke-width:2.21115" />
|
||||
<radialGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXf"
|
||||
cx="24.5"
|
||||
cy="11.39"
|
||||
r="2.5"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset=".582"
|
||||
stop-opacity=".2"
|
||||
id="stop15" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop16" />
|
||||
</radialGradient>
|
||||
<circle
|
||||
cx="49.092525"
|
||||
cy="76.640755"
|
||||
r="5.5278635"
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXf)"
|
||||
id="circle16"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXf);stroke-width:2.21115" />
|
||||
<radialGradient
|
||||
id="sQy7OvPXH0t2mKfqk7XuXg"
|
||||
cx="11.5"
|
||||
cy="11.39"
|
||||
r="2.5"
|
||||
gradientTransform="matrix(2.2111455,0,0,-2.2111455,-5.0805451,101.8257)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset=".582"
|
||||
stop-opacity=".2"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop18" />
|
||||
</radialGradient>
|
||||
<circle
|
||||
cx="20.347635"
|
||||
cy="76.640755"
|
||||
r="5.5278635"
|
||||
fill="url(#sQy7OvPXH0t2mKfqk7XuXg)"
|
||||
id="circle18"
|
||||
style="fill:url(#sQy7OvPXH0t2mKfqk7XuXg);stroke-width:2.21115" />
|
||||
<circle
|
||||
cx="75.626282"
|
||||
cy="76.640755"
|
||||
r="3.3167181"
|
||||
fill="#50e6ff"
|
||||
id="circle19"
|
||||
style="stroke-width:2.21115" />
|
||||
<circle
|
||||
cx="62.359394"
|
||||
cy="76.640755"
|
||||
r="3.3167181"
|
||||
fill="#50e6ff"
|
||||
id="circle20"
|
||||
style="stroke-width:2.21115" />
|
||||
<circle
|
||||
cx="49.092525"
|
||||
cy="76.640755"
|
||||
r="3.3167181"
|
||||
fill="#50e6ff"
|
||||
id="circle21"
|
||||
style="stroke-width:2.21115" />
|
||||
<circle
|
||||
cx="20.347635"
|
||||
cy="76.640755"
|
||||
r="3.3167181"
|
||||
fill="#50e6ff"
|
||||
id="circle22"
|
||||
style="stroke-width:2.21115" />
|
||||
<path
|
||||
fill="#0078d4"
|
||||
d="M 76.06186,21.738016 71.411821,26.423432 47.942723,17.974646 24.495735,26.403533 19.894342,21.766761 C 19.049684,20.913259 19.012095,19.504758 19.863382,18.65789 27.279564,11.290354 37.453044,6.9542994 47.942718,6.9476659 c 10.421129,-0.011054 20.76929,4.3272091 28.154515,11.6881131 0.849081,0.844657 0.809281,2.250946 -0.03538,3.102237 z"
|
||||
id="path22"
|
||||
style="stroke-width:2.21115" />
|
||||
<path
|
||||
fill="#199be2"
|
||||
d="m 71.414032,26.425643 -0.455497,0.442231 -5.757821,5.757823 -17.253569,-5.819736 -17.233669,5.797623 -5.757823,-5.73571 -0.455494,-0.464341 c 5.779935,-6.507401 14.146909,-10.6334 23.446986,-10.6334 9.319978,0 17.684742,4.123788 23.466887,10.65551 z"
|
||||
id="path23"
|
||||
style="stroke-width:2.21115" />
|
||||
<path
|
||||
fill="#35c1f1"
|
||||
d="m 65.198502,32.623485 -0.999438,0.992804 -5.216091,5.207248 -11.04025,-3.192894 -11.018139,3.192894 -5.216092,-5.207248 -0.999437,-1.014916 c 4.194543,-4.897687 10.36585,-8.008769 17.233668,-8.008769 6.889929,0.0023 13.061235,3.111082 17.255779,8.030881 z"
|
||||
id="path24"
|
||||
style="stroke-width:2.21115" />
|
||||
<path
|
||||
fill="#50e6ff"
|
||||
d="m 58.982973,38.823537 -1.629615,1.631826 -7.862833,7.907056 c -0.844658,0.85129 -2.208935,0.85129 -3.055803,0.0045 l -7.902635,-7.911521 -1.607503,-1.631824 c 2.587041,-3.287976 6.56268,-5.40404 11.018139,-5.40404 4.477569,-0.0023 8.453208,2.116064 11.04025,5.40404 z"
|
||||
id="path25"
|
||||
style="stroke-width:2.21115" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="48px" height="48px" fill-rule="nonzero"><g fill="#0088cc" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.33333,5.33333)"><path d="M28.465,38.611c0.419,-1.105 0.664,-2.365 0.664,-3.714c0,-4.133 -2.211,-7.494 -4.929,-7.494c-2.741,0 -4.951,3.361 -4.951,7.494c0,1.326 0.221,2.586 0.641,3.669c-9.041,0.951 -15.407,4.731 -17.993,6.432c4.355,-6.278 8.909,-13.638 13.262,-22.105c1.083,-2.101 2.101,-4.178 3.05,-6.211c0.375,0.243 0.751,0.509 1.171,0.775c1.945,1.215 3.759,1.879 5.084,2.233c-0.973,-0.73 -2.033,-1.613 -3.116,-2.697c-0.817,-0.817 -1.547,-1.637 -2.167,-2.433c1.835,-4.022 3.427,-7.891 4.819,-11.56c2.32,6.144 5.217,12.842 8.841,19.893c2.343,4.531 4.731,8.754 7.117,12.644c-0.685,-0.375 -1.437,-0.73 -2.233,-1.039c-1.371,-0.53 -2.652,-0.862 -3.759,-1.06c1.503,0.751 3.25,1.747 5.084,3.073c1.194,0.885 2.254,1.769 3.161,2.631c0.021,0.021 0.021,0.021 0.045,0.045c1.26,2.056 2.565,3.957 3.846,5.813c-2.541,-1.681 -8.796,-5.395 -17.637,-6.389z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
123
datamodels/2.x/itop-config-mgmt/assets/img/icons8-asus.svg
Normal file
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0,0,256,256"
|
||||
width="64px"
|
||||
height="64px"
|
||||
fill-rule="nonzero"
|
||||
version="1.1"
|
||||
id="svg13"
|
||||
sodipodi:docname="icons8-asus (1).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">
|
||||
<sodipodi:namedview
|
||||
id="namedview13"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="17.1875"
|
||||
inkscape:cx="31.970909"
|
||||
inkscape:cy="32"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1360"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g13" />
|
||||
<defs
|
||||
id="defs10">
|
||||
<radialGradient
|
||||
cx="34.625"
|
||||
cy="31.875"
|
||||
r="23.206"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="color-1">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#f4e9c3"
|
||||
id="stop1" />
|
||||
<stop
|
||||
offset="0.219"
|
||||
stop-color="#f8eecd"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="0.644"
|
||||
stop-color="#fdf4dc"
|
||||
id="stop3" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#fff6e1"
|
||||
id="stop4" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
x1="0.365"
|
||||
y1="32.5"
|
||||
x2="64"
|
||||
y2="32.5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="color-2">
|
||||
<stop
|
||||
offset="0.053"
|
||||
stop-color="#000000"
|
||||
id="stop5" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#000000"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="34.625"
|
||||
cy="31.875"
|
||||
r="23.206"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="color-3">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#f4e9c3"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="0.219"
|
||||
stop-color="#f8eecd"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="0.644"
|
||||
stop-color="#fdf4dc"
|
||||
id="stop9" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#fff6e1"
|
||||
id="stop10" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="nonzero"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke-miterlimit="10"
|
||||
stroke-dasharray=""
|
||||
stroke-dashoffset="0"
|
||||
font-family="none"
|
||||
font-weight="none"
|
||||
font-size="none"
|
||||
text-anchor="none"
|
||||
style="mix-blend-mode: normal"
|
||||
id="g13">
|
||||
<g
|
||||
transform="scale(4,4)"
|
||||
id="g12">
|
||||
<path
|
||||
d="M6.156,29.243l-5.723,9.919c-0.192,0.333 0.048,0.75 0.433,0.75h2.764c0.356,0 0.686,-0.19 0.865,-0.498l5.629,-9.701zM6.299,29.005c0,0 0.815,-1.486 1.625,-2.92c0.354,-0.628 1.019,-1.014 1.74,-1.014c1.408,0.001 3.757,0.003 5.086,0.004c0.552,0 0.995,0.448 0.995,1.001v2.61c0,0 0.323,-1.386 0.891,-2.043c0.534,-0.619 1.246,-1.478 2.872,-1.592h10.963c0.552,0 1,0.448 1,1v1.955c0,0.552 -0.448,1 -1,1zM64,28.008v-1.958c0,-0.552 -0.448,-1 -1,-1h-11.8c-1.622,0.114 -2.337,0.972 -2.872,1.592c-0.569,0.657 -0.89,2.043 -0.89,2.043v0.318l15.562,0.005c0.552,0 1,-0.448 1,-1zM33.095,25.07h1.578c0.552,0 1,0.448 1,1v2.935h-3.578v-2.935c0,-0.552 0.448,-1 1,-1zM44.839,25.07h1.574c0.552,0 1,0.448 1,1v2.935h-3.574v-2.935c0,-0.552 0.447,-1 1,-1zM47.413,30.425l-3.514,-0.233v4.566c0,0 -0.01,1.314 -1.158,1.314c-1.138,0 -6.039,0 -6.039,0c0,0 -1.023,-0.093 -1.023,-1.303c0,-1.207 0,-5.196 0,-5.196l-3.549,-0.285v7.001c0.574,3.359 3.311,3.617 3.311,3.617c0,0 0.278,0.022 0.324,0.026h8.156c0,0 3.491,-0.311 3.491,-4.023c0.001,-3.713 0.001,-5.484 0.001,-5.484zM13.111,39.914h15.73c2.914,-0.647 3.218,-3.577 3.218,-3.577c0.136,-0.871 0.057,-1.574 0.057,-1.574c-0.088,-0.588 -1.094,-3.178 -3.281,-3.405c-1.304,-0.134 -12.91,-1.155 -12.91,-1.155c0.225,1.288 0.748,1.938 1.094,2.311c0.805,0.857 2.087,1.099 2.087,1.099c0.309,0.033 8.945,0.824 8.945,0.824c0.274,0.017 0.797,0.093 0.79,0.849c0,0.091 -0.075,0.757 -0.738,0.757h-12.014c-0.276,0 -0.5,-0.224 -0.5,-0.5v-5.373l-3.478,-0.281v9.027c0,0.55 0.448,0.998 1,0.998zM47.444,37.017c0.001,-0.552 0.448,-0.998 1,-0.998h11.429c0.286,0 0.595,-0.187 0.595,-0.187c0.13,-0.129 0.235,-0.364 0.235,-0.591c0,-0.753 -0.561,-0.786 -0.843,-0.803c0,0 -8.732,-0.808 -9.036,-0.834c0,0 -1.211,-0.207 -2.017,-1.068c-0.351,-0.369 -0.815,-0.771 -1.161,-2.099c0,0 11.671,0.763 12.968,0.897c2.189,0.232 3.215,2.632 3.308,3.43c0,0 0.093,0.722 -0.02,1.607c0,0 -0.454,3.374 -3.664,3.579h-11.797c-0.553,0 -1.001,-0.449 -1,-1.002z"
|
||||
fill="url(#color-2)"
|
||||
id="path11" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |