mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-15 00:14:10 +01:00
Compare commits
22 Commits
feature/ph
...
8231-proto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6105255d76 | ||
|
|
f3909eb50a | ||
|
|
7f2a1a6416 | ||
|
|
32dbf1490c | ||
|
|
2dc9f5dcc6 | ||
|
|
200b148c86 | ||
|
|
6fcbf68013 | ||
|
|
2fedfa1b4c | ||
|
|
755ac3a15c | ||
|
|
01e2d3b317 | ||
|
|
39fd258544 | ||
|
|
f58a2be620 | ||
|
|
e8c622a15d | ||
|
|
783fa01fc9 | ||
|
|
b1f49ae487 | ||
|
|
896069d64b | ||
|
|
85434578d3 | ||
|
|
e142fba0e6 | ||
|
|
c9f32311b4 | ||
|
|
a9e10742ec | ||
|
|
cb2a093498 | ||
|
|
944b1f557d |
103
.doc/README.md
Normal file
103
.doc/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Phpdoc dokuwiki template
|
||||
This directory contains a template for rendering iTop phpdoc as dokuwiki pages.
|
||||
|
||||
|
||||
Conventional tags that you should use:
|
||||
* `@internal` : exclude from the documentation.
|
||||
* `@api` : it means that a method is an api, thus it may be interacted with.
|
||||
* `@see` : it points to another documented method
|
||||
* `@link` : external url
|
||||
* if you point to another page of the wiki, please use relative links.
|
||||
* `@example` : let you provide example of code
|
||||
* `@param`, `@return`, `@throws`, ...
|
||||
|
||||
|
||||
## Special instructions
|
||||
|
||||
Some iTop specific tags were added :
|
||||
* `@api-advanced`: it means that a method is an `@api` but mark it also as "complex" to use
|
||||
* `@overwritable-hook`: used to mark a method as "designed to be extended"
|
||||
* `@extension-hook`: not used for now
|
||||
* `@phpdoc-tuning-exclude-inherited`: once this tag is present on a class, it's inherited methods won't be showed.
|
||||
|
||||
|
||||
### known limitations:
|
||||
#### `@see` tags must be very specific:
|
||||
* always prefix class members (attributes or methods) with `ClassName::` (do not use self)
|
||||
* for methods always suffix them with `()`,
|
||||
* do not reference variables since they are not documented. If you have to, always prefix them with `$`
|
||||
|
||||
examples:
|
||||
```
|
||||
/**
|
||||
* @see DBObject
|
||||
* @see DBObject::Get()
|
||||
* @see DBObject::$foo
|
||||
*/
|
||||
```
|
||||
|
||||
#### Do not use inline tags, they do not work properly, example:
|
||||
```
|
||||
/**
|
||||
* This is a texts with an inline tag {@see [FQSEN] [<description>]} it must never be used
|
||||
*/
|
||||
```
|
||||
|
||||
#### The `@example` tag must respect this very precise syntax
|
||||
* the sentence in the first line (next to the tag) is the title, it must be enclosed by double quotes
|
||||
* the following lines are the sample code.
|
||||
* 💔 since we simply hack the official tag, this syntax must be respected carefully 💔
|
||||
example:
|
||||
```
|
||||
/**
|
||||
* @example "This is the title of the multiline example"
|
||||
* $foo = DBObject::Get('foo');
|
||||
* DBObject::Set('foo', ++$foo);
|
||||
*/
|
||||
```
|
||||
|
||||
## How content is included into the documentation
|
||||
|
||||
**For a class** those requirements have to be respected:
|
||||
- the file containing the class must be listed in `/phpdoc/files/file[]` of `.doc/phpdoc-objects-manipulation.dist.xml`
|
||||
- the class **must not** have the tag `@internal`
|
||||
- the class **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||
|
||||
Then, **for a method** of an eligible class:
|
||||
- **public** methods **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||
- **protected** methods **must** have at least one of: `@overwritable-hook`, `@extension-hook`
|
||||
- **private** methods are **always excluded**
|
||||
|
||||
**Class properties** and **constants** are never documented (this is subject to change).
|
||||
|
||||
|
||||
|
||||
|
||||
## A note about the rendering engine
|
||||
|
||||
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
|
||||
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
```
|
||||
cd .doc
|
||||
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||
```
|
||||
|
||||
## Generation
|
||||
`./bin/build-doc-object-manipulation` and `./bin/build-doc-extensions` contains examples of doc. generation, beware: they have to be called from the .doc directory:
|
||||
```shell
|
||||
cd /path/to/itop/.doc
|
||||
./bin/build-doc-object-manipulation
|
||||
```
|
||||
|
||||
the resulting documentation is written into `data/phpdocumentor/output`
|
||||
|
||||
|
||||
## Dokuwiki requirements
|
||||
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
|
||||
* the generated files have to be placed under an arbitrary directory of `[/path/to/dokuwiki]/data/pages`.
|
||||
* the html has to be activated [config:htmlok](https://www.dokuwiki.org/config:htmlok)
|
||||
* the generated files have to be in lowercase
|
||||
6
.doc/bin/build-doc-extensions
Executable file
6
.doc/bin/build-doc-extensions
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && .doc/vendor/bin/phpdoc -c .doc/phpdoc-extensions.dist.xml -vvv
|
||||
|
||||
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||
cd data/phpdocumentor/output/extensions/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
||||
7
.doc/bin/build-doc-object-manipulation
Executable file
7
.doc/bin/build-doc-object-manipulation
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf ../data/phpdocumentor/output/objects-manipulation/ && rm -rf ../data/phpdocumentor/temp/objects-manipulation/ && ./vendor/bin/phpdoc -c ./phpdoc-objects-manipulation.dist.xml -vvv
|
||||
|
||||
|
||||
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||
cd ../data/phpdocumentor/output/objects-manipulation/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
||||
6
.doc/composer.json
Normal file
6
.doc/composer.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"require-dev": {
|
||||
"phpdocumentor/phpdocumentor": "~2",
|
||||
"jms/serializer": "1.7.*"
|
||||
}
|
||||
}
|
||||
3015
.doc/composer.lock
generated
Normal file
3015
.doc/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
.doc/phpdoc-extensions.dist.xml
Executable file
20
.doc/phpdoc-extensions.dist.xml
Executable file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
<title><![CDATA[iTop extensions]]></title>
|
||||
|
||||
<parser>
|
||||
<target>../data/phpdocumentor/temp/extensions</target>
|
||||
</parser>
|
||||
|
||||
<transformer>
|
||||
<target>../data/phpdocumentor/output/extensions</target>
|
||||
</transformer>
|
||||
|
||||
<transformations>
|
||||
<template name="phpdoc-templates/combodo-wiki"/>
|
||||
</transformations>
|
||||
|
||||
<files>
|
||||
<file>../application/applicationextension.inc.php</file>
|
||||
</files>
|
||||
</phpdoc>
|
||||
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
|
||||
<!--
|
||||
/**
|
||||
The documentation of this file can be found here : https://docs.phpdoc.org/references/configuration.html
|
||||
it has to be completed by the CLI parameters documentation which is more comprehensive: https://docs.phpdoc.org/references/commands/project_run.html#usage
|
||||
|
||||
usage:
|
||||
vendor/bin/phpdoc -c phpdoc-objects-manipulation.dist.xml
|
||||
|
||||
*/
|
||||
-->
|
||||
|
||||
<title><![CDATA[iTop's objects manipulation API]]></title>
|
||||
|
||||
<parser>
|
||||
<default-package-name>iTopORM</default-package-name>
|
||||
<target>../data/phpdocumentor/temp/objects-manipulation</target>
|
||||
<visibility>public,protected</visibility>
|
||||
<markers>
|
||||
<!--<item>TODO</item>-->
|
||||
<!--<item>FIXME</item>-->
|
||||
</markers>
|
||||
<extensions>
|
||||
<extension>php</extension>
|
||||
</extensions>
|
||||
</parser>
|
||||
|
||||
<transformer>
|
||||
<target>../data/phpdocumentor/output/objects-manipulation</target>
|
||||
</transformer>
|
||||
|
||||
<transformations>
|
||||
<template name="phpdoc-templates/combodo-wiki"/>
|
||||
</transformations>
|
||||
|
||||
<!--<logging>-->
|
||||
<!--<level>warn</level>-->
|
||||
<!--<paths>-->
|
||||
<!--<!–<default>data/phpdocumentor/log/objects-manipulation/{DATE}.log</default>–>-->
|
||||
<!--<!–<errors>data/phpdocumentor/log/objects-manipulation/{DATE}.errors.log</errors>–>-->
|
||||
|
||||
<!--<default>{APP_ROOT}/data/log/{DATE}.log</default>-->
|
||||
<!--<errors>{APP_ROOT}/data/log/{DATE}.errors.log</errors>-->
|
||||
<!--</paths>-->
|
||||
<!--</logging>-->
|
||||
|
||||
<files>
|
||||
<file>../core/dbobject.class.php</file>
|
||||
<file>../core/dbobjectsearch.class.php</file>
|
||||
<file>../core/metamodel.class.php</file>
|
||||
<file>../core/dbobjectset.class.php</file>
|
||||
<file>../core/dbsearch.class.php</file>
|
||||
<file>../core/dbunionsearch.class.php</file>
|
||||
</files>
|
||||
|
||||
</phpdoc>
|
||||
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
@@ -0,0 +1,136 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
|
||||
{% if node.tags['internal'] is defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This class is "internal", and thus is not documented!</WRAP>
|
||||
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This class is neither "api", "api-advanced", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||
{% else %}
|
||||
|
||||
====== {{ node.name }} ======
|
||||
|
||||
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
|
||||
|
||||
{% if node.deprecated %}
|
||||
=== **<del>Deprecated</del>**===
|
||||
//{{ node.tags.deprecated[0].description }}//
|
||||
{% endif %}
|
||||
|
||||
|
||||
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||
|
||||
|
||||
{% set class = node.parent %}
|
||||
{% block hierarchy_element %}
|
||||
|
||||
{% if class and class.name is defined and class.name|trim != '' %}
|
||||
==== parent ====
|
||||
{% set child = class %}
|
||||
{% set class = class.parent %}
|
||||
{{ block('hierarchy_element') }}
|
||||
[[{{ child.name }}|{{ child.name }}]]
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% for interface in node.interfaces|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Implements ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for trait in node.usedTraits|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Uses traits ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||
|
||||
{% set methods = node.inheritedMethods.merge(node.methods.merge(node.magicMethods)) %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '=====', sub_title_level: '=='} %}
|
||||
|
||||
<WRAP clear />
|
||||
|
||||
{% for method in methods|sort_asc
|
||||
if method.visibility == 'public'
|
||||
and (
|
||||
method.tags['api'] is defined
|
||||
or method.tags['api-advanced'] is defined
|
||||
or method.tags['overwritable-hook'] is defined
|
||||
or method.tags['extension-hook'] is defined
|
||||
)
|
||||
and (
|
||||
node.tags['phpdoc-tuning-exclude-inherited'] is not defined
|
||||
or method.parent.name == node.name
|
||||
)
|
||||
%}
|
||||
{%- if loop.first %}
|
||||
===== Public methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% for method in methods|sort_asc if method.visibility == 'protected' and (method.tags['overwritable-hook'] is defined or method.tags['extension-hook'] is defined) %}
|
||||
{%- if loop.first %}
|
||||
===== Protected methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||
{% if constants|length > 0 %}
|
||||
===== Constants =====
|
||||
{% for constant in constants|sort_asc %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#{% set properties = node.inheritedProperties.merge(node.properties.merge(node.magicProperties)) %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Public properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Protected properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
{% block constant %}
|
||||
|
||||
<WRAP group box >
|
||||
<WRAP twothirds column >
|
||||
==== {{ constant.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if constant.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and constant.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
== {{ constant.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ constant.description|markdown|raw }}</html>
|
||||
|
||||
{% if constant.deprecated %}
|
||||
=== Deprecated ===
|
||||
{{ constant.tags.deprecated[0].description|raw }}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:constant} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:constant, title_level: '==', blacklist: ['link', 'see', 'var', 'deprecated', 'uses', 'package', 'subpackage', 'todo', 'code-example']} %}
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endblock %}
|
||||
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
@@ -0,0 +1,95 @@
|
||||
{% block method %}
|
||||
|
||||
|
||||
<WRAP group box >
|
||||
<WRAP twothirds column >
|
||||
==== {{ method.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
<WRAP third column >
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:method, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
{% if method.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and method.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
{% if method.abstract %}<wrap warning>abstract</wrap> {% endif %}
|
||||
{% if method.final %}<wrap notice>final</wrap> {% endif %}
|
||||
<wrap notice>{{ method.visibility }}</wrap>
|
||||
{% if method.static %}<wrap warning>static</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
== {{ method.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ method.description|markdown|raw }}</html>
|
||||
|
||||
<code php>{% if method.abstract %}abstract {% endif %}{% if method.final %}final {% endif %}{{ method.visibility }} {% if method.static %}static {% endif %}{{ method.name }}({% for argument in method.arguments %}{{ argument.isVariadic ? '...' }}{{ argument.name }}{{ argument.default ? (' = '~argument.default)|raw }}{% if not loop.last %}, {% endif %}{% endfor %})</code>
|
||||
|
||||
<WRAP twothirds column >
|
||||
|
||||
|
||||
=== Parameters ===
|
||||
{% if method.arguments|length > 0 -%}
|
||||
^ types ^ name ^ default ^ description ^
|
||||
{% for argument in method.arguments -%}
|
||||
| **<nowiki>{{ argument.types|join('|')|raw }}</nowiki>** | {{ argument.name }} {{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }} | <nowiki>{{ argument.default|raw }}</nowiki> | {{ argument.description|trim|replace("\n", ' ')|raw }} |{{ "\r\n" }}
|
||||
{%- endfor %}
|
||||
{% else %}
|
||||
//none//
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#=== Parameters ===#}
|
||||
{#{% if method.arguments|length > 0 -%}#}
|
||||
{#{% for argument in method.arguments -%}#}
|
||||
{#== {{ argument.name }} ==#}
|
||||
|
||||
|
||||
{#{% set varDesc %}#}
|
||||
{#<span style="margin:0 10px; 0 20px; font-weight: bold;">{{ argument.types|join('|') }}</span>#}
|
||||
{#{{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }}#}
|
||||
{#{{ argument.description|raw }}#}
|
||||
{#{% endset %}#}
|
||||
{#<html>{{ varDesc|markdown|raw }}</html>#}
|
||||
{#{%- endfor %}#}
|
||||
{#{% else %}#}
|
||||
{#<wrap tip>This method has no parameter</wrap>#}
|
||||
{#{% endif %}#}
|
||||
|
||||
|
||||
{% if method.response and method.response.types|join() != 'void' %}
|
||||
=== Returns ===
|
||||
<html>{{ ('**' ~ method.response.types|join('|')|trim ~ '** ' ~ method.response.description)|markdown|raw }}</html>
|
||||
{% endif %}
|
||||
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column >
|
||||
|
||||
{% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %}
|
||||
=== Throws ===
|
||||
{% for exception in method.tags.throws -%}
|
||||
{% if loop.length > 1 %} * {% endif %}''{{ exception.types|join('|')|raw }}'' <nowiki>{{ exception.description|raw }}</nowiki>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:method} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/used-by.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags-with-description.txt.twig' with {structure:method, title_level: '===', WRAP: 'info', tagsWithDescription: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:method, title_level: '===', blacklist: ['todo', 'link', 'see', 'abstract', 'example', 'param', 'return', 'access', 'deprecated', 'throws', 'throw', 'uses', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'used-by', 'inheritdoc', 'code-example']} %}
|
||||
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
{% block property %}
|
||||
|
||||
<WRAP group box>
|
||||
<WRAP twothirds column >
|
||||
==== ${{ property.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if property.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and property.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
|
||||
|
||||
== {{ property.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ property.description|markdown|raw }}</html>
|
||||
{% if property.var.0.description %}<html>{{ property.var.0.description|markdown|raw }}</html>{% endif %}
|
||||
|
||||
|
||||
|
||||
{#{% if property.types %}#}
|
||||
{#== Type ==#}
|
||||
{#{% for type in property.types %}#}
|
||||
{#{% if loop.length > 1 %} * {% endif %}{{ type|raw }} : {{ type.description|raw }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{{ property.types|join('|')|raw }}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
|
||||
{% if property.deprecated %}
|
||||
== Deprecated ==
|
||||
{{ property.tags.deprecated[0].description }}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:property} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:property, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:property, title_level: ''} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:property, title_level: '==', blacklist: ['link', 'see', 'access', 'var', 'deprecated', 'uses', 'todo', 'code-example']} %}
|
||||
|
||||
|
||||
<code php>{{ property.visibility }} ${{ property.name }}{% if property.types %} : {{ property.types|join('|')|raw }}{% endif %}</code>
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endblock %}
|
||||
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
@@ -0,0 +1 @@
|
||||
{{ node.source|raw }}
|
||||
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
@@ -0,0 +1,122 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block javascripts %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{#<section class="row-fluid">#}
|
||||
{#<div class="span2 sidebar">#}
|
||||
{#{% set namespace = project.namespace %}#}
|
||||
{#{{ block('sidebarNamespaces') }}#}
|
||||
{#</div>#}
|
||||
{#</section>#}
|
||||
{#<section class="row-fluid">#}
|
||||
====== {{ node.path|split('/')|slice(0,-1)|join('/') }}{{ node.name }} ======
|
||||
{{ node.summary }}
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
{% if node.traits|length > 0 %}
|
||||
|
||||
===== Traits =====
|
||||
{% for trait in node.traits %}
|
||||
<tr>
|
||||
<td>{{ trait|raw }}</td>
|
||||
<td><em>{{ trait.summary }}</em></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if node.interfaces|length > 0 %}
|
||||
===== Interfaces =====
|
||||
{% for interface in node.interfaces %}
|
||||
<tr>
|
||||
<td>{{ interface|raw }}</td>
|
||||
<td><em>{{ interface.summary }}</em></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.classes|length > 0 %}
|
||||
===== Classes =====
|
||||
{% for class in node.classes %}
|
||||
{{ class|raw }}
|
||||
<em>{{ class.summary }}</em>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.package is not empty and node.package != '\\' %}
|
||||
===== Package =====
|
||||
{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}
|
||||
{% endif %}
|
||||
|
||||
{% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
|
||||
{% if loop.first %}
|
||||
===== See also =====
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
<dd><a href="{{ tag.reference ?: tag.link }}"><div class="namespace-wrapper">{{ tag.description ?: tag.reference }}</div></a></dd>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<h2>Tags</h2>
|
||||
<table class="table table-condensed">
|
||||
{% for tagName,tags in node.tags if tagName not in ['link', 'see', 'package', 'subpackage'] %}
|
||||
<tr>
|
||||
<th>
|
||||
{{ tagName }}
|
||||
</th>
|
||||
<td>
|
||||
{% for tag in tags %}
|
||||
{{ tag.description|markdown|raw }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="2"><em>None found</em></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
{% if node.constants|length > 0 %}
|
||||
<div class="row-fluid">
|
||||
<section class="span8 content file">
|
||||
<h2>Constants</h2>
|
||||
</section>
|
||||
<aside class="span4 detailsbar"></aside>
|
||||
</div>
|
||||
|
||||
{% for constant in node.constants %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.functions|length > 0 %}
|
||||
<div class="row-fluid">
|
||||
<section class="span8 content file">
|
||||
<h2>Functions</h2>
|
||||
</section>
|
||||
<aside class="span4 detailsbar"></aside>
|
||||
</div>
|
||||
|
||||
{% for method in node.functions %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="source-view-label">{{ node.file.name }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre data-src="{{ path('files/' ~ node.path ~ '.txt')|raw }}" class="language-php line-numbers"></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
@@ -0,0 +1,42 @@
|
||||
{% extends 'layout.html.twig' %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link href="{{ path('css/jquery.iviewer.css') }}" rel="stylesheet" media="all"/>
|
||||
<style>
|
||||
#viewer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="{{ path('js/jquery.mousewheel.js') }}" type="text/javascript"></script>
|
||||
<script src="{{ path('js/jquery.iviewer.js') }}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).resize(function(){
|
||||
$("#viewer").height($(window).height() - 100);
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
|
||||
$('#viewer img').bind('dragstart', function(event){
|
||||
event.preventDefault();
|
||||
});
|
||||
$(window).resize();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div class="wrapper">
|
||||
<div id="viewer" class="viewer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
@@ -0,0 +1,5 @@
|
||||
# Fixes a vulnerability in CentOS: http://stackoverflow.com/questions/20533279/prevent-php-from-parsing-non-php-files-such-as-somefile-php-txt
|
||||
<FilesMatch \.php\.txt$>
|
||||
RemoveHandler .php
|
||||
ForceType text/plain
|
||||
</FilesMatch>
|
||||
@@ -0,0 +1,34 @@
|
||||
{% if title_level is not defined %}
|
||||
{%- set title_level = '==' -%}
|
||||
{% endif %}
|
||||
|
||||
{% if sub_title_level is not defined %}
|
||||
{%- set sub_title_level = title_level|slice(1) -%}
|
||||
{% endif %}
|
||||
{% if sub_title_level == '=' %}
|
||||
{%- set sub_title_level = '' -%}
|
||||
{% endif %}
|
||||
|
||||
{#{% for tagName,tags in structure.tags if tagName in ['code-example'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#{{title_level}} Examples {{title_level}}#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#{%- set descToken = tag.description|split("\n", 2) -%}#}
|
||||
{#{%- set title = descToken[0] -%}#}
|
||||
{#{%- set code = descToken[1] -%}#}
|
||||
{#{{sub_title_level}} {{ title }} {{sub_title_level}}#}
|
||||
{#<code php>{{ code|raw }}</code>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{% for tagName,tags in structure.tags if tagName in ['example'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Examples {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{{ sub_title_level }} {{ tag.filePath|escape }}{{ sub_title_level }}
|
||||
<code php>{{ tag.description|raw }}</code>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
|
||||
{% if (node.parent is null) %}
|
||||
{{title_level}} File {{ structure.path }} {{title_level}}
|
||||
{% endif %}
|
||||
|
||||
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
|
||||
{{title_level}} Inherited from {{title_level}}
|
||||
[[{{structure.parent}}|{{structure.parent}}]]
|
||||
{% endif %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% for structure in structures|sort_asc if structure.tags['internal'] is not defined and (structure.tags['api'] is defined or structure.tags['api-advanced'] is defined or structure.tags['overwritable-hook'] is defined or structure.tags['extension-hook'] is defined ) %}
|
||||
{#{{ structure|raw }}#}
|
||||
|
||||
{% set structureName = structure|trim('\\', 'left') %}
|
||||
|
||||
<WRAP group box>
|
||||
<WRAP twothirds column >
|
||||
==== {{ structureName }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if structure.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if structure.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if structure.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:structure, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
{{ structure.summary|raw }}
|
||||
[[{{structureName}}|More information]]
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{% if title_level is not defined %}
|
||||
{%- set title_level='==' -%}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['link', 'see'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} See also {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{%- set linkTag = tag.reference|trim('\\', 'left') -%}
|
||||
{% if not('()' in linkTag or '$' in linkTag or node.name in linkTag or '::' in linkTag ) %}
|
||||
{%- set linkTag = linkTag|lower -%}
|
||||
{% elseif node.name~'::' in linkTag %}
|
||||
{%- set linkTag = linkTag|replace({(node.name~'::'): '#'})|lower -%}
|
||||
{% elseif '::' in linkTag -%}
|
||||
{%- set linkTag = linkTag|replace({'::': '#'})|lower -%}
|
||||
{% else %}
|
||||
{%- set linkTag = '#' ~ linkTag|lower -%}
|
||||
{%- endif %}
|
||||
|
||||
{% if loop.length > 1 %} * {% endif %}{% if tag.reference is not empty -%}
|
||||
[[{{linkTag}}|{{ (tag.reference)|trim('\\', 'left') }}]] {% if tag.description|trim is not empty %}: {{ tag.description|trim('\\', 'left') }} {% endif %}
|
||||
{%- else -%}
|
||||
{#{{ tag.description|trim('\\', 'left') }}#}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,56 @@
|
||||
{% if tag is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set tag = "api" -%}
|
||||
{%- endif %}
|
||||
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
|
||||
|
||||
{% for method in methods|sort_asc
|
||||
if (method.visibility == 'public')
|
||||
and (
|
||||
method.tags[tag] is defined
|
||||
and (
|
||||
hidden_by[tag] is not defined or method.tags[hidden_by[tag]] is not defined
|
||||
)
|
||||
)
|
||||
%}
|
||||
{%- if loop.first %}
|
||||
{% if tag == 'api' %}
|
||||
===== API synthesis =====
|
||||
<WRAP>
|
||||
List of the public API methods.
|
||||
When manipulating {{ node.name }}, You can call those methods:
|
||||
</WRAP>
|
||||
{% elseif tag == 'api-advanced' %}
|
||||
===== Advanced API synthesis =====
|
||||
<WRAP>
|
||||
List of advanced API methods
|
||||
Beware they usage is recommended to advanced users only.
|
||||
</WRAP>
|
||||
{% elseif tag == 'overwritable-hook' %}
|
||||
===== overwritable-hook synthesis =====
|
||||
<WRAP >When inheriting from {{ node.name }},
|
||||
you can overwrite those methods in order to add custom logic:
|
||||
</WRAP>
|
||||
{% elseif tag == 'extension-hook' %}
|
||||
===== extension-hook synthesis =====
|
||||
<WRAP >
|
||||
When inheriting from {{ node.name }},
|
||||
you can extend the behaviour of iTop by implementing:
|
||||
</WRAP>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set sanitizedMethod = method|trim('\\', 'left')|replace({(node.name~'::'): ''}) %}
|
||||
{% if '::' in sanitizedMethod -%}
|
||||
{%- if node.tags['phpdoc-tuning-exclude-inherited'] is not defined %}
|
||||
* [[{{sanitizedMethod|replace({'::': '#'})|lower}}|↪{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||
{% endif %}
|
||||
{%- else %}
|
||||
* [[#{{sanitizedMethod}}|{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,20 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level = '==' %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{%- for tagName,tags in structure.tags if tagName in tagsWithDescription -%}
|
||||
{%- for tag in tags -%}
|
||||
{%- if tag.description is not empty -%}
|
||||
{%- if WRAP is defined -%}
|
||||
<WRAP {{WRAP}}>
|
||||
{%- endif -%}
|
||||
{{title_level}} {{ tagName }} {{title_level}}
|
||||
{{ tag.description|escape }}
|
||||
{%- if WRAP is defined -%}
|
||||
</WRAP>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
|
||||
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='=====' %}
|
||||
{% endif %}
|
||||
|
||||
{% if blacklist is not defined %}
|
||||
{% set blacklist =['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'api', 'api-advanced', 'todo', 'code-example'] %}
|
||||
{% endif %}
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
{#^ {% for tagName,tags in structure.tags if tagName not in blacklist -%}#}
|
||||
{#{{ tagName }} ^#}
|
||||
{#{%- endfor %}#}
|
||||
|
||||
{% for tagName,tags in structure.tags if tagName not in blacklist and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||
{%- if loop.first %}
|
||||
{{title_level}} Tags {{title_level}}
|
||||
{% endif %}
|
||||
^ {{ tagName }} | {% for tag in tags %}{{ tag.version ? tag.version ~ ' ' : '' }}{{ tag.description}}{% endfor %} |
|
||||
{% endfor %}
|
||||
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['used-by'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Used by {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#<dt>Uses</dt>#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['uses'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Uses {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#<dt>Uses</dt>#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% if wrap is not defined -%}
|
||||
{% set wrap = 'notice' %}
|
||||
{%- endif -%}
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
{%- for tagName,tags in structure.tags if tagName in wrapTags and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||
<wrap {{wrap}}>{{tagName}}</wrap>
|
||||
{% endfor %}
|
||||
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
@@ -0,0 +1,121 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
|
||||
{% if node.tags['internal'] is defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This interface is "internal", and thus is not documented!</WRAP>
|
||||
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This interface is neither "api", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||
{% else %}
|
||||
|
||||
====== {{ node.name }} ======
|
||||
|
||||
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
|
||||
|
||||
{% if node.deprecated %}
|
||||
=== **<del>Deprecated</del>**===
|
||||
//{{ node.tags.deprecated[0].description }}//
|
||||
{% endif %}
|
||||
|
||||
|
||||
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||
|
||||
|
||||
{% set class = node.parent %}
|
||||
{% block hierarchy_element %}
|
||||
|
||||
{% if class and class.name is defined and class.name|trim != '' %}
|
||||
==== parent ====
|
||||
{% set child = class %}
|
||||
{% set class = class.parent %}
|
||||
{{ block('hierarchy_element') }}
|
||||
[[{{ child.name }}|{{ child.name }}]]
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% for interface in node.interfaces|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Implements ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for trait in node.usedTraits|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Uses traits ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||
|
||||
|
||||
{% set methods = node.inheritedMethods.merge(node.methods) %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||
|
||||
<WRAP clear />
|
||||
|
||||
|
||||
{% for method in methods|sort_asc if method.visibility == 'public' %}
|
||||
{%- if loop.first %}
|
||||
===== Public methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% for method in methods|sort_asc if method.visibility == 'protected' %}
|
||||
{%- if loop.first %}
|
||||
===== Protected methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||
{% if constants|length > 0 %}
|
||||
===== Constants =====
|
||||
{% for constant in constants|sort_asc %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#{% set properties = node.inheritedProperties.merge(node.properties) %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Public properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Protected properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
{% endblock %}
|
||||
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
@@ -0,0 +1,5 @@
|
||||
{% use 'elements/constant.txt.twig' %}
|
||||
{% use 'elements/property.txt.twig' %}
|
||||
{% use 'elements/method.txt.twig' %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
@@ -0,0 +1,51 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% set namespace = project.namespace %}
|
||||
{{ block('sidebarNamespaces') }}
|
||||
|
||||
{#{{ node.parent|raw }}#}
|
||||
{#====== {{ node.parent.fullyQualifiedStructuralElementName }}{{ node.name }} ======#}
|
||||
|
||||
{% if node.children|length > 0 %}
|
||||
=====Namespaces=====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.children} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
{% if node.traits|length > 0 %}
|
||||
===== Traits =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.traits} %}
|
||||
----
|
||||
{%- endif %}
|
||||
|
||||
{% if node.interfaces|length > 0 %}
|
||||
===== Interfaces =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.interfaces} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
{% if node.classes|length > 0 %}
|
||||
===== Classes =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.classes} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{#{% if node.constants|length > 0 %}#}
|
||||
{#===== Constants =====#}
|
||||
{#{% for constant in node.constants|sort_asc %}#}
|
||||
{# {{ block('constant') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
{#{% if node.functions|length > 0 %}#}
|
||||
{#===== Functions =====#}
|
||||
|
||||
{#{% for method in node.functions|sort_asc %}#}
|
||||
{# {{ block('method') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
====== Deprecated elements ======
|
||||
|
||||
{#{% for element in project.indexes.elements if element.deprecated %}#}
|
||||
{#{% if element.file.path != previousPath %}#}
|
||||
{#<li><a href="#{{ element.file.path }}"><i class="icon-file"></i> {{ element.file.path }}</a></li>#}
|
||||
{#{% endif %}#}
|
||||
{#{% set previousPath = element.file.path %}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
{% for element in project.indexes.elements if element.deprecated %}
|
||||
{% if element.file.path != previousPath %}
|
||||
{% if previousPath %}
|
||||
</WRAP>{# group #}
|
||||
{% endif %}
|
||||
{#<a name="{{ element.file.path }}" id="{{ element.file.path }}"></a>#}
|
||||
===== {{ element.file.path }} ({{ element.tags.deprecated.count }} found)=====
|
||||
|
||||
<WRAP group >
|
||||
<WRAP third column >
|
||||
Element
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
Line
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
Description
|
||||
</WRAP>{# third column#}
|
||||
|
||||
{% endif %}
|
||||
{% for tag in element.tags.deprecated %}
|
||||
<WRAP group >
|
||||
<WRAP third column >
|
||||
{{ element.fullyQualifiedStructuralElementName }}
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
{{ element.line }}
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
{{ tag.description }}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
{% endfor %}
|
||||
</WRAP>{# group #}
|
||||
{% set previousPath = element.file.path %}
|
||||
{% else %}
|
||||
<WRAP info>No deprecated elements have been found in this project.</WRAP>
|
||||
{% endfor %}
|
||||
|
||||
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<template>
|
||||
<author>Bruno DA SILVA</author>
|
||||
<email>contact [at] combodo.com</email>
|
||||
<version>1.0.0</version>
|
||||
<copyright>Combodo 2018</copyright>
|
||||
<description><![CDATA[
|
||||
|
||||
Forked from the clean theme of https://github.com/phpDocumentor/phpDocumentor2 provided under the MIT licence.
|
||||
The original work is copyright "Mike van Riel".
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
To improve performance you can add the following to your .htaccess:
|
||||
|
||||
<ifModule mod_deflate.c>
|
||||
<filesMatch "\.(js|css|html)$">
|
||||
SetOutputFilter DEFLATE
|
||||
</filesMatch>
|
||||
</ifModule>
|
||||
]]></description>
|
||||
<transformations>
|
||||
<transformation writer="twig" query="namespace" source="templates/combodo-wiki/namespace.txt.twig" artifact="start.txt"/>
|
||||
<transformation writer="twig" query="indexes.classes" source="templates/combodo-wiki/class.txt.twig" artifact="{{name}}.txt"/>
|
||||
<transformation writer="twig" query="indexes.interfaces" source="templates/combodo-wiki/interface.txt.twig" artifact="{{name}}.txt" />
|
||||
</transformations>
|
||||
</template>
|
||||
@@ -11,7 +11,7 @@ tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = true
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = 300
|
||||
ij_wrap_on_typing = true
|
||||
@@ -78,7 +78,7 @@ ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
ij_editorconfig_spaces_around_assignment_operators = true
|
||||
|
||||
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
||||
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul, phpunit.xml.dist}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_smart_tabs = true
|
||||
@@ -280,17 +280,16 @@ ij_javascript_while_brace_force = always
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
|
||||
[{*.ctp, *.hphp, *.inc, *.module, *.php, *.php4, *.php5, *.phtml}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = true
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_group_field_declarations = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_key_value_pairs = true
|
||||
ij_php_align_match_arm_bodies = false
|
||||
ij_php_align_multiline_array_initializer_expression = true
|
||||
ij_php_align_multiline_binary_operation = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
@@ -299,7 +298,6 @@ ij_php_align_multiline_for = true
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_parameters_in_calls = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_named_arguments = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_align_phpdoc_param_names = false
|
||||
ij_php_anonymous_brace_style = end_of_line
|
||||
@@ -419,7 +417,6 @@ ij_php_see_weight = 3
|
||||
ij_php_since_weight = 28
|
||||
ij_php_sort_phpdoc_elements = true
|
||||
ij_php_space_after_colon = true
|
||||
ij_php_space_after_colon_in_enum_backed_type = true
|
||||
ij_php_space_after_colon_in_named_argument = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_after_comma = true
|
||||
@@ -434,7 +431,6 @@ ij_php_space_before_catch_parentheses = true
|
||||
ij_php_space_before_class_left_brace = true
|
||||
ij_php_space_before_closure_left_parenthesis = true
|
||||
ij_php_space_before_colon = true
|
||||
ij_php_space_before_colon_in_enum_backed_type = false
|
||||
ij_php_space_before_colon_in_named_argument = false
|
||||
ij_php_space_before_colon_in_return_type = false
|
||||
ij_php_space_before_comma = false
|
||||
@@ -470,7 +466,6 @@ ij_php_spaces_around_equality_operators = true
|
||||
ij_php_spaces_around_logical_operators = true
|
||||
ij_php_spaces_around_multiplicative_operators = true
|
||||
ij_php_spaces_around_null_coalesce_operator = true
|
||||
ij_php_spaces_around_pipe_in_union_type = false
|
||||
ij_php_spaces_around_relational_operators = true
|
||||
ij_php_spaces_around_shift_operators = true
|
||||
ij_php_spaces_around_unary_operator = false
|
||||
@@ -545,6 +540,7 @@ ij_html_space_after_tag_name = false
|
||||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
ij_html_uniform_ident = false
|
||||
|
||||
[{*.markdown,*.md}]
|
||||
ij_visual_guides = none
|
||||
|
||||
26
.gitignore
vendored
26
.gitignore
vendored
@@ -1,15 +1,4 @@
|
||||
|
||||
################################### Temporary ignore rules during 2.8 UI/UX dev - START
|
||||
/css/backoffice/main.css
|
||||
|
||||
# Sass converter
|
||||
/**/.sass-cache/
|
||||
################################### Temporary ignore rules during 2.8 UI/UX dev - END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# no slash at the end to handle also symlinks
|
||||
/toolkit
|
||||
/env-*
|
||||
@@ -32,8 +21,6 @@ tests/*/vendor/*
|
||||
!/data/.htaccess
|
||||
!/data/index.php
|
||||
!/data/web.config
|
||||
!/data/exclude.txt
|
||||
!/data/.compilation-symlinks
|
||||
|
||||
# iTop extensions
|
||||
/extensions/**
|
||||
@@ -47,12 +34,6 @@ tests/*/vendor/*
|
||||
!/log/index.php
|
||||
!/log/web.config
|
||||
|
||||
# NPM: `jquery-ui` package is just there for vulnerability scans, so we don't want to version its files (only `jquery-ui-dist` is used within the code base)
|
||||
/node_modules/jquery-ui/**
|
||||
|
||||
# Symfony: Local env file
|
||||
/resources/symfony/.env.local
|
||||
|
||||
# PHPUnit: Cache file, local XML working copies
|
||||
/tests/php-unit-tests/.phpunit.result.cache
|
||||
/tests/php-unit-tests/phpunit.xml
|
||||
@@ -156,10 +137,3 @@ local.properties
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
# Mac
|
||||
.DS_Store
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ $iBeginTime = time();
|
||||
chdir(__DIR__);
|
||||
|
||||
$aCommands = [
|
||||
'php composer/rmUnnecessaryFolders.php',
|
||||
'php composer/rmDeniedTestDir.php',
|
||||
'php build/commands/setupCssCompiler.php',
|
||||
// 'bash /tmp/gabuzomeu.sh',
|
||||
];
|
||||
@@ -22,13 +22,13 @@ $iElapsed = time() - $iBeginTime;
|
||||
|
||||
if (count($aFailedCommands))
|
||||
{
|
||||
fwrite(STDERR, "\nafterBuild execution failed! (in {$iElapsed}s)\n");
|
||||
fwrite(STDERR, "\nafterBuild execution failed! (in ${iElapsed}s)\n");
|
||||
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
echo "\nDone ({$iElapsed}s)\n";
|
||||
echo "\nDone (${iElapsed}s)\n";
|
||||
exit(0);
|
||||
|
||||
/**
|
||||
@@ -74,7 +74,7 @@ function ExecCommand($cmd) {
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "| elapsed:{$iElapsed}s \n";
|
||||
echo "| elapsed:${iElapsed}s \n";
|
||||
}
|
||||
|
||||
if (!empty($stderr))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -19,23 +19,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Alias for `composer show -loD`
|
||||
* You can also use `composer outdated -D`
|
||||
*
|
||||
* @link https://getcomposer.org/doc/03-cli.md#show
|
||||
*/
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
|
||||
$iTopFolder = __DIR__."/../../../";
|
||||
|
||||
require_once("$iTopFolder/approot.inc.php");
|
||||
require_once ("$iTopFolder/approot.inc.php");
|
||||
$sApproot = APPROOT;
|
||||
$aTrace = array();
|
||||
|
||||
$aParamsConfig = array(
|
||||
'composer-path' => array(
|
||||
'default' => 'composer',
|
||||
),
|
||||
'default' => 'composer.phar',
|
||||
)
|
||||
);
|
||||
$aParamsConfigNotFound = array_flip(array_keys($aParamsConfig));
|
||||
$aGivenArgs = $argv;
|
||||
73
.make/composer/rmDeniedTestDir.php
Normal file
73
.make/composer/rmDeniedTestDir.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Composer\iTopComposer;
|
||||
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
|
||||
require_once ("$iTopFolder/approot.inc.php");
|
||||
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
||||
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
throw new \Exception('This script can only run from CLI');
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
|
||||
|
||||
echo "\n";
|
||||
foreach ($aDeniedButStillPresent as $sDir)
|
||||
{
|
||||
if (false === iTopComposer::IsTestDir($sDir))
|
||||
{
|
||||
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
||||
throw new \Exception("$sDir must end with /Test/ or /test/");
|
||||
}
|
||||
|
||||
if (false === file_exists($sDir)) {
|
||||
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
SetupUtils::rrmdir($sDir);
|
||||
echo "OK Remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
echo "\nFAILED to remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oiTopComposer->ListAllowedTestDir(),
|
||||
$oiTopComposer->ListDeniedTestDir()
|
||||
);
|
||||
$aExistingDirs = $oiTopComposer->ListAllTestDir();
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
if (false === empty($aMissing)) {
|
||||
echo "Some new tests dirs exists !\n"
|
||||
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
courier.php
|
||||
courierb.php
|
||||
courierbi.php
|
||||
courieri.php
|
||||
dejavusans.ctg.z
|
||||
dejavusans.php
|
||||
dejavusans.z
|
||||
dejavusansb.ctg.z
|
||||
dejavusansb.php
|
||||
dejavusansb.z
|
||||
dejavusansbi.ctg.z
|
||||
dejavusansbi.php
|
||||
dejavusansbi.z
|
||||
dejavusanscondensed.ctg.z
|
||||
dejavusanscondensed.php
|
||||
dejavusanscondensed.z
|
||||
dejavusanscondensedb.ctg.z
|
||||
dejavusanscondensedb.php
|
||||
dejavusanscondensedb.z
|
||||
dejavusanscondensedbi.ctg.z
|
||||
dejavusanscondensedbi.php
|
||||
dejavusanscondensedbi.z
|
||||
dejavusanscondensedi.ctg.z
|
||||
dejavusanscondensedi.php
|
||||
dejavusanscondensedi.z
|
||||
dejavusansextralight.ctg.z
|
||||
dejavusansextralight.php
|
||||
dejavusansextralight.z
|
||||
dejavusansi.ctg.z
|
||||
dejavusansi.php
|
||||
dejavusansi.z
|
||||
dejavusansmono.ctg.z
|
||||
dejavusansmono.php
|
||||
dejavusansmono.z
|
||||
dejavusansmonob.ctg.z
|
||||
dejavusansmonob.php
|
||||
dejavusansmonob.z
|
||||
dejavusansmonobi.ctg.z
|
||||
dejavusansmonobi.php
|
||||
dejavusansmonobi.z
|
||||
dejavusansmonoi.ctg.z
|
||||
dejavusansmonoi.php
|
||||
dejavusansmonoi.z
|
||||
droidsansfallback.ctg.z
|
||||
droidsansfallback.php
|
||||
droidsansfallback.z
|
||||
helvetica.php
|
||||
helveticab.php
|
||||
helveticabi.php
|
||||
helveticai.php
|
||||
symbol.php
|
||||
times.php
|
||||
timesb.php
|
||||
timesbi.php
|
||||
timesi.php
|
||||
zapfdingbats.php
|
||||
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This script will copy custom fonts in the TCPDF lib fonts directory.
|
||||
* If you need to add other files :
|
||||
* - add the corresponding files in this script directory
|
||||
* - modify this script to copy also your files
|
||||
*
|
||||
* @since 2.7.0 N°1947 add DroidSansFallback font (see also PR #49 in the links below)
|
||||
* @since 2.7.0 N°2435 TCPPDF lib forked and added in composer.json (at that time the lib was announced as deprecated and rewritten in tecnickcom/tc-lib-pdf)
|
||||
* @since 3.2.0 N°7175 switch back to TCPDF original lib (which is finally still maintained, tecnickcom/tc-lib-pdf us still under dev), script creation to keep custom DroidSansFallback font
|
||||
*
|
||||
* @link https://github.com/Combodo/iTop/pull/49 add DroidSansFallback font
|
||||
* @link https://github.com/tecnickcom/TCPDF?tab=readme-ov-file#note TCPDF is in support only mode
|
||||
*/
|
||||
|
||||
$sItopRootFolder = realpath(__DIR__ . "/../../../../");
|
||||
$sCurrentScriptFileName = basename(__FILE__);
|
||||
|
||||
|
||||
require_once ("$sItopRootFolder/lib/autoload.php");
|
||||
|
||||
|
||||
$sTcPdfRootFolder = $sItopRootFolder.'/lib/tecnickcom/tcpdf';
|
||||
if (false === file_exists($sTcPdfRootFolder)) {
|
||||
echo $sCurrentScriptFileName.": No TCPDF lib detected, exiting !\n";
|
||||
return;
|
||||
}
|
||||
$sTcPdfFontsFolder = $sTcPdfRootFolder.'/fonts/';
|
||||
|
||||
|
||||
/**
|
||||
* 1) Cleaning up the fonts directory to keep only the ones we want in iTop
|
||||
*/
|
||||
echo $sCurrentScriptFileName.": ---1) Cleaning up the fonts files\n";
|
||||
$aTcpdfDefaultFontsToKeepInItop = file(__DIR__.'/tcpdfDefaultFontsToKeepInItop.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
|
||||
$aTcpdfFontsDirContent = scandir($sTcPdfFontsFolder);
|
||||
foreach ($aTcpdfFontsDirContent as $sTcpdfFontResourceName) {
|
||||
if ($sTcpdfFontResourceName === '.') {
|
||||
continue;
|
||||
}
|
||||
if ($sTcpdfFontResourceName === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_array($sTcpdfFontResourceName, $aTcpdfDefaultFontsToKeepInItop, true)) {
|
||||
echo $sCurrentScriptFileName.": Removing $sTcpdfFontResourceName !\n";
|
||||
|
||||
$sTcpdfFontResourceFullPath = $sTcPdfFontsFolder.$sTcpdfFontResourceName;
|
||||
if (is_file($sTcpdfFontResourceFullPath)) {
|
||||
unlink($sTcpdfFontResourceFullPath);
|
||||
} elseif (is_dir($sTcpdfFontResourceFullPath)) {
|
||||
rrmdir($sTcpdfFontResourceFullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 2) Then adding the DroidSansFallback font (useful for CJK data for example)
|
||||
*/
|
||||
echo $sCurrentScriptFileName.": ---2) Copying font files to TCPDF ($sTcPdfFontsFolder)...\n";
|
||||
$aFontFilesToCopy = glob(__DIR__.'\droidsansfallback.*');
|
||||
foreach ($aFontFilesToCopy as $sFontFileToCopy) {
|
||||
$sFontFileName = basename($sFontFileToCopy);
|
||||
echo $sCurrentScriptFileName.': copying '.$sFontFileName."\n";
|
||||
copy($sFontFileToCopy, $sTcPdfFontsFolder.$sFontFileName);
|
||||
}
|
||||
echo $sCurrentScriptFileName.": Done !\n";
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Recursively delete a directory and its content
|
||||
*
|
||||
* @param $sDirToRemovePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function rrmdir($sDirToRemovePath):void
|
||||
{
|
||||
if (is_dir($sDirToRemovePath)) {
|
||||
$objects = scandir($sDirToRemovePath);
|
||||
foreach ($objects as $object) {
|
||||
if ($object != "." && $object != "..") {
|
||||
if (filetype($sDirToRemovePath."/".$object) == "dir") {
|
||||
rrmdir($sDirToRemovePath."/".$object);
|
||||
} else {
|
||||
unlink($sDirToRemovePath."/".$object);
|
||||
}
|
||||
}
|
||||
}
|
||||
reset($objects);
|
||||
rmdir($sDirToRemovePath);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensure that the files for folder browsing protection (.htaccess, web.config) are kept after an "npm install/update" command
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__."/../../../";
|
||||
|
||||
require_once("$iTopFolder/approot.inc.php");
|
||||
|
||||
$sDependenciesRootFolderAbsPath = APPROOT . "node_modules/";
|
||||
$aFilesToCheck = [
|
||||
".htaccess",
|
||||
"web.config",
|
||||
];
|
||||
|
||||
echo "This command aims at ensuring that folder browsing protection files (.htaccess, web.config) are present in the dependencies folder even after an install/upgrade command\n";
|
||||
echo "Checking files:\n";
|
||||
|
||||
foreach($aFilesToCheck as $sFileToCheck) {
|
||||
if (file_exists($sDependenciesRootFolderAbsPath . $sFileToCheck)) {
|
||||
echo "✔️ $sFileToCheck is present\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// If missing, copy the one from /lib as it contains the necessary allow/deny directives for third-parties
|
||||
copy(APPROOT . "lib/$sFileToCheck", $sDependenciesRootFolderAbsPath . $sFileToCheck);
|
||||
echo "✔️ $sFileToCheck was missing and has been re-created\n";
|
||||
}
|
||||
|
||||
// Ensure separation with following scripts
|
||||
echo "\n";
|
||||
@@ -1,100 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
|
||||
require_once ("$iTopFolder/approot.inc.php");
|
||||
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
||||
|
||||
if (php_sapi_name() !== 'cli')
|
||||
{
|
||||
throw new \Exception('This script can only run from CLI');
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
// Read params
|
||||
$key = array_search("--manager", $argv);
|
||||
if (false === $key || false === isset($argv[$key + 1]) ) {
|
||||
throw new \InvalidArgumentException("Usage: " . __FILE__ . " --manager composer|npm");
|
||||
}
|
||||
$sDependenciesHandlerCode = $argv[$key + 1];
|
||||
|
||||
switch ($sDependenciesHandlerCode) {
|
||||
case "composer":
|
||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\Composer\iTopComposer::class;
|
||||
break;
|
||||
|
||||
case "npm":
|
||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\NPM\iTopNPM::class;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception("Invalid dependencies handler code, $sDependenciesHandlerCode given, expected composer|npm");
|
||||
}
|
||||
|
||||
// Start handler
|
||||
$oDependenciesHandler = new $sDependenciesHandlerFQCN();
|
||||
$aDeniedButStillPresent = $oDependenciesHandler->ListDeniedButStillPresentFilesAbsPaths();
|
||||
|
||||
echo "\n";
|
||||
foreach ($aDeniedButStillPresent as $sDir)
|
||||
{
|
||||
if (false === $oDependenciesHandler::IsQuestionnableFile($sDir))
|
||||
{
|
||||
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
||||
throw new \RuntimeException("$sDir is in the denied list but doesn't comply with the rule (see IsQuestionnableFolder method)");
|
||||
}
|
||||
|
||||
if (false === file_exists($sDir)) {
|
||||
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if(is_dir($sDir)){
|
||||
SetupUtils::rrmdir($sDir);
|
||||
}
|
||||
else{
|
||||
unlink($sDir);
|
||||
}
|
||||
echo "✔️ Remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
echo "\n❌ FAILED to remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oDependenciesHandler->ListAllowedFilesAbsPaths(),
|
||||
$oDependenciesHandler->ListDeniedFilesAbsPaths()
|
||||
);
|
||||
$aExistingDirs = $oDependenciesHandler->ListAllFilesAbsPaths();
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
if (false === empty($aMissing)) {
|
||||
echo "Some new tests dirs exists !\n"
|
||||
." They must be declared either in the allowed or denied list in {$sDependenciesHandlerFQCN}\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true)."\n";
|
||||
}
|
||||
|
||||
// Ensure separation with following scripts
|
||||
echo "\n";
|
||||
@@ -1,13 +0,0 @@
|
||||
# Git hooks for iTop
|
||||
|
||||
## ❓ Goal
|
||||
|
||||
Those [git hooks](https://git-scm.com/docs/githooks) aims to ease developing on [iTop](https://github.com/Combodo/iTop).
|
||||
|
||||
## ☑ Available hooks
|
||||
|
||||
* pre-commit : rejects commit if you have at least one SCSS file staged, and no CSS file
|
||||
|
||||
## ⚙ Install
|
||||
|
||||
Just run install.php !
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
$aHooks = [
|
||||
'pre-commit.php',
|
||||
];
|
||||
|
||||
$sAppRoot = dirname(__DIR__, 2);
|
||||
|
||||
|
||||
foreach ($aHooks as $sSourceHookFileName) {
|
||||
echo "Processing for `{$sSourceHookFileName}`...\n";
|
||||
$sSourceHookPath = __DIR__.DIRECTORY_SEPARATOR.$sSourceHookFileName;
|
||||
|
||||
$aPathParts = pathinfo($sSourceHookFileName);
|
||||
$sTargetHookPath = $sAppRoot.DIRECTORY_SEPARATOR.'.git'.DIRECTORY_SEPARATOR.'hooks'.DIRECTORY_SEPARATOR.$aPathParts['filename'];
|
||||
|
||||
if (file_exists($sTargetHookPath) || is_link($sTargetHookPath)) {
|
||||
echo "Existing $sTargetHookPath ! Removing...";
|
||||
unlink($sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
echo "Creating symlink for hook in $sTargetHookPath...";
|
||||
symlink($sSourceHookPath, $sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
/**
|
||||
* Reject any commit containing .scss files, but no .css file !
|
||||
*/
|
||||
|
||||
echo "Checking files staged...\n";
|
||||
$sFilesToCommit = shell_exec('git diff --cached --name-only --diff-filter=ACMRT');
|
||||
$aFilesToCommit = explode("\n", $sFilesToCommit);
|
||||
|
||||
$aScssFiles = GetFilesWithExtension('scss', $aFilesToCommit);
|
||||
if (count($aScssFiles) === 0) {
|
||||
echo "No scss file : OK to go !\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$aCssFiles = GetFilesWithExtension('css', $aFilesToCommit);
|
||||
if (count($aCssFiles) === 0) {
|
||||
echo "There are SCSS files staged but no CSS file : REJECTING commit.\n";
|
||||
echo "You must add the compiled SCSS files by running the setup !\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "We have SCSS but also CSS => OK to commit !\n";
|
||||
exit(0);
|
||||
|
||||
|
||||
|
||||
function GetFilesWithExtension($sExtension, $aFiles) {
|
||||
return array_filter(
|
||||
$aFiles,
|
||||
function($item) use ($sExtension) {
|
||||
return (endsWith($item, '.'.$sExtension));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function endsWith( $haystack, $needle ) {
|
||||
$length = strlen( $needle );
|
||||
if( !$length ) {
|
||||
return true;
|
||||
}
|
||||
return substr( $haystack, -$length ) === $needle;
|
||||
}
|
||||
|
||||
function exitWithMessage($sMessage, $iCode) {
|
||||
echo $sMessage;
|
||||
exit($iCode);
|
||||
}
|
||||
@@ -25,6 +25,7 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php');
|
||||
/** @var \FileVersionUpdater[] $aFilesUpdaters */
|
||||
$aFilesUpdaters = array(
|
||||
new iTopVersionFileUpdater(),
|
||||
new CssVariablesFileUpdater(),
|
||||
new DatamodelsModulesFiles(),
|
||||
new ConstantFileUpdater('ITOP_CORE_VERSION', 'approot.inc.php'),
|
||||
);
|
||||
|
||||
@@ -6,19 +6,11 @@
|
||||
* Will update version in the following files :
|
||||
*
|
||||
* datamodels/2.x/.../datamodel.*.xml
|
||||
* application/*.xml
|
||||
* core/*.xml
|
||||
*
|
||||
* Usage :
|
||||
* `php .make\release\update-xml.php "1.7"`
|
||||
* `php .make\release\update-xml.php`
|
||||
*
|
||||
* If no parameter provided then the current XML version will be used as target version
|
||||
*
|
||||
* @since 2.7.0 simple version change using regexp (not doing conversion)
|
||||
* @since 3.1.0 N°5405 now does a real conversion
|
||||
* @since 3.1.0 N°5633 allow to use without parameter
|
||||
* @since 3.1.0 N°5633 add /application and /core XML files
|
||||
* @since 2.7.0
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
@@ -30,12 +22,10 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php');
|
||||
|
||||
if (count($argv) === 1)
|
||||
{
|
||||
echo '/!\ No version passed: assuming target XML version is current XML version ('.ITOP_DESIGN_LATEST_VERSION.")\n";
|
||||
$sVersionLabel = ITOP_DESIGN_LATEST_VERSION;
|
||||
} else {
|
||||
$sVersionLabel = $argv[1];
|
||||
echo '/!\ You must pass the new version as parameter';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$sVersionLabel = $argv[1];
|
||||
if (empty($sVersionLabel))
|
||||
{
|
||||
echo 'Version passed as parameter is empty !';
|
||||
|
||||
@@ -123,33 +123,38 @@ class iTopVersionFileUpdater extends AbstractSingleFileVersionUpdater
|
||||
}
|
||||
}
|
||||
|
||||
class CssVariablesFileUpdater extends AbstractSingleFileVersionUpdater
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('css/css-variables.scss');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
|
||||
{
|
||||
return preg_replace(
|
||||
'/(\$version: "v)[^"]*(";)/',
|
||||
'${1}'.$sVersionLabel.'${2}',
|
||||
$sFileContent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractGlobFileVersionUpdater extends FileVersionUpdater
|
||||
{
|
||||
/** @var array|string glob patterns to seek for files to modify */
|
||||
protected $globPattern;
|
||||
protected $sGlobPattern;
|
||||
|
||||
public function __construct($globPattern)
|
||||
public function __construct($sGlobPattern)
|
||||
{
|
||||
$this->globPattern = $globPattern;
|
||||
$this->sGlobPattern = $sGlobPattern;
|
||||
}
|
||||
|
||||
public function GetFiles()
|
||||
{
|
||||
$aGlobPatterns = (is_array($this->globPattern))
|
||||
? $this->globPattern
|
||||
: [$this->globPattern];
|
||||
|
||||
$aFiles = [];
|
||||
foreach ($aGlobPatterns as $sGlobPattern) {
|
||||
$result = glob($sGlobPattern);
|
||||
if (false === $result) {
|
||||
continue;
|
||||
}
|
||||
/** @noinspection SlowArrayOperationsInLoopInspection */
|
||||
$aFiles = array_merge($aFiles, $result);
|
||||
}
|
||||
|
||||
return $aFiles;
|
||||
return glob($this->sGlobPattern);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,11 +186,7 @@ class DatamodelsXmlFiles extends AbstractGlobFileVersionUpdater
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
APPROOT.'datamodels/2.x/*/datamodel.*.xml',
|
||||
APPROOT.'application/*.xml',
|
||||
APPROOT.'core/*.xml',
|
||||
]);
|
||||
parent::__construct(APPROOT.'datamodels/2.x/*/datamodel.*.xml');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,40 +194,10 @@ class DatamodelsXmlFiles extends AbstractGlobFileVersionUpdater
|
||||
*/
|
||||
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
|
||||
{
|
||||
require_once APPROOT.'setup/itopdesignformat.class.inc.php';
|
||||
$oFileXml = new DOMDocument();
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
libxml_clear_errors();
|
||||
$oFileXml->formatOutput = true;
|
||||
$oFileXml->preserveWhiteSpace = false;
|
||||
$oFileXml->loadXML($sFileContent, LIBXML_BIGLINES);
|
||||
|
||||
$oFileItopFormat = new iTopDesignFormat($oFileXml);
|
||||
|
||||
$sDesignVersionToSet = static::GetDesignVersionToSet($oFileItopFormat->GetVersion());
|
||||
if (false === is_null($sDesignVersionToSet)) {
|
||||
// N°5779 if same as target version, we will try to convert from version below
|
||||
$oFileItopFormat->GetITopDesignNode()->setAttribute('version', $sDesignVersionToSet);
|
||||
}
|
||||
|
||||
$bConversionResult = $oFileItopFormat->Convert($sVersionLabel);
|
||||
|
||||
if (false === $bConversionResult) {
|
||||
throw new Exception("Error when converting $sFileFullPath");
|
||||
}
|
||||
|
||||
return $oFileItopFormat->GetXmlAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?string version to use : if file version is same as current version then return previous version, else return null
|
||||
* @since 3.1.0 N°5779
|
||||
*/
|
||||
protected static function GetDesignVersionToSet($sFileDesignVersion):?string {
|
||||
if ($sFileDesignVersion !== ITOP_DESIGN_LATEST_VERSION) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return iTopDesignFormat::GetPreviousDesignVersion(ITOP_DESIGN_LATEST_VERSION);
|
||||
return preg_replace(
|
||||
'/(<itop_design .* version=")[^"]+(">)/',
|
||||
'${1}'.$sVersionLabel.'${2}',
|
||||
$sFileContent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,11 @@ If you have an idea you're sure would benefit to all of iTop users, you may
|
||||
[create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) to submit it, but be warned that there are lots of good
|
||||
reasons to refuse such changes.
|
||||
|
||||
### 📄 License and copyright
|
||||
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file).
|
||||
### 📄 License
|
||||
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file),
|
||||
your code must comply with this license.
|
||||
|
||||
The iTop repository is divided in three parts: iTop (mainly PHP/JS/XML sources and dictionaries), images, and third-party libraries.
|
||||
Combodo has the copyright on most of the source files in the iTop part of the repository: please do not modify the existing file copyrights.
|
||||
Anyhow, you are encouraged to signal your contribution by the mean of `@author` annotations.
|
||||
|
||||
If you want to use another license or keep the code ownership (copyright), you may [create an extension][wiki new ext].
|
||||
If you want to use another license, you may [create an extension][wiki new ext].
|
||||
|
||||
[license.txt]: https://github.com/Combodo/iTop/blob/develop/license.txt
|
||||
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
|
||||
@@ -45,7 +42,7 @@ If you want to use another license or keep the code ownership (copyright), you m
|
||||
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
|
||||
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
|
||||
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
|
||||
we don't have a `master` branch anymore.
|
||||
we don't have anymore a `master` branch.
|
||||
|
||||
Here are the branches we use and their meaning :
|
||||
|
||||
@@ -55,26 +52,26 @@ Here are the branches we use and their meaning :
|
||||
|
||||
For example, if no version is currently prepared for shipping we could have:
|
||||
|
||||
- `develop` containing future 3.1.0 version
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `develop` containing future 2.8.0 version
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
In this example, when 3.1.0-beta is shipped that will become:
|
||||
In this example, when 2.8.0-beta is shipped that will become:
|
||||
|
||||
- `develop`: future 3.2.0 version
|
||||
- `release/3.1.0`: 3.1.0-beta
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `develop`: future 2.9.0 version
|
||||
- `release/2.8`: 2.8.0-beta
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
And when 3.1.0 final will be out:
|
||||
And when 2.8.0 final will be out:
|
||||
|
||||
- `develop`: future 3.2.0 version
|
||||
- `support/3.1`: 3.1.x maintenance version (will host developments for 3.1.1)
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `develop`: future 2.9.0 version
|
||||
- `support/2.8`: 2.8.x maintenance version (will host developments for 2.8.1)
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
Also note that we have a "micro-version" concept : each of those versions have a very small amount of modifications. They are made from
|
||||
`support/*` branches as well. For example 2.6.2-1 and 2.6.2-2 were made from the `support/2.6.2` branch.
|
||||
@@ -128,37 +125,15 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* ⬆️ `:arrow_up:` when upgrading dependencies
|
||||
* ⬇️ `:arrow_down:` when downgrading dependencies
|
||||
* ♻️ `:recycle:` code refactoring
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
|
||||
|
||||
## 👥 Pull request
|
||||
|
||||
When your code is working, please:
|
||||
|
||||
* Squash as much as possible your commits,
|
||||
* Rebase your branch on our repo last commit,
|
||||
* Create a pull request. _Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)_.
|
||||
* Pull request description: mind to add all the information useful to understand why you're suggesting this modification and anything necessary to dive into your work. Especially:
|
||||
- Bugfixes: exact steps to reproduce the bug (given/when/then), description of the bug cause and what solution is implemented
|
||||
- Enhancements: use cases, implementation details if needed
|
||||
* Mind to check the "[Allow edits from maintainers](https://docs.github.com/en/github-ae@latest/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)" option ! (note that if you are working with an org fork, this option [won't be available](https://github.com/orgs/community/discussions/5634))
|
||||
* squash as much as possible your commits,
|
||||
* rebase your branch on our repo last commit,
|
||||
* create a pull request.
|
||||
|
||||
|
||||
## 🙏 We are thankful
|
||||
|
||||
We are thankful for all your contributions to the iTop universe! As a thank you gift, we will send stickers to every iTop (& extensions) contributors!
|
||||
|
||||
We have one sticker per contribution type. You might get multiple stickers with one contribution though :)
|
||||
|
||||
* Bug hunter: Fix a bug
|
||||
* Translator: Add/update translations
|
||||
* White hat: Find and/or fix a vulnerability
|
||||
* Contributor: Contribute by finding a bug, making an extension or any other way
|
||||
* Partner: For Combodo's official partners
|
||||
* Graduated: Follow a Combodo's iTop training
|
||||
* Ambassador: Outstanding community contributors
|
||||
* Beta tester: Test and give feedback on beta releases
|
||||
* Extension developer: Develop and publish an extension
|
||||
|
||||
Here is the design of each stickers for year 2024:
|
||||
|
||||

|
||||
Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
||||
|
||||
133
README.md
133
README.md
@@ -1,15 +1,13 @@
|
||||
<p align="center"><a href="https://www.combodo.com/itop-193" 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>
|
||||
<img src="https://www.combodo.com/logos/logo-itop.svg">
|
||||
</a></p>
|
||||
|
||||
|
||||
iTop stands for IT Operations Portal. It is a complete open source and web-based IT service management platform, including a fully customizable CMDB, a helpdesk system, and a document management tool. It is ITIL compliant and easily customizable and extensible thanks to a high number of add-ons and web services to integrate with your IT.
|
||||
|
||||
iTop also offers mass import tools to help you become even more efficient.
|
||||
# iTop - ITSM & CMDB
|
||||
|
||||
iTop stands for *IT Operations Portal*.
|
||||
It is a complete open source, ITIL, web based service management tool including a fully customizable CMDB, a helpdesk system and a document management tool.
|
||||
iTop also offers mass import tools and web services to integrate with your IT
|
||||
|
||||
## Features
|
||||
- Fully configurable [Configuration Management (CMDB)][10]
|
||||
@@ -25,10 +23,10 @@ iTop also offers mass import tools to help you become even more efficient.
|
||||
|
||||
## Latest release
|
||||
|
||||
- [Changes since the previous version][62]
|
||||
- [New features][63]
|
||||
- [Installation notes][64]
|
||||
- [Download][65]
|
||||
- [Changes since the previous version][62]
|
||||
- [New features][63]
|
||||
- [Installation notes][64]
|
||||
- [Download][65]
|
||||
|
||||
[62]: https://www.itophub.io/wiki/page?id=latest:release:change_log
|
||||
[63]: https://www.itophub.io/wiki/page?id=latest:release:start
|
||||
@@ -41,19 +39,16 @@ iTop also offers mass import tools to help you become even more efficient.
|
||||
- [iTop Forums][1]: community support
|
||||
- [iTop Tickets][2]: for feature requests and bug reports
|
||||
- [Releases download][3]
|
||||
- [iTop requirements][4]
|
||||
- [Documentation][5] covering both iTop and its official extensions
|
||||
- [iTop Hub][6] : discover and install extensions !
|
||||
- [iTop versions history][7]
|
||||
- [Documentation][4] covering both iTop and its official extensions
|
||||
- [iTop Hub][5] : discover and install extensions !
|
||||
|
||||
|
||||
|
||||
[1]: https://sourceforge.net/p/itop/discussion/
|
||||
[2]: https://sourceforge.net/p/itop/tickets/
|
||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||
[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
|
||||
[4]: https://www.itophub.io/wiki
|
||||
[5]: https://store.itophub.io/en_US/
|
||||
|
||||
[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
|
||||
@@ -69,76 +64,58 @@ iTop also offers mass import tools to help you become even more efficient.
|
||||
|
||||
## About Us
|
||||
|
||||
iTop development is sponsored, led, and supported by [Combodo][0].
|
||||
iTop development is sponsored, led and supported by [Combodo][0].
|
||||
|
||||
[0]: https://www.combodo.com
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
We would like to give a special thank you 🤗 to the people from the community who contributed to this project, including:
|
||||
We would like to give a special thank you to the people from the community who contributed to this project, including:
|
||||
|
||||
### Names
|
||||
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
|
||||
- Bilger, Jean-François
|
||||
- Bostoen, Jeffrey (a.k.a [@jbostoen](https://www.github.com/jbostoen))
|
||||
- Cardoso, Anderson
|
||||
- Cassaro, Bruno
|
||||
- Casteleyn, Thomas (a.k.a [@Hipska](https://www.github.com/Hipska))
|
||||
- Castro, Randall Badilla
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dejin, Bie (a.k.a [@bdejin](https://github.com/bdejin))
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Gumble, David
|
||||
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
|
||||
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Bilger, Jean-François
|
||||
- Bostoen, Jeffrey
|
||||
- Cardoso, Anderson
|
||||
- Cassaro, Bruno
|
||||
- Casteleyn, Thomas
|
||||
- Castro, Randall Badilla
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Gumble, David
|
||||
- Hippler, Lars
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Malik, Remie
|
||||
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
|
||||
- Mozart de Oliveira, Eduardo (a.k.a [@eduardomozart](https://github.com/eduardomozart))
|
||||
- Raenker, Martin
|
||||
- Roháč, Richard (a.k.a [@RohacRichard](https://github.com/RohacRichard))
|
||||
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||
- Rosenke, Stephan
|
||||
- Rossi, Tommaso (a.k.a [@tomrss](https://www.github.com/tomrss))
|
||||
- Rudner, Björn (a.k.a [@rudnerbjoern](https://github.com/rudnerbjoern))
|
||||
- Šafránek, Jaroslav (a.k.a [jkcinik](https://sourceforge.net/u/jkcinik/profile/) on SourceForge)
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Stetina, Pavel (a.k.a [@Stetinac](https://github.com/Stetinac))
|
||||
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
|
||||
- Tarjányi, Csaba (a.k.a [@tacsaby](https://github.com/tacsaby))
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
- Vlk, Karel (a.k.a [@vlk-charles](https://www.github.com/vlk-charles))
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
|
||||
### Aliases
|
||||
|
||||
- chifu1234
|
||||
- cprobst
|
||||
- DudekArtur
|
||||
- Karkoff1212
|
||||
- Laura
|
||||
- nv35
|
||||
- Purple Grape
|
||||
- Schlobinux
|
||||
- theBigOne
|
||||
- ulmerspatz
|
||||
- chifu1234
|
||||
- cprobst
|
||||
- Karkoff1212
|
||||
- larhip
|
||||
- Laura
|
||||
- Purple Grape
|
||||
- Schlobinux
|
||||
- theBigOne
|
||||
- ulmerspatz
|
||||
|
||||
### Companies
|
||||
|
||||
- [Hardis](https://www.hardis-group.com/)
|
||||
- [ITOMIG](https://www.itomig.de/)
|
||||
- [Pimkie](https://www.pimkie.com/)
|
||||
- [Super-Visions](https://www.super-visions.com/)
|
||||
- Hardis
|
||||
- ITOMIG
|
||||
- Pimkie
|
||||
|
||||
|
||||
14
SECURITY.md
14
SECURITY.md
@@ -9,7 +9,7 @@ responsible disclosure and will make every effort to acknowledge your contributi
|
||||
### iTop vulnerabilities
|
||||
Please send a procedure to reproduce iTop vulnerabilities to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
||||
|
||||
You can send us a standard "given / when / then" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||
You can send us a standard "given / then / when" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||
needed to reproduce.
|
||||
|
||||
### Dependencies vulnerabilities
|
||||
@@ -18,7 +18,8 @@ to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
||||
|
||||
|
||||
|
||||
## 🔍 Combodo acknowledgment and investigation
|
||||
## 📆 Disclosure Policy
|
||||
|
||||
Report sent to us will be acknowledged within the week.
|
||||
|
||||
Then, a Combodo developer will be assigned to the reported issue and will:
|
||||
@@ -33,12 +34,3 @@ Then, a Combodo developer will be assigned to the reported issue and will:
|
||||
Security issues always take precedence over bug fixes and feature work.
|
||||
|
||||
The assignee will keep you informed of the resolution progress, and may ask you for additional information or guidance.
|
||||
|
||||
|
||||
## 📆 Disclosure Policy
|
||||
Once the fix is done and acknowledged by every stakeholder, it will be included in the next iTop version.
|
||||
Mind we have at least 2 active branches (LTS and STS, see [iTop Community Releases [iTop Documentation]](https://www.itophub.io/wiki/page?id=latest:release:start))
|
||||
|
||||
The release communications will include the information of the vulnerability fix.
|
||||
|
||||
Corresponding GitHub advisories and CVE will be published 3 months after the iTop version release date so that iTop instances can be updated.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// 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.
|
||||
@@ -20,33 +19,34 @@
|
||||
/**
|
||||
* UserRightsMatrix (User management Module)
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class UserRightsMatrixClassGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => [],
|
||||
"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", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new 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", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new 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())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,25 +54,25 @@ class UserRightsMatrixClassStimulusGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => [],
|
||||
"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", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new 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", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new 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())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,44 +80,48 @@ class UserRightsMatrixAttributeGrant extends DBObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => [],
|
||||
"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", ["targetclass" => "User", "jointype" => "", "allowed_values" => null, "sql" => "userid", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", ["allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login"]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("class", ["allowed_values" => null, "sql" => "class", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("attcode", ["allowed_values" => null, "sql" => "attcode", "default_value" => null, "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", 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", ["allowed_values" => null, "sql" => "action", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", ["allowed_values" => new ValueSetEnum('yes,no'), "sql" => "permission", "default_value" => "yes", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new 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
|
||||
{
|
||||
public static $m_aActionCodes = [
|
||||
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
|
||||
CMDBObject::SetTrackInfo('Initialization');
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', $sAdminUser);
|
||||
$oUser->Set('password', $sAdminPwd);
|
||||
@@ -146,7 +150,8 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
// 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()) {
|
||||
while ($oUser = $oUserSet->Fetch())
|
||||
{
|
||||
$this->SetupUser($oUser->GetKey());
|
||||
}
|
||||
return true;
|
||||
@@ -154,16 +159,23 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
|
||||
protected function SetupUser($iUserId, $bNewUser = false)
|
||||
{
|
||||
foreach (['bizmodel', 'application', 'gui', 'core/cmdb'] as $sCategory) {
|
||||
foreach (MetaModel::GetClasses($sCategory) as $sClass) {
|
||||
foreach (self::$m_aActionCodes as $iActionCode => $sAction) {
|
||||
if ($bNewUser) {
|
||||
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 {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell) {
|
||||
if ($bAddCell)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
|
||||
$oMyClassGrant->Set("userid", $iUserId);
|
||||
@@ -173,14 +185,19 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
|
||||
if ($bNewUser) {
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
|
||||
{
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddCell = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell) {
|
||||
if ($bAddCell)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
|
||||
$oMyClassGrant->Set("userid", $iUserId);
|
||||
@@ -190,15 +207,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
$iId = $oMyClassGrant->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) {
|
||||
if ($bNewUser) {
|
||||
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
|
||||
{
|
||||
if ($bNewUser)
|
||||
{
|
||||
$bAddCell = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
|
||||
$bAddCell = ($oSet->Count() < 1);
|
||||
}
|
||||
if ($bAddCell) {
|
||||
foreach (['read', 'modify'] as $sAction) {
|
||||
if ($bAddCell)
|
||||
{
|
||||
foreach (array('read', 'modify') as $sAction)
|
||||
{
|
||||
// Create a new entry
|
||||
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
|
||||
$oMyAttGrant->Set("userid", $iUserId);
|
||||
@@ -239,13 +262,14 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public function Init()
|
||||
{
|
||||
// Could be loaded in a shared memory (?)
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||
{
|
||||
$oNullFilter = new DBObjectSearch($sClass);
|
||||
return $oNullFilter;
|
||||
@@ -253,18 +277,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
|
||||
public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
$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) {
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission')) {
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
@@ -278,18 +305,21 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
|
||||
public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
|
||||
{
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes)) {
|
||||
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
$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) {
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission')) {
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
@@ -304,12 +334,14 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
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) {
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
$oGrantRecord = $oSet->Fetch();
|
||||
switch ($oGrantRecord->Get('permission')) {
|
||||
switch ($oGrantRecord->Get('permission'))
|
||||
{
|
||||
case 'yes':
|
||||
$iRetCode = UR_ALLOWED_YES;
|
||||
break;
|
||||
@@ -327,3 +359,5 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
}
|
||||
|
||||
UserRights::SelectModule('UserRightsMatrix');
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// 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.
|
||||
@@ -21,7 +20,7 @@
|
||||
* UserRightsNull
|
||||
* User management Module - say Yeah! to everything
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -48,7 +47,7 @@ class UserRightsNull extends UserRightsAddOnAPI
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = array())
|
||||
{
|
||||
$oNullFilter = new DBObjectSearch($sClass);
|
||||
return $oNullFilter;
|
||||
@@ -75,3 +74,5 @@ class UserRightsNull extends UserRightsAddOnAPI
|
||||
}
|
||||
|
||||
UserRights::SelectModule('UserRightsNull');
|
||||
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
30
app.php
30
app.php
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Kernel;
|
||||
|
||||
require_once __DIR__.'/lib/autoload_runtime.php';
|
||||
|
||||
require_once('approot.inc.php');
|
||||
require_once('application/startup.inc.php');
|
||||
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class DBSearchHelper
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class DBSearchHelper
|
||||
{
|
||||
/**
|
||||
* Add context filter to DBUnionSearch
|
||||
*
|
||||
* @param \DBSearch|null $oSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function AddContextFilter(?DBSearch $oSearch): void
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sClass = $oSearch->GetClass();
|
||||
foreach ($oAppContext->GetNames() as $key) {
|
||||
// Find the value of the object corresponding to each 'context' parameter
|
||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
||||
$sAttCode = '';
|
||||
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)) {
|
||||
// Add Hierarchical condition if hierarchical key
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if (isset($oAttDef) && ($oAttDef->IsExternalKey())) {
|
||||
$iDefaultValue = intval($oAppContext->GetCurrentValue($key));
|
||||
if ($iDefaultValue != 0) {
|
||||
try {
|
||||
/** @var AttributeExternalKey $oAttDef */
|
||||
$sTargetClass = $oAttDef->GetTargetClass();
|
||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass);
|
||||
if ($sHierarchicalKeyCode !== false) {
|
||||
$oFilter = new DBObjectSearch($sTargetClass);
|
||||
$oFilter->AddCondition('id', $iDefaultValue);
|
||||
$oHKFilter = new DBObjectSearch($sTargetClass);
|
||||
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
||||
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// If filtering fails just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
328
application/Html2Text.php
Normal file
328
application/Html2Text.php
Normal file
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
namespace Html2Text;
|
||||
|
||||
if (!function_exists('mb_split'))
|
||||
{
|
||||
function mb_split($pattern, $subject, $limit = -1)
|
||||
{
|
||||
return preg_split('/'.$pattern.'/', $subject, $limit);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Replace all occurrences of the search string with the replacement string.
|
||||
*
|
||||
* @author Sean Murphy <sean@iamseanmurphy.com>
|
||||
* @copyright Copyright 2012 Sean Murphy. All rights reserved.
|
||||
* @license http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* @link http://php.net/manual/function.str-replace.php
|
||||
*
|
||||
* @param mixed $search
|
||||
* @param mixed $replace
|
||||
* @param mixed $subject
|
||||
* @param int $count
|
||||
* @return mixed
|
||||
*/
|
||||
function mb_str_replace($search, $replace, $subject, &$count = 0) {
|
||||
if (!is_array($subject)) {
|
||||
// Normalize $search and $replace so they are both arrays of the same length
|
||||
$searches = is_array($search) ? array_values($search) : array($search);
|
||||
$replacements = is_array($replace) ? array_values($replace) : array($replace);
|
||||
$replacements = array_pad($replacements, count($searches), '');
|
||||
foreach ($searches as $key => $search) {
|
||||
$parts = mb_split(preg_quote($search), $subject);
|
||||
$count += count($parts) - 1;
|
||||
$subject = implode($replacements[$key], $parts);
|
||||
}
|
||||
} else {
|
||||
// Call mb_str_replace for each subject in array, recursively
|
||||
foreach ($subject as $key => $value) {
|
||||
$subject[$key] = mb_str_replace($search, $replace, $value, $count);
|
||||
}
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2010 Jevon Wright and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* or
|
||||
*
|
||||
* LGPL which is available at http://www.gnu.org/licenses/lgpl.html
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Jevon Wright - initial API and implementation
|
||||
* Denis Flaven - some fixes for properly handling UTF-8 characters
|
||||
****************************************************************************/
|
||||
|
||||
class Html2Text {
|
||||
|
||||
/**
|
||||
* Tries to convert the given HTML into a plain text format - best suited for
|
||||
* e-mail display, etc.
|
||||
*
|
||||
* <p>In particular, it tries to maintain the following features:
|
||||
* <ul>
|
||||
* <li>Links are maintained, with the 'href' copied over
|
||||
* <li>Information in the <head> is lost
|
||||
* </ul>
|
||||
*
|
||||
* @param string html the input HTML
|
||||
* @return string the HTML converted, as best as possible, to text
|
||||
* @throws Html2TextException if the HTML could not be loaded as a {@link DOMDocument}
|
||||
*/
|
||||
static function convert($html) {
|
||||
// replace with spaces
|
||||
|
||||
$html = str_replace(" ", " ", $html);
|
||||
$html = mb_str_replace("\xc2\xa0", " ", $html); // DO NOT USE str_replace since it breaks the "à" character which is \xc3 \xa0 in UTF-8
|
||||
|
||||
$html = static::fixNewlines($html);
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
if (!@$doc->loadHTML('<?xml encoding="UTF-8">'.$html)) // Forces the UTF-8 character set for HTML fragments
|
||||
{
|
||||
throw new Html2TextException("Could not load HTML - badly formed?", $html);
|
||||
}
|
||||
|
||||
$output = static::iterateOverNode($doc);
|
||||
|
||||
// remove leading and trailing spaces on each line
|
||||
$output = preg_replace("/[ \t]*\n[ \t]*/im", "\n", $output);
|
||||
$output = preg_replace("/ *\t */im", "\t", $output);
|
||||
|
||||
// remove unnecessary empty lines
|
||||
$output = preg_replace("/\n\n\n*/im", "\n\n", $output);
|
||||
|
||||
// remove leading and trailing whitespace
|
||||
$output = trim($output);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unify newlines; in particular, \r\n becomes \n, and
|
||||
* then \r becomes \n. This means that all newlines (Unix, Windows, Mac)
|
||||
* all become \ns.
|
||||
*
|
||||
* @param string text text with any number of \r, \r\n and \n combinations
|
||||
* @return string the fixed text
|
||||
*/
|
||||
static function fixNewlines($text) {
|
||||
// replace \r\n to \n
|
||||
$text = str_replace("\r\n", "\n", $text);
|
||||
// remove \rs
|
||||
$text = str_replace("\r", "\n", $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
static function nextChildName($node) {
|
||||
// get the next child
|
||||
$nextNode = $node->nextSibling;
|
||||
while ($nextNode != null) {
|
||||
if ($nextNode instanceof \DOMElement) {
|
||||
break;
|
||||
}
|
||||
$nextNode = $nextNode->nextSibling;
|
||||
}
|
||||
$nextName = null;
|
||||
if ($nextNode instanceof \DOMElement && $nextNode != null) {
|
||||
$nextName = strtolower($nextNode->nodeName);
|
||||
}
|
||||
|
||||
return $nextName;
|
||||
}
|
||||
|
||||
static function prevChildName($node) {
|
||||
// get the previous child
|
||||
$nextNode = $node->previousSibling;
|
||||
while ($nextNode != null) {
|
||||
if ($nextNode instanceof \DOMElement) {
|
||||
break;
|
||||
}
|
||||
$nextNode = $nextNode->previousSibling;
|
||||
}
|
||||
$nextName = null;
|
||||
if ($nextNode instanceof \DOMElement && $nextNode != null) {
|
||||
$nextName = strtolower($nextNode->nodeName);
|
||||
}
|
||||
|
||||
return $nextName;
|
||||
}
|
||||
|
||||
static function iterateOverNode($node) {
|
||||
if ($node instanceof \DOMText) {
|
||||
// Replace whitespace characters with a space (equivilant to \s)
|
||||
return preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $node->wholeText);
|
||||
}
|
||||
if ($node instanceof \DOMDocumentType) {
|
||||
// ignore
|
||||
return "";
|
||||
}
|
||||
|
||||
$nextName = static::nextChildName($node);
|
||||
$prevName = static::prevChildName($node);
|
||||
|
||||
$name = strtolower($node->nodeName);
|
||||
|
||||
// start whitespace
|
||||
switch ($name) {
|
||||
case "hr":
|
||||
return "---------------------------------------------------------------\n";
|
||||
|
||||
case "style":
|
||||
case "head":
|
||||
case "title":
|
||||
case "meta":
|
||||
case "script":
|
||||
// ignore these tags
|
||||
return "";
|
||||
|
||||
case "h1":
|
||||
case "h2":
|
||||
case "h3":
|
||||
case "h4":
|
||||
case "h5":
|
||||
case "h6":
|
||||
case "ol":
|
||||
case "ul":
|
||||
// add two newlines, second line is added below
|
||||
$output = "\n";
|
||||
break;
|
||||
|
||||
case "td":
|
||||
case "th":
|
||||
// add tab char to separate table fields
|
||||
$output = "\t";
|
||||
break;
|
||||
|
||||
case "tr":
|
||||
case "p":
|
||||
case "div":
|
||||
// add one line
|
||||
$output = "\n";
|
||||
break;
|
||||
|
||||
case "li":
|
||||
$output = "- ";
|
||||
break;
|
||||
|
||||
default:
|
||||
// print out contents of unknown tags
|
||||
$output = "";
|
||||
break;
|
||||
}
|
||||
|
||||
// debug
|
||||
//$output .= "[$name,$nextName]";
|
||||
|
||||
if (isset($node->childNodes)) {
|
||||
for ($i = 0; $i < $node->childNodes->length; $i++) {
|
||||
$n = $node->childNodes->item($i);
|
||||
|
||||
$text = static::iterateOverNode($n);
|
||||
|
||||
$output .= $text;
|
||||
}
|
||||
}
|
||||
|
||||
// end whitespace
|
||||
switch ($name) {
|
||||
case "h1":
|
||||
case "h2":
|
||||
case "h3":
|
||||
case "h4":
|
||||
case "h5":
|
||||
case "h6":
|
||||
$output .= "\n";
|
||||
break;
|
||||
|
||||
case "p":
|
||||
case "br":
|
||||
// add one line
|
||||
if ($nextName != "div")
|
||||
$output .= "\n";
|
||||
break;
|
||||
|
||||
case "div":
|
||||
// add one line only if the next child isn't a div
|
||||
if ($nextName != "div" && $nextName != null)
|
||||
$output .= "\n";
|
||||
break;
|
||||
|
||||
case "a":
|
||||
// links are returned in [text](link) format
|
||||
$href = $node->getAttribute("href");
|
||||
|
||||
$output = trim($output);
|
||||
|
||||
// remove double [[ ]] s from linking images
|
||||
if (substr($output, 0, 1) == "[" && substr($output, -1) == "]") {
|
||||
$output = substr($output, 1, strlen($output) - 2);
|
||||
|
||||
// for linking images, the title of the <a> overrides the title of the <img>
|
||||
if ($node->getAttribute("title")) {
|
||||
$output = $node->getAttribute("title");
|
||||
}
|
||||
}
|
||||
|
||||
// if there is no link text, but a title attr
|
||||
if (!$output && $node->getAttribute("title")) {
|
||||
$output = $node->getAttribute("title");
|
||||
}
|
||||
|
||||
if ($href == null) {
|
||||
// it doesn't link anywhere
|
||||
if ($node->getAttribute("name") != null) {
|
||||
$output = "[$output]";
|
||||
}
|
||||
} else {
|
||||
if ($href == $output || $href == "mailto:$output" || $href == "http://$output" || $href == "https://$output") {
|
||||
// link to the same address: just use link
|
||||
$output;
|
||||
} else {
|
||||
// replace it
|
||||
if ($output) {
|
||||
$output = "[$output]($href)";
|
||||
} else {
|
||||
// empty string
|
||||
$output = $href;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// does the next node require additional whitespace?
|
||||
switch ($nextName) {
|
||||
case "h1": case "h2": case "h3": case "h4": case "h5": case "h6":
|
||||
$output .= "\n";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case "img":
|
||||
if ($node->getAttribute("title")) {
|
||||
$output = "[" . $node->getAttribute("title") . "]";
|
||||
} elseif ($node->getAttribute("alt")) {
|
||||
$output = "[" . $node->getAttribute("alt") . "]";
|
||||
} else {
|
||||
$output = "";
|
||||
}
|
||||
break;
|
||||
|
||||
case "li":
|
||||
$output .= "\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
28
application/Html2TextException.php
Normal file
28
application/Html2TextException.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2010 Jevon Wright and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* or
|
||||
*
|
||||
* LGPL which is available at http://www.gnu.org/licenses/lgpl.html
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Jevon Wright - initial API and implementation
|
||||
****************************************************************************/
|
||||
|
||||
namespace Html2Text;
|
||||
|
||||
class Html2TextException extends \Exception {
|
||||
var $more_info;
|
||||
|
||||
public function __construct($message = "", $more_info = "") {
|
||||
parent::__construct($message);
|
||||
$this->more_info = $more_info;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,425 @@
|
||||
<?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
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to AjaxPage
|
||||
* 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
|
||||
*/
|
||||
class ajax_page extends AjaxPage
|
||||
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class ajax_page extends WebPage implements iTabbedPage
|
||||
{
|
||||
public function __construct($s_title)
|
||||
/**
|
||||
* Jquery style ready script
|
||||
* @var array
|
||||
*/
|
||||
protected $m_sReadyScript;
|
||||
protected $m_oTabs;
|
||||
private $m_sMenu; // If set, then the menu will be updated
|
||||
|
||||
/**
|
||||
* constructor for the web page
|
||||
*
|
||||
* @param string $s_title Not used
|
||||
*/
|
||||
function __construct($s_title) {
|
||||
$sPrintable = utils::ReadParam('printable', '0');
|
||||
$bPrintable = ($sPrintable == '1');
|
||||
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
$this->m_sReadyScript = "";
|
||||
//$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->no_cache();
|
||||
$this->add_http_headers();
|
||||
$this->m_oTabs = new TabManager();
|
||||
$this->sContentType = 'text/html';
|
||||
$this->sContentDisposition = 'inline';
|
||||
$this->m_sMenu = "";
|
||||
|
||||
utils::InitArchiveMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disabling sending the header so that resource won't be blocked by CORB. See parent method documentation.
|
||||
* @return void
|
||||
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation
|
||||
*/
|
||||
public function add_xcontent_type_options()
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('ajax_page is deprecated. Please use AjaxPage instead');
|
||||
parent::__construct($s_title);
|
||||
// Nothing to do !
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '')
|
||||
{
|
||||
$this->add($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabCode, $sHtml)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabCode, $sHtml));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTab($sTabCode = '', $sTabTitle = null)
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTab($sTabCode, $sTabTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddAjaxTab($sTabCode, $sUrl, $bCache, $sTabTitle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_oTabs->GetCurrentTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function RemoveTab($sTabCode, $sTabContainer = null)
|
||||
{
|
||||
$this->m_oTabs->RemoveTab($sTabCode, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null)
|
||||
{
|
||||
return $this->m_oTabs->FindTab($sPattern, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given tab the active one, as if it were clicked
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*/
|
||||
public function SelectTab($sTabContainer, $sTabCode)
|
||||
{
|
||||
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*/
|
||||
public function AddToMenu($sHtml)
|
||||
{
|
||||
$this->m_sMenu .= $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
if (!empty($this->sContentType))
|
||||
{
|
||||
$this->add_header('Content-type: '.$this->sContentType);
|
||||
}
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
if ($this->m_oTabs->TabsContainerCount() > 0)
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
// The "tab widgets" to handle.
|
||||
var tabs = $('div[id^=tabbedContent]');
|
||||
|
||||
// Ugly patch for a change in the behavior of jQuery UI:
|
||||
// Before jQuery UI 1.9, tabs were always considered as "local" (opposed to Ajax)
|
||||
// when their href was beginning by #. Starting with 1.9, a <base> tag in the page
|
||||
// is taken into account and causes "local" tabs to be considered as Ajax
|
||||
// unless their URL is equal to the URL of the page...
|
||||
if ($('base').length > 0)
|
||||
{
|
||||
$('div[id^=tabbedContent] > ul > li > a').each(function() {
|
||||
var sHash = location.hash;
|
||||
var sCleanLocation = location.href.toString().replace(sHash, '').replace(/#$/, '');
|
||||
$(this).attr("href", sCleanLocation+$(this).attr("href"));
|
||||
});
|
||||
}
|
||||
if ($.bbq)
|
||||
{
|
||||
// This selector will be reused when selecting actual tab widget A elements.
|
||||
var tab_a_selector = 'ul.ui-tabs-nav a';
|
||||
|
||||
// Enable tabs on all tab widgets. The `event` property must be overridden so
|
||||
// that the tabs aren't changed on click, and any custom event name can be
|
||||
// specified. Note that if you define a callback for the 'select' event, it
|
||||
// will be executed for the selected tab whenever the hash changes.
|
||||
tabs.tabs({ event: 'change' });
|
||||
|
||||
// Define our own click handler for the tabs, overriding the default.
|
||||
tabs.find( tab_a_selector ).click(function()
|
||||
{
|
||||
var state = {};
|
||||
|
||||
// Get the id of this tab widget.
|
||||
var id = $(this).closest( 'div[id^=tabbedContent]' ).attr( 'id' );
|
||||
|
||||
// Get the index of this tab.
|
||||
var idx = $(this).parent().prevAll().length;
|
||||
|
||||
// Set the state!
|
||||
state[ id ] = idx;
|
||||
$.bbq.pushState( state );
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
tabs.tabs();
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
// Render the tabs in the page (if any)
|
||||
$this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content, $this);
|
||||
|
||||
// Additional UI widgets to be activated inside the ajax fragment
|
||||
// Important: Testing the content type is not enough because some ajax handlers have not correctly positionned the flag (e.g json response corrupted by the script)
|
||||
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
EOF
|
||||
);
|
||||
}
|
||||
$this->outputCollapsibleSectionInit();
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
{
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
echo self::FilterXSS($this->s_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $this->s_content;
|
||||
}
|
||||
if (!empty($this->m_sMenu))
|
||||
{
|
||||
$uid = time();
|
||||
echo "<div id=\"accordion_temp_$uid\">\n";
|
||||
echo "<div id=\"accordion\">\n";
|
||||
echo "<!-- Beginning of the accordion menu -->\n";
|
||||
echo self::FilterXSS($this->m_sMenu);
|
||||
echo "<!-- End of the accordion menu-->\n";
|
||||
echo "</div>\n";
|
||||
echo "</div>\n";
|
||||
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo "$('#inner_menu').html($('#accordion_temp_$uid').html());\n";
|
||||
echo "$('#accordion_temp_$uid').remove();\n";
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
|
||||
//echo $this->s_deferred_content;
|
||||
if (count($this->a_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo implode("\n", $this->a_scripts);
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (count($this->a_linked_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
foreach($this->a_linked_scripts as $sScriptUrl)
|
||||
{
|
||||
echo '$.getScript('.json_encode($sScriptUrl).");\n";
|
||||
}
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (!empty($this->s_deferred_content))
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo "\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');\n";
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (!empty($this->m_sReadyScript))
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if(count($this->a_linked_stylesheets) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">";
|
||||
foreach($this->a_linked_stylesheets as $aStylesheet)
|
||||
{
|
||||
$sStylesheetUrl = $aStylesheet['link'];
|
||||
echo "if (!$('link[href=\"{$sStylesheetUrl}\"]').length) $('<link href=\"{$sStylesheetUrl}\" rel=\"stylesheet\">').appendTo('head');\n";
|
||||
}
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
|
||||
if (trim($s_captured_output) != "")
|
||||
{
|
||||
echo self::FilterXSS($s_captured_output);
|
||||
}
|
||||
|
||||
$oKPI->ComputeAndReport('Echoing');
|
||||
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a paragraph with a smaller font into the page
|
||||
* NOT implemented (i.e does nothing)
|
||||
* @param string $sText Content of the (small) paragraph
|
||||
* @return void
|
||||
*/
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add($sHtml)
|
||||
{
|
||||
if (($this->m_oTabs->GetCurrentTabContainer() != '') && ($this->m_oTabs->GetCurrentTab() != ''))
|
||||
{
|
||||
$this->m_oTabs->AddToTab($this->m_oTabs->GetCurrentTabContainer(), $this->m_oTabs->GetCurrentTab(), $sHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent::add($sHtml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function start_capture()
|
||||
{
|
||||
$sCurrentTabContainer = $this->m_oTabs->GetCurrentTabContainer();
|
||||
$sCurrentTab = $this->m_oTabs->GetCurrentTab();
|
||||
|
||||
if (!empty($sCurrentTabContainer) && !empty($sCurrentTab))
|
||||
{
|
||||
$iOffset = $this->m_oTabs->GetCurrentTabLength();
|
||||
return array('tc' => $sCurrentTabContainer, 'tab' => $sCurrentTab, 'offset' => $iOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::start_capture();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function end_capture($offset)
|
||||
{
|
||||
if (is_array($offset))
|
||||
{
|
||||
if ($this->m_oTabs->TabExists($offset['tc'], $offset['tab']))
|
||||
{
|
||||
$sCaptured = $this->m_oTabs->TruncateTab($offset['tc'], $offset['tab'], $offset['offset']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCaptured = '';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCaptured = parent::end_capture($offset);
|
||||
}
|
||||
return $sCaptured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_at_the_end($s_html, $sId = '')
|
||||
{
|
||||
if ($sId != '')
|
||||
{
|
||||
$this->add_script("$('#{$sId}').remove();"); // Remove any previous instance of the same Id
|
||||
}
|
||||
$this->s_deferred_content .= $s_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_ready_script($sScript)
|
||||
{
|
||||
$this->m_sReadyScript .= $sScript."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetUniqueId()
|
||||
{
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function FilterXSS($sHTML)
|
||||
{
|
||||
return str_ireplace(array('<script', '</script>'), array('<!-- <removed-script', '</removed-script> -->'), $sHTML);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Includes all the classes to have the application up and running
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.category.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.domain.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||
require_once(APPROOT.'/application/query.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||
//require_once(APPROOT.'/application/menunode.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
|
||||
class ApplicationException extends CoreException
|
||||
{
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2018 Combodo SARL
|
||||
//
|
||||
// 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.
|
||||
@@ -17,46 +16,42 @@
|
||||
// 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
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
|
||||
require_once(APPROOT."/application/utils.inc.php");
|
||||
|
||||
/**
|
||||
* Interface for directing end-users to the relevant application
|
||||
*/
|
||||
*/
|
||||
interface iDBObjectURLMaker
|
||||
{
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function MakeObjectURL($sClass, $iId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 +63,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,6 +81,7 @@ class PortalURLMaker implements iDBObjectURLMaker
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to store and manipulate the parameters that make the application's context
|
||||
*
|
||||
@@ -98,182 +94,141 @@ 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 = [
|
||||
'org_id', 'menu',
|
||||
];
|
||||
if ($bReadContext) {
|
||||
$this->ReadContext();
|
||||
$this->aNames = array(
|
||||
'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 = [];
|
||||
$aContext = utils::ReadParam('c', [], false, 'context_param');
|
||||
foreach ($this->aNames as $sName) {
|
||||
if (!isset(self::$aDefaultValues))
|
||||
{
|
||||
self::$aDefaultValues = array();
|
||||
$aContext = utils::ReadParam('c', array(), 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
|
||||
*
|
||||
*/
|
||||
public function GetForLink(bool $bWithLeadingAmpersand = false)
|
||||
public function GetForLink()
|
||||
{
|
||||
// If there are no parameters, return an empty string
|
||||
if (empty($this->aValues)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Build the query string with ampersand separated parameters
|
||||
$aParams = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aParams = array();
|
||||
foreach($this->aValues as $sName => $sValue)
|
||||
{
|
||||
$aParams[] = "c[$sName]".'='.urlencode($sValue);
|
||||
}
|
||||
$sReturnValue = implode('&', $aParams);
|
||||
|
||||
// add the leading ampersand if requested
|
||||
if ($bWithLeadingAmpersand) {
|
||||
$sReturnValue = '&'.$sReturnValue;
|
||||
}
|
||||
|
||||
return $sReturnValue;
|
||||
return implode("&", $aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
|
||||
* Returns the params as c[menu]:..., c[org_id]:....
|
||||
* @return string The params
|
||||
*/
|
||||
public function GetForPostParams()
|
||||
{
|
||||
return json_encode($this->aValues);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||
*
|
||||
* @return string The context as a sequence of <input type="hidden" /> tags
|
||||
*/
|
||||
public function GetForForm()
|
||||
{
|
||||
$sContext = "";
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".utils::EscapeHtml($sValue)."\" />\n";
|
||||
foreach($this->aValues as $sName => $sValue)
|
||||
{
|
||||
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||
}
|
||||
return $sContext;
|
||||
}
|
||||
/**
|
||||
* Returns the context an array of input blocks
|
||||
*
|
||||
* @return array The context as a sequence of <input type="hidden" /> tags
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetForUIForm()
|
||||
{
|
||||
$aContextInputBlocks = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", $sValue);
|
||||
}
|
||||
return $aContextInputBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||
*
|
||||
*/
|
||||
public function GetForFormBlock(): UIBlock
|
||||
{
|
||||
$oContext = new UIContentBlock();
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$oContext->AddSubBlock(InputUIBlockFactory::MakeForHidden('c[$sName]', utils::HtmlEntities($sValue)));
|
||||
}
|
||||
return $oContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context as a hash array 'parameter_name' => value
|
||||
*
|
||||
* @return array The context information
|
||||
*/
|
||||
public function GetAsHash()
|
||||
{
|
||||
$aReturn = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aReturn = array();
|
||||
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
|
||||
@@ -286,10 +241,11 @@ 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]);
|
||||
}
|
||||
}
|
||||
@@ -305,22 +261,27 @@ class ApplicationContext
|
||||
public function InitObjectFromContext(DBObject &$oObj)
|
||||
{
|
||||
$sClass = get_class($oObj);
|
||||
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
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,7 +294,7 @@ class ApplicationContext
|
||||
$sPrevious = self::GetUrlMakerClass();
|
||||
|
||||
self::$m_sUrlMakerClass = $sClass;
|
||||
Session::Set('UrlMakerClass', $sClass);
|
||||
$_SESSION['UrlMakerClass'] = $sClass;
|
||||
|
||||
return $sPrevious;
|
||||
}
|
||||
@@ -344,10 +305,14 @@ class ApplicationContext
|
||||
*/
|
||||
public static function GetUrlMakerClass()
|
||||
{
|
||||
if (is_null(self::$m_sUrlMakerClass)) {
|
||||
if (Session::IsSet('UrlMakerClass')) {
|
||||
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
||||
} else {
|
||||
if (is_null(self::$m_sUrlMakerClass))
|
||||
{
|
||||
if (isset($_SESSION['UrlMakerClass']))
|
||||
{
|
||||
self::$m_sUrlMakerClass = $_SESSION['UrlMakerClass'];
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$m_sUrlMakerClass = 'iTopStandardURLMaker';
|
||||
}
|
||||
}
|
||||
@@ -365,23 +330,30 @@ 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)) {
|
||||
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 {
|
||||
$sUrl = call_user_func(array($sUrlMakerClass, 'MakeObjectUrl'), $sObjClass, $sObjKey);
|
||||
if (strlen($sUrl) > 0)
|
||||
{
|
||||
if ($bWithNavigationContext)
|
||||
{
|
||||
return $sUrl."&".$oAppContext->GetForLink();
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sUrl;
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,10 +362,13 @@ class ApplicationContext
|
||||
*/
|
||||
protected static function LoadPluginProperties()
|
||||
{
|
||||
if (Session::IsSet('PluginProperties')) {
|
||||
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
||||
} else {
|
||||
self::$m_aPluginProperties = [];
|
||||
if (isset($_SESSION['PluginProperties']))
|
||||
{
|
||||
self::$m_aPluginProperties = $_SESSION['PluginProperties'];
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$m_aPluginProperties = array();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,12 +381,10 @@ 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);
|
||||
$_SESSION['PluginProperties'][$sPluginClass][$sProperty] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,14 +394,15 @@ class ApplicationContext
|
||||
*/
|
||||
public static function GetPluginProperties($sPluginClass)
|
||||
{
|
||||
if (is_null(self::$m_aPluginProperties)) {
|
||||
self::LoadPluginProperties();
|
||||
}
|
||||
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||
|
||||
if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) {
|
||||
if (array_key_exists($sPluginClass, self::$m_aPluginProperties))
|
||||
{
|
||||
return self::$m_aPluginProperties[$sPluginClass];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// 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.
|
||||
@@ -17,12 +16,13 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* This class manages the audit "categories". Each category defines a set of objects
|
||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
||||
* inside the set
|
||||
* inside the set
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -32,66 +32,29 @@ class AuditCategory extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['name'],
|
||||
"db_table" => "priv_auditcategory",
|
||||
"db_key_field" => "id",
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "application, grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('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", ["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, "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']
|
||||
));
|
||||
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)));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'definition_set', 'ok_error_tolerance', 'warning_error_tolerance', 'rules_list', 'domains_list']); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['description', ]); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'definition_set', 'rules_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('description', )); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iTotal
|
||||
* @param int $iErrors
|
||||
*
|
||||
* @return string A semantic color name (eg. red, green, orange, success, failure, ... {@see css/backoffice/utils/variables/colors/_semantic-palette.scss}) to use for this category depending on its error count and tolerance
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public function GetReportColor($iTotal, $iErrors)
|
||||
{
|
||||
$sResult = 'red';
|
||||
if (($iTotal == 0) || ($iErrors / $iTotal) <= ($this->Get('ok_error_tolerance') / 100)) {
|
||||
$sResult = 'green';
|
||||
} elseif (($iErrors / $iTotal) <= ($this->Get('warning_error_tolerance') / 100)) {
|
||||
$sResult = 'orange';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public static function GetShortcutActions($sFinalClass)
|
||||
{
|
||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
||||
}
|
||||
|
||||
return $aShortcutActions;
|
||||
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
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* This class manages the audit "categories". Each category defines a set of objects
|
||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
||||
* inside the set
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 3.1.0
|
||||
*/
|
||||
class AuditDomain extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"complementary_name_attcode" => ['description'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['name'],
|
||||
"db_table" => "priv_auditdomain",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
'style' => new ormStyle(null, null, null, null, null, '../images/icons/icons8-audit-album.svg'),
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeImage("icon", ["is_null_allowed" => true, "depends_on" => [], "display_max_width" => 96, "display_max_height" => 96, "storage_max_width" => 256, "storage_max_height" => 256, "default_image" => null, "always_load_in_tables" => false]));
|
||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect(
|
||||
"categories_list",
|
||||
["linked_class" => "lnkAuditCategoryToAuditDomain", "ext_key_to_me" => "domain_id", "ext_key_to_remote" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => []]
|
||||
));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', ['name', 'description', 'icon', 'categories_list']); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['description',]); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', ['description']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', ['name', 'description']); // Criteria of the default search form
|
||||
}
|
||||
|
||||
public static function GetShortcutActions($sFinalClass)
|
||||
{
|
||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
||||
}
|
||||
|
||||
return $aShortcutActions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0
|
||||
*/
|
||||
class lnkAuditCategoryToAuditDomain extends cmdbAbstractObject
|
||||
{
|
||||
/**
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['category_id', 'domain_id'],
|
||||
"db_table" => "priv_link_audit_category_domain",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"is_link" => true,
|
||||
'uniqueness_rules' => [
|
||||
'no_duplicate' => [
|
||||
'attributes' => [
|
||||
0 => 'category_id',
|
||||
1 => 'domain_id',
|
||||
],
|
||||
'filter' => '',
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["targetclass" => "AuditCategory", "jointype" => '', "allowed_values" => null, "sql" => "category_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("domain_id", ["targetclass" => "AuditDomain", "jointype" => '', "allowed_values" => null, "sql" => "domain_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("domain_name", ["allowed_values" => null, "extkey_attcode" => 'domain_id', "target_attcode" => "name"]));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', ['category_id', 'domain_id']);
|
||||
MetaModel::Init_SetZListItems('list', ['category_id', 'domain_id']);
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', ['category_id', 'domain_id']);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// 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.
|
||||
@@ -17,13 +16,14 @@
|
||||
// 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
|
||||
* or the "bad" ones. The core audit engines computes the complement to the definition
|
||||
* set when needed to obtain either the valid objects, or the ones with an error
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -33,41 +33,32 @@ class AuditRule extends cmdbAbstractObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams =
|
||||
[
|
||||
"category" => "application,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['name'],
|
||||
"db_table" => "priv_auditrule",
|
||||
"db_key_field" => "id",
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "application, grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('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'),
|
||||
];
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", ["allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []]));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("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 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")));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag']); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'valid_flag']); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('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
|
||||
// Search criteria
|
||||
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']); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public static function GetShortcutActions($sFinalClass)
|
||||
{
|
||||
$aShortcutActions = parent::GetShortcutActions($sFinalClass);
|
||||
if (!in_array('UI:Menu:RunAudit', $aShortcutActions)) {
|
||||
$aShortcutActions[] = 'UI:Menu:RunAudit';
|
||||
}
|
||||
|
||||
return $aShortcutActions;
|
||||
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
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,9 +1,84 @@
|
||||
<?php
|
||||
// Copyright (C) 2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||
* Adapter class: when an API requires WebPage and you want to produce something else
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Combodo SARL
|
||||
* @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');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CaptureWebPage extends WebPage
|
||||
{
|
||||
protected $aReadyScripts;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('capture web page');
|
||||
$this->aReadyScripts = array();
|
||||
}
|
||||
|
||||
public function GetHtml()
|
||||
{
|
||||
$trash = $this->ob_get_clean_safe();
|
||||
return $this->s_content;
|
||||
}
|
||||
|
||||
public function GetJS()
|
||||
{
|
||||
$sRet = implode("\n", $this->a_scripts);
|
||||
if (!empty($this->s_deferred_content))
|
||||
{
|
||||
$sRet .= "\n\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');";
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function GetReadyJS()
|
||||
{
|
||||
return "\$(document).ready(function() {\n".implode("\n", $this->aReadyScripts)."\n});";
|
||||
}
|
||||
|
||||
public function GetCSS()
|
||||
{
|
||||
return $this->a_styles;
|
||||
}
|
||||
|
||||
public function GetJSFiles()
|
||||
{
|
||||
return $this->a_linked_scripts;
|
||||
}
|
||||
|
||||
public function GetCSSFiles()
|
||||
{
|
||||
return $this->a_linked_stylesheets;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
throw new Exception(__method__.' should not be called');
|
||||
}
|
||||
|
||||
public function add_ready_script($sScript)
|
||||
{
|
||||
$this->aReadyScripts[] = $sScript;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,97 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader
|
||||
* CLI page
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @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');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CLIPage implements Page
|
||||
{
|
||||
function __construct($s_title)
|
||||
{
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
echo $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function pre($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
echo "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CompileCSSService : used to ease testing ThemeHander class via mocks
|
||||
*
|
||||
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||
* @since 3.0.0 N°2982
|
||||
*/
|
||||
class CompileCSSService
|
||||
{
|
||||
/**
|
||||
* CompileCSSService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = [])
|
||||
{
|
||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,111 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader
|
||||
* Simple web page with no includes or fancy formatting, useful to generateXML documents
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CSVPage extends WebPage
|
||||
{
|
||||
function __construct($s_title) {
|
||||
parent::__construct($s_title);
|
||||
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
|
||||
$this->no_cache();
|
||||
$this->add_http_headers();
|
||||
//$this->add_header("Content-Transfer-Encoding: binary");
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
|
||||
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
echo trim($this->s_content);
|
||||
echo "\n";
|
||||
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
$this->s_content .= $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
$this->s_content .= $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
$this->s_content .= "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// 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,18 +15,15 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
|
||||
/**
|
||||
* Dashboard presentation
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
abstract class DashboardLayout
|
||||
{
|
||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||
@@ -39,21 +35,21 @@ abstract class DashboardLayout
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract public function GetDashletCoordinates($iCellIdx);
|
||||
|
||||
|
||||
public static function GetInfo()
|
||||
{
|
||||
return [
|
||||
return array(
|
||||
'label' => '',
|
||||
'icon' => '',
|
||||
'description' => '',
|
||||
];
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
{
|
||||
protected $iNbCols;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->iNbCols = 1;
|
||||
@@ -64,103 +60,115 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
$aKeys = array_reverse(array_keys($aDashlets));
|
||||
$idx = 0;
|
||||
$bNoVisibleFound = true;
|
||||
while ($idx < count($aKeys) && $bNoVisibleFound) {
|
||||
while($idx < count($aKeys) && $bNoVisibleFound)
|
||||
{
|
||||
/** @var \Dashlet $oDashlet */
|
||||
$oDashlet = $aDashlets[$aKeys[$idx]];
|
||||
if ($oDashlet::IsVisible()) {
|
||||
if ($oDashlet::IsVisible())
|
||||
{
|
||||
$bNoVisibleFound = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($aDashlets[$aKeys[$idx]]);
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
return $aDashlets;
|
||||
}
|
||||
|
||||
|
||||
protected function TrimCellsArray($aCells)
|
||||
{
|
||||
foreach ($aCells as $key => $aDashlets) {
|
||||
foreach($aCells as $key => $aDashlets)
|
||||
{
|
||||
$aCells[$key] = $this->TrimCell($aDashlets);
|
||||
}
|
||||
$aKeys = array_reverse(array_keys($aCells));
|
||||
$idx = 0;
|
||||
$bNoVisibleFound = true;
|
||||
while ($idx < count($aKeys) && $bNoVisibleFound) {
|
||||
while($idx < count($aKeys) && $bNoVisibleFound)
|
||||
{
|
||||
$aDashlets = $aCells[$aKeys[$idx]];
|
||||
if (count($aDashlets) > 0) {
|
||||
if (count($aDashlets) > 0)
|
||||
{
|
||||
$bNoVisibleFound = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($aCells[$aKeys[$idx]]);
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
return $aCells;
|
||||
|
||||
return $aCells;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebPage $oPage
|
||||
* @param \WebPage $oPage
|
||||
* @param $aCells
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams
|
||||
*/
|
||||
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = [])
|
||||
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||
$aCells = $this->TrimCellsArray($aCells);
|
||||
|
||||
$oDashboardLayout = new DashboardLayoutUIBlock();
|
||||
//$oPage->AddUiBlock($oDashboardLayout);
|
||||
|
||||
$oPage->add('<table style="width:100%;table-layout:fixed;"><tbody>');
|
||||
$iCellIdx = 0;
|
||||
$fColSize = 100 / $this->iNbCols;
|
||||
$sStyle = $bEditMode ? 'border: 1px #ccc dashed; width:'.$fColSize.'%;' : 'width: '.$fColSize.'%;';
|
||||
$sClass = $bEditMode ? 'layout_cell edit_mode' : 'dashboard';
|
||||
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||
|
||||
//Js given by each dashlet to reload
|
||||
$sJSReload = "";
|
||||
|
||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||
$oDashboardRow = new DashboardRow();
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
|
||||
if (array_key_exists($iCellIdx, $aCells)) {
|
||||
for($iRows = 0; $iRows < $iNbRows; $iRows++)
|
||||
{
|
||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$sCellClass = ($iRows == $iNbRows-1) ? $sClass.' layout_last_used_rank' : $sClass;
|
||||
$oPage->add("<td style=\"$sStyle\" class=\"$sCellClass\" data-dashboard-column-index=\"$iCols\" data-dashboard-cell-index=\"$iCellIdx\">");
|
||||
if (array_key_exists($iCellIdx, $aCells))
|
||||
{
|
||||
$aDashlets = $aCells[$iCellIdx];
|
||||
if (count($aDashlets) > 0) {
|
||||
if (count($aDashlets) > 0)
|
||||
{
|
||||
/** @var \Dashlet $oDashlet */
|
||||
foreach ($aDashlets as $oDashlet) {
|
||||
if ($oDashlet::IsVisible()) {
|
||||
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||
foreach($aDashlets as $oDashlet)
|
||||
{
|
||||
if ($oDashlet::IsVisible())
|
||||
{
|
||||
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
$oPage->add('</td>');
|
||||
$iCellIdx++;
|
||||
}
|
||||
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
|
||||
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||
|
||||
if ($bEditMode) { // Add one row for extensibility
|
||||
$oDashboardRow = new DashboardRow();
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode, true);
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
if ($bEditMode) // Add one row for extensibility
|
||||
{
|
||||
$sStyle = 'style="border: 1px #ccc dashed; width:'.$fColSize.'%;" class="layout_cell edit_mode layout_extension" data-dashboard-cell-index="'.$iCellIdx.'"';
|
||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$oPage->add("<td $sStyle data-dashboard-column-index=\"$iCols\">");
|
||||
$oPage->add(' ');
|
||||
$oPage->add('</td>');
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
|
||||
return $oDashboardLayout;
|
||||
$oPage->add('</tbody></table>');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +179,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
$iColNumber = (int) $iCellIdx % $this->iNbCols;
|
||||
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
|
||||
|
||||
return [$iColNumber, $iRowNumber];
|
||||
return array($iColNumber, $iRowNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,13 +190,13 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 1;
|
||||
}
|
||||
public static function GetInfo()
|
||||
static public function GetInfo()
|
||||
{
|
||||
return [
|
||||
return array(
|
||||
'label' => 'One Column',
|
||||
'icon' => 'images/layout_1col.png',
|
||||
'description' => '',
|
||||
];
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,13 +207,13 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 2;
|
||||
}
|
||||
public static function GetInfo()
|
||||
static public function GetInfo()
|
||||
{
|
||||
return [
|
||||
return array(
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_2col.png',
|
||||
'description' => '',
|
||||
];
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,12 +224,12 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
|
||||
parent::__construct();
|
||||
$this->iNbCols = 3;
|
||||
}
|
||||
public static function GetInfo()
|
||||
static public function GetInfo()
|
||||
{
|
||||
return [
|
||||
return array(
|
||||
'label' => 'Two Columns',
|
||||
'icon' => 'images/layout_3col.png',
|
||||
'description' => '',
|
||||
];
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="AbstractResource" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<comment>/* Resource access control abstraction. Can be herited by abstract resource access control classes. Generaly controlled using UR_ACTION_MODIFY access right. */</comment>
|
||||
<abstract>true</abstract>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceAdminMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* AdminTools menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceRunQueriesMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* RunQueriesMenu menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceSystemMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* System menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="WelcomePopupAcknowledge" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
<properties>
|
||||
<comment>/** Acknowledge welcome popup messages */</comment>
|
||||
<abstract>false</abstract>
|
||||
<category></category>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_welcome_popup_acknowledge</db_table>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="message_uuid" xsi:type="AttributeString">
|
||||
<sql>message_uuid</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="user_id" xsi:type="AttributeExternalKey">
|
||||
<sql>user_id</sql>
|
||||
<target_class>User</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_SILENT</on_target_delete>
|
||||
</field>
|
||||
<field id="acknowledge_date" xsi:type="AttributeDateTime">
|
||||
<sql>acknowledge_date</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
</classes>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
|
||||
<portals>
|
||||
<portal id="backoffice" _delta="define">
|
||||
<url>pages/UI.php</url>
|
||||
@@ -83,774 +12,13 @@
|
||||
</portal>
|
||||
</portals>
|
||||
<menus>
|
||||
<menu id="WelcomeMenu" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>10</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-home</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="WelcomeMenuPage" xsi:type="DashboardMenuNode" _delta="define">
|
||||
<rank>10</rank>
|
||||
<parent>WelcomeMenu</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title>Menu:WelcomeMenuPage</title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="MyShortcuts" xsi:type="ShortcutContainerMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>WelcomeMenu</parent>
|
||||
</menu>
|
||||
<menu id="UserManagement" xsi:type="TemplateMenuNode" _delta="define">
|
||||
<rank>10</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="UserAccountsMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>11</rank>
|
||||
<parent>UserManagement</parent>
|
||||
<oql><![CDATA[SELECT User]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<search_form_open>1</search_form_open>
|
||||
<enable_class>User</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ProfilesMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>12</rank>
|
||||
<parent>UserManagement</parent>
|
||||
<oql><![CDATA[SELECT URP_Profiles]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>URP_Profiles</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="AuditCategories" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<oql><![CDATA[SELECT AuditCategory]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>AuditCategory</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="Queries" xsi:type="TemplateMenuNode" _delta="define">
|
||||
<rank>30</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="RunQueriesMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>31</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$pages/run_query.php</url>
|
||||
<enable_class>ResourceRunQueriesMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="QueryMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>32</rank>
|
||||
<parent>Queries</parent>
|
||||
<oql><![CDATA[SELECT Query]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>Query</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ExportMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>33</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$webservices/export-v2.php?interactive=1</url>
|
||||
<enable_class>ResourceAdminMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="DataModelMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>40</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<url>$pages/schema.php</url>
|
||||
<enable_class>ResourceRunQueriesMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="UniversalSearchMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>35</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$pages/UniversalSearch.php</url>
|
||||
<enable_class>ResourceAdminMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ConfigurationTools" xsi:type="MenuGroup" _delta="define_if_not_exists">
|
||||
<rank>90</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-cog</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="Integrations" xsi:type="TemplateMenuNode" _delta="define">
|
||||
<rank>50</rank>
|
||||
<parent>ConfigurationTools</parent>
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="DataSources" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>ConfigurationTools</parent>
|
||||
<oql><![CDATA[SELECT SynchroDataSource]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>SynchroDataSource</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="NotificationsMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>40</rank>
|
||||
<parent>ConfigurationTools</parent>
|
||||
<url>$pages/notifications.php</url>
|
||||
<enable_class>Trigger</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>80</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-tools</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>100</rank>
|
||||
<enable_class>ResourceSystemMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
<style>
|
||||
<decoration_classes>fas fa-terminal</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
</menus>
|
||||
<events>
|
||||
<event id="EVENT_DB_BEFORE_WRITE" _delta="define">
|
||||
<name>Before create or update</name>
|
||||
<description><![CDATA[An object is about to be written into the database.
|
||||
The object can be modified.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>DBObject::OnInsert</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object inserted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="is_new">
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_CHECK_TO_WRITE" _delta="define">
|
||||
<name>Check to write</name>
|
||||
<description><![CDATA[Check an object before it is written into the database (no change possible).
|
||||
Call $this->AddCheckIssue($sErrorMessage) to report a blocking issue.
|
||||
Call $this->AddCheckWarning($sWarningMessage) to display a warning.
|
||||
]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>cmdbAbstractObject::DoCheckToWrite</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object to check</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="is_new">
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_AFTER_WRITE" _delta="define">
|
||||
<name>After create or update</name>
|
||||
<description><![CDATA[An object has been written into the database.
|
||||
The modifications can be propagated to other objects.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>DBObject::AfterInsert</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object inserted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="is_new">
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="changes">
|
||||
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_CHECK_TO_DELETE" _delta="define">
|
||||
<name>Check to delete</name>
|
||||
<description><![CDATA[Check an object before it is deleted from the database.
|
||||
Call $this->AddDeleteIssue($sIssueMessage) to signal an issue.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>cmdbAbstractObject::DoCheckToDelete</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object to check</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_ABOUT_TO_DELETE" _delta="define">
|
||||
<name>Before delete</name>
|
||||
<description><![CDATA[An object is about to be deleted from the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>cmdbAbstractObject::OnDelete</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object about to be deleted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_AFTER_DELETE" _delta="define">
|
||||
<name>After delete</name>
|
||||
<description><![CDATA[An object has been deleted into the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>DBObject::AfterDelete</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object deleted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_ENUM_TRANSITIONS" _delta="define">
|
||||
<name>Enum transitions</name>
|
||||
<description><![CDATA[Manage the allowed transitions in current object state.
|
||||
The only action allowed is to deny transitions with $this->DenyTransition($sTransitionCode)]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object where the stimulus is targeted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="allowed_stimuli">
|
||||
<description>The list of available stimuli in the current state</description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_LINKS_CHANGED" _delta="define">
|
||||
<name>Links on object have changed</name>
|
||||
<description><![CDATA[At least one link class was changed]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object where the link is or was pointing to</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_OBJECT_RELOAD" _delta="define">
|
||||
<name>Object reload</name>
|
||||
<internal>true</internal>
|
||||
<description><![CDATA[An object has been re-loaded from the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object re-loaded</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_COMPUTE_VALUES" _delta="define">
|
||||
<name>Recompute object values</name>
|
||||
<description><![CDATA[An object needs to be recomputed after changes]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<replaces>DBObject::ComputeValues</replaces>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object inserted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="is_new">
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_ARCHIVE" _delta="define">
|
||||
<name>Object archived</name>
|
||||
<description><![CDATA[An object has been archived]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object archived</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_UNARCHIVE" _delta="define">
|
||||
<name>Object unarchived</name>
|
||||
<description><![CDATA[An object has been unarchived]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object unarchived</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_SET_ATTRIBUTES_FLAGS" _delta="define">
|
||||
<name>Set attributes flags</name>
|
||||
<description><![CDATA[Set object attributes flags.
|
||||
Call $this->AddAttributeFlags($sAttCode, $iFlags) for all the attributes to be set for this target state.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The current object</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="target_state">
|
||||
<description>The target state in which to evaluate the flags</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS" _delta="define">
|
||||
<name>Set initial attributes flags</name>
|
||||
<description><![CDATA[Set object initial attributes flags.
|
||||
Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial attributes to be set initially.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The current object</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
|
||||
<name>Document downloaded</name>
|
||||
<description><![CDATA[A document has been downloaded from the GUI]]></description>
|
||||
<sources>
|
||||
<source id="Document">Document</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object containing the document</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="att_code">
|
||||
<description>The optional object attribute code hosting the document</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="document">
|
||||
<description>The document downloaded</description>
|
||||
<type>ormDocument</type>
|
||||
</event_datum>
|
||||
<event_datum id="content_disposition">
|
||||
<description>The content disposition of the document ("inline" or "attachment")</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_LOGIN" _delta="define">
|
||||
<name>Login</name>
|
||||
<internal>true</internal>
|
||||
<description><![CDATA[Inform the listeners about the connection states]]></description>
|
||||
<event_data>
|
||||
<event_datum id="code">
|
||||
<description>The login step result code (LoginWebPage::EXIT_CODE_...) </description>
|
||||
<type>integer</type>
|
||||
</event_datum>
|
||||
<event_datum id="state">
|
||||
<description>Current login state (LoginWebPage::LOGIN_STATE_CONNECTED...)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
</events>
|
||||
<meta>
|
||||
<classes>
|
||||
<class id="cmdbAbstractObject" _delta="define">
|
||||
<methods>
|
||||
<method id="Set">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
<type id="AttributeLinkedSetIndirect"/>
|
||||
<type id="AttributeLinkedSet"/>
|
||||
<type id="AttributeImage"/>
|
||||
<type id="AttributeBlob"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
<type id="AttributeLinkedSetIndirect"/>
|
||||
<type id="AttributeLinkedSet"/>
|
||||
<type id="AttributeImage"/>
|
||||
<type id="AttributeBlob"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="AddValue">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeDecimal"/>
|
||||
<type id="AttributePercentage"/>
|
||||
<type id="AttributeDuration"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetComputedDate">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>attcode</type>
|
||||
<mandatory>false</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetComputedDateIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>attcode</type>
|
||||
<mandatory>false</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentDate">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentDateIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentUser">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeExternalKey"/>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentPerson">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeExternalKey"/>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetElapsedTime">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDuration"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Reset">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="ResetStopWatch">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Copy">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="ApplyStimulus">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
</classes>
|
||||
</meta>
|
||||
</itop_design>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||
|
||||
class ErrorPage extends NiceWebPage
|
||||
{
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
parent::__construct($sTitle);
|
||||
$this->add_linked_script("../js/jquery.blockUI.js");
|
||||
$this->add_linked_script("../setup/setup.js");
|
||||
$this->add_saas("css/setup.scss");
|
||||
}
|
||||
|
||||
public function info($sText)
|
||||
{
|
||||
$this->add("<p class=\"info\">$sText</p>\n");
|
||||
$this->log_info($sText);
|
||||
}
|
||||
|
||||
public function ok($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-valid\"><span class=\"message-title\">Success:</span>$sText</div>");
|
||||
$this->log_ok($sText);
|
||||
}
|
||||
|
||||
public function warning($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-warning\"><span class=\"message-title\">Warning:</span>$sText</div>");
|
||||
$this->log_warning($sText);
|
||||
}
|
||||
|
||||
public function error($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-error\">$sText</div>");
|
||||
$this->log_error($sText);
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$sLogo = utils::GetAbsoluteUrlAppRoot().'/images/itop-logo.png';
|
||||
$sTimeStamp = utils::GetCacheBusterTimestamp();
|
||||
$sTitle = utils::HtmlEntities($this->s_title);
|
||||
$this->s_content = <<<HTML
|
||||
<div id="header" class="error_page">
|
||||
<h1><a href="http://www.combodo.com/itop" target="_blank"><img title="iTop by Combodo" alt=" " src="{$sLogo}?t={$sTimeStamp}"></a> {$sTitle}</h1>
|
||||
</div>
|
||||
<div id="setup" class="error_page">
|
||||
{$this->s_content}
|
||||
</div>
|
||||
HTML;
|
||||
return parent::output();
|
||||
}
|
||||
|
||||
public static function log_error($sText)
|
||||
{
|
||||
IssueLog::Error($sText);
|
||||
}
|
||||
|
||||
public static function log_warning($sText)
|
||||
{
|
||||
IssueLog::Warning($sText);
|
||||
}
|
||||
|
||||
public static function log_info($sText)
|
||||
{
|
||||
IssueLog::Info($sText);
|
||||
}
|
||||
|
||||
public static function log_ok($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
|
||||
public static function log($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\WebPage\CLIPage;
|
||||
use Combodo\iTop\Application\WebPage\Page;
|
||||
|
||||
require_once('xlsxwriter.class.php');
|
||||
|
||||
class ExcelExporter
|
||||
@@ -19,67 +15,73 @@ class ExcelExporter
|
||||
protected $iPosition;
|
||||
protected $sOutputFilePath;
|
||||
protected $bAdvancedMode;
|
||||
|
||||
|
||||
public function __construct($sToken = null)
|
||||
{
|
||||
$this->aStatistics = [
|
||||
$this->aStatistics = array(
|
||||
'objects_count' => 0,
|
||||
'total_duration' => 0,
|
||||
'data_retrieval_duration' => 0,
|
||||
'excel_build_duration' => 0,
|
||||
'excel_write_duration' => 0,
|
||||
'peak_memory_usage' => 0,
|
||||
];
|
||||
'peak_memory_usage' => 0,
|
||||
);
|
||||
$this->fStartTime = microtime(true);
|
||||
$this->oSearch = null;
|
||||
|
||||
|
||||
$this->sState = 'new';
|
||||
$this->aObjectsIDs = [];
|
||||
$this->aObjectsIDs = array();
|
||||
$this->iPosition = 0;
|
||||
$this->aAuthorizedClasses = null;
|
||||
$this->aTableHeaders = null;
|
||||
$this->sOutputFilePath = null;
|
||||
$this->bAdvancedMode = false;
|
||||
$this->CheckDataDir();
|
||||
if ($sToken == null) {
|
||||
if ($sToken == null)
|
||||
{
|
||||
$this->sToken = $this->GetNewToken();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sToken = $sToken;
|
||||
$this->ReloadState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null)) {
|
||||
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null))
|
||||
{
|
||||
// Operation in progress, save the state
|
||||
$this->SaveState();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Operation completed, cleanup the temp files
|
||||
@unlink($this->GetStateFile());
|
||||
@unlink($this->GetDataFile());
|
||||
}
|
||||
self::CleanupOldFiles();
|
||||
self::CleanupOldFiles();
|
||||
}
|
||||
|
||||
|
||||
public function SetChunkSize($iChunkSize)
|
||||
{
|
||||
$this->iChunkSize = $iChunkSize;
|
||||
$this->iChunkSize = $iChunkSize;
|
||||
}
|
||||
|
||||
|
||||
public function SetOutputFilePath($sDestFilePath)
|
||||
{
|
||||
$this->sOutputFilePath = $sDestFilePath;
|
||||
}
|
||||
|
||||
|
||||
public function SetAdvancedMode($bAdvanced)
|
||||
{
|
||||
$this->bAdvancedMode = $bAdvanced;
|
||||
}
|
||||
|
||||
|
||||
public function SaveState()
|
||||
{
|
||||
$aState = [
|
||||
$aState = array(
|
||||
'state' => $this->sState,
|
||||
'statistics' => $this->aStatistics,
|
||||
'filter' => $this->oSearch->serialize(),
|
||||
@@ -88,28 +90,31 @@ class ExcelExporter
|
||||
'object_ids' => $this->aObjectsIDs,
|
||||
'output_file_path' => $this->sOutputFilePath,
|
||||
'advanced_mode' => $this->bAdvancedMode,
|
||||
];
|
||||
|
||||
);
|
||||
|
||||
file_put_contents($this->GetStateFile(), json_encode($aState));
|
||||
|
||||
|
||||
return $this->sToken;
|
||||
}
|
||||
|
||||
|
||||
public function ReloadState()
|
||||
{
|
||||
if ($this->sToken == null) {
|
||||
if ($this->sToken == null)
|
||||
{
|
||||
throw new Exception('ExcelExporter not initialized with a token, cannot reload state');
|
||||
}
|
||||
|
||||
if (!file_exists($this->GetStateFile())) {
|
||||
|
||||
if (!file_exists($this->GetStateFile()))
|
||||
{
|
||||
throw new Exception("ExcelExporter: missing status file '".$this->GetStateFile()."', cannot reload state.");
|
||||
}
|
||||
$sJson = file_get_contents($this->GetStateFile());
|
||||
$aState = json_decode($sJson, true);
|
||||
if ($aState === null) {
|
||||
if ($aState === null)
|
||||
{
|
||||
throw new Exception("ExcelExporter:corrupted status file '".$this->GetStateFile()."', not a JSON, cannot reload state.");
|
||||
}
|
||||
|
||||
|
||||
$this->sState = $aState['state'];
|
||||
$this->aStatistics = $aState['statistics'];
|
||||
$this->oSearch = DBObjectSearch::unserialize($aState['filter']);
|
||||
@@ -119,183 +124,206 @@ class ExcelExporter
|
||||
$this->sOutputFilePath = $aState['output_file_path'];
|
||||
$this->bAdvancedMode = $aState['advanced_mode'];
|
||||
}
|
||||
|
||||
|
||||
public function SetObjectList($oSearch)
|
||||
{
|
||||
$this->oSearch = $oSearch;
|
||||
}
|
||||
|
||||
|
||||
public function Run()
|
||||
{
|
||||
$sCode = 'error';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::Format('ExcelExporter:ErrorUnexpected_State', $this->sState);
|
||||
$fTime = microtime(true);
|
||||
|
||||
try {
|
||||
switch ($this->sState) {
|
||||
|
||||
try
|
||||
{
|
||||
switch($this->sState)
|
||||
{
|
||||
case 'new':
|
||||
$oIDSet = new DBObjectSet($this->oSearch);
|
||||
$oIDSet->OptimizeColumnLoad(['id']);
|
||||
$this->aObjectsIDs = [];
|
||||
while ($oObj = $oIDSet->Fetch()) {
|
||||
$this->aObjectsIDs[] = $oObj->GetKey();
|
||||
}
|
||||
$sCode = 'retrieving-data';
|
||||
$iPercentage = 5;
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
$this->iPosition = 0;
|
||||
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
|
||||
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
|
||||
|
||||
// The first line of the file is the "headers" specifying the label and the type of each column
|
||||
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
|
||||
$sRow = json_encode($this->aTableHeaders);
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false) {
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
fwrite($hFile, $sRow."\n");
|
||||
fclose($hFile);
|
||||
|
||||
// Next state
|
||||
$this->sState = 'retrieving-data';
|
||||
break;
|
||||
|
||||
$oIDSet = new DBObjectSet($this->oSearch);
|
||||
$oIDSet->OptimizeColumnLoad(array('id'));
|
||||
$this->aObjectsIDs = array();
|
||||
while($oObj = $oIDSet->Fetch())
|
||||
{
|
||||
$this->aObjectsIDs[] = $oObj->GetKey();
|
||||
}
|
||||
$sCode = 'retrieving-data';
|
||||
$iPercentage = 5;
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
$this->iPosition = 0;
|
||||
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
|
||||
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
|
||||
|
||||
// The first line of the file is the "headers" specifying the label and the type of each column
|
||||
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
|
||||
$sRow = json_encode($this->aTableHeaders);
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
fwrite($hFile, $sRow."\n");
|
||||
fclose($hFile);
|
||||
|
||||
// Next state
|
||||
$this->sState = 'retrieving-data';
|
||||
break;
|
||||
|
||||
case 'retrieving-data':
|
||||
$oCurrentSearch = clone $this->oSearch;
|
||||
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
|
||||
|
||||
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false) {
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
$oSet = new DBObjectSet($oCurrentSearch);
|
||||
$this->GetFieldsList($oSet, $this->bAdvancedMode);
|
||||
while ($aObjects = $oSet->FetchAssoc()) {
|
||||
$aRow = [];
|
||||
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
|
||||
$oObj = $aObjects[$sAlias];
|
||||
if ($this->bAdvancedMode) {
|
||||
$aRow[] = $oObj->GetKey();
|
||||
}
|
||||
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
|
||||
$value = $oObj->Get($sAttCodeEx);
|
||||
if ($value instanceof ormCaseLog) {
|
||||
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
|
||||
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
|
||||
} else {
|
||||
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
|
||||
}
|
||||
$aRow[] = $sExcelVal;
|
||||
}
|
||||
$oCurrentSearch = clone $this->oSearch;
|
||||
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
|
||||
|
||||
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
$oSet = new DBObjectSet($oCurrentSearch);
|
||||
$this->GetFieldsList($oSet, $this->bAdvancedMode);
|
||||
while($aObjects = $oSet->FetchAssoc())
|
||||
{
|
||||
$aRow = array();
|
||||
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||
{
|
||||
$oObj = $aObjects[$sAlias];
|
||||
if ($this->bAdvancedMode)
|
||||
{
|
||||
$aRow[] = $oObj->GetKey();
|
||||
}
|
||||
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||
{
|
||||
$value = $oObj->Get($sAttCodeEx);
|
||||
if ($value instanceOf ormCaseLog)
|
||||
{
|
||||
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
|
||||
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
|
||||
}
|
||||
$aRow[] = $sExcelVal;
|
||||
}
|
||||
$sRow = json_encode($aRow);
|
||||
fwrite($hFile, $sRow."\n");
|
||||
}
|
||||
fclose($hFile);
|
||||
|
||||
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs)) {
|
||||
// Next state
|
||||
$this->sState = 'building-excel';
|
||||
$sCode = 'building-excel';
|
||||
$iPercentage = 80;
|
||||
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
|
||||
} else {
|
||||
$sCode = 'retrieving-data';
|
||||
$this->iPosition += $this->iChunkSize;
|
||||
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'building-excel':
|
||||
$hFile = @fopen($this->GetDataFile(), 'rb');
|
||||
if ($hFile === false) {
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
|
||||
}
|
||||
$sHeaders = fgets($hFile);
|
||||
$aHeaders = json_decode($sHeaders, true);
|
||||
|
||||
$aData = [];
|
||||
while ($sLine = fgets($hFile)) {
|
||||
$aRow = json_decode($sLine);
|
||||
$aData[] = $aRow;
|
||||
}
|
||||
fclose($hFile);
|
||||
@unlink($this->GetDataFile());
|
||||
|
||||
$fStartExcel = microtime(true);
|
||||
$writer = new XLSXWriter();
|
||||
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
||||
$writer->writeSheet($aData, 'Sheet1', $aHeaders);
|
||||
$fExcelTime = microtime(true) - $fStartExcel;
|
||||
$this->aStatistics['excel_build_duration'] = $fExcelTime;
|
||||
|
||||
$fTime = microtime(true);
|
||||
$writer->writeToFile($this->GetExcelFilePath());
|
||||
$fExcelSaveTime = microtime(true) - $fTime;
|
||||
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
|
||||
|
||||
$sRow = json_encode($aRow);
|
||||
fwrite($hFile, $sRow."\n");
|
||||
}
|
||||
fclose($hFile);
|
||||
|
||||
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs))
|
||||
{
|
||||
// Next state
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
|
||||
$this->sState = 'building-excel';
|
||||
$sCode = 'building-excel';
|
||||
$iPercentage = 80;
|
||||
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCode = 'retrieving-data';
|
||||
$this->iPosition += $this->iChunkSize;
|
||||
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'building-excel':
|
||||
$hFile = @fopen($this->GetDataFile(), 'rb');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
|
||||
}
|
||||
$sHeaders = fgets($hFile);
|
||||
$aHeaders = json_decode($sHeaders, true);
|
||||
|
||||
$aData = array();
|
||||
while($sLine = fgets($hFile))
|
||||
{
|
||||
$aRow = json_decode($sLine);
|
||||
$aData[] = $aRow;
|
||||
}
|
||||
fclose($hFile);
|
||||
@unlink($this->GetDataFile());
|
||||
|
||||
$fStartExcel = microtime(true);
|
||||
$writer = new XLSXWriter();
|
||||
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
||||
$writer->writeSheet($aData,'Sheet1', $aHeaders);
|
||||
$fExcelTime = microtime(true) - $fStartExcel;
|
||||
$this->aStatistics['excel_build_duration'] = $fExcelTime;
|
||||
|
||||
$fTime = microtime(true);
|
||||
$writer->writeToFile($this->GetExcelFilePath());
|
||||
$fExcelSaveTime = microtime(true) - $fTime;
|
||||
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
|
||||
|
||||
// Next state
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
|
||||
case 'done':
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$sCode = 'error';
|
||||
$sMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
$this->aStatistics['total_duration'] += microtime(true) - $fTime;
|
||||
$peak_memory = memory_get_peak_usage(true);
|
||||
if ($peak_memory > $this->aStatistics['peak_memory_usage']) {
|
||||
if ($peak_memory > $this->aStatistics['peak_memory_usage'])
|
||||
{
|
||||
$this->aStatistics['peak_memory_usage'] = $peak_memory;
|
||||
}
|
||||
|
||||
return [
|
||||
|
||||
return array(
|
||||
'code' => $sCode,
|
||||
'message' => $sMessage,
|
||||
'percentage' => $iPercentage,
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function GetExcelFilePath()
|
||||
{
|
||||
if ($this->sOutputFilePath == null) {
|
||||
if ($this->sOutputFilePath == null)
|
||||
{
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->sOutputFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function GetExcelFileFromToken($sToken)
|
||||
{
|
||||
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
|
||||
public static function CleanupFromToken($sToken)
|
||||
{
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
|
||||
public function Cleanup()
|
||||
{
|
||||
self::CleanupFromToken($this->sToken);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete all files in the data/bulk_export directory which are older than 1 day
|
||||
* unless a different delay is configured.
|
||||
@@ -304,12 +332,15 @@ class ExcelExporter
|
||||
{
|
||||
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
|
||||
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
|
||||
|
||||
if ($iDelay > 0) {
|
||||
foreach ($aFiles as $sFile) {
|
||||
|
||||
if($iDelay > 0)
|
||||
{
|
||||
foreach($aFiles as $sFile)
|
||||
{
|
||||
$iModificationTime = filemtime($sFile);
|
||||
|
||||
if ($iModificationTime < (time() - $iDelay)) {
|
||||
|
||||
if($iModificationTime < (time() - $iDelay))
|
||||
{
|
||||
// Temporary files older than one day are deleted
|
||||
//echo "Supposed to delete: '".$sFile." (Unix Modification Time: $iModificationTime)'\n";
|
||||
@unlink($sFile);
|
||||
@@ -317,155 +348,189 @@ class ExcelExporter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function DisplayStatistics(Page $oPage)
|
||||
{
|
||||
$aStats = [
|
||||
$aStats = array(
|
||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||
];
|
||||
|
||||
if ($oPage instanceof CLIPage) {
|
||||
);
|
||||
|
||||
if ($oPage instanceof CLIPage)
|
||||
{
|
||||
$oPage->add($this->GetStatistics('text'));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add($this->GetStatistics('html'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function GetStatistics($sFormat = 'html')
|
||||
{
|
||||
$sStats = '';
|
||||
$aStats = [
|
||||
$aStats = array(
|
||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||
];
|
||||
|
||||
if ($sFormat == 'text') {
|
||||
foreach ($aStats as $sLabel => $sValue) {
|
||||
);
|
||||
|
||||
if ($sFormat == 'text')
|
||||
{
|
||||
foreach($aStats as $sLabel => $sValue)
|
||||
{
|
||||
$sStats .= "+------------------------------+----------+\n";
|
||||
$sStats .= sprintf("|%-30s|%10s|\n", $sLabel, $sValue);
|
||||
}
|
||||
$sStats .= "+------------------------------+----------+";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sStats .= '<table><tbody>';
|
||||
foreach ($aStats as $sLabel => $sValue) {
|
||||
foreach($aStats as $sLabel => $sValue)
|
||||
{
|
||||
$sStats .= "<tr><td>$sLabel</td><td>$sValue</td></tr>";
|
||||
}
|
||||
$sStats .= '</tbody></table>';
|
||||
|
||||
|
||||
}
|
||||
return $sStats;
|
||||
}
|
||||
|
||||
|
||||
public static function HumanDisplay($iSize)
|
||||
{
|
||||
$aUnits = ['B','KB','MB','GB','TB','PB'];
|
||||
return @round($iSize / pow(1024, ($i = floor(log($iSize, 1024)))), 2).' '.$aUnits[$i];
|
||||
$aUnits = array('B','KB','MB','GB','TB','PB');
|
||||
return @round($iSize/pow(1024,($i=floor(log($iSize,1024)))),2).' '.$aUnits[$i];
|
||||
}
|
||||
|
||||
|
||||
protected function CheckDataDir()
|
||||
{
|
||||
if (!is_dir(APPROOT."data/bulk_export")) {
|
||||
if(!is_dir(APPROOT."data/bulk_export"))
|
||||
{
|
||||
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
||||
clearstatcache();
|
||||
}
|
||||
if (!is_writable(APPROOT."data/bulk_export")) {
|
||||
if (!is_writable(APPROOT."data/bulk_export"))
|
||||
{
|
||||
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function GetStateFile($sToken = null)
|
||||
{
|
||||
if ($sToken == null) {
|
||||
if ($sToken == null)
|
||||
{
|
||||
$sToken = $this->sToken;
|
||||
}
|
||||
return APPROOT."data/bulk_export/$sToken.status";
|
||||
}
|
||||
|
||||
|
||||
protected function GetDataFile()
|
||||
{
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
|
||||
}
|
||||
|
||||
|
||||
protected function GetNewToken()
|
||||
{
|
||||
$iNum = rand();
|
||||
do {
|
||||
do
|
||||
{
|
||||
$iNum++;
|
||||
$sToken = sprintf("%08x", $iNum);
|
||||
$sFileName = $this->GetStateFile($sToken);
|
||||
$hFile = @fopen($sFileName, 'x');
|
||||
} while ($hFile === false);
|
||||
|
||||
}
|
||||
while($hFile === false);
|
||||
|
||||
fclose($hFile);
|
||||
return $sToken;
|
||||
}
|
||||
|
||||
|
||||
protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
|
||||
{
|
||||
$this->aFieldsList = [];
|
||||
|
||||
$this->aFieldsList = array();
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
|
||||
$this->aAuthorizedClasses = [];
|
||||
foreach ($aClasses as $sAlias => $sClassName) {
|
||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) {
|
||||
$this->aAuthorizedClasses = array();
|
||||
foreach($aClasses as $sAlias => $sClassName)
|
||||
{
|
||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO)
|
||||
{
|
||||
$this->aAuthorizedClasses[$sAlias] = $sClassName;
|
||||
}
|
||||
}
|
||||
$aAttribs = [];
|
||||
$this->aTableHeaders = [];
|
||||
foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
|
||||
$aList[$sAlias] = [];
|
||||
|
||||
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
|
||||
if (is_null($aFields) || (count($aFields) == 0)) {
|
||||
$aAttribs = array();
|
||||
$this->aTableHeaders = array();
|
||||
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||
{
|
||||
$aList[$sAlias] = array();
|
||||
|
||||
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if (is_null($aFields) || (count($aFields) == 0))
|
||||
{
|
||||
// Standard list of attributes (no link sets)
|
||||
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) {
|
||||
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField()))
|
||||
{
|
||||
$sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode;
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
|
||||
if ($bFieldsAdvanced) {
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||
{
|
||||
if ($bFieldsAdvanced)
|
||||
{
|
||||
$aList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE)) {
|
||||
$sRemoteClass = $oAttDef->GetTargetClass();
|
||||
foreach (MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode) {
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE))
|
||||
{
|
||||
$sRemoteClass = $oAttDef->GetTargetClass();
|
||||
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode)
|
||||
{
|
||||
$this->aFieldsList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Any other attribute
|
||||
$this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// User defined list of attributes
|
||||
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields)) {
|
||||
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields))
|
||||
{
|
||||
$this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($bFieldsAdvanced) {
|
||||
if ($bFieldsAdvanced)
|
||||
{
|
||||
$this->aTableHeaders['id'] = '0';
|
||||
}
|
||||
foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
|
||||
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||
{
|
||||
$sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
|
||||
if ($oAttDef instanceof AttributeDateTime) {
|
||||
if($oAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
$this->aTableHeaders[$sLabel] = 'datetime';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aTableHeaders[$sLabel] = 'string';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class ApplicationException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thrown when querying on an object that exists in the database but is archived
|
||||
*
|
||||
* @since 2.5.1 N°1108
|
||||
*/
|
||||
class ArchivedObjectException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class BulkChangeException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CSVParserException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class ConfigException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CoreCannotSaveObjectException
|
||||
*
|
||||
* Specialized exception to raise if {@link DBObject::CheckToWrite()} fails, which allow easy data retrieval
|
||||
*
|
||||
* @see \DBObject::DBInsertNoReload()
|
||||
* @see \DBObject::DBUpdate()
|
||||
*
|
||||
* @since 2.6.0 N°659 uniqueness constraint
|
||||
*/
|
||||
class CoreCannotSaveObjectException extends CoreException
|
||||
{
|
||||
/** @var string[] */
|
||||
private $aIssues;
|
||||
/** @var int */
|
||||
private $iObjectId;
|
||||
/** @var string */
|
||||
private $sObjectClass;
|
||||
|
||||
/**
|
||||
* CoreCannotSaveObjectException constructor.
|
||||
*
|
||||
* @param array $aContextData containing at least those keys : issues, id, class
|
||||
*/
|
||||
public function __construct($aContextData, $oPrevious = null)
|
||||
{
|
||||
$this->aIssues = $aContextData['issues'];
|
||||
$this->iObjectId = $aContextData['id'];
|
||||
$this->sObjectClass = $aContextData['class'];
|
||||
|
||||
$sIssues = implode(', ', $this->aIssues);
|
||||
parent::__construct($sIssues, $aContextData, '', $oPrevious);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHtmlMessage()
|
||||
{
|
||||
$sTitle = Dict::S('UI:Error:SaveFailed');
|
||||
$sContent = "<span><strong>".utils::HtmlEntities($sTitle)."</strong></span>";
|
||||
|
||||
if (count($this->aIssues) == 1) {
|
||||
$sIssue = reset($this->aIssues);
|
||||
$sContent .= " <span>".utils::HtmlEntities($sIssue)."</span>";
|
||||
} else {
|
||||
$sContent .= '<ul>';
|
||||
foreach ($this->aIssues as $sError) {
|
||||
$sContent .= "<li>".utils::HtmlEntities($sError)."</li>";
|
||||
}
|
||||
$sContent .= '</ul>';
|
||||
}
|
||||
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
public function getTextMessage()
|
||||
{
|
||||
$sTitle = Dict::S('UI:Error:SaveFailed');
|
||||
$sContent = $sTitle;
|
||||
|
||||
if (count($this->aIssues) == 1) {
|
||||
$sIssue = reset($this->aIssues);
|
||||
$sContent .= $sIssue;
|
||||
} else {
|
||||
foreach ($this->aIssues as $sError) {
|
||||
$sContent .= " ".$sError.", ";
|
||||
}
|
||||
}
|
||||
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
public function getIssues()
|
||||
{
|
||||
return $this->aIssues;
|
||||
}
|
||||
|
||||
public function getObjectId()
|
||||
{
|
||||
return $this->iObjectId;
|
||||
}
|
||||
|
||||
public function getObjectClass()
|
||||
{
|
||||
return $this->sObjectClass;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreException extends Exception
|
||||
{
|
||||
protected $m_sIssue;
|
||||
protected $m_sImpact;
|
||||
protected $m_aContextData;
|
||||
|
||||
/**
|
||||
* CoreException constructor.
|
||||
*
|
||||
* @param string $sIssue error message
|
||||
* @param array|null $aContextData key/value array, value MUST implements _toString
|
||||
* @param string $sImpact
|
||||
* @param Exception|null $oPrevious
|
||||
*/
|
||||
public function __construct($sIssue, $aContextData = null, $sImpact = '', $oPrevious = null)
|
||||
{
|
||||
$this->m_sIssue = $sIssue;
|
||||
$this->m_sImpact = $sImpact;
|
||||
|
||||
if (is_array($aContextData)) {
|
||||
$this->m_aContextData = $aContextData;
|
||||
} else {
|
||||
$this->m_aContextData = [];
|
||||
}
|
||||
|
||||
$sMessage = $sIssue;
|
||||
if (!empty($sImpact)) {
|
||||
$sMessage .= "($sImpact)";
|
||||
}
|
||||
if (count($this->m_aContextData) > 0) {
|
||||
$sMessage .= ": ";
|
||||
$aContextItems = [];
|
||||
foreach ($this->m_aContextData as $sKey => $value) {
|
||||
if (is_array($value)) {
|
||||
$aPairs = [];
|
||||
foreach ($value as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$aPairs[] = $key.'=>('.implode(', ', $val).')';
|
||||
} else {
|
||||
$aPairs[] = $key.'=>'.$val;
|
||||
}
|
||||
}
|
||||
$sValue = '{'.implode('; ', $aPairs).'}';
|
||||
} else {
|
||||
$sValue = $value;
|
||||
}
|
||||
$aContextItems[] = "$sKey = $sValue";
|
||||
}
|
||||
$sMessage .= implode(', ', $aContextItems);
|
||||
}
|
||||
parent::__construct($sMessage, 0, $oPrevious);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string code and message for log purposes
|
||||
*/
|
||||
public function getInfoLog()
|
||||
{
|
||||
return 'error_code='.$this->getCode().', message="'.$this->getMessage().'"';
|
||||
}
|
||||
|
||||
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
|
||||
{
|
||||
return utils::EscapeHtml($this->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* getTraceAsString() cannot be overrided and it is limited as only current exception stack is returned.
|
||||
* we need stack of all previous exceptions
|
||||
*
|
||||
* @uses __tostring() already does the work.
|
||||
* @since 2.7.2/ 3.0.0
|
||||
*/
|
||||
public function getFullStackTraceAsString()
|
||||
{
|
||||
return "".$this;
|
||||
}
|
||||
|
||||
public function getTraceAsHtml()
|
||||
{
|
||||
$aBackTrace = $this->getTrace();
|
||||
|
||||
return MyHelpers::get_callstack_html(0, $this->getTrace());
|
||||
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
|
||||
}
|
||||
|
||||
public function addInfo($sKey, $value)
|
||||
{
|
||||
$this->m_aContextData[$sKey] = $value;
|
||||
}
|
||||
|
||||
public function getIssue()
|
||||
{
|
||||
return $this->m_sIssue;
|
||||
}
|
||||
|
||||
public function getImpact()
|
||||
{
|
||||
return $this->m_sImpact;
|
||||
}
|
||||
|
||||
public function getContextData()
|
||||
{
|
||||
return $this->m_aContextData;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 N°2555
|
||||
*/
|
||||
class CorePortalInvalidActionRuleException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 3.0.0 N°3522
|
||||
*/
|
||||
class CoreTemplateException extends CoreException
|
||||
{
|
||||
public function __construct(Exception $oTwigException, string $sTemplatePath)
|
||||
{
|
||||
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
|
||||
parent::__construct($sMessage, null, '', $oTwigException);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreUnexpectedValue extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreWarning extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DeleteException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* A parameter stored in the {@link Config} is invalid
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class InvalidConfigParamException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458 object creation
|
||||
*/
|
||||
class InvalidExternalKeyValueException extends CoreUnexpectedValue
|
||||
{
|
||||
private const ENUM_PARAMS_OBJECT = 'current_object';
|
||||
private const ENUM_PARAMS_ATTCODE = 'attcode';
|
||||
private const ENUM_PARAMS_ATTVALUE = 'attvalue';
|
||||
private const ENUM_PARAMS_USER = 'current_user';
|
||||
|
||||
public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null)
|
||||
{
|
||||
$aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject).'::'.$oObject->GetKey();
|
||||
$aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode;
|
||||
$aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode);
|
||||
|
||||
$oCurrentUser = UserRights::GetUserObject();
|
||||
if (false === is_null($oCurrentUser)) {
|
||||
$aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser).'::'.$oCurrentUser->GetKey();
|
||||
}
|
||||
|
||||
parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious);
|
||||
}
|
||||
|
||||
public function GetAttCode(): string
|
||||
{
|
||||
return $this->getContextData()[self::ENUM_PARAMS_ATTCODE];
|
||||
}
|
||||
|
||||
public function GetAttValue(): string
|
||||
{
|
||||
return $this->getContextData()[self::ENUM_PARAMS_ATTVALUE];
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thrown when the password is not valid
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class InvalidPasswordAttributeOneWayPassword extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\TwigBase\Controller;
|
||||
|
||||
use Exception;
|
||||
|
||||
class PageNotFoundException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class SecurityException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class SynchroExceptionNotStarted extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class UserRightException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DictException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DictExceptionMissingString extends DictException
|
||||
{
|
||||
public function __construct($sLanguageCode, $sStringCode)
|
||||
{
|
||||
$aContext = [];
|
||||
$aContext['language_code'] = $sLanguageCode;
|
||||
$aContext['string_code'] = $sStringCode;
|
||||
parent::__construct('Missing localized string', $aContext);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user