mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-23 09:12:16 +02:00
Compare commits
3 Commits
support/3.
...
feature/fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b87845c844 | ||
|
|
37dd887cf1 | ||
|
|
b6cfb40f8f |
99
.doc/README.md
Normal file
99
.doc/README.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Phpdoc dokuwiki template
|
||||||
|
This directory contains a template for rendering iTop phpdoc as dokuwiki pages.
|
||||||
|
|
||||||
|
|
||||||
|
Conventional tags that you should use:
|
||||||
|
* `@internal` : exclude from the documentation.
|
||||||
|
* `@api` : it means that a method is an api, thus it may be interacted with.
|
||||||
|
* `@see` : it points to another documented method
|
||||||
|
* `@link` : external url
|
||||||
|
* if you point to another page of the wiki, please use relative links.
|
||||||
|
* `@example` : let you provide example of code
|
||||||
|
* `@param`, `@return`, `@throws`, ...
|
||||||
|
|
||||||
|
|
||||||
|
## Special instructions
|
||||||
|
|
||||||
|
Some iTop specific tags were added :
|
||||||
|
* `@api-advanced`: it means that a method is an `@api` but mark it also as "complex" to use
|
||||||
|
* `@overwritable-hook`: used to mark a method as "designed to be extended"
|
||||||
|
* `@extension-hook`: not used for now
|
||||||
|
* `@phpdoc-tuning-exclude-inherited`: once this tag is present on a class, it's inherited methods won't be showed.
|
||||||
|
|
||||||
|
|
||||||
|
### known limitations:
|
||||||
|
#### `@see` tags must be very specific:
|
||||||
|
* always prefix class members (attributes or methods) with `ClassName::` (do not use self)
|
||||||
|
* for methods always suffix them with `()`,
|
||||||
|
* do not reference variables since they are not documented. If you have to, always prefix them with `$`
|
||||||
|
|
||||||
|
examples:
|
||||||
|
```
|
||||||
|
/**
|
||||||
|
* @see DBObject
|
||||||
|
* @see DBObject::Get()
|
||||||
|
* @see DBObject::$foo
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Do not use inline tags, they do not work properly, example:
|
||||||
|
```
|
||||||
|
/**
|
||||||
|
* This is a texts with an inline tag {@see [FQSEN] [<description>]} it must never be used
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### The `@example` tag must respect this very precise syntax
|
||||||
|
* the sentence in the first line (next to the tag) is the title, it must be enclosed by double quotes
|
||||||
|
* the following lines are the sample code.
|
||||||
|
* 💔 since we simply hack the official tag, this syntax must be respected carefully 💔
|
||||||
|
example:
|
||||||
|
```
|
||||||
|
/**
|
||||||
|
* @example "This is the title of the multiline example"
|
||||||
|
* $foo = DBObject::Get('foo');
|
||||||
|
* DBObject::Set('foo', ++$foo);
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
## How content is included into the documentation
|
||||||
|
|
||||||
|
**For a class** those requirements have to be respected:
|
||||||
|
- the file containing the class must be listed in `/phpdoc/files/file[]` of `.doc/phpdoc-objects-manipulation.dist.xml`
|
||||||
|
- the class **must not** have the tag `@internal`
|
||||||
|
- the class **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||||
|
|
||||||
|
Then, **for a method** of an eligible class:
|
||||||
|
- **public** methods **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||||
|
- **protected** methods **must** have at least one of: `@overwritable-hook`, `@extension-hook`
|
||||||
|
- **private** methods are **always excluded**
|
||||||
|
|
||||||
|
**Class properties** and **constants** are never documented (this is subject to change).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## A note about the rendering engine
|
||||||
|
|
||||||
|
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
cd .doc
|
||||||
|
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generation
|
||||||
|
|
||||||
|
1. Switch to this directory : `cd /path/to/itop/.doc`
|
||||||
|
2. `composer install`
|
||||||
|
3. `./bin/build-doc-object-manipulation`
|
||||||
|
3. `./bin/build-doc-extensions`
|
||||||
|
4. Get the generated files from `/path/to/itop/data/phpdocumentor/output`
|
||||||
|
|
||||||
|
## Dokuwiki requirements
|
||||||
|
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
|
||||||
|
* the generated files have to be placed under an arbitrary directory of `[/path/to/dokuwiki]/data/pages`.
|
||||||
|
* the html has to be activated [config:htmlok](https://www.dokuwiki.org/config:htmlok)
|
||||||
|
* the generated files have to be in lowercase
|
||||||
6
.doc/bin/build-doc-extensions
Executable file
6
.doc/bin/build-doc-extensions
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh -x
|
||||||
|
|
||||||
|
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && ./vendor/bin/phpdoc -c ./phpdoc-extensions.dist.xml -vvv
|
||||||
|
|
||||||
|
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||||
|
cd ../data/phpdocumentor/output/extensions/ && for i in $(ls | grep [A-Z]); do mv -i $i $(echo $i | tr 'A-Z' 'a-z'); done
|
||||||
7
.doc/bin/build-doc-object-manipulation
Executable file
7
.doc/bin/build-doc-object-manipulation
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh -x
|
||||||
|
|
||||||
|
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf ../data/phpdocumentor/output/objects-manipulation/ && rm -rf ../data/phpdocumentor/temp/objects-manipulation/ && ./vendor/bin/phpdoc -c ./phpdoc-objects-manipulation.dist.xml -vvv
|
||||||
|
|
||||||
|
|
||||||
|
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||||
|
cd ../data/phpdocumentor/output/objects-manipulation/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
||||||
6
.doc/composer.json
Normal file
6
.doc/composer.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"require-dev": {
|
||||||
|
"phpdocumentor/phpdocumentor": "~2",
|
||||||
|
"jms/serializer": "1.7.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
3015
.doc/composer.lock
generated
Normal file
3015
.doc/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
.doc/contributing-guide/contributing-stickers-side-by-side.png
Normal file
BIN
.doc/contributing-guide/contributing-stickers-side-by-side.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
@@ -1,111 +0,0 @@
|
|||||||
# 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).
|
|
||||||
20
.doc/phpdoc-extensions.dist.xml
Executable file
20
.doc/phpdoc-extensions.dist.xml
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<phpdoc>
|
||||||
|
<title><![CDATA[iTop extensions]]></title>
|
||||||
|
|
||||||
|
<parser>
|
||||||
|
<target>../data/phpdocumentor/temp/extensions</target>
|
||||||
|
</parser>
|
||||||
|
|
||||||
|
<transformer>
|
||||||
|
<target>../data/phpdocumentor/output/extensions</target>
|
||||||
|
</transformer>
|
||||||
|
|
||||||
|
<transformations>
|
||||||
|
<template name="phpdoc-templates/combodo-wiki"/>
|
||||||
|
</transformations>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file>../application/applicationextension.inc.php</file>
|
||||||
|
</files>
|
||||||
|
</phpdoc>
|
||||||
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<phpdoc>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
The documentation of this file can be found here : https://docs.phpdoc.org/references/configuration.html
|
||||||
|
it has to be completed by the CLI parameters documentation which is more comprehensive: https://docs.phpdoc.org/references/commands/project_run.html#usage
|
||||||
|
|
||||||
|
usage:
|
||||||
|
vendor/bin/phpdoc -c phpdoc-objects-manipulation.dist.xml
|
||||||
|
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<title><![CDATA[iTop's objects manipulation API]]></title>
|
||||||
|
|
||||||
|
<parser>
|
||||||
|
<default-package-name>iTopORM</default-package-name>
|
||||||
|
<target>../data/phpdocumentor/temp/objects-manipulation</target>
|
||||||
|
<visibility>public,protected</visibility>
|
||||||
|
<markers>
|
||||||
|
<!--<item>TODO</item>-->
|
||||||
|
<!--<item>FIXME</item>-->
|
||||||
|
</markers>
|
||||||
|
<extensions>
|
||||||
|
<extension>php</extension>
|
||||||
|
</extensions>
|
||||||
|
</parser>
|
||||||
|
|
||||||
|
<transformer>
|
||||||
|
<target>../data/phpdocumentor/output/objects-manipulation</target>
|
||||||
|
</transformer>
|
||||||
|
|
||||||
|
<transformations>
|
||||||
|
<template name="phpdoc-templates/combodo-wiki"/>
|
||||||
|
</transformations>
|
||||||
|
|
||||||
|
<!--<logging>-->
|
||||||
|
<!--<level>warn</level>-->
|
||||||
|
<!--<paths>-->
|
||||||
|
<!--<!–<default>data/phpdocumentor/log/objects-manipulation/{DATE}.log</default>–>-->
|
||||||
|
<!--<!–<errors>data/phpdocumentor/log/objects-manipulation/{DATE}.errors.log</errors>–>-->
|
||||||
|
|
||||||
|
<!--<default>{APP_ROOT}/data/log/{DATE}.log</default>-->
|
||||||
|
<!--<errors>{APP_ROOT}/data/log/{DATE}.errors.log</errors>-->
|
||||||
|
<!--</paths>-->
|
||||||
|
<!--</logging>-->
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file>../core/dbobject.class.php</file>
|
||||||
|
<file>../core/dbobjectsearch.class.php</file>
|
||||||
|
<file>../core/metamodel.class.php</file>
|
||||||
|
<file>../core/dbobjectset.class.php</file>
|
||||||
|
<file>../core/dbsearch.class.php</file>
|
||||||
|
<file>../core/dbunionsearch.class.php</file>
|
||||||
|
</files>
|
||||||
|
|
||||||
|
</phpdoc>
|
||||||
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
{% extends 'layout.txt.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<wrap button>[[start|🔙 Back]]</wrap>
|
||||||
|
|
||||||
|
{% if node.tags['internal'] is defined %}
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
<WRAP alert>This class is "internal", and thus is not documented!</WRAP>
|
||||||
|
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
<WRAP alert>This class is neither "api", "api-advanced", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
|
||||||
|
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||||
|
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||||
|
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||||
|
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% if node.deprecated %}
|
||||||
|
=== **<del>Deprecated</del>**===
|
||||||
|
//{{ node.tags.deprecated[0].description }}//
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||||
|
<html>{{ node.description|markdown|raw }}</html>
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||||
|
|
||||||
|
|
||||||
|
{% set class = node.parent %}
|
||||||
|
{% block hierarchy_element %}
|
||||||
|
|
||||||
|
{% if class and class.name is defined and class.name|trim != '' %}
|
||||||
|
==== parent ====
|
||||||
|
{% set child = class %}
|
||||||
|
{% set class = class.parent %}
|
||||||
|
{{ block('hierarchy_element') }}
|
||||||
|
[[{{ child.name }}|{{ child.name }}]]
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for interface in node.interfaces|sort_asc %}
|
||||||
|
{% if loop.first %}
|
||||||
|
==== Implements ====
|
||||||
|
{% endif %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for trait in node.usedTraits|sort_asc %}
|
||||||
|
{% if loop.first %}
|
||||||
|
==== Uses traits ====
|
||||||
|
{% endif %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||||
|
|
||||||
|
{% set methods = node.inheritedMethods.merge(node.methods.merge(node.magicMethods)) %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '=====', sub_title_level: '=='} %}
|
||||||
|
|
||||||
|
<WRAP clear />
|
||||||
|
|
||||||
|
{% for method in methods|sort_asc
|
||||||
|
if method.visibility == 'public'
|
||||||
|
and (
|
||||||
|
method.tags['api'] is defined
|
||||||
|
or method.tags['api-advanced'] is defined
|
||||||
|
or method.tags['overwritable-hook'] is defined
|
||||||
|
or method.tags['extension-hook'] is defined
|
||||||
|
)
|
||||||
|
and (
|
||||||
|
node.tags['phpdoc-tuning-exclude-inherited'] is not defined
|
||||||
|
or method.parent.name == node.name
|
||||||
|
)
|
||||||
|
%}
|
||||||
|
{%- if loop.first %}
|
||||||
|
===== Public methods =====
|
||||||
|
{% endif %}
|
||||||
|
{{ block('method') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for method in methods|sort_asc if method.visibility == 'protected' and (method.tags['overwritable-hook'] is defined or method.tags['extension-hook'] is defined) %}
|
||||||
|
{%- if loop.first %}
|
||||||
|
===== Protected methods =====
|
||||||
|
{% endif %}
|
||||||
|
{{ block('method') }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||||
|
{% if constants|length > 0 %}
|
||||||
|
===== Constants =====
|
||||||
|
{% for constant in constants|sort_asc %}
|
||||||
|
{{ block('constant') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{#{% set properties = node.inheritedProperties.merge(node.properties.merge(node.magicProperties)) %}#}
|
||||||
|
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||||
|
{#{%- if loop.first %}#}
|
||||||
|
{#===== Public properties =====#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{{ block('property') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||||
|
{#{%- if loop.first %}#}
|
||||||
|
{#===== Protected properties =====#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{{ block('property') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
|
||||||
|
|
||||||
|
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||||
|
|
||||||
|
<wrap button>[[start|🔙 Back]]</wrap>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{% block constant %}
|
||||||
|
|
||||||
|
<WRAP group box >
|
||||||
|
<WRAP twothirds column >
|
||||||
|
==== {{ constant.name }} ====
|
||||||
|
</WRAP>{# twothirds column#}
|
||||||
|
|
||||||
|
<WRAP third column>
|
||||||
|
{% if constant.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||||
|
{% if (node.parent is not null and constant.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
== {{ constant.summary|replace({"\n":""})|raw }} ==
|
||||||
|
<html>{{ constant.description|markdown|raw }}</html>
|
||||||
|
|
||||||
|
{% if constant.deprecated %}
|
||||||
|
=== Deprecated ===
|
||||||
|
{{ constant.tags.deprecated[0].description|raw }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'includes/inherited-from.txt.twig' with {structure:constant} %}
|
||||||
|
|
||||||
|
{% include 'includes/see-also.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||||
|
|
||||||
|
{% include 'includes/uses.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags.txt.twig' with {structure:constant, title_level: '==', blacklist: ['link', 'see', 'var', 'deprecated', 'uses', 'package', 'subpackage', 'todo', 'code-example']} %}
|
||||||
|
|
||||||
|
</WRAP>{# group #}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
{% block method %}
|
||||||
|
|
||||||
|
|
||||||
|
<WRAP group box >
|
||||||
|
<WRAP twothirds column >
|
||||||
|
==== {{ method.name }} ====
|
||||||
|
</WRAP>{# twothirds column#}
|
||||||
|
<WRAP third column >
|
||||||
|
{% include 'includes/wrap-tags.txt.twig' with {structure:method, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||||
|
{% if method.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||||
|
{% if (node.parent is not null and method.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||||
|
{% if method.abstract %}<wrap warning>abstract</wrap> {% endif %}
|
||||||
|
{% if method.final %}<wrap notice>final</wrap> {% endif %}
|
||||||
|
<wrap notice>{{ method.visibility }}</wrap>
|
||||||
|
{% if method.static %}<wrap warning>static</wrap> {% endif %}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
|
||||||
|
== {{ method.summary|replace({"\n":""})|raw }} ==
|
||||||
|
<html>{{ method.description|markdown|raw }}</html>
|
||||||
|
|
||||||
|
<code php>{% if method.abstract %}abstract {% endif %}{% if method.final %}final {% endif %}{{ method.visibility }} {% if method.static %}static {% endif %}{{ method.name }}({% for argument in method.arguments %}{{ argument.isVariadic ? '...' }}{{ argument.name }}{{ argument.default ? (' = '~argument.default)|raw }}{% if not loop.last %}, {% endif %}{% endfor %})</code>
|
||||||
|
|
||||||
|
<WRAP twothirds column >
|
||||||
|
|
||||||
|
|
||||||
|
=== Parameters ===
|
||||||
|
{% if method.arguments|length > 0 -%}
|
||||||
|
^ types ^ name ^ default ^ description ^
|
||||||
|
{% for argument in method.arguments -%}
|
||||||
|
| **<nowiki>{{ argument.types|join('|')|raw }}</nowiki>** | {{ argument.name }} {{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }} | <nowiki>{{ argument.default|raw }}</nowiki> | {{ argument.description|trim|replace("\n", ' ')|raw }} |{{ "\r\n" }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% else %}
|
||||||
|
//none//
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{#=== Parameters ===#}
|
||||||
|
{#{% if method.arguments|length > 0 -%}#}
|
||||||
|
{#{% for argument in method.arguments -%}#}
|
||||||
|
{#== {{ argument.name }} ==#}
|
||||||
|
|
||||||
|
|
||||||
|
{#{% set varDesc %}#}
|
||||||
|
{#<span style="margin:0 10px; 0 20px; font-weight: bold;">{{ argument.types|join('|') }}</span>#}
|
||||||
|
{#{{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }}#}
|
||||||
|
{#{{ argument.description|raw }}#}
|
||||||
|
{#{% endset %}#}
|
||||||
|
{#<html>{{ varDesc|markdown|raw }}</html>#}
|
||||||
|
{#{%- endfor %}#}
|
||||||
|
{#{% else %}#}
|
||||||
|
{#<wrap tip>This method has no parameter</wrap>#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
|
||||||
|
|
||||||
|
{% if method.response and method.response.types|join() != 'void' %}
|
||||||
|
=== Returns ===
|
||||||
|
<html>{{ ('**' ~ method.response.types|join('|')|trim ~ '** ' ~ method.response.description)|markdown|raw }}</html>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</WRAP>{# twothirds column#}
|
||||||
|
|
||||||
|
<WRAP third column >
|
||||||
|
|
||||||
|
{% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %}
|
||||||
|
=== Throws ===
|
||||||
|
{% for exception in method.tags.throws -%}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}''{{ exception.types|join('|')|raw }}'' <nowiki>{{ exception.description|raw }}</nowiki>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'includes/inherited-from.txt.twig' with {structure:method} %}
|
||||||
|
|
||||||
|
{% include 'includes/see-also.txt.twig' with {structure:method, title_level: '==='} %}
|
||||||
|
|
||||||
|
{% include 'includes/uses.txt.twig' with {structure:method, title_level: '==='} %}
|
||||||
|
|
||||||
|
{% include 'includes/used-by.txt.twig' with {structure:method, title_level: '==='} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags-with-description.txt.twig' with {structure:method, title_level: '===', WRAP: 'info', tagsWithDescription: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags.txt.twig' with {structure:method, title_level: '===', blacklist: ['todo', 'link', 'see', 'abstract', 'example', 'param', 'return', 'access', 'deprecated', 'throws', 'throw', 'uses', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'used-by', 'inheritdoc', 'code-example']} %}
|
||||||
|
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/code-examples.txt.twig' with {structure:method, title_level: '==='} %}
|
||||||
|
|
||||||
|
</WRAP>{# group #}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
{% block property %}
|
||||||
|
|
||||||
|
<WRAP group box>
|
||||||
|
<WRAP twothirds column >
|
||||||
|
==== ${{ property.name }} ====
|
||||||
|
</WRAP>{# twothirds column#}
|
||||||
|
|
||||||
|
<WRAP third column>
|
||||||
|
{% if property.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||||
|
{% if (node.parent is not null and property.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== {{ property.summary|replace({"\n":""})|raw }} ==
|
||||||
|
<html>{{ property.description|markdown|raw }}</html>
|
||||||
|
{% if property.var.0.description %}<html>{{ property.var.0.description|markdown|raw }}</html>{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{#{% if property.types %}#}
|
||||||
|
{#== Type ==#}
|
||||||
|
{#{% for type in property.types %}#}
|
||||||
|
{#{% if loop.length > 1 %} * {% endif %}{{ type|raw }} : {{ type.description|raw }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{{ property.types|join('|')|raw }}#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
|
||||||
|
|
||||||
|
{% if property.deprecated %}
|
||||||
|
== Deprecated ==
|
||||||
|
{{ property.tags.deprecated[0].description }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include 'includes/inherited-from.txt.twig' with {structure:property} %}
|
||||||
|
|
||||||
|
{% include 'includes/see-also.txt.twig' with {structure:property, title_level: '=='} %}
|
||||||
|
|
||||||
|
{% include 'includes/uses.txt.twig' with {structure:property, title_level: ''} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags.txt.twig' with {structure:property, title_level: '==', blacklist: ['link', 'see', 'access', 'var', 'deprecated', 'uses', 'todo', 'code-example']} %}
|
||||||
|
|
||||||
|
|
||||||
|
<code php>{{ property.visibility }} ${{ property.name }}{% if property.types %} : {{ property.types|join('|')|raw }}{% endif %}</code>
|
||||||
|
|
||||||
|
</WRAP>{# group #}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{{ node.source|raw }}
|
||||||
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
{% extends 'layout.txt.twig' %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{#<section class="row-fluid">#}
|
||||||
|
{#<div class="span2 sidebar">#}
|
||||||
|
{#{% set namespace = project.namespace %}#}
|
||||||
|
{#{{ block('sidebarNamespaces') }}#}
|
||||||
|
{#</div>#}
|
||||||
|
{#</section>#}
|
||||||
|
{#<section class="row-fluid">#}
|
||||||
|
====== {{ node.path|split('/')|slice(0,-1)|join('/') }}{{ node.name }} ======
|
||||||
|
{{ node.summary }}
|
||||||
|
<html>{{ node.description|markdown|raw }}</html>
|
||||||
|
|
||||||
|
{% if node.traits|length > 0 %}
|
||||||
|
|
||||||
|
===== Traits =====
|
||||||
|
{% for trait in node.traits %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ trait|raw }}</td>
|
||||||
|
<td><em>{{ trait.summary }}</em></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{% if node.interfaces|length > 0 %}
|
||||||
|
===== Interfaces =====
|
||||||
|
{% for interface in node.interfaces %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ interface|raw }}</td>
|
||||||
|
<td><em>{{ interface.summary }}</em></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if node.classes|length > 0 %}
|
||||||
|
===== Classes =====
|
||||||
|
{% for class in node.classes %}
|
||||||
|
{{ class|raw }}
|
||||||
|
<em>{{ class.summary }}</em>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if node.package is not empty and node.package != '\\' %}
|
||||||
|
===== Package =====
|
||||||
|
{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
|
||||||
|
{% if loop.first %}
|
||||||
|
===== See also =====
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in tags %}
|
||||||
|
<dd><a href="{{ tag.reference ?: tag.link }}"><div class="namespace-wrapper">{{ tag.description ?: tag.reference }}</div></a></dd>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<h2>Tags</h2>
|
||||||
|
<table class="table table-condensed">
|
||||||
|
{% for tagName,tags in node.tags if tagName not in ['link', 'see', 'package', 'subpackage'] %}
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{{ tagName }}
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{% for tag in tags %}
|
||||||
|
{{ tag.description|markdown|raw }}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr><td colspan="2"><em>None found</em></td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if node.constants|length > 0 %}
|
||||||
|
<div class="row-fluid">
|
||||||
|
<section class="span8 content file">
|
||||||
|
<h2>Constants</h2>
|
||||||
|
</section>
|
||||||
|
<aside class="span4 detailsbar"></aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for constant in node.constants %}
|
||||||
|
{{ block('constant') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if node.functions|length > 0 %}
|
||||||
|
<div class="row-fluid">
|
||||||
|
<section class="span8 content file">
|
||||||
|
<h2>Functions</h2>
|
||||||
|
</section>
|
||||||
|
<aside class="span4 detailsbar"></aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for method in node.functions %}
|
||||||
|
{{ block('method') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h3 id="source-view-label">{{ node.file.name }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<pre data-src="{{ path('files/' ~ node.path ~ '.txt')|raw }}" class="language-php line-numbers"></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{% extends 'layout.html.twig' %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
<link href="{{ path('css/jquery.iviewer.css') }}" rel="stylesheet" media="all"/>
|
||||||
|
<style>
|
||||||
|
#viewer {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="{{ path('js/jquery.mousewheel.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ path('js/jquery.iviewer.js') }}" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(window).resize(function(){
|
||||||
|
$("#viewer").height($(window).height() - 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
|
||||||
|
$('#viewer img').bind('dragstart', function(event){
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
$(window).resize();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
<div class="wrapper">
|
||||||
|
<div id="viewer" class="viewer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Fixes a vulnerability in CentOS: http://stackoverflow.com/questions/20533279/prevent-php-from-parsing-non-php-files-such-as-somefile-php-txt
|
||||||
|
<FilesMatch \.php\.txt$>
|
||||||
|
RemoveHandler .php
|
||||||
|
ForceType text/plain
|
||||||
|
</FilesMatch>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{%- set title_level = '==' -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if sub_title_level is not defined %}
|
||||||
|
{%- set sub_title_level = title_level|slice(1) -%}
|
||||||
|
{% endif %}
|
||||||
|
{% if sub_title_level == '=' %}
|
||||||
|
{%- set sub_title_level = '' -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{#{% for tagName,tags in structure.tags if tagName in ['code-example'] %}#}
|
||||||
|
{#{% if loop.first %}#}
|
||||||
|
{#{{title_level}} Examples {{title_level}}#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{% for tag in tags %}#}
|
||||||
|
{#{%- set descToken = tag.description|split("\n", 2) -%}#}
|
||||||
|
{#{%- set title = descToken[0] -%}#}
|
||||||
|
{#{%- set code = descToken[1] -%}#}
|
||||||
|
{#{{sub_title_level}} {{ title }} {{sub_title_level}}#}
|
||||||
|
{#<code php>{{ code|raw }}</code>#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
|
||||||
|
|
||||||
|
{% for tagName,tags in structure.tags if tagName in ['example'] %}
|
||||||
|
{% if loop.first %}
|
||||||
|
{{title_level}} Examples {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in tags %}
|
||||||
|
{{ sub_title_level }} {{ tag.filePath|escape }}{{ sub_title_level }}
|
||||||
|
<code php>{{ tag.description|raw }}</code>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{% set title_level='' %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if (node.parent is null) %}
|
||||||
|
{{title_level}} File {{ structure.path }} {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
|
||||||
|
{{title_level}} Inherited from {{title_level}}
|
||||||
|
[[{{structure.parent}}|{{structure.parent}}]]
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{% for structure in structures|sort_asc if structure.tags['internal'] is not defined and (structure.tags['api'] is defined or structure.tags['api-advanced'] is defined or structure.tags['overwritable-hook'] is defined or structure.tags['extension-hook'] is defined ) %}
|
||||||
|
{#{{ structure|raw }}#}
|
||||||
|
|
||||||
|
{% set structureName = structure|trim('\\', 'left') %}
|
||||||
|
|
||||||
|
<WRAP group box>
|
||||||
|
<WRAP twothirds column >
|
||||||
|
==== {{ structureName }} ====
|
||||||
|
</WRAP>{# twothirds column#}
|
||||||
|
|
||||||
|
<WRAP third column>
|
||||||
|
{% if structure.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||||
|
{% if structure.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||||
|
{% if structure.final %}<wrap notice>final</wrap>{% endif %}
|
||||||
|
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||||
|
{% include 'includes/wrap-tags.txt.twig' with {structure:structure, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
|
||||||
|
{{ structure.summary|raw }}
|
||||||
|
[[{{structureName}}|More information]]
|
||||||
|
|
||||||
|
</WRAP>{# group #}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{%- set title_level='==' -%}
|
||||||
|
{% endif %}
|
||||||
|
{% for tagName,tags in structure.tags if tagName in ['link', 'see'] %}
|
||||||
|
{% if loop.first %}
|
||||||
|
{{title_level}} See also {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in tags %}
|
||||||
|
{%- set linkTag = tag.reference|trim('\\', 'left') -%}
|
||||||
|
{% if not('()' in linkTag or '$' in linkTag or node.name in linkTag or '::' in linkTag ) %}
|
||||||
|
{%- set linkTag = linkTag|lower -%}
|
||||||
|
{% elseif node.name~'::' in linkTag %}
|
||||||
|
{%- set linkTag = linkTag|replace({(node.name~'::'): '#'})|lower -%}
|
||||||
|
{% elseif '::' in linkTag -%}
|
||||||
|
{%- set linkTag = linkTag|replace({'::': '#'})|lower -%}
|
||||||
|
{% else %}
|
||||||
|
{%- set linkTag = '#' ~ linkTag|lower -%}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{% if tag.reference is not empty -%}
|
||||||
|
[[{{linkTag}}|{{ (tag.reference)|trim('\\', 'left') }}]] {% if tag.description|trim is not empty %}: {{ tag.description|trim('\\', 'left') }} {% endif %}
|
||||||
|
{%- else -%}
|
||||||
|
{#{{ tag.description|trim('\\', 'left') }}#}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{% if tag is not defined -%}
|
||||||
|
{# Do not display @api if @api-advanced is also present #}
|
||||||
|
{%- set tag = "api" -%}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{% if hidden_by is not defined -%}
|
||||||
|
{# Do not display @api if @api-advanced is also present #}
|
||||||
|
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% for method in methods|sort_asc
|
||||||
|
if (method.visibility == 'public')
|
||||||
|
and (
|
||||||
|
method.tags[tag] is defined
|
||||||
|
and (
|
||||||
|
hidden_by[tag] is not defined or method.tags[hidden_by[tag]] is not defined
|
||||||
|
)
|
||||||
|
)
|
||||||
|
%}
|
||||||
|
{%- if loop.first %}
|
||||||
|
{% if tag == 'api' %}
|
||||||
|
===== API synthesis =====
|
||||||
|
<WRAP>
|
||||||
|
List of the public API methods.
|
||||||
|
When manipulating {{ node.name }}, You can call those methods:
|
||||||
|
</WRAP>
|
||||||
|
{% elseif tag == 'api-advanced' %}
|
||||||
|
===== Advanced API synthesis =====
|
||||||
|
<WRAP>
|
||||||
|
List of advanced API methods
|
||||||
|
Beware they usage is recommended to advanced users only.
|
||||||
|
</WRAP>
|
||||||
|
{% elseif tag == 'overwritable-hook' %}
|
||||||
|
===== overwritable-hook synthesis =====
|
||||||
|
<WRAP >When inheriting from {{ node.name }},
|
||||||
|
you can overwrite those methods in order to add custom logic:
|
||||||
|
</WRAP>
|
||||||
|
{% elseif tag == 'extension-hook' %}
|
||||||
|
===== extension-hook synthesis =====
|
||||||
|
<WRAP >
|
||||||
|
When inheriting from {{ node.name }},
|
||||||
|
you can extend the behaviour of iTop by implementing:
|
||||||
|
</WRAP>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% set sanitizedMethod = method|trim('\\', 'left')|replace({(node.name~'::'): ''}) %}
|
||||||
|
{% if '::' in sanitizedMethod -%}
|
||||||
|
{%- if node.tags['phpdoc-tuning-exclude-inherited'] is not defined %}
|
||||||
|
* [[{{sanitizedMethod|replace({'::': '#'})|lower}}|↪{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{%- else %}
|
||||||
|
* [[#{{sanitizedMethod}}|{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{% set title_level = '==' %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{%- for tagName,tags in structure.tags if tagName in tagsWithDescription -%}
|
||||||
|
{%- for tag in tags -%}
|
||||||
|
{%- if tag.description is not empty -%}
|
||||||
|
{%- if WRAP is defined -%}
|
||||||
|
<WRAP {{WRAP}}>
|
||||||
|
{%- endif -%}
|
||||||
|
{{title_level}} {{ tagName }} {{title_level}}
|
||||||
|
{{ tag.description|escape }}
|
||||||
|
{%- if WRAP is defined -%}
|
||||||
|
</WRAP>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
|
||||||
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{% set title_level='=====' %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if blacklist is not defined %}
|
||||||
|
{% set blacklist =['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'api', 'api-advanced', 'todo', 'code-example'] %}
|
||||||
|
{% endif %}
|
||||||
|
{% if hidden_by is not defined -%}
|
||||||
|
{# Do not display @api if @api-advanced is also present #}
|
||||||
|
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{#^ {% for tagName,tags in structure.tags if tagName not in blacklist -%}#}
|
||||||
|
{#{{ tagName }} ^#}
|
||||||
|
{#{%- endfor %}#}
|
||||||
|
|
||||||
|
{% for tagName,tags in structure.tags if tagName not in blacklist and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||||
|
{%- if loop.first %}
|
||||||
|
{{title_level}} Tags {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
^ {{ tagName }} | {% for tag in tags %}{{ tag.version ? tag.version ~ ' ' : '' }}{{ tag.description}}{% endfor %} |
|
||||||
|
{% endfor %}
|
||||||
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{% set title_level='' %}
|
||||||
|
{% endif %}
|
||||||
|
{% for tagName,tags in structure.tags if tagName in ['used-by'] %}
|
||||||
|
{% if loop.first %}
|
||||||
|
{{title_level}} Used by {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in tags %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||||
|
{#{% if loop.first %}#}
|
||||||
|
{#<dt>Uses</dt>#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{% for tag in tags %}#}
|
||||||
|
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{% if title_level is not defined %}
|
||||||
|
{% set title_level='' %}
|
||||||
|
{% endif %}
|
||||||
|
{% for tagName,tags in structure.tags if tagName in ['uses'] %}
|
||||||
|
{% if loop.first %}
|
||||||
|
{{title_level}} Uses {{title_level}}
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in tags %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||||
|
{#{% if loop.first %}#}
|
||||||
|
{#<dt>Uses</dt>#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{% for tag in tags %}#}
|
||||||
|
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{% if wrap is not defined -%}
|
||||||
|
{% set wrap = 'notice' %}
|
||||||
|
{%- endif -%}
|
||||||
|
{% if hidden_by is not defined -%}
|
||||||
|
{# Do not display @api if @api-advanced is also present #}
|
||||||
|
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{%- for tagName,tags in structure.tags if tagName in wrapTags and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||||
|
<wrap {{wrap}}>{{tagName}}</wrap>
|
||||||
|
{% endfor %}
|
||||||
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
{% extends 'layout.txt.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<wrap button>[[start|🔙 Back]]</wrap>
|
||||||
|
|
||||||
|
{% if node.tags['internal'] is defined %}
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
<WRAP alert>This interface is "internal", and thus is not documented!</WRAP>
|
||||||
|
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
<WRAP alert>This interface is neither "api", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
====== {{ node.name }} ======
|
||||||
|
|
||||||
|
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||||
|
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||||
|
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||||
|
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% if node.deprecated %}
|
||||||
|
=== **<del>Deprecated</del>**===
|
||||||
|
//{{ node.tags.deprecated[0].description }}//
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||||
|
<html>{{ node.description|markdown|raw }}</html>
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||||
|
|
||||||
|
|
||||||
|
{% set class = node.parent %}
|
||||||
|
{% block hierarchy_element %}
|
||||||
|
|
||||||
|
{% if class and class.name is defined and class.name|trim != '' %}
|
||||||
|
==== parent ====
|
||||||
|
{% set child = class %}
|
||||||
|
{% set class = class.parent %}
|
||||||
|
{{ block('hierarchy_element') }}
|
||||||
|
[[{{ child.name }}|{{ child.name }}]]
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for interface in node.interfaces|sort_asc %}
|
||||||
|
{% if loop.first %}
|
||||||
|
==== Implements ====
|
||||||
|
{% endif %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for trait in node.usedTraits|sort_asc %}
|
||||||
|
{% if loop.first %}
|
||||||
|
==== Uses traits ====
|
||||||
|
{% endif %}
|
||||||
|
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||||
|
|
||||||
|
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||||
|
|
||||||
|
|
||||||
|
{% set methods = node.inheritedMethods.merge(node.methods) %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||||
|
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||||
|
|
||||||
|
<WRAP clear />
|
||||||
|
|
||||||
|
|
||||||
|
{% for method in methods|sort_asc if method.visibility == 'public' %}
|
||||||
|
{%- if loop.first %}
|
||||||
|
===== Public methods =====
|
||||||
|
{% endif %}
|
||||||
|
{{ block('method') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for method in methods|sort_asc if method.visibility == 'protected' %}
|
||||||
|
{%- if loop.first %}
|
||||||
|
===== Protected methods =====
|
||||||
|
{% endif %}
|
||||||
|
{{ block('method') }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||||
|
{% if constants|length > 0 %}
|
||||||
|
===== Constants =====
|
||||||
|
{% for constant in constants|sort_asc %}
|
||||||
|
{{ block('constant') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{#{% set properties = node.inheritedProperties.merge(node.properties) %}#}
|
||||||
|
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||||
|
{#{%- if loop.first %}#}
|
||||||
|
{#===== Public properties =====#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{{ block('property') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||||
|
{#{%- if loop.first %}#}
|
||||||
|
{#===== Protected properties =====#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{{ block('property') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
|
||||||
|
|
||||||
|
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||||
|
|
||||||
|
<wrap button>[[start|🔙 Back]]</wrap>
|
||||||
|
{% endblock %}
|
||||||
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{% use 'elements/constant.txt.twig' %}
|
||||||
|
{% use 'elements/property.txt.twig' %}
|
||||||
|
{% use 'elements/method.txt.twig' %}
|
||||||
|
|
||||||
|
{% block content %}{% endblock %}
|
||||||
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{% extends 'layout.txt.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% set namespace = project.namespace %}
|
||||||
|
{{ block('sidebarNamespaces') }}
|
||||||
|
|
||||||
|
{#{{ node.parent|raw }}#}
|
||||||
|
{#====== {{ node.parent.fullyQualifiedStructuralElementName }}{{ node.name }} ======#}
|
||||||
|
|
||||||
|
{% if node.children|length > 0 %}
|
||||||
|
=====Namespaces=====
|
||||||
|
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.children} %}
|
||||||
|
----
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if node.traits|length > 0 %}
|
||||||
|
===== Traits =====
|
||||||
|
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.traits} %}
|
||||||
|
----
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{% if node.interfaces|length > 0 %}
|
||||||
|
===== Interfaces =====
|
||||||
|
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.interfaces} %}
|
||||||
|
----
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if node.classes|length > 0 %}
|
||||||
|
===== Classes =====
|
||||||
|
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.classes} %}
|
||||||
|
----
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{#{% if node.constants|length > 0 %}#}
|
||||||
|
{#===== Constants =====#}
|
||||||
|
{#{% for constant in node.constants|sort_asc %}#}
|
||||||
|
{# {{ block('constant') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
|
||||||
|
{#{% if node.functions|length > 0 %}#}
|
||||||
|
{#===== Functions =====#}
|
||||||
|
|
||||||
|
{#{% for method in node.functions|sort_asc %}#}
|
||||||
|
{# {{ block('method') }}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
====== Deprecated elements ======
|
||||||
|
|
||||||
|
{#{% for element in project.indexes.elements if element.deprecated %}#}
|
||||||
|
{#{% if element.file.path != previousPath %}#}
|
||||||
|
{#<li><a href="#{{ element.file.path }}"><i class="icon-file"></i> {{ element.file.path }}</a></li>#}
|
||||||
|
{#{% endif %}#}
|
||||||
|
{#{% set previousPath = element.file.path %}#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
|
||||||
|
{% for element in project.indexes.elements if element.deprecated %}
|
||||||
|
{% if element.file.path != previousPath %}
|
||||||
|
{% if previousPath %}
|
||||||
|
</WRAP>{# group #}
|
||||||
|
{% endif %}
|
||||||
|
{#<a name="{{ element.file.path }}" id="{{ element.file.path }}"></a>#}
|
||||||
|
===== {{ element.file.path }} ({{ element.tags.deprecated.count }} found)=====
|
||||||
|
|
||||||
|
<WRAP group >
|
||||||
|
<WRAP third column >
|
||||||
|
Element
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
<WRAP third column >
|
||||||
|
Line
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
<WRAP third column >
|
||||||
|
Description
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% for tag in element.tags.deprecated %}
|
||||||
|
<WRAP group >
|
||||||
|
<WRAP third column >
|
||||||
|
{{ element.fullyQualifiedStructuralElementName }}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
<WRAP third column >
|
||||||
|
{{ element.line }}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
<WRAP third column >
|
||||||
|
{{ tag.description }}
|
||||||
|
</WRAP>{# third column#}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</WRAP>{# group #}
|
||||||
|
{% set previousPath = element.file.path %}
|
||||||
|
{% else %}
|
||||||
|
<WRAP info>No deprecated elements have been found in this project.</WRAP>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<template>
|
||||||
|
<author>Bruno DA SILVA</author>
|
||||||
|
<email>contact [at] combodo.com</email>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<copyright>Combodo 2018</copyright>
|
||||||
|
<description><![CDATA[
|
||||||
|
|
||||||
|
Forked from the clean theme of https://github.com/phpDocumentor/phpDocumentor2 provided under the MIT licence.
|
||||||
|
The original work is copyright "Mike van Riel".
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
To improve performance you can add the following to your .htaccess:
|
||||||
|
|
||||||
|
<ifModule mod_deflate.c>
|
||||||
|
<filesMatch "\.(js|css|html)$">
|
||||||
|
SetOutputFilter DEFLATE
|
||||||
|
</filesMatch>
|
||||||
|
</ifModule>
|
||||||
|
]]></description>
|
||||||
|
<transformations>
|
||||||
|
<transformation writer="twig" query="namespace" source="templates/combodo-wiki/namespace.txt.twig" artifact="start.txt"/>
|
||||||
|
<transformation writer="twig" query="indexes.classes" source="templates/combodo-wiki/class.txt.twig" artifact="{{name}}.txt"/>
|
||||||
|
<transformation writer="twig" query="indexes.interfaces" source="templates/combodo-wiki/interface.txt.twig" artifact="{{name}}.txt" />
|
||||||
|
</transformations>
|
||||||
|
</template>
|
||||||
48
.gitattributes
vendored
48
.gitattributes
vendored
@@ -1,48 +0,0 @@
|
|||||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
|
||||||
* text=auto
|
|
||||||
|
|
||||||
# Explicitly declare text files you want to always be normalized and converted
|
|
||||||
# to native line endings on checkout.
|
|
||||||
*.bash text eol=lf
|
|
||||||
*.bat text eol=lf
|
|
||||||
*.cmd text eol=lf
|
|
||||||
*.css text eol=lf
|
|
||||||
*.scss text eol=lf
|
|
||||||
*.dist text eol=lf
|
|
||||||
.editorconfig text eol=lf
|
|
||||||
.env* text eol=lf
|
|
||||||
.gitignore text eol=lf
|
|
||||||
.htaccess text eol=lf
|
|
||||||
*.htm text eol=lf
|
|
||||||
*.html text eol=lf
|
|
||||||
*.ini text eol=lf
|
|
||||||
*.js text eol=lf
|
|
||||||
*.json text eol=lf
|
|
||||||
*.lock text eol=lf
|
|
||||||
*.md text eol=lf
|
|
||||||
*.php text eol=lf
|
|
||||||
*.php_cs text eol=lf
|
|
||||||
*.php8 text eol=lf
|
|
||||||
*.plex text eol=lf
|
|
||||||
*.sh text eol=lf
|
|
||||||
*.svg text eol=lf
|
|
||||||
*.ts text eol=lf
|
|
||||||
*.twig text eol=lf
|
|
||||||
*.txt text eol=lf
|
|
||||||
*.xml text eol=lf
|
|
||||||
*.xsd text eol=lf
|
|
||||||
*.yaml text eol=lf
|
|
||||||
*.yml text eol=lf
|
|
||||||
|
|
||||||
# Denote all files that are truly binary and should not be modified.
|
|
||||||
*.png binary
|
|
||||||
*.jpeg binary
|
|
||||||
*.jpg binary
|
|
||||||
*.gif binary
|
|
||||||
*.ico binary
|
|
||||||
*.pdf binary
|
|
||||||
*.swf binary
|
|
||||||
*.zip binary
|
|
||||||
*.ttf binary
|
|
||||||
*.woff binary
|
|
||||||
*.woff2 binary
|
|
||||||
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,59 +0,0 @@
|
|||||||
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
54
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
@@ -1,54 +0,0 @@
|
|||||||
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"
|
|
||||||
76
.github/pull_request_template.md
vendored
76
.github/pull_request_template.md
vendored
@@ -1,76 +0,0 @@
|
|||||||
<!--
|
|
||||||
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.
|
|
||||||
|
|
||||||
Once you've done it, and we confirmed we're interested in it, please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
|
|
||||||
|
|
||||||
Any PRs not following the guidelines or with missing information will not be considered.
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Base information
|
|
||||||
|
|
||||||
| Question | Answer |
|
|
||||||
|---------------------------------------------------------------------------------|--------------------------------------|
|
|
||||||
| Related to a SourceForge thread / Another PR / 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 many details as possible.
|
|
||||||
- Add screenshots if it's related to UI.
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Reproduction procedure (bug)
|
|
||||||
|
|
||||||
<!--
|
|
||||||
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) -->
|
|
||||||
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 without digging in the code?
|
|
||||||
53
.github/workflows/action.yml
vendored
53
.github/workflows/action.yml
vendored
@@ -1,53 +0,0 @@
|
|||||||
name: Add PRs to Combodo PRs Dashboard
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add-to-project:
|
|
||||||
name: Add PR to Combodo Project
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check if author is a member of the organization
|
|
||||||
id: check-membership
|
|
||||||
run: |
|
|
||||||
ORG="Combodo"
|
|
||||||
AUTHOR=$(jq -r .pull_request.user.login "$GITHUB_EVENT_PATH")
|
|
||||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
|
||||||
"https://api.github.com/orgs/$ORG/members/$AUTHOR")
|
|
||||||
if [ "$RESPONSE" == "404" ]; then
|
|
||||||
echo "project_url=https://github.com/orgs/Combodo/projects/5" >> $GITHUB_ENV
|
|
||||||
echo "is_member=false" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "project_url=https://github.com/orgs/Combodo/projects/4" >> $GITHUB_ENV
|
|
||||||
echo "is_member=true" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Add internal tag if member of the organization
|
|
||||||
if: env.is_member == 'true'
|
|
||||||
run: |
|
|
||||||
curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
|
||||||
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/labels \
|
|
||||||
-d '{"labels":["internal"]}'
|
|
||||||
|
|
||||||
- name: Set PR author as assignee if member of the organization
|
|
||||||
if: env.is_member == 'true'
|
|
||||||
run: |
|
|
||||||
curl -L \
|
|
||||||
-X POST \
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-H "Authorization: Bearer ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
|
|
||||||
https://api.github.com/repos/Combodo/iTop/issues/${{ github.event.pull_request.number }}/assignees \
|
|
||||||
-d '{"assignees":["${{ github.event.pull_request.user.login }}"]}'
|
|
||||||
env:
|
|
||||||
is_member: ${{ env.is_member }}
|
|
||||||
|
|
||||||
- name: Add PR to the appropriate project
|
|
||||||
uses: actions/add-to-project@v1.0.2
|
|
||||||
with:
|
|
||||||
project-url: ${{ env.project_url }}
|
|
||||||
github-token: ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}
|
|
||||||
26
.gitignore
vendored
26
.gitignore
vendored
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
# composer reserver directory, from sources, populate/update using "composer install"
|
# composer reserver directory, from sources, populate/update using "composer install"
|
||||||
vendor/*
|
vendor/*
|
||||||
tests/*/vendor/*
|
test/vendor/*
|
||||||
|
|
||||||
# all conf but listing prevention
|
# all conf but listing prevention
|
||||||
/conf/**
|
/conf/**
|
||||||
@@ -37,9 +37,7 @@ tests/*/vendor/*
|
|||||||
|
|
||||||
# iTop extensions
|
# iTop extensions
|
||||||
/extensions/**
|
/extensions/**
|
||||||
!/extensions/.htaccess
|
|
||||||
!/extensions/readme.txt
|
!/extensions/readme.txt
|
||||||
!/extensions/web.config
|
|
||||||
|
|
||||||
# all logs but listing prevention
|
# all logs but listing prevention
|
||||||
/log/**
|
/log/**
|
||||||
@@ -47,24 +45,9 @@ tests/*/vendor/*
|
|||||||
!/log/index.php
|
!/log/index.php
|
||||||
!/log/web.config
|
!/log/web.config
|
||||||
|
|
||||||
# NPM: `jquery-ui` package is just there for vulnerability scans, so we don't want to version its files (only `jquery-ui-dist` is used within the code base)
|
|
||||||
/node_modules/jquery-ui/**
|
|
||||||
|
|
||||||
# Symfony: Local env file
|
|
||||||
/resources/symfony/.env.local
|
|
||||||
|
|
||||||
# PHPUnit: Cache file, local XML working copies
|
|
||||||
/tests/php-unit-tests/.phpunit.result.cache
|
|
||||||
/tests/php-unit-tests/phpunit.xml
|
|
||||||
/tests/php-unit-tests/postbuild_integration.xml
|
|
||||||
|
|
||||||
# PHP CS Fixer: Cache file
|
|
||||||
/.php-cs-fixer.cache
|
|
||||||
|
|
||||||
|
|
||||||
# Jetbrains
|
# Jetbrains
|
||||||
/.idea/**
|
/.idea/**
|
||||||
!/.idea/IntelliLang.xml
|
|
||||||
|
|
||||||
# doc. generation
|
# doc. generation
|
||||||
/.doc/vendor
|
/.doc/vendor
|
||||||
@@ -159,10 +142,3 @@ local.properties
|
|||||||
.cache-main
|
.cache-main
|
||||||
.scala_dependencies
|
.scala_dependencies
|
||||||
.worksheet
|
.worksheet
|
||||||
|
|
||||||
# Mac
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Windows
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
|
|||||||
15
.idea/IntelliLang.xml
generated
15
.idea/IntelliLang.xml
generated
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="LanguageInjectionConfiguration">
|
|
||||||
<injection language="InjectablePHP" injector-id="xml">
|
|
||||||
<display-name>iTop - Class method code</display-name>
|
|
||||||
<place><![CDATA[xmlTag().withLocalName(string().equalTo("code"))]]></place>
|
|
||||||
<xpath-condition>name(..) = 'method' and count(/itop_design) = 1</xpath-condition>
|
|
||||||
</injection>
|
|
||||||
<injection language="InjectablePHP" injector-id="xml">
|
|
||||||
<display-name>iTop - Snippet code</display-name>
|
|
||||||
<place><![CDATA[xmlTag().withLocalName(string().equalTo("snippet"))]]></place>
|
|
||||||
<xpath-condition>name(..) = 'snippets' and count(/itop_design) = 1</xpath-condition>
|
|
||||||
</injection>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -4,7 +4,7 @@ $iBeginTime = time();
|
|||||||
chdir(__DIR__);
|
chdir(__DIR__);
|
||||||
|
|
||||||
$aCommands = [
|
$aCommands = [
|
||||||
'php composer/rmUnnecessaryFolders.php',
|
'php composer/rmDeniedTestDir.php',
|
||||||
'php build/commands/setupCssCompiler.php',
|
'php build/commands/setupCssCompiler.php',
|
||||||
// 'bash /tmp/gabuzomeu.sh',
|
// 'bash /tmp/gabuzomeu.sh',
|
||||||
];
|
];
|
||||||
@@ -22,13 +22,13 @@ $iElapsed = time() - $iBeginTime;
|
|||||||
|
|
||||||
if (count($aFailedCommands))
|
if (count($aFailedCommands))
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "\nafterBuild execution failed! (in {$iElapsed}s)\n");
|
fwrite(STDERR, "\nafterBuild execution failed! (in ${iElapsed}s)\n");
|
||||||
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
|
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
echo "\nDone ({$iElapsed}s)\n";
|
echo "\nDone (${iElapsed}s)\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +74,7 @@ function ExecCommand($cmd) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
echo "| elapsed:{$iElapsed}s \n";
|
echo "| elapsed:${iElapsed}s \n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($stderr))
|
if (!empty($stderr))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2010-2024 Combodo SAS
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -27,7 +27,7 @@ $iTopFolder = __DIR__."/../../../";
|
|||||||
require_once("$iTopFolder/approot.inc.php");
|
require_once("$iTopFolder/approot.inc.php");
|
||||||
require_once(APPROOT."/application/utils.inc.php");
|
require_once(APPROOT."/application/utils.inc.php");
|
||||||
|
|
||||||
if (PHP_SAPI !== 'cli')
|
if (php_sapi_name() !== 'cli')
|
||||||
{
|
{
|
||||||
throw new \Exception('This script can only run from CLI');
|
throw new \Exception('This script can only run from CLI');
|
||||||
}
|
}
|
||||||
@@ -48,4 +48,4 @@ if (!file_exists($sCssFile))
|
|||||||
{
|
{
|
||||||
fwrite(STDERR, "Failed to compile $sCssFile, exiting.");
|
fwrite(STDERR, "Failed to compile $sCssFile, exiting.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2010-2024 Combodo SAS
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -19,23 +19,16 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
$iTopFolder = __DIR__ . "/../../" ;
|
||||||
* Alias for `composer show -loD`
|
|
||||||
* You can also use `composer outdated -D`
|
|
||||||
*
|
|
||||||
* @link https://getcomposer.org/doc/03-cli.md#show
|
|
||||||
*/
|
|
||||||
|
|
||||||
$iTopFolder = __DIR__."/../../../";
|
require_once ("$iTopFolder/approot.inc.php");
|
||||||
|
|
||||||
require_once("$iTopFolder/approot.inc.php");
|
|
||||||
$sApproot = APPROOT;
|
$sApproot = APPROOT;
|
||||||
$aTrace = array();
|
$aTrace = array();
|
||||||
|
|
||||||
$aParamsConfig = array(
|
$aParamsConfig = array(
|
||||||
'composer-path' => array(
|
'composer-path' => array(
|
||||||
'default' => 'composer',
|
'default' => 'composer.phar',
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
$aParamsConfigNotFound = array_flip(array_keys($aParamsConfig));
|
$aParamsConfigNotFound = array_flip(array_keys($aParamsConfig));
|
||||||
$aGivenArgs = $argv;
|
$aGivenArgs = $argv;
|
||||||
63
.make/composer/rmDeniedTestDir.php
Normal file
63
.make/composer/rmDeniedTestDir.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
*
|
||||||
|
* 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/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Composer\iTopComposer;
|
||||||
|
|
||||||
|
$iTopFolder = __DIR__ . "/../../" ;
|
||||||
|
|
||||||
|
require_once ("$iTopFolder/approot.inc.php");
|
||||||
|
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
||||||
|
|
||||||
|
if (php_sapi_name() !== 'cli')
|
||||||
|
{
|
||||||
|
throw new \Exception('This script can only run from CLI');
|
||||||
|
}
|
||||||
|
|
||||||
|
clearstatcache();
|
||||||
|
|
||||||
|
$oiTopComposer = new iTopComposer();
|
||||||
|
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
foreach ($aDeniedButStillPresent as $sDir)
|
||||||
|
{
|
||||||
|
if (false === iTopComposer::IsTestDir($sDir))
|
||||||
|
{
|
||||||
|
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
||||||
|
throw new \Exception("$sDir must end with /Test/ or /test/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === file_exists($sDir)) {
|
||||||
|
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetupUtils::rrmdir($sDir);
|
||||||
|
echo "OK Remove denied test dir: '$sDir'\n";
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
echo "\nFAILED to remove denied test dir: '$sDir'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
courier.php
|
|
||||||
courierb.php
|
|
||||||
courierbi.php
|
|
||||||
courieri.php
|
|
||||||
dejavusans.ctg.z
|
|
||||||
dejavusans.php
|
|
||||||
dejavusans.z
|
|
||||||
dejavusansb.ctg.z
|
|
||||||
dejavusansb.php
|
|
||||||
dejavusansb.z
|
|
||||||
dejavusansbi.ctg.z
|
|
||||||
dejavusansbi.php
|
|
||||||
dejavusansbi.z
|
|
||||||
dejavusanscondensed.ctg.z
|
|
||||||
dejavusanscondensed.php
|
|
||||||
dejavusanscondensed.z
|
|
||||||
dejavusanscondensedb.ctg.z
|
|
||||||
dejavusanscondensedb.php
|
|
||||||
dejavusanscondensedb.z
|
|
||||||
dejavusanscondensedbi.ctg.z
|
|
||||||
dejavusanscondensedbi.php
|
|
||||||
dejavusanscondensedbi.z
|
|
||||||
dejavusanscondensedi.ctg.z
|
|
||||||
dejavusanscondensedi.php
|
|
||||||
dejavusanscondensedi.z
|
|
||||||
dejavusansextralight.ctg.z
|
|
||||||
dejavusansextralight.php
|
|
||||||
dejavusansextralight.z
|
|
||||||
dejavusansi.ctg.z
|
|
||||||
dejavusansi.php
|
|
||||||
dejavusansi.z
|
|
||||||
dejavusansmono.ctg.z
|
|
||||||
dejavusansmono.php
|
|
||||||
dejavusansmono.z
|
|
||||||
dejavusansmonob.ctg.z
|
|
||||||
dejavusansmonob.php
|
|
||||||
dejavusansmonob.z
|
|
||||||
dejavusansmonobi.ctg.z
|
|
||||||
dejavusansmonobi.php
|
|
||||||
dejavusansmonobi.z
|
|
||||||
dejavusansmonoi.ctg.z
|
|
||||||
dejavusansmonoi.php
|
|
||||||
dejavusansmonoi.z
|
|
||||||
droidsansfallback.ctg.z
|
|
||||||
droidsansfallback.php
|
|
||||||
droidsansfallback.z
|
|
||||||
helvetica.php
|
|
||||||
helveticab.php
|
|
||||||
helveticabi.php
|
|
||||||
helveticai.php
|
|
||||||
symbol.php
|
|
||||||
times.php
|
|
||||||
timesb.php
|
|
||||||
timesbi.php
|
|
||||||
timesi.php
|
|
||||||
zapfdingbats.php
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This script will copy custom fonts in the TCPDF lib fonts directory.
|
|
||||||
* If you need to add other files :
|
|
||||||
* - add the corresponding files in this script directory
|
|
||||||
* - modify this script to copy also your files
|
|
||||||
*
|
|
||||||
* @since 2.7.0 N°1947 add DroidSansFallback font (see also PR #49 in the links below)
|
|
||||||
* @since 2.7.0 N°2435 TCPPDF lib forked and added in composer.json (at that time the lib was announced as deprecated and rewritten in tecnickcom/tc-lib-pdf)
|
|
||||||
* @since 3.2.0 N°7175 switch back to TCPDF original lib (which is finally still maintained, tecnickcom/tc-lib-pdf us still under dev), script creation to keep custom DroidSansFallback font
|
|
||||||
*
|
|
||||||
* @link https://github.com/Combodo/iTop/pull/49 add DroidSansFallback font
|
|
||||||
* @link https://github.com/tecnickcom/TCPDF?tab=readme-ov-file#note TCPDF is in support only mode
|
|
||||||
*/
|
|
||||||
|
|
||||||
$sItopRootFolder = realpath(__DIR__ . "/../../../../");
|
|
||||||
$sCurrentScriptFileName = basename(__FILE__);
|
|
||||||
|
|
||||||
|
|
||||||
require_once ("$sItopRootFolder/lib/autoload.php");
|
|
||||||
|
|
||||||
|
|
||||||
$sTcPdfRootFolder = $sItopRootFolder.'/lib/tecnickcom/tcpdf';
|
|
||||||
if (false === file_exists($sTcPdfRootFolder)) {
|
|
||||||
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/fonts/';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1) Cleaning up the fonts directory to keep only the ones we want in iTop
|
|
||||||
*/
|
|
||||||
echo $sCurrentScriptFileName.": ---1) Cleaning up the fonts files\n";
|
|
||||||
$aTcpdfDefaultFontsToKeepInItop = file(__DIR__.'/tcpdfDefaultFontsToKeepInItop.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
||||||
|
|
||||||
$aTcpdfFontsDirContent = scandir($sTcPdfFontsFolder);
|
|
||||||
foreach ($aTcpdfFontsDirContent as $sTcpdfFontResourceName) {
|
|
||||||
if ($sTcpdfFontResourceName === '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($sTcpdfFontResourceName === '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($sTcpdfFontResourceName, $aTcpdfDefaultFontsToKeepInItop, true)) {
|
|
||||||
echo $sCurrentScriptFileName.": Removing $sTcpdfFontResourceName !\n";
|
|
||||||
|
|
||||||
$sTcpdfFontResourceFullPath = $sTcPdfFontsFolder.$sTcpdfFontResourceName;
|
|
||||||
if (is_file($sTcpdfFontResourceFullPath)) {
|
|
||||||
unlink($sTcpdfFontResourceFullPath);
|
|
||||||
} elseif (is_dir($sTcpdfFontResourceFullPath)) {
|
|
||||||
rrmdir($sTcpdfFontResourceFullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2) Then adding the DroidSansFallback font (useful for CJK data for example)
|
|
||||||
*/
|
|
||||||
echo $sCurrentScriptFileName.": ---2) Copying font files to TCPDF ($sTcPdfFontsFolder)...\n";
|
|
||||||
$aFontFilesToCopy = glob(__DIR__.'\droidsansfallback.*');
|
|
||||||
foreach ($aFontFilesToCopy as $sFontFileToCopy) {
|
|
||||||
$sFontFileName = basename($sFontFileToCopy);
|
|
||||||
echo $sCurrentScriptFileName.': copying '.$sFontFileName."\n";
|
|
||||||
copy($sFontFileToCopy, $sTcPdfFontsFolder.$sFontFileName);
|
|
||||||
}
|
|
||||||
echo $sCurrentScriptFileName.": Done !\n";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively delete a directory and its content
|
|
||||||
*
|
|
||||||
* @param $sDirToRemovePath
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function rrmdir($sDirToRemovePath):void
|
|
||||||
{
|
|
||||||
if (is_dir($sDirToRemovePath)) {
|
|
||||||
$objects = scandir($sDirToRemovePath);
|
|
||||||
foreach ($objects as $object) {
|
|
||||||
if ($object != "." && $object != "..") {
|
|
||||||
if (filetype($sDirToRemovePath."/".$object) == "dir") {
|
|
||||||
rrmdir($sDirToRemovePath."/".$object);
|
|
||||||
} else {
|
|
||||||
unlink($sDirToRemovePath."/".$object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reset($objects);
|
|
||||||
rmdir($sDirToRemovePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<?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/>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure that the files for folder browsing protection (.htaccess, web.config) are kept after an "npm install/update" command
|
|
||||||
*/
|
|
||||||
|
|
||||||
$iTopFolder = __DIR__."/../../../";
|
|
||||||
|
|
||||||
require_once("$iTopFolder/approot.inc.php");
|
|
||||||
|
|
||||||
$sDependenciesRootFolderAbsPath = APPROOT . "node_modules/";
|
|
||||||
$aFilesToCheck = [
|
|
||||||
".htaccess",
|
|
||||||
"web.config",
|
|
||||||
];
|
|
||||||
|
|
||||||
echo "This command aims at ensuring that folder browsing protection files (.htaccess, web.config) are present in the dependencies folder even after an install/upgrade command\n";
|
|
||||||
echo "Checking files:\n";
|
|
||||||
|
|
||||||
foreach($aFilesToCheck as $sFileToCheck) {
|
|
||||||
if (file_exists($sDependenciesRootFolderAbsPath . $sFileToCheck)) {
|
|
||||||
echo "✔️ $sFileToCheck is present\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If missing, copy the one from /lib as it contains the necessary allow/deny directives for third-parties
|
|
||||||
copy(APPROOT . "lib/$sFileToCheck", $sDependenciesRootFolderAbsPath . $sFileToCheck);
|
|
||||||
echo "✔️ $sFileToCheck was missing and has been re-created\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure separation with following scripts
|
|
||||||
echo "\n";
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<?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/>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
$iTopFolder = __DIR__ . "/../../" ;
|
|
||||||
|
|
||||||
require_once ("$iTopFolder/approot.inc.php");
|
|
||||||
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
|
||||||
|
|
||||||
if (php_sapi_name() !== 'cli')
|
|
||||||
{
|
|
||||||
throw new \Exception('This script can only run from CLI');
|
|
||||||
}
|
|
||||||
|
|
||||||
clearstatcache();
|
|
||||||
|
|
||||||
// Read params
|
|
||||||
$key = array_search("--manager", $argv);
|
|
||||||
if (false === $key || false === isset($argv[$key + 1]) ) {
|
|
||||||
throw new \InvalidArgumentException("Usage: " . __FILE__ . " --manager composer|npm");
|
|
||||||
}
|
|
||||||
$sDependenciesHandlerCode = $argv[$key + 1];
|
|
||||||
|
|
||||||
switch ($sDependenciesHandlerCode) {
|
|
||||||
case "composer":
|
|
||||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\Composer\iTopComposer::class;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "npm":
|
|
||||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\NPM\iTopNPM::class;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new \Exception("Invalid dependencies handler code, $sDependenciesHandlerCode given, expected composer|npm");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start handler
|
|
||||||
$oDependenciesHandler = new $sDependenciesHandlerFQCN();
|
|
||||||
$aDeniedButStillPresent = $oDependenciesHandler->ListDeniedButStillPresentFilesAbsPaths();
|
|
||||||
|
|
||||||
echo "\n";
|
|
||||||
foreach ($aDeniedButStillPresent as $sDir)
|
|
||||||
{
|
|
||||||
if (false === $oDependenciesHandler::IsQuestionnableFile($sDir))
|
|
||||||
{
|
|
||||||
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
|
||||||
throw new \RuntimeException("$sDir is in the denied list but doesn't comply with the rule (see IsQuestionnableFolder method)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === file_exists($sDir)) {
|
|
||||||
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(is_dir($sDir)){
|
|
||||||
SetupUtils::rrmdir($sDir);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
unlink($sDir);
|
|
||||||
}
|
|
||||||
echo "✔️ Remove denied test dir: '$sDir'\n";
|
|
||||||
}
|
|
||||||
catch (\Exception $e) {
|
|
||||||
echo "\n❌ FAILED to remove denied test dir: '$sDir'\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$aAllowedAndDeniedDirs = array_merge(
|
|
||||||
$oDependenciesHandler->ListAllowedFilesAbsPaths(),
|
|
||||||
$oDependenciesHandler->ListDeniedFilesAbsPaths()
|
|
||||||
);
|
|
||||||
$aExistingDirs = $oDependenciesHandler->ListAllFilesAbsPaths();
|
|
||||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
|
||||||
if (false === empty($aMissing)) {
|
|
||||||
echo "Some new tests dirs exists !\n"
|
|
||||||
." They must be declared either in the allowed or denied list in {$sDependenciesHandlerFQCN}\n"
|
|
||||||
.' List of dirs:'."\n".var_export($aMissing, true)."\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure separation with following scripts
|
|
||||||
echo "\n";
|
|
||||||
@@ -19,24 +19,17 @@
|
|||||||
* The target license file path is in `$xmlFilePath`
|
* The target license file path is in `$xmlFilePath`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$iTopFolder = __DIR__."/../../";
|
$iTopFolder = __DIR__ . "/../../" ;
|
||||||
$xmlFilePath = $iTopFolder."setup/licenses/community-licenses.xml";
|
$xmlFilePath = $iTopFolder . "setup/licenses/community-licenses.xml";
|
||||||
|
|
||||||
$jqExec = shell_exec("jq -V"); // a param is mandatory otherwise the script will freeze
|
function get_scope($product_node)
|
||||||
if ((null === $jqExec) || (false === $jqExec)) {
|
{
|
||||||
echo "/!\ JQ is required but cannot be launched :( \n";
|
|
||||||
echo "Check this script PHPDoc block for instructions\n";
|
|
||||||
die(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function get_scope($product_node) {
|
|
||||||
$scope = $product_node->getAttribute("scope");
|
$scope = $product_node->getAttribute("scope");
|
||||||
|
|
||||||
if ($scope === "") { //put iTop first
|
if ($scope === "")
|
||||||
|
{ //put iTop first
|
||||||
return "aaaaaaaaa";
|
return "aaaaaaaaa";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $scope;
|
return $scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,11 @@
|
|||||||
* Will update version in the following files :
|
* Will update version in the following files :
|
||||||
*
|
*
|
||||||
* datamodels/2.x/.../datamodel.*.xml
|
* datamodels/2.x/.../datamodel.*.xml
|
||||||
* application/*.xml
|
|
||||||
* core/*.xml
|
|
||||||
*
|
*
|
||||||
* Usage :
|
* Usage :
|
||||||
* `php .make\release\update-xml.php "1.7"`
|
* `php .make\release\update-xml.php "1.7"`
|
||||||
* `php .make\release\update-xml.php`
|
|
||||||
*
|
*
|
||||||
* If no parameter provided then the current XML version will be used as target version
|
* @since 2.7.0
|
||||||
*
|
|
||||||
* @since 2.7.0 simple version change using regexp (not doing conversion)
|
|
||||||
* @since 3.1.0 N°5405 now does a real conversion
|
|
||||||
* @since 3.1.0 N°5633 allow to use without parameter
|
|
||||||
* @since 3.1.0 N°5633 add /application and /core XML files
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -30,12 +22,10 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php');
|
|||||||
|
|
||||||
if (count($argv) === 1)
|
if (count($argv) === 1)
|
||||||
{
|
{
|
||||||
echo '/!\ No version passed: assuming target XML version is current XML version ('.ITOP_DESIGN_LATEST_VERSION.")\n";
|
echo '/!\ You must pass the new version as parameter';
|
||||||
$sVersionLabel = ITOP_DESIGN_LATEST_VERSION;
|
exit(1);
|
||||||
} else {
|
|
||||||
$sVersionLabel = $argv[1];
|
|
||||||
}
|
}
|
||||||
|
$sVersionLabel = $argv[1];
|
||||||
if (empty($sVersionLabel))
|
if (empty($sVersionLabel))
|
||||||
{
|
{
|
||||||
echo 'Version passed as parameter is empty !';
|
echo 'Version passed as parameter is empty !';
|
||||||
|
|||||||
@@ -125,31 +125,16 @@ class iTopVersionFileUpdater extends AbstractSingleFileVersionUpdater
|
|||||||
|
|
||||||
abstract class AbstractGlobFileVersionUpdater extends FileVersionUpdater
|
abstract class AbstractGlobFileVersionUpdater extends FileVersionUpdater
|
||||||
{
|
{
|
||||||
/** @var array|string glob patterns to seek for files to modify */
|
protected $sGlobPattern;
|
||||||
protected $globPattern;
|
|
||||||
|
|
||||||
public function __construct($globPattern)
|
public function __construct($sGlobPattern)
|
||||||
{
|
{
|
||||||
$this->globPattern = $globPattern;
|
$this->sGlobPattern = $sGlobPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetFiles()
|
public function GetFiles()
|
||||||
{
|
{
|
||||||
$aGlobPatterns = (is_array($this->globPattern))
|
return glob($this->sGlobPattern);
|
||||||
? $this->globPattern
|
|
||||||
: [$this->globPattern];
|
|
||||||
|
|
||||||
$aFiles = [];
|
|
||||||
foreach ($aGlobPatterns as $sGlobPattern) {
|
|
||||||
$result = glob($sGlobPattern);
|
|
||||||
if (false === $result) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/** @noinspection SlowArrayOperationsInLoopInspection */
|
|
||||||
$aFiles = array_merge($aFiles, $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aFiles;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,11 +166,7 @@ class DatamodelsXmlFiles extends AbstractGlobFileVersionUpdater
|
|||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct([
|
parent::__construct(APPROOT.'datamodels/2.x/*/datamodel.*.xml');
|
||||||
APPROOT.'datamodels/2.x/*/datamodel.*.xml',
|
|
||||||
APPROOT.'application/*.xml',
|
|
||||||
APPROOT.'core/*.xml',
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,40 +174,10 @@ class DatamodelsXmlFiles extends AbstractGlobFileVersionUpdater
|
|||||||
*/
|
*/
|
||||||
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
|
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
|
||||||
{
|
{
|
||||||
require_once APPROOT.'setup/itopdesignformat.class.inc.php';
|
return preg_replace(
|
||||||
$oFileXml = new DOMDocument();
|
'/(<itop_design .* version=")[^"]+(">)/',
|
||||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
'${1}'.$sVersionLabel.'${2}',
|
||||||
libxml_clear_errors();
|
$sFileContent
|
||||||
$oFileXml->formatOutput = true;
|
);
|
||||||
$oFileXml->preserveWhiteSpace = false;
|
|
||||||
$oFileXml->loadXML($sFileContent, LIBXML_BIGLINES);
|
|
||||||
|
|
||||||
$oFileItopFormat = new iTopDesignFormat($oFileXml);
|
|
||||||
|
|
||||||
$sDesignVersionToSet = static::GetDesignVersionToSet($oFileItopFormat->GetVersion());
|
|
||||||
if (false === is_null($sDesignVersionToSet)) {
|
|
||||||
// N°5779 if same as target version, we will try to convert from version below
|
|
||||||
$oFileItopFormat->GetITopDesignNode()->setAttribute('version', $sDesignVersionToSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
$bConversionResult = $oFileItopFormat->Convert($sVersionLabel);
|
|
||||||
|
|
||||||
if (false === $bConversionResult) {
|
|
||||||
throw new Exception("Error when converting $sFileFullPath");
|
|
||||||
}
|
|
||||||
|
|
||||||
return $oFileItopFormat->GetXmlAsString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ?string version to use : if file version is same as current version then return previous version, else return null
|
|
||||||
* @since 3.1.0 N°5779
|
|
||||||
*/
|
|
||||||
protected static function GetDesignVersionToSet($sFileDesignVersion):?string {
|
|
||||||
if ($sFileDesignVersion !== ITOP_DESIGN_LATEST_VERSION) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iTopDesignFormat::GetPreviousDesignVersion(ITOP_DESIGN_LATEST_VERSION);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
113
CONTRIBUTING.md
113
CONTRIBUTING.md
@@ -4,69 +4,78 @@ You want to contribute to iTop? Many thanks to you! 🎉 👍
|
|||||||
|
|
||||||
Here are some guidelines that will help us integrate your work!
|
Here are some guidelines that will help us integrate your work!
|
||||||
|
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
### Subjects
|
### Subjects
|
||||||
|
|
||||||
You are welcome to create pull requests on any of those subjects:
|
You are welcome to create pull requests on any of those subjects:
|
||||||
|
|
||||||
* 🐛 bug fix
|
* 🐛 bug fix
|
||||||
* 🌐 translation / i18n / l10n
|
* 🌐 translation / i18n / l10n
|
||||||
* 🚸 enhancement
|
|
||||||
|
|
||||||
But before creating a PR, please [create a corresponding issue][itop-issues] for review.
|
If you want to implement a **new feature**, please [create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) 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 ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the ticket.
|
||||||
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).
|
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
|
All **datamodel modification** should be done in an extension. Beware that such change would
|
||||||
impact all existing customers, and could prevent them from upgrading!
|
impact all existing customers, and could prevent them from
|
||||||
Combodo has a long experience of datamodel changes: they are very disruptive!
|
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.
|
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
|
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
|
[create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) to submit it, but be warned that there are lots of good
|
||||||
reasons to refuse such changes.
|
reasons to refuse such changes.
|
||||||
|
|
||||||
### 📄 License and copyright
|
### 📄 License
|
||||||
|
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file),
|
||||||
|
your code must comply with this license.
|
||||||
|
|
||||||
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file).
|
If you want to use another license, you may [create an extension][wiki new ext].
|
||||||
|
|
||||||
The iTop repository is divided in three parts: iTop (mainly PHP/JS/XML sources and dictionaries), images, and third-party libraries.
|
|
||||||
Combodo has the copyright on most of the source files in the iTop part of the repository: please do not modify the existing file copyrights.
|
|
||||||
Anyhow, you are encouraged to signal your contribution by the mean of `@author` annotations.
|
|
||||||
|
|
||||||
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
|
[license.txt]: https://github.com/Combodo/iTop/blob/develop/license.txt
|
||||||
|
|
||||||
[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
|
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
|
||||||
|
|
||||||
|
|
||||||
## 🔀 iTop branch model
|
## 🔀 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
|
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
|
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
|
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.
|
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
|
- `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
|
- `support/*`: maintenance branches for older versions
|
||||||
|
|
||||||
For example, if no version is currently prepared for shipping we could have:
|
For example, if no version is currently prepared for shipping we could have:
|
||||||
|
|
||||||
- `develop` containing future 3.3.0 version
|
- `develop` containing future 3.0.0 version
|
||||||
- `support/3.2`: 3.2.x maintenance version
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
|
- `support/2.5`: 2.5.x maintenance version
|
||||||
|
|
||||||
And when 3.3.0 will be out:
|
In this example, when 3.0.0-beta is shipped that will become:
|
||||||
|
|
||||||
|
- `develop`: future 3.1.0 version
|
||||||
|
- `release/3.0.0`: 3.0.0-beta
|
||||||
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
|
- `support/2.5`: 2.5.x maintenance version
|
||||||
|
|
||||||
|
And when 3.0.0 final will be out:
|
||||||
|
|
||||||
|
- `develop`: future 3.1.0 version
|
||||||
|
- `support/3.0`: 3.0.x maintenance version (will host developments for 3.0.1)
|
||||||
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
|
- `support/2.5`: 2.5.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.
|
||||||
|
|
||||||
- `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
|
## Coding
|
||||||
|
|
||||||
@@ -80,11 +89,12 @@ 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
|
2. Create a branch in this fork, based on the develop branch
|
||||||
3. Code !
|
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 base your developments on the develop branch.
|
Most of the time you should based 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.
|
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
|
### 🎨 PHP styleguide
|
||||||
|
|
||||||
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
|
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
|
||||||
@@ -93,7 +103,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.
|
Please create tests that covers as much as possible the code you're submitting.
|
||||||
|
|
||||||
Our tests are located in the `tests/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
|
Our tests are located in the `test/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
|
||||||
|
|
||||||
### Git Commit Messages
|
### Git Commit Messages
|
||||||
|
|
||||||
@@ -101,9 +111,9 @@ Our tests are located in the `tests/` directory, containing a PHPUnit config fil
|
|||||||
* Use the present tense ("Add feature" not "Added feature")
|
* Use the present tense ("Add feature" not "Added feature")
|
||||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||||
* Limit the first line to 72 characters or less
|
* Limit the first line to 72 characters or less
|
||||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)).
|
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
|
||||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||||
Emoji examples :
|
Emoji examples :
|
||||||
* 🌐 `:globe_with_meridians:` for translations
|
* 🌐 `:globe_with_meridians:` for translations
|
||||||
* 🎨 `:art:` when improving the format/structure of the code
|
* 🎨 `:art:` when improving the format/structure of the code
|
||||||
* ⚡️ `:zap:` when improving performance
|
* ⚡️ `:zap:` when improving performance
|
||||||
@@ -121,20 +131,21 @@ Our tests are located in the `tests/` directory, containing a PHPUnit config fil
|
|||||||
|
|
||||||
When your code is working, please:
|
When your code is working, please:
|
||||||
|
|
||||||
* Squash as much as possible your commits,
|
* stash as much as possible your commits,
|
||||||
* Rebase your branch on our repo last commit,
|
* 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/)_.
|
* create a pull request.
|
||||||
* 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))
|
|
||||||
|
|
||||||
## 🙏 We are thankful
|
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/).
|
||||||
|
|
||||||
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!
|
You might check the ["Allow edits from maintainers" PR checkbox][allow_edits_checkbox] to ease review.
|
||||||
|
|
||||||
We have one sticker per contribution type. You might get multiple stickers with one contribution though :)
|
[allow_edits_checkbox]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork#enabling-repository-maintainer-permissions-on-existing-pull-requests
|
||||||
|
|
||||||
|
### 🙏 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!
|
||||||
|
|
||||||
|
Stickers' design might change from one year to another. For the first year we wanted to try a "craft beer label" look, see examples below:
|
||||||
|
|
||||||
* Bug hunter: Fix a bug
|
* Bug hunter: Fix a bug
|
||||||
* Translator: Add/update translations
|
* Translator: Add/update translations
|
||||||
@@ -144,4 +155,6 @@ We have one sticker per contribution type. You might get multiple stickers with
|
|||||||
* Graduated: Follow a Combodo's iTop training
|
* Graduated: Follow a Combodo's iTop training
|
||||||
* Ambassador: Outstanding community contributors
|
* Ambassador: Outstanding community contributors
|
||||||
* Beta tester: Test and give feedback on beta releases
|
* Beta tester: Test and give feedback on beta releases
|
||||||
* Extension developer: Develop and publish an extension
|
* Extension developer: Develop and publish an extension
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -1,14 +1,6 @@
|
|||||||
def infra
|
def infra
|
||||||
|
|
||||||
node(){
|
node(){
|
||||||
properties([
|
|
||||||
buildDiscarder(
|
|
||||||
logRotator(
|
|
||||||
daysToKeepStr: "28",
|
|
||||||
numToKeepStr: "500")
|
|
||||||
)
|
|
||||||
])
|
|
||||||
|
|
||||||
checkout scm
|
checkout scm
|
||||||
|
|
||||||
infra = load '/var/lib/jenkins/workspace/itop-test-infra_master/src/Infra.groovy'
|
infra = load '/var/lib/jenkins/workspace/itop-test-infra_master/src/Infra.groovy'
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -1,15 +1,13 @@
|
|||||||
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
|
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
|
||||||
<picture>
|
<img src="https://www.combodo.com/logos/logo-itop.svg">
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="/images/logos/logo-itop-baseline-light.svg">
|
|
||||||
<source media="(prefers-color-scheme: light)" srcset="/images/logos/logo-itop-baseline-dark.svg">
|
|
||||||
<img src="/images/logos/logo-itop-baseline-light.svg" width="350" alt="Logo iTop with baseline" />
|
|
||||||
</picture>
|
|
||||||
</a></p>
|
</a></p>
|
||||||
|
|
||||||
|
|
||||||
iTop stands for IT Operations Portal. It is a complete open source and web-based IT service management platform, including a fully customizable CMDB, a helpdesk system, and a document management tool. It is ITIL compliant and easily customizable and extensible thanks to a high number of add-ons and web services to integrate with your IT.
|
# iTop - ITSM & CMDB
|
||||||
|
|
||||||
iTop also offers mass import tools to help you become even more efficient.
|
iTop stands for *IT Operations Portal*.
|
||||||
|
It is a complete open source, ITIL, web based service management tool including a fully customizable CMDB, a helpdesk system and a document management tool.
|
||||||
|
iTop also offers mass import tools and web services to integrate with your IT
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Fully configurable [Configuration Management (CMDB)][10]
|
- Fully configurable [Configuration Management (CMDB)][10]
|
||||||
@@ -41,19 +39,17 @@ iTop also offers mass import tools to help you become even more efficient.
|
|||||||
- [iTop Forums][1]: community support
|
- [iTop Forums][1]: community support
|
||||||
- [iTop Tickets][2]: for feature requests and bug reports
|
- [iTop Tickets][2]: for feature requests and bug reports
|
||||||
- [Releases download][3]
|
- [Releases download][3]
|
||||||
- [iTop requirements][4]
|
- [Software requirements][4]
|
||||||
- [Documentation][5] covering both iTop and its official extensions
|
- [Documentation][5] covering both iTop and its official extensions
|
||||||
- [iTop Hub][6] : discover and install extensions !
|
- [iTop Hub][6] : discover and install extensions !
|
||||||
- [iTop versions history][7]
|
|
||||||
|
|
||||||
|
|
||||||
[1]: https://sourceforge.net/p/itop/discussion/
|
[1]: https://sourceforge.net/p/itop/discussion/
|
||||||
[2]: https://sourceforge.net/p/itop/tickets/
|
[2]: https://sourceforge.net/p/itop/tickets/
|
||||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||||
[4]: https://www.itophub.io/wiki/page?id=latest:install:requirements
|
[4]: https://www.itophub.io/wiki/page?id=latest:install:upgrading_itop
|
||||||
[5]: https://www.itophub.io/wiki
|
[5]: https://www.itophub.io/wiki
|
||||||
[6]: https://store.itophub.io/en_US/
|
[6]: https://store.itophub.io/en_US/
|
||||||
[7]: .doc/itop-version-history.md
|
|
||||||
|
|
||||||
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
||||||
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
||||||
@@ -69,7 +65,7 @@ iTop also offers mass import tools to help you become even more efficient.
|
|||||||
|
|
||||||
## About Us
|
## About Us
|
||||||
|
|
||||||
iTop development is sponsored, led, and supported by [Combodo][0].
|
iTop development is sponsored, led and supported by [Combodo][0].
|
||||||
|
|
||||||
[0]: https://www.combodo.com
|
[0]: https://www.combodo.com
|
||||||
|
|
||||||
@@ -82,21 +78,18 @@ We would like to give a special thank you 🤗 to the people from the community
|
|||||||
|
|
||||||
- Alves, David
|
- Alves, David
|
||||||
- Beck, Pedro
|
- Beck, Pedro
|
||||||
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
|
|
||||||
- Bilger, Jean-François
|
- Bilger, Jean-François
|
||||||
- Bostoen, Jeffrey (a.k.a [@jbostoen](https://www.github.com/jbostoen))
|
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
||||||
- Cardoso, Anderson
|
- Cardoso, Anderson
|
||||||
- Cassaro, Bruno
|
- Cassaro, Bruno
|
||||||
- Casteleyn, Thomas (a.k.a [@Hipska](https://www.github.com/Hipska))
|
- Casteleyn, Thomas (a.k.a @Hipska)
|
||||||
- Castro, Randall Badilla
|
- Castro, Randall Badilla
|
||||||
- Colantoni, Maria Laura
|
- Colantoni, Maria Laura
|
||||||
- Couronné, Guy
|
- Couronné, Guy
|
||||||
- Dejin, Bie (a.k.a [@bdejin](https://github.com/bdejin))
|
|
||||||
- Dvořák, Lukáš
|
- Dvořák, Lukáš
|
||||||
- Goethals, Stefan
|
- Goethals, Stefan
|
||||||
- Gumble, David
|
- Gumble, David
|
||||||
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
|
- Kaltefleiter, Lars (a.k.a @larhip)
|
||||||
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
|
|
||||||
- Khamit, Shamil
|
- Khamit, Shamil
|
||||||
- Kincel, Martin
|
- Kincel, Martin
|
||||||
- Konečný, Kamil
|
- Konečný, Kamil
|
||||||
@@ -105,22 +98,14 @@ We would like to give a special thank you 🤗 to the people from the community
|
|||||||
- Lazcano, Federico
|
- Lazcano, Federico
|
||||||
- Lucas, Jonathan
|
- Lucas, Jonathan
|
||||||
- Malik, Remie
|
- Malik, Remie
|
||||||
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
|
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||||
- Mozart de Oliveira, Eduardo (a.k.a [@eduardomozart](https://github.com/eduardomozart))
|
|
||||||
- Raenker, Martin
|
- Raenker, Martin
|
||||||
- Roháč, Richard (a.k.a [@RohacRichard](https://github.com/RohacRichard))
|
|
||||||
- Rosenke, Stephan
|
- Rosenke, Stephan
|
||||||
- Rossi, Tommaso (a.k.a [@tomrss](https://www.github.com/tomrss))
|
|
||||||
- Rudner, Björn (a.k.a [@rudnerbjoern](https://github.com/rudnerbjoern))
|
|
||||||
- Šafránek, Jaroslav (a.k.a [jkcinik](https://sourceforge.net/u/jkcinik/profile/) on SourceForge)
|
|
||||||
- Seki, Shoji
|
- Seki, Shoji
|
||||||
- Shilov, Vladimir
|
- Shilov, Vladimir
|
||||||
- Stetina, Pavel (a.k.a [@Stetinac](https://github.com/Stetinac))
|
- Stukalov, Ilya (a.k.a @ilya-stukalov)
|
||||||
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
|
|
||||||
- Tarjányi, Csaba (a.k.a [@tacsaby](https://github.com/tacsaby))
|
|
||||||
- Tulio, Marco
|
- Tulio, Marco
|
||||||
- Turrubiates, Miguel
|
- Turrubiates, Miguel
|
||||||
- Vlk, Karel (a.k.a [@vlk-charles](https://www.github.com/vlk-charles))
|
|
||||||
|
|
||||||
### Aliases
|
### Aliases
|
||||||
|
|
||||||
@@ -129,7 +114,6 @@ We would like to give a special thank you 🤗 to the people from the community
|
|||||||
- DudekArtur
|
- DudekArtur
|
||||||
- Karkoff1212
|
- Karkoff1212
|
||||||
- Laura
|
- Laura
|
||||||
- nv35
|
|
||||||
- Purple Grape
|
- Purple Grape
|
||||||
- Schlobinux
|
- Schlobinux
|
||||||
- theBigOne
|
- theBigOne
|
||||||
|
|||||||
12
SECURITY.md
12
SECURITY.md
@@ -18,7 +18,8 @@ to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 🔍 Combodo acknowledgment and investigation
|
## 📆 Disclosure Policy
|
||||||
|
|
||||||
Report sent to us will be acknowledged within the week.
|
Report sent to us will be acknowledged within the week.
|
||||||
|
|
||||||
Then, a Combodo developer will be assigned to the reported issue and will:
|
Then, a Combodo developer will be assigned to the reported issue and will:
|
||||||
@@ -33,12 +34,3 @@ Then, a Combodo developer will be assigned to the reported issue and will:
|
|||||||
Security issues always take precedence over bug fixes and feature work.
|
Security issues always take precedence over bug fixes and feature work.
|
||||||
|
|
||||||
The assignee will keep you informed of the resolution progress, and may ask you for additional information or guidance.
|
The assignee will keep you informed of the resolution progress, and may ask you for additional information or guidance.
|
||||||
|
|
||||||
|
|
||||||
## 📆 Disclosure Policy
|
|
||||||
Once the fix is done and acknowledged by every stakeholder, it will be included in the next iTop version.
|
|
||||||
Mind we have at least 2 active branches (LTS and STS, see [iTop Community Releases [iTop Documentation]](https://www.itophub.io/wiki/page?id=latest:release:start))
|
|
||||||
|
|
||||||
The release communications will include the information of the vulnerability fix.
|
|
||||||
|
|
||||||
Corresponding GitHub advisories and CVE will be published 3 months after the iTop version release date so that iTop instances can be updated.
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -20,33 +19,34 @@
|
|||||||
/**
|
/**
|
||||||
* UserRightsMatrix (User management Module)
|
* UserRightsMatrix (User management Module)
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class UserRightsMatrixClassGrant extends DBObject
|
class UserRightsMatrixClassGrant extends DBObject
|
||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => [],
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_ur_matrixclasses",
|
"db_table" => "priv_ur_matrixclasses",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
];
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("action", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,25 +54,25 @@ class UserRightsMatrixClassStimulusGrant extends DBObject
|
|||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => [],
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_ur_matrixclassesstimulus",
|
"db_table" => "priv_ur_matrixclassesstimulus",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
];
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("stimulus", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,44 +80,48 @@ class UserRightsMatrixAttributeGrant extends DBObject
|
|||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "",
|
"name_attcode" => "",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => [],
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_ur_matrixattributes",
|
"db_table" => "priv_ur_matrixattributes",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
];
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("class", array("allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("attcode", ["allowed_values" => null, "sql" => "attcode", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("action", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserRightsMatrix extends UserRightsAddOnAPI
|
class UserRightsMatrix extends UserRightsAddOnAPI
|
||||||
{
|
{
|
||||||
public static $m_aActionCodes = [
|
static public $m_aActionCodes = array(
|
||||||
UR_ACTION_READ => 'read',
|
UR_ACTION_READ => 'read',
|
||||||
UR_ACTION_MODIFY => 'modify',
|
UR_ACTION_MODIFY => 'modify',
|
||||||
UR_ACTION_DELETE => 'delete',
|
UR_ACTION_DELETE => 'delete',
|
||||||
UR_ACTION_BULK_READ => 'bulk read',
|
UR_ACTION_BULK_READ => 'bulk read',
|
||||||
UR_ACTION_BULK_MODIFY => 'bulk modify',
|
UR_ACTION_BULK_MODIFY => 'bulk modify',
|
||||||
UR_ACTION_BULK_DELETE => 'bulk delete',
|
UR_ACTION_BULK_DELETE => 'bulk delete',
|
||||||
];
|
);
|
||||||
|
|
||||||
// Installation: create the very first user
|
// Installation: create the very first user
|
||||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||||
{
|
{
|
||||||
// Maybe we should check that no other user with userid == 0 exists
|
// Maybe we should check that no other user with userid == 0 exists
|
||||||
|
CMDBObject::SetTrackInfo('Initialization');
|
||||||
$oUser = new UserLocal();
|
$oUser = new UserLocal();
|
||||||
$oUser->Set('login', $sAdminUser);
|
$oUser->Set('login', $sAdminUser);
|
||||||
$oUser->Set('password', $sAdminPwd);
|
$oUser->Set('password', $sAdminPwd);
|
||||||
@@ -146,7 +150,8 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
// Users must be added manually
|
// Users must be added manually
|
||||||
// This procedure will then update the matrix when a new user is found or a new class/attribute appears
|
// This procedure will then update the matrix when a new user is found or a new class/attribute appears
|
||||||
$oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT User"));
|
$oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT User"));
|
||||||
while ($oUser = $oUserSet->Fetch()) {
|
while ($oUser = $oUserSet->Fetch())
|
||||||
|
{
|
||||||
$this->SetupUser($oUser->GetKey());
|
$this->SetupUser($oUser->GetKey());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -154,16 +159,23 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
|
|
||||||
protected function SetupUser($iUserId, $bNewUser = false)
|
protected function SetupUser($iUserId, $bNewUser = false)
|
||||||
{
|
{
|
||||||
foreach (['bizmodel', 'application', 'gui', 'core/cmdb'] as $sCategory) {
|
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory)
|
||||||
foreach (MetaModel::GetClasses($sCategory) as $sClass) {
|
{
|
||||||
foreach (self::$m_aActionCodes as $iActionCode => $sAction) {
|
foreach (MetaModel::GetClasses($sCategory) as $sClass)
|
||||||
if ($bNewUser) {
|
{
|
||||||
|
foreach (self::$m_aActionCodes as $iActionCode => $sAction)
|
||||||
|
{
|
||||||
|
if ($bNewUser)
|
||||||
|
{
|
||||||
$bAddCell = true;
|
$bAddCell = true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
|
||||||
$bAddCell = ($oSet->Count() < 1);
|
$bAddCell = ($oSet->Count() < 1);
|
||||||
}
|
}
|
||||||
if ($bAddCell) {
|
if ($bAddCell)
|
||||||
|
{
|
||||||
// Create a new entry
|
// Create a new entry
|
||||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
|
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
|
||||||
$oMyClassGrant->Set("userid", $iUserId);
|
$oMyClassGrant->Set("userid", $iUserId);
|
||||||
@@ -173,14 +185,19 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
|
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
|
||||||
if ($bNewUser) {
|
{
|
||||||
|
if ($bNewUser)
|
||||||
|
{
|
||||||
$bAddCell = true;
|
$bAddCell = true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
|
||||||
$bAddCell = ($oSet->Count() < 1);
|
$bAddCell = ($oSet->Count() < 1);
|
||||||
}
|
}
|
||||||
if ($bAddCell) {
|
if ($bAddCell)
|
||||||
|
{
|
||||||
// Create a new entry
|
// Create a new entry
|
||||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
|
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
|
||||||
$oMyClassGrant->Set("userid", $iUserId);
|
$oMyClassGrant->Set("userid", $iUserId);
|
||||||
@@ -190,15 +207,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) {
|
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
|
||||||
if ($bNewUser) {
|
{
|
||||||
|
if ($bNewUser)
|
||||||
|
{
|
||||||
$bAddCell = true;
|
$bAddCell = true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
|
||||||
$bAddCell = ($oSet->Count() < 1);
|
$bAddCell = ($oSet->Count() < 1);
|
||||||
}
|
}
|
||||||
if ($bAddCell) {
|
if ($bAddCell)
|
||||||
foreach (['read', 'modify'] as $sAction) {
|
{
|
||||||
|
foreach (array('read', 'modify') as $sAction)
|
||||||
|
{
|
||||||
// Create a new entry
|
// Create a new entry
|
||||||
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
|
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
|
||||||
$oMyAttGrant->Set("userid", $iUserId);
|
$oMyAttGrant->Set("userid", $iUserId);
|
||||||
@@ -239,13 +262,14 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function Init()
|
public function Init()
|
||||||
{
|
{
|
||||||
// Could be loaded in a shared memory (?)
|
// Could be loaded in a shared memory (?)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||||
{
|
{
|
||||||
$oNullFilter = new DBObjectSearch($sClass);
|
$oNullFilter = new DBObjectSearch($sClass);
|
||||||
return $oNullFilter;
|
return $oNullFilter;
|
||||||
@@ -253,18 +277,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
|
|
||||||
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
|
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
|
||||||
{
|
{
|
||||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
|
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||||
|
{
|
||||||
return UR_ALLOWED_NO;
|
return UR_ALLOWED_NO;
|
||||||
}
|
}
|
||||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||||
|
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
|
||||||
if ($oSet->Count() < 1) {
|
if ($oSet->Count() < 1)
|
||||||
|
{
|
||||||
return UR_ALLOWED_NO;
|
return UR_ALLOWED_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oGrantRecord = $oSet->Fetch();
|
$oGrantRecord = $oSet->Fetch();
|
||||||
switch ($oGrantRecord->Get('permission')) {
|
switch ($oGrantRecord->Get('permission'))
|
||||||
|
{
|
||||||
case 'yes':
|
case 'yes':
|
||||||
$iRetCode = UR_ALLOWED_YES;
|
$iRetCode = UR_ALLOWED_YES;
|
||||||
break;
|
break;
|
||||||
@@ -278,18 +305,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
|
|
||||||
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
|
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
|
||||||
{
|
{
|
||||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
|
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||||
|
{
|
||||||
return UR_ALLOWED_NO;
|
return UR_ALLOWED_NO;
|
||||||
}
|
}
|
||||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||||
|
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
|
||||||
if ($oSet->Count() < 1) {
|
if ($oSet->Count() < 1)
|
||||||
|
{
|
||||||
return UR_ALLOWED_NO;
|
return UR_ALLOWED_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oGrantRecord = $oSet->Fetch();
|
$oGrantRecord = $oSet->Fetch();
|
||||||
switch ($oGrantRecord->Get('permission')) {
|
switch ($oGrantRecord->Get('permission'))
|
||||||
|
{
|
||||||
case 'yes':
|
case 'yes':
|
||||||
$iRetCode = UR_ALLOWED_YES;
|
$iRetCode = UR_ALLOWED_YES;
|
||||||
break;
|
break;
|
||||||
@@ -304,12 +334,14 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
|
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
|
||||||
{
|
{
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = '{$oUser->GetKey()}'"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = '{$oUser->GetKey()}'"));
|
||||||
if ($oSet->Count() < 1) {
|
if ($oSet->Count() < 1)
|
||||||
|
{
|
||||||
return UR_ALLOWED_NO;
|
return UR_ALLOWED_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oGrantRecord = $oSet->Fetch();
|
$oGrantRecord = $oSet->Fetch();
|
||||||
switch ($oGrantRecord->Get('permission')) {
|
switch ($oGrantRecord->Get('permission'))
|
||||||
|
{
|
||||||
case 'yes':
|
case 'yes':
|
||||||
$iRetCode = UR_ALLOWED_YES;
|
$iRetCode = UR_ALLOWED_YES;
|
||||||
break;
|
break;
|
||||||
@@ -327,3 +359,5 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserRights::SelectModule('UserRightsMatrix');
|
UserRights::SelectModule('UserRightsMatrix');
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -21,7 +20,7 @@
|
|||||||
* UserRightsNull
|
* UserRightsNull
|
||||||
* User management Module - say Yeah! to everything
|
* User management Module - say Yeah! to everything
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -48,7 +47,7 @@ class UserRightsNull extends UserRightsAddOnAPI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||||
{
|
{
|
||||||
$oNullFilter = new DBObjectSearch($sClass);
|
$oNullFilter = new DBObjectSearch($sClass);
|
||||||
return $oNullFilter;
|
return $oNullFilter;
|
||||||
@@ -75,3 +74,5 @@ class UserRightsNull extends UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserRights::SelectModule('UserRightsNull');
|
UserRights::SelectModule('UserRightsNull');
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
|
||||||
|
|
||||||
define('ADMIN_PROFILE_NAME', 'Administrator');
|
define('ADMIN_PROFILE_NAME', 'Administrator');
|
||||||
define('PORTAL_PROFILE_NAME', 'Portal user');
|
define('PORTAL_PROFILE_NAME', 'Portal user');
|
||||||
|
|
||||||
class UserRightsBaseClassGUI extends cmdbAbstractObject
|
class UserRightsBaseClassGUI extends cmdbAbstractObject
|
||||||
{
|
{
|
||||||
// Whenever something changes, reload the privileges
|
// Whenever something changes, reload the privileges
|
||||||
|
|
||||||
protected function AfterInsert()
|
protected function AfterInsert()
|
||||||
{
|
{
|
||||||
UserRights::FlushPrivileges();
|
UserRights::FlushPrivileges();
|
||||||
@@ -30,77 +27,86 @@ class UserRightsBaseClassGUI extends cmdbAbstractObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class URP_Profiles extends UserRightsBaseClassGUI
|
class URP_Profiles extends UserRightsBaseClassGUI
|
||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights,grant_by_profile,filter",
|
"category" => "addon/userrights,grant_by_profile,filter",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "name",
|
"name_attcode" => "name",
|
||||||
"complementary_name_attcode" => ['description'],
|
"state_attcode" => "",
|
||||||
"state_attcode" => "",
|
"reconc_keys" => array(),
|
||||||
"reconc_keys" => [],
|
"db_table" => "priv_urp_profiles",
|
||||||
"db_table" => "priv_urp_profiles",
|
"db_key_field" => "id",
|
||||||
"db_key_field" => "id",
|
"db_finalclass_field" => "",
|
||||||
"db_finalclass_field" => "",
|
);
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["allowed_values" => null, "sql" => "name", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("user_list", ["linked_class" => "URP_UserProfile", "ext_key_to_me" => "profileid", "ext_key_to_remote" => "userid", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("user_list", array("linked_class"=>"URP_UserProfile", "ext_key_to_me"=>"profileid", "ext_key_to_remote"=>"userid", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'user_list']); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('name', 'description', 'user_list')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['name','description']); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('name','description')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('default_search', ['name','description']);
|
MetaModel::Init_SetZListItems('default_search', array ('name','description'));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static $m_aCacheProfiles = null;
|
protected static $m_aCacheProfiles = null;
|
||||||
|
|
||||||
public static function DoCreateProfile($sName, $sDescription)
|
public static function DoCreateProfile($sName, $sDescription)
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_aCacheProfiles)) {
|
if (is_null(self::$m_aCacheProfiles))
|
||||||
self::$m_aCacheProfiles = [];
|
{
|
||||||
|
self::$m_aCacheProfiles = array();
|
||||||
$oFilterAll = new DBObjectSearch('URP_Profiles');
|
$oFilterAll = new DBObjectSearch('URP_Profiles');
|
||||||
$oSet = new DBObjectSet($oFilterAll);
|
$oSet = new DBObjectSet($oFilterAll);
|
||||||
while ($oProfile = $oSet->Fetch()) {
|
while ($oProfile = $oSet->Fetch())
|
||||||
|
{
|
||||||
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
|
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sCacheKey = $sName;
|
$sCacheKey = $sName;
|
||||||
if (isset(self::$m_aCacheProfiles[$sCacheKey])) {
|
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
|
||||||
|
{
|
||||||
return self::$m_aCacheProfiles[$sCacheKey];
|
return self::$m_aCacheProfiles[$sCacheKey];
|
||||||
}
|
}
|
||||||
$oNewObj = MetaModel::NewObject("URP_Profiles");
|
$oNewObj = MetaModel::NewObject("URP_Profiles");
|
||||||
$oNewObj->Set('name', $sName);
|
$oNewObj->Set('name', $sName);
|
||||||
$oNewObj->Set('description', $sDescription);
|
$oNewObj->Set('description', $sDescription);
|
||||||
$iId = $oNewObj->DBInsertNoReload();
|
$iId = $oNewObj->DBInsertNoReload();
|
||||||
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
||||||
return $iId;
|
return $iId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
||||||
{
|
{
|
||||||
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
|
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
|
||||||
if (is_null($bGrant)) {
|
if (is_null($bGrant))
|
||||||
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
{
|
||||||
} elseif ($bGrant) {
|
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||||
return '<span class="ibo-user-rights ibo-is-success">'.Dict::S('UI:UserManagement:ActionAllowed:Yes').'</span>';
|
}
|
||||||
} else {
|
elseif ($bGrant)
|
||||||
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
{
|
||||||
|
return '<span style="background-color: #ddffdd;">'.Dict::S('UI:UserManagement:ActionAllowed:Yes').'</span>';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DoShowGrantSumary($oPage)
|
function DoShowGrantSumary($oPage)
|
||||||
{
|
{
|
||||||
if ($this->GetRawName() == "Administrator") {
|
if ($this->GetRawName() == "Administrator")
|
||||||
|
{
|
||||||
// Looks dirty, but ok that's THE ONE
|
// Looks dirty, but ok that's THE ONE
|
||||||
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
|
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
|
||||||
return;
|
return;
|
||||||
@@ -108,19 +114,22 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
|
|
||||||
// Note: for sure, we assume that the instance is derived from UserRightsProfile
|
// Note: for sure, we assume that the instance is derived from UserRightsProfile
|
||||||
$oUserRights = UserRights::GetModuleInstance();
|
$oUserRights = UserRights::GetModuleInstance();
|
||||||
|
|
||||||
$aDisplayData = [];
|
$aDisplayData = array();
|
||||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
|
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
|
||||||
$aStimuli = [];
|
{
|
||||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
|
$aStimuli = array();
|
||||||
|
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
|
||||||
|
{
|
||||||
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
|
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
|
||||||
if ($bGrant === true) {
|
if ($bGrant === true)
|
||||||
$aStimuli[] = '<span title="'.$sStimulusCode.': '.utils::EscapeHtml($oStimulus->GetDescription()).'">'.utils::EscapeHtml($oStimulus->GetLabel()).'</span>';
|
{
|
||||||
|
$aStimuli[] = '<span title="'.$sStimulusCode.': '.htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8').'">'.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').'</span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sStimuli = implode(', ', $aStimuli);
|
$sStimuli = implode(', ', $aStimuli);
|
||||||
|
|
||||||
$aDisplayData[] = [
|
$aDisplayData[] = array(
|
||||||
'class' => MetaModel::GetName($sClass),
|
'class' => MetaModel::GetName($sClass),
|
||||||
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
|
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
|
||||||
'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'),
|
'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'),
|
||||||
@@ -129,22 +138,22 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'),
|
'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'),
|
||||||
'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'),
|
'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'),
|
||||||
'stimuli' => $sStimuli,
|
'stimuli' => $sStimuli,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$aDisplayConfig = [];
|
$aDisplayConfig = array();
|
||||||
$aDisplayConfig['class'] = ['label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+')];
|
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
|
||||||
$aDisplayConfig['read'] = ['label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+')];
|
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
|
||||||
$aDisplayConfig['bulkread'] = ['label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+')];
|
$aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
|
||||||
$aDisplayConfig['write'] = ['label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+')];
|
$aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
|
||||||
$aDisplayConfig['bulkwrite'] = ['label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+')];
|
$aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
|
||||||
$aDisplayConfig['delete'] = ['label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+')];
|
$aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+'));
|
||||||
$aDisplayConfig['bulkdelete'] = ['label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+')];
|
$aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+'));
|
||||||
$aDisplayConfig['stimuli'] = ['label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+')];
|
$aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
|
||||||
$oPage->table($aDisplayConfig, $aDisplayData);
|
$oPage->table($aDisplayConfig, $aDisplayData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||||
{
|
{
|
||||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||||
|
|
||||||
@@ -154,9 +163,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
|
|
||||||
public static function GetReadOnlyAttributes()
|
public static function GetReadOnlyAttributes()
|
||||||
{
|
{
|
||||||
return ['name', 'description'];
|
return array('name', 'description');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns an array of id => array of column => php value(so-called "real value")
|
// returns an array of id => array of column => php value(so-called "real value")
|
||||||
public static function GetPredefinedObjects()
|
public static function GetPredefinedObjects()
|
||||||
{
|
{
|
||||||
@@ -168,13 +178,15 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
protected function OnDelete()
|
protected function OnDelete()
|
||||||
{
|
{
|
||||||
// Don't remove admin profile
|
// Don't remove admin profile
|
||||||
if ($this->Get('name') === ADMIN_PROFILE_NAME) {
|
if ($this->Get('name') === ADMIN_PROFILE_NAME)
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
|
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: this may break the rule that says: "a user must have at least ONE profile" !
|
// Note: this may break the rule that says: "a user must have at least ONE profile" !
|
||||||
$oLnkSet = $this->Get('user_list');
|
$oLnkSet = $this->Get('user_list');
|
||||||
while ($oLnk = $oLnkSet->Fetch()) {
|
while($oLnk = $oLnkSet->Fetch())
|
||||||
|
{
|
||||||
$oLnk->DBDelete();
|
$oLnk->DBDelete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,11 +198,12 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
|
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
|
||||||
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
|
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
|
||||||
* @return integer Flags: the binary combination of the flags applicable to this attribute
|
* @return integer Flags: the binary combination of the flags applicable to this attribute
|
||||||
*/
|
*/
|
||||||
public function GetAttributeFlags($sAttCode, &$aReasons = [], $sTargetState = '')
|
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||||
{
|
{
|
||||||
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||||
|
{
|
||||||
$aReasons[] = 'Sorry, profiles are read-only in the demonstration mode!';
|
$aReasons[] = 'Sorry, profiles are read-only in the demonstration mode!';
|
||||||
$iFlags |= OPT_ATT_READONLY;
|
$iFlags |= OPT_ATT_READONLY;
|
||||||
}
|
}
|
||||||
@@ -198,52 +211,39 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class URP_UserProfile extends UserRightsBaseClassGUI
|
class URP_UserProfile extends UserRightsBaseClassGUI
|
||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights,grant_by_profile,filter",
|
"category" => "addon/userrights,grant_by_profile,filter",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => ["userlogin", "profile"],
|
"name_attcode" => array("userlogin", "profile"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => [],
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"is_link" => true, /** @since 3.1.0 N°6482 */
|
);
|
||||||
'uniqueness_rules' => [
|
|
||||||
'no_duplicate' => [
|
|
||||||
'attributes' => [
|
|
||||||
0 => 'userid',
|
|
||||||
1 => 'profileid',
|
|
||||||
],
|
|
||||||
'filter' => '',
|
|
||||||
'disabled' => false,
|
|
||||||
'is_blocking' => true,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey(
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||||
"profileid",
|
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
|
||||||
["targetclass" => "URP_Profiles", "jointype" => "", "allowed_values" => null, "sql" => "profileid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => [], "allow_target_creation" => false]
|
|
||||||
));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", ["allowed_values" => null, "extkey_attcode" => 'profileid', "target_attcode" => "name"]));
|
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', ['userid', 'profileid', 'reason']); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('userid', 'profileid', 'reason')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', ['userid', 'profileid', 'reason']); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('userid', 'profileid', 'reason')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['userid', 'profileid']); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('advanced_search', ['userid', 'profileid']); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function CheckToDelete(&$oDeletionPlan)
|
public function CheckToDelete(&$oDeletionPlan)
|
||||||
@@ -251,14 +251,15 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||||
// Users deletion is NOT allowed in demo mode
|
// Users deletion is NOT allowed in demo mode
|
||||||
$oDeletionPlan->AddToDelete($this, null);
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
|
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||||
$oDeletionPlan->ComputeResults();
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||||
} catch (SecurityException $e) {
|
}
|
||||||
|
catch (SecurityException $e) {
|
||||||
// Users deletion is NOT allowed
|
// Users deletion is NOT allowed
|
||||||
$oDeletionPlan->AddToDelete($this, null);
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||||
@@ -275,14 +276,15 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||||
// Users deletion is NOT allowed in demo mode
|
// Users deletion is NOT allowed in demo mode
|
||||||
$oDeletionPlan->AddToDelete($this, null);
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
|
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||||
$oDeletionPlan->ComputeResults();
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||||
} catch (SecurityException $e) {
|
}
|
||||||
|
catch (SecurityException $e) {
|
||||||
// Users deletion is NOT allowed
|
// Users deletion is NOT allowed
|
||||||
$oDeletionPlan->AddToDelete($this, null);
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||||
@@ -318,26 +320,29 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
protected function CheckIfProfileIsAllowed($iActionCode)
|
protected function CheckIfProfileIsAllowed($iActionCode)
|
||||||
{
|
{
|
||||||
// When initializing or admin, we need to let everything pass trough
|
// When initializing or admin, we need to let everything pass trough
|
||||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
|
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only administrators can manage administrators
|
// Only administrators can manage administrators
|
||||||
$iOrigUserId = $this->GetOriginal('userid');
|
$iOrigUserId = $this->GetOriginal('userid');
|
||||||
if (!empty($iOrigUserId)) {
|
if (!empty($iOrigUserId))
|
||||||
|
{
|
||||||
$oUser = MetaModel::GetObject('User', $iOrigUserId, true, true);
|
$oUser = MetaModel::GetObject('User', $iOrigUserId, true, true);
|
||||||
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator()) {
|
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator())
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
|
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$oUser = MetaModel::GetObject('User', $this->Get('userid'), true, true);
|
$oUser = MetaModel::GetObject('User', $this->Get('userid'), true, true);
|
||||||
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator()) {
|
if (UserRights::IsAdministrator($oUser) && !UserRights::IsAdministrator())
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
|
throw new SecurityException(Dict::Format('UI:Login:Error:AccessRestricted'));
|
||||||
}
|
}
|
||||||
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, DBObjectSet::FromObject($this))) {
|
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, DBObjectSet::FromObject($this)))
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('UI:Error:ObjectCannotBeUpdated'));
|
throw new SecurityException(Dict::Format('UI:Error:ObjectCannotBeUpdated'));
|
||||||
}
|
}
|
||||||
if (!UserRights::IsAdministrator() && ($this->Get('profile') === ADMIN_PROFILE_NAME)) {
|
if (!UserRights::IsAdministrator() && ($this->Get('profile') === ADMIN_PROFILE_NAME))
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
|
throw new SecurityException(Dict::Format('UI:Login:Error:AccessAdmin'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,33 +353,33 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "addon/userrights,grant_by_profile",
|
"category" => "addon/userrights,grant_by_profile",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => ["userlogin", "allowed_org_name"],
|
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => [],
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userorg",
|
"db_table" => "priv_urp_userorg",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
];
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("allowed_org_id", ["targetclass" => "Organization", "jointype" => "", "allowed_values" => null, "sql" => "allowed_org_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("allowed_org_id", array("targetclass"=>"Organization", "jointype"=> "", "allowed_values"=>null, "sql"=>"allowed_org_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("allowed_org_name", ["allowed_values" => null, "extkey_attcode" => 'allowed_org_id', "target_attcode" => "name"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("allowed_org_name", array("allowed_values"=>null, "extkey_attcode"=> 'allowed_org_id', "target_attcode"=>"name")));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "reason", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"reason", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', ['userid', 'allowed_org_id', 'reason']); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('userid', 'allowed_org_id', 'reason')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', ['allowed_org_id', 'reason']); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('allowed_org_id', 'reason')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['userid', 'allowed_org_id']); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('advanced_search', ['userid', 'allowed_org_id']); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function OnInsert()
|
protected function OnInsert()
|
||||||
@@ -397,58 +402,58 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
*/
|
*/
|
||||||
protected function CheckIfOrgIsAllowed()
|
protected function CheckIfOrgIsAllowed()
|
||||||
{
|
{
|
||||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
|
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oUser = UserRights::GetUserObject();
|
$oUser = UserRights::GetUserObject();
|
||||||
$oAddon = UserRights::GetModuleInstance();
|
$oAddon = UserRights::GetModuleInstance();
|
||||||
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
|
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
|
||||||
if (count($aOrgs) > 0) {
|
if (count($aOrgs) > 0)
|
||||||
|
{
|
||||||
$iOrigOrgId = $this->GetOriginal('allowed_org_id');
|
$iOrigOrgId = $this->GetOriginal('allowed_org_id');
|
||||||
if ((!empty($iOrigOrgId) && !in_array($iOrigOrgId, $aOrgs)) || !in_array($this->Get('allowed_org_id'), $aOrgs)) {
|
if ((!empty($iOrigOrgId) && !in_array($iOrigOrgId, $aOrgs)) || !in_array($this->Get('allowed_org_id'), $aOrgs))
|
||||||
|
{
|
||||||
throw new SecurityException(Dict::Format('Class:User/Error:OrganizationNotAllowed'));
|
throw new SecurityException(Dict::Format('Class:User/Error:OrganizationNotAllowed'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserRightsProfile extends UserRightsAddOnAPI
|
class UserRightsProfile extends UserRightsAddOnAPI
|
||||||
{
|
{
|
||||||
public static $m_aActionCodes = [
|
static public $m_aActionCodes = array(
|
||||||
UR_ACTION_READ => 'r',
|
UR_ACTION_READ => 'r',
|
||||||
UR_ACTION_MODIFY => 'w',
|
UR_ACTION_MODIFY => 'w',
|
||||||
UR_ACTION_DELETE => 'd',
|
UR_ACTION_DELETE => 'd',
|
||||||
UR_ACTION_BULK_READ => 'br',
|
UR_ACTION_BULK_READ => 'br',
|
||||||
UR_ACTION_BULK_MODIFY => 'bw',
|
UR_ACTION_BULK_MODIFY => 'bw',
|
||||||
UR_ACTION_BULK_DELETE => 'bd',
|
UR_ACTION_BULK_DELETE => 'bd',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
|
|
||||||
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
|
|
||||||
*/
|
|
||||||
private $aUsersProfilesList = [];
|
|
||||||
|
|
||||||
// Installation: create the very first user
|
// Installation: create the very first user
|
||||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||||
{
|
{
|
||||||
CMDBObject::SetCurrentChangeFromParams('Initialization create administrator');
|
CMDBObject::SetTrackInfo('Initialization');
|
||||||
|
|
||||||
$iContactId = 0;
|
$iContactId = 0;
|
||||||
// Support drastic data model changes: no organization class (or not writable)!
|
// Support drastic data model changes: no organization class (or not writable)!
|
||||||
if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization')) {
|
if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization'))
|
||||||
|
{
|
||||||
$oOrg = MetaModel::NewObject('Organization');
|
$oOrg = MetaModel::NewObject('Organization');
|
||||||
$oOrg->Set('name', 'My Company/Department');
|
$oOrg->Set('name', 'My Company/Department');
|
||||||
$oOrg->Set('code', 'SOMECODE');
|
$oOrg->Set('code', 'SOMECODE');
|
||||||
$iOrgId = $oOrg->DBInsertNoReload();
|
$iOrgId = $oOrg->DBInsertNoReload();
|
||||||
|
|
||||||
// Support drastic data model changes: no Person class (or not writable)!
|
// Support drastic data model changes: no Person class (or not writable)!
|
||||||
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person')) {
|
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person'))
|
||||||
|
{
|
||||||
$oContact = MetaModel::NewObject('Person');
|
$oContact = MetaModel::NewObject('Person');
|
||||||
$oContact->Set('name', 'My last name');
|
$oContact->Set('name', 'My last name');
|
||||||
$oContact->Set('first_name', 'My first name');
|
$oContact->Set('first_name', 'My first name');
|
||||||
if (MetaModel::IsValidAttCode('Person', 'org_id')) {
|
if (MetaModel::IsValidAttCode('Person', 'org_id'))
|
||||||
|
{
|
||||||
$oContact->Set('org_id', $iOrgId);
|
$oContact->Set('org_id', $iOrgId);
|
||||||
}
|
}
|
||||||
$oContact->Set('email', 'my.email@foo.org');
|
$oContact->Set('email', 'my.email@foo.org');
|
||||||
@@ -456,17 +461,20 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$oUser = new UserLocal();
|
$oUser = new UserLocal();
|
||||||
$oUser->Set('login', $sAdminUser);
|
$oUser->Set('login', $sAdminUser);
|
||||||
$oUser->Set('password', $sAdminPwd);
|
$oUser->Set('password', $sAdminPwd);
|
||||||
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0)) {
|
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0))
|
||||||
|
{
|
||||||
$oUser->Set('contactid', $iContactId);
|
$oUser->Set('contactid', $iContactId);
|
||||||
}
|
}
|
||||||
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
||||||
|
|
||||||
// Add this user to the very specific 'admin' profile
|
// Add this user to the very specific 'admin' profile
|
||||||
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => ADMIN_PROFILE_NAME], true /*all data*/);
|
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true /*all data*/);
|
||||||
if (is_object($oAdminProfile)) {
|
if (is_object($oAdminProfile))
|
||||||
|
{
|
||||||
$oUserProfile = new URP_UserProfile();
|
$oUserProfile = new URP_UserProfile();
|
||||||
$oUserProfile->Set('profileid', $oAdminProfile->GetKey());
|
$oUserProfile->Set('profileid', $oAdminProfile->GetKey());
|
||||||
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
||||||
@@ -481,11 +489,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $m_aUserOrgs = []; // userid -> array of orgid
|
protected $m_aUserOrgs = array(); // userid -> array of orgid
|
||||||
protected $m_aAdministrators = null; // [user id]
|
|
||||||
|
|
||||||
// Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read)
|
// Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read)
|
||||||
protected $m_aObjectActionGrants = [];
|
protected $m_aObjectActionGrants = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read and cache organizations allowed to the given user
|
* Read and cache organizations allowed to the given user
|
||||||
@@ -500,25 +507,31 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
public function GetUserOrgs($oUser, $sClass)
|
public function GetUserOrgs($oUser, $sClass)
|
||||||
{
|
{
|
||||||
$iUser = $oUser->GetKey();
|
$iUser = $oUser->GetKey();
|
||||||
if (!array_key_exists($iUser, $this->m_aUserOrgs)) {
|
if (!array_key_exists($iUser, $this->m_aUserOrgs))
|
||||||
$this->m_aUserOrgs[$iUser] = [];
|
{
|
||||||
|
$this->m_aUserOrgs[$iUser] = array();
|
||||||
|
|
||||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
|
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
|
||||||
if ($sHierarchicalKeyCode !== false) {
|
if ($sHierarchicalKeyCode !== false)
|
||||||
|
{
|
||||||
$sUserOrgQuery = 'SELECT UserOrg, Org FROM Organization AS Org JOIN Organization AS Root ON Org.'.$sHierarchicalKeyCode.' BELOW Root.id JOIN URP_UserOrg AS UserOrg ON UserOrg.allowed_org_id = Root.id WHERE UserOrg.userid = :userid';
|
$sUserOrgQuery = 'SELECT UserOrg, Org FROM Organization AS Org JOIN Organization AS Root ON Org.'.$sHierarchicalKeyCode.' BELOW Root.id JOIN URP_UserOrg AS UserOrg ON UserOrg.allowed_org_id = Root.id WHERE UserOrg.userid = :userid';
|
||||||
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), [], ['userid' => $iUser]);
|
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), array(), array('userid' => $iUser));
|
||||||
while ($aRow = $oUserOrgSet->FetchAssoc()) {
|
while ($aRow = $oUserOrgSet->FetchAssoc())
|
||||||
|
{
|
||||||
$oOrg = $aRow['Org'];
|
$oOrg = $aRow['Org'];
|
||||||
$this->m_aUserOrgs[$iUser][] = $oOrg->GetKey();
|
$this->m_aUserOrgs[$iUser][] = $oOrg->GetKey();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oSearch = new DBObjectSearch('URP_UserOrg');
|
$oSearch = new DBObjectSearch('URP_UserOrg');
|
||||||
$oSearch->AllowAllData();
|
$oSearch->AllowAllData();
|
||||||
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
|
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
|
||||||
$oSearch->AddConditionExpression($oCondition);
|
$oSearch->AddConditionExpression($oCondition);
|
||||||
|
|
||||||
$oUserOrgSet = new DBObjectSet($oSearch, [], ['userid' => $iUser]);
|
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
|
||||||
while ($oUserOrg = $oUserOrgSet->Fetch()) {
|
while ($oUserOrg = $oUserOrgSet->Fetch())
|
||||||
|
{
|
||||||
$this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id');
|
$this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,19 +542,20 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
public function ResetCache()
|
public function ResetCache()
|
||||||
{
|
{
|
||||||
// Loaded by Load cache
|
// Loaded by Load cache
|
||||||
$this->m_aUserOrgs = [];
|
$this->m_aUserOrgs = array();
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
$this->m_aObjectActionGrants = [];
|
$this->m_aObjectActionGrants = array();
|
||||||
$this->m_aAdministrators = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LoadCache()
|
public function LoadCache()
|
||||||
{
|
{
|
||||||
static $bSharedObjectInitialized = false;
|
static $bSharedObjectInitialized = false;
|
||||||
if (!$bSharedObjectInitialized) {
|
if (!$bSharedObjectInitialized)
|
||||||
|
{
|
||||||
$bSharedObjectInitialized = true;
|
$bSharedObjectInitialized = true;
|
||||||
if (self::HasSharing()) {
|
if (self::HasSharing())
|
||||||
|
{
|
||||||
SharedObject::InitSharedClassProperties();
|
SharedObject::InitSharedClassProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -579,40 +593,45 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
*/
|
*/
|
||||||
public function ListProfiles($oUser)
|
public function ListProfiles($oUser)
|
||||||
{
|
{
|
||||||
$aRet = [];
|
$aRet = array();
|
||||||
$oSearch = new DBObjectSearch('URP_UserProfile');
|
$oSearch = new DBObjectSearch('URP_UserProfile');
|
||||||
$oSearch->AllowAllData();
|
$oSearch->AllowAllData();
|
||||||
$oSearch->NoContextParameters();
|
$oSearch->NoContextParameters();
|
||||||
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
|
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
|
||||||
$oProfiles = new DBObjectSet($oSearch);
|
$oProfiles = new DBObjectSet($oSearch);
|
||||||
while ($oUserProfile = $oProfiles->Fetch()) {
|
while ($oUserProfile = $oProfiles->Fetch())
|
||||||
|
{
|
||||||
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
||||||
}
|
}
|
||||||
return $aRet;
|
return $aRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||||
{
|
{
|
||||||
$this->LoadCache();
|
$this->LoadCache();
|
||||||
|
|
||||||
// Let us pass an administrator for bypassing the grant matrix check in order to test this method without the need to set up a complex profile
|
// Let us pass an administrator for bypassing the grant matrix check in order to test this method without the need to set up a complex profile
|
||||||
// In the nominal case Administrators never end up here (since they completely bypass GetSelectFilter)
|
// In the nominal case Administrators never end up here (since they completely bypass GetSelectFilter)
|
||||||
if (!static::IsAdministrator($oUser) && (MetaModel::HasCategory($sClass, 'silo') || MetaModel::HasCategory($sClass, 'bizmodel'))) {
|
if (!static::IsAdministrator($oUser) && (MetaModel::HasCategory($sClass, 'silo') || MetaModel::HasCategory($sClass, 'bizmodel')))
|
||||||
|
{
|
||||||
// N°4354 - Categories 'silo' and 'bizmodel' do check the grant matrix. Whereas 'filter' always allows to read (but the result can be filtered)
|
// N°4354 - Categories 'silo' and 'bizmodel' do check the grant matrix. Whereas 'filter' always allows to read (but the result can be filtered)
|
||||||
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
|
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
|
||||||
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO) {
|
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oFilter = true;
|
$oFilter = true;
|
||||||
$aConditions = [];
|
$aConditions = array();
|
||||||
|
|
||||||
// Determine if this class is part of a silo and build the filter for it
|
// Determine if this class is part of a silo and build the filter for it
|
||||||
$sAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
$sAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||||
if (!is_null($sAttCode)) {
|
if (!is_null($sAttCode))
|
||||||
|
{
|
||||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||||
if (count($aUserOrgs) > 0) {
|
if (count($aUserOrgs) > 0)
|
||||||
|
{
|
||||||
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
|
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
|
||||||
}
|
}
|
||||||
// else: No org means 'any org'
|
// else: No org means 'any org'
|
||||||
@@ -621,15 +640,20 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
|
|
||||||
// Specific conditions to hide, for non-administrators, the Administrator Users, the Administrator Profile and related links
|
// Specific conditions to hide, for non-administrators, the Administrator Users, the Administrator Profile and related links
|
||||||
// Note: when logged as an administrator, GetSelectFilter is completely bypassed.
|
// Note: when logged as an administrator, GetSelectFilter is completely bypassed.
|
||||||
if ($this->AdministratorsAreHidden()) {
|
if ($this->AdministratorsAreHidden())
|
||||||
if ($sClass == 'URP_Profiles') {
|
{
|
||||||
|
if ($sClass == 'URP_Profiles')
|
||||||
|
{
|
||||||
$oExpression = new FieldExpression('id', $sClass);
|
$oExpression = new FieldExpression('id', $sClass);
|
||||||
$oScalarExpr = new ScalarExpression(1);
|
$oScalarExpr = new ScalarExpression(1);
|
||||||
|
|
||||||
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
|
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
|
||||||
} elseif (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User'))) {
|
}
|
||||||
|
else if (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User')))
|
||||||
|
{
|
||||||
$aAdministrators = $this->GetAdministrators();
|
$aAdministrators = $this->GetAdministrators();
|
||||||
if (count($aAdministrators) > 0) {
|
if (count($aAdministrators) > 0)
|
||||||
|
{
|
||||||
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
|
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
|
||||||
$oExpression = new FieldExpression($sAttCode, $sClass);
|
$oExpression = new FieldExpression($sAttCode, $sClass);
|
||||||
$oListExpr = ListExpression::FromScalars($aAdministrators);
|
$oListExpr = ListExpression::FromScalars($aAdministrators);
|
||||||
@@ -639,14 +663,17 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handling of the added conditions
|
// Handling of the added conditions
|
||||||
if (count($aConditions) > 0) {
|
if (count($aConditions) > 0)
|
||||||
if ($oFilter === true) {
|
{
|
||||||
|
if($oFilter === true)
|
||||||
|
{
|
||||||
// No 'silo' filter, let's build a clean one
|
// No 'silo' filter, let's build a clean one
|
||||||
$oFilter = new DBObjectSearch($sClass);
|
$oFilter = new DBObjectSearch($sClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the conditions to the filter
|
// Add the conditions to the filter
|
||||||
foreach ($aConditions as $oCondition) {
|
foreach($aConditions as $oCondition)
|
||||||
|
{
|
||||||
$oFilter->AddConditionExpression($oCondition);
|
$oFilter->AddConditionExpression($oCondition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -661,9 +688,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
*/
|
*/
|
||||||
private function GetAdministrators()
|
private function GetAdministrators()
|
||||||
{
|
{
|
||||||
if ($this->m_aAdministrators === null) {
|
static $aAdministrators = null;
|
||||||
|
|
||||||
|
if ($aAdministrators === null)
|
||||||
|
{
|
||||||
// Find all administrators
|
// Find all administrators
|
||||||
$this->m_aAdministrators = [];
|
$aAdministrators = array();
|
||||||
$oAdministratorsFilter = new DBObjectSearch('User');
|
$oAdministratorsFilter = new DBObjectSearch('User');
|
||||||
$oLnkFilter = new DBObjectSearch('URP_UserProfile');
|
$oLnkFilter = new DBObjectSearch('URP_UserProfile');
|
||||||
$oExpression = new FieldExpression('profileid', 'URP_UserProfile');
|
$oExpression = new FieldExpression('profileid', 'URP_UserProfile');
|
||||||
@@ -673,12 +703,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
|
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
|
||||||
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
|
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
|
||||||
$oSet = new DBObjectSet($oAdministratorsFilter);
|
$oSet = new DBObjectSet($oAdministratorsFilter);
|
||||||
$oSet->OptimizeColumnLoad(['User' => ['login']]);
|
$oSet->OptimizeColumnLoad(array('User' => array('login')));
|
||||||
while ($oUser = $oSet->Fetch()) {
|
while($oUser = $oSet->Fetch())
|
||||||
$this->m_aAdministrators[] = $oUser->GetKey();
|
{
|
||||||
|
$aAdministrators[] = $oUser->GetKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->m_aAdministrators;
|
return $aAdministrators;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -690,6 +721,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
return ((bool)MetaModel::GetConfig()->Get('security.hide_administrators'));
|
return ((bool)MetaModel::GetConfig()->Get('security.hide_administrators'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This verb has been made public to allow the development of an accurate feedback for the current configuration
|
// This verb has been made public to allow the development of an accurate feedback for the current configuration
|
||||||
public function GetProfileActionGrant($iProfile, $sClass, $sAction)
|
public function GetProfileActionGrant($iProfile, $sClass, $sAction)
|
||||||
{
|
{
|
||||||
@@ -706,29 +738,27 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
// load and cache permissions for the current user on the given class
|
// load and cache permissions for the current user on the given class
|
||||||
//
|
//
|
||||||
$iUser = $oUser->GetKey();
|
$iUser = $oUser->GetKey();
|
||||||
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])) {
|
$aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||||
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
if (is_array($aTest)) return $aTest;
|
||||||
if (is_array($aTest)) {
|
|
||||||
return $aTest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||||
|
|
||||||
$bStatus = null;
|
$bStatus = null;
|
||||||
// Cache user's profiles
|
|
||||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
|
||||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
|
||||||
}
|
|
||||||
// Call the API of UserRights because it caches the list for us
|
// Call the API of UserRights because it caches the list for us
|
||||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
|
||||||
|
{
|
||||||
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
|
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
|
||||||
if (!is_null($bGrant)) {
|
if (!is_null($bGrant))
|
||||||
if ($bGrant) {
|
{
|
||||||
if (is_null($bStatus)) {
|
if ($bGrant)
|
||||||
|
{
|
||||||
|
if (is_null($bStatus))
|
||||||
|
{
|
||||||
$bStatus = true;
|
$bStatus = true;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$bStatus = false;
|
$bStatus = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -736,9 +766,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
|
|
||||||
$iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO;
|
$iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO;
|
||||||
|
|
||||||
$aRes = [
|
$aRes = array(
|
||||||
'permission' => $iPermission,
|
'permission' => $iPermission,
|
||||||
];
|
);
|
||||||
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
|
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
|
||||||
return $aRes;
|
return $aRes;
|
||||||
}
|
}
|
||||||
@@ -753,46 +783,64 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
// Note: In most cases the object set is ignored because it was interesting to optimize for huge data sets
|
// Note: In most cases the object set is ignored because it was interesting to optimize for huge data sets
|
||||||
// and acceptable to consider only the root class of the object set
|
// and acceptable to consider only the root class of the object set
|
||||||
|
|
||||||
if ($iPermission != UR_ALLOWED_YES) {
|
if ($iPermission != UR_ALLOWED_YES)
|
||||||
|
{
|
||||||
// It is already NO for everyone... that's the final word!
|
// It is already NO for everyone... that's the final word!
|
||||||
} elseif ($iActionCode == UR_ACTION_READ) {
|
}
|
||||||
|
elseif ($iActionCode == UR_ACTION_READ)
|
||||||
|
{
|
||||||
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
||||||
} elseif ($iActionCode == UR_ACTION_BULK_READ) {
|
}
|
||||||
|
elseif ($iActionCode == UR_ACTION_BULK_READ)
|
||||||
|
{
|
||||||
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
||||||
} elseif ($oInstanceSet) {
|
}
|
||||||
|
elseif ($oInstanceSet)
|
||||||
|
{
|
||||||
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
||||||
// We have to answer NO for objects shared for reading purposes
|
// We have to answer NO for objects shared for reading purposes
|
||||||
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
|
if (self::HasSharing())
|
||||||
// This class is shared, GetSelectFilter may allow some objects for read only
|
{
|
||||||
// But currently we are checking whether the objects might be written...
|
$aClassProps = SharedObject::GetSharedClassProperties($sClass);
|
||||||
// Let's exclude the objects based on the relevant criteria
|
if ($aClassProps)
|
||||||
|
{
|
||||||
|
// This class is shared, GetSelectFilter may allow some objects for read only
|
||||||
|
// But currently we are checking wether the objects might be written...
|
||||||
|
// Let's exclude the objects based on the relevant criteria
|
||||||
|
|
||||||
// Use $oInstanceSet only if sClass is the main class
|
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||||
if (!is_a($oInstanceSet->GetClass(), $sClass, true)) {
|
if (!is_null($sOrgAttCode))
|
||||||
/** @var \DBObjectSet $oInstanceSet */
|
{
|
||||||
throw new CoreException(__FUNCTION__.': Expecting object set to be of class '.$sClass.' but it is of class '.$oInstanceSet->GetClass(), ['OQL_Query' => $oInstanceSet->GetFilter()->ToOQL(), 'classes' => $oInstanceSet->GetSelectedClasses()]);
|
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||||
}
|
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0)
|
||||||
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
{
|
||||||
if (!is_null($sOrgAttCode)) {
|
$iCountNO = 0;
|
||||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
$iCountYES = 0;
|
||||||
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0) {
|
$oInstanceSet->Rewind();
|
||||||
$iCountNO = 0;
|
while($oObject = $oInstanceSet->Fetch())
|
||||||
$iCountYES = 0;
|
{
|
||||||
$oInstanceSet->Rewind();
|
$iOrg = $oObject->Get($sOrgAttCode);
|
||||||
while ($oObject = $oInstanceSet->Fetch()) {
|
if (in_array($iOrg, $aUserOrgs))
|
||||||
$iOrg = $oObject->Get($sOrgAttCode);
|
{
|
||||||
if (in_array($iOrg, $aUserOrgs)) {
|
$iCountYES++;
|
||||||
$iCountYES++;
|
}
|
||||||
} else {
|
else
|
||||||
$iCountNO++;
|
{
|
||||||
|
$iCountNO++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($iCountNO == 0)
|
||||||
|
{
|
||||||
|
$iPermission = UR_ALLOWED_YES;
|
||||||
|
}
|
||||||
|
elseif ($iCountYES == 0)
|
||||||
|
{
|
||||||
|
$iPermission = UR_ALLOWED_NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$iPermission = UR_ALLOWED_DEPENDS;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if ($iCountNO == 0) {
|
|
||||||
$iPermission = UR_ALLOWED_YES;
|
|
||||||
} elseif ($iCountYES == 0) {
|
|
||||||
$iPermission = UR_ALLOWED_NO;
|
|
||||||
} else {
|
|
||||||
$iPermission = UR_ALLOWED_DEPENDS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -823,23 +871,24 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
// Note: this code is VERY close to the code of IsActionAllowed()
|
// Note: this code is VERY close to the code of IsActionAllowed()
|
||||||
$iUser = $oUser->GetKey();
|
$iUser = $oUser->GetKey();
|
||||||
|
|
||||||
// Cache user's profiles
|
|
||||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
|
||||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: The object set is ignored because it was interesting to optimize for huge data sets
|
// Note: The object set is ignored because it was interesting to optimize for huge data sets
|
||||||
// and acceptable to consider only the root class of the object set
|
// and acceptable to consider only the root class of the object set
|
||||||
$bStatus = null;
|
$bStatus = null;
|
||||||
// Call the API of UserRights because it caches the list for us
|
// Call the API of UserRights because it caches the list for us
|
||||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
|
||||||
|
{
|
||||||
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
|
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
|
||||||
if (!is_null($bGrant)) {
|
if (!is_null($bGrant))
|
||||||
if ($bGrant) {
|
{
|
||||||
if (is_null($bStatus)) {
|
if ($bGrant)
|
||||||
|
{
|
||||||
|
if (is_null($bStatus))
|
||||||
|
{
|
||||||
$bStatus = true;
|
$bStatus = true;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$bStatus = false;
|
$bStatus = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -855,24 +904,29 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* Find out which attribute is corresponding the the dimension 'owner org'
|
||||||
* @return string|null Find out which attribute is corresponding the dimension 'owner org'
|
* returns null if no such attribute has been found (no filtering should occur)
|
||||||
* returns null if no such attribute has been found (no filtering should occur)
|
*/
|
||||||
*/
|
|
||||||
public static function GetOwnerOrganizationAttCode($sClass)
|
public static function GetOwnerOrganizationAttCode($sClass)
|
||||||
{
|
{
|
||||||
$sAttCode = null;
|
$sAttCode = null;
|
||||||
|
|
||||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
$aCallSpec = array($sClass, 'MapContextParam');
|
||||||
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization')) {
|
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization'))
|
||||||
|
{
|
||||||
$sAttCode = 'id';
|
$sAttCode = 'id';
|
||||||
} elseif (is_callable($aCallSpec)) {
|
}
|
||||||
|
elseif (is_callable($aCallSpec))
|
||||||
|
{
|
||||||
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
|
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
|
||||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||||
|
{
|
||||||
// Skip silently. The data model checker will tell you something about this...
|
// Skip silently. The data model checker will tell you something about this...
|
||||||
$sAttCode = null;
|
$sAttCode = null;
|
||||||
}
|
}
|
||||||
} elseif (MetaModel::IsValidAttCode($sClass, 'org_id')) {
|
}
|
||||||
|
elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
|
||||||
|
{
|
||||||
$sAttCode = 'org_id';
|
$sAttCode = 'org_id';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,11 +939,15 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
protected static function HasSharing()
|
protected static function HasSharing()
|
||||||
{
|
{
|
||||||
static $bHasSharing;
|
static $bHasSharing;
|
||||||
if (!isset($bHasSharing)) {
|
if (!isset($bHasSharing))
|
||||||
|
{
|
||||||
$bHasSharing = class_exists('SharedObject');
|
$bHasSharing = class_exists('SharedObject');
|
||||||
}
|
}
|
||||||
return $bHasSharing;
|
return $bHasSharing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserRights::SelectModule('UserRightsProfile');
|
UserRights::SelectModule('UserRightsProfile');
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
30
app.php
30
app.php
@@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2013-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
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Combodo\iTop\Kernel;
|
|
||||||
|
|
||||||
require_once __DIR__.'/lib/autoload_runtime.php';
|
|
||||||
|
|
||||||
require_once('approot.inc.php');
|
|
||||||
require_once('application/startup.inc.php');
|
|
||||||
|
|
||||||
return function (array $context) {
|
|
||||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
|
||||||
};
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -49,7 +48,8 @@ class DBSearchHelper
|
|||||||
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
||||||
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
// If filtering fails just ignore it
|
// If filtering fails just ignore it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,4 +57,4 @@ class DBSearchHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
331
application/Html2Text.php
Normal file
331
application/Html2Text.php
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
<?php
|
||||||
|
namespace Html2Text;
|
||||||
|
|
||||||
|
if (!function_exists('mb_split'))
|
||||||
|
{
|
||||||
|
function mb_split($pattern, $subject, $limit = -1)
|
||||||
|
{
|
||||||
|
return preg_split('/'.$pattern.'/', $subject, $limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Replace all occurrences of the search string with the replacement string.
|
||||||
|
*
|
||||||
|
* @author Sean Murphy <sean@iamseanmurphy.com>
|
||||||
|
* @copyright Copyright 2012 Sean Murphy. All rights reserved.
|
||||||
|
* @license http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
* @link http://php.net/manual/function.str-replace.php
|
||||||
|
*
|
||||||
|
* @param mixed $search
|
||||||
|
* @param mixed $replace
|
||||||
|
* @param mixed $subject
|
||||||
|
* @param int $count
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function mb_str_replace($search, $replace, $subject, &$count = 0) {
|
||||||
|
if (!is_array($subject)) {
|
||||||
|
// Normalize $search and $replace so they are both arrays of the same length
|
||||||
|
$searches = is_array($search) ? array_values($search) : array($search);
|
||||||
|
$replacements = is_array($replace) ? array_values($replace) : array($replace);
|
||||||
|
$replacements = array_pad($replacements, count($searches), '');
|
||||||
|
foreach ($searches as $key => $search) {
|
||||||
|
$parts = mb_split(preg_quote($search), $subject);
|
||||||
|
if (is_array($parts))
|
||||||
|
{
|
||||||
|
$count += count($parts) - 1;
|
||||||
|
$subject = implode($replacements[$key], $parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Call mb_str_replace for each subject in array, recursively
|
||||||
|
foreach ($subject as $key => $value) {
|
||||||
|
$subject[$key] = mb_str_replace($search, $replace, $value, $count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2010 Jevon Wright and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* or
|
||||||
|
*
|
||||||
|
* LGPL which is available at http://www.gnu.org/licenses/lgpl.html
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Jevon Wright - initial API and implementation
|
||||||
|
* Denis Flaven - some fixes for properly handling UTF-8 characters
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
class Html2Text {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to convert the given HTML into a plain text format - best suited for
|
||||||
|
* e-mail display, etc.
|
||||||
|
*
|
||||||
|
* <p>In particular, it tries to maintain the following features:
|
||||||
|
* <ul>
|
||||||
|
* <li>Links are maintained, with the 'href' copied over
|
||||||
|
* <li>Information in the <head> is lost
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param string html the input HTML
|
||||||
|
* @return string the HTML converted, as best as possible, to text
|
||||||
|
* @throws Html2TextException if the HTML could not be loaded as a {@link DOMDocument}
|
||||||
|
*/
|
||||||
|
static function convert($html) {
|
||||||
|
// replace with spaces
|
||||||
|
|
||||||
|
$html = str_replace(" ", " ", $html);
|
||||||
|
$html = mb_str_replace("\xc2\xa0", " ", $html); // DO NOT USE str_replace since it breaks the "à" character which is \xc3 \xa0 in UTF-8
|
||||||
|
|
||||||
|
$html = static::fixNewlines($html);
|
||||||
|
|
||||||
|
$doc = new \DOMDocument();
|
||||||
|
if (!@$doc->loadHTML('<?xml encoding="UTF-8">'.$html)) // Forces the UTF-8 character set for HTML fragments
|
||||||
|
{
|
||||||
|
throw new Html2TextException("Could not load HTML - badly formed?", $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = static::iterateOverNode($doc);
|
||||||
|
|
||||||
|
// remove leading and trailing spaces on each line
|
||||||
|
$output = preg_replace("/[ \t]*\n[ \t]*/im", "\n", $output);
|
||||||
|
$output = preg_replace("/ *\t */im", "\t", $output);
|
||||||
|
|
||||||
|
// remove unnecessary empty lines
|
||||||
|
$output = preg_replace("/\n\n\n*/im", "\n\n", $output);
|
||||||
|
|
||||||
|
// remove leading and trailing whitespace
|
||||||
|
$output = trim($output);
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unify newlines; in particular, \r\n becomes \n, and
|
||||||
|
* then \r becomes \n. This means that all newlines (Unix, Windows, Mac)
|
||||||
|
* all become \ns.
|
||||||
|
*
|
||||||
|
* @param string text text with any number of \r, \r\n and \n combinations
|
||||||
|
* @return string the fixed text
|
||||||
|
*/
|
||||||
|
static function fixNewlines($text) {
|
||||||
|
// replace \r\n to \n
|
||||||
|
$text = str_replace("\r\n", "\n", $text);
|
||||||
|
// remove \rs
|
||||||
|
$text = str_replace("\r", "\n", $text);
|
||||||
|
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function nextChildName($node) {
|
||||||
|
// get the next child
|
||||||
|
$nextNode = $node->nextSibling;
|
||||||
|
while ($nextNode != null) {
|
||||||
|
if ($nextNode instanceof \DOMElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$nextNode = $nextNode->nextSibling;
|
||||||
|
}
|
||||||
|
$nextName = null;
|
||||||
|
if ($nextNode instanceof \DOMElement && $nextNode != null) {
|
||||||
|
$nextName = strtolower($nextNode->nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nextName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function prevChildName($node) {
|
||||||
|
// get the previous child
|
||||||
|
$nextNode = $node->previousSibling;
|
||||||
|
while ($nextNode != null) {
|
||||||
|
if ($nextNode instanceof \DOMElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$nextNode = $nextNode->previousSibling;
|
||||||
|
}
|
||||||
|
$nextName = null;
|
||||||
|
if ($nextNode instanceof \DOMElement && $nextNode != null) {
|
||||||
|
$nextName = strtolower($nextNode->nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nextName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function iterateOverNode($node) {
|
||||||
|
if ($node instanceof \DOMText) {
|
||||||
|
// Replace whitespace characters with a space (equivilant to \s)
|
||||||
|
return preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $node->wholeText);
|
||||||
|
}
|
||||||
|
if ($node instanceof \DOMDocumentType) {
|
||||||
|
// ignore
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$nextName = static::nextChildName($node);
|
||||||
|
$prevName = static::prevChildName($node);
|
||||||
|
|
||||||
|
$name = strtolower($node->nodeName);
|
||||||
|
|
||||||
|
// start whitespace
|
||||||
|
switch ($name) {
|
||||||
|
case "hr":
|
||||||
|
return "---------------------------------------------------------------\n";
|
||||||
|
|
||||||
|
case "style":
|
||||||
|
case "head":
|
||||||
|
case "title":
|
||||||
|
case "meta":
|
||||||
|
case "script":
|
||||||
|
// ignore these tags
|
||||||
|
return "";
|
||||||
|
|
||||||
|
case "h1":
|
||||||
|
case "h2":
|
||||||
|
case "h3":
|
||||||
|
case "h4":
|
||||||
|
case "h5":
|
||||||
|
case "h6":
|
||||||
|
case "ol":
|
||||||
|
case "ul":
|
||||||
|
// add two newlines, second line is added below
|
||||||
|
$output = "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "td":
|
||||||
|
case "th":
|
||||||
|
// add tab char to separate table fields
|
||||||
|
$output = "\t";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "tr":
|
||||||
|
case "p":
|
||||||
|
case "div":
|
||||||
|
// add one line
|
||||||
|
$output = "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "li":
|
||||||
|
$output = "- ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// print out contents of unknown tags
|
||||||
|
$output = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug
|
||||||
|
//$output .= "[$name,$nextName]";
|
||||||
|
|
||||||
|
if (isset($node->childNodes)) {
|
||||||
|
for ($i = 0; $i < $node->childNodes->length; $i++) {
|
||||||
|
$n = $node->childNodes->item($i);
|
||||||
|
|
||||||
|
$text = static::iterateOverNode($n);
|
||||||
|
|
||||||
|
$output .= $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end whitespace
|
||||||
|
switch ($name) {
|
||||||
|
case "h1":
|
||||||
|
case "h2":
|
||||||
|
case "h3":
|
||||||
|
case "h4":
|
||||||
|
case "h5":
|
||||||
|
case "h6":
|
||||||
|
$output .= "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "p":
|
||||||
|
case "br":
|
||||||
|
// add one line
|
||||||
|
if ($nextName != "div")
|
||||||
|
$output .= "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "div":
|
||||||
|
// add one line only if the next child isn't a div
|
||||||
|
if ($nextName != "div" && $nextName != null)
|
||||||
|
$output .= "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "a":
|
||||||
|
// links are returned in [text](link) format
|
||||||
|
$href = $node->getAttribute("href");
|
||||||
|
|
||||||
|
$output = trim($output);
|
||||||
|
|
||||||
|
// remove double [[ ]] s from linking images
|
||||||
|
if (substr($output, 0, 1) == "[" && substr($output, -1) == "]") {
|
||||||
|
$output = substr($output, 1, strlen($output) - 2);
|
||||||
|
|
||||||
|
// for linking images, the title of the <a> overrides the title of the <img>
|
||||||
|
if ($node->getAttribute("title")) {
|
||||||
|
$output = $node->getAttribute("title");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is no link text, but a title attr
|
||||||
|
if (!$output && $node->getAttribute("title")) {
|
||||||
|
$output = $node->getAttribute("title");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($href == null) {
|
||||||
|
// it doesn't link anywhere
|
||||||
|
if ($node->getAttribute("name") != null) {
|
||||||
|
$output = "[$output]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($href == $output || $href == "mailto:$output" || $href == "http://$output" || $href == "https://$output") {
|
||||||
|
// link to the same address: just use link
|
||||||
|
$output;
|
||||||
|
} else {
|
||||||
|
// replace it
|
||||||
|
if ($output) {
|
||||||
|
$output = "[$output]($href)";
|
||||||
|
} else {
|
||||||
|
// empty string
|
||||||
|
$output = $href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// does the next node require additional whitespace?
|
||||||
|
switch ($nextName) {
|
||||||
|
case "h1": case "h2": case "h3": case "h4": case "h5": case "h6":
|
||||||
|
$output .= "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "img":
|
||||||
|
if ($node->getAttribute("title")) {
|
||||||
|
$output = "[" . $node->getAttribute("title") . "]";
|
||||||
|
} elseif ($node->getAttribute("alt")) {
|
||||||
|
$output = "[" . $node->getAttribute("alt") . "]";
|
||||||
|
} else {
|
||||||
|
$output = "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "li":
|
||||||
|
$output .= "\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
application/Html2TextException.php
Normal file
28
application/Html2TextException.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2010 Jevon Wright and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* or
|
||||||
|
*
|
||||||
|
* LGPL which is available at http://www.gnu.org/licenses/lgpl.html
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Jevon Wright - initial API and implementation
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
namespace Html2Text;
|
||||||
|
|
||||||
|
class Html2TextException extends \Exception {
|
||||||
|
var $more_info;
|
||||||
|
|
||||||
|
public function __construct($message = "", $more_info = "") {
|
||||||
|
parent::__construct($message);
|
||||||
|
$this->more_info = $more_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// cannot notify depreciation for now as this is still load in autoloader
|
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader');
|
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||||
use Combodo\iTop\Application\WebPage\AjaxPage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ajax_page
|
* Class ajax_page
|
||||||
*
|
*
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to AjaxPage
|
* @deprecated will be removed in 3.1.0 - moved to AjaxPage
|
||||||
*/
|
*/
|
||||||
class ajax_page extends AjaxPage
|
class ajax_page extends AjaxPage
|
||||||
{
|
{
|
||||||
public function __construct($s_title)
|
|
||||||
{
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead');
|
|
||||||
parent::__construct($s_title);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -13,7 +12,6 @@ require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
|||||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
require_once(APPROOT.'/application/audit.category.class.inc.php');
|
require_once(APPROOT.'/application/audit.category.class.inc.php');
|
||||||
require_once(APPROOT.'/application/audit.domain.class.inc.php');
|
|
||||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||||
require_once(APPROOT.'/application/query.class.inc.php');
|
require_once(APPROOT.'/application/query.class.inc.php');
|
||||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -17,10 +16,11 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ApplicationContext
|
* Class ApplicationContext
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -47,16 +47,16 @@ interface iDBObjectURLMaker
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Direct end-users to the standard iTop application: UI.php
|
* Direct end-users to the standard iTop application: UI.php
|
||||||
*/
|
*/
|
||||||
class iTopStandardURLMaker implements iDBObjectURLMaker
|
class iTopStandardURLMaker implements iDBObjectURLMaker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $iId
|
* @param string $iId
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function MakeObjectURL($sClass, $iId)
|
public static function MakeObjectURL($sClass, $iId)
|
||||||
{
|
{
|
||||||
$sPage = DBObject::ComputeStandardUIPage($sClass);
|
$sPage = DBObject::ComputeStandardUIPage($sClass);
|
||||||
@@ -68,16 +68,16 @@ class iTopStandardURLMaker implements iDBObjectURLMaker
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Direct end-users to the standard Portal application
|
* Direct end-users to the standard Portal application
|
||||||
*/
|
*/
|
||||||
class PortalURLMaker implements iDBObjectURLMaker
|
class PortalURLMaker implements iDBObjectURLMaker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $iId
|
* @param string $iId
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function MakeObjectURL($sClass, $iId)
|
public static function MakeObjectURL($sClass, $iId)
|
||||||
{
|
{
|
||||||
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
|
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
|
||||||
@@ -86,6 +86,7 @@ class PortalURLMaker implements iDBObjectURLMaker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to store and manipulate the parameters that make the application's context
|
* Helper class to store and manipulate the parameters that make the application's context
|
||||||
*
|
*
|
||||||
@@ -98,117 +99,112 @@ class PortalURLMaker implements iDBObjectURLMaker
|
|||||||
*/
|
*/
|
||||||
class ApplicationContext
|
class ApplicationContext
|
||||||
{
|
{
|
||||||
public static $m_sUrlMakerClass = null;
|
public static $m_sUrlMakerClass = null;
|
||||||
protected static $m_aPluginProperties = null;
|
protected static $m_aPluginProperties = null;
|
||||||
protected static $aDefaultValues; // Cache shared among all instances
|
protected static $aDefaultValues; // Cache shared among all instances
|
||||||
|
|
||||||
protected $aNames;
|
protected $aNames;
|
||||||
protected $aValues;
|
protected $aValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ApplicationContext constructor.
|
* ApplicationContext constructor.
|
||||||
*
|
*
|
||||||
* @param bool $bReadContext
|
* @param bool $bReadContext
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function __construct($bReadContext = true)
|
public function __construct($bReadContext = true)
|
||||||
{
|
{
|
||||||
$this->aNames = [
|
$this->aNames = array(
|
||||||
'org_id', 'menu',
|
'org_id', 'menu'
|
||||||
];
|
);
|
||||||
if ($bReadContext) {
|
if ($bReadContext)
|
||||||
$this->ReadContext();
|
{
|
||||||
|
$this->ReadContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the context directly in the PHP parameters (either POST or GET)
|
* Read the context directly in the PHP parameters (either POST or GET)
|
||||||
* return nothing
|
* return nothing
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
protected function ReadContext()
|
protected function ReadContext()
|
||||||
{
|
{
|
||||||
if (!isset(self::$aDefaultValues)) {
|
if (!isset(self::$aDefaultValues))
|
||||||
self::$aDefaultValues = [];
|
{
|
||||||
$aContext = utils::ReadParam('c', [], false, 'context_param');
|
self::$aDefaultValues = array();
|
||||||
foreach ($this->aNames as $sName) {
|
$aContext = utils::ReadParam('c', array(), false, 'context_param');
|
||||||
|
foreach($this->aNames as $sName)
|
||||||
|
{
|
||||||
$sValue = isset($aContext[$sName]) ? $aContext[$sName] : '';
|
$sValue = isset($aContext[$sName]) ? $aContext[$sName] : '';
|
||||||
// TO DO: check if some of the context parameters are mandatory (or have default values)
|
// TO DO: check if some of the context parameters are mandatory (or have default values)
|
||||||
if (!empty($sValue)) {
|
if (!empty($sValue))
|
||||||
|
{
|
||||||
self::$aDefaultValues[$sName] = $sValue;
|
self::$aDefaultValues[$sName] = $sValue;
|
||||||
}
|
}
|
||||||
// Hmm, there must be a better (more generic) way to handle the case below:
|
// Hmm, there must be a better (more generic) way to handle the case below:
|
||||||
// When there is only one possible (allowed) organization, the context must be
|
// When there is only one possible (allowed) organization, the context must be
|
||||||
// fixed to this org unless there is only one organization in the system then
|
// fixed to this org unless there is only one organization in the system then
|
||||||
// no filter is applied
|
// no filter is applied
|
||||||
if ($sName == 'org_id') {
|
if ($sName == 'org_id')
|
||||||
if (MetaModel::IsValidClass('Organization')) {
|
{
|
||||||
|
if (MetaModel::IsValidClass('Organization'))
|
||||||
|
{
|
||||||
$oSearchFilter = new DBObjectSearch('Organization');
|
$oSearchFilter = new DBObjectSearch('Organization');
|
||||||
$oSet = new CMDBObjectSet($oSearchFilter);
|
$oSet = new CMDBObjectSet($oSearchFilter);
|
||||||
$iCount = $oSet->CountWithLimit(2);
|
$iCount = $oSet->CountWithLimit(2);
|
||||||
if ($iCount > 1) {
|
if ($iCount > 1)
|
||||||
|
{
|
||||||
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
||||||
$oSet = new CMDBObjectSet($oSearchFilter);
|
$oSet = new CMDBObjectSet($oSearchFilter);
|
||||||
$iCount = $oSet->CountWithLimit(2);
|
$iCount = $oSet->CountWithLimit(2);
|
||||||
if ($iCount == 1) {
|
if ($iCount == 1)
|
||||||
|
{
|
||||||
// Only one possible value for org_id, set it in the context
|
// Only one possible value for org_id, set it in the context
|
||||||
$oOrg = $oSet->Fetch();
|
$oOrg = $oSet->Fetch();
|
||||||
self::$aDefaultValues[$sName] = $oOrg->GetKey();
|
self::$aDefaultValues[$sName] = $oOrg->GetKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->aValues = self::$aDefaultValues;
|
$this->aValues = self::$aDefaultValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current value for the given parameter
|
* Returns the current value for the given parameter
|
||||||
*
|
*
|
||||||
* @param string $sParamName Name of the parameter to read
|
* @param string $sParamName Name of the parameter to read
|
||||||
* @param string $defaultValue
|
* @param string $defaultValue
|
||||||
*
|
*
|
||||||
* @return mixed The value for this parameter
|
* @return mixed The value for this parameter
|
||||||
*/
|
*/
|
||||||
public function GetCurrentValue($sParamName, $defaultValue = '')
|
public function GetCurrentValue($sParamName, $defaultValue = '')
|
||||||
{
|
{
|
||||||
if (isset($this->aValues[$sParamName])) {
|
if (isset($this->aValues[$sParamName]))
|
||||||
|
{
|
||||||
return $this->aValues[$sParamName];
|
return $this->aValues[$sParamName];
|
||||||
}
|
}
|
||||||
return $defaultValue;
|
return $defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the context as string with the format name1=value1&name2=value2....
|
* Returns the context as string with the format name1=value1&name2=value2....
|
||||||
* @return string The context as a string to be appended to an href property
|
* @return string The context as a string to be appended to an href property
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public function GetForLink(bool $bWithLeadingAmpersand = false)
|
public function GetForLink()
|
||||||
{
|
{
|
||||||
// If there are no parameters, return an empty string
|
$aParams = array();
|
||||||
if (empty($this->aValues)) {
|
foreach($this->aValues as $sName => $sValue)
|
||||||
return '';
|
{
|
||||||
}
|
|
||||||
|
|
||||||
// Build the query string with ampersand separated parameters
|
|
||||||
$aParams = [];
|
|
||||||
foreach ($this->aValues as $sName => $sValue) {
|
|
||||||
$aParams[] = "c[$sName]".'='.urlencode($sValue);
|
$aParams[] = "c[$sName]".'='.urlencode($sValue);
|
||||||
}
|
}
|
||||||
$sReturnValue = implode('&', $aParams);
|
return implode("&", $aParams);
|
||||||
|
|
||||||
// add the leading ampersand if requested
|
|
||||||
if ($bWithLeadingAmpersand) {
|
|
||||||
$sReturnValue = '&'.$sReturnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sReturnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.0.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
|
* @since 3.0.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
|
||||||
* Returns the params as c[menu]:..., c[org_id]:....
|
* Returns the params as c[menu]:..., c[org_id]:....
|
||||||
@@ -228,7 +224,7 @@ class ApplicationContext
|
|||||||
{
|
{
|
||||||
$sContext = "";
|
$sContext = "";
|
||||||
foreach ($this->aValues as $sName => $sValue) {
|
foreach ($this->aValues as $sName => $sValue) {
|
||||||
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".utils::EscapeHtml($sValue)."\" />\n";
|
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||||
}
|
}
|
||||||
return $sContext;
|
return $sContext;
|
||||||
}
|
}
|
||||||
@@ -242,7 +238,7 @@ class ApplicationContext
|
|||||||
{
|
{
|
||||||
$aContextInputBlocks = [];
|
$aContextInputBlocks = [];
|
||||||
foreach ($this->aValues as $sName => $sValue) {
|
foreach ($this->aValues as $sName => $sValue) {
|
||||||
$aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", $sValue);
|
$aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", htmlentities($sValue, ENT_QUOTES, 'UTF-8'));
|
||||||
}
|
}
|
||||||
return $aContextInputBlocks;
|
return $aContextInputBlocks;
|
||||||
}
|
}
|
||||||
@@ -267,13 +263,14 @@ class ApplicationContext
|
|||||||
*/
|
*/
|
||||||
public function GetAsHash()
|
public function GetAsHash()
|
||||||
{
|
{
|
||||||
$aReturn = [];
|
$aReturn = array();
|
||||||
foreach ($this->aValues as $sName => $sValue) {
|
foreach($this->aValues as $sName => $sValue)
|
||||||
|
{
|
||||||
$aReturn["c[$sName]"] = $sValue;
|
$aReturn["c[$sName]"] = $sValue;
|
||||||
}
|
}
|
||||||
return $aReturn;
|
return $aReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of the context parameters NAMEs
|
* Returns an array of the context parameters NAMEs
|
||||||
* @return array The list of context parameters
|
* @return array The list of context parameters
|
||||||
@@ -286,10 +283,11 @@ class ApplicationContext
|
|||||||
* Removes the specified parameter from the context, for example when the same parameter
|
* Removes the specified parameter from the context, for example when the same parameter
|
||||||
* is already a search parameter
|
* is already a search parameter
|
||||||
* @param string $sParamName Name of the parameter to remove
|
* @param string $sParamName Name of the parameter to remove
|
||||||
*/
|
*/
|
||||||
public function Reset($sParamName)
|
public function Reset($sParamName)
|
||||||
{
|
{
|
||||||
if (isset($this->aValues[$sParamName])) {
|
if (isset($this->aValues[$sParamName]))
|
||||||
|
{
|
||||||
unset($this->aValues[$sParamName]);
|
unset($this->aValues[$sParamName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,22 +303,27 @@ class ApplicationContext
|
|||||||
public function InitObjectFromContext(DBObject &$oObj)
|
public function InitObjectFromContext(DBObject &$oObj)
|
||||||
{
|
{
|
||||||
$sClass = get_class($oObj);
|
$sClass = get_class($oObj);
|
||||||
foreach ($this->GetNames() as $key) {
|
foreach($this->GetNames() as $key)
|
||||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
{
|
||||||
if (is_callable($aCallSpec)) {
|
$aCallSpec = array($sClass, 'MapContextParam');
|
||||||
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
|
if (is_callable($aCallSpec))
|
||||||
|
{
|
||||||
|
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
|
||||||
|
|
||||||
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||||
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
if ($oAttDef->IsWritable()) {
|
if ($oAttDef->IsWritable())
|
||||||
|
{
|
||||||
$value = $this->GetCurrentValue($key, null);
|
$value = $this->GetCurrentValue($key, null);
|
||||||
if (!is_null($value)) {
|
if (!is_null($value))
|
||||||
|
{
|
||||||
$oObj->Set($sAttCode, $value);
|
$oObj->Set($sAttCode, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,10 +347,14 @@ class ApplicationContext
|
|||||||
*/
|
*/
|
||||||
public static function GetUrlMakerClass()
|
public static function GetUrlMakerClass()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_sUrlMakerClass)) {
|
if (is_null(self::$m_sUrlMakerClass))
|
||||||
if (Session::IsSet('UrlMakerClass')) {
|
{
|
||||||
|
if (Session::IsSet('UrlMakerClass'))
|
||||||
|
{
|
||||||
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
self::$m_sUrlMakerClass = 'iTopStandardURLMaker';
|
self::$m_sUrlMakerClass = 'iTopStandardURLMaker';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,23 +372,30 @@ class ApplicationContext
|
|||||||
* @return string the name of the class
|
* @return string the name of the class
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
|
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
|
||||||
{
|
{
|
||||||
$oAppContext = new ApplicationContext();
|
$oAppContext = new ApplicationContext();
|
||||||
|
|
||||||
if (is_null($sUrlMakerClass)) {
|
if (is_null($sUrlMakerClass))
|
||||||
|
{
|
||||||
$sUrlMakerClass = self::GetUrlMakerClass();
|
$sUrlMakerClass = self::GetUrlMakerClass();
|
||||||
}
|
}
|
||||||
$sUrl = call_user_func([$sUrlMakerClass, 'MakeObjectUrl'], $sObjClass, $sObjKey);
|
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey);
|
||||||
if (utils::StrLen($sUrl) > 0) {
|
if (strlen($sUrl) > 0)
|
||||||
if ($bWithNavigationContext) {
|
{
|
||||||
return $sUrl.$oAppContext->GetForLink(true);
|
if ($bWithNavigationContext)
|
||||||
} else {
|
{
|
||||||
|
return $sUrl."&".$oAppContext->GetForLink();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return $sUrl;
|
return $sUrl;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,10 +404,13 @@ class ApplicationContext
|
|||||||
*/
|
*/
|
||||||
protected static function LoadPluginProperties()
|
protected static function LoadPluginProperties()
|
||||||
{
|
{
|
||||||
if (Session::IsSet('PluginProperties')) {
|
if (Session::IsSet('PluginProperties'))
|
||||||
|
{
|
||||||
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
||||||
} else {
|
}
|
||||||
self::$m_aPluginProperties = [];
|
else
|
||||||
|
{
|
||||||
|
self::$m_aPluginProperties = array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,9 +423,7 @@ class ApplicationContext
|
|||||||
*/
|
*/
|
||||||
public static function SetPluginProperty($sPluginClass, $sProperty, $value)
|
public static function SetPluginProperty($sPluginClass, $sProperty, $value)
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_aPluginProperties)) {
|
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||||
self::LoadPluginProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
|
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
|
||||||
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
|
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
|
||||||
@@ -421,14 +436,15 @@ class ApplicationContext
|
|||||||
*/
|
*/
|
||||||
public static function GetPluginProperties($sPluginClass)
|
public static function GetPluginProperties($sPluginClass)
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_aPluginProperties)) {
|
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||||
self::LoadPluginProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) {
|
if (array_key_exists($sPluginClass, self::$m_aPluginProperties))
|
||||||
|
{
|
||||||
return self::$m_aPluginProperties[$sPluginClass];
|
return self::$m_aPluginProperties[$sPluginClass];
|
||||||
} else {
|
}
|
||||||
return [];
|
else
|
||||||
|
{
|
||||||
|
return array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -17,12 +16,13 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages the audit "categories". Each category defines a set of objects
|
* This class manages the audit "categories". Each category defines a set of objects
|
||||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
* to check and is linked to a set of rules that determine the valid or invalid objects
|
||||||
* inside the set
|
* inside the set
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -32,66 +32,29 @@ class AuditCategory extends cmdbAbstractObject
|
|||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "application,grant_by_profile",
|
"category" => "application, grant_by_profile",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "name",
|
"name_attcode" => "name",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => ['name'],
|
"reconc_keys" => array('name'),
|
||||||
"db_table" => "priv_auditcategory",
|
"db_table" => "priv_auditcategory",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-folder.svg'),
|
);
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("name", array("description"=>"Short name for this category", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", ["allowed_values" => null, "sql" => "definition_set", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", array("allowed_values"=>null, "sql"=>"definition_set", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", ["linked_class" => "AuditRule", "ext_key_to_me" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "edit_mode" => LINKSET_EDITMODE_INPLACE, "tracking_level" => LINKSET_TRACKING_ALL]));
|
MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", array("linked_class"=>"AuditRule", "ext_key_to_me"=>"category_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array(), "edit_mode" => LINKSET_EDITMODE_INPLACE, "tracking_level" => LINKSET_TRACKING_ALL)));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("ok_error_tolerance", ["allowed_values" => null, "sql" => "ok_error_tolerance", "default_value" => 5, "is_null_allowed" => true, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("warning_error_tolerance", ["allowed_values" => null, "sql" => "warning_error_tolerance", "default_value" => 25, "is_null_allowed" => true, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
|
|
||||||
"domains_list",
|
|
||||||
["linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "category_id", "ext_key_to_remote" => "domain_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "display_style" => 'property']
|
|
||||||
));
|
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'definition_set', 'ok_error_tolerance', 'warning_error_tolerance', 'rules_list', 'domains_list']); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('name', 'description', 'definition_set', 'rules_list')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', ['description', ]); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('description', )); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['description', 'definition_set']); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('description', 'definition_set')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
|
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $iTotal
|
|
||||||
* @param int $iErrors
|
|
||||||
*
|
|
||||||
* @return string A semantic color name (eg. red, green, orange, success, failure, ... {@see css/backoffice/utils/variables/colors/_semantic-palette.scss}) to use for this category depending on its error count and tolerance
|
|
||||||
* @throws \CoreException
|
|
||||||
*
|
|
||||||
* @since 3.1.0
|
|
||||||
*/
|
|
||||||
public function GetReportColor($iTotal, $iErrors)
|
|
||||||
{
|
|
||||||
$sResult = 'red';
|
|
||||||
if (($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100)) {
|
|
||||||
$sResult = 'green';
|
|
||||||
} elseif (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) {
|
|
||||||
$sResult = 'orange';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function GetShortcutActions($sFinalClass)
|
|
||||||
{
|
|
||||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
|
||||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
|
||||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aShortcutActions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
<?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/>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class manages the audit "categories". Each category defines a set of objects
|
|
||||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
|
||||||
* inside the set
|
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 3.1.0
|
|
||||||
*/
|
|
||||||
class AuditDomain extends cmdbAbstractObject
|
|
||||||
{
|
|
||||||
public static function Init()
|
|
||||||
{
|
|
||||||
$aParams =
|
|
||||||
[
|
|
||||||
"category" => "application,grant_by_profile",
|
|
||||||
"key_type" => "autoincrement",
|
|
||||||
"name_attcode" => "name",
|
|
||||||
"complementary_name_attcode" => ['description'],
|
|
||||||
"state_attcode" => "",
|
|
||||||
"reconc_keys" => ['name'],
|
|
||||||
"db_table" => "priv_auditdomain",
|
|
||||||
"db_key_field" => "id",
|
|
||||||
"db_finalclass_field" => "",
|
|
||||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-album.svg'),
|
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeImage("icon", ["is_null_allowed" => true, "depends_on" => [], "display_max_width" => 96, "display_max_height" => 96, "storage_max_width" => 256, "storage_max_height" => 256, "default_image" => null, "always_load_in_tables" => false]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
|
|
||||||
"categories_list",
|
|
||||||
["linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "domain_id", "ext_key_to_remote" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => []]
|
|
||||||
));
|
|
||||||
|
|
||||||
// Display lists
|
|
||||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'icon', 'categories_list']); // Attributes to be displayed for the complete details
|
|
||||||
MetaModel::Init_SetZListItems('list', ['description',]); // Attributes to be displayed for a list
|
|
||||||
// Search criteria
|
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['description']); // Criteria of the std search form
|
|
||||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function GetShortcutActions($sFinalClass)
|
|
||||||
{
|
|
||||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
|
||||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
|
||||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aShortcutActions;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 3.1.0
|
|
||||||
*/
|
|
||||||
class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public static function Init()
|
|
||||||
{
|
|
||||||
$aParams =
|
|
||||||
[
|
|
||||||
"category" => "application,grant_by_profile",
|
|
||||||
"key_type" => "autoincrement",
|
|
||||||
"name_attcode" => "",
|
|
||||||
"state_attcode" => "",
|
|
||||||
"reconc_keys" => ['category_id', 'domain_id'],
|
|
||||||
"db_table" => "priv_link_audit_category_domain",
|
|
||||||
"db_key_field" => "id",
|
|
||||||
"db_finalclass_field" => "",
|
|
||||||
"is_link" => true,
|
|
||||||
'uniqueness_rules' => [
|
|
||||||
'no_duplicate' => [
|
|
||||||
'attributes' => [
|
|
||||||
0 => 'category_id',
|
|
||||||
1 => 'domain_id',
|
|
||||||
],
|
|
||||||
'filter' => '',
|
|
||||||
'disabled' => false,
|
|
||||||
'is_blocking' => true,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["targetclass" => "AuditCategory", "jointype" => '', "allowed_values" => null, "sql" => "category_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("domain_id", ["targetclass" => "AuditDomain", "jointype" => '', "allowed_values" => null, "sql" => "domain_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("domain_name", ["allowed_values" => null, "extkey_attcode" => 'domain_id', "target_attcode" => "name"]));
|
|
||||||
|
|
||||||
// Display lists
|
|
||||||
MetaModel::Init_SetZListItems('details', ['category_id', 'domain_id']);
|
|
||||||
MetaModel::Init_SetZListItems('list', ['category_id', 'domain_id']);
|
|
||||||
// Search criteria
|
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['category_id', 'domain_id']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -17,13 +16,14 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages the audit "rule" linked to a given audit category.
|
* This class manages the audit "rule" linked to a given audit category.
|
||||||
* Each rule is based on an OQL expression that returns either the "good" objects
|
* Each rule is based on an OQL expression that returns either the "good" objects
|
||||||
* or the "bad" ones. The core audit engines computes the complement to the definition
|
* or the "bad" ones. The core audit engines computes the complement to the definition
|
||||||
* set when needed to obtain either the valid objects, or the ones with an error
|
* set when needed to obtain either the valid objects, or the ones with an error
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -33,41 +33,31 @@ class AuditRule extends cmdbAbstractObject
|
|||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams =
|
$aParams = array
|
||||||
[
|
(
|
||||||
"category" => "application,grant_by_profile",
|
"category" => "application, grant_by_profile",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "name",
|
"name_attcode" => "name",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => ['name'],
|
"reconc_keys" => array('name'),
|
||||||
"db_table" => "priv_auditrule",
|
"db_table" => "priv_auditrule",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit.svg'),
|
);
|
||||||
];
|
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("query", ["allowed_values" => null, "sql" => "query", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeOQL("query", array("allowed_values"=>null, "sql"=>"query", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", ["allowed_values" => new ValueSetEnum('true,false'), "sql" => "valid_flag", "default_value" => "true", "is_null_allowed" => false, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", array("allowed_values"=>new ValueSetEnum('true,false'), "sql"=>"valid_flag", "default_value"=>"true", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["allowed_values" => null, "sql" => "category_id", "targetclass" => "AuditCategory", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", array("allowed_values"=>null, "sql"=>"category_id", "targetclass"=>"AuditCategory", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", array("allowed_values"=>null, "extkey_attcode"=> 'category_id', "target_attcode"=>"name")));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag']); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('category_id', 'name', 'description', 'query', 'valid_flag')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'valid_flag']); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('category_id', 'description', 'valid_flag')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', ['category_id', 'name', 'description', 'valid_flag', 'query']); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'name', 'description', 'valid_flag', 'query')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'category_id']); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'category_id')); // Criteria of the advanced search form
|
||||||
}
|
|
||||||
|
|
||||||
public static function GetShortcutActions($sFinalClass)
|
|
||||||
{
|
|
||||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
|
||||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
|
||||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aShortcutActions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader');
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2024 Combodo SAS
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -33,8 +32,7 @@ class CompileCSSService
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = [])
|
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
||||||
{
|
|
||||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader');
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
// Copyright (C) 2010-2024 Combodo SAS
|
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -20,12 +19,11 @@ use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
|||||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow;
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard presentation
|
* Dashboard presentation
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
abstract class DashboardLayout
|
abstract class DashboardLayout
|
||||||
@@ -39,21 +37,21 @@ abstract class DashboardLayout
|
|||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
*/
|
*/
|
||||||
abstract public function GetDashletCoordinates($iCellIdx);
|
abstract public function GetDashletCoordinates($iCellIdx);
|
||||||
|
|
||||||
public static function GetInfo()
|
public static function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return array(
|
||||||
'label' => '',
|
'label' => '',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DashboardLayoutMultiCol extends DashboardLayout
|
abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||||
{
|
{
|
||||||
protected $iNbCols;
|
protected $iNbCols;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->iNbCols = 1;
|
$this->iNbCols = 1;
|
||||||
@@ -64,47 +62,56 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
$aKeys = array_reverse(array_keys($aDashlets));
|
$aKeys = array_reverse(array_keys($aDashlets));
|
||||||
$idx = 0;
|
$idx = 0;
|
||||||
$bNoVisibleFound = true;
|
$bNoVisibleFound = true;
|
||||||
while ($idx < count($aKeys) && $bNoVisibleFound) {
|
while($idx < count($aKeys) && $bNoVisibleFound)
|
||||||
|
{
|
||||||
/** @var \Dashlet $oDashlet */
|
/** @var \Dashlet $oDashlet */
|
||||||
$oDashlet = $aDashlets[$aKeys[$idx]];
|
$oDashlet = $aDashlets[$aKeys[$idx]];
|
||||||
if ($oDashlet::IsVisible()) {
|
if ($oDashlet::IsVisible())
|
||||||
|
{
|
||||||
$bNoVisibleFound = false;
|
$bNoVisibleFound = false;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
unset($aDashlets[$aKeys[$idx]]);
|
unset($aDashlets[$aKeys[$idx]]);
|
||||||
}
|
}
|
||||||
$idx++;
|
$idx++;
|
||||||
}
|
}
|
||||||
return $aDashlets;
|
return $aDashlets;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function TrimCellsArray($aCells)
|
protected function TrimCellsArray($aCells)
|
||||||
{
|
{
|
||||||
foreach ($aCells as $key => $aDashlets) {
|
foreach($aCells as $key => $aDashlets)
|
||||||
|
{
|
||||||
$aCells[$key] = $this->TrimCell($aDashlets);
|
$aCells[$key] = $this->TrimCell($aDashlets);
|
||||||
}
|
}
|
||||||
$aKeys = array_reverse(array_keys($aCells));
|
$aKeys = array_reverse(array_keys($aCells));
|
||||||
$idx = 0;
|
$idx = 0;
|
||||||
$bNoVisibleFound = true;
|
$bNoVisibleFound = true;
|
||||||
while ($idx < count($aKeys) && $bNoVisibleFound) {
|
while($idx < count($aKeys) && $bNoVisibleFound)
|
||||||
|
{
|
||||||
$aDashlets = $aCells[$aKeys[$idx]];
|
$aDashlets = $aCells[$aKeys[$idx]];
|
||||||
if (count($aDashlets) > 0) {
|
if (count($aDashlets) > 0)
|
||||||
|
{
|
||||||
$bNoVisibleFound = false;
|
$bNoVisibleFound = false;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
unset($aCells[$aKeys[$idx]]);
|
unset($aCells[$aKeys[$idx]]);
|
||||||
}
|
}
|
||||||
$idx++;
|
$idx++;
|
||||||
}
|
}
|
||||||
return $aCells;
|
return $aCells;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aCells
|
* @param $aCells
|
||||||
* @param bool $bEditMode
|
* @param bool $bEditMode
|
||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
*/
|
*/
|
||||||
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = [])
|
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||||
$aCells = $this->TrimCellsArray($aCells);
|
$aCells = $this->TrimCellsArray($aCells);
|
||||||
@@ -149,7 +156,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
|
|
||||||
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||||
|
|
||||||
if ($bEditMode) { // Add one row for extensibility
|
if ($bEditMode) // Add one row for extensibility
|
||||||
|
{
|
||||||
$oDashboardRow = new DashboardRow();
|
$oDashboardRow = new DashboardRow();
|
||||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||||
|
|
||||||
@@ -171,7 +179,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
$iColNumber = (int) $iCellIdx % $this->iNbCols;
|
$iColNumber = (int) $iCellIdx % $this->iNbCols;
|
||||||
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
|
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
|
||||||
|
|
||||||
return [$iColNumber, $iRowNumber];
|
return array($iColNumber, $iRowNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,13 +190,13 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 1;
|
$this->iNbCols = 1;
|
||||||
}
|
}
|
||||||
public static function GetInfo()
|
static public function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return array(
|
||||||
'label' => 'One Column',
|
'label' => 'One Column',
|
||||||
'icon' => 'images/layout_1col.png',
|
'icon' => 'images/layout_1col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,13 +207,13 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 2;
|
$this->iNbCols = 2;
|
||||||
}
|
}
|
||||||
public static function GetInfo()
|
static public function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return array(
|
||||||
'label' => 'Two Columns',
|
'label' => 'Two Columns',
|
||||||
'icon' => 'images/layout_2col.png',
|
'icon' => 'images/layout_2col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,12 +224,12 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->iNbCols = 3;
|
$this->iNbCols = 3;
|
||||||
}
|
}
|
||||||
public static function GetInfo()
|
static public function GetInfo()
|
||||||
{
|
{
|
||||||
return [
|
return array(
|
||||||
'label' => 'Two Columns',
|
'label' => 'Two Columns',
|
||||||
'icon' => 'images/layout_3col.png',
|
'icon' => 'images/layout_3col.png',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||||
<classes>
|
<classes>
|
||||||
<class id="AbstractResource" _delta="define">
|
<class id="AbstractResource" _delta="define">
|
||||||
<parent>cmdbAbstractObject</parent>
|
<parent>cmdbAbstractObject</parent>
|
||||||
@@ -40,36 +40,6 @@
|
|||||||
<presentation/>
|
<presentation/>
|
||||||
<methods/>
|
<methods/>
|
||||||
</class>
|
</class>
|
||||||
<class id="WelcomePopupAcknowledge" _delta="define">
|
|
||||||
<parent>DBObject</parent>
|
|
||||||
<properties>
|
|
||||||
<comment>/** Acknowledge welcome popup messages */</comment>
|
|
||||||
<abstract>false</abstract>
|
|
||||||
<category></category>
|
|
||||||
<key_type>autoincrement</key_type>
|
|
||||||
<db_table>priv_welcome_popup_acknowledge</db_table>
|
|
||||||
</properties>
|
|
||||||
<fields>
|
|
||||||
<field id="message_uuid" xsi:type="AttributeString">
|
|
||||||
<sql>message_uuid</sql>
|
|
||||||
<default_value/>
|
|
||||||
<is_null_allowed>false</is_null_allowed>
|
|
||||||
</field>
|
|
||||||
<field id="user_id" xsi:type="AttributeExternalKey">
|
|
||||||
<sql>user_id</sql>
|
|
||||||
<target_class>User</target_class>
|
|
||||||
<is_null_allowed>false</is_null_allowed>
|
|
||||||
<on_target_delete>DEL_SILENT</on_target_delete>
|
|
||||||
</field>
|
|
||||||
<field id="acknowledge_date" xsi:type="AttributeDateTime">
|
|
||||||
<sql>acknowledge_date</sql>
|
|
||||||
<default_value/>
|
|
||||||
<is_null_allowed>false</is_null_allowed>
|
|
||||||
</field>
|
|
||||||
</fields>
|
|
||||||
<presentation/>
|
|
||||||
<methods/>
|
|
||||||
</class>
|
|
||||||
</classes>
|
</classes>
|
||||||
<portals>
|
<portals>
|
||||||
<portal id="backoffice" _delta="define">
|
<portal id="backoffice" _delta="define">
|
||||||
@@ -85,9 +55,9 @@
|
|||||||
<menus>
|
<menus>
|
||||||
<menu id="WelcomeMenu" xsi:type="MenuGroup" _delta="define">
|
<menu id="WelcomeMenu" xsi:type="MenuGroup" _delta="define">
|
||||||
<rank>10</rank>
|
<rank>10</rank>
|
||||||
<style>
|
<style>
|
||||||
<decoration_classes>fas fa-home</decoration_classes>
|
<decoration_classes>fas fa-home</decoration_classes>
|
||||||
</style>
|
</style>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="WelcomeMenuPage" xsi:type="DashboardMenuNode" _delta="define">
|
<menu id="WelcomeMenuPage" xsi:type="DashboardMenuNode" _delta="define">
|
||||||
<rank>10</rank>
|
<rank>10</rank>
|
||||||
@@ -181,14 +151,9 @@
|
|||||||
</menu>
|
</menu>
|
||||||
<menu id="ConfigurationTools" xsi:type="MenuGroup" _delta="define_if_not_exists">
|
<menu id="ConfigurationTools" xsi:type="MenuGroup" _delta="define_if_not_exists">
|
||||||
<rank>90</rank>
|
<rank>90</rank>
|
||||||
<style>
|
<style>
|
||||||
<decoration_classes>fas fa-cog</decoration_classes>
|
<decoration_classes>fas fa-cog</decoration_classes>
|
||||||
</style>
|
</style>
|
||||||
</menu>
|
|
||||||
<menu id="Integrations" xsi:type="TemplateMenuNode" _delta="define">
|
|
||||||
<rank>50</rank>
|
|
||||||
<parent>ConfigurationTools</parent>
|
|
||||||
<template_file/>
|
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="DataSources" xsi:type="OQLMenuNode" _delta="define">
|
<menu id="DataSources" xsi:type="OQLMenuNode" _delta="define">
|
||||||
<rank>20</rank>
|
<rank>20</rank>
|
||||||
@@ -207,364 +172,19 @@
|
|||||||
</menu>
|
</menu>
|
||||||
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
||||||
<rank>80</rank>
|
<rank>80</rank>
|
||||||
<style>
|
<style>
|
||||||
<decoration_classes>fas fa-tools</decoration_classes>
|
<decoration_classes>fas fa-tools</decoration_classes>
|
||||||
</style>
|
</style>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
||||||
<rank>100</rank>
|
<rank>100</rank>
|
||||||
<enable_class>ResourceSystemMenu</enable_class>
|
<enable_class>ResourceSystemMenu</enable_class>
|
||||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||||
<style>
|
<style>
|
||||||
<decoration_classes>fas fa-terminal</decoration_classes>
|
<decoration_classes>fas fa-terminal</decoration_classes>
|
||||||
</style>
|
</style>
|
||||||
</menu>
|
</menu>
|
||||||
</menus>
|
</menus>
|
||||||
<events>
|
|
||||||
<event id="EVENT_DB_BEFORE_WRITE" _delta="define">
|
|
||||||
<name>Before create or update</name>
|
|
||||||
<description><![CDATA[An object is about to be written into the database.
|
|
||||||
The object can be modified.]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>DBObject::OnInsert</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object inserted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="is_new">
|
|
||||||
<description>Creation flag</description>
|
|
||||||
<type>boolean</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="stimulus_applied">
|
|
||||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_CHECK_TO_WRITE" _delta="define">
|
|
||||||
<name>Check to write</name>
|
|
||||||
<description><![CDATA[Check an object before it is written into the database (no change possible).
|
|
||||||
Call $this->AddCheckIssue($sErrorMessage) to report a blocking issue.
|
|
||||||
Call $this->AddCheckWarning($sWarningMessage) to display a warning.
|
|
||||||
]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>cmdbAbstractObject::DoCheckToWrite</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object to check</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="is_new">
|
|
||||||
<description>Creation flag</description>
|
|
||||||
<type>boolean</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="stimulus_applied">
|
|
||||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_AFTER_WRITE" _delta="define">
|
|
||||||
<name>After create or update</name>
|
|
||||||
<description><![CDATA[An object has been written into the database.
|
|
||||||
The modifications can be propagated to other objects.]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>DBObject::AfterInsert</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object inserted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="is_new">
|
|
||||||
<description>Creation flag</description>
|
|
||||||
<type>boolean</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="changes">
|
|
||||||
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
|
|
||||||
<type>array</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="stimulus_applied">
|
|
||||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_CHECK_TO_DELETE" _delta="define">
|
|
||||||
<name>Check to delete</name>
|
|
||||||
<description><![CDATA[Check an object before it is deleted from the database.
|
|
||||||
Call $this->AddDeleteIssue($sIssueMessage) to signal an issue.]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>cmdbAbstractObject::DoCheckToDelete</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object to check</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_ABOUT_TO_DELETE" _delta="define">
|
|
||||||
<name>Before delete</name>
|
|
||||||
<description><![CDATA[An object is about to be deleted from the database]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>cmdbAbstractObject::OnDelete</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object about to be deleted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_AFTER_DELETE" _delta="define">
|
|
||||||
<name>After delete</name>
|
|
||||||
<description><![CDATA[An object has been deleted into the database]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>DBObject::AfterDelete</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object deleted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_ENUM_TRANSITIONS" _delta="define">
|
|
||||||
<name>Enum transitions</name>
|
|
||||||
<description><![CDATA[Manage the allowed transitions in current object state.
|
|
||||||
The only action allowed is to deny transitions with $this->DenyTransition($sTransitionCode)]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object where the stimulus is targeted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="allowed_stimuli">
|
|
||||||
<description>The list of available stimuli in the current state</description>
|
|
||||||
<type>array</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_LINKS_CHANGED" _delta="define">
|
|
||||||
<name>Links on object have changed</name>
|
|
||||||
<description><![CDATA[At least one link class was changed]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object where the link is or was pointing to</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_OBJECT_RELOAD" _delta="define">
|
|
||||||
<name>Object reload</name>
|
|
||||||
<internal>true</internal>
|
|
||||||
<description><![CDATA[An object has been re-loaded from the database]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object re-loaded</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_COMPUTE_VALUES" _delta="define">
|
|
||||||
<name>Recompute object values</name>
|
|
||||||
<description><![CDATA[An object needs to be recomputed after changes]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<replaces>DBObject::ComputeValues</replaces>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object inserted</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="is_new">
|
|
||||||
<description>Creation flag</description>
|
|
||||||
<type>boolean</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="stimulus_applied">
|
|
||||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_ARCHIVE" _delta="define">
|
|
||||||
<name>Object archived</name>
|
|
||||||
<description><![CDATA[An object has been archived]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object archived</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_UNARCHIVE" _delta="define">
|
|
||||||
<name>Object unarchived</name>
|
|
||||||
<description><![CDATA[An object has been unarchived]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object unarchived</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_SET_ATTRIBUTES_FLAGS" _delta="define">
|
|
||||||
<name>Set attributes flags</name>
|
|
||||||
<description><![CDATA[Set object attributes flags.
|
|
||||||
Call $this->AddAttributeFlags($sAttCode, $iFlags) for all the attributes to be set for this target state.]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The current object</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="target_state">
|
|
||||||
<description>The target state in which to evaluate the flags</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS" _delta="define">
|
|
||||||
<name>Set initial attributes flags</name>
|
|
||||||
<description><![CDATA[Set object initial attributes flags.
|
|
||||||
Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial attributes to be set initially.]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The current object</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
|
|
||||||
<name>Document downloaded</name>
|
|
||||||
<description><![CDATA[A document has been downloaded from the GUI]]></description>
|
|
||||||
<sources>
|
|
||||||
<source id="Document">Document</source>
|
|
||||||
</sources>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="object">
|
|
||||||
<description>The object containing the document</description>
|
|
||||||
<type>DBObject</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="att_code">
|
|
||||||
<description>The optional object attribute code hosting the document</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="document">
|
|
||||||
<description>The document downloaded</description>
|
|
||||||
<type>ormDocument</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="content_disposition">
|
|
||||||
<description>The content disposition of the document ("inline" or "attachment")</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="debug_info">
|
|
||||||
<description>Debug string</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
<event id="EVENT_LOGIN" _delta="define">
|
|
||||||
<name>Login</name>
|
|
||||||
<internal>true</internal>
|
|
||||||
<description><![CDATA[Inform the listeners about the connection states]]></description>
|
|
||||||
<event_data>
|
|
||||||
<event_datum id="code">
|
|
||||||
<description>The login step result code (LoginWebPage::EXIT_CODE_...) </description>
|
|
||||||
<type>integer</type>
|
|
||||||
</event_datum>
|
|
||||||
<event_datum id="state">
|
|
||||||
<description>Current login state (LoginWebPage::LOGIN_STATE_CONNECTED...)</description>
|
|
||||||
<type>string</type>
|
|
||||||
</event_datum>
|
|
||||||
</event_data>
|
|
||||||
</event>
|
|
||||||
</events>
|
|
||||||
<meta>
|
<meta>
|
||||||
<classes>
|
<classes>
|
||||||
<class id="cmdbAbstractObject" _delta="define">
|
<class id="cmdbAbstractObject" _delta="define">
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
|
||||||
use Combodo\iTop\Application\WebPage\WebPage;
|
|
||||||
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2024 Combodo SAS
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -21,7 +19,7 @@ use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*
|
*
|
||||||
* @deprecated 3.0.0 use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable
|
* @deprecated since 3.0.0 use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DataTable
|
class DataTable
|
||||||
@@ -63,8 +61,8 @@ class DataTable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param DataTableSettings $oSettings
|
* @param \DataTableSettings $oSettings
|
||||||
* @param $bActionsMenu
|
* @param $bActionsMenu
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
* @param $bViewLink
|
* @param $bViewLink
|
||||||
@@ -80,31 +78,42 @@ class DataTable
|
|||||||
|
|
||||||
// Identified tables can have their own specific settings
|
// Identified tables can have their own specific settings
|
||||||
$oCustomSettings = DataTableSettings::GetTableSettings($this->aClassAliases, $this->sTableId);
|
$oCustomSettings = DataTableSettings::GetTableSettings($this->aClassAliases, $this->sTableId);
|
||||||
|
|
||||||
if ($oCustomSettings != null) {
|
if ($oCustomSettings != null)
|
||||||
|
{
|
||||||
// Custom settings overload the default ones
|
// Custom settings overload the default ones
|
||||||
$this->bUseCustomSettings = true;
|
$this->bUseCustomSettings = true;
|
||||||
if ($this->oDefaultSettings->iDefaultPageSize == 0) {
|
if ($this->oDefaultSettings->iDefaultPageSize == 0)
|
||||||
|
{
|
||||||
$oCustomSettings->iDefaultPageSize = 0;
|
$oCustomSettings->iDefaultPageSize = 0;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oCustomSettings = $oSettings;
|
$oCustomSettings = $oSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oCustomSettings->iDefaultPageSize > 0) {
|
if ($oCustomSettings->iDefaultPageSize > 0)
|
||||||
|
{
|
||||||
$this->oSet->SetLimit($oCustomSettings->iDefaultPageSize);
|
$this->oSet->SetLimit($oCustomSettings->iDefaultPageSize);
|
||||||
}
|
}
|
||||||
$this->oSet->SetOrderBy($oCustomSettings->GetSortOrder());
|
$this->oSet->SetOrderBy($oCustomSettings->GetSortOrder());
|
||||||
|
|
||||||
// Load only the requested columns
|
// Load only the requested columns
|
||||||
$aColumnsToLoad = [];
|
$aColumnsToLoad = array();
|
||||||
foreach ($oCustomSettings->aColumns as $sAlias => $aColumnsInfo) {
|
foreach($oCustomSettings->aColumns as $sAlias => $aColumnsInfo)
|
||||||
foreach ($aColumnsInfo as $sAttCode => $aData) {
|
{
|
||||||
if ($sAttCode != '_key_') {
|
foreach($aColumnsInfo as $sAttCode => $aData)
|
||||||
if ($aData['checked']) {
|
{
|
||||||
|
if ($sAttCode != '_key_')
|
||||||
|
{
|
||||||
|
if ($aData['checked'])
|
||||||
|
{
|
||||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||||
} else {
|
}
|
||||||
// See if this column is a must to load
|
else
|
||||||
|
{
|
||||||
|
// See if this column is a must to load
|
||||||
$sClass = $this->aClassAliases[$sAlias];
|
$sClass = $this->aClassAliases[$sAlias];
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
if ($oAttDef->AlwaysLoadInTables()) {
|
if ($oAttDef->AlwaysLoadInTables()) {
|
||||||
@@ -116,20 +125,23 @@ class DataTable
|
|||||||
}
|
}
|
||||||
$this->oSet->OptimizeColumnLoad($aColumnsToLoad);
|
$this->oSet->OptimizeColumnLoad($aColumnsToLoad);
|
||||||
|
|
||||||
|
|
||||||
$bToolkitMenu = true;
|
$bToolkitMenu = true;
|
||||||
if (isset($aExtraParams['toolkit_menu'])) {
|
if (isset($aExtraParams['toolkit_menu']))
|
||||||
|
{
|
||||||
$bToolkitMenu = (bool) $aExtraParams['toolkit_menu'];
|
$bToolkitMenu = (bool) $aExtraParams['toolkit_menu'];
|
||||||
}
|
}
|
||||||
if (UserRights::IsPortalUser()) {
|
if (UserRights::IsPortalUser())
|
||||||
|
{
|
||||||
// Portal users have a limited access to data, for now they can only see what's configured for them
|
// Portal users have a limited access to data, for now they can only see what's configured for them
|
||||||
$bToolkitMenu = false;
|
$bToolkitMenu = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $iPageSize
|
* @param $iPageSize
|
||||||
* @param $iDefaultPageSize
|
* @param $iDefaultPageSize
|
||||||
* @param $iPageIndex
|
* @param $iPageIndex
|
||||||
@@ -153,10 +165,10 @@ class DataTable
|
|||||||
if ($bActionsMenu) {
|
if ($bActionsMenu) {
|
||||||
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
|
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
|
||||||
}
|
}
|
||||||
// if ($bToolkitMenu)
|
// if ($bToolkitMenu)
|
||||||
// {
|
// {
|
||||||
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||||
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
||||||
@@ -174,7 +186,7 @@ class DataTable
|
|||||||
|
|
||||||
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
|
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
|
||||||
|
|
||||||
$aOptions = [
|
$aOptions = array(
|
||||||
'sPersistentId' => '',
|
'sPersistentId' => '',
|
||||||
'sFilter' => $this->oSet->GetFilter()->serialize(),
|
'sFilter' => $this->oSet->GetFilter()->serialize(),
|
||||||
'oColumns' => $aColumns,
|
'oColumns' => $aColumns,
|
||||||
@@ -188,11 +200,12 @@ class DataTable
|
|||||||
'sTableId' => $this->sTableId,
|
'sTableId' => $this->sTableId,
|
||||||
'oExtraParams' => $aExtraParams,
|
'oExtraParams' => $aExtraParams,
|
||||||
'sRenderUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
|
'sRenderUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
|
||||||
'oRenderParameters' => ['str' => ''], // Forces JSON to encode this as a object...
|
'oRenderParameters' => array('str' => ''), // Forces JSON to encode this as a object...
|
||||||
'oDefaultSettings' => ['str' => ''], // Forces JSON to encode this as a object...
|
'oDefaultSettings' => array('str' => ''), // Forces JSON to encode this as a object...
|
||||||
'oLabels' => ['moveup' => Dict::S('UI:Button:MoveUp'), 'movedown' => Dict::S('UI:Button:MoveDown')],
|
'oLabels' => array('moveup' => Dict::S('UI:Button:MoveUp'), 'movedown' => Dict::S('UI:Button:MoveDown')),
|
||||||
];
|
);
|
||||||
if ($this->oDefaultSettings != null) {
|
if($this->oDefaultSettings != null)
|
||||||
|
{
|
||||||
$aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings);
|
$aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings);
|
||||||
}
|
}
|
||||||
$sJSOptions = json_encode($aOptions);
|
$sJSOptions = json_encode($aOptions);
|
||||||
@@ -207,37 +220,42 @@ class DataTable
|
|||||||
*/
|
*/
|
||||||
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
|
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
|
||||||
{
|
{
|
||||||
if ($iPageSize < 1) {
|
if ($iPageSize < 1)
|
||||||
|
{
|
||||||
$iPageSize = -1; // convention: no pagination
|
$iPageSize = -1; // convention: no pagination
|
||||||
}
|
}
|
||||||
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
||||||
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||||
|
|
||||||
$sHtml = '';
|
$sHtml = '';
|
||||||
foreach ($aValues as $aRow) {
|
foreach($aValues as $aRow)
|
||||||
|
{
|
||||||
$sHtml .= $oPage->GetTableRow($aRow, $aAttribs);
|
$sHtml .= $oPage->GetTableRow($aRow, $aAttribs);
|
||||||
}
|
}
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function GetObjectCount(WebPage $oPage, $sSelectMode)
|
protected function GetObjectCount(WebPage $oPage, $sSelectMode)
|
||||||
{
|
{
|
||||||
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
|
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
|
||||||
|
{
|
||||||
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderSelection', '<span id="total">'.$this->iNbObjects.'</span>', '<span class="selectedCount">0</span>').'</div>';
|
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderSelection', '<span id="total">'.$this->iNbObjects.'</span>', '<span class="selectedCount">0</span>').'</div>';
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderNoSelection', '<span id="total">'.$this->iNbObjects.'</span>').'</div>';
|
$sHtml = '<div class="pagination_objcount">'.Dict::Format('UI:Pagination:HeaderNoSelection', '<span id="total">'.$this->iNbObjects.'</span>').'</div>';
|
||||||
}
|
}
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $iPageSize
|
* @param $iPageSize
|
||||||
* @param $iDefaultPageSize
|
* @param $iDefaultPageSize
|
||||||
* @param $iPageIndex
|
* @param $iPageIndex
|
||||||
@@ -247,19 +265,26 @@ class DataTable
|
|||||||
protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex)
|
protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex)
|
||||||
{
|
{
|
||||||
$sHtml = '';
|
$sHtml = '';
|
||||||
if ($iPageSize < 1) { // Display all
|
if ($iPageSize < 1) // Display all
|
||||||
|
{
|
||||||
$sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI
|
$sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI
|
||||||
// WARNING: mPDF does not take the "display" style into account
|
// WARNING: mPDF does not take the "display" style into account
|
||||||
// when applied to a <td> or a <table> tag, so make sure you apply this to a div
|
// when applied to a <td> or a <table> tag, so make sure you apply this to a div
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$sPagerStyle = '';
|
$sPagerStyle = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sCombo = '<select class="pagesize">';
|
$sCombo = '<select class="pagesize">';
|
||||||
if ($iPageSize < 1) {
|
if($iPageSize < 1)
|
||||||
|
{
|
||||||
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
|
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
|
||||||
} else {
|
}
|
||||||
for ($iPage = 1; $iPage < 5; $iPage++) {
|
else
|
||||||
|
{
|
||||||
|
for($iPage = 1; $iPage < 5; $iPage++)
|
||||||
|
{
|
||||||
$iNbItems = $iPage * $iDefaultPageSize;
|
$iNbItems = $iPage * $iDefaultPageSize;
|
||||||
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
|
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
|
||||||
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
|
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
|
||||||
@@ -268,32 +293,37 @@ class DataTable
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sCombo .= '</select>';
|
$sCombo .= '</select>';
|
||||||
|
|
||||||
$sPages = Dict::S('UI:Pagination:PagesLabel');
|
$sPages = Dict::S('UI:Pagination:PagesLabel');
|
||||||
$sPageSizeCombo = Dict::Format('UI:Pagination:PageSize', $sCombo);
|
$sPageSizeCombo = Dict::Format('UI:Pagination:PageSize', $sCombo);
|
||||||
|
|
||||||
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
||||||
if ($iNbPages == 1) {
|
if ($iNbPages == 1)
|
||||||
|
{
|
||||||
// No need to display the pager
|
// No need to display the pager
|
||||||
$sPagerStyle = 'style="display:none"';
|
$sPagerStyle = 'style="display:none"';
|
||||||
}
|
}
|
||||||
$aPagesToDisplay = [];
|
$aPagesToDisplay = array();
|
||||||
for ($idx = 0; $idx <= min(4, $iNbPages - 1); $idx++) {
|
for($idx = 0; $idx <= min(4, $iNbPages-1); $idx++)
|
||||||
if ($idx == 0) {
|
{
|
||||||
|
if ($idx == 0)
|
||||||
|
{
|
||||||
$aPagesToDisplay[$idx] = '<span page="0" class="curr_page">1</span>';
|
$aPagesToDisplay[$idx] = '<span page="0" class="curr_page">1</span>';
|
||||||
} else {
|
}
|
||||||
$aPagesToDisplay[$idx] = "<span id=\"gotopage_$idx\" class=\"gotopage\" page=\"$idx\">".(1 + $idx)."</span>";
|
else
|
||||||
|
{
|
||||||
|
$aPagesToDisplay[$idx] = "<span id=\"gotopage_$idx\" class=\"gotopage\" page=\"$idx\">".(1+$idx)."</span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$iLastPageIdx = $iNbPages - 1;
|
$iLastPageIdx = $iNbPages - 1;
|
||||||
if (!isset($aPagesToDisplay[$iLastPageIdx])) {
|
if (!isset($aPagesToDisplay[$iLastPageIdx]))
|
||||||
|
{
|
||||||
unset($aPagesToDisplay[$idx - 1]); // remove the last page added to make room for the very last page
|
unset($aPagesToDisplay[$idx - 1]); // remove the last page added to make room for the very last page
|
||||||
$aPagesToDisplay[$iLastPageIdx] = "<span id=\"gotopage_$iLastPageIdx\" class=\"gotopage\" page=\"$iLastPageIdx\">... $iNbPages</span>";
|
$aPagesToDisplay[$iLastPageIdx] = "<span id=\"gotopage_$iLastPageIdx\" class=\"gotopage\" page=\"$iLastPageIdx\">... $iNbPages</span>";
|
||||||
}
|
}
|
||||||
$sPagesLinks = implode('', $aPagesToDisplay);
|
$sPagesLinks = implode('', $aPagesToDisplay);
|
||||||
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
|
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
|
||||||
|
|
||||||
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
|
|
||||||
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
|
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
|
||||||
$sHtml =
|
$sHtml =
|
||||||
<<<EOF
|
<<<EOF
|
||||||
@@ -301,11 +331,11 @@ class DataTable
|
|||||||
<div $sPagerStyle>
|
<div $sPagerStyle>
|
||||||
<table id="pager{$this->iListId}" class="pager"><tr>
|
<table id="pager{$this->iListId}" class="pager"><tr>
|
||||||
<td>$sPages</td>
|
<td>$sPages</td>
|
||||||
<td><img src="{$sAppRootUrl}images/first.png" class="first"/>AAAA</td>
|
<td><img src="../images/first.png" class="first"/></td>
|
||||||
<td><img src="{$sAppRootUrl}images/prev.png" class="prev"/></td>
|
<td><img src="../images/prev.png" class="prev"/></td>
|
||||||
<td><span id="index">$sPagesLinks</span></td>
|
<td><span id="index">$sPagesLinks</span></td>
|
||||||
<td><img src="{$sAppRootUrl}images/next.png" class="next"/></td>
|
<td><img src="../images/next.png" class="next"/></td>
|
||||||
<td><img src="{$sAppRootUrl}images/last.png" class="last"/></td>
|
<td><img src="../images/last.png" class="last"/></td>
|
||||||
<td>$sPageSizeCombo</td>
|
<td>$sPageSizeCombo</td>
|
||||||
<td><span id="loading"> </span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
|
<td><span id="loading"> </span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
|
||||||
</td>
|
</td>
|
||||||
@@ -318,7 +348,7 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aExtraParams
|
* @param $aExtraParams
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
@@ -345,7 +375,7 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aExtraParams
|
* @param $aExtraParams
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
@@ -353,26 +383,29 @@ EOF;
|
|||||||
*/
|
*/
|
||||||
protected function GetToolkitMenu(WebPage $oPage, $aExtraParams)
|
protected function GetToolkitMenu(WebPage $oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
if (!$oPage->IsPrintableVersion()) {
|
if (!$oPage->IsPrintableVersion())
|
||||||
|
{
|
||||||
$sMenuTitle = Dict::S('UI:ConfigureThisList');
|
$sMenuTitle = Dict::S('UI:ConfigureThisList');
|
||||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||||
|
|
||||||
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
|
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
|
||||||
$aActions = [
|
$aActions = array(
|
||||||
$oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(),
|
$oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(),
|
||||||
];
|
);
|
||||||
$this->oSet->Rewind();
|
$this->oSet->Rewind();
|
||||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions, $this->sTableId, $this->iListId);
|
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions, $this->sTableId, $this->iListId);
|
||||||
$this->oSet->Rewind();
|
$this->oSet->Rewind();
|
||||||
$sHtml .= $oPage->RenderPopupMenuItems($aActions);
|
$sHtml .= $oPage->RenderPopupMenuItems($aActions);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$sHtml = '';
|
$sHtml = '';
|
||||||
}
|
}
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aColumns
|
* @param $aColumns
|
||||||
* @param $bViewLink
|
* @param $bViewLink
|
||||||
* @param $iDefaultPageSize
|
* @param $iDefaultPageSize
|
||||||
@@ -386,10 +419,10 @@ EOF;
|
|||||||
$sChecked = ($this->bUseCustomSettings) ? '' : 'checked';
|
$sChecked = ($this->bUseCustomSettings) ? '' : 'checked';
|
||||||
$sHtml .= "<p><input id=\"dtbl_dlg_settings_{$this->iListId}\" type=\"radio\" name=\"settings\" $sChecked value=\"defaults\"><label for=\"dtbl_dlg_settings_{$this->iListId}\"> ".Dict::S('UI:UseDefaultSettings').'</label></p>';
|
$sHtml .= "<p><input id=\"dtbl_dlg_settings_{$this->iListId}\" type=\"radio\" name=\"settings\" $sChecked value=\"defaults\"><label for=\"dtbl_dlg_settings_{$this->iListId}\"> ".Dict::S('UI:UseDefaultSettings').'</label></p>';
|
||||||
$sHtml .= "<fieldset>";
|
$sHtml .= "<fieldset>";
|
||||||
$sChecked = ($this->bUseCustomSettings) ? 'checked' : '';
|
$sChecked = ($this->bUseCustomSettings) ? 'checked': '';
|
||||||
$sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_specific_{$this->iListId}\" type=\"radio\" class=\"specific_settings\" name=\"settings\" $sChecked value=\"specific\"><label for=\"dtbl_dlg_specific_{$this->iListId}\"> ".Dict::S('UI:UseSpecificSettings')."</label></legend>";
|
$sHtml .= "<legend class=\"transparent\"><input id=\"dtbl_dlg_specific_{$this->iListId}\" type=\"radio\" class=\"specific_settings\" name=\"settings\" $sChecked value=\"specific\"><label for=\"dtbl_dlg_specific_{$this->iListId}\"> ".Dict::S('UI:UseSpecificSettings')."</label></legend>";
|
||||||
$sHtml .= Dict::S('UI:ColumnsAndSortOrder').'<br/><ul class="sortable_field_list" id="sfl_'.$this->iListId.'"></ul>';
|
$sHtml .= Dict::S('UI:ColumnsAndSortOrder').'<br/><ul class="sortable_field_list" id="sfl_'.$this->iListId.'"></ul>';
|
||||||
|
|
||||||
$sHtml .= '<p>'.Dict::Format('UI:Display_X_ItemsPerPage', '<input type="text" size="4" name="page_size" value="'.$iDefaultPageSize.'">').'</p>';
|
$sHtml .= '<p>'.Dict::Format('UI:Display_X_ItemsPerPage', '<input type="text" size="4" name="page_size" value="'.$iDefaultPageSize.'">').'</p>';
|
||||||
$sHtml .= "</fieldset>";
|
$sHtml .= "</fieldset>";
|
||||||
$sHtml .= "<fieldset>";
|
$sHtml .= "<fieldset>";
|
||||||
@@ -408,7 +441,7 @@ EOF;
|
|||||||
$sHtml .= '</td></tr></table>';
|
$sHtml .= '</td></tr></table>';
|
||||||
$sHtml .= "</form>";
|
$sHtml .= "</form>";
|
||||||
$sHtml .= "</div>";
|
$sHtml .= "</div>";
|
||||||
|
|
||||||
$sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle'));
|
$sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle'));
|
||||||
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });");
|
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });");
|
||||||
|
|
||||||
@@ -422,7 +455,7 @@ EOF;
|
|||||||
*/
|
*/
|
||||||
public function GetAsHash($oSetting)
|
public function GetAsHash($oSetting)
|
||||||
{
|
{
|
||||||
$aSettings = ['iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns];
|
$aSettings = array('iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns);
|
||||||
return $aSettings;
|
return $aSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,46 +471,55 @@ EOF;
|
|||||||
*/
|
*/
|
||||||
protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
|
protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
|
||||||
{
|
{
|
||||||
$aAttribs = [];
|
$aAttribs = array();
|
||||||
if ($sSelectMode == 'multiple') {
|
if ($sSelectMode == 'multiple')
|
||||||
$aAttribs['form::select'] = [
|
{
|
||||||
|
$aAttribs['form::select'] = array(
|
||||||
'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>",
|
'label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>",
|
||||||
'description' => Dict::S('UI:SelectAllToggle+'),
|
'description' => Dict::S('UI:SelectAllToggle+'),
|
||||||
'metadata' => [],
|
'metadata' => array(),
|
||||||
];
|
);
|
||||||
} elseif ($sSelectMode == 'single') {
|
}
|
||||||
$aAttribs['form::select'] = ['label' => '', 'description' => '', 'metadata' => []];
|
else if ($sSelectMode == 'single')
|
||||||
|
{
|
||||||
|
$aAttribs['form::select'] = array('label' => '', 'description' => '', 'metadata' => array());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->aClassAliases as $sAlias => $sClassName) {
|
foreach($this->aClassAliases as $sAlias => $sClassName)
|
||||||
foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
|
{
|
||||||
if ($aData['checked']) {
|
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||||
if ($sAttCode == '_key_') {
|
{
|
||||||
|
if ($aData['checked'])
|
||||||
|
{
|
||||||
|
if ($sAttCode == '_key_')
|
||||||
|
{
|
||||||
$sAttLabel = MetaModel::GetName($sClassName);
|
$sAttLabel = MetaModel::GetName($sClassName);
|
||||||
|
|
||||||
$aAttribs['key_'.$sAlias] = [
|
$aAttribs['key_'.$sAlias] = array(
|
||||||
'label' => $sAttLabel,
|
'label' => $sAttLabel,
|
||||||
'description' => '',
|
'description' => '',
|
||||||
'metadata' => [
|
'metadata' => array(
|
||||||
'object_class' => $sClassName,
|
'object_class' => $sClassName,
|
||||||
'attribute_label' => $sAttLabel,
|
'attribute_label' => $sAttLabel,
|
||||||
],
|
),
|
||||||
];
|
);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||||
$sAttDefClass = get_class($oAttDef);
|
$sAttDefClass = get_class($oAttDef);
|
||||||
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
|
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
|
||||||
|
|
||||||
$aAttribs[$sAttCode.'_'.$sAlias] = [
|
$aAttribs[$sAttCode.'_'.$sAlias] = array(
|
||||||
'label' => $sAttLabel,
|
'label' => $sAttLabel,
|
||||||
'description' => $oAttDef->GetOrderByHint(),
|
'description' => $oAttDef->GetOrderByHint(),
|
||||||
'metadata' => [
|
'metadata' => array(
|
||||||
'object_class' => $sClassName,
|
'object_class' => $sClassName,
|
||||||
'attribute_code' => $sAttCode,
|
'attribute_code' => $sAttCode,
|
||||||
'attribute_type' => $sAttDefClass,
|
'attribute_type' => $sAttDefClass,
|
||||||
'attribute_label' => $sAttLabel,
|
'attribute_label' => $sAttLabel,
|
||||||
],
|
),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,6 +527,7 @@ EOF;
|
|||||||
return $aAttribs;
|
return $aAttribs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $aColumns
|
* @param $aColumns
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
@@ -503,74 +546,104 @@ EOF;
|
|||||||
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||||
{
|
{
|
||||||
$bLocalize = true;
|
$bLocalize = true;
|
||||||
if (isset($aExtraParams['localize_values'])) {
|
if (isset($aExtraParams['localize_values']))
|
||||||
|
{
|
||||||
$bLocalize = (bool) $aExtraParams['localize_values'];
|
$bLocalize = (bool) $aExtraParams['localize_values'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$aValues = [];
|
$aValues = array();
|
||||||
$aAttDefsCache = [];
|
$aAttDefsCache = array();
|
||||||
$this->oSet->Seek(0);
|
$this->oSet->Seek(0);
|
||||||
$iMaxObjects = $iPageSize;
|
$iMaxObjects = $iPageSize;
|
||||||
while (($aObjects = $this->oSet->FetchAssoc()) && ($iMaxObjects != 0)) {
|
while (($aObjects = $this->oSet->FetchAssoc()) && ($iMaxObjects != 0))
|
||||||
|
{
|
||||||
$bFirstObject = true;
|
$bFirstObject = true;
|
||||||
$aRow = [];
|
$aRow = array();
|
||||||
foreach ($this->aClassAliases as $sAlias => $sClassName) {
|
foreach($this->aClassAliases as $sAlias => $sClassName)
|
||||||
if (is_object($aObjects[$sAlias])) {
|
{
|
||||||
$sHilightClass = MetaModel::GetHilightClass($sClassName, $aObjects[$sAlias]);
|
if (is_object($aObjects[$sAlias]))
|
||||||
if ($sHilightClass != '') {
|
{
|
||||||
$aRow['@class'] = $sHilightClass;
|
$sHilightClass = $aObjects[$sAlias]->GetHilightClass();
|
||||||
|
if ($sHilightClass != '')
|
||||||
|
{
|
||||||
|
$aRow['@class'] = $sHilightClass;
|
||||||
}
|
}
|
||||||
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject) {
|
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject)
|
||||||
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()])) {
|
{
|
||||||
|
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]))
|
||||||
|
{
|
||||||
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
|
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$sDisabled = '';
|
$sDisabled = '';
|
||||||
}
|
}
|
||||||
if ($sSelectMode == 'single') {
|
if ($sSelectMode == 'single')
|
||||||
|
{
|
||||||
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
$aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
|
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||||
if ($aData['checked']) {
|
{
|
||||||
if ($sAttCode == '_key_') {
|
if ($aData['checked'])
|
||||||
$aRow['key_'.$sAlias] = [
|
{
|
||||||
|
if ($sAttCode == '_key_')
|
||||||
|
{
|
||||||
|
$aRow['key_'.$sAlias] = array(
|
||||||
'value_raw' => $aObjects[$sAlias]->GetKey(),
|
'value_raw' => $aObjects[$sAlias]->GetKey(),
|
||||||
'value_html' => $aObjects[$sAlias]->GetHyperLink(),
|
'value_html' => $aObjects[$sAlias]->GetHyperLink(),
|
||||||
];
|
);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Prepare att. def. classes cache to avoid retrieving AttDef for each row
|
// Prepare att. def. classes cache to avoid retrieving AttDef for each row
|
||||||
if (!isset($aAttDefsCache[$sClassName][$sAttCode])) {
|
if(!isset($aAttDefsCache[$sClassName][$sAttCode]))
|
||||||
|
{
|
||||||
$aAttDefClassesCache[$sClassName][$sAttCode] = get_class(MetaModel::GetAttributeDef($sClassName, $sAttCode));
|
$aAttDefClassesCache[$sClassName][$sAttCode] = get_class(MetaModel::GetAttributeDef($sClassName, $sAttCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only retrieve raw (stored) value for simple fields
|
// Only retrieve raw (stored) value for simple fields
|
||||||
$bExcludeRawValue = false;
|
$bExcludeRawValue = false;
|
||||||
foreach (cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
|
foreach (cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||||
if (is_a($aAttDefClassesCache[$sClassName][$sAttCode], $sAttDefClassToExclude, true)) {
|
{
|
||||||
|
if (is_a($aAttDefClassesCache[$sClassName][$sAttCode], $sAttDefClassToExclude, true))
|
||||||
|
{
|
||||||
$bExcludeRawValue = true;
|
$bExcludeRawValue = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bExcludeRawValue) {
|
if($bExcludeRawValue)
|
||||||
|
{
|
||||||
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize);
|
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize);
|
||||||
} else {
|
}
|
||||||
$aRow[$sAttCode.'_'.$sAlias] = [
|
else
|
||||||
|
{
|
||||||
|
$aRow[$sAttCode.'_'.$sAlias] = array(
|
||||||
'value_raw' => $aObjects[$sAlias]->Get($sAttCode),
|
'value_raw' => $aObjects[$sAlias]->Get($sAttCode),
|
||||||
'value_html' => $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize),
|
'value_html' => $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
|
else
|
||||||
if ($aData['checked']) {
|
{
|
||||||
if ($sAttCode == '_key_') {
|
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||||
|
{
|
||||||
|
if ($aData['checked'])
|
||||||
|
{
|
||||||
|
if ($sAttCode == '_key_')
|
||||||
|
{
|
||||||
$aRow['key_'.$sAlias] = '';
|
$aRow['key_'.$sAlias] = '';
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$aRow[$sAttCode.'_'.$sAlias] = '';
|
$aRow[$sAttCode.'_'.$sAlias] = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,7 +658,7 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aColumns
|
* @param $aColumns
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
* @param $iPageSize
|
* @param $iPageSize
|
||||||
@@ -605,7 +678,8 @@ EOF;
|
|||||||
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||||
{
|
{
|
||||||
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
||||||
if ($iPageSize < 1) {
|
if ($iPageSize < 1)
|
||||||
|
{
|
||||||
$iPageSize = -1; // convention: no pagination
|
$iPageSize = -1; // convention: no pagination
|
||||||
}
|
}
|
||||||
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
||||||
@@ -614,7 +688,8 @@ EOF;
|
|||||||
|
|
||||||
$sHtml = '<table class="listContainer object-list">';
|
$sHtml = '<table class="listContainer object-list">';
|
||||||
|
|
||||||
foreach ($this->oSet->GetFilter()->GetInternalParams() as $sName => $sValue) {
|
foreach($this->oSet->GetFilter()->GetInternalParams() as $sName => $sValue)
|
||||||
|
{
|
||||||
$aExtraParams['query_params'][$sName] = $sValue;
|
$aExtraParams['query_params'][$sName] = $sValue;
|
||||||
}
|
}
|
||||||
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
|
$aExtraParams['show_obsolete_data'] = $this->bShowObsoleteData;
|
||||||
@@ -629,16 +704,20 @@ EOF;
|
|||||||
$sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them
|
$sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them
|
||||||
$sSelectModeJS = '';
|
$sSelectModeJS = '';
|
||||||
$sHeaders = '';
|
$sHeaders = '';
|
||||||
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
|
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
|
||||||
|
{
|
||||||
$sSelectModeJS = $sSelectMode;
|
$sSelectModeJS = $sSelectMode;
|
||||||
$sHeaders = 'headers: { 0: {sorter: false}},';
|
$sHeaders = 'headers: { 0: {sorter: false}},';
|
||||||
}
|
}
|
||||||
$sDisplayKey = ($bViewLink) ? 'true' : 'false';
|
$sDisplayKey = ($bViewLink) ? 'true' : 'false';
|
||||||
// Protect against duplicate elements in the Zlist
|
// Protect against duplicate elements in the Zlist
|
||||||
$aUniqueOrderedList = [];
|
$aUniqueOrderedList = array();
|
||||||
foreach ($this->aClassAliases as $sAlias => $sClassName) {
|
foreach($this->aClassAliases as $sAlias => $sClassName)
|
||||||
foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
|
{
|
||||||
if ($aData['checked']) {
|
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||||
|
{
|
||||||
|
if ($aData['checked'])
|
||||||
|
{
|
||||||
$aUniqueOrderedList[$sAttCode] = true;
|
$aUniqueOrderedList[$sAttCode] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -650,32 +729,41 @@ EOF;
|
|||||||
$this->oSet->ApplyParameters();
|
$this->oSet->ApplyParameters();
|
||||||
// Display the actual sort order of the table
|
// Display the actual sort order of the table
|
||||||
$aRealSortOrder = $this->oSet->GetRealSortOrder();
|
$aRealSortOrder = $this->oSet->GetRealSortOrder();
|
||||||
$aDefaultSort = [];
|
$aDefaultSort = array();
|
||||||
$iColOffset = 0;
|
$iColOffset = 0;
|
||||||
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple')) {
|
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
|
||||||
|
{
|
||||||
$iColOffset += 1;
|
$iColOffset += 1;
|
||||||
}
|
}
|
||||||
if ($bViewLink) {
|
if ($bViewLink)
|
||||||
// $iColOffset += 1;
|
{
|
||||||
|
// $iColOffset += 1;
|
||||||
}
|
}
|
||||||
foreach ($aRealSortOrder as $sColCode => $bAscending) {
|
foreach($aRealSortOrder as $sColCode => $bAscending)
|
||||||
|
{
|
||||||
$iPos = array_search($sColCode, $aUniqueOrderedList);
|
$iPos = array_search($sColCode, $aUniqueOrderedList);
|
||||||
if ($iPos !== false) {
|
if ($iPos !== false)
|
||||||
$aDefaultSort[] = "[".($iColOffset + $iPos).",".($bAscending ? '0' : '1')."]";
|
{
|
||||||
} elseif (($iPos = array_search(preg_replace('/_friendlyname$/', '', $sColCode), $aUniqueOrderedList)) !== false) {
|
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]";
|
||||||
|
}
|
||||||
|
else if (($iPos = array_search(preg_replace('/_friendlyname$/', '', $sColCode), $aUniqueOrderedList)) !== false)
|
||||||
|
{
|
||||||
// if sorted on the friendly name of an external key, then consider it sorted on the column that shows the links
|
// if sorted on the friendly name of an external key, then consider it sorted on the column that shows the links
|
||||||
$aDefaultSort[] = "[".($iColOffset + $iPos).",".($bAscending ? '0' : '1')."]";
|
$aDefaultSort[] = "[".($iColOffset+$iPos).",".($bAscending ? '0' : '1')."]";
|
||||||
} elseif ($sColCode == 'friendlyname' && $bViewLink) {
|
}
|
||||||
|
else if($sColCode == 'friendlyname' && $bViewLink)
|
||||||
|
{
|
||||||
$aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]";
|
$aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sFakeSortList = '';
|
$sFakeSortList = '';
|
||||||
if (count($aDefaultSort) > 0) {
|
if (count($aDefaultSort) > 0)
|
||||||
|
{
|
||||||
$sFakeSortList = '['.implode(',', $aDefaultSort).']';
|
$sFakeSortList = '['.implode(',', $aDefaultSort).']';
|
||||||
}
|
}
|
||||||
$sOQL = addslashes($this->oSet->GetFilter()->serialize());
|
$sOQL = addslashes($this->oSet->GetFilter()->serialize());
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<JS
|
<<<JS
|
||||||
var oTable = $('#{$this->sDatatableContainerId} table.listResults');
|
var oTable = $('#{$this->sDatatableContainerId} table.listResults');
|
||||||
oTable.tableHover();
|
oTable.tableHover();
|
||||||
oTable
|
oTable
|
||||||
@@ -693,15 +781,16 @@ oTable
|
|||||||
class_aliases: $sJSClassAliases $sCssCount
|
class_aliases: $sJSClassAliases $sCssCount
|
||||||
});
|
});
|
||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
if ($sFakeSortList != '') {
|
if ($sFakeSortList != '')
|
||||||
|
{
|
||||||
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
|
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
|
||||||
}
|
}
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $iDefaultPageSize
|
* @param $iDefaultPageSize
|
||||||
* @param $iStart
|
* @param $iStart
|
||||||
*/
|
*/
|
||||||
@@ -711,9 +800,12 @@ JS
|
|||||||
$iPageIndex = 0;
|
$iPageIndex = 0;
|
||||||
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
||||||
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
|
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
|
||||||
if ($iDefaultPageSize < 1) {
|
if ($iDefaultPageSize < 1)
|
||||||
|
{
|
||||||
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().hide()");
|
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().hide()");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().show()");
|
$oPage->add_ready_script("$('#pager{$this->iListId}').parent().show()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -726,7 +818,7 @@ JS
|
|||||||
class PrintableDataTable extends DataTable
|
class PrintableDataTable extends DataTable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $iPageSize
|
* @param $iPageSize
|
||||||
* @param $iDefaultPageSize
|
* @param $iDefaultPageSize
|
||||||
* @param $iPageIndex
|
* @param $iPageIndex
|
||||||
@@ -752,7 +844,7 @@ class PrintableDataTable extends DataTable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aColumns
|
* @param $aColumns
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
* @param $iPageSize
|
* @param $iPageSize
|
||||||
@@ -770,15 +862,16 @@ class PrintableDataTable extends DataTable
|
|||||||
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||||
{
|
{
|
||||||
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
||||||
if ($iPageSize < 1) {
|
if ($iPageSize < 1)
|
||||||
|
{
|
||||||
$iPageSize = -1; // convention: no pagination
|
$iPageSize = -1; // convention: no pagination
|
||||||
}
|
}
|
||||||
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
||||||
|
|
||||||
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||||
|
|
||||||
$sHtml = $oPage->GetTable($aAttribs, $aValues);
|
$sHtml = $oPage->GetTable($aAttribs, $aValues);
|
||||||
|
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader');
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Combodo\iTop\Application\WebPage\CLIPage;
|
|
||||||
use Combodo\iTop\Application\WebPage\Page;
|
|
||||||
|
|
||||||
require_once('xlsxwriter.class.php');
|
require_once('xlsxwriter.class.php');
|
||||||
|
|
||||||
class ExcelExporter
|
class ExcelExporter
|
||||||
@@ -19,67 +15,73 @@ class ExcelExporter
|
|||||||
protected $iPosition;
|
protected $iPosition;
|
||||||
protected $sOutputFilePath;
|
protected $sOutputFilePath;
|
||||||
protected $bAdvancedMode;
|
protected $bAdvancedMode;
|
||||||
|
|
||||||
public function __construct($sToken = null)
|
public function __construct($sToken = null)
|
||||||
{
|
{
|
||||||
$this->aStatistics = [
|
$this->aStatistics = array(
|
||||||
'objects_count' => 0,
|
'objects_count' => 0,
|
||||||
'total_duration' => 0,
|
'total_duration' => 0,
|
||||||
'data_retrieval_duration' => 0,
|
'data_retrieval_duration' => 0,
|
||||||
'excel_build_duration' => 0,
|
'excel_build_duration' => 0,
|
||||||
'excel_write_duration' => 0,
|
'excel_write_duration' => 0,
|
||||||
'peak_memory_usage' => 0,
|
'peak_memory_usage' => 0,
|
||||||
];
|
);
|
||||||
$this->fStartTime = microtime(true);
|
$this->fStartTime = microtime(true);
|
||||||
$this->oSearch = null;
|
$this->oSearch = null;
|
||||||
|
|
||||||
$this->sState = 'new';
|
$this->sState = 'new';
|
||||||
$this->aObjectsIDs = [];
|
$this->aObjectsIDs = array();
|
||||||
$this->iPosition = 0;
|
$this->iPosition = 0;
|
||||||
$this->aAuthorizedClasses = null;
|
$this->aAuthorizedClasses = null;
|
||||||
$this->aTableHeaders = null;
|
$this->aTableHeaders = null;
|
||||||
$this->sOutputFilePath = null;
|
$this->sOutputFilePath = null;
|
||||||
$this->bAdvancedMode = false;
|
$this->bAdvancedMode = false;
|
||||||
$this->CheckDataDir();
|
$this->CheckDataDir();
|
||||||
if ($sToken == null) {
|
if ($sToken == null)
|
||||||
|
{
|
||||||
$this->sToken = $this->GetNewToken();
|
$this->sToken = $this->GetNewToken();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$this->sToken = $sToken;
|
$this->sToken = $sToken;
|
||||||
$this->ReloadState();
|
$this->ReloadState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null)) {
|
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null))
|
||||||
|
{
|
||||||
// Operation in progress, save the state
|
// Operation in progress, save the state
|
||||||
$this->SaveState();
|
$this->SaveState();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Operation completed, cleanup the temp files
|
// Operation completed, cleanup the temp files
|
||||||
@unlink($this->GetStateFile());
|
@unlink($this->GetStateFile());
|
||||||
@unlink($this->GetDataFile());
|
@unlink($this->GetDataFile());
|
||||||
}
|
}
|
||||||
self::CleanupOldFiles();
|
self::CleanupOldFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetChunkSize($iChunkSize)
|
public function SetChunkSize($iChunkSize)
|
||||||
{
|
{
|
||||||
$this->iChunkSize = $iChunkSize;
|
$this->iChunkSize = $iChunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetOutputFilePath($sDestFilePath)
|
public function SetOutputFilePath($sDestFilePath)
|
||||||
{
|
{
|
||||||
$this->sOutputFilePath = $sDestFilePath;
|
$this->sOutputFilePath = $sDestFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetAdvancedMode($bAdvanced)
|
public function SetAdvancedMode($bAdvanced)
|
||||||
{
|
{
|
||||||
$this->bAdvancedMode = $bAdvanced;
|
$this->bAdvancedMode = $bAdvanced;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SaveState()
|
public function SaveState()
|
||||||
{
|
{
|
||||||
$aState = [
|
$aState = array(
|
||||||
'state' => $this->sState,
|
'state' => $this->sState,
|
||||||
'statistics' => $this->aStatistics,
|
'statistics' => $this->aStatistics,
|
||||||
'filter' => $this->oSearch->serialize(),
|
'filter' => $this->oSearch->serialize(),
|
||||||
@@ -88,28 +90,31 @@ class ExcelExporter
|
|||||||
'object_ids' => $this->aObjectsIDs,
|
'object_ids' => $this->aObjectsIDs,
|
||||||
'output_file_path' => $this->sOutputFilePath,
|
'output_file_path' => $this->sOutputFilePath,
|
||||||
'advanced_mode' => $this->bAdvancedMode,
|
'advanced_mode' => $this->bAdvancedMode,
|
||||||
];
|
);
|
||||||
|
|
||||||
file_put_contents($this->GetStateFile(), json_encode($aState));
|
file_put_contents($this->GetStateFile(), json_encode($aState));
|
||||||
|
|
||||||
return $this->sToken;
|
return $this->sToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ReloadState()
|
public function ReloadState()
|
||||||
{
|
{
|
||||||
if ($this->sToken == null) {
|
if ($this->sToken == null)
|
||||||
|
{
|
||||||
throw new Exception('ExcelExporter not initialized with a token, cannot reload state');
|
throw new Exception('ExcelExporter not initialized with a token, cannot reload state');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file_exists($this->GetStateFile())) {
|
if (!file_exists($this->GetStateFile()))
|
||||||
|
{
|
||||||
throw new Exception("ExcelExporter: missing status file '".$this->GetStateFile()."', cannot reload state.");
|
throw new Exception("ExcelExporter: missing status file '".$this->GetStateFile()."', cannot reload state.");
|
||||||
}
|
}
|
||||||
$sJson = file_get_contents($this->GetStateFile());
|
$sJson = file_get_contents($this->GetStateFile());
|
||||||
$aState = json_decode($sJson, true);
|
$aState = json_decode($sJson, true);
|
||||||
if ($aState === null) {
|
if ($aState === null)
|
||||||
|
{
|
||||||
throw new Exception("ExcelExporter:corrupted status file '".$this->GetStateFile()."', not a JSON, cannot reload state.");
|
throw new Exception("ExcelExporter:corrupted status file '".$this->GetStateFile()."', not a JSON, cannot reload state.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sState = $aState['state'];
|
$this->sState = $aState['state'];
|
||||||
$this->aStatistics = $aState['statistics'];
|
$this->aStatistics = $aState['statistics'];
|
||||||
$this->oSearch = DBObjectSearch::unserialize($aState['filter']);
|
$this->oSearch = DBObjectSearch::unserialize($aState['filter']);
|
||||||
@@ -119,183 +124,206 @@ class ExcelExporter
|
|||||||
$this->sOutputFilePath = $aState['output_file_path'];
|
$this->sOutputFilePath = $aState['output_file_path'];
|
||||||
$this->bAdvancedMode = $aState['advanced_mode'];
|
$this->bAdvancedMode = $aState['advanced_mode'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetObjectList($oSearch)
|
public function SetObjectList($oSearch)
|
||||||
{
|
{
|
||||||
$this->oSearch = $oSearch;
|
$this->oSearch = $oSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Run()
|
public function Run()
|
||||||
{
|
{
|
||||||
$sCode = 'error';
|
$sCode = 'error';
|
||||||
$iPercentage = 100;
|
$iPercentage = 100;
|
||||||
$sMessage = Dict::Format('ExcelExporter:ErrorUnexpected_State', $this->sState);
|
$sMessage = Dict::Format('ExcelExporter:ErrorUnexpected_State', $this->sState);
|
||||||
$fTime = microtime(true);
|
$fTime = microtime(true);
|
||||||
|
|
||||||
try {
|
try
|
||||||
switch ($this->sState) {
|
{
|
||||||
|
switch($this->sState)
|
||||||
|
{
|
||||||
case 'new':
|
case 'new':
|
||||||
$oIDSet = new DBObjectSet($this->oSearch);
|
$oIDSet = new DBObjectSet($this->oSearch);
|
||||||
$oIDSet->OptimizeColumnLoad(['id']);
|
$oIDSet->OptimizeColumnLoad(array('id'));
|
||||||
$this->aObjectsIDs = [];
|
$this->aObjectsIDs = array();
|
||||||
while ($oObj = $oIDSet->Fetch()) {
|
while($oObj = $oIDSet->Fetch())
|
||||||
$this->aObjectsIDs[] = $oObj->GetKey();
|
{
|
||||||
}
|
$this->aObjectsIDs[] = $oObj->GetKey();
|
||||||
$sCode = 'retrieving-data';
|
}
|
||||||
$iPercentage = 5;
|
$sCode = 'retrieving-data';
|
||||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
$iPercentage = 5;
|
||||||
$this->iPosition = 0;
|
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||||
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
|
$this->iPosition = 0;
|
||||||
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
|
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
|
||||||
|
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
|
||||||
// The first line of the file is the "headers" specifying the label and the type of each column
|
|
||||||
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
|
// The first line of the file is the "headers" specifying the label and the type of each column
|
||||||
$sRow = json_encode($this->aTableHeaders);
|
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
|
||||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
$sRow = json_encode($this->aTableHeaders);
|
||||||
if ($hFile === false) {
|
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
if ($hFile === false)
|
||||||
}
|
{
|
||||||
fwrite($hFile, $sRow."\n");
|
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||||
fclose($hFile);
|
}
|
||||||
|
fwrite($hFile, $sRow."\n");
|
||||||
// Next state
|
fclose($hFile);
|
||||||
$this->sState = 'retrieving-data';
|
|
||||||
break;
|
// Next state
|
||||||
|
$this->sState = 'retrieving-data';
|
||||||
|
break;
|
||||||
|
|
||||||
case 'retrieving-data':
|
case 'retrieving-data':
|
||||||
$oCurrentSearch = clone $this->oSearch;
|
$oCurrentSearch = clone $this->oSearch;
|
||||||
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
|
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
|
||||||
|
|
||||||
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
|
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
|
||||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||||
if ($hFile === false) {
|
if ($hFile === false)
|
||||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
{
|
||||||
}
|
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||||
$oSet = new DBObjectSet($oCurrentSearch);
|
}
|
||||||
$this->GetFieldsList($oSet, $this->bAdvancedMode);
|
$oSet = new DBObjectSet($oCurrentSearch);
|
||||||
while ($aObjects = $oSet->FetchAssoc()) {
|
$this->GetFieldsList($oSet, $this->bAdvancedMode);
|
||||||
$aRow = [];
|
while($aObjects = $oSet->FetchAssoc())
|
||||||
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
|
{
|
||||||
$oObj = $aObjects[$sAlias];
|
$aRow = array();
|
||||||
if ($this->bAdvancedMode) {
|
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||||
$aRow[] = $oObj->GetKey();
|
{
|
||||||
}
|
$oObj = $aObjects[$sAlias];
|
||||||
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
|
if ($this->bAdvancedMode)
|
||||||
$value = $oObj->Get($sAttCodeEx);
|
{
|
||||||
if ($value instanceof ormCaseLog) {
|
$aRow[] = $oObj->GetKey();
|
||||||
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
|
}
|
||||||
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
|
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||||
} else {
|
{
|
||||||
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
|
$value = $oObj->Get($sAttCodeEx);
|
||||||
}
|
if ($value instanceOf ormCaseLog)
|
||||||
$aRow[] = $sExcelVal;
|
{
|
||||||
}
|
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
|
||||||
|
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
|
||||||
|
}
|
||||||
|
$aRow[] = $sExcelVal;
|
||||||
}
|
}
|
||||||
$sRow = json_encode($aRow);
|
|
||||||
fwrite($hFile, $sRow."\n");
|
|
||||||
}
|
}
|
||||||
fclose($hFile);
|
$sRow = json_encode($aRow);
|
||||||
|
fwrite($hFile, $sRow."\n");
|
||||||
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs)) {
|
}
|
||||||
// Next state
|
fclose($hFile);
|
||||||
$this->sState = 'building-excel';
|
|
||||||
$sCode = 'building-excel';
|
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs))
|
||||||
$iPercentage = 80;
|
{
|
||||||
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
|
|
||||||
} else {
|
|
||||||
$sCode = 'retrieving-data';
|
|
||||||
$this->iPosition += $this->iChunkSize;
|
|
||||||
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
|
|
||||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'building-excel':
|
|
||||||
$hFile = @fopen($this->GetDataFile(), 'rb');
|
|
||||||
if ($hFile === false) {
|
|
||||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
|
|
||||||
}
|
|
||||||
$sHeaders = fgets($hFile);
|
|
||||||
$aHeaders = json_decode($sHeaders, true);
|
|
||||||
|
|
||||||
$aData = [];
|
|
||||||
while ($sLine = fgets($hFile)) {
|
|
||||||
$aRow = json_decode($sLine);
|
|
||||||
$aData[] = $aRow;
|
|
||||||
}
|
|
||||||
fclose($hFile);
|
|
||||||
@unlink($this->GetDataFile());
|
|
||||||
|
|
||||||
$fStartExcel = microtime(true);
|
|
||||||
$writer = new XLSXWriter();
|
|
||||||
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
|
||||||
$writer->writeSheet($aData, 'Sheet1', $aHeaders);
|
|
||||||
$fExcelTime = microtime(true) - $fStartExcel;
|
|
||||||
$this->aStatistics['excel_build_duration'] = $fExcelTime;
|
|
||||||
|
|
||||||
$fTime = microtime(true);
|
|
||||||
$writer->writeToFile($this->GetExcelFilePath());
|
|
||||||
$fExcelSaveTime = microtime(true) - $fTime;
|
|
||||||
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
|
|
||||||
|
|
||||||
// Next state
|
// Next state
|
||||||
$this->sState = 'done';
|
$this->sState = 'building-excel';
|
||||||
$sCode = 'done';
|
$sCode = 'building-excel';
|
||||||
$iPercentage = 100;
|
$iPercentage = 80;
|
||||||
$sMessage = Dict::S('ExcelExporter:Done');
|
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sCode = 'retrieving-data';
|
||||||
|
$this->iPosition += $this->iChunkSize;
|
||||||
|
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
|
||||||
|
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'building-excel':
|
||||||
|
$hFile = @fopen($this->GetDataFile(), 'rb');
|
||||||
|
if ($hFile === false)
|
||||||
|
{
|
||||||
|
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
|
||||||
|
}
|
||||||
|
$sHeaders = fgets($hFile);
|
||||||
|
$aHeaders = json_decode($sHeaders, true);
|
||||||
|
|
||||||
|
$aData = array();
|
||||||
|
while($sLine = fgets($hFile))
|
||||||
|
{
|
||||||
|
$aRow = json_decode($sLine);
|
||||||
|
$aData[] = $aRow;
|
||||||
|
}
|
||||||
|
fclose($hFile);
|
||||||
|
@unlink($this->GetDataFile());
|
||||||
|
|
||||||
|
$fStartExcel = microtime(true);
|
||||||
|
$writer = new XLSXWriter();
|
||||||
|
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
||||||
|
$writer->writeSheet($aData,'Sheet1', $aHeaders);
|
||||||
|
$fExcelTime = microtime(true) - $fStartExcel;
|
||||||
|
$this->aStatistics['excel_build_duration'] = $fExcelTime;
|
||||||
|
|
||||||
|
$fTime = microtime(true);
|
||||||
|
$writer->writeToFile($this->GetExcelFilePath());
|
||||||
|
$fExcelSaveTime = microtime(true) - $fTime;
|
||||||
|
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
|
||||||
|
|
||||||
|
// Next state
|
||||||
|
$this->sState = 'done';
|
||||||
|
$sCode = 'done';
|
||||||
|
$iPercentage = 100;
|
||||||
|
$sMessage = Dict::S('ExcelExporter:Done');
|
||||||
|
break;
|
||||||
|
|
||||||
case 'done':
|
case 'done':
|
||||||
$this->sState = 'done';
|
$this->sState = 'done';
|
||||||
$sCode = 'done';
|
$sCode = 'done';
|
||||||
$iPercentage = 100;
|
$iPercentage = 100;
|
||||||
$sMessage = Dict::S('ExcelExporter:Done');
|
$sMessage = Dict::S('ExcelExporter:Done');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
$sCode = 'error';
|
$sCode = 'error';
|
||||||
$sMessage = $e->getMessage();
|
$sMessage = $e->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->aStatistics['total_duration'] += microtime(true) - $fTime;
|
$this->aStatistics['total_duration'] += microtime(true) - $fTime;
|
||||||
$peak_memory = memory_get_peak_usage(true);
|
$peak_memory = memory_get_peak_usage(true);
|
||||||
if ($peak_memory > $this->aStatistics['peak_memory_usage']) {
|
if ($peak_memory > $this->aStatistics['peak_memory_usage'])
|
||||||
|
{
|
||||||
$this->aStatistics['peak_memory_usage'] = $peak_memory;
|
$this->aStatistics['peak_memory_usage'] = $peak_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
'code' => $sCode,
|
'code' => $sCode,
|
||||||
'message' => $sMessage,
|
'message' => $sMessage,
|
||||||
'percentage' => $iPercentage,
|
'percentage' => $iPercentage,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetExcelFilePath()
|
public function GetExcelFilePath()
|
||||||
{
|
{
|
||||||
if ($this->sOutputFilePath == null) {
|
if ($this->sOutputFilePath == null)
|
||||||
|
{
|
||||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
|
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return $this->sOutputFilePath;
|
return $this->sOutputFilePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetExcelFileFromToken($sToken)
|
public static function GetExcelFileFromToken($sToken)
|
||||||
{
|
{
|
||||||
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function CleanupFromToken($sToken)
|
public static function CleanupFromToken($sToken)
|
||||||
{
|
{
|
||||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
|
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
|
||||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
|
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
|
||||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Cleanup()
|
public function Cleanup()
|
||||||
{
|
{
|
||||||
self::CleanupFromToken($this->sToken);
|
self::CleanupFromToken($this->sToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all files in the data/bulk_export directory which are older than 1 day
|
* Delete all files in the data/bulk_export directory which are older than 1 day
|
||||||
* unless a different delay is configured.
|
* unless a different delay is configured.
|
||||||
@@ -304,12 +332,15 @@ class ExcelExporter
|
|||||||
{
|
{
|
||||||
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
|
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
|
||||||
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
|
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
|
||||||
|
|
||||||
if ($iDelay > 0) {
|
if($iDelay > 0)
|
||||||
foreach ($aFiles as $sFile) {
|
{
|
||||||
|
foreach($aFiles as $sFile)
|
||||||
|
{
|
||||||
$iModificationTime = filemtime($sFile);
|
$iModificationTime = filemtime($sFile);
|
||||||
|
|
||||||
if ($iModificationTime < (time() - $iDelay)) {
|
if($iModificationTime < (time() - $iDelay))
|
||||||
|
{
|
||||||
// Temporary files older than one day are deleted
|
// Temporary files older than one day are deleted
|
||||||
//echo "Supposed to delete: '".$sFile." (Unix Modification Time: $iModificationTime)'\n";
|
//echo "Supposed to delete: '".$sFile." (Unix Modification Time: $iModificationTime)'\n";
|
||||||
@unlink($sFile);
|
@unlink($sFile);
|
||||||
@@ -317,155 +348,189 @@ class ExcelExporter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DisplayStatistics(Page $oPage)
|
public function DisplayStatistics(Page $oPage)
|
||||||
{
|
{
|
||||||
$aStats = [
|
$aStats = array(
|
||||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||||
];
|
);
|
||||||
|
|
||||||
if ($oPage instanceof CLIPage) {
|
if ($oPage instanceof CLIPage)
|
||||||
|
{
|
||||||
$oPage->add($this->GetStatistics('text'));
|
$oPage->add($this->GetStatistics('text'));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$oPage->add($this->GetStatistics('html'));
|
$oPage->add($this->GetStatistics('html'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetStatistics($sFormat = 'html')
|
public function GetStatistics($sFormat = 'html')
|
||||||
{
|
{
|
||||||
$sStats = '';
|
$sStats = '';
|
||||||
$aStats = [
|
$aStats = array(
|
||||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||||
];
|
);
|
||||||
|
|
||||||
if ($sFormat == 'text') {
|
if ($sFormat == 'text')
|
||||||
foreach ($aStats as $sLabel => $sValue) {
|
{
|
||||||
|
foreach($aStats as $sLabel => $sValue)
|
||||||
|
{
|
||||||
$sStats .= "+------------------------------+----------+\n";
|
$sStats .= "+------------------------------+----------+\n";
|
||||||
$sStats .= sprintf("|%-30s|%10s|\n", $sLabel, $sValue);
|
$sStats .= sprintf("|%-30s|%10s|\n", $sLabel, $sValue);
|
||||||
}
|
}
|
||||||
$sStats .= "+------------------------------+----------+";
|
$sStats .= "+------------------------------+----------+";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$sStats .= '<table><tbody>';
|
$sStats .= '<table><tbody>';
|
||||||
foreach ($aStats as $sLabel => $sValue) {
|
foreach($aStats as $sLabel => $sValue)
|
||||||
|
{
|
||||||
$sStats .= "<tr><td>$sLabel</td><td>$sValue</td></tr>";
|
$sStats .= "<tr><td>$sLabel</td><td>$sValue</td></tr>";
|
||||||
}
|
}
|
||||||
$sStats .= '</tbody></table>';
|
$sStats .= '</tbody></table>';
|
||||||
|
|
||||||
}
|
}
|
||||||
return $sStats;
|
return $sStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function HumanDisplay($iSize)
|
public static function HumanDisplay($iSize)
|
||||||
{
|
{
|
||||||
$aUnits = ['B','KB','MB','GB','TB','PB'];
|
$aUnits = array('B','KB','MB','GB','TB','PB');
|
||||||
return @round($iSize / pow(1024, ($i = floor(log($iSize, 1024)))), 2).' '.$aUnits[$i];
|
return @round($iSize/pow(1024,($i=floor(log($iSize,1024)))),2).' '.$aUnits[$i];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function CheckDataDir()
|
protected function CheckDataDir()
|
||||||
{
|
{
|
||||||
if (!is_dir(APPROOT."data/bulk_export")) {
|
if(!is_dir(APPROOT."data/bulk_export"))
|
||||||
|
{
|
||||||
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
}
|
}
|
||||||
if (!is_writable(APPROOT."data/bulk_export")) {
|
if (!is_writable(APPROOT."data/bulk_export"))
|
||||||
|
{
|
||||||
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function GetStateFile($sToken = null)
|
protected function GetStateFile($sToken = null)
|
||||||
{
|
{
|
||||||
if ($sToken == null) {
|
if ($sToken == null)
|
||||||
|
{
|
||||||
$sToken = $this->sToken;
|
$sToken = $this->sToken;
|
||||||
}
|
}
|
||||||
return APPROOT."data/bulk_export/$sToken.status";
|
return APPROOT."data/bulk_export/$sToken.status";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function GetDataFile()
|
protected function GetDataFile()
|
||||||
{
|
{
|
||||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
|
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function GetNewToken()
|
protected function GetNewToken()
|
||||||
{
|
{
|
||||||
$iNum = rand();
|
$iNum = rand();
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
$iNum++;
|
$iNum++;
|
||||||
$sToken = sprintf("%08x", $iNum);
|
$sToken = sprintf("%08x", $iNum);
|
||||||
$sFileName = $this->GetStateFile($sToken);
|
$sFileName = $this->GetStateFile($sToken);
|
||||||
$hFile = @fopen($sFileName, 'x');
|
$hFile = @fopen($sFileName, 'x');
|
||||||
} while ($hFile === false);
|
}
|
||||||
|
while($hFile === false);
|
||||||
|
|
||||||
fclose($hFile);
|
fclose($hFile);
|
||||||
return $sToken;
|
return $sToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
|
protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
|
||||||
{
|
{
|
||||||
$this->aFieldsList = [];
|
$this->aFieldsList = array();
|
||||||
|
|
||||||
$oAppContext = new ApplicationContext();
|
$oAppContext = new ApplicationContext();
|
||||||
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
|
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
|
||||||
$this->aAuthorizedClasses = [];
|
$this->aAuthorizedClasses = array();
|
||||||
foreach ($aClasses as $sAlias => $sClassName) {
|
foreach($aClasses as $sAlias => $sClassName)
|
||||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) {
|
{
|
||||||
|
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO)
|
||||||
|
{
|
||||||
$this->aAuthorizedClasses[$sAlias] = $sClassName;
|
$this->aAuthorizedClasses[$sAlias] = $sClassName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$aAttribs = [];
|
$aAttribs = array();
|
||||||
$this->aTableHeaders = [];
|
$this->aTableHeaders = array();
|
||||||
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
|
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||||
$aList[$sAlias] = [];
|
{
|
||||||
|
$aList[$sAlias] = array();
|
||||||
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
|
|
||||||
if (is_null($aFields) || (count($aFields) == 0)) {
|
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
|
||||||
|
{
|
||||||
|
if (is_null($aFields) || (count($aFields) == 0))
|
||||||
|
{
|
||||||
// Standard list of attributes (no link sets)
|
// Standard list of attributes (no link sets)
|
||||||
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) {
|
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField()))
|
||||||
|
{
|
||||||
$sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode;
|
$sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode;
|
||||||
|
|
||||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
|
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||||
if ($bFieldsAdvanced) {
|
{
|
||||||
|
if ($bFieldsAdvanced)
|
||||||
|
{
|
||||||
$aList[$sAlias][$sAttCodeEx] = $oAttDef;
|
$aList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||||
|
|
||||||
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE)) {
|
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE))
|
||||||
$sRemoteClass = $oAttDef->GetTargetClass();
|
{
|
||||||
foreach (MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode) {
|
$sRemoteClass = $oAttDef->GetTargetClass();
|
||||||
|
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode)
|
||||||
|
{
|
||||||
$this->aFieldsList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
|
$this->aFieldsList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Any other attribute
|
// Any other attribute
|
||||||
$this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
|
$this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// User defined list of attributes
|
// User defined list of attributes
|
||||||
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields)) {
|
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields))
|
||||||
|
{
|
||||||
$this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
|
$this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($bFieldsAdvanced) {
|
if ($bFieldsAdvanced)
|
||||||
|
{
|
||||||
$this->aTableHeaders['id'] = '0';
|
$this->aTableHeaders['id'] = '0';
|
||||||
}
|
}
|
||||||
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
|
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||||
|
{
|
||||||
$sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
|
$sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
|
||||||
if ($oAttDef instanceof AttributeDateTime) {
|
if($oAttDef instanceof AttributeDateTime)
|
||||||
|
{
|
||||||
$this->aTableHeaders[$sLabel] = 'datetime';
|
$this->aTableHeaders[$sLabel] = 'datetime';
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$this->aTableHeaders[$sLabel] = 'string';
|
$this->aTableHeaders[$sLabel] = 'string';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BulkChangeException extends CoreException
|
class BulkChangeException extends CoreException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CSVParserException extends CoreException
|
class CSVParserException extends CoreException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ConfigException extends CoreException
|
class ConfigException extends CoreException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -45,15 +44,15 @@ class CoreCannotSaveObjectException extends CoreException
|
|||||||
public function getHtmlMessage()
|
public function getHtmlMessage()
|
||||||
{
|
{
|
||||||
$sTitle = Dict::S('UI:Error:SaveFailed');
|
$sTitle = Dict::S('UI:Error:SaveFailed');
|
||||||
$sContent = "<span><strong>".utils::HtmlEntities($sTitle)."</strong></span>";
|
$sContent = "<span><strong>{$sTitle}</strong></span>";
|
||||||
|
|
||||||
if (count($this->aIssues) == 1) {
|
if (count($this->aIssues) == 1) {
|
||||||
$sIssue = reset($this->aIssues);
|
$sIssue = reset($this->aIssues);
|
||||||
$sContent .= " <span>".utils::HtmlEntities($sIssue)."</span>";
|
$sContent .= " <span>{$sIssue}</span>";
|
||||||
} else {
|
} else {
|
||||||
$sContent .= '<ul>';
|
$sContent .= '<ul>';
|
||||||
foreach ($this->aIssues as $sError) {
|
foreach ($this->aIssues as $sError) {
|
||||||
$sContent .= "<li>".utils::HtmlEntities($sError)."</li>";
|
$sContent .= "<li>$sError</li>";
|
||||||
}
|
}
|
||||||
$sContent .= '</ul>';
|
$sContent .= '</ul>';
|
||||||
}
|
}
|
||||||
@@ -61,23 +60,6 @@ class CoreCannotSaveObjectException extends CoreException
|
|||||||
return $sContent;
|
return $sContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTextMessage()
|
|
||||||
{
|
|
||||||
$sTitle = Dict::S('UI:Error:SaveFailed');
|
|
||||||
$sContent = $sTitle;
|
|
||||||
|
|
||||||
if (count($this->aIssues) == 1) {
|
|
||||||
$sIssue = reset($this->aIssues);
|
|
||||||
$sContent .= $sIssue;
|
|
||||||
} else {
|
|
||||||
foreach ($this->aIssues as $sError) {
|
|
||||||
$sContent .= " ".$sError.", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIssues()
|
public function getIssues()
|
||||||
{
|
{
|
||||||
return $this->aIssues;
|
return $this->aIssues;
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CoreException extends Exception
|
class CoreException extends Exception
|
||||||
{
|
{
|
||||||
protected $m_sIssue;
|
|
||||||
protected $m_sImpact;
|
|
||||||
protected $m_aContextData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CoreException constructor.
|
* CoreException constructor.
|
||||||
*
|
*
|
||||||
@@ -36,10 +31,10 @@ class CoreException extends Exception
|
|||||||
}
|
}
|
||||||
if (count($this->m_aContextData) > 0) {
|
if (count($this->m_aContextData) > 0) {
|
||||||
$sMessage .= ": ";
|
$sMessage .= ": ";
|
||||||
$aContextItems = [];
|
$aContextItems = array();
|
||||||
foreach ($this->m_aContextData as $sKey => $value) {
|
foreach ($this->m_aContextData as $sKey => $value) {
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$aPairs = [];
|
$aPairs = array();
|
||||||
foreach ($value as $key => $val) {
|
foreach ($value as $key => $val) {
|
||||||
if (is_array($val)) {
|
if (is_array($val)) {
|
||||||
$aPairs[] = $key.'=>('.implode(', ', $val).')';
|
$aPairs[] = $key.'=>('.implode(', ', $val).')';
|
||||||
@@ -68,7 +63,7 @@ class CoreException extends Exception
|
|||||||
|
|
||||||
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
|
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
|
||||||
{
|
{
|
||||||
return utils::EscapeHtml($this->getMessage());
|
return $this->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,4 +105,4 @@ class CoreException extends Exception
|
|||||||
{
|
{
|
||||||
return $this->m_aContextData;
|
return $this->m_aContextData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,4 +9,5 @@
|
|||||||
*/
|
*/
|
||||||
class CorePortalInvalidActionRuleException extends CoreException
|
class CorePortalInvalidActionRuleException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,4 +14,4 @@ class CoreTemplateException extends CoreException
|
|||||||
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
|
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
|
||||||
parent::__construct($sMessage, null, '', $oTwigException);
|
parent::__construct($sMessage, null, '', $oTwigException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DeleteException extends CoreException
|
class DeleteException extends CoreException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ForgotPasswordApplicationException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ForgotPasswordUserInputException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458 object creation
|
|
||||||
*/
|
|
||||||
class InvalidExternalKeyValueException extends CoreUnexpectedValue
|
|
||||||
{
|
|
||||||
private const ENUM_PARAMS_OBJECT = 'current_object';
|
|
||||||
private const ENUM_PARAMS_ATTCODE = 'attcode';
|
|
||||||
private const ENUM_PARAMS_ATTVALUE = 'attvalue';
|
|
||||||
private const ENUM_PARAMS_USER = 'current_user';
|
|
||||||
|
|
||||||
public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null)
|
|
||||||
{
|
|
||||||
$aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject).'::'.$oObject->GetKey();
|
|
||||||
$aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode;
|
|
||||||
$aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode);
|
|
||||||
|
|
||||||
$oCurrentUser = UserRights::GetUserObject();
|
|
||||||
if (false === is_null($oCurrentUser)) {
|
|
||||||
$aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser).'::'.$oCurrentUser->GetKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetAttCode(): string
|
|
||||||
{
|
|
||||||
return $this->getContextData()[self::ENUM_PARAMS_ATTCODE];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetAttValue(): string
|
|
||||||
{
|
|
||||||
return $this->getContextData()[self::ENUM_PARAMS_ATTVALUE];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user