mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-05 00:18:46 +02:00
Compare commits
38 Commits
faf/cron_m
...
support/3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cac280b83 | ||
|
|
8f2c990065 | ||
|
|
03437c3453 | ||
|
|
33a51b47bf | ||
|
|
e768cc1c0c | ||
|
|
f6741a6306 | ||
|
|
1ec8aca12d | ||
|
|
39011faedd | ||
|
|
46f8f5faeb | ||
|
|
170d24d0ad | ||
|
|
89231976f8 | ||
|
|
f0a95cbb3d | ||
|
|
30f720b9ad | ||
|
|
87dd003a6d | ||
|
|
7201bef8db | ||
|
|
af01ff9e62 | ||
|
|
ab1290dfd0 | ||
|
|
68d14c4de6 | ||
|
|
a96e1c286d | ||
|
|
b799be3cb7 | ||
|
|
d000d93b19 | ||
|
|
9f25635a64 | ||
|
|
6bd34dc73e | ||
|
|
9dc3c56689 | ||
|
|
effd35c3e6 | ||
|
|
f1735767c3 | ||
|
|
00735f0c54 | ||
|
|
882390e8d6 | ||
|
|
5d0da47f21 | ||
|
|
4eadff7f3b | ||
|
|
f66ce1c956 | ||
|
|
802f9f3e08 | ||
|
|
5c5d98bb78 | ||
|
|
a08a9b43f3 | ||
|
|
abd85ff4db | ||
|
|
81f328b26e | ||
|
|
9a2c8f10bf | ||
|
|
3cdadf3c6e |
111
.doc/itop-version-history.md
Normal file
111
.doc/itop-version-history.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# iTop version history
|
||||
|
||||
```mermaid
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'themeVariables': {
|
||||
'git0': 'lawngreen',
|
||||
'git3': 'dodgerblue',
|
||||
'git4': 'grey',
|
||||
'git5': 'grey',
|
||||
'git6': 'grey',
|
||||
'git7': 'grey',
|
||||
'git8': 'grey'
|
||||
}, 'gitGraph': {'showBranches': true,'mainBranchName': 'develop','rotateCommitLabel': true}} }%%
|
||||
gitGraph
|
||||
commit id: "2016-07-06" tag: "2.3.0" type: HIGHLIGHT
|
||||
branch support/2.3 order: 900
|
||||
commit id: "2016-07-08" tag: "2.3.1"
|
||||
commit id: "2016-12-22" tag: "2.3.3"
|
||||
commit id: "2017-04-14" tag: "2.3.4"
|
||||
checkout develop
|
||||
commit id: "2017-07-12" tag: "2.4.0-beta" type: REVERSE
|
||||
commit id: "2017-11-16" tag: "2.4.0" type: HIGHLIGHT
|
||||
branch support/2.4 order: 890
|
||||
commit id: "2018-02-14" tag: "2.4.1"
|
||||
checkout develop
|
||||
commit id: "2018-04-25" tag: "2.5.0-beta" type: REVERSE
|
||||
checkout support/2.4
|
||||
commit id: "2018-06-14" tag: "2.4.2"
|
||||
checkout develop
|
||||
commit id: "2018-06-27" tag: "2.5.0" type: HIGHLIGHT
|
||||
branch support/2.5 order: 880
|
||||
checkout develop
|
||||
commit id: "2019-01-09" tag: "2.6.0" type: HIGHLIGHT
|
||||
branch support/2.6 order: 870
|
||||
commit id: "2019-03-28" tag: "2.6.1"
|
||||
checkout develop
|
||||
commit id: "2019-12-18" tag: "2.7.0-beta" type: REVERSE
|
||||
checkout support/2.5
|
||||
commit id: "2020-01-22" tag: "2.5.4"
|
||||
checkout support/2.6
|
||||
commit id: "2020-01-23" tag: "2.6.3"
|
||||
checkout develop
|
||||
commit id: "2020-01-29" tag: "2.7.0-beta2" type: REVERSE
|
||||
commit id: "2020-04-01" tag: "2.7.0-1" type: HIGHLIGHT
|
||||
checkout support/2.6
|
||||
commit id: "2020-04-22" tag: "2.6.4"
|
||||
checkout develop
|
||||
branch support/2.7 order: 860
|
||||
commit id: "2020-06-26" tag: "2.7.1"
|
||||
checkout support/2.7
|
||||
commit id: "2020-12-09" tag: "2.7.3"
|
||||
commit id: "2021-03-31" tag: "2.7.4"
|
||||
checkout develop
|
||||
commit id: "2021-04-06" tag: "3.0.0-beta" type: REVERSE
|
||||
checkout support/2.7
|
||||
commit id: "2021-07-05" tag: "2.7.5"
|
||||
checkout develop
|
||||
commit id: "2021-07-05." tag: "3.0.0-beta2" type: REVERSE
|
||||
checkout support/2.7
|
||||
commit id: "2021-12-17" tag: "2.7.6"
|
||||
checkout develop
|
||||
commit id: "2022-01-04" tag: "3.0.0" type: HIGHLIGHT
|
||||
branch support/3.0 order: 850
|
||||
commit id: "2022-04-08" tag: "3.0.1"
|
||||
checkout support/2.7
|
||||
commit id: "2022-07-11" tag: "2.7.7"
|
||||
checkout support/3.0
|
||||
commit id: "2022-09-12" tag: "3.0.2-1"
|
||||
checkout develop
|
||||
checkout support/2.7
|
||||
commit id: "2022-12-28" tag: "2.7.8"
|
||||
checkout support/3.0
|
||||
commit id: "2023-04-12" tag: "3.0.3"
|
||||
checkout develop
|
||||
commit id: "2023-06-19" tag: "3.1.0-beta" type: REVERSE
|
||||
commit id: "2023-07-26" tag: "3.1.0-1" type: HIGHLIGHT
|
||||
branch support/3.1 order: 840
|
||||
checkout support/3.1
|
||||
commit id: "2023-08-09" tag: "3.1.0-2"
|
||||
checkout support/2.7
|
||||
commit id: "2023-08-10" tag: "2.7.9"
|
||||
checkout support/3.1
|
||||
commit id: "2023-12-20" tag: "3.1.1"
|
||||
checkout develop
|
||||
commit id: "2024-01-15" tag: "Start 3.2" type: HIGHLIGHT
|
||||
branch support/3.2 order: 830
|
||||
checkout support/2.7
|
||||
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"
|
||||
checkout support/2.7
|
||||
commit id: "2025-02-07a" tag: "2.7.12"
|
||||
checkout support/3.1
|
||||
commit id: "2025-02-07b" tag: "3.1.3"
|
||||
checkout support/3.2
|
||||
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-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).
|
||||
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: "Bug report"
|
||||
description: "Report a bug that you identified in iTop, with the steps to reproduce it and the expected vs actual behavior. If you have an improvement proposition, please use the 'Enhancement suggestion' template instead."
|
||||
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, .tar.gz"
|
||||
54
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: "Enhancement suggestion"
|
||||
description: "Suggest an improvement to iTop, with a clear description of the expected behavior and the benefits it would bring. If you identified a bug and have an improvement proposition, please use the 'Bug report' template instead."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please explain why you're creating this issue :
|
||||
- Are you willing to create a PR for this enhancement ? If so, we'll indicate in the issue if we're interested in it.
|
||||
- Then, please describe what's your improvement proposition.
|
||||
|
||||
- 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: 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: 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, .tar.gz"
|
||||
61
.github/pull_request_template.md
vendored
61
.github/pull_request_template.md
vendored
@@ -1,83 +1,76 @@
|
||||
<!--
|
||||
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 thead / 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 |
|
||||
|
||||
## 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 :)
|
||||
|
||||
@@ -157,8 +144,4 @@ We have one sticker per contribution type. You might get multiple stickers with
|
||||
* Graduated: Follow a Combodo's iTop training
|
||||
* Ambassador: Outstanding community contributors
|
||||
* 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:
|
||||
|
||||

|
||||
* Extension developer: Develop and publish an extension
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1546,12 +1546,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>
|
||||
|
||||
@@ -3252,4 +3252,50 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.2');
|
||||
* @used-by utils::GetItopVersionWikiSyntax()
|
||||
* @used-by iTopModulesPhpVersionIntegrationTest
|
||||
*/
|
||||
define('ITOP_CORE_VERSION', '3.2.1');
|
||||
define('ITOP_CORE_VERSION', '3.2.3');
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
||||
@@ -4829,7 +4829,7 @@ class AttributeCaseLog extends AttributeLongText
|
||||
}
|
||||
|
||||
if (strlen($sIndex) > 0) {
|
||||
$aIndex = unserialize($sIndex);
|
||||
$aIndex = utils::Unserialize($sIndex, ['allowed_classes' => false], false);
|
||||
$value = new ormCaseLog($sLog, $aIndex);
|
||||
} else {
|
||||
$value = new ormCaseLog($sLog);
|
||||
|
||||
@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get iTop core version
|
||||
*/
|
||||
define('ITOP_VERSION', '3.2.0-dev');
|
||||
define('ITOP_VERSION', '3.2.3-dev');
|
||||
|
||||
define('ITOP_VERSION_NAME', 'Fullmoon');
|
||||
define('ITOP_REVISION', 'svn');
|
||||
@@ -75,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)
|
||||
@@ -869,6 +870,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',
|
||||
@@ -1603,7 +1612,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,
|
||||
@@ -1746,11 +1755,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,
|
||||
],
|
||||
@@ -1966,11 +1975,6 @@ class Config
|
||||
*/
|
||||
protected $m_sAllowedLoginTypes;
|
||||
|
||||
/**
|
||||
* @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 +2047,6 @@ class Config
|
||||
$this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED;
|
||||
$this->m_sDefaultLanguage = 'EN US';
|
||||
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_aCharsets = [];
|
||||
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
|
||||
$this->m_iPasswordHashAlgo = DEFAULT_HASH_ALGO;
|
||||
@@ -2197,7 +2200,6 @@ class Config
|
||||
|
||||
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
||||
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_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'] : [];
|
||||
@@ -2350,9 +2352,73 @@ class Config
|
||||
return explode('|', $this->m_sAllowedLoginTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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()
|
||||
@@ -2448,7 +2514,7 @@ class Config
|
||||
|
||||
public function SetExternalAuthenticationVariable($sExtAuthVariable)
|
||||
{
|
||||
$this->m_sExtAuthVariable = $sExtAuthVariable;
|
||||
$this->Set('ext_auth_variable', $sExtAuthVariable);
|
||||
}
|
||||
|
||||
public function SetEncryptionKey($sKey)
|
||||
@@ -2503,7 +2569,6 @@ class Config
|
||||
$aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired;
|
||||
$aSettings['default_language'] = $this->m_sDefaultLanguage;
|
||||
$aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes;
|
||||
$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;
|
||||
@@ -2608,7 +2673,6 @@ class Config
|
||||
$aOtherValues = [
|
||||
'default_language' => $this->m_sDefaultLanguage,
|
||||
'allowed_login_types' => $this->m_sAllowedLoginTypes,
|
||||
'ext_auth_variable' => $this->m_sExtAuthVariable,
|
||||
'encryption_key' => $this->m_sEncryptionKey,
|
||||
'encryption_library' => $this->m_sEncryptionLibrary,
|
||||
'csv_import_charsets' => $this->m_aCharsets,
|
||||
|
||||
@@ -176,7 +176,7 @@ class EventNotificationEmail extends EventNotification
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', ['date', 'userinfo', 'message', 'trigger_id', 'action_id', '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
|
||||
|
||||
@@ -1157,7 +1157,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;
|
||||
}
|
||||
@@ -1350,7 +1350,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 '';
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
//
|
||||
// .site-nav a { color:#BADA55!important; }
|
||||
|
||||
$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;
|
||||
@@ -109,3 +111,11 @@ input:checked + .slider:before {
|
||||
.slider.round:before {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -201,8 +201,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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-cas/3.2.1',
|
||||
'authent-cas/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-external/3.2.1',
|
||||
'authent-external/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -7,7 +7,7 @@ if (function_exists('ldap_connect')) {
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-ldap/3.2.1',
|
||||
'authent-ldap/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-local/3.2.1',
|
||||
'authent-local/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-darkmoon-theme/3.2.1',
|
||||
'combodo-backoffice-darkmoon-theme/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -53,6 +53,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;
|
||||
@@ -175,6 +176,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;
|
||||
@@ -222,6 +224,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;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.2.1',
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.2.1',
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.2.1',
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-db-tools/3.2.1',
|
||||
'combodo-db-tools/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-attachments/3.2.1',
|
||||
'itop-attachments/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/3.2.1',
|
||||
'itop-backup/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-cmdb-services/3.2.1',
|
||||
'itop-bridge-cmdb-services/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-cmdb-ticket/3.2.1',
|
||||
'itop-bridge-cmdb-ticket/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-datacenter-mgmt-services/3.2.1',
|
||||
'itop-bridge-datacenter-mgmt-services/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-endusers-devices-services/3.2.1',
|
||||
'itop-bridge-endusers-devices-services/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-storage-mgmt-services/3.2.1',
|
||||
'itop-bridge-storage-mgmt-services/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-virtualization-mgmt-services/3.2.1',
|
||||
'itop-bridge-virtualization-mgmt-services/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-virtualization-storage/3.2.1',
|
||||
'itop-bridge-virtualization-storage/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt-itil/3.2.1',
|
||||
'itop-change-mgmt-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt/3.2.1',
|
||||
'itop-change-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config-mgmt/3.2.1',
|
||||
'itop-config-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config/3.2.1',
|
||||
'itop-config/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-core-update/3.2.1',
|
||||
'itop-core-update/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-datacenter-mgmt/3.2.1',
|
||||
'itop-datacenter-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-endusers-devices/3.2.1',
|
||||
'itop-endusers-devices/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-faq-light/3.2.1',
|
||||
'itop-faq-light/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-files-information/3.2.1',
|
||||
'itop-files-information/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-full-itil/3.2.1',
|
||||
'itop-full-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-hub-connector/3.2.1',
|
||||
'itop-hub-connector/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-incident-mgmt-itil/3.2.1',
|
||||
'itop-incident-mgmt-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-knownerror-mgmt/3.2.1',
|
||||
'itop-knownerror-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-oauth-client/3.2.1',
|
||||
'itop-oauth-client/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-portal-base/3.2.1',
|
||||
'itop-portal-base/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
'label' => 'Portal Development Library',
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-portal/3.2.1',
|
||||
'itop-portal/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
'label' => 'Enhanced Customer Portal',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-problem-mgmt/3.2.1',
|
||||
'itop-problem-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-profiles-itil/3.2.1',
|
||||
'itop-profiles-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-request-mgmt-itil/3.2.1',
|
||||
'itop-request-mgmt-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-request-mgmt/3.2.1',
|
||||
'itop-request-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-service-mgmt-provider/3.2.1',
|
||||
'itop-service-mgmt-provider/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-service-mgmt/3.2.1',
|
||||
'itop-service-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-sla-computation/3.2.1',
|
||||
'itop-sla-computation/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-storage-mgmt/3.2.1',
|
||||
'itop-storage-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-structure/3.2.1',
|
||||
'itop-structure/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-themes-compat/3.2.1',
|
||||
'itop-themes-compat/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__,
|
||||
'itop-tickets/3.2.1',
|
||||
'itop-tickets/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-virtualization-mgmt/3.2.1',
|
||||
'itop-virtualization-mgmt/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-welcome-itil/3.2.1',
|
||||
'itop-welcome-itil/3.2.3',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<information>
|
||||
<version>3.2.1</version>
|
||||
<version>3.2.3</version>
|
||||
</information>
|
||||
|
||||
@@ -36,7 +36,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'UI:ResetPwd-Ready' => 'Le mot de passe a bien été changé.',
|
||||
'UI:ResetPwd-Login' => 'Cliquez ici pour vous connecter...',
|
||||
|
||||
'UI:Login:About' => ITOP_APPLICATION.' Powered by Combodo~~',
|
||||
'UI:Login:About' => ITOP_APPLICATION.' Powered by Combodo',
|
||||
'UI:Login:ChangeYourPassword' => 'Changer de mot de passe',
|
||||
'UI:Login:OldPasswordPrompt' => 'Ancien mot de passe',
|
||||
'UI:Login:NewPasswordPrompt' => 'Nouveau mot de passe',
|
||||
|
||||
@@ -120,6 +120,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
|
||||
this.sFormAttCode = sFormAttCode;
|
||||
|
||||
var me = this;
|
||||
const iDropdownContentHeightDifference = 4;
|
||||
|
||||
this.Init = function () {
|
||||
// make sure that the form is clean
|
||||
@@ -171,7 +172,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
|
||||
// To avoid dropdown to be cut by the container's overflow hidden rule
|
||||
dropdownParent: 'body',
|
||||
onDropdownOpen: function (oDropdownElem) {
|
||||
me.UpdateDropdownPosition(this.$control, oDropdownElem);
|
||||
me.UpdateDropdownPosition(this.$control, oDropdownElem, this.$dropdown_content);
|
||||
},
|
||||
});
|
||||
let $selectize = $select[0].selectize; // This stores the selectize object to a variable (with name 'selectize')
|
||||
@@ -314,13 +315,14 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the dropdown's position so it always fits in the screen
|
||||
*
|
||||
* @param {object} oControlElem jQuery object representing the "control" input (= where the user types) of the external key
|
||||
* @param {object} oDropdownElem jQuery object representing the results dropdown
|
||||
* @return {void}
|
||||
*/
|
||||
this.UpdateDropdownPosition = function (oControlElem, oDropdownElem) {
|
||||
* Update the dropdown's position so it always fits in the screen
|
||||
*
|
||||
* @param {object} oControlElem jQuery object representing the "control" input (= where the user types) of the external key
|
||||
* @param {object} oDropdownElem jQuery object representing the results dropdown
|
||||
* @param {object|undefined} oDropdownContentElem
|
||||
* @return {void}
|
||||
*/
|
||||
this.UpdateDropdownPosition = function (oControlElem, oDropdownElem, oDropdownContentElem) {
|
||||
// First fix width to ensure it's not too long
|
||||
const fControlWidth = oControlElem.outerWidth();
|
||||
oDropdownElem.css('width', fControlWidth);
|
||||
@@ -328,6 +330,13 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
|
||||
// Then, fix height / position to ensure it's within the viewport
|
||||
const fWindowHeight = window.innerHeight;
|
||||
|
||||
// Clear previously set rule so the comparison is done with dropdown real height
|
||||
oDropdownElem.css('max-height', '');
|
||||
|
||||
if(oDropdownContentElem) {
|
||||
oDropdownContentElem.css('max-height', '');
|
||||
}
|
||||
|
||||
const fControlTopY = oControlElem.offset().top;
|
||||
const fControlHeight = oControlElem.outerHeight();
|
||||
|
||||
@@ -338,14 +347,38 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
|
||||
|
||||
if (fDropdownBottomY > fWindowHeight) {
|
||||
// Set dropdown max-height to 1/3 of the screen, this way we are sure the dropdown will fit in either the top / bottom half of the screen
|
||||
oDropdownElem.css('max-height', '30vh');
|
||||
oDropdownElem.css({
|
||||
maxHeight: '30vh',
|
||||
});
|
||||
fDropdownHeight = oDropdownElem.outerHeight();
|
||||
|
||||
// Position dropdown above input if not enough space on the bottom part of the screen
|
||||
// N°9468 Dropdown content needs to be a few pixel shorter than the dropdown itself to avoid double scrollbar
|
||||
if(oDropdownContentElem) {
|
||||
oDropdownContentElem.css('max-height', `calc(30vh - ${iDropdownContentHeightDifference}px)`);
|
||||
}
|
||||
|
||||
/* Position dropdown above input if not enough space on the bottom part of the screen
|
||||
Doesn't seem to work with selectize as an internal plugin "auto_position" refreshes the top position after
|
||||
this method is called, input set use a custom plugin to avoid fix this issue "plugin_combodo_auto_position"
|
||||
This would need to take the potential 4px difference (iDropdownContentHeightDifference) into account if this is fixed.
|
||||
*/
|
||||
if ((fDropdownTopY / fWindowHeight) > 0.6) {
|
||||
oDropdownElem.css('top', fDropdownTopY - fDropdownHeight - fControlHeight);
|
||||
}
|
||||
oDropdownElem.css({
|
||||
top: fDropdownTopY - fDropdownHeight - fControlHeight,
|
||||
borderTop: oDropdownElem.css('border-bottom')
|
||||
});
|
||||
}
|
||||
else {
|
||||
oDropdownElem.css({
|
||||
borderTop: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
oDropdownElem.css({
|
||||
borderTop: 'none'
|
||||
})
|
||||
}
|
||||
};
|
||||
this.ManageScroll = function () {
|
||||
if ($('#label_'+me.id).scrollParent()[0].tagName != 'HTML') {
|
||||
|
||||
@@ -189,11 +189,14 @@ $(function()
|
||||
this.buildData.script_code = '';
|
||||
this.buildData.style_code = '';
|
||||
|
||||
for (var i in oData.updated_fields)
|
||||
for (let i in oData.updated_fields)
|
||||
{
|
||||
var oUpdatedField = oData.updated_fields[i];
|
||||
this.options.fields_list[oUpdatedField.id] = oUpdatedField;
|
||||
this._prepareField(oUpdatedField.id);
|
||||
const oUpdatedField = oData.updated_fields[i];
|
||||
const oPreviousField = this.options.fields_list[oUpdatedField.id];
|
||||
if (!oPreviousField || JSON.stringify(oPreviousField) !== JSON.stringify(oUpdatedField)) {
|
||||
this.options.fields_list[oUpdatedField.id] = oUpdatedField;
|
||||
this._prepareField(oUpdatedField.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Adding code to the dom
|
||||
|
||||
@@ -301,88 +301,112 @@ function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue, origi
|
||||
return true; // Do not stop propagation ??
|
||||
}
|
||||
|
||||
function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue)
|
||||
function EvaluateCKEditorValidation(oOptions)
|
||||
{
|
||||
let oField = $('#'+sFieldId);
|
||||
let oField = $('#'+oOptions.sFieldId);
|
||||
if (oField.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let oCKEditor = CombodoCKEditorHandler.GetInstanceSynchronous('#'+sFieldId);
|
||||
let oCKEditor = CombodoCKEditorHandler.GetInstanceSynchronous('#'+oOptions.sFieldId);
|
||||
let bValid = true;
|
||||
let sExplain = '';
|
||||
let sTextContent;
|
||||
let sTextOriginalContents;
|
||||
|
||||
var bValid;
|
||||
var sExplain = '';
|
||||
if (oField.prop('disabled')) {
|
||||
bValid = true; // disabled fields are not checked
|
||||
} else {
|
||||
// If the CKEditor is not yet loaded, we need to wait for it to be ready
|
||||
// but as we need this function to be synchronous, we need to call it again when the CKEditor is ready
|
||||
if (oCKEditor === undefined){
|
||||
CombodoCKEditorHandler.GetInstance('#'+sFieldId).then((oCKEditor) => {
|
||||
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
|
||||
CombodoCKEditorHandler.GetInstance('#'+oOptions.sFieldId).then((oCKEditor) => {
|
||||
oOptions.onRetry();
|
||||
});
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let sTextContent;
|
||||
let sFormattedContent = oCKEditor.getData();
|
||||
|
||||
// Get the contents without the tags
|
||||
// Check if we have a formatted content that is HTML, otherwise we just have plain text, and we can use it directly
|
||||
let sFormattedContent = oCKEditor.getData();
|
||||
sTextContent = $(sFormattedContent).length > 0 ? $(sFormattedContent).text() : sFormattedContent;
|
||||
|
||||
if (sTextContent === '') {
|
||||
if (sTextContent === '')
|
||||
{
|
||||
// No plain text, maybe there is just an image
|
||||
let oImg = $(sFormattedContent).find("img");
|
||||
if (oImg.length !== 0) {
|
||||
let oImg = $(sFormattedContent).find('img');
|
||||
if (oImg.length !== 0)
|
||||
{
|
||||
sTextContent = 'image';
|
||||
}
|
||||
}
|
||||
|
||||
// Get the original value without the tags
|
||||
let oFormattedOriginalContents = (originalValue !== undefined) ? $('<div></div>').html(originalValue) : undefined;
|
||||
let sTextOriginalContents = (oFormattedOriginalContents !== undefined) ? oFormattedOriginalContents.text() : undefined;
|
||||
let oFormattedOriginalContents = (oOptions.sOriginalValue !== undefined) ? $('<div></div>').html(oOptions.sOriginalValue) : undefined;
|
||||
sTextOriginalContents = (oFormattedOriginalContents !== undefined) ? oFormattedOriginalContents.text() : undefined;
|
||||
|
||||
if (bMandatory && (sTextContent === nullValue)) {
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
} else if ((sTextOriginalContents !== undefined) && (sTextContent === sTextOriginalContents)) {
|
||||
bValid = false;
|
||||
if (sTextOriginalContents === nullValue) {
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
} else {
|
||||
// Note: value change check is not working well yet as the HTML to Text conversion is not exactly the same when done from the PHP value or the CKEditor value.
|
||||
sExplain = Dict.S('UI:ValueMustBeChanged');
|
||||
}
|
||||
} else {
|
||||
bValid = true;
|
||||
if (oOptions.validate !== undefined) {
|
||||
let oValidation = oOptions.validate(sTextContent, sTextOriginalContents);
|
||||
bValid = oValidation.bValid;
|
||||
sExplain = oValidation.sExplain;
|
||||
}
|
||||
|
||||
// Put and event to check the field when the content changes, remove the event right after as we'll call this same function again, and we don't want to call the event more than once (especially not ^2 times on each call)
|
||||
|
||||
// Put an event to check the field when the content changes, remove the event right after as we'll call this same function again, and we don't want to call the event more than once (especially not ^2 times on each call)
|
||||
oCKEditor.model.document.once('change:data', (event) => {
|
||||
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
|
||||
oOptions.onChange();
|
||||
});
|
||||
}
|
||||
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, sExplain);
|
||||
|
||||
ReportFieldValidationStatus(oOptions.sFieldId, oOptions.sFormId, bValid, sExplain);
|
||||
return bValid;
|
||||
}
|
||||
|
||||
function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue)
|
||||
{
|
||||
return EvaluateCKEditorValidation({
|
||||
sFieldId: sFieldId,
|
||||
sFormId: sFormId,
|
||||
sOriginalValue: originalValue,
|
||||
onRetry: function() {
|
||||
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
|
||||
},
|
||||
onChange: function() {
|
||||
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
|
||||
},
|
||||
validate: function(sTextContent, sTextOriginalContents) {
|
||||
var bValid;
|
||||
var sExplain = '';
|
||||
if (bMandatory && (sTextContent === nullValue)) {
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
} else if ((sTextOriginalContents !== undefined) && (sTextContent === sTextOriginalContents)) {
|
||||
bValid = false;
|
||||
if (sTextOriginalContents === nullValue) {
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
} else {
|
||||
// Note: value change check is not working well yet as the HTML to Text conversion is not exactly the same when done from the PHP value or the CKEditor value.
|
||||
sExplain = Dict.S('UI:ValueMustBeChanged');
|
||||
}
|
||||
} else {
|
||||
bValid = true;
|
||||
}
|
||||
return {bValid: bValid, sExplain: sExplain};
|
||||
}
|
||||
});
|
||||
}
|
||||
function ResetPwd(id)
|
||||
{
|
||||
// Reset the values of the password fields
|
||||
$('#'+id).val('*****');
|
||||
$('#'+id+'_confirm').val('*****');
|
||||
// And reset the flag, to tell it that the password remains unchanged
|
||||
$('#'+id+'_changed').val(0);
|
||||
// Visual feedback, None when it's Ok
|
||||
$('#v_'+id).html('');
|
||||
// Reset the values of the password fields
|
||||
$('#'+id).val('*****');
|
||||
$('#'+id+'_confirm').val('*****');
|
||||
// And reset the flag, to tell it that the password remains unchanged
|
||||
$('#'+id+'_changed').val(0);
|
||||
// Visual feedback, None when it's Ok
|
||||
$('#v_'+id).html('');
|
||||
}
|
||||
|
||||
// Called whenever the content of a one way encrypted password changes
|
||||
function PasswordFieldChanged(id)
|
||||
{
|
||||
// Set the flag, to tell that the password changed
|
||||
$('#'+id+'_changed').val(1);
|
||||
// Set the flag, to tell that the password changed
|
||||
$('#'+id+'_changed').val(1);
|
||||
}
|
||||
|
||||
// Special validation function for one way encrypted password fields
|
||||
@@ -415,37 +439,48 @@ function ValidatePasswordField(id, sFormId)
|
||||
// to determine if the field is empty or not
|
||||
function ValidateCaseLogField(sFieldId, bMandatory, sFormId, nullValue, originalValue)
|
||||
{
|
||||
var bValid = true;
|
||||
var sExplain = '';
|
||||
var sTextContent;
|
||||
|
||||
if ($('#'+sFieldId).prop('disabled'))
|
||||
{
|
||||
bValid = true; // disabled fields are not checked
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the contents (with tags)
|
||||
// Note: For CaseLog we can't retrieve the formatted contents from CKEditor (unlike in ValidateCKEditorField() method) because of the place holder.
|
||||
sTextContent = $('#' + sFieldId).val();
|
||||
var count = $('#'+sFieldId+'_count').val();
|
||||
return EvaluateCKEditorValidation({
|
||||
sFieldId: sFieldId,
|
||||
sFormId: sFormId,
|
||||
sOriginalValue: originalValue,
|
||||
onRetry: function() {
|
||||
ValidateCaseLogField(sFieldId, bMandatory, sFormId, nullValue, originalValue);
|
||||
},
|
||||
onChange: function() {
|
||||
ValidateCaseLogField(sFieldId, bMandatory, sFormId, nullValue, originalValue);
|
||||
},
|
||||
validate: function(sTextContent, sTextOriginalContents) {
|
||||
var bValid;
|
||||
var sExplain = '';
|
||||
// CaseLog is special: history count matters when deciding if the field is empty
|
||||
var count = $('#'+sFieldId+'_count').val();
|
||||
|
||||
if (bMandatory && (count == 0) && (sTextContent == nullValue))
|
||||
{
|
||||
// No previous entry and no content typed
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
if (bMandatory && (count == 0) && (sTextContent === nullValue))
|
||||
{
|
||||
// No previous entry and no content typed
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
}
|
||||
else if ((sTextOriginalContents !== undefined) && (sTextContent === sTextOriginalContents))
|
||||
{
|
||||
bValid = false;
|
||||
if (sTextOriginalContents === nullValue)
|
||||
{
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: value change check is not working well yet as the HTML to Text conversion is not exactly the same when done from the PHP value or the CKEditor value.
|
||||
sExplain = Dict.S('UI:ValueMustBeChanged');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bValid = true;
|
||||
}
|
||||
return {bValid: bValid, sExplain: sExplain};
|
||||
}
|
||||
else if ((originalValue != undefined) && (sTextContent == originalValue))
|
||||
{
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeChanged');
|
||||
}
|
||||
}
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, '' /* sExplain */);
|
||||
|
||||
// We need to check periodically as CKEditor doesn't trigger our events. More details in UIHTMLEditorWidget::Display() @ line 92
|
||||
setTimeout(function(){ValidateCaseLogField(sFieldId, bMandatory, sFormId, nullValue, originalValue);}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
// Validate the inputs depending on the current setting
|
||||
|
||||
@@ -19,10 +19,11 @@ Selectize.define("combodo_auto_position", function (aOptions) {
|
||||
|
||||
// Selectize instance
|
||||
let oSelf = this;
|
||||
const iDropdownContentHeightDifference = 4;
|
||||
|
||||
// Plugin options
|
||||
aOptions = $.extend({
|
||||
maxDropDownHeight: 200,
|
||||
maxDropDownHeight: '200px',
|
||||
},
|
||||
aOptions
|
||||
);
|
||||
@@ -33,28 +34,47 @@ Selectize.define("combodo_auto_position", function (aOptions) {
|
||||
// Override position dropdown function
|
||||
oSelf.positionDropdown = (function () {
|
||||
return function () {
|
||||
let iRefHeight = oSelf.$dropdown.outerHeight() < aOptions.maxDropDownHeight ?
|
||||
oSelf.$dropdown.outerHeight() : aOptions.maxDropDownHeight;
|
||||
// Clear previously set rules so the comparison is done with dropdown real height
|
||||
oSelf.$dropdown.css({
|
||||
'max-height': '',
|
||||
});
|
||||
|
||||
if(oSelf.$control.offset().top + oSelf.$control.outerHeight() + iRefHeight > window.innerHeight){
|
||||
oSelf.$dropdown_content.css({
|
||||
'max-height': '',
|
||||
});
|
||||
|
||||
oSelf.$dropdown.css({
|
||||
top: oSelf.$control.offset().top - iRefHeight,
|
||||
left: oSelf.$control.offset().left,
|
||||
let iDropdownHeight = oSelf.$dropdown.outerHeight();
|
||||
if(oSelf.$control.offset().top + oSelf.$control.outerHeight() + iDropdownHeight > window.innerHeight){
|
||||
|
||||
// Apply max-height as we are overflowing, that'll allow us to calculate where we should place ourselves later
|
||||
oSelf.$dropdown.css({
|
||||
maxHeight: `${aOptions.maxDropDownHeight}`,
|
||||
})
|
||||
|
||||
iDropdownHeight = oSelf.$dropdown.outerHeight();
|
||||
|
||||
oSelf.$dropdown.css({
|
||||
top: oSelf.$control.offset().top - iDropdownHeight + iDropdownContentHeightDifference, // Content will be shorter, so our real height too
|
||||
left: oSelf.$control.offset().left,
|
||||
width: oSelf.$wrapper.outerWidth(),
|
||||
'max-height': `${aOptions.maxDropDownHeight}px`,
|
||||
'overflow-y': 'auto',
|
||||
'border-top': '1px solid #d0d0d0',
|
||||
overflowY: 'auto',
|
||||
borderTop : oSelf.$dropdown.css('border-bottom')
|
||||
});
|
||||
|
||||
// N°9468 Dropdown content needs to be a few pixel shorter than the dropdown itself to avoid double scrollbar
|
||||
oSelf.$dropdown_content.css({
|
||||
'max-height': `calc(${aOptions.maxDropDownHeight} - ${iDropdownContentHeightDifference}px)`
|
||||
});
|
||||
|
||||
}
|
||||
else{
|
||||
oSelf.$dropdown.css({
|
||||
top: oSelf.$control.offset().top + oSelf.$control.outerHeight(),
|
||||
left: oSelf.$control.offset().left,
|
||||
width: oSelf.$wrapper.outerWidth(),
|
||||
'max-height': `${aOptions.maxDropDownHeight}px`,
|
||||
'overflow-y': 'auto'
|
||||
});
|
||||
overflowY: 'auto',
|
||||
borderTop: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
@@ -193,6 +193,8 @@ return array(
|
||||
'Combodo\\iTop\\Application\\Helper\\CKEditorHelper' => $baseDir . '/sources/Application/Helper/CKEditorHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => $baseDir . '/sources/Application/Helper/ExportHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\FormHelper' => $baseDir . '/sources/Application/Helper/FormHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\ImportHelper' => $baseDir . '/sources/Application/Helper/ImportHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\SearchHelper' => $baseDir . '/sources/Application/Helper/SearchHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\Session' => $baseDir . '/sources/Application/Helper/Session.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => $baseDir . '/sources/Application/Helper/WebResourcesHelper.php',
|
||||
'Combodo\\iTop\\Application\\Newsroom\\iTopNewsroomProvider' => $baseDir . '/sources/Application/Newsroom/iTopNewsroomProvider.php',
|
||||
|
||||
@@ -548,6 +548,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Combodo\\iTop\\Application\\Helper\\CKEditorHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/CKEditorHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/ExportHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\FormHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/FormHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\ImportHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/ImportHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\SearchHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/SearchHelper.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\Session' => __DIR__ . '/../..' . '/sources/Application/Helper/Session.php',
|
||||
'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/WebResourcesHelper.php',
|
||||
'Combodo\\iTop\\Application\\Newsroom\\iTopNewsroomProvider' => __DIR__ . '/../..' . '/sources/Application/Newsroom/iTopNewsroomProvider.php',
|
||||
|
||||
73
pages/UI.php
73
pages/UI.php
@@ -5,6 +5,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\SearchHelper;
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
@@ -126,72 +127,6 @@ function SetObjectBreadCrumbEntry(DBObject $oObj, WebPage $oPage)
|
||||
$oPage->SetBreadCrumbEntry("ui-details-$sClass-".$oObj->GetKey(), $oObj->Get('friendlyname'), MetaModel::GetName($sClass).': '.$oObj->Get('friendlyname'), '', $sIcon, $sIconType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the result of a search request
|
||||
* @param $oP WebPage Web page for the output
|
||||
* @param $oFilter DBSearch The search of objects to display
|
||||
* @param $bSearchForm boolean Whether or not to display the search form at the top the page
|
||||
* @param $sBaseClass string The base class for the search (can be different from the actual class of the results)
|
||||
* @param $sFormat string The format to use for the output: csv or html
|
||||
* @param $bDoSearch bool True to display the search results below the search form
|
||||
* @param $bSearchFormOpen bool True to display the search form fully expanded (only if $bSearchForm of course)
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true, $aParams = [])
|
||||
{
|
||||
//search block
|
||||
$oBlockForm = null;
|
||||
if ($bSearchForm) {
|
||||
$aParams['open'] = $bSearchFormOpen;
|
||||
if (false === isset($aParams['table_id'])) {
|
||||
$aParams['table_id'] = 'result_1';
|
||||
}
|
||||
if (!empty($sBaseClass)) {
|
||||
$aParams['baseClass'] = $sBaseClass;
|
||||
}
|
||||
$oBlockForm = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams);
|
||||
|
||||
if (!$bDoSearch) {
|
||||
$oBlockForm->Display($oP, 0);
|
||||
}
|
||||
}
|
||||
if ($bDoSearch) {
|
||||
if (strtolower($sFormat) == 'csv') {
|
||||
$oBlock = new DisplayBlock($oFilter, 'csv', false);
|
||||
// Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
|
||||
$oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block
|
||||
} else {
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
|
||||
// Breadcrumb
|
||||
//$iCount = $oBlock->GetDisplayedCount();
|
||||
$sPageId = "ui-search-".$oFilter->GetClass();
|
||||
$sLabel = MetaModel::GetName($oFilter->GetClass());
|
||||
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
}
|
||||
if ($bSearchForm) {
|
||||
//add search block
|
||||
$sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
|
||||
if ($sTableId == '') {
|
||||
$sTableId = 'result_1';
|
||||
}
|
||||
$aExtraParams['table_id'] = $sTableId;
|
||||
$aExtraParams['submit_on_load'] = false;
|
||||
$oUIBlockForm = $oBlockForm->GetDisplay($oP, 'search_1', $aExtraParams);
|
||||
//add result block
|
||||
$oUIBlock = $oBlock->GetDisplay($oP, $sTableId);
|
||||
$oUIBlock->AddCSSClasses(['display_block', 'sf_results_area']);
|
||||
$oUIBlock->AddDataAttribute('target', 'search_results');
|
||||
//$oUIBlockForm->AddSubBlock($oUIBlock);
|
||||
$oP->AddUiBlock($oUIBlockForm);
|
||||
$oUIBlockForm->AddSubBlock($oUIBlock);
|
||||
} else {
|
||||
$oBlock->Display($oP, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form (checkboxes) to select the objects for which to apply a given action
|
||||
* Only the objects for which the action is valid can be checked. By default all valid objects are checked
|
||||
@@ -460,7 +395,7 @@ try {
|
||||
$sOQL = "SELECT $sOQLClass $sOQLClause";
|
||||
try {
|
||||
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||
DisplaySearchSet($oP, $oFilter, $bSearchForm, $sBaseClass, $sFormat);
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, $sBaseClass, $sFormat);
|
||||
} catch (CoreException $e) {
|
||||
$oFilter = new DBObjectSearch($sOQLClass);
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
@@ -487,7 +422,7 @@ try {
|
||||
}
|
||||
$oP->set_title(Dict::S('UI:SearchResultsPageTitle'));
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat, $bDoSearch, true /* Search Form Expanded */);
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat, $bDoSearch, true /* Search Form Expanded */);
|
||||
break;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -509,7 +444,7 @@ try {
|
||||
// $sParams = utils::ReadParam('aParams', '{}', false, \utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
// $aParams = json_decode($sParams, true);
|
||||
|
||||
DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); //, true, true, $aParams
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); //, true, true, $aParams
|
||||
break;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\ImportHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\Select;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
|
||||
@@ -387,6 +389,14 @@ EOF
|
||||
}
|
||||
break;
|
||||
|
||||
case 'display_classes_select':
|
||||
$oPage = new AjaxPage("");
|
||||
$sClassName = utils::ReadPostedParam('class_name', '', utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
$bAdvanced = utils::ReadPostedParam('advanced', 'false');
|
||||
$oClassesSelect = ImportHelper::GetClassesSelectUIBlock('class_name', $sClassName, UR_ACTION_BULK_MODIFY, $bAdvanced === 'true');
|
||||
$oPage->AddSubBlock($oClassesSelect);
|
||||
break;
|
||||
|
||||
case 'get_csv_template':
|
||||
$sClassName = utils::ReadParam('class_name');
|
||||
$sFormat = utils::ReadParam('format', 'csv');
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\ImportHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory;
|
||||
@@ -14,7 +15,6 @@ use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\FileSelect\FileSelectUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\Select;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
|
||||
@@ -30,7 +30,6 @@ use Combodo\iTop\Application\WebPage\AjaxPage;
|
||||
use Combodo\iTop\Application\WebPage\ErrorPage;
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use Combodo\iTop\Service\Import\CSVImportPageProcessor;
|
||||
|
||||
try {
|
||||
@@ -52,67 +51,6 @@ try {
|
||||
$oPage = new iTopWebPage(Dict::S('UI:Title:BulkImport'));
|
||||
$oPage->SetBreadCrumbEntry('ui-tool-bulkimport', Dict::S('Menu:CSVImportMenu'), Dict::S('UI:Title:BulkImport+'), '', 'fas fa-file-import', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
|
||||
/**
|
||||
* Helper function to build a select from the list of valid classes for a given action
|
||||
*
|
||||
* @deprecated 3.0.0 use GetClassesSelectUIBlock
|
||||
*
|
||||
* @param $sDefaultValue
|
||||
* @param integer $iWidthPx The width (in pixels) of the drop-down list
|
||||
* @param integer $iActionCode The ActionCode (from UserRights) to check for authorization for the classes
|
||||
*
|
||||
* @param string $sName The name of the select in the HTML form
|
||||
*
|
||||
* @return string The HTML fragment corresponding to the select tag
|
||||
*/
|
||||
function GetClassesSelect($sName, $sDefaultValue, $iWidthPx, $iActionCode = null)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use GetClassesSelectUIBlock');
|
||||
$oSelectBlock = GetClassesSelectUIBlock($sName, $sDefaultValue, $iActionCode);
|
||||
|
||||
return BlockRenderer::RenderBlockTemplates($oSelectBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build a select from the list of valid classes for a given action
|
||||
*
|
||||
* @param string $sName The name of the select in the HTML form
|
||||
* @param $sDefaultValue
|
||||
* @param integer $iWidthPx The width (in pixels) of the drop-down list
|
||||
* @param integer $iActionCode The ActionCode (from UserRights) to check for authorization for the classes
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Component\Input\Select\
|
||||
*/
|
||||
function GetClassesSelectUIBlock(string $sName, $sDefaultValue, int $iActionCode, bool $bAdvanced = false): Select
|
||||
{
|
||||
$oSelectBlock = SelectUIBlockFactory::MakeForSelect($sName, 'select_'.$sName);
|
||||
$oOption = SelectOptionUIBlockFactory::MakeForSelectOption("", Dict::S('UI:CSVImport:ClassesSelectOne'), false);
|
||||
$oSelectBlock->AddSubBlock($oOption);
|
||||
$aValidClasses = [];
|
||||
$aClassCategories = ['bizmodel', 'addon/authentication'];
|
||||
if ($bAdvanced) {
|
||||
$aClassCategories[] = 'grant_by_profile';
|
||||
}
|
||||
if (UserRights::IsAdministrator()) {
|
||||
$aClassCategories[] = 'application';
|
||||
}
|
||||
foreach ($aClassCategories as $sClassCategory) {
|
||||
foreach (MetaModel::GetClasses($sClassCategory) as $sClassName) {
|
||||
if ((is_null($iActionCode) || UserRights::IsActionAllowed($sClassName, $iActionCode)) &&
|
||||
(!MetaModel::IsAbstract($sClassName))) {
|
||||
$sDisplayName = ($bAdvanced) ? MetaModel::GetName($sClassName)." ($sClassName)" : MetaModel::GetName($sClassName);
|
||||
$aValidClasses[$sDisplayName] = SelectOptionUIBlockFactory::MakeForSelectOption($sClassName, $sDisplayName, ($sClassName == $sDefaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($aValidClasses);
|
||||
foreach ($aValidClasses as $sValue => $oBlock) {
|
||||
$oSelectBlock->AddSubBlock($oBlock);
|
||||
}
|
||||
|
||||
return $oSelectBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to 'check' an input in an HTML form if the current value equals the value given
|
||||
*
|
||||
@@ -351,7 +289,7 @@ try {
|
||||
$oClassesSelect->AddSubBlock($oDefaultSelect);
|
||||
$aSynchroUpdate = utils::ReadParam('synchro_update', []);
|
||||
} else {
|
||||
$oClassesSelect = GetClassesSelectUIBlock('class_name', $sClassName, UR_ACTION_BULK_MODIFY, (bool)$bAdvanced);
|
||||
$oClassesSelect = ImportHelper::GetClassesSelectUIBlock('class_name', $sClassName, UR_ACTION_BULK_MODIFY, (bool)$bAdvanced);
|
||||
}
|
||||
$oPanel = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:CSVImportStep3'));
|
||||
$oPage->AddSubBlock($oPanel);
|
||||
@@ -375,11 +313,9 @@ try {
|
||||
$oAdvancedMode->GetInput()->SetIsChecked(($bAdvanced == 1));
|
||||
$oAdvancedMode->SetBeforeInput(false);
|
||||
$oAdvancedMode->GetInput()->AddCSSClass('ibo-input-checkbox');
|
||||
$oAdvancedMode->SetDescription(utils::EscapeHtml(Dict::S('UI:CSVImport:AdvancedMode+')));
|
||||
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oAdvancedMode));
|
||||
|
||||
$oDivAdvancedHelp = UIContentBlockUIBlockFactory::MakeStandard("advanced_help")->AddCSSClass('ibo-is-hidden');
|
||||
$oForm->AddSubBlock($oDivAdvancedHelp);
|
||||
|
||||
$oDivMapping = UIContentBlockUIBlockFactory::MakeStandard("mapping")->AddCSSClass('mt-5');
|
||||
$oMessage = AlertUIBlockFactory::MakeForInformation(Dict::S('UI:CSVImport:SelectAClassFirst'))->SetIsClosable(false)->SetIsCollapsible(false);
|
||||
$oDivMapping->AddSubBlock($oMessage);
|
||||
@@ -416,7 +352,7 @@ try {
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('#select_class_name').on('change', function(ev) { DoMapping(); } );
|
||||
$('#advanced').on('click', function(ev) { DoReload(); } );
|
||||
$('#advanced').on('click', function(ev) { DoAdvanced(); } );
|
||||
EOF
|
||||
);
|
||||
if ($sClassName != '') {
|
||||
@@ -429,15 +365,13 @@ EOF
|
||||
}
|
||||
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
<<<JS
|
||||
var aDefaultKeys = new Array();
|
||||
var aReadOnlyKeys = new Array();
|
||||
|
||||
function DoReload()
|
||||
function DoAdvanced()
|
||||
{
|
||||
$('input[name=step]').val(3);
|
||||
$('#wizForm').removeAttr('onsubmit'); // No need to perform validation checks when going back
|
||||
$('#wizForm').submit();
|
||||
UpdateClassesSelect();
|
||||
}
|
||||
|
||||
function CSVGoBack()
|
||||
@@ -462,14 +396,7 @@ EOF
|
||||
{
|
||||
var class_name = $('select[name=class_name]').val();
|
||||
var advanced = $('input[name=advanced]:checked').val();
|
||||
if (advanced != 1)
|
||||
{
|
||||
$('#advanced_help').hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#advanced_help').show();
|
||||
}
|
||||
|
||||
if (class_name != '')
|
||||
{
|
||||
var separator = $('input[name=separator]').val();
|
||||
@@ -517,6 +444,26 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateClassesSelect()
|
||||
{
|
||||
const aParams = {
|
||||
operation: 'display_classes_select',
|
||||
class_name: $('#select_class_name').val(),
|
||||
advanced: $('#advanced').is(':checked'),
|
||||
};
|
||||
|
||||
$('#select_class_name').block();
|
||||
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.csvimport.php',
|
||||
aParams,
|
||||
function(data) {
|
||||
$('#select_class_name').replaceWith($(data));
|
||||
$('#select_class_name').on('change', function(ev) { DoMapping(); } );
|
||||
DoMapping();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function CheckValues()
|
||||
{
|
||||
// Reset the highlight in case the check has already been executed with failure
|
||||
@@ -647,7 +594,7 @@ EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1065,7 +1012,7 @@ EOF
|
||||
}*/
|
||||
//Tab:Template
|
||||
$oTabTemplate = $oTabContainer->AddTab('tabsTemplate', Dict::S('UI:CSVImport:Tab:Templates'));
|
||||
$oFieldTemplate = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:PickClassForTemplate'), GetClassesSelectUIBlock('template_class', '', UR_ACTION_BULK_MODIFY));
|
||||
$oFieldTemplate = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:PickClassForTemplate'), ImportHelper::GetClassesSelectUIBlock('template_class', '', UR_ACTION_BULK_MODIFY));
|
||||
$oTabTemplate->AddSubBlock($oFieldTemplate);
|
||||
$oDivTemplate = UIContentBlockUIBlockFactory::MakeStandard("template")->AddCSSClass("ibo-is-visible");
|
||||
$oTabTemplate->AddSubBlock($oDivTemplate);
|
||||
|
||||
@@ -104,7 +104,7 @@ if ($sTargetPage === false || $sModule === 'core' || $sModule === 'dictionaries'
|
||||
$aModuleDelegatedAuthenticationEndpointsList = GetModuleDelegatedAuthenticationEndpoints($sModule);
|
||||
// If module doesn't have the delegated authentication endpoints list defined, we rely on the conf. param. to decide if we force login or not.
|
||||
if (is_null($aModuleDelegatedAuthenticationEndpointsList)) {
|
||||
$bForceLoginWhenNoDelegatedAuthenticationEndpoints = utils::GetConfig()->Get('security.force_login_when_no_delegated_authentication_endpoints_list');
|
||||
$bForceLoginWhenNoDelegatedAuthenticationEndpoints = !utils::GetConfig()->Get('security.disable_exec_forced_login_for_all_enpoints');
|
||||
if ($bForceLoginWhenNoDelegatedAuthenticationEndpoints) {
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
LoginWebPage::DoLoginEx();
|
||||
|
||||
@@ -2643,6 +2643,58 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">doctrine/lexer</product>
|
||||
<author>Guilherme Blanco - Roman Borschel - Johannes Schmitt</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2006-2018 Doctrine Project
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">egulias/email-validator</product>
|
||||
<author>Eduardo Gulias Davis</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2013-2023 Eduardo Gulias Davis
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -2778,204 +2830,6 @@ 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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-loader</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-mail</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-mime</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-servicemanager</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-stdlib</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">laminas/laminas-validator</product>
|
||||
<author/>
|
||||
<license_type>BSD-3-Clause</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -2985,7 +2839,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
<text><![CDATA[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2020 Alex Bilbie <hello@alexbilbie.com>
|
||||
Copyright (c) 2013-2023 Alex Bilbie <hello@alexbilbie.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -3032,79 +2886,6 @@ 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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">masterminds/html5</product>
|
||||
<author>Matt Butcher - Matt Farina - Asmir Mustafic</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
## HTML5-PHP License
|
||||
|
||||
Copyright (c) 2013 The Authors of HTML5-PHP
|
||||
|
||||
Matt Butcher - mattbutcher@google.com
|
||||
Matt Farina - matt@mattfarina.com
|
||||
Asmir Mustafic - goetas@gmail.com
|
||||
|
||||
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.
|
||||
|
||||
## HTML5Lib License
|
||||
|
||||
Portions of this are based on html5lib's PHP version, which was a
|
||||
sub-project of html5lib. The following is the list of contributors from
|
||||
html5lib:
|
||||
|
||||
html5lib:
|
||||
|
||||
Copyright (c) 2006-2009 The Authors
|
||||
|
||||
Contributors:
|
||||
James Graham - jg307@cam.ac.uk
|
||||
Anne van Kesteren - annevankesteren@gmail.com
|
||||
Lachlan Hunt - lachlan.hunt@lachy.id.au
|
||||
Matt McDonald - kanashii@kanashii.ca
|
||||
Sam Ruby - rubys@intertwingly.net
|
||||
Ian Hickson (Google) - ian@hixie.ch
|
||||
Thomas Broyer - t.broyer@ltgt.net
|
||||
Jacques Distler - distler@golem.ph.utexas.edu
|
||||
Henri Sivonen - hsivonen@iki.fi
|
||||
Adam Barth - abarth@webkit.org
|
||||
Eric Seidel - eric@webkit.org
|
||||
The Mozilla Foundation (contributions from Henri Sivonen since 2008)
|
||||
David Flanagan (Mozilla) - dflanagan@mozilla.com
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -3141,34 +2922,6 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">paragonie/random_compat</product>
|
||||
<author>Paragon Initiative Enterprises</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Paragon Initiative Enterprises
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -3499,7 +3252,7 @@ SOFTWARE.
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">sabberworm/php-css-parser</product>
|
||||
<author>Raphael Schweikert</author>
|
||||
<author>Raphael Schweikert - Oliver Klee - Jake Hotson</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
MIT License
|
||||
@@ -3550,6 +3303,34 @@ 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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">soundasleep/html2text</product>
|
||||
<author>Jevon Wright</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Jevon Wright
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -3985,6 +3766,58 @@ 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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/mailer</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2019-present Fabien Potencier
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/mime</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2010-present Fabien Potencier
|
||||
|
||||
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
|
||||
@@ -4115,58 +3948,6 @@ 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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/polyfill-php72</product>
|
||||
<author>Nicolas Grekas - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2015-present Fabien Potencier
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/polyfill-php80</product>
|
||||
<author>Ion Bazan - Nicolas Grekas - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2020-present Fabien Potencier
|
||||
|
||||
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
|
||||
@@ -4535,7 +4316,7 @@ THE SOFTWARE.
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
2002-2023 Nicola Asuni - Tecnick.com LTD
|
||||
2002-2025 Nicola Asuni - Tecnick.com LTD
|
||||
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
@@ -5448,33 +5229,6 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">webmozart/assert</product>
|
||||
<author>Bernhard Schussek</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Bernhard Schussek
|
||||
|
||||
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.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
|
||||
@@ -36,7 +36,7 @@ class SetupPage extends NiceWebPage
|
||||
{
|
||||
public const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/setuppage/layout';
|
||||
|
||||
protected const BODY_DATA_GUI_TYPE = 'setup';
|
||||
public const BODY_DATA_GUI_TYPE = 'setup';
|
||||
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
|
||||
65
sources/Application/Helper/ImportHelper.php
Normal file
65
sources/Application/Helper/ImportHelper.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Application\Helper;
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\Select;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\SelectUIBlockFactory;
|
||||
use CoreException;
|
||||
use Dict;
|
||||
use DictExceptionMissingString;
|
||||
use MetaModel;
|
||||
use UserRights;
|
||||
|
||||
/**
|
||||
* Class
|
||||
* ImportHelper
|
||||
*
|
||||
* @internal
|
||||
* @since 3.2.3
|
||||
* @package Combodo\iTop\Application\Helper
|
||||
*/
|
||||
class ImportHelper
|
||||
{
|
||||
/**
|
||||
* Get classes select UI block.
|
||||
*
|
||||
* @param string $sName
|
||||
* @param $sDefaultValue
|
||||
* @param int $iActionCode
|
||||
* @param bool $bAdvanced
|
||||
*
|
||||
* @return Select
|
||||
* @throws CoreException
|
||||
* @throws DictExceptionMissingString
|
||||
*/
|
||||
public static function GetClassesSelectUIBlock(string $sName, $sDefaultValue, int $iActionCode, bool $bAdvanced = false): Select
|
||||
{
|
||||
$oSelectBlock = SelectUIBlockFactory::MakeForSelect($sName, 'select_'.$sName);
|
||||
$oOption = SelectOptionUIBlockFactory::MakeForSelectOption("", Dict::S('UI:CSVImport:ClassesSelectOne'), false);
|
||||
$oSelectBlock->AddSubBlock($oOption);
|
||||
$aValidClasses = [];
|
||||
$aClassCategories = ['bizmodel', 'addon/authentication'];
|
||||
if ($bAdvanced) {
|
||||
$aClassCategories[] = 'grant_by_profile';
|
||||
}
|
||||
if (UserRights::IsAdministrator()) {
|
||||
$aClassCategories[] = 'application';
|
||||
}
|
||||
foreach ($aClassCategories as $sClassCategory) {
|
||||
foreach (MetaModel::GetClasses($sClassCategory) as $sClassName) {
|
||||
if ((is_null($iActionCode) || UserRights::IsActionAllowed($sClassName, $iActionCode)) &&
|
||||
(!MetaModel::IsAbstract($sClassName))) {
|
||||
$sDisplayName = ($bAdvanced) ? MetaModel::GetName($sClassName)." ($sClassName)" : MetaModel::GetName($sClassName);
|
||||
$aValidClasses[$sDisplayName] = SelectOptionUIBlockFactory::MakeForSelectOption($sClassName, $sDisplayName, ($sClassName == $sDefaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($aValidClasses);
|
||||
foreach ($aValidClasses as $sValue => $oBlock) {
|
||||
$oSelectBlock->AddSubBlock($oBlock);
|
||||
}
|
||||
|
||||
return $oSelectBlock;
|
||||
}
|
||||
}
|
||||
88
sources/Application/Helper/SearchHelper.php
Normal file
88
sources/Application/Helper/SearchHelper.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\Helper;
|
||||
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use DBSearch;
|
||||
use DisplayBlock;
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class SearchHelper
|
||||
{
|
||||
/**
|
||||
* Displays the result of a search request
|
||||
* @param $oP WebPage Web page for the output
|
||||
* @param $oFilter DBSearch The search of objects to display
|
||||
* @param $bSearchForm boolean Whether or not to display the search form at the top the page
|
||||
* @param $sBaseClass string The base class for the search (can be different from the actual class of the results)
|
||||
* @param $sFormat string The format to use for the output: csv or html
|
||||
* @param $bDoSearch bool True to display the search results below the search form
|
||||
* @param $bSearchFormOpen bool True to display the search form fully expanded (only if $bSearchForm of course)
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public static function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true, $aParams = []): void
|
||||
{
|
||||
//search block
|
||||
$oBlockForm = null;
|
||||
if ($bSearchForm) {
|
||||
$aParams['open'] = $bSearchFormOpen;
|
||||
if (false === isset($aParams['table_id'])) {
|
||||
$aParams['table_id'] = 'result_1';
|
||||
}
|
||||
if (!empty($sBaseClass)) {
|
||||
$aParams['baseClass'] = $sBaseClass;
|
||||
}
|
||||
$oBlockForm = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams);
|
||||
|
||||
if (!$bDoSearch) {
|
||||
$oBlockForm->Display($oP, 0);
|
||||
}
|
||||
}
|
||||
if ($bDoSearch) {
|
||||
if (strtolower($sFormat) == 'csv') {
|
||||
$oBlock = new DisplayBlock($oFilter, 'csv', false);
|
||||
// Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
|
||||
$oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block
|
||||
} else {
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
|
||||
// Breadcrumb
|
||||
//$iCount = $oBlock->GetDisplayedCount();
|
||||
$sPageId = "ui-search-".$oFilter->GetClass();
|
||||
$sLabel = MetaModel::GetName($oFilter->GetClass());
|
||||
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
}
|
||||
if ($bSearchForm) {
|
||||
//add search block
|
||||
$sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
|
||||
if ($sTableId == '') {
|
||||
$sTableId = 'result_1';
|
||||
}
|
||||
$aExtraParams['table_id'] = $sTableId;
|
||||
$aExtraParams['submit_on_load'] = false;
|
||||
$oUIBlockForm = $oBlockForm->GetDisplay($oP, 'search_1', $aExtraParams);
|
||||
|
||||
// If the class is not high cardinality, we can display the results directly in the same page
|
||||
if (!utils::IsHighCardinality($oFilter->GetClass())) {
|
||||
//add result block
|
||||
$oUIBlock = $oBlock->GetDisplay($oP, $sTableId);
|
||||
$oUIBlock->AddCSSClasses(['display_block', 'sf_results_area']);
|
||||
$oUIBlock->AddDataAttribute('target', 'search_results');
|
||||
$oUIBlockForm->AddSubBlock($oUIBlock);
|
||||
}
|
||||
|
||||
$oP->AddUiBlock($oUIBlockForm);
|
||||
} else {
|
||||
$oBlock->Display($oP, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,13 @@ use AttributeFriendlyName;
|
||||
use AttributeLinkedSet;
|
||||
use cmdbAbstract;
|
||||
use cmdbAbstractObject;
|
||||
use CoreException;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use LogChannels;
|
||||
use Metamodel;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Class DataTableSettings
|
||||
@@ -130,7 +135,10 @@ class DataTableSettings
|
||||
*/
|
||||
public function unserialize($sData)
|
||||
{
|
||||
$aData = unserialize($sData);
|
||||
$aData = utils::Unserialize($sData);
|
||||
if (!is_array($aData)) {
|
||||
throw new CoreException('Wrong data table settings format, expected an array', ['datatable_settings_data' => $aData]);
|
||||
}
|
||||
$this->iDefaultPageSize = $aData['iDefaultPageSize'];
|
||||
$this->aColumns = $aData['aColumns'];
|
||||
foreach ($this->aClassAliases as $sAlias => $sClass) {
|
||||
@@ -269,7 +277,19 @@ class DataTableSettings
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$oSettings->unserialize($pref);
|
||||
|
||||
try {
|
||||
$oSettings->unserialize($pref);
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Warning("User table settings corrupted, back to the default values provided by the data model", LogChannels::CONSOLE, [
|
||||
'table_id' => $sTableId,
|
||||
'root_cause' => $e->getMessage(),
|
||||
]);
|
||||
// unset the preference
|
||||
appUserPreferences::UnsetPref($oSettings->GetPrefsKey($sTableId));
|
||||
// use the default values provided by the data model
|
||||
return null;
|
||||
}
|
||||
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ class ActivityPanelFactory
|
||||
if (false === empty($aRelatedTriggersIDs)) {
|
||||
// - Prepare query to retrieve events
|
||||
$oNotifEventsSearch = DBObjectSearch::FromOQL('SELECT EN FROM EventNotification AS EN JOIN Action AS A ON EN.action_id = A.id WHERE EN.trigger_id IN (:triggers_ids) AND EN.object_id = :object_id');
|
||||
$oNotifEventsSearch->AllowAllData();
|
||||
$oNotifEventsSet = new DBObjectSet($oNotifEventsSearch, ['id' => false], ['triggers_ids' => $aRelatedTriggersIDs, 'object_id' => $sObjId]);
|
||||
$oNotifEventsSet->SetLimit(MetaModel::GetConfig()->Get('max_history_length'));
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ class WebPage implements Page
|
||||
*/
|
||||
public const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/webpage/layout';
|
||||
|
||||
protected const BODY_DATA_GUI_TYPE = 'backoffice';
|
||||
public const BODY_DATA_GUI_TYPE = 'backoffice';
|
||||
|
||||
protected $s_title;
|
||||
protected $s_content;
|
||||
|
||||
@@ -30,6 +30,7 @@ use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mime\Email as SymfonyEmail;
|
||||
use Symfony\Component\Mime\HtmlToTextConverter\DefaultHtmlToTextConverter;
|
||||
use Symfony\Component\Mime\Part\DataPart;
|
||||
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
|
||||
use Symfony\Component\Mime\Part\Multipart\MixedPart;
|
||||
@@ -389,20 +390,40 @@ class EMailSymfony extends Email
|
||||
*/
|
||||
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
|
||||
{
|
||||
// Some mime types can have options, let's retrieve the different parts so we can extract the primary mime type
|
||||
$aMimeTypeParts = array_map('trim', explode(';', $sMimeType));
|
||||
$sPrimaryMimeType = strtolower(array_shift($aMimeTypeParts));
|
||||
|
||||
$aMimeTypeParams = [];
|
||||
foreach ($aMimeTypeParts as $sPart) {
|
||||
// Parse key=value parameters (eg method=REQUEST, charset=UTF-8) after the semicolon.
|
||||
// Stored in $aMimeTypeParams so they can be added to the Content-Type header.
|
||||
if ($sPart === '') {
|
||||
continue;
|
||||
}
|
||||
$aPair = explode('=', $sPart, 2);
|
||||
$sKey = strtolower(trim($aPair[0]));
|
||||
// Normalize and unquote the parameter value for Content-Type (eg charset=UTF-8).
|
||||
$sValue = isset($aPair[1]) ? trim($aPair[1], " \t\n\r\0\x0B\"") : '';
|
||||
if ($sKey !== '') {
|
||||
$aMimeTypeParams[$sKey] = $sValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Inline CSS if needed
|
||||
if ($sMimeType === 'text/html') {
|
||||
if ($sPrimaryMimeType === 'text/html') {
|
||||
$sBody = static::InlineCssIntoBodyContent($sBody, $sCustomStyles);
|
||||
}
|
||||
|
||||
$this->m_aData['body'] = ['body' => $sBody, 'mimeType' => $sMimeType];
|
||||
|
||||
$oTextPart = new TextPart(strip_tags($sBody), 'utf-8', 'plain', 'base64');
|
||||
|
||||
// Embed inline images and store them in attachments (so BuildSymfonyMessageFromInternal can pick them)
|
||||
if ($sMimeType === 'text/html') {
|
||||
if ($sPrimaryMimeType === 'text/html') {
|
||||
$aAdditionalParts = $this->EmbedInlineImages($sBody);
|
||||
$oTextPart = new TextPart((new DefaultHtmlToTextConverter())->convert($sBody, 'utf-8'), 'utf-8', 'plain', 'base64');
|
||||
$oHtmlPart = new TextPart($sBody, 'utf-8', 'html', 'base64');
|
||||
$oAlternativePart = new AlternativePart($oHtmlPart, $oTextPart);
|
||||
// It's important de order parts from least prefered to most prefered as per RFC 2046 {@see https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.4}
|
||||
$oAlternativePart = new AlternativePart($oTextPart, $oHtmlPart);
|
||||
// Default root part is the HTML body
|
||||
$oRootPart = $oAlternativePart;
|
||||
|
||||
@@ -411,8 +432,20 @@ class EMailSymfony extends Email
|
||||
$oRootPart = new RelatedPart(...$aRelatedParts);
|
||||
}
|
||||
} else {
|
||||
// Default root part is the text body
|
||||
$oRootPart = $oTextPart;
|
||||
// Default root part is a TextPart with the right mimetype
|
||||
$sSubtype = 'plain';
|
||||
// Extract subtype for text/* content; default to plain otherwise.
|
||||
if (strpos($sPrimaryMimeType, '/') !== false) {
|
||||
list($sType, $sSubtype) = explode('/', $sPrimaryMimeType, 2);
|
||||
if ($sType !== 'text') {
|
||||
$sSubtype = 'plain';
|
||||
}
|
||||
}
|
||||
$oRootPart = new TextPart($sBody, 'utf-8', $sSubtype, 'base64');
|
||||
// Add parsed Content-Type parameters like method/charset if provided.
|
||||
if (!empty($aMimeTypeParams)) {
|
||||
$oRootPart->getHeaders()->addParameterizedHeader('Content-Type', $sPrimaryMimeType, $aMimeTypeParams);
|
||||
}
|
||||
}
|
||||
|
||||
$this->m_oMessage->setBody($oRootPart);
|
||||
@@ -432,9 +465,13 @@ class EMailSymfony extends Email
|
||||
|
||||
/**
|
||||
* Add a new part to the existing body
|
||||
*
|
||||
* @deprecated 3.2.3 3.3.0 N°9549 This worked with the previous mail lib (Laminas) but it no longer works with SymfonyMailer and needs to be split in specific methods
|
||||
*/
|
||||
public function AddPart($sText, $sMimeType = 'text/html')
|
||||
{
|
||||
\DeprecatedCallsLog::NotifyDeprecatedPhpMethod('No generic alternative yet, if you want to add an attachment use `self::AddAttachment()`');
|
||||
|
||||
$sMimeSubtype = $this->GetMimeSubtype($sMimeType);
|
||||
|
||||
if (!array_key_exists('parts', $this->m_aData)) {
|
||||
|
||||
@@ -7,6 +7,6 @@ oWidget{{ oUIBlock.oUILinksDirectWidget.GetInputId() }} = $('#{{ oUIBlock.oUILin
|
||||
input_name: '{{ oUIBlock.sInputName }}',
|
||||
submit_to: '{{ oUIBlock.sSubmitUrl }}',
|
||||
oWizardHelper: {{ oUIBlock.sWizHelper }},
|
||||
do_search: '{{ oUIBlock.sJSDoSearch }}'
|
||||
do_search: {{ oUIBlock.sJSDoSearch }}
|
||||
});
|
||||
{% endapply %}
|
||||
@@ -23,7 +23,7 @@ let oWidget{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').selectize({
|
||||
},
|
||||
{# PLUGIN combodo auto position #}
|
||||
'combodo_auto_position' : {
|
||||
maxDropDownHeight: 300, {# in px #}
|
||||
maxDropDownHeight: '30vh', {# same value as external key widget #}
|
||||
},
|
||||
{# PLUGIN combodo add button #}
|
||||
{% if oUIBlock.HasAddOptionButton() %}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<div id="{{ oUIBlock.GetId() }}" class="{{ oUIBlock.GetBlocksInheritanceCSSClassesAsString() }} {{ oUIBlock.GetAdditionalCSSClassesAsString() }} {% if oUIBlock.HasIcon() %}ibo-has-icon{% endif %}{% if oUIBlock.IsHidden() %} ibo-is-hidden{% endif %}" data-role="ibo-title">
|
||||
{% if oUIBlock.HasIcon() %}
|
||||
<div class="ibo-title--icon">
|
||||
<div class="ibo-title--icon-background ibo-title--icon-background--must-{{ oUIBlock.GetIconCoverMethod() }} ibo-title--icon-level-{{ oUIBlock.GetLevel() }}" style="background-image: url('{{ oUIBlock.GetIconUrl()|raw }}');"></div>
|
||||
<img class="ibo-title--icon-background ibo-title--icon-background--must-{{ oUIBlock.GetIconCoverMethod() }} ibo-title--icon-level-{{ oUIBlock.GetLevel() }}"
|
||||
{% if oUIBlock.HasLazyLoadIcon %} loading="lazy" {% endif %}
|
||||
data-role="ibo-title--icon-img" src="{{ oUIBlock.GetIconUrl()|raw }}" alt="" aria-hidden="true"/>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="ibo-title--content">
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body data-gui-type="{{ aPage.sBodyDataGuiType|default('backoffice') }}">
|
||||
<body data-gui-type="{{ aPage.sBodyDataGuiType|default(constant('Combodo\\iTop\\Application\\WebPage\\WebPage::BODY_DATA_GUI_TYPE')) }}">
|
||||
{% if aPage.isPrintable %}<div class="printable-content" style="width: 27.7cm;">{% endif %}
|
||||
{% block iboPageBodyHtml %}
|
||||
<div id="ibo-page-container">
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
namespace Combodo\iTop\Test\VisualTest\Backoffice;
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
@@ -402,7 +403,8 @@ $oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 1', 1));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 2', 2));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 3', 3));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 4', 4));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 5', 5));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeForPageWithIcon('Title example 5', MetaModel::GetClassIcon('Organization', false)));
|
||||
$oPage->AddUiBlock(TitleUIBlockFactory::MakeForPageWithIcon('Title example 6', Branding::GetFullMainLogoAbsoluteUrl()));
|
||||
|
||||
/////////
|
||||
// DataTable
|
||||
|
||||
@@ -26,14 +26,14 @@ class LoginWebPageTest extends ItopDataTestCase
|
||||
$this->BackupConfiguration();
|
||||
$sFolderPath = APPROOT.'env-production/extension-with-delegated-authentication-endpoints-list';
|
||||
if (file_exists($sFolderPath)) {
|
||||
throw new Exception("Folder $sFolderPath already exists, please remove it before running the test");
|
||||
$this->RecurseRmdir($sFolderPath);
|
||||
}
|
||||
mkdir($sFolderPath);
|
||||
$this->RecurseCopy(__DIR__.'/extension-with-delegated-authentication-endpoints-list', $sFolderPath);
|
||||
|
||||
$sFolderPath = APPROOT.'env-production/extension-without-delegated-authentication-endpoints-list';
|
||||
if (file_exists($sFolderPath)) {
|
||||
throw new Exception("Folder $sFolderPath already exists, please remove it before running the test");
|
||||
$this->RecurseRmdir($sFolderPath);
|
||||
}
|
||||
mkdir($sFolderPath);
|
||||
$this->RecurseCopy(__DIR__.'/extension-without-delegated-authentication-endpoints-list', $sFolderPath);
|
||||
@@ -81,8 +81,7 @@ class LoginWebPageTest extends ItopDataTestCase
|
||||
|
||||
public function testUserCanAccessAnyFile()
|
||||
{
|
||||
// generate random login
|
||||
$sUserLogin = 'user-'.date('YmdHis');
|
||||
$sUserLogin = 'user-'.uniqid();
|
||||
$this->CreateUser($sUserLogin, self::$aURP_Profiles['Service Desk Agent'], self::PASSWORD);
|
||||
$this->GivenConfigFileAllowedLoginTypes(explode('|', 'form'));
|
||||
|
||||
@@ -102,7 +101,7 @@ class LoginWebPageTest extends ItopDataTestCase
|
||||
public function testWithoutDelegatedAuthenticationEndpointsListWithForceLoginConf()
|
||||
{
|
||||
@chmod($this->oConfig->GetLoadedFile(), 0770);
|
||||
$this->oConfig->Set('security.force_login_when_no_delegated_authentication_endpoints_list', true, 'AnythingButEmptyOrUnknownValue'); // 3rd param to write file even if show_in_conf_sample is false
|
||||
$this->oConfig->Set('security.disable_exec_forced_login_for_all_enpoints', false, 'AnythingButEmptyOrUnknownValue'); // 3rd param to write file even if show_in_conf_sample is false
|
||||
$this->oConfig->WriteToFile();
|
||||
@chmod($this->oConfig->GetLoadedFile(), 0444);
|
||||
$sPageContent = $this->CallItopUri(
|
||||
|
||||
@@ -1470,4 +1470,19 @@ abstract class ItopDataTestCase extends ItopTestCase
|
||||
@chmod($sConfigPath, 0440);
|
||||
@unlink($this->sConfigTmpBackupFile);
|
||||
}
|
||||
protected function AddLoginModeAndSaveConfiguration(string $sLoginMode): void
|
||||
{
|
||||
$aAllowedLoginTypes = $this->oiTopConfig->GetAllowedLoginTypes();
|
||||
if (!in_array($sLoginMode, $aAllowedLoginTypes)) {
|
||||
$aAllowedLoginTypes[] = $sLoginMode;
|
||||
$this->oiTopConfig->SetAllowedLoginTypes($aAllowedLoginTypes);
|
||||
$this->SaveItopConfFile();
|
||||
}
|
||||
}
|
||||
protected function SaveItopConfFile(): void
|
||||
{
|
||||
@chmod($this->oiTopConfig->GetLoadedFile(), 0770);
|
||||
$this->oiTopConfig->WriteToFile();
|
||||
@chmod($this->oiTopConfig->GetLoadedFile(), 0440);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@ abstract class ItopTestCase extends KernelTestCase
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $sUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
|
||||
curl_setopt($ch, CURLOPT_POST, $aCurlOptions[CURLOPT_POST] ?? 1);// set post data to true
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
// Force disable of certificate check as most of dev / test env have a self-signed certificate
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
@@ -708,6 +708,16 @@ abstract class ItopTestCase extends KernelTestCase
|
||||
{
|
||||
$sUrl = \MetaModel::GetConfig()->Get('app_root_url')."/$sUri";
|
||||
|
||||
// Add PHP version in header to be able to handle Docker dev environments with automatic PHP version detection (instead of hardcoding the PHP version in the app_root_url)
|
||||
$sPhpVersion = PHP_VERSION;
|
||||
$aPhpVersionParts = explode('.', $sPhpVersion);
|
||||
$sPhpVersionHeaderValue = ($aPhpVersionParts[0] ?? '0').($aPhpVersionParts[1] ?? '0');
|
||||
$aCurlOptions = $aCurlOptions ?? [];
|
||||
$aCurlOptions[CURLOPT_HTTPHEADER] = array_merge(
|
||||
$aCurlOptions[CURLOPT_HTTPHEADER] ?? [],
|
||||
['X-PHP-Version: '.$sPhpVersionHeaderValue]
|
||||
);
|
||||
|
||||
return $this->CallUrl($sUrl, $aPostFields, $aCurlOptions, $bXDebugEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Helper;
|
||||
|
||||
use Combodo\iTop\Application\Helper\SearchHelper;
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBSearch;
|
||||
use MetaModel;
|
||||
|
||||
class SearchHelperTest extends ItopDataTestCase
|
||||
{
|
||||
protected static array $aHighCardinalityClasses = [];
|
||||
protected static bool $bSearchManualSubmit = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
self::$aHighCardinalityClasses = MetaModel::GetConfig()->Get('high_cardinality_classes');
|
||||
self::$bSearchManualSubmit = MetaModel::GetConfig()->Get('search_manual_submit');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
MetaModel::GetConfig()->Set('high_cardinality_classes', static::$aHighCardinalityClasses);
|
||||
MetaModel::GetConfig()->Set('search_manual_submit', static::$bSearchManualSubmit);
|
||||
}
|
||||
|
||||
public function testDisplaySearchSetWithNoHighCardinalityClassesAddsResultSubBlock(): void
|
||||
{
|
||||
MetaModel::GetConfig()->Set('high_cardinality_classes', []);
|
||||
MetaModel::GetConfig()->Set('search_manual_submit', false);
|
||||
|
||||
$oP = new iTopWebPage('SearchHelperTest');
|
||||
$oFilter = DBSearch::FromOQL('SELECT UserRequest');
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter);
|
||||
$oContentLayout = $oP->GetContentLayout();
|
||||
$this->assertTrue($oContentLayout->HasSubBlock('search_1'));
|
||||
$oSearchBlock = $oContentLayout->getSubBlock('search_1');
|
||||
$this->assertTrue($oSearchBlock->HasSubBlock('result_1'));
|
||||
|
||||
if (ob_get_level() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
}
|
||||
|
||||
public function testDisplaySearchSetWithHighCardinalityClassesDoesNotAddResultSubBlock(): void
|
||||
{
|
||||
MetaModel::GetConfig()->Set('high_cardinality_classes', ['UserRequest']);
|
||||
MetaModel::GetConfig()->Set('search_manual_submit', false);
|
||||
|
||||
$oP = new iTopWebPage('SearchHelperTest');
|
||||
$oFilter = DBSearch::FromOQL('SELECT UserRequest');
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter);
|
||||
$oContentLayout = $oP->GetContentLayout();
|
||||
$this->assertTrue($oContentLayout->HasSubBlock('search_1'));
|
||||
$oSearchBlock = $oContentLayout->getSubBlock('search_1');
|
||||
$this->assertFalse($oSearchBlock->HasSubBlock('result_1'));
|
||||
|
||||
if (ob_get_level() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
}
|
||||
|
||||
public function testDisplaySearchSetWithSearchManualSubmitAndWithoutHighCardinalityClassesDoesNotAddResultSubBlock(): void
|
||||
{
|
||||
MetaModel::GetConfig()->Set('high_cardinality_classes', []);
|
||||
MetaModel::GetConfig()->Set('search_manual_submit', true);
|
||||
|
||||
$oP = new iTopWebPage('SearchHelperTest');
|
||||
$oFilter = DBSearch::FromOQL('SELECT UserRequest');
|
||||
SearchHelper::DisplaySearchSet($oP, $oFilter);
|
||||
$oContentLayout = $oP->GetContentLayout();
|
||||
$this->assertTrue($oContentLayout->HasSubBlock('search_1'));
|
||||
$oSearchBlock = $oContentLayout->getSubBlock('search_1');
|
||||
$this->assertFalse($oSearchBlock->HasSubBlock('result_1'));
|
||||
|
||||
if (ob_get_level() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use utils;
|
||||
|
||||
class LoginExternalTest extends ItopDataTestCase
|
||||
{
|
||||
private $oConfig;
|
||||
private $sOriginalExtAuthVariable;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
require_once APPROOT.'application/loginexternal.class.inc.php';
|
||||
$this->oConfig = utils::GetConfig();
|
||||
$this->sOriginalExtAuthVariable = $this->oConfig->Get('ext_auth_variable');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->oConfig->SetExternalAuthenticationVariable($this->sOriginalExtAuthVariable);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
private function CallGetAuthUser()
|
||||
{
|
||||
$oLoginExternal = new \LoginExternal();
|
||||
$oMethod = new \ReflectionMethod(\LoginExternal::class, 'GetAuthUser');
|
||||
$oMethod->setAccessible(true);
|
||||
return $oMethod->invoke($oLoginExternal);
|
||||
}
|
||||
|
||||
public function testGetAuthUserFromServerVariable()
|
||||
{
|
||||
$_SERVER['REMOTE_USER'] = 'alice';
|
||||
$this->oConfig->SetExternalAuthenticationVariable('$_SERVER[\'REMOTE_USER\']');
|
||||
|
||||
$this->assertSame('alice', $this->CallGetAuthUser());
|
||||
}
|
||||
|
||||
public function testGetAuthUserFromCookie()
|
||||
{
|
||||
$_COOKIE['auth_user'] = 'bob';
|
||||
$this->oConfig->SetExternalAuthenticationVariable('$_COOKIE[\'auth_user\']');
|
||||
|
||||
$this->assertSame('bob', $this->CallGetAuthUser());
|
||||
}
|
||||
|
||||
public function testGetAuthUserFromRequest()
|
||||
{
|
||||
$_REQUEST['auth_user'] = 'carol';
|
||||
$this->oConfig->SetExternalAuthenticationVariable('$_REQUEST[\'auth_user\']');
|
||||
|
||||
$this->assertSame('carol', $this->CallGetAuthUser());
|
||||
}
|
||||
|
||||
public function testInvalidExpressionReturnsFalse()
|
||||
{
|
||||
$this->oConfig->SetExternalAuthenticationVariable('$_SERVER[\'HTTP_X_CMD\']) ? print(\'x\') : false; //');
|
||||
|
||||
$this->assertFalse($this->CallGetAuthUser());
|
||||
}
|
||||
|
||||
public function testGetAuthUserFromHeaderWithoutAllowlist()
|
||||
{
|
||||
if (!function_exists('getallheaders')) {
|
||||
$this->markTestSkipped('getallheaders() not available');
|
||||
}
|
||||
$_SERVER['HTTP_X_REMOTE_USER'] = 'CN=header-test';
|
||||
$this->oConfig->SetExternalAuthenticationVariable('getallheaders()[\'X-Remote-User\']');
|
||||
|
||||
$this->assertSame('CN=header-test', $this->CallGetAuthUser());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user