mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 23:44:11 +01:00
Compare commits
255 Commits
faf/quick_
...
feature/63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a3519c907 | ||
|
|
05deaf33bb | ||
|
|
73f868ac83 | ||
|
|
5a2157ba21 | ||
|
|
03e25a226e | ||
|
|
24048d2b9c | ||
|
|
d8121b563a | ||
|
|
f266f5ff36 | ||
|
|
4a6b129eb8 | ||
|
|
4187f552a9 | ||
|
|
7f7ce0837e | ||
|
|
bc4d50dd0b | ||
|
|
e21a541b70 | ||
|
|
ed360edb83 | ||
|
|
53de040934 | ||
|
|
b8345de553 | ||
|
|
fd10887849 | ||
|
|
7df09541ac | ||
|
|
e09987e442 | ||
|
|
6d5660ca67 | ||
|
|
0013b8cfee | ||
|
|
7fb0ae48f9 | ||
|
|
e89a8edae0 | ||
|
|
262cc3c206 | ||
|
|
b5fe12ca3c | ||
|
|
6d279647f1 | ||
|
|
299c468eaa | ||
|
|
7bbcc388ea | ||
|
|
5b7a5e14a3 | ||
|
|
2b1ecf15b4 | ||
|
|
f6366057c9 | ||
|
|
41a90b5033 | ||
|
|
67018b9b17 | ||
|
|
fa8ecb956e | ||
|
|
58eae4dde3 | ||
|
|
d098a5eb87 | ||
|
|
8597dea398 | ||
|
|
a6972af266 | ||
|
|
066b27c982 | ||
|
|
283de1ef7c | ||
|
|
8b00016115 | ||
|
|
b5c79e1d75 | ||
|
|
dd82950eee | ||
|
|
2e8b48ce47 | ||
|
|
80d4e65a81 | ||
|
|
b0a792afab | ||
|
|
7681c157ec | ||
|
|
4a9a85458d | ||
|
|
890a2568c8 | ||
|
|
12f23113f5 | ||
|
|
6cf6e7dd8d | ||
|
|
d4183acfde | ||
|
|
26f21ee6eb | ||
|
|
c5fb116052 | ||
|
|
bdc8fdd02f | ||
|
|
adfa800063 | ||
|
|
5df936c587 | ||
|
|
8056a63e82 | ||
|
|
775ac3df77 | ||
|
|
83927af8ed | ||
|
|
f1609168b7 | ||
|
|
4f845c63cf | ||
|
|
d029039d22 | ||
|
|
10a7fafe59 | ||
|
|
700b95e8c6 | ||
|
|
600a6185a3 | ||
|
|
354a7cabab | ||
|
|
0802e5abb5 | ||
|
|
8ade0a6e85 | ||
|
|
6226ac8746 | ||
|
|
e661e0bdbb | ||
|
|
1d52665012 | ||
|
|
4aa0c19183 | ||
|
|
809d4cd665 | ||
|
|
0c3bc7f35b | ||
|
|
bfc583e6b5 | ||
|
|
5bc453bca6 | ||
|
|
5dd450e9bf | ||
|
|
82395727bf | ||
|
|
318b792b31 | ||
|
|
0fe2183369 | ||
|
|
8f038d2f95 | ||
|
|
fbf3dd8cf7 | ||
|
|
01c9e73020 | ||
|
|
0736045b90 | ||
|
|
778c16da86 | ||
|
|
86776edfb3 | ||
|
|
5045ec4afa | ||
|
|
d78805d8ae | ||
|
|
03e1d46586 | ||
|
|
f3deb8be11 | ||
|
|
981d5c6263 | ||
|
|
e000befc0f | ||
|
|
2eba58998b | ||
|
|
4ed21dc21a | ||
|
|
fa5cad0fdb | ||
|
|
5d28de1636 | ||
|
|
6be9255ca0 | ||
|
|
1f4a2f0f56 | ||
|
|
edbe4974ac | ||
|
|
7e515e7216 | ||
|
|
bf7a756714 | ||
|
|
428d2c6356 | ||
|
|
d589d9d05a | ||
|
|
c0c9ea9287 | ||
|
|
fae2bcc6e9 | ||
|
|
53047d35fe | ||
|
|
8982f7e0e3 | ||
|
|
909469ce97 | ||
|
|
dacb54285c | ||
|
|
5af93ca92a | ||
|
|
3fa500c9c1 | ||
|
|
f0adbbba29 | ||
|
|
bbdb30f421 | ||
|
|
897b5d452e | ||
|
|
fdd1479c8e | ||
|
|
7851109794 | ||
|
|
810e6c1bda | ||
|
|
d164f48cfe | ||
|
|
506def4340 | ||
|
|
08b8e919b7 | ||
|
|
696e2c9565 | ||
|
|
d728be119c | ||
|
|
463869b89d | ||
|
|
1d4c0b8e7f | ||
|
|
bf1b2a5104 | ||
|
|
15103dc49f | ||
|
|
bb8a09d8e2 | ||
|
|
901f8f2a7b | ||
|
|
ba6fff801b | ||
|
|
50098bad73 | ||
|
|
2ee68ff819 | ||
|
|
44972f34e5 | ||
|
|
65c9145b10 | ||
|
|
a104310379 | ||
|
|
f5cce23bb4 | ||
|
|
0f39106b56 | ||
|
|
ee993ef80a | ||
|
|
0a4180f7fc | ||
|
|
b56113aada | ||
|
|
c82c150411 | ||
|
|
00818f411f | ||
|
|
a6a459967e | ||
|
|
2ba4109343 | ||
|
|
738664e560 | ||
|
|
88e0f17164 | ||
|
|
d48bc15211 | ||
|
|
32f0cfb091 | ||
|
|
20393b55b9 | ||
|
|
437296eab9 | ||
|
|
f03b008ebf | ||
|
|
7f98ef3478 | ||
|
|
d80e26791d | ||
|
|
e6a0d95cba | ||
|
|
965c9dba14 | ||
|
|
8bca3ac830 | ||
|
|
a975f67bd5 | ||
|
|
f5b86ff4d9 | ||
|
|
0deeeeb587 | ||
|
|
2011570b84 | ||
|
|
1458ba877b | ||
|
|
71386198cf | ||
|
|
5b9e0a1d4f | ||
|
|
1667f834b9 | ||
|
|
7cf6f65265 | ||
|
|
cdbcd14767 | ||
|
|
603340b852 | ||
|
|
820087e4d1 | ||
|
|
c5ee123f88 | ||
|
|
69d5015a24 | ||
|
|
1d1365d951 | ||
|
|
3da33c4c64 | ||
|
|
491f55c7bd | ||
|
|
7b95d65f60 | ||
|
|
d3e450c54e | ||
|
|
5a50398dba | ||
|
|
387ca19ec2 | ||
|
|
c0651edaa1 | ||
|
|
b06f3cd13e | ||
|
|
5aeb408edd | ||
|
|
7456383d72 | ||
|
|
9c6b8f90f0 | ||
|
|
e6ea2fd541 | ||
|
|
7d94e6f1f8 | ||
|
|
2bd7c7a01a | ||
|
|
f1762845f0 | ||
|
|
3eb8437c32 | ||
|
|
9acc6a8bd4 | ||
|
|
4d794fe656 | ||
|
|
c9f88a16ef | ||
|
|
95f84a98cc | ||
|
|
6cb10ab13a | ||
|
|
048aaeb854 | ||
|
|
2b18ab9690 | ||
|
|
36dc71fdce | ||
|
|
db2ad86c70 | ||
|
|
56616ab08e | ||
|
|
f339498497 | ||
|
|
b24a359b36 | ||
|
|
78c63f7502 | ||
|
|
2f8b35c153 | ||
|
|
271a1f66c1 | ||
|
|
738c7e1b8e | ||
|
|
54278f8c02 | ||
|
|
00e117b05f | ||
|
|
504261a2c2 | ||
|
|
14a1a4e9c7 | ||
|
|
cfc4a43d0b | ||
|
|
503a5ec25a | ||
|
|
09364ccf84 | ||
|
|
7b44ec23a1 | ||
|
|
f00b8d529c | ||
|
|
4bbd1fea5c | ||
|
|
3c27847a04 | ||
|
|
af44ffd0ad | ||
|
|
8523da3329 | ||
|
|
c63e01e27b | ||
|
|
de54676b9f | ||
|
|
8580cb70a4 | ||
|
|
1438006861 | ||
|
|
e5129c9618 | ||
|
|
d0f816109b | ||
|
|
700470dd29 | ||
|
|
05642cdf84 | ||
|
|
bfbc939bac | ||
|
|
dffce3f2f7 | ||
|
|
497fc4978a | ||
|
|
e96095e02d | ||
|
|
6826ab509d | ||
|
|
8330582f86 | ||
|
|
5a4ad7b8c3 | ||
|
|
a116967b0a | ||
|
|
a13f353721 | ||
|
|
bd254e56d1 | ||
|
|
346bd5de47 | ||
|
|
41194ce9ab | ||
|
|
599e08f150 | ||
|
|
0e5bece5b6 | ||
|
|
0462298cd3 | ||
|
|
80abaec9a6 | ||
|
|
e987ea72bc | ||
|
|
a7877dc6a6 | ||
|
|
c8371f1c19 | ||
|
|
031305cfbf | ||
|
|
a2d6423f32 | ||
|
|
471422b274 | ||
|
|
5573a222c8 | ||
|
|
83eb2b81e3 | ||
|
|
86d2a3424d | ||
|
|
cd1c6f5ec5 | ||
|
|
2ee30692ff | ||
|
|
9aa13f57d8 | ||
|
|
f9d9fcc440 | ||
|
|
a4a05a2579 | ||
|
|
f44468b7a1 |
101
.doc/README.md
101
.doc/README.md
@@ -1,101 +0,0 @@
|
||||
# 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
|
||||
|
||||
Note : PHP7 is required. Migrating to PHP8 requires some additional work which is questionable as an alternative way to generate a documentation is being considered.
|
||||
|
||||
```
|
||||
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
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"require-dev": {
|
||||
"phpdocumentor/phpdocumentor": "~2",
|
||||
"jms/serializer": "1.7.*"
|
||||
}
|
||||
}
|
||||
3015
.doc/composer.lock
generated
3015
.doc/composer.lock
generated
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 983 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.0 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -86,19 +86,24 @@ gitGraph
|
||||
commit id: "2024-01-17a" tag: "2.7.10"
|
||||
checkout support/3.0
|
||||
commit id: "2024-01-17b" tag: "3.0.4"
|
||||
checkout support/2.7
|
||||
commit id: "2024-09-28" tag: "2.7.11"
|
||||
checkout support/3.1
|
||||
commit id: "2024-09-27" tag: "3.1.2"
|
||||
checkout support/3.2
|
||||
commit id: "2024-06-25" tag: "3.2.0-beta1" type: REVERSE
|
||||
commit id: "2024-08-07" tag: "3.2.0"
|
||||
commit id: "2024-09-13" tag: "3.2.0-2"
|
||||
checkout support/3.1
|
||||
commit id: "2024-09-27" tag: "3.1.2"
|
||||
checkout support/2.7
|
||||
commit id: "2024-09-28" tag: "2.7.11"
|
||||
checkout support/2.7
|
||||
commit id: "2025-02-25" tag: "2.7.12"
|
||||
checkout support/3.1
|
||||
commit id: "2025-02-25 " tag: "3.1.3"
|
||||
checkout support/3.2
|
||||
commit id: "2025-02-25 " tag: "3.2.1"
|
||||
commit id: "2025-04-08" tag: "3.2.1-1"
|
||||
commit id: "2025-08-19" tag: "3.2.2-1"
|
||||
checkout support/2.7
|
||||
commit id: "2025-10-07" tag: "2.7.13"
|
||||
```
|
||||
|
||||
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,58 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,136 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,31 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,95 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,49 +0,0 @@
|
||||
{% 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 +0,0 @@
|
||||
{{ node.source|raw }}
|
||||
@@ -1,122 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,42 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,5 +0,0 @@
|
||||
# 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>
|
||||
@@ -1,34 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,12 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,26 +0,0 @@
|
||||
{% 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 %}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,56 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,20 +0,0 @@
|
||||
{% 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 -%}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,24 +0,0 @@
|
||||
{% 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 %}#}
|
||||
@@ -1,24 +0,0 @@
|
||||
{% 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 %}#}
|
||||
@@ -1,11 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,121 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,5 +0,0 @@
|
||||
{% use 'elements/constant.txt.twig' %}
|
||||
{% use 'elements/property.txt.twig' %}
|
||||
{% use 'elements/method.txt.twig' %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
@@ -1,51 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
====== 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 %}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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>
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -9,7 +9,7 @@ Any PRs not following the guidelines or with missing information will not be con
|
||||
## Base information
|
||||
| Question | Answer
|
||||
|---------------------------------------------------------------|--------
|
||||
| Related to a SourceForge thead / Another PR / Combodo ticket? | <!-- Put the URL -->
|
||||
| Related to a SourceForge thread / Another PR / Combodo ticket? | <!-- Put the URL -->
|
||||
| Type of change? | Bug fix / Enhancement / Translations
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ if (false === file_exists($sTcPdfRootFolder)) {
|
||||
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
|
||||
return;
|
||||
}
|
||||
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/Fonts/';
|
||||
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/fonts/';
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -199,7 +199,7 @@ class DatamodelsXmlFiles extends AbstractGlobFileVersionUpdater
|
||||
libxml_clear_errors();
|
||||
$oFileXml->formatOutput = true;
|
||||
$oFileXml->preserveWhiteSpace = false;
|
||||
$oFileXml->loadXML($sFileContent);
|
||||
$oFileXml->loadXML($sFileContent, LIBXML_BIGLINES);
|
||||
|
||||
$oFileItopFormat = new iTopDesignFormat($oFileXml);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ You want to contribute to iTop? Many thanks to you! 🎉 👍
|
||||
Here are some guidelines that will help us integrate your work!
|
||||
|
||||
|
||||
## Contributions
|
||||
|
||||
|
||||
### Subjects
|
||||
You are welcome to create pull requests on any of those subjects:
|
||||
@@ -161,4 +161,4 @@ We have one sticker per contribution type. You might get multiple stickers with
|
||||
|
||||
Here is the design of each stickers for year 2024:
|
||||
|
||||

|
||||

|
||||
|
||||
11
README.md
11
README.md
@@ -1,5 +1,9 @@
|
||||
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
|
||||
<img src="https://www.combodo.com/logos/logo-itop-baseline.svg" width=350>
|
||||
<p align="center"><a href="https://combodo.com" target="_blank">
|
||||
<picture>
|
||||
<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>
|
||||
|
||||
|
||||
@@ -49,7 +53,7 @@ iTop also offers mass import tools to help you become even more efficient.
|
||||
[4]: https://www.itophub.io/wiki/page?id=latest:install:requirements
|
||||
[5]: https://www.itophub.io/wiki
|
||||
[6]: https://store.itophub.io/en_US/
|
||||
[7]: .doc/itop-version-history.md
|
||||
[7]: itop-version-history.md
|
||||
|
||||
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
||||
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
||||
@@ -95,6 +99,7 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- Goethals, Stefan
|
||||
- Giuva, Vincenzo Katriel (a.k.a [@DarkNight97boss](https://github.com/DarkNight97boss))
|
||||
- Gumble, David
|
||||
- Håkon, Harnes (a.k.a [@hakonharnes](https://github.com/hakonharnes))
|
||||
- Heloir, Arthur
|
||||
- Janssens, Jelle (a.k.a [@janssensjelle](https://github.com/janssensjelle))
|
||||
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
|
||||
|
||||
@@ -1,362 +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/>
|
||||
|
||||
/**
|
||||
* UserRightsMatrix (User management Module)
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class UserRightsMatrixClassGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_ur_matrixclasses",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||
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", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
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 UserRightsMatrixClassStimulusGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_ur_matrixclassesstimulus",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||
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", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
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 UserRightsMatrixAttributeGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_ur_matrixattributes",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||
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", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
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", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
{
|
||||
static public $m_aActionCodes = array(
|
||||
UR_ACTION_READ => 'read',
|
||||
UR_ACTION_MODIFY => 'modify',
|
||||
UR_ACTION_DELETE => 'delete',
|
||||
UR_ACTION_BULK_READ => 'bulk read',
|
||||
UR_ACTION_BULK_MODIFY => 'bulk modify',
|
||||
UR_ACTION_BULK_DELETE => 'bulk delete',
|
||||
);
|
||||
|
||||
// Installation: create the very first user
|
||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||
{
|
||||
// Maybe we should check that no other user with userid == 0 exists
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', $sAdminUser);
|
||||
$oUser->Set('password', $sAdminPwd);
|
||||
$oUser->Set('contactid', 1); // one is for root !
|
||||
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
||||
|
||||
// Now record the admin user object
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
$this->SetupUser($iUserId, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function IsAdministrator($oUser)
|
||||
{
|
||||
return ($oUser->GetKey() == 1);
|
||||
}
|
||||
|
||||
public function IsPortalUser($oUser)
|
||||
{
|
||||
return ($oUser->GetKey() == 1);
|
||||
}
|
||||
|
||||
// Deprecated - create a new module !
|
||||
public function Setup()
|
||||
{
|
||||
// Users must be added manually
|
||||
// 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"));
|
||||
while ($oUser = $oUserSet->Fetch())
|
||||
{
|
||||
$this->SetupUser($oUser->GetKey());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function SetupUser($iUserId, $bNewUser = false)
|
||||
{
|
||||
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory)
|
||||
{
|
||||
foreach (MetaModel::GetClasses($sCategory) as $sClass)
|
||||
{
|
||||
foreach (self::$m_aActionCodes as $iActionCode => $sAction)
|
||||
{
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddCell = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
|
||||
$oMyClassGrant->Set("userid", $iUserId);
|
||||
$oMyClassGrant->Set("class", $sClass);
|
||||
$oMyClassGrant->Set("action", $sAction);
|
||||
$oMyClassGrant->Set("permission", "yes");
|
||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
|
||||
{
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddCell = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
|
||||
$oMyClassGrant->Set("userid", $iUserId);
|
||||
$oMyClassGrant->Set("class", $sClass);
|
||||
$oMyClassGrant->Set("stimulus", $sStimulusCode);
|
||||
$oMyClassGrant->Set("permission", "yes");
|
||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
|
||||
{
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddCell = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell)
|
||||
{
|
||||
foreach (array('read', 'modify') as $sAction)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
|
||||
$oMyAttGrant->Set("userid", $iUserId);
|
||||
$oMyAttGrant->Set("class", $sClass);
|
||||
$oMyAttGrant->Set("attcode", $sAttCode);
|
||||
$oMyAttGrant->Set("action", $sAction);
|
||||
$oMyAttGrant->Set("permission", "yes");
|
||||
$iId = $oMyAttGrant->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Create the "My Bookmarks" menu item (parent_id = 0, rank = 6)
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddMenu = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT menuNode WHERE type = 'user' AND parent_id = 0 AND user_id = $iUserId"));
|
||||
$bAddMenu = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddMenu)
|
||||
{
|
||||
$oMenu = MetaModel::NewObject('menuNode');
|
||||
$oMenu->Set('type', 'user');
|
||||
$oMenu->Set('parent_id', 0); // It's a toplevel entry
|
||||
$oMenu->Set('rank', 6); // Located just above the Admin Tools section (=7)
|
||||
$oMenu->Set('name', 'My Bookmarks');
|
||||
$oMenu->Set('label', 'My Favorite Items');
|
||||
$oMenu->Set('hyperlink', 'UI.php');
|
||||
$oMenu->Set('template', '<p></p><p></p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:32px;">My bookmarks</p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:14px;"><i>This section contains my most favorite search results</i></p>');
|
||||
$oMenu->Set('user_id', $iUserId);
|
||||
$oMenu->DBInsert();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public function Init()
|
||||
{
|
||||
// Could be loaded in a shared memory (?)
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||
{
|
||||
$oNullFilter = new DBObjectSearch($sClass);
|
||||
return $oNullFilter;
|
||||
}
|
||||
|
||||
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = '{$oUser->GetKey()}'"));
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
case 'no':
|
||||
default:
|
||||
$iRetCode = UR_ALLOWED_NO;
|
||||
break;
|
||||
}
|
||||
return $iRetCode;
|
||||
}
|
||||
|
||||
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
$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()}'"));
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
case 'no':
|
||||
default:
|
||||
$iRetCode = UR_ALLOWED_NO;
|
||||
break;
|
||||
}
|
||||
return $iRetCode;
|
||||
}
|
||||
|
||||
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()}'"));
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
case 'no':
|
||||
default:
|
||||
$iRetCode = UR_ALLOWED_NO;
|
||||
break;
|
||||
}
|
||||
return $iRetCode;
|
||||
}
|
||||
|
||||
public function FlushPrivileges()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
UserRights::SelectModule('UserRightsMatrix');
|
||||
|
||||
?>
|
||||
@@ -1,78 +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/>
|
||||
|
||||
/**
|
||||
* UserRightsNull
|
||||
* User management Module - say Yeah! to everything
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class UserRightsNull extends UserRightsAddOnAPI
|
||||
{
|
||||
// Installation: create the very first user
|
||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function IsAdministrator($oUser)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function IsPortalUser($oUser)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||
{
|
||||
$oNullFilter = new DBObjectSearch($sClass);
|
||||
return $oNullFilter;
|
||||
}
|
||||
|
||||
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
return UR_ALLOWED_YES;
|
||||
}
|
||||
|
||||
public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
|
||||
{
|
||||
return UR_ALLOWED_YES;
|
||||
}
|
||||
|
||||
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
return UR_ALLOWED_YES;
|
||||
}
|
||||
|
||||
public function FlushPrivileges()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
UserRights::SelectModule('UserRightsNull');
|
||||
|
||||
?>
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -29,56 +30,52 @@ class UserRightsBaseClassGUI extends cmdbAbstractObject
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "addon/userrights,grant_by_profile,filter",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"complementary_name_attcode" => array('description'),
|
||||
"complementary_name_attcode" => ['description'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"reconc_keys" => [],
|
||||
"db_table" => "priv_urp_profiles",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
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("description", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "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())));
|
||||
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" => []]));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'user_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'user_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', array('name','description')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array ('name','description'));
|
||||
MetaModel::Init_SetZListItems('standard_search', ['name','description']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', ['name','description']);
|
||||
}
|
||||
|
||||
protected static $m_aCacheProfiles = null;
|
||||
|
||||
public static function DoCreateProfile($sName, $sDescription)
|
||||
{
|
||||
if (is_null(self::$m_aCacheProfiles))
|
||||
{
|
||||
self::$m_aCacheProfiles = array();
|
||||
if (is_null(self::$m_aCacheProfiles)) {
|
||||
self::$m_aCacheProfiles = [];
|
||||
$oFilterAll = new DBObjectSearch('URP_Profiles');
|
||||
$oSet = new DBObjectSet($oFilterAll);
|
||||
while ($oProfile = $oSet->Fetch())
|
||||
{
|
||||
while ($oProfile = $oSet->Fetch()) {
|
||||
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
|
||||
}
|
||||
}
|
||||
|
||||
$sCacheKey = $sName;
|
||||
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
|
||||
{
|
||||
if (isset(self::$m_aCacheProfiles[$sCacheKey])) {
|
||||
return self::$m_aCacheProfiles[$sCacheKey];
|
||||
}
|
||||
$oNewObj = MetaModel::NewObject("URP_Profiles");
|
||||
@@ -89,27 +86,21 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
return $iId;
|
||||
}
|
||||
|
||||
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
||||
public function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
||||
{
|
||||
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
|
||||
if (is_null($bGrant))
|
||||
{
|
||||
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||
}
|
||||
elseif ($bGrant)
|
||||
{
|
||||
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>';
|
||||
if (is_null($bGrant)) {
|
||||
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||
} elseif ($bGrant) {
|
||||
return '<span class="ibo-user-rights ibo-is-success">'.Dict::S('UI:UserManagement:ActionAllowed:Yes').'</span>';
|
||||
} else {
|
||||
return '<span class="ibo-user-rights ibo-is-failure">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||
}
|
||||
}
|
||||
|
||||
function DoShowGrantSumary($oPage)
|
||||
public function DoShowGrantSumary($oPage)
|
||||
{
|
||||
if ($this->GetRawName() == "Administrator")
|
||||
{
|
||||
if ($this->GetRawName() == "Administrator") {
|
||||
// Looks dirty, but ok that's THE ONE
|
||||
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
|
||||
return;
|
||||
@@ -118,21 +109,18 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
// Note: for sure, we assume that the instance is derived from UserRightsProfile
|
||||
$oUserRights = UserRights::GetModuleInstance();
|
||||
|
||||
$aDisplayData = array();
|
||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
|
||||
{
|
||||
$aStimuli = array();
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
|
||||
{
|
||||
$aDisplayData = [];
|
||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
|
||||
$aStimuli = [];
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
|
||||
$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>';
|
||||
}
|
||||
}
|
||||
$sStimuli = implode(', ', $aStimuli);
|
||||
|
||||
$aDisplayData[] = array(
|
||||
$aDisplayData[] = [
|
||||
'class' => MetaModel::GetName($sClass),
|
||||
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
|
||||
'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'),
|
||||
@@ -141,22 +129,22 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'),
|
||||
'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'),
|
||||
'stimuli' => $sStimuli,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
$aDisplayConfig = array();
|
||||
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
|
||||
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
|
||||
$aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
|
||||
$aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
|
||||
$aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
|
||||
$aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+'));
|
||||
$aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+'));
|
||||
$aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
|
||||
$aDisplayConfig = [];
|
||||
$aDisplayConfig['class'] = ['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['bulkread'] = ['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['bulkwrite'] = ['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['bulkdelete'] = ['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+')];
|
||||
$oPage->table($aDisplayConfig, $aDisplayData);
|
||||
}
|
||||
|
||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||
|
||||
@@ -166,10 +154,9 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
|
||||
public static function GetReadOnlyAttributes()
|
||||
{
|
||||
return array('name', 'description');
|
||||
return ['name', 'description'];
|
||||
}
|
||||
|
||||
|
||||
// returns an array of id => array of column => php value(so-called "real value")
|
||||
public static function GetPredefinedObjects()
|
||||
{
|
||||
@@ -181,15 +168,13 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
protected function OnDelete()
|
||||
{
|
||||
// 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'));
|
||||
}
|
||||
|
||||
// Note: this may break the rule that says: "a user must have at least ONE profile" !
|
||||
$oLnkSet = $this->Get('user_list');
|
||||
while($oLnk = $oLnkSet->Fetch())
|
||||
{
|
||||
while ($oLnk = $oLnkSet->Fetch()) {
|
||||
$oLnk->DBDelete();
|
||||
}
|
||||
}
|
||||
@@ -202,11 +187,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
* @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
|
||||
*/
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
public function 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!';
|
||||
$iFlags |= OPT_ATT_READONLY;
|
||||
}
|
||||
@@ -214,52 +198,52 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "addon/userrights,grant_by_profile,filter",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "profile"),
|
||||
"name_attcode" => ["userlogin", "profile"],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"reconc_keys" => [],
|
||||
"db_table" => "priv_urp_userprofile",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"is_link" => true, /** @since 3.1.0 N°6482 */
|
||||
'uniqueness_rules' => array(
|
||||
'no_duplicate' => array(
|
||||
'attributes' => array(
|
||||
'uniqueness_rules' => [
|
||||
'no_duplicate' => [
|
||||
'attributes' => [
|
||||
0 => 'userid',
|
||||
1 => 'profileid',
|
||||
),
|
||||
],
|
||||
'filter' => '',
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login")));
|
||||
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 AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
||||
|
||||
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(), "allow_target_creation" => false)));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values" => null, "extkey_attcode" => 'profileid', "target_attcode" => "name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey(
|
||||
"profileid",
|
||||
["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", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('userid', 'profileid', 'reason')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('userid', 'profileid', 'reason')); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', ['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
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||
MetaModel::Init_SetZListItems('standard_search', ['userid', 'profileid']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', ['userid', 'profileid']); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function CheckToDelete(&$oDeletionPlan)
|
||||
@@ -267,15 +251,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
// Users deletion is NOT allowed in demo mode
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||
}
|
||||
catch (SecurityException $e) {
|
||||
} catch (SecurityException $e) {
|
||||
// Users deletion is NOT allowed
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||
@@ -292,15 +275,14 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
// Users deletion is NOT allowed in demo mode
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||
$oDeletionPlan->SetDeletionIssues($this, ['deletion not allowed in demo mode.'], true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||
}
|
||||
catch (SecurityException $e) {
|
||||
} catch (SecurityException $e) {
|
||||
// Users deletion is NOT allowed
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||
@@ -336,29 +318,30 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
protected function CheckIfProfileIsAllowed($iActionCode)
|
||||
{
|
||||
// When initializing or admin, we need to let everything pass trough
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only administrators can manage administrators
|
||||
$iOrigUserId = $this->GetOriginal('userid');
|
||||
if (!empty($iOrigUserId))
|
||||
{
|
||||
if (!empty($iOrigUserId)) {
|
||||
$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'));
|
||||
}
|
||||
}
|
||||
$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'));
|
||||
}
|
||||
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, DBObjectSet::FromObject($this)))
|
||||
{
|
||||
|
||||
$oSet = new \ormLinkSet(get_class($oUser), 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
|
||||
$oSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $this->GetKey(), 'reason' => 'CheckIfProfileIsAllowed']));
|
||||
|
||||
if (!UserRights::IsActionAllowed(get_class($this), $iActionCode, $oSet)) {
|
||||
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'));
|
||||
}
|
||||
}
|
||||
@@ -369,33 +352,33 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "addon/userrights,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||
"name_attcode" => ["userlogin", "allowed_org_name"],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"reconc_keys" => [],
|
||||
"db_table" => "priv_urp_userorg",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
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", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
|
||||
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 AttributeExternalField("userlogin", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
||||
|
||||
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", array("allowed_values"=>null, "extkey_attcode"=> 'allowed_org_id', "target_attcode"=>"name")));
|
||||
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 AttributeExternalField("allowed_org_name", ["allowed_values" => null, "extkey_attcode" => 'allowed_org_id', "target_attcode" => "name"]));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"reason", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reason", ["allowed_values" => null, "sql" => "reason", "default_value" => null, "is_null_allowed" => true, "depends_on" => []]));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('userid', 'allowed_org_id', 'reason')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('allowed_org_id', 'reason')); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', ['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
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||
MetaModel::Init_SetZListItems('standard_search', ['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
|
||||
}
|
||||
|
||||
protected function OnInsert()
|
||||
@@ -418,40 +401,37 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
*/
|
||||
protected function CheckIfOrgIsAllowed()
|
||||
{
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$oAddon = UserRights::GetModuleInstance();
|
||||
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
|
||||
if (count($aOrgs) > 0)
|
||||
{
|
||||
if (count($aOrgs) > 0) {
|
||||
$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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
static public $m_aActionCodes = array(
|
||||
public static $m_aActionCodes = [
|
||||
UR_ACTION_READ => 'r',
|
||||
UR_ACTION_MODIFY => 'w',
|
||||
UR_ACTION_DELETE => 'd',
|
||||
UR_ACTION_BULK_READ => 'br',
|
||||
UR_ACTION_BULK_MODIFY => 'bw',
|
||||
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
|
||||
*/
|
||||
/**
|
||||
* @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
|
||||
@@ -472,8 +452,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oContact = MetaModel::NewObject('Person');
|
||||
$oContact->Set('name', 'My last 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('email', 'my.email@foo.org');
|
||||
@@ -481,24 +460,19 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', $sAdminUser);
|
||||
$oUser->Set('password', $sAdminPwd);
|
||||
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0))
|
||||
{
|
||||
if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && ($iContactId != 0)) {
|
||||
$oUser->Set('contactid', $iContactId);
|
||||
}
|
||||
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
||||
|
||||
// Add this user to the very specific 'admin' profile
|
||||
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true /*all data*/);
|
||||
if (is_object($oAdminProfile))
|
||||
{
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $oAdminProfile->GetKey());
|
||||
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
||||
$oSet = DBObjectSet::FromObject($oUserProfile);
|
||||
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => ADMIN_PROFILE_NAME], true /*all data*/);
|
||||
if (is_object($oAdminProfile)) {
|
||||
$oSet = new \ormLinkSet(UserLocal::class, 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
|
||||
$oSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $oAdminProfile->GetKey(), 'reason' => 'CreateAdministrator']));
|
||||
$oUser->Set('profile_list', $oSet);
|
||||
}
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
@@ -509,11 +483,11 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
}
|
||||
|
||||
protected $m_aUserOrgs = array(); // userid -> array of orgid
|
||||
protected $m_aUserOrgs = []; // 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)
|
||||
protected $m_aObjectActionGrants = array();
|
||||
protected $m_aObjectActionGrants = [];
|
||||
|
||||
/**
|
||||
* Read and cache organizations allowed to the given user
|
||||
@@ -528,31 +502,25 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
public function GetUserOrgs($oUser, $sClass)
|
||||
{
|
||||
$iUser = $oUser->GetKey();
|
||||
if (!array_key_exists($iUser, $this->m_aUserOrgs))
|
||||
{
|
||||
$this->m_aUserOrgs[$iUser] = array();
|
||||
if (!array_key_exists($iUser, $this->m_aUserOrgs)) {
|
||||
$this->m_aUserOrgs[$iUser] = [];
|
||||
|
||||
$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';
|
||||
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), array(), array('userid' => $iUser));
|
||||
while ($aRow = $oUserOrgSet->FetchAssoc())
|
||||
{
|
||||
$oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData($sUserOrgQuery), [], ['userid' => $iUser]);
|
||||
while ($aRow = $oUserOrgSet->FetchAssoc()) {
|
||||
$oOrg = $aRow['Org'];
|
||||
$this->m_aUserOrgs[$iUser][] = $oOrg->GetKey();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSearch = new DBObjectSearch('URP_UserOrg');
|
||||
$oSearch->AllowAllData();
|
||||
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
|
||||
$oSearch->AddConditionExpression($oCondition);
|
||||
|
||||
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
|
||||
while ($oUserOrg = $oUserOrgSet->Fetch())
|
||||
{
|
||||
$oUserOrgSet = new DBObjectSet($oSearch, [], ['userid' => $iUser]);
|
||||
while ($oUserOrg = $oUserOrgSet->Fetch()) {
|
||||
$this->m_aUserOrgs[$iUser][] = $oUserOrg->Get('allowed_org_id');
|
||||
}
|
||||
}
|
||||
@@ -563,21 +531,20 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
public function ResetCache()
|
||||
{
|
||||
// Loaded by Load cache
|
||||
$this->m_aUserOrgs = array();
|
||||
$this->m_aUserOrgs = [];
|
||||
|
||||
// Cache
|
||||
$this->m_aObjectActionGrants = array();
|
||||
$this->m_aObjectActionGrants = [];
|
||||
$this->m_aAdministrators = null;
|
||||
$this->aUsersProfilesList = [];
|
||||
}
|
||||
|
||||
public function LoadCache()
|
||||
{
|
||||
static $bSharedObjectInitialized = false;
|
||||
if (!$bSharedObjectInitialized)
|
||||
{
|
||||
if (!$bSharedObjectInitialized) {
|
||||
$bSharedObjectInitialized = true;
|
||||
if (self::HasSharing())
|
||||
{
|
||||
if (self::HasSharing()) {
|
||||
SharedObject::InitSharedClassProperties();
|
||||
}
|
||||
}
|
||||
@@ -615,45 +582,40 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
*/
|
||||
public function ListProfiles($oUser)
|
||||
{
|
||||
$aRet = array();
|
||||
$aRet = [];
|
||||
$oSearch = new DBObjectSearch('URP_UserProfile');
|
||||
$oSearch->AllowAllData();
|
||||
$oSearch->NoContextParameters();
|
||||
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
|
||||
$oProfiles = new DBObjectSet($oSearch);
|
||||
while ($oUserProfile = $oProfiles->Fetch())
|
||||
{
|
||||
while ($oUserProfile = $oProfiles->Fetch()) {
|
||||
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
||||
{
|
||||
$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
|
||||
// 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)
|
||||
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
|
||||
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
|
||||
{
|
||||
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$oFilter = true;
|
||||
$aConditions = array();
|
||||
$aConditions = [];
|
||||
|
||||
// Determine if this class is part of a silo and build the filter for it
|
||||
$sAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||
if (!is_null($sAttCode))
|
||||
{
|
||||
if (!is_null($sAttCode)) {
|
||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||
if (count($aUserOrgs) > 0)
|
||||
{
|
||||
if (count($aUserOrgs) > 0) {
|
||||
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
|
||||
}
|
||||
// else: No org means 'any org'
|
||||
@@ -662,20 +624,15 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
|
||||
// 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.
|
||||
if ($this->AdministratorsAreHidden())
|
||||
{
|
||||
if ($sClass == 'URP_Profiles')
|
||||
{
|
||||
if ($this->AdministratorsAreHidden()) {
|
||||
if ($sClass == 'URP_Profiles') {
|
||||
$oExpression = new FieldExpression('id', $sClass);
|
||||
$oScalarExpr = new ScalarExpression(1);
|
||||
|
||||
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
|
||||
}
|
||||
else if (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User')))
|
||||
{
|
||||
} elseif (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User'))) {
|
||||
$aAdministrators = $this->GetAdministrators();
|
||||
if (count($aAdministrators) > 0)
|
||||
{
|
||||
if (count($aAdministrators) > 0) {
|
||||
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
|
||||
$oExpression = new FieldExpression($sAttCode, $sClass);
|
||||
$oListExpr = ListExpression::FromScalars($aAdministrators);
|
||||
@@ -685,17 +642,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
}
|
||||
|
||||
// Handling of the added conditions
|
||||
if (count($aConditions) > 0)
|
||||
{
|
||||
if($oFilter === true)
|
||||
{
|
||||
if (count($aConditions) > 0) {
|
||||
if ($oFilter === true) {
|
||||
// No 'silo' filter, let's build a clean one
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
}
|
||||
|
||||
// Add the conditions to the filter
|
||||
foreach($aConditions as $oCondition)
|
||||
{
|
||||
foreach ($aConditions as $oCondition) {
|
||||
$oFilter->AddConditionExpression($oCondition);
|
||||
}
|
||||
}
|
||||
@@ -710,10 +664,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
*/
|
||||
private function GetAdministrators()
|
||||
{
|
||||
if ($this->m_aAdministrators === null)
|
||||
{
|
||||
if ($this->m_aAdministrators === null) {
|
||||
// Find all administrators
|
||||
$this->m_aAdministrators = array();
|
||||
$this->m_aAdministrators = [];
|
||||
$oAdministratorsFilter = new DBObjectSearch('User');
|
||||
$oLnkFilter = new DBObjectSearch('URP_UserProfile');
|
||||
$oExpression = new FieldExpression('profileid', 'URP_UserProfile');
|
||||
@@ -723,9 +676,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
|
||||
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
|
||||
$oSet = new DBObjectSet($oAdministratorsFilter);
|
||||
$oSet->OptimizeColumnLoad(array('User' => array('login')));
|
||||
while($oUser = $oSet->Fetch())
|
||||
{
|
||||
$oSet->OptimizeColumnLoad(['User' => ['login']]);
|
||||
while ($oUser = $oSet->Fetch()) {
|
||||
$this->m_aAdministrators[] = $oUser->GetKey();
|
||||
}
|
||||
}
|
||||
@@ -741,7 +693,6 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
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
|
||||
public function GetProfileActionGrant($iProfile, $sClass, $sAction)
|
||||
{
|
||||
@@ -758,33 +709,29 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// load and cache permissions for the current user on the given class
|
||||
//
|
||||
$iUser = $oUser->GetKey();
|
||||
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])){
|
||||
if (isset($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];
|
||||
|
||||
$bStatus = null;
|
||||
// Cache user's profiles
|
||||
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
// Cache user's profiles
|
||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
|
||||
{
|
||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
||||
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
|
||||
if (!is_null($bGrant))
|
||||
{
|
||||
if ($bGrant)
|
||||
{
|
||||
if (is_null($bStatus))
|
||||
{
|
||||
if (!is_null($bGrant)) {
|
||||
if ($bGrant) {
|
||||
if (is_null($bStatus)) {
|
||||
$bStatus = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$bStatus = false;
|
||||
}
|
||||
}
|
||||
@@ -792,9 +739,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
|
||||
$iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO;
|
||||
|
||||
$aRes = array(
|
||||
$aRes = [
|
||||
'permission' => $iPermission,
|
||||
);
|
||||
];
|
||||
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
|
||||
return $aRes;
|
||||
}
|
||||
@@ -809,20 +756,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// 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
|
||||
|
||||
if ($iPermission != UR_ALLOWED_YES)
|
||||
{
|
||||
if ($iPermission != UR_ALLOWED_YES) {
|
||||
// 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
|
||||
}
|
||||
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
|
||||
}
|
||||
elseif ($oInstanceSet)
|
||||
{
|
||||
} elseif ($oInstanceSet) {
|
||||
// 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
|
||||
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
|
||||
@@ -886,8 +826,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// Note: this code is VERY close to the code of IsActionAllowed()
|
||||
$iUser = $oUser->GetKey();
|
||||
|
||||
// Cache user's profiles
|
||||
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
|
||||
// Cache user's profiles
|
||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
|
||||
@@ -895,20 +835,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// and acceptable to consider only the root class of the object set
|
||||
$bStatus = null;
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
|
||||
{
|
||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
||||
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
|
||||
if (!is_null($bGrant))
|
||||
{
|
||||
if ($bGrant)
|
||||
{
|
||||
if (is_null($bStatus))
|
||||
{
|
||||
if (!is_null($bGrant)) {
|
||||
if ($bGrant) {
|
||||
if (is_null($bStatus)) {
|
||||
$bStatus = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$bStatus = false;
|
||||
}
|
||||
}
|
||||
@@ -932,22 +866,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
$sAttCode = null;
|
||||
|
||||
$aCallSpec = array($sClass, 'MapContextParam');
|
||||
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization'))
|
||||
{
|
||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
||||
if (($sClass == 'Organization') || is_subclass_of($sClass, 'Organization')) {
|
||||
$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
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
||||
// Skip silently. The data model checker will tell you something about this...
|
||||
$sAttCode = null;
|
||||
}
|
||||
}
|
||||
elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
|
||||
{
|
||||
} elseif (MetaModel::IsValidAttCode($sClass, 'org_id')) {
|
||||
$sAttCode = 'org_id';
|
||||
}
|
||||
|
||||
@@ -960,14 +888,11 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
protected static function HasSharing()
|
||||
{
|
||||
static $bHasSharing;
|
||||
if (!isset($bHasSharing))
|
||||
{
|
||||
if (!isset($bHasSharing)) {
|
||||
$bHasSharing = class_exists('SharedObject');
|
||||
}
|
||||
return $bHasSharing;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UserRights::SelectModule('UserRightsProfile');
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
29
app.php
29
app.php
@@ -1,29 +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,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -48,8 +49,7 @@ class DBSearchHelper
|
||||
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
||||
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
// If filtering fails just ignore it
|
||||
}
|
||||
}
|
||||
@@ -57,4 +57,4 @@ class DBSearchHelper
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated 3.0.0 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
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*/
|
||||
|
||||
// cannot notify depreciation for now as this is still load in autoloader
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||
use Combodo\iTop\Application\WebPage\AjaxPage;
|
||||
|
||||
/**
|
||||
* Class ajax_page
|
||||
*
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to AjaxPage
|
||||
*/
|
||||
class ajax_page extends AjaxPage
|
||||
{
|
||||
function __construct($s_title)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead');
|
||||
parent::__construct($s_title);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Class ApplicationContext
|
||||
*
|
||||
@@ -47,16 +47,16 @@ interface iDBObjectURLMaker
|
||||
|
||||
/**
|
||||
* Direct end-users to the standard iTop application: UI.php
|
||||
*/
|
||||
*/
|
||||
class iTopStandardURLMaker implements iDBObjectURLMaker
|
||||
{
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function MakeObjectURL($sClass, $iId)
|
||||
{
|
||||
$sPage = DBObject::ComputeStandardUIPage($sClass);
|
||||
@@ -68,16 +68,16 @@ class iTopStandardURLMaker implements iDBObjectURLMaker
|
||||
|
||||
/**
|
||||
* Direct end-users to the standard Portal application
|
||||
*/
|
||||
*/
|
||||
class PortalURLMaker implements iDBObjectURLMaker
|
||||
{
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function MakeObjectURL($sClass, $iId)
|
||||
{
|
||||
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
@@ -86,7 +86,6 @@ class PortalURLMaker implements iDBObjectURLMaker
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to store and manipulate the parameters that make the application's context
|
||||
*
|
||||
@@ -99,99 +98,90 @@ class PortalURLMaker implements iDBObjectURLMaker
|
||||
*/
|
||||
class ApplicationContext
|
||||
{
|
||||
public static $m_sUrlMakerClass = null;
|
||||
protected static $m_aPluginProperties = null;
|
||||
protected static $aDefaultValues; // Cache shared among all instances
|
||||
public static $m_sUrlMakerClass = null;
|
||||
protected static $m_aPluginProperties = null;
|
||||
protected static $aDefaultValues; // Cache shared among all instances
|
||||
|
||||
protected $aNames;
|
||||
protected $aValues;
|
||||
|
||||
/**
|
||||
* ApplicationContext constructor.
|
||||
*
|
||||
* @param bool $bReadContext
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* ApplicationContext constructor.
|
||||
*
|
||||
* @param bool $bReadContext
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($bReadContext = true)
|
||||
{
|
||||
$this->aNames = array(
|
||||
'org_id', 'menu'
|
||||
);
|
||||
if ($bReadContext)
|
||||
{
|
||||
$this->ReadContext();
|
||||
$this->aNames = [
|
||||
'org_id', 'menu',
|
||||
];
|
||||
if ($bReadContext) {
|
||||
$this->ReadContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the context directly in the PHP parameters (either POST or GET)
|
||||
* return nothing
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Read the context directly in the PHP parameters (either POST or GET)
|
||||
* return nothing
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function ReadContext()
|
||||
{
|
||||
if (!isset(self::$aDefaultValues))
|
||||
{
|
||||
self::$aDefaultValues = array();
|
||||
$aContext = utils::ReadParam('c', array(), false, 'context_param');
|
||||
foreach($this->aNames as $sName)
|
||||
{
|
||||
if (!isset(self::$aDefaultValues)) {
|
||||
self::$aDefaultValues = [];
|
||||
$aContext = utils::ReadParam('c', [], false, 'context_param');
|
||||
foreach ($this->aNames as $sName) {
|
||||
$sValue = isset($aContext[$sName]) ? $aContext[$sName] : '';
|
||||
// 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;
|
||||
}
|
||||
// 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
|
||||
// fixed to this org unless there is only one organization in the system then
|
||||
// no filter is applied
|
||||
if ($sName == 'org_id')
|
||||
{
|
||||
if (MetaModel::IsValidClass('Organization'))
|
||||
{
|
||||
if ($sName == 'org_id') {
|
||||
if (MetaModel::IsValidClass('Organization')) {
|
||||
$oSearchFilter = new DBObjectSearch('Organization');
|
||||
$oSet = new CMDBObjectSet($oSearchFilter);
|
||||
$iCount = $oSet->CountWithLimit(2);
|
||||
if ($iCount > 1)
|
||||
{
|
||||
if ($iCount > 1) {
|
||||
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
||||
$oSet = new CMDBObjectSet($oSearchFilter);
|
||||
$iCount = $oSet->CountWithLimit(2);
|
||||
if ($iCount == 1)
|
||||
{
|
||||
if ($iCount == 1) {
|
||||
// Only one possible value for org_id, set it in the context
|
||||
$oOrg = $oSet->Fetch();
|
||||
self::$aDefaultValues[$sName] = $oOrg->GetKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->aValues = self::$aDefaultValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value for the given parameter
|
||||
*
|
||||
* @param string $sParamName Name of the parameter to read
|
||||
* @param string $defaultValue
|
||||
*
|
||||
* @return mixed The value for this parameter
|
||||
*/
|
||||
/**
|
||||
* Returns the current value for the given parameter
|
||||
*
|
||||
* @param string $sParamName Name of the parameter to read
|
||||
* @param string $defaultValue
|
||||
*
|
||||
* @return mixed The value for this parameter
|
||||
*/
|
||||
public function GetCurrentValue($sParamName, $defaultValue = '')
|
||||
{
|
||||
if (isset($this->aValues[$sParamName]))
|
||||
{
|
||||
if (isset($this->aValues[$sParamName])) {
|
||||
return $this->aValues[$sParamName];
|
||||
}
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -200,21 +190,20 @@ class ApplicationContext
|
||||
public function GetForLink(bool $bWithLeadingAmpersand = false)
|
||||
{
|
||||
// If there are no parameters, return an empty string
|
||||
if(empty($this->aValues)){
|
||||
if (empty($this->aValues)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Build the query string with ampersand separated parameters
|
||||
$aParams = array();
|
||||
foreach($this->aValues as $sName => $sValue)
|
||||
{
|
||||
$aParams = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aParams[] = "c[$sName]".'='.urlencode($sValue);
|
||||
}
|
||||
$sReturnValue = implode('&', $aParams);
|
||||
|
||||
// add the leading ampersand if requested
|
||||
if($bWithLeadingAmpersand){
|
||||
$sReturnValue = '&' . $sReturnValue;
|
||||
if ($bWithLeadingAmpersand) {
|
||||
$sReturnValue = '&'.$sReturnValue;
|
||||
}
|
||||
|
||||
return $sReturnValue;
|
||||
@@ -278,14 +267,13 @@ class ApplicationContext
|
||||
*/
|
||||
public function GetAsHash()
|
||||
{
|
||||
$aReturn = array();
|
||||
foreach($this->aValues as $sName => $sValue)
|
||||
{
|
||||
$aReturn = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aReturn["c[$sName]"] = $sValue;
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of the context parameters NAMEs
|
||||
* @return array The list of context parameters
|
||||
@@ -298,11 +286,10 @@ class ApplicationContext
|
||||
* Removes the specified parameter from the context, for example when the same parameter
|
||||
* is already a search parameter
|
||||
* @param string $sParamName Name of the parameter to remove
|
||||
*/
|
||||
*/
|
||||
public function Reset($sParamName)
|
||||
{
|
||||
if (isset($this->aValues[$sParamName]))
|
||||
{
|
||||
if (isset($this->aValues[$sParamName])) {
|
||||
unset($this->aValues[$sParamName]);
|
||||
}
|
||||
}
|
||||
@@ -318,27 +305,22 @@ class ApplicationContext
|
||||
public function InitObjectFromContext(DBObject &$oObj)
|
||||
{
|
||||
$sClass = get_class($oObj);
|
||||
foreach($this->GetNames() as $key)
|
||||
{
|
||||
$aCallSpec = array($sClass, 'MapContextParam');
|
||||
if (is_callable($aCallSpec))
|
||||
{
|
||||
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
|
||||
foreach ($this->GetNames() as $key) {
|
||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
||||
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);
|
||||
if ($oAttDef->IsWritable())
|
||||
{
|
||||
if ($oAttDef->IsWritable()) {
|
||||
$value = $this->GetCurrentValue($key, null);
|
||||
if (!is_null($value))
|
||||
{
|
||||
if (!is_null($value)) {
|
||||
$oObj->Set($sAttCode, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,14 +344,10 @@ class ApplicationContext
|
||||
*/
|
||||
public static function GetUrlMakerClass()
|
||||
{
|
||||
if (is_null(self::$m_sUrlMakerClass))
|
||||
{
|
||||
if (Session::IsSet('UrlMakerClass'))
|
||||
{
|
||||
if (is_null(self::$m_sUrlMakerClass)) {
|
||||
if (Session::IsSet('UrlMakerClass')) {
|
||||
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
self::$m_sUrlMakerClass = 'iTopStandardURLMaker';
|
||||
}
|
||||
}
|
||||
@@ -387,23 +365,23 @@ class ApplicationContext
|
||||
* @return string the name of the class
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
|
||||
if (is_null($sUrlMakerClass)) {
|
||||
$sUrlMakerClass = self::GetUrlMakerClass();
|
||||
}
|
||||
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey);
|
||||
if (utils::StrLen($sUrl) > 0) {
|
||||
if ($bWithNavigationContext) {
|
||||
return $sUrl.$oAppContext->GetForLink(true);
|
||||
} else {
|
||||
return $sUrl;
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
if (is_null($sUrlMakerClass)) {
|
||||
$sUrlMakerClass = self::GetUrlMakerClass();
|
||||
}
|
||||
$sUrl = call_user_func([$sUrlMakerClass, 'MakeObjectUrl'], $sObjClass, $sObjKey);
|
||||
if (utils::StrLen($sUrl) > 0) {
|
||||
if ($bWithNavigationContext) {
|
||||
return $sUrl.$oAppContext->GetForLink(true);
|
||||
} else {
|
||||
return $sUrl;
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,13 +390,10 @@ class ApplicationContext
|
||||
*/
|
||||
protected static function LoadPluginProperties()
|
||||
{
|
||||
if (Session::IsSet('PluginProperties'))
|
||||
{
|
||||
if (Session::IsSet('PluginProperties')) {
|
||||
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$m_aPluginProperties = array();
|
||||
} else {
|
||||
self::$m_aPluginProperties = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +406,9 @@ class ApplicationContext
|
||||
*/
|
||||
public static function SetPluginProperty($sPluginClass, $sProperty, $value)
|
||||
{
|
||||
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||
if (is_null(self::$m_aPluginProperties)) {
|
||||
self::LoadPluginProperties();
|
||||
}
|
||||
|
||||
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
|
||||
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
|
||||
@@ -444,15 +421,14 @@ class ApplicationContext
|
||||
*/
|
||||
public static function GetPluginProperties($sPluginClass)
|
||||
{
|
||||
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||
|
||||
if (array_key_exists($sPluginClass, self::$m_aPluginProperties))
|
||||
{
|
||||
return self::$m_aPluginProperties[$sPluginClass];
|
||||
if (is_null(self::$m_aPluginProperties)) {
|
||||
self::LoadPluginProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
|
||||
if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) {
|
||||
return self::$m_aPluginProperties[$sPluginClass];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Extend this class instead of implementing iApplicationUIExtension if you don't need to overload
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractApplicationUIExtension implements iApplicationUIExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function OnFormSubmit($oObject, $sFormPrefix = '')
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function OnFormCancel($sTempId)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function EnumUsedAttributes($oObject)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetIcon($oObject)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetHilightClass($oObject)
|
||||
{
|
||||
return HILIGHT_CLASS_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function EnumAllowedActions(DBObjectSet $oSet)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Extend this class instead of iPageUIBlockExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package UIBlockExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetBannerBlock()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetHeaderBlock()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetFooterBlock()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Extend this class instead of implementing iPreferencesExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package PreferencesExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractPreferencesExtension implements iPreferencesExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Inherit from this class to provide messages to be displayed in the "Welcome Popup"
|
||||
*
|
||||
* @api
|
||||
* @since 3.2.0
|
||||
*/
|
||||
abstract class AbstractWelcomePopupExtension implements iWelcomePopupExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetIconRelPath(): string
|
||||
{
|
||||
return \Combodo\iTop\Application\Branding::$aLogoPaths[\Combodo\iTop\Application\Branding::ENUM_LOGO_TYPE_MAIN_LOGO_COMPACT]['default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetMessages(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function AcknowledgeMessage(string $sMessageId): void
|
||||
{
|
||||
// No need to process the acknowledgment notice by default
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Base class for the various types of custom menus
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class ApplicationPopupMenuItem
|
||||
{
|
||||
/** @ignore */
|
||||
protected $sUID;
|
||||
/** @ignore */
|
||||
protected $sLabel;
|
||||
/** @ignore */
|
||||
protected $sTooltip;
|
||||
/** @ignore */
|
||||
protected $sIconClass;
|
||||
/** @ignore */
|
||||
protected $aCssClasses;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
||||
* @param string $sLabel The display label of the menu (must be localized)
|
||||
* @api
|
||||
*/
|
||||
public function __construct($sUID, $sLabel)
|
||||
{
|
||||
$this->sUID = $sUID;
|
||||
$this->sLabel = $sLabel;
|
||||
$this->sTooltip = '';
|
||||
$this->sIconClass = '';
|
||||
$this->aCssClasses = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UID
|
||||
*
|
||||
* @return string The unique identifier
|
||||
* @ignore
|
||||
*/
|
||||
public function GetUID()
|
||||
{
|
||||
return $this->sUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label
|
||||
*
|
||||
* @return string The label
|
||||
* @ignore
|
||||
*/
|
||||
public function GetLabel()
|
||||
{
|
||||
return $this->sLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CSS classes
|
||||
*
|
||||
* @return array
|
||||
* @ignore
|
||||
*/
|
||||
public function GetCssClasses()
|
||||
{
|
||||
return $this->aCssClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aCssClasses
|
||||
* @api
|
||||
*/
|
||||
public function SetCssClasses($aCssClasses)
|
||||
{
|
||||
$this->aCssClasses = $aCssClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a CSS class to the CSS classes that will be put on the menu item
|
||||
*
|
||||
* @param $sCssClass
|
||||
* @api
|
||||
*/
|
||||
public function AddCssClass($sCssClass)
|
||||
{
|
||||
$this->aCssClasses[] = $sCssClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sTooltip
|
||||
*
|
||||
* @api
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function SetTooltip($sTooltip)
|
||||
{
|
||||
$this->sTooltip = $sTooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetTooltip()
|
||||
{
|
||||
return $this->sTooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sIconClass
|
||||
*
|
||||
* @api
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function SetIconClass($sIconClass)
|
||||
{
|
||||
$this->sIconClass = $sIconClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetIconClass()
|
||||
{
|
||||
return $this->sIconClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the components to create a popup menu item in HTML
|
||||
*
|
||||
* @return array A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
|
||||
* @ignore
|
||||
*/
|
||||
abstract public function GetMenuItem();
|
||||
|
||||
/** @ignore */
|
||||
public function GetLinkedScripts()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
12
application/applicationextension/backoffice/JSButtonItem.php
Normal file
12
application/applicationextension/backoffice/JSButtonItem.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for adding an item as a button that runs some JS code
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class JSButtonItem extends JSPopupMenuItem
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for adding an item into a popup menu that triggers some Javascript code
|
||||
*
|
||||
* Note: This works only in the backoffice, {@see \JSButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||
{
|
||||
/** @ignore */
|
||||
protected $sJsCode;
|
||||
/** @ignore */
|
||||
protected $sUrl;
|
||||
/** @ignore */
|
||||
protected $aIncludeJSFiles;
|
||||
|
||||
/**
|
||||
* Class for adding an item that triggers some Javascript code
|
||||
*
|
||||
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
||||
* @param string $sLabel The display label of the menu (must be localized)
|
||||
* @param string $sJSCode In case the menu consists in executing some havascript code inside the page, pass it here. If supplied $sURL
|
||||
* ans $sTarget will be ignored
|
||||
* @param array $aIncludeJSFiles An array of file URLs to be included (once) to provide some JS libraries for the page.
|
||||
* @api
|
||||
*/
|
||||
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = [])
|
||||
{
|
||||
parent::__construct($sUID, $sLabel);
|
||||
$this->sJsCode = $sJSCode;
|
||||
$this->sUrl = '#';
|
||||
$this->aIncludeJSFiles = $aIncludeJSFiles;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetMenuItem()
|
||||
{
|
||||
// Note: the semicolumn is a must here!
|
||||
return [
|
||||
'label' => $this->GetLabel(),
|
||||
'onclick' => $this->GetJsCode().'; return false;',
|
||||
'url' => $this->GetUrl(),
|
||||
'css_classes' => $this->GetCssClasses(),
|
||||
'icon_class' => $this->sIconClass,
|
||||
'tooltip' => $this->sTooltip,
|
||||
];
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetLinkedScripts()
|
||||
{
|
||||
return $this->aIncludeJSFiles;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetJsCode()
|
||||
{
|
||||
return $this->sJsCode;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetUrl()
|
||||
{
|
||||
return $this->sUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for adding a separator (horizontal line, not selectable) the output
|
||||
* will automatically reduce several consecutive separators to just one
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
|
||||
{
|
||||
public static $idx = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('_separator_'.(self::$idx++), '');
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetMenuItem()
|
||||
{
|
||||
return ['label' => '<hr class="menu-separator">', 'url' => '', 'css_classes' => $this->aCssClasses];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for adding an item as a button that browses to the given URL
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class URLButtonItem extends URLPopupMenuItem
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for adding an item into a popup menu that browses to the given URL
|
||||
*
|
||||
* Note: This works only in the backoffice, {@see \URLButtonItem} for the end-user portal
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||
{
|
||||
/** @ignore */
|
||||
protected $sUrl;
|
||||
/** @ignore */
|
||||
protected $sTarget;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
||||
* @param string $sLabel The display label of the menu (must be localized)
|
||||
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
|
||||
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
|
||||
* @api
|
||||
*/
|
||||
public function __construct($sUID, $sLabel, $sUrl, $sTarget = '_top')
|
||||
{
|
||||
parent::__construct($sUID, $sLabel);
|
||||
$this->sUrl = $sUrl;
|
||||
$this->sTarget = $sTarget;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetMenuItem()
|
||||
{
|
||||
return ['label' => $this->GetLabel(),
|
||||
'url' => $this->GetUrl(),
|
||||
'target' => $this->GetTarget(),
|
||||
'css_classes' => $this->aCssClasses,
|
||||
'icon_class' => $this->sIconClass,
|
||||
'tooltip' => $this->sTooltip,
|
||||
];
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetUrl()
|
||||
{
|
||||
return $this->sUrl;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
public function GetTarget()
|
||||
{
|
||||
return $this->sTarget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to change the behavior of the GUI for some objects.
|
||||
*
|
||||
* All methods are invoked by iTop for a given object. There are basically two usages:
|
||||
*
|
||||
* 1) To tweak the form of an object, you will have to implement a specific behavior within:
|
||||
*
|
||||
* * OnDisplayProperties (bEditMode = true)
|
||||
* * OnFormSubmit
|
||||
* * OnFormCancel
|
||||
*
|
||||
* 2) To tune the display of the object details, you can use:
|
||||
*
|
||||
* * OnDisplayProperties
|
||||
* * OnDisplayRelations
|
||||
* * GetIcon
|
||||
* * GetHilightClass
|
||||
*
|
||||
* Please note that some of the APIs can be called several times for a single page displayed.
|
||||
* Therefore it is not recommended to perform too many operations, such as querying the database.
|
||||
* A recommended pattern is to cache data by the mean of static members.
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
*/
|
||||
interface iApplicationUIExtension
|
||||
{
|
||||
/**
|
||||
* Invoked when an object is being displayed (wiew or edit)
|
||||
*
|
||||
* The method is called right after the main tab has been displayed.
|
||||
* You can add output to the page, either to change the display, or to add a form input
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* if ($bEditMode)
|
||||
* {
|
||||
* $oPage->p('Age of the captain: <input type="text" name="captain_age"/>');
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* $oPage->p('Age of the captain: '.$iCaptainAge);
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @api
|
||||
*
|
||||
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
|
||||
* @param boolean $bEditMode True if the edition form is being displayed
|
||||
*
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function OnDisplayProperties($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
|
||||
|
||||
/**
|
||||
* Invoked when an object is being displayed (wiew or edit)
|
||||
*
|
||||
* The method is called rigth after all the tabs have been displayed
|
||||
*
|
||||
* @api
|
||||
*
|
||||
*@param \Combodo\iTop\Application\WebPage\WebPage $oPage The output context
|
||||
* @param boolean $bEditMode True if the edition form is being displayed
|
||||
*
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function OnDisplayRelations($oObject, \Combodo\iTop\Application\WebPage\WebPage $oPage, $bEditMode = false);
|
||||
|
||||
/**
|
||||
* Invoked when the end-user clicks on Modify from the object edition form
|
||||
*
|
||||
* The method is called after the changes from the standard form have been
|
||||
* taken into account, and before saving the changes into the database.
|
||||
*
|
||||
* @param DBObject $oObject The object being edited
|
||||
* @param string $sFormPrefix Prefix given to the HTML form inputs
|
||||
*
|
||||
* @return void
|
||||
* @api
|
||||
*/
|
||||
public function OnFormSubmit($oObject, $sFormPrefix = '');
|
||||
|
||||
/**
|
||||
* Invoked when the end-user clicks on Cancel from the object edition form
|
||||
*
|
||||
* Implement here any cleanup. This is necessary when you have injected some
|
||||
* javascript into the edition form, and if that code requires to store temporary data
|
||||
* (this is the case when a file must be uploaded).
|
||||
*
|
||||
* @param string $sTempId Unique temporary identifier made of session_id and transaction_id. It identifies the object in a unique way.
|
||||
*
|
||||
* @return void
|
||||
* @api
|
||||
*/
|
||||
public function OnFormCancel($sTempId);
|
||||
|
||||
/**
|
||||
* Not yet called by the framework!
|
||||
*
|
||||
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
|
||||
*
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return string[] desc
|
||||
* @api
|
||||
*/
|
||||
public function EnumUsedAttributes($oObject); // Not yet implemented
|
||||
|
||||
/**
|
||||
* Not yet called by the framework!
|
||||
*
|
||||
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
|
||||
*
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return string Path of the icon, relative to the modules directory.
|
||||
* @api
|
||||
*/
|
||||
public function GetIcon($oObject); // Not yet implemented
|
||||
|
||||
/**
|
||||
* Invoked when the object is displayed alone or within a list
|
||||
*
|
||||
* Returns a value influencing the appearance of the object depending on its
|
||||
* state.
|
||||
*
|
||||
* Possible values are:
|
||||
*
|
||||
* * HILIGHT_CLASS_CRITICAL
|
||||
* * HILIGHT_CLASS_WARNING
|
||||
* * HILIGHT_CLASS_OK
|
||||
* * HILIGHT_CLASS_NONE
|
||||
*
|
||||
* @param DBObject $oObject The object being displayed
|
||||
*
|
||||
* @return integer The value representing the mood of the object
|
||||
* @api
|
||||
*/
|
||||
public function GetHilightClass($oObject);
|
||||
|
||||
/**
|
||||
* Called when building the Actions menu for a single object or a list of objects
|
||||
*
|
||||
* Use this to add items to the Actions menu. You will have to specify a label and an URL.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $oObject = $oSet->fetch();
|
||||
* if ($oObject instanceof Sheep)
|
||||
* {
|
||||
* return array('View in my app' => 'http://myserver/view_sheeps?id='.$oObject->Get('name'));
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* return array();
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* See also iPopupMenuExtension for greater flexibility
|
||||
*
|
||||
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
|
||||
*
|
||||
* @return array
|
||||
* @api
|
||||
*/
|
||||
public function EnumAllowedActions(DBObjectSet $oSet);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add Dict entries
|
||||
*
|
||||
* @see \iTopWebPage::$a_dict_entries
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeDictEntriesExtension
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
* @see \iTopWebPage::a_dict_entries
|
||||
* @api
|
||||
*/
|
||||
public function GetDictEntries(): array;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add Dict entries prefixes
|
||||
*
|
||||
* @see \iTopWebPage::$a_dict_entries_prefixes
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeDictEntriesPrefixesExtension
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
* @see \iTopWebPage::a_dict_entries_prefixes
|
||||
* @api
|
||||
*/
|
||||
public function GetDictEntriesPrefixes(): array;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add inline script (JS) to the backoffice pages' head.
|
||||
* Will be executed first, BEFORE the DOM interpretation.
|
||||
*
|
||||
* @see \iTopWebPage::$a_early_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeEarlyScriptExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_early_scripts
|
||||
* @api
|
||||
*/
|
||||
public function GetEarlyScript(): string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed right when the DOM is ready.
|
||||
*
|
||||
* @see \iTopWebPage::$a_init_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeInitScriptExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_init_scripts
|
||||
* @api
|
||||
*/
|
||||
public function GetInitScript(): string;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add script (JS) files to the backoffice pages
|
||||
*
|
||||
* @see \iTopWebPage::$a_linked_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeLinkedScriptsExtension
|
||||
{
|
||||
/**
|
||||
* Each script will be included using this property
|
||||
* @return array An array of absolute URLs to the files to include
|
||||
* @see \iTopWebPage::$a_linked_scripts
|
||||
* @api
|
||||
*/
|
||||
public function GetLinkedScriptsAbsUrls(): array;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add stylesheets (CSS) to the backoffice pages
|
||||
*
|
||||
* @see \iTopWebPage::$a_linked_stylesheets
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeLinkedStylesheetsExtension
|
||||
{
|
||||
/**
|
||||
* @return array An array of absolute URLs to the files to include
|
||||
* @see \iTopWebPage::$a_linked_stylesheets
|
||||
* @api
|
||||
*/
|
||||
public function GetLinkedStylesheetsAbsUrls(): array;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed slightly AFTER the DOM is ready (just after the init. scripts).
|
||||
*
|
||||
* @see \iTopWebPage::$a_ready_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeReadyScriptExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_ready_scripts
|
||||
* @api
|
||||
*/
|
||||
public function GetReadyScript(): string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add sass file (SCSS) to the backoffice pages.
|
||||
* example: return "css/setup.scss"
|
||||
*
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.3.0
|
||||
*/
|
||||
interface iBackofficeSassExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_styles
|
||||
* @api
|
||||
*/
|
||||
public function GetSass(): string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add inline script (JS) to the backoffice pages that will be executed immediately, without waiting for the DOM to be ready.
|
||||
*
|
||||
* @see \iTopWebPage::$a_scripts
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeScriptExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_scripts
|
||||
* @api
|
||||
*/
|
||||
public function GetScript(): string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add inline style (CSS) to the backoffice pages' head.
|
||||
*
|
||||
* @see \iTopWebPage::$a_styles
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iBackofficeStyleExtension
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
* @see \iTopWebPage::$a_styles
|
||||
* @api
|
||||
*/
|
||||
public function GetStyle(): string;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to register a new field renderer mapping to either:
|
||||
* - Add the rendering of a new attribute type
|
||||
* - Overload the default rendering of an attribute type
|
||||
*
|
||||
* @since 3.1.0 N°6041
|
||||
*
|
||||
* @experimental Form / Field / Renderer should be used in more places in next iTop releases, which may introduce major API changes
|
||||
*/
|
||||
interface iFieldRendererMappingsExtension
|
||||
{
|
||||
/**
|
||||
* @return array {
|
||||
* array: {
|
||||
* field: string,
|
||||
* form_renderer: string,
|
||||
* field_renderer: string
|
||||
* }
|
||||
* } List of field renderer mapping: FQCN field class, FQCN Form Renderer class, FQCN Field Renderer class
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
|
||||
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Console\ConsoleFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
|
||||
* ['field' => 'FQCN\FieldA', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererA'],
|
||||
* ['field' => 'FQCN\FieldB', 'form_renderer' => 'Combodo\iTop\Renderer\Bootstrap\BsFormRenderer', 'field_renderer' => 'FQCN\FieldRendererB'],
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
public static function RegisterSupportedFields(): array;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add content to any iTopWebPage
|
||||
*
|
||||
* There are 3 places where content can be added:
|
||||
*
|
||||
* * The north pane: (normaly empty/hidden) at the top of the page, spanning the whole
|
||||
* width of the page
|
||||
* * The south pane: (normaly empty/hidden) at the bottom of the page, spanning the whole
|
||||
* width of the page
|
||||
* * The admin banner (two tones gray background) at the left of the global search.
|
||||
* Limited space, use it for short messages
|
||||
*
|
||||
* Each of the methods of this interface is supposed to return the HTML to be inserted at
|
||||
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
|
||||
*
|
||||
* @api
|
||||
* @package BackofficeUIExtensibilityAPI
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface iPageUIBlockExtension
|
||||
{
|
||||
/**
|
||||
* Add content to the "admin banner"
|
||||
*
|
||||
* @api
|
||||
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
|
||||
*/
|
||||
public function GetBannerBlock();
|
||||
|
||||
/**
|
||||
* Add content to the header of the page
|
||||
*
|
||||
* @api
|
||||
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
|
||||
*/
|
||||
public function GetHeaderBlock();
|
||||
|
||||
/**
|
||||
* Add content to the footer of the page
|
||||
*
|
||||
* @api
|
||||
* @return \Combodo\iTop\Application\UI\Base\iUIBlock|null The Block to add into the page
|
||||
*/
|
||||
public function GetFooterBlock();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* New extension to add menu items in the "popup" menus inside iTop. Provides a greater flexibility than
|
||||
* iApplicationUIExtension::EnumAllowedActions.
|
||||
*
|
||||
* To add some menus into iTop, declare a class that implements this interface, it will be called automatically
|
||||
* by the application, as long as the class definition is included somewhere in the code
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.0
|
||||
*/
|
||||
interface iPopupMenuExtension
|
||||
{
|
||||
/**
|
||||
* Insert an item into the Actions menu of a list
|
||||
*
|
||||
* $param is a DBObjectSet containing the list of objects
|
||||
* @api
|
||||
*/
|
||||
public const MENU_OBJLIST_ACTIONS = 1;
|
||||
/**
|
||||
* Insert an item into the Toolkit menu of a list
|
||||
*
|
||||
* $param is a DBObjectSet containing the list of objects
|
||||
* @api
|
||||
*/
|
||||
public const MENU_OBJLIST_TOOLKIT = 2;
|
||||
/**
|
||||
* Insert an item into the Actions menu on an object details page
|
||||
*
|
||||
* $param is a DBObject instance: the object currently displayed
|
||||
* @api
|
||||
*/
|
||||
public const MENU_OBJDETAILS_ACTIONS = 3;
|
||||
/**
|
||||
* Insert an item into the Dashboard menu
|
||||
*
|
||||
* The dashboad menu is shown on the top right corner when a dashboard
|
||||
* is being displayed.
|
||||
*
|
||||
* $param is a Dashboard instance: the dashboard currently displayed
|
||||
* @api
|
||||
*/
|
||||
public const MENU_DASHBOARD_ACTIONS = 4;
|
||||
/**
|
||||
* Insert an item into the User menu (upper right corner)
|
||||
*
|
||||
* $param is null
|
||||
* @api
|
||||
*/
|
||||
public const MENU_USER_ACTIONS = 5;
|
||||
/**
|
||||
* Insert an item into the Action menu on an object item in an objects list in the portal
|
||||
*
|
||||
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object on
|
||||
* the current line)
|
||||
* @api
|
||||
*/
|
||||
public const PORTAL_OBJLISTITEM_ACTIONS = 7;
|
||||
/**
|
||||
* Insert an item into the Action menu on an object details page in the portal
|
||||
*
|
||||
* $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object
|
||||
* currently displayed)
|
||||
* @api
|
||||
*/
|
||||
public const PORTAL_OBJDETAILS_ACTIONS = 8;
|
||||
|
||||
/**
|
||||
* Insert an item into the Actions menu of a list in the portal
|
||||
* Note: This is not implemented yet !
|
||||
*
|
||||
* $param is an array('portal_id' => $sPortalId, 'object_set' => $oSet) containing DBObjectSet containing the list of objects
|
||||
*
|
||||
* @todo
|
||||
*/
|
||||
public const PORTAL_OBJLIST_ACTIONS = 6;
|
||||
/**
|
||||
* Insert an item into the user menu of the portal
|
||||
* Note: This is not implemented yet !
|
||||
*
|
||||
* $param is the portal id
|
||||
*
|
||||
* @todo
|
||||
*/
|
||||
public const PORTAL_USER_ACTIONS = 9;
|
||||
/**
|
||||
* Insert an item into the navigation menu of the portal
|
||||
* Note: This is not implemented yet !
|
||||
*
|
||||
* $param is the portal id
|
||||
*
|
||||
* @todo
|
||||
*/
|
||||
public const PORTAL_MENU_ACTIONS = 10;
|
||||
|
||||
/**
|
||||
* Get the list of items to be added to a menu.
|
||||
*
|
||||
* This method is called by the framework for each menu.
|
||||
* The items will be inserted in the menu in the order of the returned array.
|
||||
*
|
||||
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
|
||||
* @param mixed $param Depends on $iMenuId, see the constants defined above
|
||||
*
|
||||
* @return object[] An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
|
||||
* @api
|
||||
*/
|
||||
public static function EnumItems($iMenuId, $param);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package PreferencesExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iPreferencesExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
*
|
||||
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
|
||||
*
|
||||
*/
|
||||
public function DisplayPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage);
|
||||
|
||||
/**
|
||||
* @api
|
||||
*
|
||||
* @param string $sOperation
|
||||
*
|
||||
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
|
||||
*
|
||||
* @return bool true if the operation has been used
|
||||
*/
|
||||
public function ApplyPreferences(\Combodo\iTop\Application\WebPage\WebPage $oPage, $sOperation);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Interface to provide messages to be displayed in the "Welcome Popup"
|
||||
*
|
||||
* @api
|
||||
* @since 3.2.0
|
||||
*/
|
||||
interface iWelcomePopupExtension
|
||||
{
|
||||
// Importance for ordering messages
|
||||
// Just two levels since less important messages have nothing to do in the welcome popup
|
||||
public const ENUM_IMPORTANCE_CRITICAL = 0;
|
||||
public const ENUM_IMPORTANCE_HIGH = 1;
|
||||
public const DEFAULT_IMPORTANCE = self::ENUM_IMPORTANCE_HIGH;
|
||||
|
||||
/**
|
||||
* Overload this method if you need to display an icon representing the provider (eg. your own company logo, module icon, ...)
|
||||
*
|
||||
* @return string Relative path (from app. root) of the icon representing the provider
|
||||
* @api
|
||||
*/
|
||||
public function GetIconRelPath(): string;
|
||||
|
||||
/**
|
||||
* @return \Combodo\iTop\Application\WelcomePopup\Message[]
|
||||
* @api
|
||||
*/
|
||||
public function GetMessages(): array;
|
||||
|
||||
/**
|
||||
* Overload this method if the provider needs to do some additional processing after the message ($sMessageId) has been acknowledged by the current user
|
||||
*
|
||||
* @param string $sMessageId
|
||||
* @api
|
||||
*/
|
||||
public function AcknowledgeMessage(string $sMessageId): void;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add files to the backup
|
||||
*
|
||||
* @api
|
||||
* @since 3.2.0
|
||||
*/
|
||||
interface iBackupExtraFilesExtension
|
||||
{
|
||||
/**
|
||||
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
|
||||
* @api
|
||||
*/
|
||||
public function GetExtraFilesRelPaths(): array;
|
||||
}
|
||||
25
application/applicationextension/iKPILoggerExtension.php
Normal file
25
application/applicationextension/iKPILoggerExtension.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* KPI logging extensibility point
|
||||
*
|
||||
* KPI Logger extension
|
||||
*/
|
||||
interface iKPILoggerExtension
|
||||
{
|
||||
/**
|
||||
* Init the statistics collected
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function InitStats();
|
||||
|
||||
/**
|
||||
* Add a new KPI to the stats
|
||||
*
|
||||
* @param \Combodo\iTop\Core\Kpi\KpiLogData $oKpiLogData
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function LogOperation($oKpiLogData);
|
||||
}
|
||||
16
application/applicationextension/iModuleExtension.php
Normal file
16
application/applicationextension/iModuleExtension.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helpers for modules extensibility, with discover performed by the MetaModel.
|
||||
*
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
*/
|
||||
interface iModuleExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function __construct();
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Login finite state machine
|
||||
*
|
||||
* Execute the action corresponding to the current login state.
|
||||
*
|
||||
* * If a page is displayed, the action must exit at this point
|
||||
* * if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
|
||||
* * if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
|
||||
* * if LoginWebPage::LOGIN_FSM_CONTINUE is returned then the FSM will proceed to next plugin or to next state
|
||||
*
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
abstract public function ListSupportedLoginModes();
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function LoginAction($sLoginState, &$iErrorCode)
|
||||
{
|
||||
switch ($sLoginState) {
|
||||
case LoginWebPage::LOGIN_STATE_START:
|
||||
return $this->OnStart($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
|
||||
return $this->OnModeDetection($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
|
||||
return $this->OnReadCredentials($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
|
||||
return $this->OnCheckCredentials($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK:
|
||||
return $this->OnCredentialsOK($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_USER_OK:
|
||||
return $this->OnUsersOK($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_CONNECTED:
|
||||
return $this->OnConnected($iErrorCode);
|
||||
|
||||
case LoginWebPage::LOGIN_STATE_ERROR:
|
||||
return $this->OnError($iErrorCode);
|
||||
}
|
||||
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnStart(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect login mode explicitly without respecting configured order (legacy mode)
|
||||
* In most case do nothing here
|
||||
*
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the credentials either if login mode is empty or set to yours.
|
||||
* This step can be called multiple times by the FSM:
|
||||
* for example:
|
||||
* 1 - display login form
|
||||
* 2 - read the values posted by the user (store that in session)
|
||||
*
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the validity of the data from the session
|
||||
* Automatic user provisioning can be done here
|
||||
*
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnUsersOK(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
}
|
||||
17
application/applicationextension/login/iLoginExtension.php
Normal file
17
application/applicationextension/login/iLoginExtension.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginExtension
|
||||
{
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @return array of supported login modes
|
||||
* @api
|
||||
*/
|
||||
public function ListSupportedLoginModes();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginFSMExtension extends iLoginExtension
|
||||
{
|
||||
/**
|
||||
* Execute action for this login state
|
||||
* If a page is displayed, the action must exit at this point
|
||||
* if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
|
||||
* if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
|
||||
* if LoginWebPage::LOGIN_FSM_CONTINUE is returned then the FSM will proceed to next plugin or state
|
||||
*
|
||||
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
|
||||
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
|
||||
*
|
||||
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_CONTINUE
|
||||
* @api
|
||||
*/
|
||||
public function LoginAction($sLoginState, &$iErrorCode);
|
||||
}
|
||||
17
application/applicationextension/login/iLoginUIExtension.php
Normal file
17
application/applicationextension/login/iLoginUIExtension.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Login page extensibility
|
||||
*
|
||||
* @api
|
||||
* @package UIExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLoginUIExtension extends iLoginExtension
|
||||
{
|
||||
/**
|
||||
* @return LoginTwigContext
|
||||
* @api
|
||||
*/
|
||||
public function GetTwigContext();
|
||||
}
|
||||
15
application/applicationextension/login/iLogoutExtension.php
Normal file
15
application/applicationextension/login/iLogoutExtension.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @package LoginExtensibilityAPI
|
||||
* @since 2.7.0
|
||||
*/
|
||||
interface iLogoutExtension extends iLoginExtension
|
||||
{
|
||||
/**
|
||||
* Execute all actions to log out properly
|
||||
* @api
|
||||
*/
|
||||
public function LogoutAction();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package PortalExtensibilityAPI
|
||||
* @since 2.4.0
|
||||
*/
|
||||
abstract class AbstractPortalUIExtension implements iPortalUIExtension
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add content to any enhanced portal page
|
||||
*
|
||||
* @api
|
||||
* @package PortalExtensibilityAPI
|
||||
*
|
||||
* @since 2.4.0 interface creation
|
||||
* @since 2.7.0 change method signatures due to Silex to Symfony migration
|
||||
*/
|
||||
interface iPortalUIExtension
|
||||
{
|
||||
public const ENUM_PORTAL_EXT_UI_BODY = 'Body';
|
||||
public const ENUM_PORTAL_EXT_UI_NAVIGATION_MENU = 'NavigationMenu';
|
||||
public const ENUM_PORTAL_EXT_UI_MAIN_CONTENT = 'MainContent';
|
||||
|
||||
/**
|
||||
* Returns an array of CSS file urls
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return array
|
||||
* @api
|
||||
*/
|
||||
public function GetCSSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns inline (raw) CSS
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
* @api
|
||||
*/
|
||||
public function GetCSSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns an array of JS file urls
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return array
|
||||
* @api
|
||||
*/
|
||||
public function GetJSFiles(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns raw JS code
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
* @api
|
||||
*/
|
||||
public function GetJSInline(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the <body> tag
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
* @api
|
||||
*/
|
||||
public function GetBodyHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the #main-wrapper element
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
* @api
|
||||
*/
|
||||
public function GetMainContentHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
|
||||
/**
|
||||
* Returns raw HTML code to put at the end of the #topbar and #sidebar elements
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\Container $oContainer
|
||||
*
|
||||
* @return string
|
||||
* @api
|
||||
*/
|
||||
public function GetNavigationMenuHTML(\Symfony\Component\DependencyInjection\Container $oContainer);
|
||||
}
|
||||
102
application/applicationextension/rest/RestResult.php
Normal file
102
application/applicationextension/rest/RestResult.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Minimal REST response structure. Derive this structure to add response data and error codes.
|
||||
*
|
||||
* @api
|
||||
* @package RESTAPI
|
||||
* @since 2.0.1
|
||||
*/
|
||||
class RestResult
|
||||
{
|
||||
/**
|
||||
* Result: no issue has been encountered
|
||||
* @api
|
||||
*/
|
||||
public const OK = 0;
|
||||
/**
|
||||
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
|
||||
* @api
|
||||
*/
|
||||
public const UNAUTHORIZED = 1;
|
||||
/**
|
||||
* Result: the parameter 'version' is missing
|
||||
* @api
|
||||
*/
|
||||
public const MISSING_VERSION = 2;
|
||||
/**
|
||||
* Result: the parameter 'json_data' is missing
|
||||
* @api
|
||||
*/
|
||||
public const MISSING_JSON = 3;
|
||||
/**
|
||||
* Result: the input structure is not a valid JSON string
|
||||
* @api
|
||||
*/
|
||||
public const INVALID_JSON = 4;
|
||||
/**
|
||||
* Result: the parameter 'auth_user' is missing, authentication aborted
|
||||
* @api
|
||||
*/
|
||||
public const MISSING_AUTH_USER = 5;
|
||||
/**
|
||||
* Result: the parameter 'auth_pwd' is missing, authentication aborted
|
||||
* @api
|
||||
*/
|
||||
public const MISSING_AUTH_PWD = 6;
|
||||
/**
|
||||
* Result: no operation is available for the specified version
|
||||
* @api
|
||||
*/
|
||||
public const UNSUPPORTED_VERSION = 10;
|
||||
/**
|
||||
* Result: the requested operation is not valid for the specified version
|
||||
* @api
|
||||
*/
|
||||
public const UNKNOWN_OPERATION = 11;
|
||||
/**
|
||||
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
|
||||
* @api
|
||||
*/
|
||||
public const UNSAFE = 12;
|
||||
/**
|
||||
* Result: the request page number is not valid. It must be an integer greater than 0
|
||||
* @api
|
||||
*/
|
||||
public const INVALID_PAGE = 13;
|
||||
/**
|
||||
* Result: the operation could not be performed, see the message for troubleshooting
|
||||
* @api
|
||||
*/
|
||||
public const INTERNAL_ERROR = 100;
|
||||
|
||||
/**
|
||||
* Default constructor - ok!
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->code = RestResult::OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result code
|
||||
* @var int
|
||||
* @api
|
||||
*/
|
||||
public $code;
|
||||
/**
|
||||
* Result message
|
||||
* @var string
|
||||
* @api
|
||||
*/
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* Sanitize the content of this result to hide sensitive information
|
||||
*/
|
||||
public function SanitizeContent()
|
||||
{
|
||||
// The default implementation does nothing
|
||||
}
|
||||
}
|
||||
364
application/applicationextension/rest/RestUtils.php
Normal file
364
application/applicationextension/rest/RestUtils.php
Normal file
@@ -0,0 +1,364 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helpers for implementing REST services
|
||||
*
|
||||
* @api
|
||||
* @package RESTAPI
|
||||
*/
|
||||
class RestUtils
|
||||
{
|
||||
/**
|
||||
* Registering tracking information. Any further object modification be associated with the given comment, when the modification gets
|
||||
* recorded into the DB
|
||||
*
|
||||
* @param StdClass $oData Structured input data. Must contain 'comment'.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @api
|
||||
*
|
||||
*/
|
||||
public static function InitTrackingComment($oData)
|
||||
{
|
||||
$sComment = self::GetMandatoryParam($oData, 'comment');
|
||||
CMDBObject::SetTrackInfo($sComment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a mandatory parameter from from a Rest/Json structure.
|
||||
*
|
||||
* @param string $sParamName Name of the parameter to fetch from the input data
|
||||
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
|
||||
*
|
||||
* @return mixed parameter value if present
|
||||
* @throws Exception If the parameter is missing
|
||||
* @api
|
||||
*/
|
||||
public static function GetMandatoryParam($oData, $sParamName)
|
||||
{
|
||||
if (isset($oData->$sParamName)) {
|
||||
return $oData->$sParamName;
|
||||
} else {
|
||||
throw new Exception("Missing parameter '$sParamName'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an optional parameter from a Rest/Json structure.
|
||||
*
|
||||
* @param string $sParamName Name of the parameter to fetch from the input data
|
||||
* @param mixed $default Default value if the parameter is not found in the input data
|
||||
*
|
||||
* @param StdClass $oData Structured input data.
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
* @api
|
||||
*/
|
||||
public static function GetOptionalParam($oData, $sParamName, $default)
|
||||
{
|
||||
if (isset($oData->$sParamName)) {
|
||||
return $oData->$sParamName;
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a class from a Rest/Json structure.
|
||||
*
|
||||
* @param string $sParamName Name of the parameter to fetch from the input data
|
||||
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception If the parameter is missing or the class is unknown
|
||||
* @api
|
||||
*/
|
||||
public static function GetClass($oData, $sParamName)
|
||||
{
|
||||
$sClass = self::GetMandatoryParam($oData, $sParamName);
|
||||
if (!MetaModel::IsValidClass($sClass)) {
|
||||
throw new Exception("$sParamName: '$sClass' is not a valid class'");
|
||||
}
|
||||
|
||||
return $sClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a list of attribute codes from a Rest/Json structure.
|
||||
*
|
||||
* @param StdClass $oData Structured input data.
|
||||
* @param string $sParamName Name of the parameter to fetch from the input data
|
||||
*
|
||||
* @param string $sClass Name of the class
|
||||
*
|
||||
* @return array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
|
||||
* @throws Exception
|
||||
* @api
|
||||
*/
|
||||
public static function GetFieldList($sClass, $oData, $sParamName)
|
||||
{
|
||||
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
|
||||
$aShowFields = [];
|
||||
if ($sFields == '*') {
|
||||
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
|
||||
$aShowFields[$sClass][] = $sAttCode;
|
||||
}
|
||||
} elseif ($sFields == '*+') {
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
|
||||
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
|
||||
$aShowFields[$sRefClass][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (explode(',', $sFields) as $sAttCode) {
|
||||
$sAttCode = trim($sAttCode);
|
||||
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
|
||||
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
|
||||
}
|
||||
$aShowFields[$sClass][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
return $aShowFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and interpret object search criteria from a Rest/Json structure
|
||||
*
|
||||
* @param string $sClass Name of the class
|
||||
* @param StdClass $oCriteria Hash of attribute code => value (can be a substructure or a scalar, depending on the nature of the
|
||||
* attriute)
|
||||
*
|
||||
* @return object The object found
|
||||
* @throws Exception If the input structure is not valid or it could not find exactly one object
|
||||
* @api
|
||||
*/
|
||||
protected static function FindObjectFromCriteria($sClass, $oCriteria)
|
||||
{
|
||||
$aCriteriaReport = [];
|
||||
if (isset($oCriteria->finalclass)) {
|
||||
if (!MetaModel::IsValidClass($oCriteria->finalclass)) {
|
||||
throw new Exception("finalclass: Unknown class '".$oCriteria->finalclass."'");
|
||||
}
|
||||
if (!MetaModel::IsParentClass($sClass, $oCriteria->finalclass)) {
|
||||
throw new Exception("finalclass: '".$oCriteria->finalclass."' is not a child class of '$sClass'");
|
||||
}
|
||||
$sClass = $oCriteria->finalclass;
|
||||
}
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
foreach ($oCriteria as $sAttCode => $value) {
|
||||
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
||||
if (is_object($value) || is_array($value)) {
|
||||
$value = json_encode($value);
|
||||
}
|
||||
$aCriteriaReport[] = "$sAttCode: $value ($realValue)";
|
||||
}
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$iCount = $oSet->Count();
|
||||
if ($iCount == 0) {
|
||||
throw new Exception("No item found with criteria: ".implode(', ', $aCriteriaReport));
|
||||
} elseif ($iCount > 1) {
|
||||
throw new Exception("Several items found ($iCount) with criteria: ".implode(', ', $aCriteriaReport));
|
||||
}
|
||||
$res = $oSet->Fetch();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an object from a polymorph search specification (Rest/Json)
|
||||
*
|
||||
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
|
||||
* @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then
|
||||
* @param string $sClass Name of the class
|
||||
*
|
||||
* @return DBObject The object found
|
||||
* @throws Exception If the input structure is not valid or it could not find exactly one object
|
||||
*
|
||||
* @api
|
||||
* @see DBObject::CheckChangedExtKeysValues() generic method to check that we can access the linked object isn't used in that use case because values can be literal, OQL, friendlyname
|
||||
*/
|
||||
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
|
||||
{
|
||||
if (is_object($key)) {
|
||||
$res = static::FindObjectFromCriteria($sClass, $key);
|
||||
} elseif (is_numeric($key)) {
|
||||
if ($bAllowNullValue && ($key == 0)) {
|
||||
$res = null;
|
||||
} else {
|
||||
$res = MetaModel::GetObject($sClass, $key, false);
|
||||
if (is_null($res)) {
|
||||
throw new Exception("Invalid object $sClass::$key");
|
||||
}
|
||||
}
|
||||
} elseif (is_string($key)) {
|
||||
// OQL
|
||||
$oSearch = DBObjectSearch::FromOQL($key);
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$iCount = $oSet->Count();
|
||||
if ($iCount == 0) {
|
||||
throw new Exception("No item found for query: $key");
|
||||
} elseif ($iCount > 1) {
|
||||
throw new Exception("Several items found ($iCount) for query: $key");
|
||||
}
|
||||
$res = $oSet->Fetch();
|
||||
} else {
|
||||
throw new Exception("Wrong format for key");
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search objects from a polymorph search specification (Rest/Json)
|
||||
*
|
||||
* @param string $sClass Name of the class
|
||||
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
|
||||
* @param int $iLimit The limit of results to return
|
||||
* @param int $iOffset The offset of results to return
|
||||
*
|
||||
* @return DBObjectSet The search result set
|
||||
* @throws Exception If the input structure is not valid
|
||||
* @api
|
||||
*/
|
||||
public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0)
|
||||
{
|
||||
if (is_object($key)) {
|
||||
if (isset($key->finalclass)) {
|
||||
$sClass = $key->finalclass;
|
||||
if (!MetaModel::IsValidClass($sClass)) {
|
||||
throw new Exception("finalclass: Unknown class '$sClass'");
|
||||
}
|
||||
}
|
||||
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
foreach ($key as $sAttCode => $value) {
|
||||
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
||||
}
|
||||
} elseif (is_numeric($key)) {
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
$oSearch->AddCondition('id', $key);
|
||||
} elseif (is_string($key)) {
|
||||
// OQL
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL($key);
|
||||
} catch (Exception $e) {
|
||||
throw new CoreOqlException('Query failed to execute', [
|
||||
'query' => $key,
|
||||
'exception_class' => get_class($e),
|
||||
'exception_message' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Wrong format for key");
|
||||
}
|
||||
$oObjectSet = new DBObjectSet($oSearch, [], [], null, $iLimit, $iOffset);
|
||||
|
||||
return $oObjectSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret the Rest/Json value and get a valid attribute value
|
||||
*
|
||||
* @param string $sAttCode Attribute code
|
||||
* @param mixed $value Depending on the type of attribute (a scalar, or search criteria, or list of related objects...)
|
||||
* @param string $sClass Name of the class
|
||||
*
|
||||
* @return mixed The value that can be used with DBObject::Set()
|
||||
* @throws Exception If the specification of the value is not valid.
|
||||
* @api
|
||||
*/
|
||||
public static function MakeValue($sClass, $sAttCode, $value)
|
||||
{
|
||||
try {
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
||||
throw new Exception("Unknown attribute");
|
||||
}
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeExternalKey) {
|
||||
$oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
|
||||
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
|
||||
} elseif ($oAttDef instanceof AttributeLinkedSet) {
|
||||
if (!is_array($value)) {
|
||||
throw new Exception("A link set must be defined by an array of objects");
|
||||
}
|
||||
$sLnkClass = $oAttDef->GetLinkedClass();
|
||||
$aLinks = [];
|
||||
foreach ($value as $oValues) {
|
||||
$oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
|
||||
// Fix for N°1939
|
||||
if (($oAttDef instanceof AttributeLinkedSetIndirect) && ($oLnk->Get($oAttDef->GetExtKeyToRemote()) == 0)) {
|
||||
continue;
|
||||
}
|
||||
$aLinks[] = $oLnk;
|
||||
}
|
||||
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
|
||||
} elseif ($oAttDef instanceof AttributeTagSet) {
|
||||
if (!is_array($value)) {
|
||||
throw new Exception("A tag set must be defined by an array of tag codes");
|
||||
}
|
||||
$value = $oAttDef->FromJSONToValue($value);
|
||||
} else {
|
||||
$value = $oAttDef->FromJSONToValue($value);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret a Rest/Json structure that defines attribute values, and build an object
|
||||
*
|
||||
* @param array $aFields A hash of attribute code => value specification.
|
||||
* @param string $sClass Name of the class
|
||||
*
|
||||
* @return DBObject The newly created object
|
||||
* @throws Exception If the specification of the values is not valid
|
||||
* @api
|
||||
*/
|
||||
public static function MakeObjectFromFields($sClass, $aFields)
|
||||
{
|
||||
$oObject = MetaModel::NewObject($sClass);
|
||||
foreach ($aFields as $sAttCode => $value) {
|
||||
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||
try {
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
return $oObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret a Rest/Json structure that defines attribute values, and update the given object
|
||||
*
|
||||
* @param array $aFields A hash of attribute code => value specification.
|
||||
* @param DBObject $oObject The object being modified
|
||||
*
|
||||
* @return DBObject The object modified
|
||||
* @throws Exception If the specification of the values is not valid
|
||||
* @api
|
||||
*/
|
||||
public static function UpdateObjectFromFields($oObject, $aFields)
|
||||
{
|
||||
$sClass = get_class($oObject);
|
||||
foreach ($aFields as $sAttCode => $value) {
|
||||
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||
try {
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
return $oObject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A REST service provider implementing this interface will have its input JSON data sanitized for logging purposes
|
||||
*
|
||||
* @see \iRestServiceProvider
|
||||
* @since 2.7.13, 3.2.1-1
|
||||
*/
|
||||
interface iRestInputSanitizer
|
||||
{
|
||||
public function SanitizeJsonInput(string $sJsonInput): string;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implement this interface to add new operations to the REST/JSON web service
|
||||
*
|
||||
* @api
|
||||
* @package RESTExtensibilityAPI
|
||||
* @since 2.0.1
|
||||
*/
|
||||
interface iRestServiceProvider
|
||||
{
|
||||
/**
|
||||
* Enumerate services delivered by this class
|
||||
*
|
||||
* @param string $sVersion The version (e.g. 1.0) supported by the services
|
||||
*
|
||||
* @return array An array of hash 'verb' => verb, 'description' => description
|
||||
* @api
|
||||
*/
|
||||
public function ListOperations($sVersion);
|
||||
|
||||
/**
|
||||
* Enumerate services delivered by this class
|
||||
*
|
||||
* @param string $sVersion The version (e.g. 1.0) supported by the services
|
||||
* @param string $sVerb
|
||||
* @param array $aParams
|
||||
*
|
||||
* @return RestResult The standardized result structure (at least a message)
|
||||
* @api
|
||||
*/
|
||||
public function ExecOperation($sVersion, $sVerb, $aParams);
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// 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
|
||||
@@ -32,34 +32,36 @@ class AuditCategory extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('name'),
|
||||
"reconc_keys" => ['name'],
|
||||
"db_table" => "priv_auditcategory",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-folder.svg'),
|
||||
);
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
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", array("allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
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", 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", array("allowed_values"=>null, "sql"=>"ok_error_tolerance", "default_value"=>5, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("warning_error_tolerance", array("allowed_values" => null, "sql" => "warning_error_tolerance", "default_value" => 25, "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("domains_list",
|
||||
array("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" => array(), "display_style" => 'property')));
|
||||
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 AttributeOQL("definition_set", ["allowed_values" => null, "sql" => "definition_set", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
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, "edit_when" => LINKSET_EDITWHEN_ALWAYS, "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
|
||||
MetaModel::Init_SetZListItems('details', array('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('list', array('description', )); // Attributes to be displayed for a list
|
||||
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('list', ['description', ]); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'definition_set')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
|
||||
MetaModel::Init_SetZListItems('standard_search', ['description', 'definition_set']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,9 +76,9 @@ class AuditCategory extends cmdbAbstractObject
|
||||
public function GetReportColor($iTotal, $iErrors)
|
||||
{
|
||||
$sResult = 'red';
|
||||
if ( ($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100) ) {
|
||||
if (($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100)) {
|
||||
$sResult = 'green';
|
||||
} else if (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) {
|
||||
} elseif (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) {
|
||||
$sResult = 'orange';
|
||||
}
|
||||
|
||||
@@ -93,4 +95,3 @@ class AuditCategory extends cmdbAbstractObject
|
||||
return $aShortcutActions;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
@@ -16,7 +17,6 @@
|
||||
// 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
|
||||
@@ -33,32 +33,34 @@ class AuditDomain extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"complementary_name_attcode" => array('description'),
|
||||
"complementary_name_attcode" => ['description'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('name'),
|
||||
"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", 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", array("allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeImage("icon", array("is_null_allowed" => true, "depends_on" => array(), "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",
|
||||
array("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" => array())));
|
||||
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', array('name', 'description', 'icon', 'categories_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('description',)); // Attributes to be displayed for a list
|
||||
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', array('description')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
|
||||
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)
|
||||
@@ -84,40 +86,39 @@ class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
|
||||
*/
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('category_id', 'domain_id'),
|
||||
"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' => array(
|
||||
'no_duplicate' => array(
|
||||
'attributes' => array(
|
||||
'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", array("targetclass" => "AuditCategory", "jointype" => '', "allowed_values" => null, "sql" => "category_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", array("allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("domain_id", array("targetclass" => "AuditDomain", "jointype" => '', "allowed_values" => null, "sql" => "domain_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("domain_name", array("allowed_values" => null, "extkey_attcode" => 'domain_id', "target_attcode" => "name")));
|
||||
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', array('category_id', 'domain_id'));
|
||||
MetaModel::Init_SetZListItems('list', array('category_id', 'domain_id'));
|
||||
MetaModel::Init_SetZListItems('details', ['category_id', 'domain_id']);
|
||||
MetaModel::Init_SetZListItems('list', ['category_id', 'domain_id']);
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'domain_id'));
|
||||
MetaModel::Init_SetZListItems('standard_search', ['category_id', 'domain_id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// 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 "rule" linked to a given audit category.
|
||||
* Each rule is based on an OQL expression that returns either the "good" objects
|
||||
@@ -33,35 +33,35 @@ class AuditRule extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('name'),
|
||||
"reconc_keys" => ['name'],
|
||||
"db_table" => "priv_auditrule",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit.svg'),
|
||||
);
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
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", array("allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => array())));
|
||||
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", 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", 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", array("allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name")));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["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 AttributeOQL("query", ["allowed_values" => null, "sql" => "query", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
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 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 AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("contact_id", ["allowed_values" => null, "sql" => "contact_id", "targetclass" => "Contact", "is_null_allowed" => true, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeHTML("process", ["allowed_values" => null, "sql" => "process", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('category_id', 'name', 'description', 'query', 'valid_flag')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('category_id', 'description', 'valid_flag')); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag', 'process', 'contact_id']); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'query']); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'name', 'description', 'valid_flag', 'query')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'category_id')); // Criteria of the advanced search form
|
||||
MetaModel::Init_SetZListItems('standard_search', ['category_id', 'name', 'description', 'valid_flag', 'query']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'category_id', 'contact_id', 'query']); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
|
||||
public static function GetShortcutActions($sFinalClass)
|
||||
{
|
||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
||||
@@ -72,4 +72,3 @@ class AuditRule extends cmdbAbstractObject
|
||||
return $aShortcutActions;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated 3.0.0 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
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated 3.0.0 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
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -32,7 +33,8 @@ class CompileCSSService
|
||||
{
|
||||
}
|
||||
|
||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = [])
|
||||
{
|
||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user