Compare commits

..

1 Commits

Author SHA1 Message Date
Pierre Goiffon
b3369c8b0e Update version number for 2.5.3 beta 2019-07-02 14:54:36 +02:00
790 changed files with 25440 additions and 63358 deletions

View File

@@ -1,103 +0,0 @@
# Phpdoc dokuwiki template
This directory contains a template rendering iTop phpdoc as wiki pages.
conventional tag 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 tags where 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 with `ClassName::`
* 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 ans 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 enclose 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
```
composer require phpdocumentor/phpdocumentor:~2 --dev
```
## Generation
`.doc/bin/build-doc-object-manipulation` and `.doc/bin/build-doc-extensions` contains examples of doc. generation, beware: they have to be called from iTop root 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

View File

@@ -1,7 +0,0 @@
#!/bin/sh -x
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && vendor/bin/phpdoc -c .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

View File

@@ -1,8 +0,0 @@
#!/bin/sh -x
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/objects-manipulation/ && rm -rf data/phpdocumentor/temp/objects-manipulation/ && vendor/bin/phpdoc -c .doc/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

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdoc>
<title><![CDATA[iTop extensions]]></title>
<parser>
<target>../data/phpdocumentor/temp/extensions</target>
</parser>
<transformer>
<target>../data/phpdocumentor/output/extensions</target>
</transformer>
<transformations>
<template name="phpdoc-templates/combodo-wiki"/>
</transformations>
<files>
<file>../application/applicationextension.inc.php</file>
</files>
</phpdoc>

View File

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdoc>
<!--
/**
The documentation of this file can be found here : https://docs.phpdoc.org/references/configuration.html
it has to be completed by the CLI parameters documentation which is more comprehensive: https://docs.phpdoc.org/references/commands/project_run.html#usage
usage:
vendor/bin/phpdoc -c phpdoc-objects-manipulation.dist.xml
*/
-->
<title><![CDATA[iTop's objects manipulation API]]></title>
<parser>
<default-package-name>iTopORM</default-package-name>
<target>../data/phpdocumentor/temp/objects-manipulation</target>
<visibility>public,protected</visibility>
<markers>
<!--<item>TODO</item>-->
<!--<item>FIXME</item>-->
</markers>
<extensions>
<extension>php</extension>
</extensions>
</parser>
<transformer>
<target>../data/phpdocumentor/output/objects-manipulation</target>
</transformer>
<transformations>
<template name="phpdoc-templates/combodo-wiki"/>
</transformations>
<!--<logging>-->
<!--<level>warn</level>-->
<!--<paths>-->
<!--&lt;!&ndash;<default>data/phpdocumentor/log/objects-manipulation/{DATE}.log</default>&ndash;&gt;-->
<!--&lt;!&ndash;<errors>data/phpdocumentor/log/objects-manipulation/{DATE}.errors.log</errors>&ndash;&gt;-->
<!--<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>

View File

@@ -1,136 +0,0 @@
{% extends 'layout.txt.twig' %}
{% block content %}
<wrap button>[[start|🔙 Back]]</wrap>
{% if node.tags['internal'] is defined %}
====== {{ node.name }} ======
<WRAP alert>This class is "internal", and thus is not documented!</WRAP>
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
====== {{ node.name }} ======
<WRAP alert>This class is neither "api", "api-advanced", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
{% else %}
====== {{ node.name }} ======
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
{% if node.final %}<wrap notice>final</wrap>{% endif %}
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
{% if node.deprecated %}
=== **<del>Deprecated</del>**===
//{{ node.tags.deprecated[0].description }}//
{% endif %}
== {{ node.summary|replace({"\n":""})|raw }} ==
<html>{{ node.description|markdown|raw }}</html>
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
{% set class = node.parent %}
{% block hierarchy_element %}
{% if class and class.name is defined and class.name|trim != '' %}
==== parent ====
{% set child = class %}
{% set class = class.parent %}
{{ block('hierarchy_element') }}
[[{{ child.name }}|{{ child.name }}]]
{% endif %}
{% endblock %}
{% for interface in node.interfaces|sort_asc %}
{% if loop.first %}
==== Implements ====
{% endif %}
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
{% endfor %}
{% for trait in node.usedTraits|sort_asc %}
{% if loop.first %}
==== Uses traits ====
{% endif %}
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
{% endfor %}
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
{% set methods = node.inheritedMethods.merge(node.methods.merge(node.magicMethods)) %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '=====', sub_title_level: '=='} %}
<WRAP clear />
{% for method in methods|sort_asc
if method.visibility == 'public'
and (
method.tags['api'] is defined
or method.tags['api-advanced'] is defined
or method.tags['overwritable-hook'] is defined
or method.tags['extension-hook'] is defined
)
and (
node.tags['phpdoc-tuning-exclude-inherited'] is not defined
or method.parent.name == node.name
)
%}
{%- if loop.first %}
===== Public methods =====
{% endif %}
{{ block('method') }}
{% endfor %}
{% for method in methods|sort_asc if method.visibility == 'protected' and (method.tags['overwritable-hook'] is defined or method.tags['extension-hook'] is defined) %}
{%- if loop.first %}
===== Protected methods =====
{% endif %}
{{ block('method') }}
{% endfor %}
{% set constants = node.inheritedConstants.merge(node.constants) %}
{% if constants|length > 0 %}
===== Constants =====
{% for constant in constants|sort_asc %}
{{ block('constant') }}
{% endfor %}
{% endif %}
{#{% set properties = node.inheritedProperties.merge(node.properties.merge(node.magicProperties)) %}#}
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
{#{%- if loop.first %}#}
{#===== Public properties =====#}
{#{% endif %}#}
{#{{ block('property') }}#}
{#{% endfor %}#}
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
{#{%- if loop.first %}#}
{#===== Protected properties =====#}
{#{% endif %}#}
{#{{ block('property') }}#}
{#{% endfor %}#}
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
<wrap button>[[start|🔙 Back]]</wrap>
{% endblock %}

View File

@@ -1,31 +0,0 @@
{% block constant %}
<WRAP group box >
<WRAP twothirds column >
==== {{ constant.name }} ====
</WRAP>{# twothirds column#}
<WRAP third column>
{% if constant.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
{% if (node.parent is not null and constant.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
</WRAP>{# third column#}
== {{ constant.summary|replace({"\n":""})|raw }} ==
<html>{{ constant.description|markdown|raw }}</html>
{% if constant.deprecated %}
=== Deprecated ===
{{ constant.tags.deprecated[0].description|raw }}
{% endif %}
{% include 'includes/inherited-from.txt.twig' with {structure:constant} %}
{% include 'includes/see-also.txt.twig' with {structure:constant, title_level: '=='} %}
{% include 'includes/uses.txt.twig' with {structure:constant, title_level: '=='} %}
{% include 'includes/tags.txt.twig' with {structure:constant, title_level: '==', blacklist: ['link', 'see', 'var', 'deprecated', 'uses', 'package', 'subpackage', 'todo', 'code-example']} %}
</WRAP>{# group #}
{% endblock %}

View File

@@ -1,95 +0,0 @@
{% block method %}
<WRAP group box >
<WRAP twothirds column >
==== {{ method.name }} ====
</WRAP>{# twothirds column#}
<WRAP third column >
{% include 'includes/wrap-tags.txt.twig' with {structure:method, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
{% if method.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
{% if (node.parent is not null and method.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
{% if method.abstract %}<wrap warning>abstract</wrap> {% endif %}
{% if method.final %}<wrap notice>final</wrap> {% endif %}
<wrap notice>{{ method.visibility }}</wrap>
{% if method.static %}<wrap warning>static</wrap> {% endif %}
</WRAP>{# third column#}
== {{ method.summary|replace({"\n":""})|raw }} ==
<html>{{ method.description|markdown|raw }}</html>
<code php>{% if method.abstract %}abstract {% endif %}{% if method.final %}final {% endif %}{{ method.visibility }} {% if method.static %}static {% endif %}{{ method.name }}({% for argument in method.arguments %}{{ argument.isVariadic ? '...' }}{{ argument.name }}{{ argument.default ? (' = '~argument.default)|raw }}{% if not loop.last %}, {% endif %}{% endfor %})</code>
<WRAP twothirds column >
=== Parameters ===
{% if method.arguments|length > 0 -%}
^ types ^ name ^ default ^ description ^
{% for argument in method.arguments -%}
| **<nowiki>{{ argument.types|join('|')|raw }}</nowiki>** | {{ argument.name }} {{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }} | <nowiki>{{ argument.default|raw }}</nowiki> | {{ argument.description|trim|replace("\n", ' ')|raw }} |{{ "\r\n" }}
{%- endfor %}
{% else %}
//none//
{% endif %}
{#=== Parameters ===#}
{#{% if method.arguments|length > 0 -%}#}
{#{% for argument in method.arguments -%}#}
{#== {{ argument.name }} ==#}
{#{% set varDesc %}#}
{#<span style="margin:0 10px; 0 20px; font-weight: bold;">{{ argument.types|join('|') }}</span>#}
{#{{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }}#}
{#{{ argument.description|raw }}#}
{#{% endset %}#}
{#<html>{{ varDesc|markdown|raw }}</html>#}
{#{%- endfor %}#}
{#{% else %}#}
{#<wrap tip>This method has no parameter</wrap>#}
{#{% endif %}#}
{% if method.response and method.response.types|join() != 'void' %}
=== Returns ===
<html>{{ ('**' ~ method.response.types|join('|')|trim ~ '** ' ~ method.response.description)|markdown|raw }}</html>
{% endif %}
</WRAP>{# twothirds column#}
<WRAP third column >
{% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %}
=== Throws ===
{% for exception in method.tags.throws -%}
{% if loop.length > 1 %} * {% endif %}''{{ exception.types|join('|')|raw }}'' <nowiki>{{ exception.description|raw }}</nowiki>
{% endfor %}
{% endif %}
{% include 'includes/inherited-from.txt.twig' with {structure:method} %}
{% include 'includes/see-also.txt.twig' with {structure:method, title_level: '==='} %}
{% include 'includes/uses.txt.twig' with {structure:method, title_level: '==='} %}
{% include 'includes/used-by.txt.twig' with {structure:method, title_level: '==='} %}
{% include 'includes/tags-with-description.txt.twig' with {structure:method, title_level: '===', WRAP: 'info', tagsWithDescription: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
{% include 'includes/tags.txt.twig' with {structure:method, title_level: '===', blacklist: ['todo', 'link', 'see', 'abstract', 'example', 'param', 'return', 'access', 'deprecated', 'throws', 'throw', 'uses', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'used-by', 'inheritdoc', 'code-example']} %}
</WRAP>{# third column#}
{% include 'includes/code-examples.txt.twig' with {structure:method, title_level: '==='} %}
</WRAP>{# group #}
{% endblock %}

View File

@@ -1,49 +0,0 @@
{% block property %}
<WRAP group box>
<WRAP twothirds column >
==== ${{ property.name }} ====
</WRAP>{# twothirds column#}
<WRAP third column>
{% if property.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
{% if (node.parent is not null and property.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
</WRAP>{# third column#}
== {{ property.summary|replace({"\n":""})|raw }} ==
<html>{{ property.description|markdown|raw }}</html>
{% if property.var.0.description %}<html>{{ property.var.0.description|markdown|raw }}</html>{% endif %}
{#{% if property.types %}#}
{#== Type ==#}
{#{% for type in property.types %}#}
{#{% if loop.length > 1 %} * {% endif %}{{ type|raw }} : {{ type.description|raw }}#}
{#{% endfor %}#}
{#{{ property.types|join('|')|raw }}#}
{#{% endif %}#}
{% if property.deprecated %}
== Deprecated ==
{{ property.tags.deprecated[0].description }}
{% endif %}
{% include 'includes/inherited-from.txt.twig' with {structure:property} %}
{% include 'includes/see-also.txt.twig' with {structure:property, title_level: '=='} %}
{% include 'includes/uses.txt.twig' with {structure:property, title_level: ''} %}
{% include 'includes/tags.txt.twig' with {structure:property, title_level: '==', blacklist: ['link', 'see', 'access', 'var', 'deprecated', 'uses', 'todo', 'code-example']} %}
<code php>{{ property.visibility }} ${{ property.name }}{% if property.types %} : {{ property.types|join('|')|raw }}{% endif %}</code>
</WRAP>{# group #}
{% endblock %}

View File

@@ -1 +0,0 @@
{{ node.source|raw }}

View File

@@ -1,122 +0,0 @@
{% extends 'layout.txt.twig' %}
{% block javascripts %}
{% endblock %}
{% block content %}
{#<section class="row-fluid">#}
{#<div class="span2 sidebar">#}
{#{% set namespace = project.namespace %}#}
{#{{ block('sidebarNamespaces') }}#}
{#</div>#}
{#</section>#}
{#<section class="row-fluid">#}
====== {{ node.path|split('/')|slice(0,-1)|join('/') }}{{ node.name }} ======
{{ node.summary }}
<html>{{ node.description|markdown|raw }}</html>
{% if node.traits|length > 0 %}
===== Traits =====
{% for trait in node.traits %}
<tr>
<td>{{ trait|raw }}</td>
<td><em>{{ trait.summary }}</em></td>
</tr>
{% endfor %}
{% endif %}
{% if node.interfaces|length > 0 %}
===== Interfaces =====
{% for interface in node.interfaces %}
<tr>
<td>{{ interface|raw }}</td>
<td><em>{{ interface.summary }}</em></td>
</tr>
{% endfor %}
{% endif %}
{% if node.classes|length > 0 %}
===== Classes =====
{% for class in node.classes %}
{{ class|raw }}
<em>{{ class.summary }}</em>
{% endfor %}
{% endif %}
{% if node.package is not empty and node.package != '\\' %}
===== Package =====
{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}
{% endif %}
{% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
{% if loop.first %}
===== See also =====
{% endif %}
{% for tag in tags %}
<dd><a href="{{ tag.reference ?: tag.link }}"><div class="namespace-wrapper">{{ tag.description ?: tag.reference }}</div></a></dd>
{% endfor %}
{% endfor %}
<h2>Tags</h2>
<table class="table table-condensed">
{% for tagName,tags in node.tags if tagName not in ['link', 'see', 'package', 'subpackage'] %}
<tr>
<th>
{{ tagName }}
</th>
<td>
{% for tag in tags %}
{{ tag.description|markdown|raw }}
{% endfor %}
</td>
</tr>
{% else %}
<tr><td colspan="2"><em>None found</em></td></tr>
{% endfor %}
</table>
</aside>
</div>
{% if node.constants|length > 0 %}
<div class="row-fluid">
<section class="span8 content file">
<h2>Constants</h2>
</section>
<aside class="span4 detailsbar"></aside>
</div>
{% for constant in node.constants %}
{{ block('constant') }}
{% endfor %}
{% endif %}
{% if node.functions|length > 0 %}
<div class="row-fluid">
<section class="span8 content file">
<h2>Functions</h2>
</section>
<aside class="span4 detailsbar"></aside>
</div>
{% for method in node.functions %}
{{ block('method') }}
{% endfor %}
{% endif %}
</div>
</section>
<div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="source-view-label">{{ node.file.name }}</h3>
</div>
<div class="modal-body">
<pre data-src="{{ path('files/' ~ node.path ~ '.txt')|raw }}" class="language-php line-numbers"></pre>
</div>
</div>
{% endblock %}

View File

@@ -1,42 +0,0 @@
{% extends 'layout.html.twig' %}
{% block stylesheets %}
<link href="{{ path('css/jquery.iviewer.css') }}" rel="stylesheet" media="all"/>
<style>
#viewer {
position: relative;
width: 100%;
}
.wrapper {
overflow: hidden;
}
</style>
{% endblock %}
{% block javascripts %}
<script src="{{ path('js/jquery.mousewheel.js') }}" type="text/javascript"></script>
<script src="{{ path('js/jquery.iviewer.js') }}" type="text/javascript"></script>
<script type="text/javascript">
$(window).resize(function(){
$("#viewer").height($(window).height() - 100);
});
$(document).ready(function() {
$("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
$('#viewer img').bind('dragstart', function(event){
event.preventDefault();
});
$(window).resize();
});
</script>
{% endblock %}
{% block content %}
<div class="row-fluid">
<div class="span12">
<div class="wrapper">
<div id="viewer" class="viewer"></div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,5 +0,0 @@
# Fixes a vulnerability in CentOS: http://stackoverflow.com/questions/20533279/prevent-php-from-parsing-non-php-files-such-as-somefile-php-txt
<FilesMatch \.php\.txt$>
RemoveHandler .php
ForceType text/plain
</FilesMatch>

View File

@@ -1,34 +0,0 @@
{% if title_level is not defined %}
{%- set title_level = '==' -%}
{% endif %}
{% if sub_title_level is not defined %}
{%- set sub_title_level = title_level|slice(1) -%}
{% endif %}
{% if sub_title_level == '=' %}
{%- set sub_title_level = '' -%}
{% endif %}
{#{% for tagName,tags in structure.tags if tagName in ['code-example'] %}#}
{#{% if loop.first %}#}
{#{{title_level}} Examples {{title_level}}#}
{#{% endif %}#}
{#{% for tag in tags %}#}
{#{%- set descToken = tag.description|split("\n", 2) -%}#}
{#{%- set title = descToken[0] -%}#}
{#{%- set code = descToken[1] -%}#}
{#{{sub_title_level}} {{ title }} {{sub_title_level}}#}
{#<code php>{{ code|raw }}</code>#}
{#{% endfor %}#}
{#{% endfor %}#}
{% for tagName,tags in structure.tags if tagName in ['example'] %}
{% if loop.first %}
{{title_level}} Examples {{title_level}}
{% endif %}
{% for tag in tags %}
{{ sub_title_level }} {{ tag.filePath|escape }}{{ sub_title_level }}
<code php>{{ tag.description|raw }}</code>
{% endfor %}
{% endfor %}

View File

@@ -1,12 +0,0 @@
{% if title_level is not defined %}
{% set title_level='' %}
{% endif %}
{% if (node.parent is null) %}
{{title_level}} File {{ structure.path }} {{title_level}}
{% endif %}
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
{{title_level}} Inherited from {{title_level}}
[[{{structure.parent}}|{{structure.parent}}]]
{% endif %}

View File

@@ -1,26 +0,0 @@
{% for structure in structures|sort_asc if structure.tags['internal'] is not defined and (structure.tags['api'] is defined or structure.tags['api-advanced'] is defined or structure.tags['overwritable-hook'] is defined or structure.tags['extension-hook'] is defined ) %}
{#{{ structure|raw }}#}
{% set structureName = structure|trim('\\', 'left') %}
<WRAP group box>
<WRAP twothirds column >
==== {{ structureName }} ====
</WRAP>{# twothirds column#}
<WRAP third column>
{% if structure.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
{% if structure.abstract %}<wrap warning>abstract</wrap>{% endif %}
{% if structure.final %}<wrap notice>final</wrap>{% endif %}
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
{% include 'includes/wrap-tags.txt.twig' with {structure:structure, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
</WRAP>{# third column#}
{{ structure.summary|raw }}
[[{{structureName}}|More informations]]
</WRAP>{# group #}
{% endfor %}

View File

@@ -1,26 +0,0 @@
{% if title_level is not defined %}
{%- set title_level='==' -%}
{% endif %}
{% for tagName,tags in structure.tags if tagName in ['link', 'see'] %}
{% if loop.first %}
{{title_level}} See also {{title_level}}
{% endif %}
{% for tag in tags %}
{%- set linkTag = tag.reference|trim('\\', 'left') -%}
{% if not('()' in linkTag or '$' in linkTag or node.name in linkTag or '::' in linkTag ) %}
{%- set linkTag = linkTag|lower -%}
{% elseif node.name~'::' in linkTag %}
{%- set linkTag = linkTag|replace({(node.name~'::'): '#'})|lower -%}
{% elseif '::' in linkTag -%}
{%- set linkTag = linkTag|replace({'::': '#'})|lower -%}
{% else %}
{%- set linkTag = '#' ~ linkTag|lower -%}
{%- endif %}
{% if loop.length > 1 %} * {% endif %}{% if tag.reference is not empty -%}
[[{{linkTag}}|{{ (tag.reference)|trim('\\', 'left') }}]] {% if tag.description|trim is not empty %}: {{ tag.description|trim('\\', 'left') }} {% endif %}
{%- else -%}
{#{{ tag.description|trim('\\', 'left') }}#}
{% endif %}
{% endfor %}
{% endfor %}

View File

@@ -1,56 +0,0 @@
{% if tag is not defined -%}
{# Do not display @api if @api-advanced is also present #}
{%- set tag = "api" -%}
{%- endif %}
{% if hidden_by is not defined -%}
{# Do not display @api if @api-advanced is also present #}
{%- set hidden_by = {"api" : "api-advanced"} -%}
{%- endif %}
{% for method in methods|sort_asc
if (method.visibility == 'public')
and (
method.tags[tag] is defined
and (
hidden_by[tag] is not defined or method.tags[hidden_by[tag]] is not defined
)
)
%}
{%- if loop.first %}
{% if tag == 'api' %}
===== API synthesis =====
<WRAP>
List of the public API methods.
When manipulating {{ node.name }}, You can call those methods:
</WRAP>
{% elseif tag == 'api-advanced' %}
===== Advanced API synthesis =====
<WRAP>
List of advanced API methods
Beware they usage is recommended to advanced users only.
</WRAP>
{% elseif tag == 'overwritable-hook' %}
===== overwritable-hook synthesis =====
<WRAP >When inheriting from {{ node.name }},
you can overwrite those methods in order to add custom logic:
</WRAP>
{% elseif tag == 'extension-hook' %}
===== extension-hook synthesis =====
<WRAP >
When inheriting from {{ node.name }},
you can extend the behaviour of iTop by implementing:
</WRAP>
{% endif %}
{% endif %}
{% set sanitizedMethod = method|trim('\\', 'left')|replace({(node.name~'::'): ''}) %}
{% if '::' in sanitizedMethod -%}
{%- if node.tags['phpdoc-tuning-exclude-inherited'] is not defined %}
* [[{{sanitizedMethod|replace({'::': '#'})|lower}}|↪{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
{% endif %}
{%- else %}
* [[#{{sanitizedMethod}}|{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
{% endif %}
{% endfor %}

View File

@@ -1,20 +0,0 @@
{% if title_level is not defined %}
{% set title_level = '==' %}
{% endif %}
{%- for tagName,tags in structure.tags if tagName in tagsWithDescription -%}
{%- for tag in tags -%}
{%- if tag.description is not empty -%}
{%- if WRAP is defined -%}
<WRAP {{WRAP}}>
{%- endif -%}
{{title_level}} {{ tagName }} {{title_level}}
{{ tag.description|escape }}
{%- if WRAP is defined -%}
</WRAP>
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}

View File

@@ -1,22 +0,0 @@
{% if title_level is not defined %}
{% set title_level='=====' %}
{% endif %}
{% if blacklist is not defined %}
{% set blacklist =['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'api', 'api-advanced', 'todo', 'code-example'] %}
{% endif %}
{% if hidden_by is not defined -%}
{# Do not display @api if @api-advanced is also present #}
{%- set hidden_by = {"api" : "api-advanced"} -%}
{%- endif %}
{#^ {% for tagName,tags in structure.tags if tagName not in blacklist -%}#}
{#{{ tagName }} ^#}
{#{%- endfor %}#}
{% for tagName,tags in structure.tags if tagName not in blacklist and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
{%- if loop.first %}
{{title_level}} Tags {{title_level}}
{% endif %}
^ {{ tagName }} | {% for tag in tags %}{{ tag.version ? tag.version ~ ' ' : '' }}{{ tag.description}}{% endfor %} |
{% endfor %}

View File

@@ -1,24 +0,0 @@
{% if title_level is not defined %}
{% set title_level='' %}
{% endif %}
{% for tagName,tags in structure.tags if tagName in ['used-by'] %}
{% if loop.first %}
{{title_level}} Used by {{title_level}}
{% endif %}
{% for tag in tags %}
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
{% endfor %}
{% endfor %}
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
{#{% if loop.first %}#}
{#<dt>Uses</dt>#}
{#{% endif %}#}
{#{% for tag in tags %}#}
{#<dd>{{ tag.reference|raw }}</dd>#}
{#{% endfor %}#}
{#{% endfor %}#}

View File

@@ -1,24 +0,0 @@
{% if title_level is not defined %}
{% set title_level='' %}
{% endif %}
{% for tagName,tags in structure.tags if tagName in ['uses'] %}
{% if loop.first %}
{{title_level}} Uses {{title_level}}
{% endif %}
{% for tag in tags %}
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
{% endfor %}
{% endfor %}
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
{#{% if loop.first %}#}
{#<dt>Uses</dt>#}
{#{% endif %}#}
{#{% for tag in tags %}#}
{#<dd>{{ tag.reference|raw }}</dd>#}
{#{% endfor %}#}
{#{% endfor %}#}

View File

@@ -1,11 +0,0 @@
{% if wrap is not defined -%}
{% set wrap = 'notice' %}
{%- endif -%}
{% if hidden_by is not defined -%}
{# Do not display @api if @api-advanced is also present #}
{%- set hidden_by = {"api" : "api-advanced"} -%}
{%- endif %}
{%- for tagName,tags in structure.tags if tagName in wrapTags and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
<wrap {{wrap}}>{{tagName}}</wrap>
{% endfor %}

View File

@@ -1,121 +0,0 @@
{% extends 'layout.txt.twig' %}
{% block content %}
<wrap button>[[start|🔙 Back]]</wrap>
{% if node.tags['internal'] is defined %}
====== {{ node.name }} ======
<WRAP alert>This interface is "internal", and thus is not documented!</WRAP>
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
====== {{ node.name }} ======
<WRAP alert>This interface is neither "api", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
{% else %}
====== {{ node.name }} ======
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
{% if node.final %}<wrap notice>final</wrap>{% endif %}
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
{% if node.deprecated %}
=== **<del>Deprecated</del>**===
//{{ node.tags.deprecated[0].description }}//
{% endif %}
== {{ node.summary|replace({"\n":""})|raw }} ==
<html>{{ node.description|markdown|raw }}</html>
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
{% set class = node.parent %}
{% block hierarchy_element %}
{% if class and class.name is defined and class.name|trim != '' %}
==== parent ====
{% set child = class %}
{% set class = class.parent %}
{{ block('hierarchy_element') }}
[[{{ child.name }}|{{ child.name }}]]
{% endif %}
{% endblock %}
{% for interface in node.interfaces|sort_asc %}
{% if loop.first %}
==== Implements ====
{% endif %}
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
{% endfor %}
{% for trait in node.usedTraits|sort_asc %}
{% if loop.first %}
==== Uses traits ====
{% endif %}
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
{% endfor %}
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
{% set methods = node.inheritedMethods.merge(node.methods) %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
<WRAP clear />
{% for method in methods|sort_asc if method.visibility == 'public' %}
{%- if loop.first %}
===== Public methods =====
{% endif %}
{{ block('method') }}
{% endfor %}
{% for method in methods|sort_asc if method.visibility == 'protected' %}
{%- if loop.first %}
===== Protected methods =====
{% endif %}
{{ block('method') }}
{% endfor %}
{% set constants = node.inheritedConstants.merge(node.constants) %}
{% if constants|length > 0 %}
===== Constants =====
{% for constant in constants|sort_asc %}
{{ block('constant') }}
{% endfor %}
{% endif %}
{#{% set properties = node.inheritedProperties.merge(node.properties) %}#}
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
{#{%- if loop.first %}#}
{#===== Public properties =====#}
{#{% endif %}#}
{#{{ block('property') }}#}
{#{% endfor %}#}
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
{#{%- if loop.first %}#}
{#===== Protected properties =====#}
{#{% endif %}#}
{#{{ block('property') }}#}
{#{% endfor %}#}
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
<wrap button>[[start|🔙 Back]]</wrap>
{% endblock %}

View File

@@ -1,5 +0,0 @@
{% use 'elements/constant.txt.twig' %}
{% use 'elements/property.txt.twig' %}
{% use 'elements/method.txt.twig' %}
{% block content %}{% endblock %}

View File

@@ -1,51 +0,0 @@
{% extends 'layout.txt.twig' %}
{% block content %}
{% set namespace = project.namespace %}
{{ block('sidebarNamespaces') }}
{#{{ node.parent|raw }}#}
{#====== {{ node.parent.fullyQualifiedStructuralElementName }}{{ node.name }} ======#}
{% if node.children|length > 0 %}
=====Namespaces=====
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.children} %}
----
{% endif %}
{% if node.traits|length > 0 %}
===== Traits =====
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.traits} %}
----
{%- endif %}
{% if node.interfaces|length > 0 %}
===== Interfaces =====
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.interfaces} %}
----
{% endif %}
{% if node.classes|length > 0 %}
===== Classes =====
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.classes} %}
----
{% endif %}
{#{% if node.constants|length > 0 %}#}
{#===== Constants =====#}
{#{% for constant in node.constants|sort_asc %}#}
{# {{ block('constant') }}#}
{#{% endfor %}#}
{#{% endif %}#}
{#{% if node.functions|length > 0 %}#}
{#===== Functions =====#}
{#{% for method in node.functions|sort_asc %}#}
{# {{ block('method') }}#}
{#{% endfor %}#}
{#{% endif %}#}
{% endblock %}

View File

@@ -1,49 +0,0 @@
====== Deprecated elements ======
{#{% for element in project.indexes.elements if element.deprecated %}#}
{#{% if element.file.path != previousPath %}#}
{#<li><a href="#{{ element.file.path }}"><i class="icon-file"></i> {{ element.file.path }}</a></li>#}
{#{% endif %}#}
{#{% set previousPath = element.file.path %}#}
{#{% endfor %}#}
{% for element in project.indexes.elements if element.deprecated %}
{% if element.file.path != previousPath %}
{% if previousPath %}
</WRAP>{# group #}
{% endif %}
{#<a name="{{ element.file.path }}" id="{{ element.file.path }}"></a>#}
===== {{ element.file.path }} ({{ element.tags.deprecated.count }} found)=====
<WRAP group >
<WRAP third column >
Element
</WRAP>{# third column#}
<WRAP third column >
Line
</WRAP>{# third column#}
<WRAP third column >
Description
</WRAP>{# third column#}
{% endif %}
{% for tag in element.tags.deprecated %}
<WRAP group >
<WRAP third column >
{{ element.fullyQualifiedStructuralElementName }}
</WRAP>{# third column#}
<WRAP third column >
{{ element.line }}
</WRAP>{# third column#}
<WRAP third column >
{{ tag.description }}
</WRAP>{# third column#}
{% endfor %}
</WRAP>{# group #}
{% set previousPath = element.file.path %}
{% else %}
<WRAP info>No deprecated elements have been found in this project.</WRAP>
{% endfor %}

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<template>
<author>Bruno DA SILVA</author>
<email>contact [at] combodo.com</email>
<version>1.0.0</version>
<copyright>Combodo 2018</copyright>
<description><![CDATA[
Forked from the clean theme of https://github.com/phpDocumentor/phpDocumentor2 provided under the MIT licence.
The original work is copyright "Mike van Riel".
------------------------------------------------------------------------------------------------------------------
To improve performance you can add the following to your .htaccess:
<ifModule mod_deflate.c>
<filesMatch "\.(js|css|html)$">
SetOutputFilter DEFLATE
</filesMatch>
</ifModule>
]]></description>
<transformations>
<transformation writer="twig" query="namespace" source="templates/combodo-wiki/namespace.txt.twig" artifact="start.txt"/>
<transformation writer="twig" query="indexes.classes" source="templates/combodo-wiki/class.txt.twig" artifact="{{name}}.txt"/>
<transformation writer="twig" query="indexes.interfaces" source="templates/combodo-wiki/interface.txt.twig" artifact="{{name}}.txt" />
</transformations>
</template>

View File

@@ -1,9 +0,0 @@
[gitflow "branch"]
master = master
develop = develop
[gitflow "prefix"]
feature = feature/
release = release/
hotfix = hotfix/
versiontag =
support = support/

4
.gitignore vendored
View File

@@ -33,8 +33,7 @@ test/vendor/*
!/.idea/inspectionProfiles
!/.idea/inspectionProfiles/*
#phpdocumentor temp file
ast.dump
# CMake
cmake-build-*/
@@ -122,4 +121,3 @@ local.properties
.cache-main
.scala_dependencies
.worksheet

View File

@@ -1,11 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="320" />
<HTMLCodeStyleSettings>
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="html,body,thead,tbody,tfoot,script,style" />
<option name="HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES" value="4" />
</HTMLCodeStyleSettings>
<PHPCodeStyleSettings>
<option name="CONCAT_SPACES" value="false" />
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
@@ -26,7 +20,6 @@
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="PHP">
<option name="RIGHT_MARGIN" value="320" />
<option name="BLANK_LINES_AFTER_PACKAGE" value="1" />
<option name="BRACE_STYLE" value="2" />
<option name="ELSE_ON_NEW_LINE" value="true" />
@@ -48,10 +41,5 @@
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

2
.idea/encodings.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -1,44 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Combodo" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="PhpTooManyParametersInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="limit" value="7" />
</inspection_tool>
<inspection_tool class="PhpUndefinedClassInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="DONT_REPORT_MULTI_RESOLVE" value="true" />
</inspection_tool>
<inspection_tool class="PhpUndefinedMethodInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnhandledExceptionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnusedLocalVariableInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_INSIDE_LIST" value="true" />
</inspection_tool>
<inspection_tool class="PhpUnusedParameterInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_ABSTRACT_CLASS" value="true" />
</inspection_tool>
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantConditionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNullComparisonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlPostgresqlSelectFromProcedureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,19 +1,154 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="PhpTooManyParametersInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="limit" value="7" />
<inspection_tool class="BladeControlDirectives" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckEmptyScriptTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckImageSize" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckNodeTest" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckValidXmlInScriptTagBody" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptArgumentsOutsideFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptFunctionSignatures" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptInfiniteLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptLiteralNotFunction" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptSillyAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptSwitchStatementWithNoDefaultBranch" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptUnusedLocalSymbols" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ComposeFileStructure" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssFloatPxLength" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidAtRule" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidCharsetRule" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidElement" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidFunction" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidHtmlTagReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidImport" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidMediaFeature" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidPropertyValue" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidPseudoSelector" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssMissingComma" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssNegativeValue" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssNoGenericFontName" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssOptimizeSimilarProperties" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssRedundantUnit" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssUnitlessNumber" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssUnknownProperty" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myCustomPropertiesEnabled" value="false" />
<option name="myIgnoreVendorSpecificProperties" value="false" />
<option name="myCustomPropertiesList">
<value>
<list size="0" />
</value>
</option>
</inspection_tool>
<inspection_tool class="PhpUndefinedClassInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="DONT_REPORT_MULTI_RESOLVE" value="true" />
<inspection_tool class="CssUnknownTarget" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedClass" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedCustomPropertySet" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberExamplesColon" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberMissedExamples" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberTableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberUndefinedStep" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DockerFileArgumentCount" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DuplicateKeyInSection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateSectionInFile" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EmptyEventHandler" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="FileHeaderInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="GherkinBrokenTableInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="GherkinMisplacedBackground" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="HamlNestedTagContent" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HardwiredNamespacePrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlDeprecatedTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlExtraClosingTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlFormInputWithoutLabel" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlMissingClosingTag" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="HtmlPresentationalElement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAnchorTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAttribute" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myValues">
<value>
<list size="0" />
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="PhpUnhandledExceptionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnusedParameterInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_ABSTRACT_CLASS" value="true" />
<inspection_tool class="HtmlUnknownBooleanAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownTag" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myValues">
<value>
<list size="6">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="HtmlUnknownTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ImplicitTypeConversion" enabled="false" level="WARNING" enabled_by_default="false">
<option name="BITS" value="1720" />
<option name="FLAG_EXPLICIT_CONVERSION" value="true" />
<option name="IGNORE_NODESET_TO_BOOLEAN_VIA_STRING" value="true" />
</inspection_tool>
<inspection_tool class="IndexZeroUsage" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSLastCommaInArrayLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSLastCommaInObjectLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnresolvedFunction" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnresolvedVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="LossyEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MissingSinceTagDocInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NonAsciiCharacters" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpDocMissingReturnTagInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpDocMissingThrowsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpIncludeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpRedundantClosingTagInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedClassConstantInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedClassInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedConstantInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedFieldInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedFunctionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedGotoLabelInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedNamespaceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUnusedParameterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RedundantTypeConversion" enabled="false" level="WARNING" enabled_by_default="false">
<option name="CHECK_ANY" value="false" />
</inspection_tool>
<inspection_tool class="RequiredAttributes" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myAdditionalRequiredHtmlAttributes" value="" />
</inspection_tool>
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantConditionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNullComparisonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlPostgresqlSelectFromProcedureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TaskProblemsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptPreferShortImport" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlDefaultAttributeValue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlUnboundNsPrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XsltUnusedDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XsltVariableShadowing" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Combodo" />
<version value="1.0" />
</settings>
</component>

View File

141
README.md
View File

@@ -1,141 +0,0 @@
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
<img src="https://www.combodo.com/logos/logo-itop.svg">
</a></p>
# 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]
- [HelpDesk][11] and Incident Management
- [Service and Contract Management][12]
- [Change][13] Management
- Configurable [SLA][14] Management
- Graphical [impact analysis][15]
- [CSV import][16] tool for any data
- Consistency [audit][17] to check data quality
- [Data synchronization][18] (for data federation)
## Resources
- [iTop Forums][1]: for support request
- [iTop Tickets][2]: for feature requests and bug reports
- [Releases download][3]
- [iTop documentation][4] for iTop and official extensions
- [iTop extensions][5] for discovering and installing extensions
## Releases
### Version 2.6
- [Changes since the previous version][58]
- [New features][59]
- [Migration notes][60]
- [Download iTop 2.6.1][61]
### Version 2.5
- [Changes since the previous version][54]
- [New features][55]
- [Migration notes][56]
- [Download iTop 2.5.1][57]
### Version 2.4
- [Changes since the previous version][50]
- [New features][51]
- [Migration notes][52]
- [Download iTop 2.4.1][53]
# About Us
iTop development is sponsored, led and supported by [Combodo][0].
# Contributors
We would like to give a special thank you to the people from the community who contributed to this project, including:
- Alves, David
- Beck, Pedro
- Bilger, Jean-François
- Bostoen, Jeffrey
- Cardoso, Anderson
- Cassaro, Bruno
- Casteleyn, Thomas
- Castro, Randall Badilla
- Colantoni, Maria Laura
- Dvořák, Lukáš
- Goethals, Stefan
- Gumble, David
- Hippler, Lars
- Khamit, Shamil
- Kincel, Martin
- Konečný, Kamil
- Kunin, Vladimir
- Lassiter, Dennis
- Lucas, Jonathan
- Malik, Remie
- Rosenke, Stephan
- Seki, Shoji
- Shilov, Vladimir
- Tulio, Marco
- Turrubiates, Miguel
#### Aliases
- chifu1234
- cprobst
- Karkoff1212
- larhip
- Laura
- Purple Grape
- Schlobinux
- theBigOne
- ulmerspatz
#### Companies
- Hardis
- ITOMIG
[0]: https://www.combodo.com
[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
[5]: https://store.itophub.io/en_US/
[10]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#configuration_management_cmdb
[11]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#ticketing
[12]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#service_management
[13]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#change_management
[14]: https://www.itophub.io/wiki/page?id=2_5_0%3Aimplementation%3Astart#service_level_agreements_and_targets
[15]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Aactions#relations
[16]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Abulk_modify#uploading_data
[17]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Aaudit
[18]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadvancedtopics%3Adata_synchro_overview
[50]: https://www.itophub.io/wiki/page?id=2_4_0:release:change_log
[51]: https://www.itophub.io/wiki/page?id=2_4_0:release:2_4_whats_new
[52]: https://www.itophub.io/wiki/page?id=2_4_0:install:230_to_240_migration_notes
[53]: https://sourceforge.net/projects/itop/files/itop/2.4.1
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.1

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2018 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
@@ -20,7 +20,7 @@
/**
* Class ApplicationContext
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -31,12 +31,6 @@ require_once(APPROOT."/application/utils.inc.php");
*/
interface iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
*/
public static function MakeObjectURL($sClass, $iId);
}
@@ -45,13 +39,6 @@ interface iDBObjectURLMaker
*/
class iTopStandardURLMaker implements iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
* @throws \Exception
*/
public static function MakeObjectURL($sClass, $iId)
{
$sPage = DBObject::ComputeStandardUIPage($sClass);
@@ -66,13 +53,6 @@ class iTopStandardURLMaker implements iDBObjectURLMaker
*/
class PortalURLMaker implements iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
* @throws \Exception
*/
public static function MakeObjectURL($sClass, $iId)
{
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
@@ -94,20 +74,10 @@ class PortalURLMaker implements iDBObjectURLMaker
*/
class ApplicationContext
{
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
*/
protected static $aDefaultValues; // Cache shared among all instances
public function __construct($bReadContext = true)
{
$this->aNames = array(
@@ -119,13 +89,11 @@ class ApplicationContext
}
}
/**
* 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
*/
protected function ReadContext()
{
if (!isset(self::$aDefaultValues))
@@ -142,26 +110,20 @@ class ApplicationContext
}
// 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
// fixed to this org
if ($sName == 'org_id')
{
if (MetaModel::IsValidClass('Organization'))
{
$oSearchFilter = new DBObjectSearch('Organization');
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
$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)
{
// Only one possible value for org_id, set it in the context
$oOrg = $oSet->Fetch();
self::$aDefaultValues[$sName] = $oOrg->GetKey();
}
// Only one possible value for org_id, set it in the context
$oOrg = $oSet->Fetch();
self::$aDefaultValues[$sName] = $oOrg->GetKey();
}
}
}
@@ -169,15 +131,12 @@ class ApplicationContext
}
$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
* @return mixed The value for this parameter
*/
public function GetCurrentValue($sParamName, $defaultValue = '')
{
if (isset($this->aValues[$sParamName]))
@@ -189,7 +148,7 @@ class ApplicationContext
/**
* Returns the context as string with the format name1=value1&name2=value2....
* @return string The context as a string to be appended to an href property
* return string The context as a string to be appended to an href property
*/
public function GetForLink()
{
@@ -203,7 +162,7 @@ class ApplicationContext
/**
* 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
* return string The context as a sequence of <input type="hidden" /> tags
*/
public function GetForForm()
{
@@ -217,7 +176,7 @@ class ApplicationContext
/**
* Returns the context as a hash array 'parameter_name' => value
* @return array The context information
* return array The context information
*/
public function GetAsHash()
{
@@ -240,7 +199,8 @@ 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
* @param string $sParamName Name of the parameter to remove
* @return none
*/
public function Reset($sParamName)
{
@@ -252,11 +212,6 @@ class ApplicationContext
/**
* Initializes the given object with the default values provided by the context
*
* @param \DBObject $oObj
*
* @throws \Exception
* @throws \CoreUnexpectedValue
*/
public function InitObjectFromContext(DBObject &$oObj)
{
@@ -283,11 +238,13 @@ class ApplicationContext
}
}
}
static $m_sUrlMakerClass = null;
/**
* Set the current application url provider
* @param string $sClass Class implementing iDBObjectURLMaker
* @return string
* @param sClass string Class implementing iDBObjectURLMaker
* @return void
*/
public static function SetUrlMakerClass($sClass = 'iTopStandardURLMaker')
{
@@ -321,14 +278,7 @@ class ApplicationContext
/**
* Get the current application url provider
*
* @param string $sObjClass
* @param string $sObjKey
* @param null $sUrlMakerClass
* @param bool $bWithNavigationContext
*
* @return string the name of the class
* @throws \Exception
*/
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
{
@@ -356,6 +306,8 @@ class ApplicationContext
}
}
protected static $m_aPluginProperties = null;
/**
* Load plugin properties for the current session
* @return void
@@ -374,9 +326,9 @@ class ApplicationContext
/**
* Set plugin properties
* @param string $sPluginClass Class implementing any plugin interface
* @param string $sProperty Name of the property
* @param mixed $value Value (numeric or string)
* @param sPluginClass string Class implementing any plugin interface
* @param sProperty string Name of the property
* @param value scalar Value (numeric or string)
* @return void
*/
public static function SetPluginProperty($sPluginClass, $sProperty, $value)
@@ -389,7 +341,7 @@ class ApplicationContext
/**
* Get plugin properties
* @param string $sPluginClass Class implementing any plugin interface
* @param sPluginClass string Class implementing any plugin interface
* @return array of sProperty=>value pairs
*/
public static function GetPluginProperties($sPluginClass)
@@ -407,3 +359,4 @@ class ApplicationContext
}
}
?>

View File

@@ -16,8 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
/**
* Management of application plugins
*
@@ -124,8 +122,7 @@ interface iApplicationUIExtension
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string[] desc
* @return type desc
*/
public function EnumUsedAttributes($oObject); // Not yet implemented
@@ -365,7 +362,7 @@ interface iPopupMenuExtension
* Base class for the various types of custom menus
*
* @package Extensibility
* @api
* @internal
* @since 2.0
*/
abstract class ApplicationPopupMenuItem
@@ -378,10 +375,8 @@ abstract class ApplicationPopupMenuItem
protected $aCssClasses;
/**
* Constructor
*
* @api
*
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param array $aCssClasses The CSS classes to add to the menu
@@ -446,9 +441,8 @@ abstract class ApplicationPopupMenuItem
/**
* Returns the components to create a popup menu item in HTML
*
* @return array A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
* @return Hash A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
*/
abstract public function GetMenuItem();
@@ -511,9 +505,6 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
/**
* Class for adding an item that triggers some Javascript code
*
* @api
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sJSCode In case the menu consists in executing some havascript code inside the page, pass it here. If supplied $sURL ans $sTarget will be ignored
@@ -768,15 +759,11 @@ interface iRestServiceProvider
* @return array An array of hash 'verb' => verb, 'description' => description
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param array $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @throws Exception in case of internal failure.
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}
@@ -883,7 +870,7 @@ class RestUtils
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @return mixed parameter value if present
* @return string
* @throws Exception If the parameter is missing
* @api
*/
@@ -906,8 +893,7 @@ class RestUtils
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
* @param mixed $default Default value if the parameter is not found in the input data
*
* @return mixed
* @return void
* @throws Exception
* @api
*/
@@ -951,8 +937,7 @@ class RestUtils
* @param string $sClass Name of the class
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @return array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @return An array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @throws Exception
* @api
*/
@@ -1135,6 +1120,7 @@ class RestUtils
{
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oObjectSet = new DBObjectSet($oSearch);
}
else
{
@@ -1183,14 +1169,6 @@ class RestUtils
}
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
}
elseif ($oAttDef instanceof AttributeTagSet)
{
if (!is_array($value))
{
throw new Exception("A tag set must be defined by an array of tag codes");
}
$value = $oAttDef->FromJSONToValue($value);
}
else
{
$value = $oAttDef->FromJSONToValue($value);

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,6 @@ require_once(APPROOT.'application/dashlet.class.inc.php');
require_once(APPROOT.'core/modelreflection.class.inc.php');
/**
*
* A user editable dashboard page
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
@@ -50,11 +49,6 @@ abstract class Dashboard
$this->sId = $sId;
}
/**
* @param $sXml
*
* @throws \Exception
*/
public function FromXml($sXml)
{
$this->aCells = array(); // reset the content of the dashboard
@@ -106,10 +100,10 @@ abstract class Dashboard
$oCellsList = $oCellsNode->getElementsByTagName('cell');
$aCellOrder = array();
$iCellRank = 0;
/** @var \DOMElement $oCellNode */
foreach($oCellsList as $oCellNode)
{
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
$aDashletList = array();
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
if ($oCellRank)
{
$iCellRank = (float)$oCellRank->textContent;
@@ -119,7 +113,6 @@ abstract class Dashboard
$oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
$iRank = 0;
$aDashletOrder = array();
/** @var \DOMElement $oDomNode */
foreach($oDashletList as $oDomNode)
{
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
@@ -152,11 +145,6 @@ abstract class Dashboard
}
}
/**
* @param \DOMElement $oDomNode
*
* @return mixed
*/
protected function InitDashletFromDOMNode($oDomNode)
{
$sId = $oDomNode->getAttribute('id');
@@ -164,8 +152,7 @@ abstract class Dashboard
// Test if dashlet can be instanciated, otherwise (uninstalled, broken, ...) we display a placeholder
$sClass = static::GetDashletClassFromType($sDashletType);
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet->SetDashletType($sDashletType);
$oNewDashlet->FromDOMNode($oDomNode);
@@ -176,17 +163,8 @@ abstract class Dashboard
{
return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
}
/**
* Error handler to turn XML loading warnings into exceptions
*
* @param $errno
* @param $errstr
* @param $errfile
* @param $errline
*
* @return bool
* @throws \DOMException
*/
public static function ErrorHandler($errno, $errstr, $errfile, $errline)
{
@@ -216,12 +194,8 @@ abstract class Dashboard
return $sXml;
}
/**
* @param \DOMElement $oDefinition
*/
public function ToDOMNode($oDefinition)
{
/** @var \DOMDocument $oDoc */
$oDoc = $oDefinition->ownerDocument;
$oNode = $oDoc->createElement('layout', $this->sLayoutClass);
@@ -253,7 +227,6 @@ abstract class Dashboard
$iDashletRank = 0;
$oDashletsNode = $oDoc->createElement('dashlets');
$oCellNode->appendChild($oDashletsNode);
/** @var \Dashlet $oDashlet */
foreach ($aCell as $oDashlet)
{
$oNode = $oDoc->createElement('dashlet');
@@ -283,7 +256,6 @@ abstract class Dashboard
{
$sDashletClass = $aDashletParams['dashlet_class'];
$sId = $aDashletParams['dashlet_id'];
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sDashletClass($this->oMetaModel, $sId);
if (isset($aDashletParams['dashlet_type']))
{
@@ -346,28 +318,31 @@ abstract class Dashboard
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec);
}
/**
* @param \Dashlet $oDashlet
*/
public function AddDashlet($oDashlet)
{
$sId = $this->GetNewDashletId();
$oDashlet->SetId($sId);
$this->aCells[] = array($oDashlet);
}
/**
* @param \WebPage $oPage *
* @param array $aExtraParams
*
* @throws \ReflectionException
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$oPage->add('<h1>'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</h1>');
$oLayout = new $this->sLayoutClass;
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
if (!$bEditMode)
{
$oPage->add_linked_script('../js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js');
}
}
public function RenderProperties($oPage)
{
// menu to pick a layout and edit other properties of the dashboard
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
$sUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->add('<div style="text-align:center">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
$oPage->add('<div id="select_layout" style="text-align:center">');
foreach( get_declared_classes() as $sLayoutClass)
@@ -385,13 +360,13 @@ abstract class Dashboard
}
}
$oPage->add('</div>');
$oForm = new DesignerForm();
$oField = new DesignerHiddenField('dashboard_id', '', $this->sId);
$oForm->AddField($oField);
$oField = new DesignerTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
$oField = new DesignerLongTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
$oForm->AddField($oField);
$oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload);
@@ -402,8 +377,8 @@ abstract class Dashboard
$oForm->AddField($oField);
$this->SetFormParams($oForm, $aExtraParams);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$this->SetFormParams($oForm);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$oPage->add('</div>');
@@ -447,28 +422,8 @@ abstract class Dashboard
EOF
);
}
/**
* @param \iTopWebPage $oPage
* @param bool $bEditMode
* @param array $aExtraParams
* @param bool $bCanEdit
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
{
$oPage->add('<div class="dashboard-title-line"><div class="dashboard-title">'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</div></div>');
$oLayout = new $this->sLayoutClass;
/** @var \DashboardLayoutMultiCol $oLayout */
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
if (!$bEditMode)
{
$oPage->add_linked_script('../js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js');
}
}
public function RenderDashletsSelection(WebPage $oPage)
public function RenderDashletsSelection($oPage)
{
// Toolbox/palette to drag and drop dashlets
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
@@ -486,7 +441,7 @@ EOF
$oPage->add_ready_script("$('.dashlet_icon').draggable({helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
}
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
public function RenderDashletsProperties($oPage)
{
// Toolbox/palette to edit the properties of each dashlet
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
@@ -494,15 +449,15 @@ EOF
$oPage->add('<div id="dashlet_properties" style="text-align:center">');
foreach($this->aCells as $aCell)
{
/** @var \Dashlet $oDashlet */
foreach($aCell as $oDashlet)
{
$sId = $oDashlet->GetID();
$sClass = get_class($oDashlet);
if ($oDashlet->IsVisible())
{
$oPage->add('<div class="dashlet_properties" id="dashlet_properties_'.$sId.'" style="display:none">');
$oForm = $oDashlet->GetForm();
$this->SetFormParams($oForm, $aExtraParams);
$this->SetFormParams($oForm);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$oPage->add('</div>');
}
@@ -517,7 +472,6 @@ EOF
* Return an array of dashlets available for selection.
*
* @return array
* @throws \ReflectionException
*/
protected function GetAvailableDashlets()
{
@@ -551,7 +505,6 @@ EOF
$iNewId = 0;
foreach($this->aCells as $aDashlets)
{
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
$iNewId = max($iNewId, (int)$oDashlet->GetID());
@@ -559,14 +512,8 @@ EOF
}
return $iNewId + 1;
}
/**
* @param $oForm
* @param array $aExtraParams
*
* @return mixed
*/
abstract protected function SetFormParams($oForm, $aExtraParams = array());
abstract protected function SetFormParams($oForm);
public static function GetDashletClassFromType($sType, $oFactory = null)
{
@@ -576,22 +523,11 @@ EOF
}
return 'DashletUnknown';
}
/**
* @return mixed
*/
public function GetId()
{
return $this->sId;
}
}
class RuntimeDashboard extends Dashboard
{
protected $bCustomized;
private $sDefinitionFile = '';
private $sReloadURL = null;
public function __construct($sId)
{
@@ -604,17 +540,10 @@ class RuntimeDashboard extends Dashboard
{
$this->bCustomized = $bCustomized;
}
/**
* @param \DesignerForm $oForm
*
* @param array $aExtraParams
*
* @throws \Exception
*/
protected function SetFormParams($oForm, $aExtraParams = array())
protected function SetFormParams($oForm)
{
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property', 'extra_params' => $aExtraParams));
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property'));
}
public function Save()
@@ -658,265 +587,41 @@ class RuntimeDashboard extends Dashboard
utils::PopArchiveMode();
}
}
/**
* @param string $sDashboardFile file name relative to the current module folder
* @param string $sDashBoardId code of the dashboard either menu_id or <class>__<attcode>
*
* @return null|RuntimeDashboard
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public static function GetDashboard($sDashboardFile, $sDashBoardId)
{
$bCustomized = false;
if (!appUserPreferences::GetPref('display_original_dashboard_'.$sDashBoardId, false))
{
// Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $sDashBoardId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0)
{
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
$sDashboardDefinition = $oUserDashboard->Get('contents');
$bCustomized = true;
}
else
{
$sDashboardDefinition = @file_get_contents($sDashboardFile);
}
}
else
{
$sDashboardDefinition = @file_get_contents($sDashboardFile);
}
if ($sDashboardDefinition !== false)
{
$oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized);
$oDashboard->SetDefinitionFile($sDashboardFile);
}
else
{
$oDashboard = null;
}
return $oDashboard;
}
/**
* @param \iTopWebPage $oPage
* @param bool $bEditMode
* @param array $aExtraParams (class and id of the current object
*
* @throws \Exception
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
{
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class']))
{
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
}
else
{
$aRenderParams = $aExtraParams;
}
parent::Render($oPage, $bEditMode, $aRenderParams);
if (isset($aExtraParams['query_params']['this->object()']))
{
/** @var \DBObject $oObj */
$oObj = $aExtraParams['query_params']['this->object()'];
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
}
else
{
$aAjaxParams = $aExtraParams;
}
if (!$bEditMode && !$oPage->IsPrintableVersion())
{
$sId = $this->GetId();
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $sId);
if ($this->GetAutoReload())
{
$sFile = addslashes($this->GetDefinitionFile());
$sExtraParams = json_encode($aAjaxParams);
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
$sReloadURL = $this->GetReloadURL();
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
{
clearInterval(AutoReloadDashboardId$sDivId);
delete AutoReloadDashboardId$sDivId;
}
AutoReloadDashboardId$sDivId = setInterval("ReloadDashboard$sDivId();", $iReloadInterval);
function ReloadDashboard$sDivId()
{
// Do not reload when a dialog box is active
if (!($('.ui-dialog:visible').length > 0) && $('.dashboard_contents#$sDivId').is(':visible'))
{
$('.dashboard_contents#$sDivId').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL'},
function(data){
$('.dashboard_contents#$sDivId').html(data);
$('.dashboard_contents#$sDivId').unblock();
}
);
}
}
EOF
);
}
else
{
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
{
clearInterval(AutoReloadDashboardId$sDivId);
delete AutoReloadDashboardId$sDivId;
}
EOF
);
}
if ($bCanEdit)
{
$this->RenderSelector($oPage, $aAjaxParams);
$this->RenderEditionTools($oPage, $aAjaxParams);
}
}
}
/**
* @param \iTopWebPage $oPage
* @param array $aAjaxParams
*/
protected function RenderSelector($oPage, $aAjaxParams = array())
{
$sId = $this->GetId();
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $sId);
$sExtraParams = json_encode($aAjaxParams);
$sSelectorHtml = '<div class="dashboard-selector">';
if ($this->HasCustomDashboard())
{
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
$sSelectorHtml .= '<div class="selector-label">'.$sStandard.'</div>';
$sSelectorHtml .= '<label class="switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="slider round"></span></label></input></label>';
$sCustom = Dict::S('UI:Toggle:CustomDashboard');
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
}
$sSelectorHtml .= '</div>';
$sSelectorHtml = addslashes($sSelectorHtml);
$sFile = addslashes($this->GetDefinitionFile());
$sReloadURL = $this->GetReloadURL();
$oPage->add_ready_script(
<<<EOF
$('.dashboard-title').after('$sSelectorHtml');
EOF
);
$oPage->add_script(
<<<EOF
function ToggleDashboardSelector$sDivId()
{
$('.dashboard_contents#$sDivId').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
function(data) {
$('.dashboard_contents#$sDivId').html(data);
$('.dashboard_contents#$sDivId').unblock();
}
);
}
EOF
);
}
protected function HasCustomDashboard()
{
try
{
// Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->GetId(), '=');
$oUDSet = new DBObjectSet($oUDSearch);
return ($oUDSet->Count() > 0);
}
catch (Exception $e)
{
return false;
}
}
/**
* @param \WebPage $oPage
* @param array $aExtraParams
*
* @throws \Exception
*/
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
public function RenderEditionTools($oPage)
{
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
$sEditMenu = "<td><span id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
$aActions = array();
$sFile = addslashes($this->sDefinitionFile);
$sJSExtraParams = json_encode($aExtraParams);
$bCanEdit = true;
if ($this->HasCustomDashboard())
{
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
}
if ($bCanEdit)
{
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
}
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}')");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
if ($this->bCustomized)
{
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}'); else return false");
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
}
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
$sEditMenu = addslashes($sEditMenu);
$sReloadURL = $this->GetReloadURL();
//$sEditBtn = addslashes('<div style="display: inline-block; height: 55px; width:200px;vertical-align:center;line-height:60px;text-align:left;"><button onclick="EditDashboard(\''.$this->sId.'\');">Edit This Page</button></div>');
$oPage->add_ready_script(
<<<EOF
$('.dashboard-title').after('$sEditMenu');
$('#logOffBtn').parent().before('$sEditMenu');
$('#DashboardMenu>ul').popupmenu();
EOF
);
$oPage->add_script(
<<<EOF
function EditDashboard(sId, sDashboardFile, aExtraParams)
function EditDashboard(sId)
{
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile, extra_params: aExtraParams, reload_url: '$sReloadURL'},
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId},
function(data)
{
$('body').append(data);
@@ -924,12 +629,12 @@ function EditDashboard(sId, sDashboardFile, aExtraParams)
);
return false;
}
function RevertDashboard(sId, aExtraParams)
function RevertDashboard(sId)
{
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'revert_dashboard', dashboard_id: sId, extra_params: aExtraParams, reload_url: '$sReloadURL'},
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'revert_dashboard', dashboard_id: sId},
function(data)
{
location.reload();
$('body').append(data);
}
);
return false;
@@ -938,14 +643,9 @@ EOF
);
}
/**
* @param \WebPage $oPage
*
* @throws \ReflectionException
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function RenderProperties($oPage)
{
parent::RenderProperties($oPage, $aExtraParams);
parent::RenderProperties($oPage);
$oPage->add_ready_script(
<<<EOF
@@ -976,36 +676,16 @@ EOF
}
/**
* @param \iTopWebPage $oPage
*
* @param array $aExtraParams
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \ReflectionException
* @throws \Exception
*/
public function RenderEditor($oPage, $aExtraParams = array())
public function RenderEditor($oPage)
{
if (isset($aExtraParams['this->class']))
{
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
}
else
{
$aRenderParams = $aExtraParams;
}
$sJSExtraParams = json_encode($aExtraParams);
$oPage->add('<div id="dashboard_editor">');
$oPage->add('<div class="ui-layout-center">');
$this->Render($oPage, true, $aRenderParams);
$this->Render($oPage, true);
$oPage->add('</div>');
$oPage->add('<div class="ui-layout-east">');
$this->RenderProperties($oPage, $aExtraParams);
$this->RenderProperties($oPage);
$this->RenderDashletsSelection($oPage);
$this->RenderDashletsProperties($oPage, $aExtraParams);
$this->RenderDashletsProperties($oPage);
$oPage->add('</div>');
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
$oPage->add('</div>');
@@ -1019,9 +699,7 @@ EOF
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sTitle = addslashes($this->sTitle);
$sFile = addslashes($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sReloadURL = $this->GetReloadURL();
$sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage'));
$sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage'));
@@ -1051,7 +729,7 @@ $('#dashboard_editor').dialog({
}
}
window.bLeavingOnUserAction = true;
oDashboard.save($(this));
oDashboard.save();
} },
{ text: "$sCancelButtonLabel", click: function() {
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
@@ -1073,8 +751,8 @@ $('#dashboard_editor').dialog({
$('#dashboard_editor .ui-layout-center').runtimedashboard({
dashboard_id: '$sId', layout_class: '$sLayoutClass', title: '$sTitle',
auto_reload: $sAutoReload, auto_reload_sec: $sAutoReloadSec,
submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl', render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard'},
render_to: '$sUrl', render_parameters: {operation: 'render_dashboard'},
new_dashlet_parameters: {operation: 'new_dashlet'}
});
@@ -1157,8 +835,7 @@ EOF
$sParentId = $aParentMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
}
/** @var \MenuNode $oParentMenu */
$oParentMenu = $aParentMenu['node'];
$oParentMenu = $aParentMenu['node'];
if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled())
{
$sMenuLabel = $oMenu->GetTitle();
@@ -1213,7 +890,6 @@ EOF
{
$oSubForm = new DesignerForm();
$oMetaModel = new ModelReflectionRuntime();
/** @var \Dashlet $oDashlet */
$oDashlet = new $sDashletClass($oMetaModel, 0);
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
@@ -1224,11 +900,7 @@ EOF
return $oForm;
}
/**
* @param \WebPage $oPage
* @param $sOQL
*/
public static function GetDashletCreationDlgFromOQL($oPage, $sOQL)
{
$oPage->add('<div id="dashlet_creation_dlg">');
@@ -1275,30 +947,4 @@ $('#dashlet_creation_dlg').dialog({
EOF
);
}
/**
* @return string
*/
public function GetDefinitionFile()
{
return $this->sDefinitionFile;
}
/**
* @param string $sDefinitionFile
*/
public function SetDefinitionFile($sDefinitionFile)
{
$this->sDefinitionFile = $sDefinitionFile;
}
public function GetReloadURL()
{
return $this->sReloadURL;
}
public function SetReloadURL($sReloadURL)
{
$this->sReloadURL = $sReloadURL;
}
}

View File

@@ -59,7 +59,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$bNoVisibleFound = true;
while($idx < count($aKeys) && $bNoVisibleFound)
{
/** @var \Dashlet $oDashlet */
$oDashlet = $aDashlets[$aKeys[$idx]];
if ($oDashlet->IsVisible())
{
@@ -99,13 +98,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
return $aCells;
}
/**
* @param \WebPage $oPage
* @param $aCells
* @param bool $bEditMode
* @param array $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
@@ -129,7 +122,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$aDashlets = $aCells[$iCellIdx];
if (count($aDashlets) > 0)
{
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
if ($oDashlet->IsVisible())

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.5">
<portals>
<portal id="legacy_portal" _delta="define">
<url>portal/index.php</url>

View File

@@ -184,10 +184,6 @@ class DataTable
*/
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
{
if ($iPageSize < 1)
{
$iPageSize = -1; // convention: no pagination
}
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
@@ -226,21 +222,14 @@ class DataTable
}
$sCombo = '<select class="pagesize">';
if($iPageSize < 1)
for($iPage = 1; $iPage < 5; $iPage++)
{
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
$iNbItems = $iPage * $iDefaultPageSize;
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
}
else
{
for($iPage = 1; $iPage < 5; $iPage++)
{
$iNbItems = $iPage * $iDefaultPageSize;
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
}
$sCombo .= "<option value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
}
$sSelected = ($iPageSize < 1) ? 'selected="selected"' : '';
$sCombo .= "<option $sSelected value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
$sCombo .= '</select>';
$sPages = Dict::S('UI:Pagination:PagesLabel');
@@ -588,8 +577,8 @@ EOF
public function UpdatePager(WebPage $oPage, $iDefaultPageSize, $iStart)
{
$iPageSize = $iDefaultPageSize;
$iPageIndex = 0;
$iPageSize = ($iDefaultPageSize < 1) ? 1 : $iDefaultPageSize;
$iPageIndex = 1 + floor($iStart / $iPageSize);
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
if ($iDefaultPageSize < 1)
@@ -767,10 +756,6 @@ class DataTableSettings implements Serializable
{
foreach($this->aClassAliases as $sAlias => $sClass)
{
if (!isset($this->aColumns[$sAlias]))
{
continue;
}
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
{
// Remove non-existent columns
@@ -786,7 +771,7 @@ class DataTableSettings implements Serializable
$aTempData = array();
foreach($aList as $sAttCode => $oAttDef)
{
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!($oAttDef instanceof AttributeLinkedSet || $oAttDef instanceof AttributeDashboard)))
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!$oAttDef instanceof AttributeLinkSet))
{
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false /* bChecked */, 'none');
if ($aFieldData) $aTempData[$aFieldData['label']] = $aFieldData;
@@ -947,4 +932,4 @@ class DataTableSettings implements Serializable
}
return $ret;
}
}
}

View File

@@ -220,26 +220,9 @@ class DisplayBlock
$aExtraParams['currentId'] = $sId;
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
if (isset($aExtraParams['this->id']) && isset($aExtraParams['this->class']))
{
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
}
else
{
$aQueryParams = array();
}
}
$sFilter = addslashes($this->m_oFilter->serialize(false, $aQueryParams)); // Used either for asynchronous or auto_reload
$sFilter = $this->m_oFilter->serialize(); // Used either for asynchronous or auto_reload
if (!$this->m_bAsynchronous)
{
// render now
@@ -331,31 +314,20 @@ class DisplayBlock
* @throws MySQLException
* @throws Exception
*/
public function GetRenderContent(WebPage $oPage, $aExtraParams, $sId)
public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
{
$sHtml = '';
// Add the extra params into the filter if they make sense for such a filter
$bDoSearch = utils::ReadParam('dosearch', false);
$aQueryParams = array();
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
if (isset($aExtraParams['this->id']) && isset($aExtraParams['this->class']))
{
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
}
}
if ($this->m_oSet == null)
{
$aQueryParams = array();
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
// In case of search, the context filtering is done by the search itself
if (($this->m_sStyle != 'links') && ($this->m_sStyle != 'search') && ($this->m_sStyle != 'list_search'))
if (($this->m_sStyle != 'links') && ($this->m_sStyle != 'search'))
{
$oAppContext = new ApplicationContext();
$sClass = $this->m_oFilter->GetClass();
@@ -485,25 +457,14 @@ class DisplayBlock
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
$oSubsetSearch->AddConditionExpression($oCondition);
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
$aQueryParams = array();
}
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
$sFilter = urlencode($oSubsetSearch->serialize());
$aData[] = array ('group' => $aLabels[$iRow],
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=$sFilter\">$iCount</a>"); // TO DO: add the context information
}
$aAttribs =array(
'group' => array('label' => $sGroupByLabel, 'description' => ''),
'value' => array(
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
),
'value' => array('label'=> Dict::S('UI:GroupBy:'.$sAggregationFunction), 'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr))
);
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
$sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount));
@@ -619,7 +580,6 @@ class DisplayBlock
}
break;
case 'list_search':
case 'list':
$aClasses = $this->m_oSet->GetSelectedClasses();
$aAuthorizedClasses = array();
@@ -702,7 +662,7 @@ class DisplayBlock
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'),
'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(),
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png',
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png'
));
$oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])");
@@ -755,7 +715,7 @@ class DisplayBlock
$sClass = $this->m_oFilter->GetClass();
$oAppContext = new ApplicationContext();
$bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
if ($bContextFilter && is_null($this->m_oSet))
if ($bContextFilter)
{
foreach($oAppContext->GetNames() as $sFilterCode)
{
@@ -774,7 +734,7 @@ class DisplayBlock
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
}
$iCount = $this->m_oSet->Count();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
$sHtml .= '<p><a class="actions" href="'.$sHyperlink.'">';
// Note: border set to 0 due to various browser interpretations (IE9 adding a 2px border)
$sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;border:0;');
@@ -863,7 +823,7 @@ class DisplayBlock
}
$sHyperlink = utils::GetAbsoluteUrlAppRoot()
.'pages/UI.php?operation=search&'.$oAppContext->GetForLink()
.'&filter='.rawurlencode($oSingleGroupByValueFilter->serialize());
.'&filter='.urlencode($oSingleGroupByValueFilter->serialize());
$aCounts[$sStateValue] = "<a href=\"$sHyperlink\">{$aCounts[$sStateValue]}</a>";
}
}
@@ -872,7 +832,7 @@ class DisplayBlock
$sHtml .= '<tr><td>'.implode('</td><td>', $aCounts).'</td></tr></table></div>';
// Title & summary
$iCount = $this->m_oSet->Count();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
$sHtml .= '<h1>'.Dict::S(str_replace('_', ':', $sTitle)).'</h1>';
$sHtml .= '<a class="summary" href="'.$sHyperlink.'">'.Dict::Format(str_replace('_', ':', $sLabel), $iCount).'</a>';
$sHtml .= '<div style="clear:both;"></div>';
@@ -883,7 +843,7 @@ class DisplayBlock
$sCsvFile = strtolower($this->m_oFilter->GetClass()).'.csv';
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($sCsvFile);
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize()).'&format=csv';
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize()).'&format=csv';
// Pass the parameters via POST, since expression may be very long
$aParamsToPost = array(
'expression' => $this->m_oFilter->ToOQL(true),
@@ -953,10 +913,10 @@ class DisplayBlock
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$sTitle = isset($aExtraParams['chart_title']) ? '<h1 style="text-align:center">'.htmlentities(Dict::S($aExtraParams['chart_title']), ENT_QUOTES, 'UTF-8').'</h1>' : '';
$sHtml = "$sTitle<div style=\"height:200px;width:100%\" class=\"dashboard_chart\" id=\"my_chart_$sId{$iChartCounter}\"><div style=\"height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%\"><img src=\"../images/indicator.gif\"></div></div>\n";
$sHtml = "$sTitle<div style=\"height:200px;width:100%\" id=\"my_chart_$sId{$iChartCounter}\"><div style=\"height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%\"><img src=\"../images/indicator.gif\"></div></div>\n";
$sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
$sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '&params[group_by_expr]='.$aExtraParams['group_by_expr'] : '';
$sFilter = $this->m_oFilter->serialize(false, $aQueryParams);
$sFilter = $this->m_oFilter->serialize();
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink();
$sAggregationFunction = isset($aExtraParams['aggregation_function']) ? $aExtraParams['aggregation_function'] : '';
@@ -967,11 +927,11 @@ class DisplayBlock
if (isset($aExtraParams['group_by_label']))
{
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam);
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam);
}
else
{
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam);
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam);
}
$oPage->add_ready_script(
@@ -1011,7 +971,7 @@ EOF
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($sValue));
$oSubsetSearch->AddConditionExpression($oCondition);
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".rawurlencode($oSubsetSearch->serialize()).'&'.$sContextParam;
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".urlencode($oSubsetSearch->serialize()).'&'.$sContextParam;
}
$sJSURLs = json_encode($aURLs);
}
@@ -1029,7 +989,6 @@ EOF
$sJson = json_encode($aValues);
$oPage->add_ready_script(
<<<EOF
var chart = c3.generate({
bindto: d3.select('#my_chart_$sId'),
data: {
@@ -1077,12 +1036,6 @@ var chart = c3.generate({
}
}
});
if (typeof(charts) === "undefined")
{
charts = [];
}
charts.push(chart);
EOF
);
break;
@@ -1121,12 +1074,6 @@ var chart = c3.generate({
}
}
});
if (typeof(charts) === "undefined")
{
charts = [];
}
charts.push(chart);
EOF
);
break;
@@ -1175,26 +1122,16 @@ EOF
}
if (($bAutoReload) && ($this->m_sStyle != 'search')) // Search form do NOT auto-reload
{
// Used either for asynchronous or auto_reload
// does a json_encode twice to get a string usable as function parameter
$sFilterBefore = $this->m_oFilter->serialize();
$sFilter = json_encode($sFilterBefore);
$sExtraParams = json_encode(json_encode($aExtraParams));
$sFilter = $this->m_oFilter->serialize(); // Used either for asynchronous or auto_reload
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
$oPage->add_script(
<<<JS
if (typeof window.oAutoReloadBlock == "undefined") {
window.oAutoReloadBlock = {};
}
if (typeof window.oAutoReloadBlock['$sId'] != "undefined") {
clearInterval(window.oAutoReloadBlock['$sId']);
}
window.oAutoReloadBlock['$sId'] = setInterval(function() {
ReloadBlock('$sId', '{$this->m_sStyle}', $sFilter, $sExtraParams);
}, '$iReloadInterval');
JS
);
$oPage->add_script('if (typeof window.oAutoReloadBlock == "undefined") {
window.oAutoReloadBlock = {};
}
if (typeof window.oAutoReloadBlock[\''.$sId.'\'] != "undefined") {
clearInterval(window.oAutoReloadBlock[\''.$sId.'\']);
}
window.oAutoReloadBlock[\''.$sId.'\'] = setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \''.$sFilter.'\', \"'.$sExtraParams.'\")", '.$iReloadInterval.');');
}
return $sHtml;
@@ -1454,7 +1391,7 @@ class HistoryBlock extends DisplayBlock
default:
if ($bTruncated)
{
$sFilter = htmlentities($this->m_oFilter->serialize(), ENT_QUOTES, 'UTF-8');
$sFilter = $this->m_oFilter->serialize();
$sHtml .= '<div id="history_container"><p>';
$sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count());
$sHtml .= ' ';
@@ -1732,7 +1669,6 @@ class MenuBlock extends DisplayBlock
*/
}
$this->AddMenuSeparator($aActions);
/** @var \iApplicationUIExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
{
$oSet->Rewind();
@@ -1828,7 +1764,6 @@ class MenuBlock extends DisplayBlock
}
$this->AddMenuSeparator($aActions);
/** @var \iApplicationUIExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
{
$oSet->Rewind();

View File

@@ -378,9 +378,9 @@ $('#$sDialogId').dialog({
}
}
} },
{ text: "$sCancelButtonLabel", click: function() { $(this).dialog( "close" ); $(this).remove(); } },
{ text: "$sCancelButtonLabel", click: function() { KillAllMenus(); $(this).dialog( "close" ); $(this).remove(); } },
],
close: function() { $(this).remove(); }
close: function() { KillAllMenus(); $(this).remove(); }
});
var oForm = $('#$sDialogId form');
var sFormId = oForm.attr('id');
@@ -682,7 +682,6 @@ class DesignerFormField
protected $sLabel;
protected $sCode;
protected $defaultValue;
/** @var \DesignerForm $oForm */
protected $oForm;
protected $bMandatory;
protected $bReadOnly;
@@ -708,11 +707,8 @@ class DesignerFormField
{
return $this->sCode;
}
/**
* @param \DesignerForm $oForm
*/
public function SetForm(\DesignerForm $oForm)
public function SetForm($oForm)
{
$this->oForm = $oForm;
}

File diff suppressed because it is too large Load Diff

View File

@@ -50,9 +50,6 @@ class LoginWebPage extends NiceWebPage
self::$sHandlerClass = $sClass;
}
/**
* @return \LoginWebPage
*/
public static function NewLoginWebPage()
{
return new self::$sHandlerClass;

View File

@@ -84,11 +84,14 @@ class ApplicationMenu
{
// Build menus from module handlers
//
/** @var \ModuleHandlerApiInterface $oPHPClass */
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMenuCreation();
}
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMenuCreation');
call_user_func($aCallSpec);
}
}
// Build menus from the menus themselves (e.g. the ShortcutContainerMenuNode will do that)
//
@@ -122,11 +125,9 @@ class ApplicationMenu
}
/**
* Check whether a menu Id is enabled or not
*
* Check wether a menu Id is enabled or not
* @param $sMenuId
*
* @throws \Exception
* @throws DictExceptionMissingString
*/
static public function CheckMenuIdEnabled($sMenuId)
{
@@ -166,9 +167,7 @@ class ApplicationMenu
}
else
{
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$iParentIndex]['node'];
$sParentId = $oNode->GetMenuId();
$sParentId = self::$aMenusIndex[$iParentIndex]['node']->GetMenuId();
self::$aMenusIndex[$iParentIndex]['children'][] = array ('rank' => $fRank, 'index' => $index);
}
@@ -182,9 +181,7 @@ class ApplicationMenu
else
{
// the menu already exists, let's combine the conditions that make it visible
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$index]['node'];
$oNode->AddCondition($oMenuNode);
self::$aMenusIndex[$index]['node']->AddCondition($oMenuNode);
}
return $index;
@@ -201,7 +198,7 @@ class ApplicationMenu
/**
* Entry point to display the whole menu into the web page, used by iTopWebPage
* @param \iTopWebPage $oPage
* @param $oPage
* @param $aExtraParams
* @throws DictExceptionMissingString
*/
@@ -211,7 +208,6 @@ class ApplicationMenu
// Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
$iAccordion = 0;
$iActiveAccordion = $iAccordion;
$iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
foreach(self::$aRootMenus as $aMenu)
{
@@ -225,18 +221,16 @@ class ApplicationMenu
$oPage->AddToMenu('</ul>');
if ($bActive)
{
$iActiveAccordion = $iAccordion;
$oPage->add_ready_script(
<<<EOF
// Accordion Menu
$("#accordion").css({display:'block'}).accordion({ header: "h3", navigation: true, heightStyle: "content", collapsible: true, active: $iAccordion, icons: false, animate:true }); // collapsible will be enabled once the item will be selected
EOF
);
}
$oPage->AddToMenu('</div>');
$iAccordion++;
}
$oPage->add_ready_script(
<<<EOF
// Accordion Menu
$("#accordion").css({display:'block'}).accordion({ header: "h3", heightStyle: "content", collapsible: true, active: $iActiveAccordion, icons: false, animate: true }); // collapsible will be enabled once the item will be selected
EOF
);
}
/**
@@ -270,7 +264,7 @@ EOF
/**
* Handles the display of the sub-menus (called recursively if necessary)
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param array $aMenus
* @param array $aExtraParams
* @param int $iActiveMenu
@@ -362,7 +356,6 @@ EOF
static public function GetMenuIndexById($sTitle)
{
$index = -1;
/** @var MenuNode[] $aMenu */
foreach(self::$aMenusIndex as $aMenu)
{
if ($aMenu['node']->GetMenuId() == $sTitle)
@@ -844,7 +837,7 @@ class OQLMenuNode extends MenuNode
/**
* Set some extra parameters to be passed to the display block to fine tune its appearence
* @param array $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
* @param Hash $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
*/
public function SetParameters($aParams)
{
@@ -957,7 +950,7 @@ class SearchMenuNode extends MenuNode
}
/**
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param array $aExtraParams
* @return mixed|void
* @throws DictExceptionMissingString
@@ -1061,9 +1054,7 @@ class NewObjectMenuNode extends MenuNode
/**
* @param string[] $aExtraParams
*
* @return string
* @throws \Exception
*/
public function GetHyperlink($aExtraParams)
{
@@ -1152,11 +1143,37 @@ class DashboardMenuNode extends MenuNode
*/
public function GetDashboard()
{
return RuntimeDashboard::GetDashboard($this->sDashboardFile, $this->sMenuId);
$sDashboardDefinition = @file_get_contents($this->sDashboardFile);
if ($sDashboardDefinition !== false)
{
$bCustomized = false;
// Search for an eventual user defined dashboard, overloading the existing one
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->sMenuId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0)
{
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
$sDashboardDefinition = $oUserDashboard->Get('contents');
$bCustomized = true;
}
$oDashboard = new RuntimeDashboard($this->sMenuId);
$oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized);
}
else
{
$oDashboard = null;
}
return $oDashboard;
}
/**
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param string[] $aExtraParams
* @throws CoreException
* @throws Exception
@@ -1169,9 +1186,38 @@ class DashboardMenuNode extends MenuNode
{
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $this->sMenuId);
$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
$oDashboard->Render($oPage, false, $aExtraParams);
$oPage->add('</div>');
$oDashboard->RenderEditionTools($oPage);
if ($oDashboard->GetAutoReload())
{
$sId = $this->sMenuId;
$sExtraParams = json_encode($aExtraParams);
$iReloadInterval = 1000 * $oDashboard->GetAutoReloadInterval();
$oPage->add_script(
<<<EOF
setInterval("ReloadDashboard('$sDivId');", $iReloadInterval);
function ReloadDashboard(sDivId)
{
var oExtraParams = $sExtraParams;
// Do not reload when a dialog box is active
if (!($('.ui-dialog:visible').length > 0))
{
$('.dashboard_contents#'+sDivId).block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'reload_dashboard', dashboard_id: '$sId', extra_params: oExtraParams},
function(data){
$('.dashboard_contents#'+sDivId).html(data);
$('.dashboard_contents#'+sDivId).unblock();
}
);
}
}
EOF
);
}
$bEdit = utils::ReadParam('edit', false);
if ($bEdit)

View File

@@ -1,159 +0,0 @@
<?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/>
/**
* A provider for messages to be displayed in the iTop Newsroom
*/
interface iNewsroomProvider
{
/**
* Inject the current configuration in the provider
* @param Config $oConfig
* @return void
*/
public function SetConfig(Config $oConfig);
/**
* Tells if this provider is enabled for the given user
* @param User $oUser The user for who to check if the provider is applicable.
* return bool
*/
public function IsApplicable(User $oUser = null);
/**
* The human readable (localized) label for this provider
* @return string
*/
public function GetLabel();
/**
* The URL to query (from the browser, using jsonp) to fetch all unread messages
* @return string
*/
public function GetFetchURL();
/**
* The URL to navigate to in order to display all messages
* @return string
*/
public function GetViewAllURL();
/**
* The URL to query(from the browser, using jsonp) to mark all unread messages as read
* @return string
*/
public function GetMarkAllAsReadURL();
/**
* Return the URL to configure the preferences for this provider or null is there is nothing to configure
* @return string|null
*/
public function GetPreferencesUrl();
/**
* Return an array key => value to be replaced in URL of the messages
* Example: '%itop_root%' => utils::GetAbsoluteUrlAppRoot();
* @return string[]
*/
public function GetPlaceholders();
/**
* The duration between to refreshes of the cache (in seconds)
* @return int
*/
public function GetTTL();
}
/**
* Basic implementation of a Newsroom provider, to be overloaded by your own provider implementation
*
*/
abstract class NewsroomProviderBase implements iNewsroomProvider
{
/**
* The current configuration parameters
* @var Config
*/
protected $oConfig;
public function __construct()
{
$this->oConfig = null;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::SetConfig()
*/
public function SetConfig(Config $oConfig)
{
$this->oConfig = $oConfig;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetPreferencesUrl()
*/
public function GetPreferencesUrl()
{
return null; // No preferences
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetLabel()
*/
public abstract function GetLabel();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetFetchURL()
*/
public abstract function GetFetchURL();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetMarkAllURL()
*/
public abstract function GetMarkAllAsReadURL();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetViewAllURL()
*/
public abstract function GetViewAllURL();
public function IsApplicable(User $oUser = null)
{
return false;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetPlaceholders()
*/
public function GetPlaceholders()
{
return array(); // By default, empty set of placeholders
}
public function GetTTL()
{
return 10*60; // Refresh every 10 minutes
}
}

View File

@@ -37,15 +37,8 @@ class NiceWebPage extends WebPage
{
parent::__construct($s_title, $bPrintable);
$this->m_aReadyScripts = array();
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-3.3.1.min.js');
if(utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
{
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.dev.js');
}
else
{
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.prod.min.js');
}
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-1.12.4.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-1.4.1.min.js'); // Needed since many other plugins still rely on oldies like $.browser
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/ui-lightness/jquery-ui-1.11.4.custom.css');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
@@ -54,7 +47,6 @@ class NiceWebPage extends WebPage
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.pager.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablehover.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
@@ -69,7 +61,6 @@ class NiceWebPage extends WebPage
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_field.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_numeric.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_enum.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_tag_set.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_key.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_hierarchical_key.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_abstract.js');

View File

@@ -35,7 +35,7 @@ class iTopPDF extends TCPDF
// Display the page number (right aligned)
// Warning: the 'R'ight alignment does not work when using placeholders like $this->getAliasNumPage() or $this->getAliasNbPages()
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber' ,$this->page), 0, 'R', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
$this->MultiCell($iPageNumberWidth, 15, 'Page '.$this->page, 0, 'R', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
// Branding logo
$sBrandingIcon = APPROOT.'images/itop-logo.png';

View File

@@ -807,7 +807,7 @@ EOF
*/
public function DoUpdateObjectFromPostedForm(DBObject $oObj, $aAttList = null)
{
$sTransactionId = utils::ReadPostedParam('transaction_id', '', 'transaction_id');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId))
{
throw new TransactionException();

View File

@@ -47,12 +47,13 @@ abstract class Query extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'fields')); // 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', array('name', 'description')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'fields')); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
@@ -77,9 +78,6 @@ class QueryOQL extends Query
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
@@ -138,41 +136,6 @@ class QueryOQL extends Query
}
return $aFieldsMap;
}
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
//
// public function ComputeValues()
// {
// parent::ComputeValues();
//
// // Remove unwanted attribute codes
// $aChanges = $this->ListChanges();
// if (isset($aChanges['fields']))
// {
// $oAttDef = MetaModel::GetAttributeDef(get_class($this), 'fields');
// $aArgs = array('this' => $this);
// $aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
//
// /** @var \ormSet $oValue */
// $oValue = $this->Get('fields');
// $aValues = $oValue->GetValues();
// $bChanged = false;
// foreach($aValues as $key => $sValue)
// {
// if (!isset($aAllowedValues[$sValue]))
// {
// unset($aValues[$key]);
// $bChanged = true;
// }
// }
// if ($bChanged)
// {
// $oValue->SetValues($aValues);
// $this->Set('fields', $oValue);
// }
// }
// }
}
?>

View File

@@ -24,26 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
// This storage is freed on error (case of allowed memory exhausted)
$sReservedMemory = str_repeat('*', 1024 * 1024);
register_shutdown_function(function()
{
global $sReservedMemory;
$sReservedMemory = null;
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR))
{
if (strpos($err['message'], 'Allowed memory size of') !== false)
{
$sLimit = ini_get('memory_limit');
echo "<p>iTop: Allowed memory size of $sLimit exhausted, contact your administrator to increase memory_limit in php.ini</p>\n";
}
else
{
echo "<p>iTop: An error occurred, check server error log for more information.</p>\n";
}
}
});
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/core/contexttag.class.inc.php');

View File

@@ -399,7 +399,6 @@ class ObjectDetailsTemplate extends DisplayTemplate
$aPlugInProperties = $aMatches[1];
foreach($aPlugInProperties as $sPlugInClass)
{
/** @var \iApplicationUIExtension $oInstance */
$oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass);
if ($oInstance != null) // Safety check...
{

View File

@@ -119,7 +119,7 @@ class privUITransactionSession
// Strictly speaking, the two lines below should be grouped together
// by a critical section
// sem_acquire($rSemIdentified);
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
$id = str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
$_SESSION['transactions'][$id] = true;
// sem_release($rSemIdentified);
@@ -174,17 +174,6 @@ class privUITransactionSession
// sem_release($rSemIdentified);
}
}
/**
* Returns a string to prefix transaction ID with info from the current user.
*
* @return string
*/
protected static function GetUserPrefix()
{
$sPrefix = 'u'.UserRights::GetUserId();
return $sPrefix.'-';
}
}
/**
@@ -217,7 +206,7 @@ class privUITransactionFile
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
}
self::CleanupOldTransactions();
$id = basename(tempnam(APPROOT.'data/transactions', static::GetUserPrefix()));
$id = basename(tempnam(APPROOT.'data/transactions', self::GetUserPrefix()));
self::Info('GetNewTransactionId: Created transaction: '.$id);
return (string)$id;
@@ -321,11 +310,6 @@ class privUITransactionFile
return $aResult;
}
/**
* Returns a prefix based on the user login instead of its ID for a better usage in tempnam()
*
* @inheritdoc
*/
protected static function GetUserPrefix()
{
$sPrefix = substr(UserRights::GetUser(), 0, 10);

View File

@@ -208,11 +208,6 @@ class UIExtKeyWidget
{
// When there is only once choice, select it by default
$sSelected = 'selected';
$oPage->add_ready_script(
<<<EOF
$('#$this->iId').attr('data-validate','dependencies');
EOF
);
}
else
{
@@ -337,8 +332,7 @@ EOF
if ( ($oCurrObject != null) && ($this->sAttCode != ''))
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
/** @var \DBObject $oCurrObject */
$aArgs = $oCurrObject->ToArgsForQuery();
$aArgs = array('this' => $oCurrObject);
$aParams = array('query_params' => $aArgs);
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs);
$oFilter = $oSet->GetFilter();
@@ -408,7 +402,7 @@ EOF
// Current extkey value, so we can display event if it is not available anymore (eg. archived).
$iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode);
$oBlock = new DisplayBlock($oFilter, 'list_search', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
$oBlock = new DisplayBlock($oFilter, 'list', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId, 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results
}

View File

@@ -101,7 +101,7 @@ class UIHTMLEditorWidget
$oPage->add_ready_script(
<<<EOF
$('#$iId').bind('update', function(evt){
BlockField('cke_$iId', $('#$iId').prop('disabled'));
BlockField('cke_$iId', $('#$iId').attr('disabled'));
//Delayed execution - ckeditor must be properly initialized before setting readonly
var retryCount = 0;
var oMe = $('#$iId');

View File

@@ -286,13 +286,11 @@ class UILinksWidgetDirect
* @param DBObject $oCurrentObj
* @param $aAlreadyLinked
*
* @param array $aPrefillFormParam
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \Exception
* @throws \OQLException
*/
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array())
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked)
{
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
@@ -335,8 +333,6 @@ class UILinksWidgetDirect
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
$oFilter->SetInternalParams($aArgs);
$aPrefillFormParam['filter'] = $oFilter;
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
}
$oBlock = new DisplayBlock($oFilter, 'search', false);
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}",
@@ -363,17 +359,13 @@ class UILinksWidgetDirect
/**
* Search for objects to be linked to the current object (i.e "remote" objects)
*
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of $this->sLinkedClass
* @param array $aAlreadyLinked Array of indentifiers of objects which are already linke to the current object (or about to be linked)
* @param DBObject $oCurrentObj The object currently being edited... if known...
* @param array $aPrefillFormParam
*
* @throws \CoreException
* @throws \OQLException
* @throws Exception
*/
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null, $aPrefillFormParam = array())
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null)
{
if ($sRemoteClass == '')
{
@@ -403,19 +395,16 @@ class UILinksWidgetDirect
$oFilter->AddCondition('id', $oCurrentObj->GetKey(), '!=');
}
}
if (count($aAlreadyLinked) > 0)
{
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
}
if ($oCurrentObj != null)
{
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
$oFilter->SetInternalParams($aArgs);
$aPrefillFormParam['filter'] = $oFilter;
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
}
if (count($aAlreadyLinked) > 0)
{
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
}
$oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results

View File

@@ -73,17 +73,17 @@ class UIPasswordWidget
$oPage->add_ready_script("$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
$oPage->add_ready_script("$('#{$this->iId}').bind('update', function(evt, sFormId)
{
if ($(this).prop('disabled'))
if ($(this).attr('disabled'))
{
$('#{$this->iId}_confirm').prop('disabled', true);
$('#{$this->iId}_changed').prop('disabled', true);
$('#{$this->iId}_reset').prop('disabled', true);
$('#{$this->iId}_confirm').attr('disabled', 'disabled');
$('#{$this->iId}_changed').attr('disabled', 'disabled');
$('#{$this->iId}_reset').attr('disabled', 'disabled');
}
else
{
$('#{$this->iId}_confirm').prop('disabled', false);
$('#{$this->iId}_changed').prop('disabled', false);
$('#{$this->iId}_reset').prop('disabled', false);
$('#{$this->iId}_confirm').removeAttr('disabled');
$('#{$this->iId}_changed').removeAttr('disabled');
$('#{$this->iId}_reset').removeAttr('disabled');
}
}
);"); // Bind to a custom event: update to handle enabling/disabling

View File

@@ -287,79 +287,74 @@ class utils
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
switch ($sSanitizationFilter)
switch($sSanitizationFilter)
{
case 'integer':
$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
break;
$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
break;
case 'class':
$retValue = $value;
if (!MetaModel::IsValidClass($value))
{
$retValue = false;
}
break;
$retValue = $value;
if (!MetaModel::IsValidClass($value))
{
$retValue = false;
}
break;
case 'string':
$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
break;
$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
break;
case 'context_param':
case 'parameter':
case 'field_name':
if (is_array($value))
if (is_array($value))
{
$retValue = array();
foreach($value as $key => $val)
{
$retValue = array();
foreach ($value as $key => $val)
$retValue[$key] = self::Sanitize_Internal($val, $sSanitizationFilter); // recursively check arrays
if ($retValue[$key] === false)
{
$retValue[$key] = self::Sanitize_Internal($val, $sSanitizationFilter); // recursively check arrays
if ($retValue[$key] === false)
{
$retValue = false;
break;
}
$retValue = false;
break;
}
}
else
}
else
{
switch($sSanitizationFilter)
{
switch ($sSanitizationFilter)
{
case 'transaction_id':
// same as parameter type but keep the dot character
// see N°1835 : when using file transaction_id on Windows you get *.tmp tokens
// it must be included at the regexp beginning otherwise you'll get an invalid character error
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case 'transaction_id':
// same as parameter type but keep the dot character
// see N°1835 : when using file transaction_id on Windows you get *.tmp tokens
// it must be included at the regexp beginning otherwise you'll get an invalid character error
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case 'parameter':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
// characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case 'field_name':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
case 'context_param':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
break;
}
case 'parameter':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^([ A-Za-z0-9_=-]|%3D|%2B|%2F)*$/'))); // the '=', '%3D, '%2B', '%2F' characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case 'field_name':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
case 'context_param':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^[ A-Za-z0-9_=%:+-]*$/')));
break;
}
break;
}
break;
default:
case 'raw_data':
$retValue = $value;
$retValue = $value;
// Do nothing
}
return $retValue;
return $retValue;
}
/**
@@ -541,7 +536,7 @@ class utils
/**
* Returns a unique tmp id for the current upload based on the transaction system (db).
*
* Build as static::GetNewTransactionId()
* Build as session_id() . '_' . static::GetNewTransactionId()
*
* @return string
*/
@@ -551,7 +546,7 @@ class utils
{
$sTransactionId = static::GetNewTransactionId();
}
return $sTransactionId;
return session_id() . '_' . $sTransactionId;
}
public static function ReadFromFile($sFileName)
@@ -586,18 +581,6 @@ class utils
}
return $iReturn;
}
/**
* Checks if the memory limit is at least what is required
*
* @param int $memoryLimit set limit in bytes
* @param int $requiredLimit required limit in bytes
* @return bool
*/
public static function IsMemoryLimitOk($memoryLimit, $requiredLimit)
{
return ($memoryLimit >= $requiredLimit) || ($memoryLimit == -1);
}
/**
* Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount.
@@ -742,11 +725,7 @@ class utils
}
/**
* Returns the absolute URL to the application root path
*
* @return string The absolute URL to the application root, without the first slash
*
* @throws \Exception
* @return string The absolute URL to the application, including host and path
*/
static public function GetAbsoluteUrlAppRoot()
{
@@ -775,15 +754,7 @@ class utils
return $sUrl;
}
/**
* Builds an root url from the server's variables.
* For most usages, when an root url is needed, use utils::GetAbsoluteUrlAppRoot() instead as uses this only as a fallback when the app_root_url conf parameter is not defined.
*
* @return string
*
* @throws \Exception
*/
static public function GetDefaultUrlAppRoot()
static public function GetDefaultUrlAppRoot()
{
// Build an absolute URL to this page on this server/port
$sServerName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
@@ -852,7 +823,7 @@ class utils
/**
* Helper to handle the variety of HTTP servers
* See 286 (fixed in [896]), and 634 (this fix)
* See #286 (fixed in [896]), and #634 (this fix)
*
* Though the official specs says 'a non empty string', some servers like IIS do set it to 'off' !
* nginx set it to an empty string
@@ -1105,7 +1076,12 @@ class utils
// $param is a DBObject
$oObj = $param;
$sOQL = "SELECT ".get_class($oObj)." WHERE id=".$oObj->GetKey();
$oFilter = DBObjectSearch::FromOQL($sOQL);
$sFilter = $oFilter->serialize();
$sUrl = ApplicationContext::MakeObjectUrl(get_class($oObj), $oObj->GetKey());
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage(get_class($oObj));
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/tabularfieldsselector.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.dragtable.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/dragtable.css');
@@ -1125,29 +1101,21 @@ class utils
break;
case iPopupMenuExtension::MENU_DASHBOARD_ACTIONS:
// $param is a Dashboard
/** @var \RuntimeDashboard $oDashboard */
$oDashboard = $param;
$sDashboardId = $oDashboard->GetId();
$sDashboardFile = $oDashboard->GetDefinitionFile();
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
$sDashboardFileJS = addslashes($sDashboardFile);
$sDashboardFileURL = urlencode($sDashboardFile);
// $param is a Dashboard
$oAppContext = new ApplicationContext();
$aParams = $oAppContext->GetAsHash();
$sMenuId = ApplicationMenu::GetActiveNodeId();
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
$sUploadDashboardTransactId = utils::GetNewTransactionId();
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
);
if ($oDashboard->GetReloadURL())
{
$aResult[] = new SeparatorPopupMenuItem();
$aResult[] = new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $oDashboard->GetReloadURL().'&printable=1', '_blank');
}
break;
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sMenuId),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'),
"UploadDashboard({dashboard_id: '$sMenuId', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
);
break;
default:
// Unknown type of menu, do nothing
@@ -1514,7 +1482,7 @@ class utils
static public function GetCSSFromSASS($sSassRelPath, $aImportPaths = null)
{
// Avoiding compilation if file is already a css file.
if (preg_match('/\.css(\?.*)?$/', $sSassRelPath))
if (preg_match('/\.css$/', $sSassRelPath))
{
return $sSassRelPath;
}
@@ -2022,14 +1990,4 @@ class utils
$aHugeClasses = MetaModel::GetConfig()->Get('high_cardinality_classes');
return in_array($sClass, $aHugeClasses);
}
/**
* Check if iTop is in a development environment (VCS vs build number)
*
* @return bool
*/
public static function IsDevelopmentEnvironment()
{
return ITOP_REVISION === 'svn';
}
}

View File

@@ -311,10 +311,7 @@ class WebPage implements Page
}
/**
* Add a script (as an include, i.e. link) to the header of the page.<br>
* Handles duplicates : calling twice with the same script will add the script only once
*
* @param string $s_linked_script
* Add a script (as an include, i.e. link) to the header of the page
*/
public function add_linked_script($s_linked_script)
{

View File

@@ -154,7 +154,7 @@ class WizardHelper
}
else
{
// May happen for security reasons (portal, see ticket 1074)
// May happen for security reasons (portal, see ticket #1074)
$oObj->Set($sAttCode, $value);
}
}
@@ -174,30 +174,6 @@ class WizardHelper
}
$oObj->Set($sAttCode, $value);
}
else if ($oAttDef instanceof AttributeTagSet) // AttributeDate is derived from AttributeDateTime
{
if (is_null($value))
{
// happens if field is hidden (see N°1827)
$value = array();
}
else
{
$value = json_decode($value, true);
}
$oTagSet = new ormTagSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else if ($oAttDef instanceof AttributeSet) // AttributeDate is derived from AttributeDateTime
{
$value = json_decode($value, true);
$oTagSet = new ormSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else
{
$oObj->Set($sAttCode, $value);
@@ -229,10 +205,11 @@ class WizardHelper
// this as to be handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
// NOT YET IMPLEMENTED !!
$sLinkedClass = $oAttDef->GetLinkedClass();
$oSet = $value;
$aData = array();
$aFields = $this->GetLinkedWizardStructure($oAttDef);
while($oLinkedObj = $oSet->fetch())
while($oSet->fetch())
{
foreach($aFields as $sLinkedAttCode)
{

View File

@@ -40,7 +40,7 @@ Class XLSXWriter
protected function tempFilename()
{
$filename = tempnam(SetupUtils::GettmpDir(), 'xlsx_writer_');
$filename = tempnam("/tmp", "xlsx_writer_");
$this->temp_files[] = $filename;
return $filename;
}

View File

@@ -1,22 +1,16 @@
{
"require": {
"php": ">=5.6.0",
"ext-mysql": "*",
"ext-ldap": "*",
"ext-mcrypt": "*",
"ext-cli": "*",
"ext-soap": "*",
"ext-json": "*",
"ext-zip": "*",
"ext-mysqli": "*",
"ext-dom": "*",
"ext-iconv": "*",
"ext-gd": "*"
},
"suggest": {
"ext-libsodium": "Required to use the AttributeEncryptedString.",
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
"ext-mcrypt": "Can be used as a polyfill if either libsodium and openssl are not installed (libsodium and openssl are more secure)",
"ext-ldap": "Required to use LDAP as an identity provider",
"ext-posix": "Not required by the core, but some extensions uses it.",
"ext-imap": "Required by the extension \"Mail to ticket automation\""
},
"config": {
"platform": {
"php": "5.6.0"

3054
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,105 +0,0 @@
# Contributing to iTop
You want to contribute to iTop? Many thanks to you! 🎉 👍
Here are some guidelines that will help us integrate your work!
## Contributions
### Subjects
You are welcome to create pull requests on any of those subjects:
* 🐛 `:bug:` bug fix
* 🔒 `:lock:` security
* 🌐 `:globe_with_meridians:` translation / i18n / l10n
If you want to implement a **new feature**, please [create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) for review.
If you ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the ticket.
### License
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file),
your code must comply with this license.
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
## Branch model
TL;DR:
> **create a fork from iTop main repository,
> create a branch based on either release branch if present, or develop otherwise**
We are using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. That means we have in our repo those
main branches:
- develop: ongoing development version
- release/\*: if present, that means we are working on a beta version
- master: previous stable version
For example, if no beta version is currently ongoing we could have:
- develop containing future 2.8.0 version
- master containing 2.7.x maintenance version
In this example, when 2.8.0-beta is shipped that will become:
- develop: future 2.9.0 version
- release/2.8: 2.8.0-beta
- master: 2.7.x maintenance version
And when 2.8.0 final will be out:
- develop: future 2.9.0 version
- master: 2.8.x maintenance version
- support/2.7 : 2.7.x maintenance version
## Coding
### PHP styleguide
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
### 🌐 Translations
A [dedicated page](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Atranslation) is available in the official wiki.
### Tests
Please create tests that covers as much as possible the code you're submitting.
Our tests are located in the `test/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
### Git Commit Messages
* Describe the functional change instead of the technical modifications
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)). For example :
* 🌐 `:globe_with_meridians:` for translations
* 🎨 `:art:` when improving the format/structure of the code
* ⚡️ `:zap:` when improving performance
* 🐛 `:bug:` when fixing a bug
* 🔥 `:fire:` when removing code or files
* 💚 `:green_heart:` when fixing the CI build
*`:white_check_mark:` when adding tests
* 🔒 `:lock:` when dealing with security
* ⬆️ `:arrow_up:` when upgrading dependencies
* ⬇️ `:arrow_down:` when downgrading dependencies
* ♻️ `:recycle:` code refactoring
* 💄 `:lipstick:` Updating the UI and style files.
## Pull request
When your code is working, please:
* stash 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/).

View File

@@ -223,14 +223,7 @@ class ActionEmail extends ActionNotification
return implode(', ', $aRecipients);
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
*/
public function DoExecute($oTrigger, $aContextArgs)
{
if (MetaModel::IsLogEnabledNotification())
@@ -299,14 +292,6 @@ class ActionEmail extends ActionNotification
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
* @param \EventNotification $oLog
*
* @return string
* @throws \CoreException
*/
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
{
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();

View File

@@ -150,7 +150,7 @@ abstract class AsyncTask extends DBObject
public function GetRetryDelay($iErrorCode = null)
{
$iRetryDelay = 600;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
@@ -162,7 +162,7 @@ abstract class AsyncTask extends DBObject
public function GetMaxRetries($iErrorCode = null)
{
$iMaxRetries = 0;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
@@ -381,6 +381,6 @@ class AsyncSendEmail extends AsyncTask
case EMAIL_SEND_ERROR:
return "Failed: ".implode(', ', $aIssues);
}
return '';
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ MetaModel::IncludeModule('core/action.class.inc.php');
MetaModel::IncludeModule('core/trigger.class.inc.php');
MetaModel::IncludeModule('core/bulkexport.class.inc.php');
MetaModel::IncludeModule('core/ownershiplock.class.inc.php');
MetaModel::IncludeModule('core/tagsetfield.class.inc.php');
MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php');
MetaModel::IncludeModule('core/backgroundtask.class.inc.php');
MetaModel::IncludeModule('core/inlineimage.class.inc.php');

View File

@@ -242,64 +242,6 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
return $sResult;
}
}
/**
* Record the modification of a tag set attribute
*
* @package iTopORM
*/
class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_setatt_tagset",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
$sResult = '';
$sTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$sAttCode = $this->Get('attcode');
$oTargetSearch = new DBObjectSearch($sTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($sTargetObjectClass, $sAttCode, UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
$sNewValue = $this->Get('newvalue');
$sOldValue = $this->Get('oldvalue');
$sResult = $oAttDef->DescribeChangeAsHTML($sOldValue, $sNewValue);
}
return $sResult;
}
}
/**
* Record the modification of an URL
*

View File

@@ -188,16 +188,6 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange->DBInsert();
}
/**
* @inheritdoc
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordObjCreation()
{
// Delete any existing change tracking about the current object (IDs can be reused due to InnoDb bug; see TRAC #886)
@@ -216,7 +206,6 @@ abstract class CMDBObject extends DBObject
MetaModel::PurgeData($oFilter);
parent::RecordObjCreation();
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpCreate");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
@@ -243,17 +232,9 @@ abstract class CMDBObject extends DBObject
}
/**
* @param string $sAttCode
* @param $sAttCode
* @param $original Original value
* @param $value Current value
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordAttChange($sAttCode, $original, $value)
{
@@ -428,19 +409,7 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("newvalue", $value);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeSet)
{
// Tag Set
//
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeTagSet");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("oldvalue", implode(' ', $original->GetValues()));
$oMyChangeOp->Set("newvalue", implode(' ', $value->GetValues()));
$iId = $oMyChangeOp->DBInsertNoReload();
}
else
else
{
// Scalars
//
@@ -457,14 +426,6 @@ abstract class CMDBObject extends DBObject
/**
* @param array $aValues
* @param array $aOrigValues
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordAttChanges(array $aValues, array $aOrigValues)
{
@@ -590,12 +551,6 @@ abstract class CMDBObject extends DBObject
$this->DBUpdate();
}
/**
* @param null $oDeletionPlan
*
* @return \DeletionPlan|null
* @throws \DeleteException
*/
public function DBDelete(&$oDeletionPlan = null)
{
return $this->DBDeleteTracked_Internal($oDeletionPlan);
@@ -608,12 +563,6 @@ abstract class CMDBObject extends DBObject
$this->DBDeleteTracked_Internal($oDeletionPlan);
}
/**
* @param null $oDeletionPlan
*
* @return \DeletionPlan|null
* @throws \DeleteException
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
$prevkey = $this->GetKey();
@@ -696,8 +645,6 @@ abstract class CMDBObject extends DBObject
* TODO: investigate how to get rid of this class that was made to workaround some language limitation... or a poor design!
*
* @package iTopORM
*
* @internal
*/
class CMDBObjectSet extends DBObjectSet
{

View File

@@ -108,22 +108,18 @@ class MySQLHasGoneAwayException extends MySQLException
*/
class CMDBSource
{
const ENUM_DB_VENDOR_MYSQL = 'MySQL';
const ENUM_DB_VENDOR_MARIADB = 'MariaDB';
const ENUM_DB_VENDOR_PERCONA = 'Percona';
protected static $m_sDBHost;
protected static $m_sDBUser;
protected static $m_sDBPwd;
protected static $m_sDBName;
/**
* @var boolean
* @since 2.5 1260 MySQL TLS first implementation
* @since 2.5 #1260 MySQL TLS first implementation
*/
protected static $m_bDBTlsEnabled;
/**
* @var string
* @since 2.5 1260 MySQL TLS first implementation
* @since 2.5 #1260 MySQL TLS first implementation
*/
protected static $m_sDBTlsCA;
@@ -137,7 +133,7 @@ class CMDBSource
* use expression as value)
*
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-column.html
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
*/
public static function GetSqlStringColumnDefinition()
{
@@ -410,27 +406,6 @@ class CMDBSource
return $aVersions[0];
}
/**
* Get the DB vendor between MySQL and its main forks
* @return string
*/
static public function GetDBVendor()
{
$sDBVendor = static::ENUM_DB_VENDOR_MYSQL;
$sVersionComment = static::GetServerVariable('version') . ' - ' . static::GetServerVariable('version_comment');
if(preg_match('/mariadb/i', $sVersionComment) === 1)
{
$sDBVendor = static::ENUM_DB_VENDOR_MARIADB;
}
else if(preg_match('/percona/i', $sVersionComment) === 1)
{
$sDBVendor = static::ENUM_DB_VENDOR_PERCONA;
}
return $sDBVendor;
}
/**
* @param string $sSource
*
@@ -480,15 +455,10 @@ class CMDBSource
public static function DropTable($sTable)
{
$res = self::Query("DROP TABLE `$sTable`");
self::_TablesInfoCacheReset(); // reset the table info cache!
self::_TablesInfoCacheReset(true); // reset the table info cache!
return $res;
}
public static function CacheReset($sTable)
{
self::_TablesInfoCacheReset($sTable);
}
/**
* @return \mysqli
*/
@@ -900,20 +870,6 @@ class CMDBSource
return ($aFieldData["Type"]);
}
private static function IsNumericType($aFieldData)
{
$aNumericTypes = array('tinyint(', 'decimal(', 'int(' );
$sType = strtolower($aFieldData["Type"]);
foreach ($aNumericTypes as $sNumericType)
{
if (strpos($sType, $sNumericType) === 0)
{
return true;
}
}
return false;
}
/**
* @param string $sTable
* @param string $sField
@@ -952,15 +908,8 @@ class CMDBSource
}
else
{
if (self::IsNumericType($aFieldData))
{
$sRet .= ' DEFAULT '.$aFieldData["Default"];
}
else
{
$default = $aFieldData["Default"] + 0; // Coerce to a numeric variable
$sRet .= ' DEFAULT '.self::Quote($default);
}
$default = $aFieldData["Default"] + 0; // Coerce to a numeric variable
$sRet .= ' DEFAULT '.self::Quote($default);
}
}
elseif (is_string($aFieldData["Default"]) == 'string')
@@ -1018,16 +967,9 @@ class CMDBSource
// Cache the information about existing tables, and their fields
private static $m_aTablesInfo = array();
private static function _TablesInfoCacheReset($sTableName = null)
private static function _TablesInfoCacheReset()
{
if (is_null($sTableName))
{
self::$m_aTablesInfo = array();
}
else
{
self::$m_aTablesInfo[strtolower($sTableName)] = null;
}
self::$m_aTablesInfo = array();
}
/**
@@ -1100,7 +1042,7 @@ class CMDBSource
* @return string query to upgrade table charset and collation if needed, null if not
* @throws \MySQLException
*
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-table.html
*/
public static function DBCheckTableCharsetAndCollation($sTableName)
@@ -1250,7 +1192,7 @@ class CMDBSource
* @return string query to upgrade database charset and collation if needed, null if not
* @throws \MySQLException
*
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-database.html
*/
public static function DBCheckCharsetAndCollation()

View File

@@ -19,7 +19,7 @@
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
define('ITOP_VERSION', '2.6.2');
define('ITOP_VERSION', '2.5.0');
define('ITOP_REVISION', 'svn');
define('ITOP_BUILD_DATE', '$WCNOW$');
@@ -37,7 +37,6 @@ define('ACCESS_READONLY', 0);
require_once('coreexception.class.inc.php');
require_once('attributedef.class.inc.php'); // For the defines
require_once('simplecrypt.class.inc.php');
class ConfigException extends CoreException
{
@@ -65,16 +64,13 @@ define('DEFAULT_FAST_RELOAD_INTERVAL', 1 * 60);
define('DEFAULT_SECURE_CONNECTION_REQUIRED', false);
define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|basic|external');
define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']');
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible)
define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random value, later...
/**
* Config
* configuration data (this class cannot not be localized, because it is responsible for loading the dictionaries)
*
* @package iTopORM
*
* @see \MetaModel::GetConfig() to get the config, if the metamodel was already loaded
* @see utils::GetConfig() to load config from the current env, if metamodel is not loaded
*/
class Config
{
@@ -97,7 +93,7 @@ class Config
protected $m_aSettings = array(
'app_env_label' => array(
'type' => 'string',
'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")',
'description' => 'Label displayed to describe the current application environnment, defaults to the environment name (e.g. "production")',
'default' => '',
'value' => '',
'source_of_value' => '',
@@ -170,7 +166,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'db_character_set' => array( // @deprecated to remove in 2.7 ? 1001 utf8mb4 switch
'db_character_set' => array( // @deprecated to remove in 2.7 ? #1001 utf8mb4 switch
'type' => 'string',
'description' => 'Deprecated since iTop 2.5 : now using utf8mb4',
'default' => 'DEPRECATED_2.5',
@@ -178,7 +174,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'db_collation' => array( // @deprecated to remove in 2.7 ? 1001 utf8mb4 switch
'db_collation' => array( // @deprecated to remove in 2.7 ? #1001 utf8mb4 switch
'type' => 'string',
'description' => 'Deprecated since iTop 2.5 : now using utf8mb4_unicode_ci',
'default' => 'DEPRECATED_2.5',
@@ -204,7 +200,7 @@ class Config
),
'skip_strong_security' => array(
'type' => 'bool',
'description' => 'Disable strong security - TEMPORARY: this flag should be removed when we are more confident in the recent change in security',
'description' => 'Disable strong security - TEMPORY: this flag should be removed when we are more confident in the recent change in security',
'default' => true,
'value' => true,
'source_of_value' => '',
@@ -220,7 +216,7 @@ class Config
),
'query_indentation_enabled' => array(
'type' => 'bool',
'description' => 'For developers: format the SQL queries for human analysis',
'description' => 'For developpers: format the SQL queries for human analysis',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -228,7 +224,7 @@ class Config
),
'disable_mandatory_ext_keys' => array(
'type' => 'bool',
'description' => 'For developers: allow every external keys to be undefined',
'description' => 'For developpers: allow every external keys to be undefined',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -411,14 +407,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'tag_set_item_separator' => array(
'type' => 'string',
'description' => 'Tag set from string: tag label separator',
'default' => '|',
'value' => '|',
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'cron_max_execution_time' => array(
'type' => 'integer',
'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout',
@@ -453,7 +441,7 @@ class Config
),
'email_transport' => array(
'type' => 'string',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocole)',
'default' => "PHPMail",
'value' => "PHPMail",
'source_of_value' => '',
@@ -549,7 +537,7 @@ class Config
),
'timezone' => array(
'type' => 'string',
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitly configured in PHP',
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitely configured in PHP',
// examples... not used (nor 'description')
'examples' => array(
'America/Sao_Paulo',
@@ -947,7 +935,7 @@ class Config
),
'tracking_level_linked_set_default' => array(
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'description' => 'Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'default' => LINKSET_TRACKING_LIST,
'value' => LINKSET_TRACKING_LIST,
'source_of_value' => '',
@@ -955,7 +943,7 @@ class Config
),
'tracking_level_linked_set_indirect_default' => array(
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSetIndirect',
'description' => 'Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSetIndirect',
'default' => LINKSET_TRACKING_ALL,
'value' => LINKSET_TRACKING_ALL,
'source_of_value' => '',
@@ -996,7 +984,7 @@ class Config
'transaction_storage' => array(
'type' => 'string',
'description' => 'The type of mechanism to use for storing the unique identifiers for transactions (Session|File).',
'default' => 'File',
'default' => 'Session',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
@@ -1068,7 +1056,7 @@ class Config
'draft_attachments_lifetime' => array(
'type' => 'integer',
'description' => 'Lifetime (in seconds) of drafts\' attachments and inline images: after this duration, the garbage collector will delete them.',
'default' => 86400,
'default' => 3600,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
@@ -1129,14 +1117,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'optimize_requests_for_join_count' => array(
'type' => 'bool',
'description' => 'Optimize request joins to minimize the count (default is true, try to set it to false in case of performance issues)',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'high_cardinality_classes' => array(
'type' => 'array',
'description' => 'List of classes with high cardinality (Force manual submit of search)',
@@ -1145,22 +1125,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'newsroom_enabled' => array(
'type' => 'bool',
'description' => 'Whether or not the whole newsroom is enabled',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'regenerate_session_id_enabled' => array(
'type' => 'bool',
'description' => 'If true then session id will be regenerated on each login, to prevent session fixation.',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
);
public function IsProperty($sPropCode)
@@ -1220,11 +1184,6 @@ class Config
}
/**
* @param string $sPropCode
*
* @return mixed
*/
public function Get($sPropCode)
{
return $this->m_aSettings[$sPropCode]['value'];
@@ -1287,29 +1246,13 @@ class Config
*/
protected $m_sEncryptionKey;
/**
* @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value
* unless you want to import a database from another iTop instance, in which case you must use
* the same encryption key in order to properly decode the encrypted fields
*/
protected $m_sEncryptionLibrary;
/**
* @var array Additional character sets to be supported by the interactive CSV import
* 'iconv_code' => 'display name'
*/
protected $m_aCharsets;
/**
* Config constructor.
*
* @param string|null $sConfigFile
* @param bool $bLoadConfig
*
* @throws \ConfigException
* @throws \CoreException
*/
public function __construct($sConfigFile = null, $bLoadConfig = true)
public function __construct($sConfigFile = null, $bLoadConfig = true)
{
$this->m_sFile = $sConfigFile;
if (is_null($sConfigFile))
@@ -1339,14 +1282,10 @@ class Config
$this->m_sDefaultLanguage = 'EN US';
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
$this->m_sEncryptionKey = DEFAULT_ENCRYPTION_KEY;
$this->m_aCharsets = array();
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
//define default encryption params according to php install
$aEncryptParams = SimpleCrypt::GetNewDefaultParams();
$this->m_sEncryptionLibrary = isset($aEncryptParams['lib']) ? $aEncryptParams['lib'] : DEFAULT_ENCRYPTION_LIB;
$this->m_sEncryptionKey= isset($aEncryptParams['key']) ? $aEncryptParams['key'] : DEFAULT_ENCRYPTION_KEY;
$this->m_aModuleSettings = array();
if ($bLoadConfig)
@@ -1371,13 +1310,7 @@ class Config
*/
}
/**
* @param string $sPurpose
* @param string $sFileName
*
* @throws \ConfigException
*/
protected function CheckFile($sPurpose, $sFileName)
protected function CheckFile($sPurpose, $sFileName)
{
if (!file_exists($sFileName))
{
@@ -1492,8 +1425,7 @@ class Config
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : DEFAULT_ENCRYPTION_KEY;
$this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : array();
}
@@ -1514,14 +1446,7 @@ class Config
return $this->GetModuleParameter($sModule, $sProperty, $defaultvalue);
}
/**
* @param string $sModule
* @param string $sProperty
* @param mixed|null $defaultvalue
*
* @return mixed|null
*/
public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null)
public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null)
{
$ret = $defaultvalue;
if (class_exists('ModulesXMLParameters'))
@@ -1553,7 +1478,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1564,7 +1488,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1575,7 +1498,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1586,8 +1508,7 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch
* @deprecated 2.5 will be removed in 2.6 #1001 utf8mb4 switch
* @see Config::DEFAULT_CHARACTER_SET
*/
public function GetDBCharacterSet()
@@ -1597,8 +1518,7 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch
* @deprecated 2.5 will be removed in 2.6 #1001 utf8mb4 switch
* @see Config::DEFAULT_COLLATION
*/
public function GetDBCollation()
@@ -1608,7 +1528,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1619,7 +1538,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1693,11 +1611,6 @@ class Config
return $this->m_sEncryptionKey;
}
public function GetEncryptionLibrary()
{
return $this->m_sEncryptionLibrary;
}
public function GetAllowedLoginTypes()
{
return explode('|', $this->m_sAllowedLoginTypes);
@@ -1826,7 +1739,6 @@ class Config
$aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes;
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
$aSettings['csv_import_charsets'] = $this->m_aCharsets;
foreach ($this->m_aModuleSettings as $sModule => $aProperties)
@@ -1844,16 +1756,14 @@ class Config
return $aSettings;
}
/**
* Write the configuration to a file (php format) that can be reloaded later
* By default write to the same file that was specified when constructing the object
*
* @param string $sFileName string Name of the file to write to (emtpy to write to the same file)
*
* @return boolean True otherwise throws an Exception
/**
* Write the configuration to a file (php format) that can be reloaded later
* By default write to the same file that was specified when constructing the object
*
* @throws \ConfigException
*/
* @param $sFileName string Name of the file to write to (emtpy to write to the same file)
*
* @return boolean True otherwise throws an Exception
*/
public function WriteToFile($sFileName = '')
{
if (empty($sFileName))
@@ -1915,7 +1825,6 @@ class Config
'allowed_login_types' => $this->m_sAllowedLoginTypes,
'ext_auth_variable' => $this->m_sExtAuthVariable,
'encryption_key' => $this->m_sEncryptionKey,
'encryption_library' => $this->m_sEncryptionLibrary,
'csv_import_charsets' => $this->m_aCharsets,
);
foreach ($aOtherValues as $sKey => $value)
@@ -2001,16 +1910,9 @@ class Config
}
}
/**
* Helper function to initialize a configuration from the page arguments
*
* @param array $aParamValues
* @param string|null $sModulesDir
* @param bool $bPreserveModuleSettings
*
* @throws \Exception
* @throws \CoreException
*/
/**
* Helper function to initialize a configuration from the page arguments
*/
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
{
if (isset($aParamValues['application_path']))
@@ -2140,13 +2042,9 @@ class Config
}
}
/**
* Helper: for an array of string, change the prefix when found
*
* @param array $aStrings
* @param string $sSearchPrefix
* @param string $sNewPrefix
*/
/**
* Helper: for an array of string, change the prefix when found
*/
protected static function ChangePrefix(&$aStrings, $sSearchPrefix, $sNewPrefix)
{
foreach ($aStrings as &$sFile)
@@ -2158,13 +2056,10 @@ class Config
}
}
/**
* Obsolete: kept only for backward compatibility of the Toolkit
* Quick and dirty way to clone a config file into another environment
*
* @param string $sSourceEnv
* @param string $sTargetEnv
*/
/**
* Obsolete: kept only for backward compatibility of the Toolkit
* Quick and dirty way to clone a config file into another environment
*/
public function ChangeModulesPath($sSourceEnv, $sTargetEnv)
{
// Now does nothing since the includes are built into the environment itself
@@ -2201,3 +2096,5 @@ class Config
}
}
?>

View File

@@ -107,82 +107,6 @@ class CoreException extends Exception
}
}
/**
* 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 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)
{
$this->aIssues = $aContextData['issues'];
$this->iObjectId = $aContextData['id'];
$this->sObjectClass = $aContextData['class'];
$sIssues = implode(', ', $this->aIssues);
parent::__construct($sIssues, $aContextData);
}
/**
* @return string
*/
public function getHtmlMessage()
{
$sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = "<span><strong>{$sTitle}</strong></span>";
if (count($this->aIssues) == 1)
{
$sIssue = reset($this->aIssues);
$sContent .= " <span>{$sIssue}</span>";
}
else
{
$sContent .= '<ul>';
foreach ($this->aIssues as $sError)
{
$sContent .= "<li>$sError</li>";
}
$sContent .= '</ul>';
}
return $sContent;
}
public function getIssues()
{
return $this->aIssues;
}
public function getObjectId()
{
return $this->iObjectId;
}
public function getObjectClass()
{
return $this->sObjectClass;
}
}
class CoreWarning extends CoreException
{
}

View File

@@ -266,7 +266,7 @@ EOF
if ($this->aStatusInfo['charset'] != 'UTF-8')
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket 991)
// and thus to convert field by field and not the whole row or file at once (see ticket #991)
$aData[$idx] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $aData[$idx]);
}
}
@@ -325,7 +325,7 @@ EOF
if ($this->aStatusInfo['charset'] != 'UTF-8')
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket 991)
// and thus to convert field by field and not the whole row or file at once (see ticket #991)
$aData[] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $sField);
}
else

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.5">
<user_rights>
<profiles>
<profile id="1024" _delta="define">

File diff suppressed because it is too large Load Diff

View File

@@ -17,22 +17,9 @@
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
/** @internal Dev hack for disabling some query build optimizations (Folding/Merging) */
// Dev hack for disabling the some query build optimizations (Folding/Merging)
define('ENABLE_OPT', true);
/**
* A search over a DBObject
*
* This is the most common search cases, the other class representing a search is DBUnionSearch.
* For clarity purpose, since only the constructor vary between DBObjectSearch and DBUnionSearch, all the API is documented on the common ancestor: DBSearch
* Please refer to DBSearch's documentation
*
* @package iTopORM
* @phpdoc-tuning-exclude-inherited this tag prevent PHPdoc from displaying inherited methods. This is done in order to force the API doc. location into DBSearch only.
* @api
* @see DBSearch
* @see DBUnionSearch
*/
class DBObjectSearch extends DBSearch
{
private $m_aClasses; // queried classes (alias => class name), the first item is the class corresponding to this filter (the rest is coming from subfilters)
@@ -42,23 +29,11 @@ class DBObjectSearch extends DBSearch
private $m_aPointingTo;
private $m_aReferencedBy;
/**
* @var bool whether or not some information should be hidden to the current user. Default to false == hide information.
* @see AllowAllData()
*/
// By default, some information may be hidden to the current user
// But it may happen that we need to disable that feature
protected $m_bAllowAllData = false;
protected $m_bDataFiltered = false;
/**
* DBObjectSearch constructor.
*
* @api
*
* @param string $sClass
* @param string|null $sClassAlias
*
* @throws Exception
*/
public function __construct($sClass, $sClassAlias = null)
{
parent::__construct();
@@ -505,11 +480,6 @@ class DBObjectSearch extends DBSearch
$oNewCondition = Expression::FromOQL($sOQLCondition);
break;
case 'MATCHES':
$oRightExpr = new ScalarExpression($value);
$oNewCondition = new MatchExpression($oField, $oRightExpr);
break;
case 'Contains':
case 'Begins with':
case 'Finishes with':
@@ -549,7 +519,7 @@ class DBObjectSearch extends DBSearch
/**
* Specify a condition on external keys or link sets
* @param string $sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
* Example: infra_list->ci_id->location_id->country
* Example: infra_list->ci_id->location_id->country
* @param $value
* @return void
* @throws \CoreException
@@ -1329,13 +1299,6 @@ class DBObjectSearch extends DBSearch
$oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases);
return new BinaryExpression($oLeft, $sOperator, $oRight);
}
elseif ($oExpression instanceof MatchOqlExpression)
{
$oLeft = $this->OQLExpressionToCondition($sQuery, $oExpression->GetLeftExpr(), $aClassAliases);
$oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases);
return new MatchExpression($oLeft, $oRight);
}
elseif ($oExpression instanceof FieldOqlExpression)
{
$sClassAlias = $oExpression->GetParent();
@@ -1667,7 +1630,7 @@ class DBObjectSearch extends DBSearch
// Query caching
//
$sOqlAPCCacheId = null;
if (self::$m_bQueryCacheEnabled && $bCanCache)
if (self::$m_bQueryCacheEnabled)
{
// Warning: using directly the query string as the key to the hash array can FAIL if the string
// is long and the differences are only near the end... so it's safer (but not bullet proof?)
@@ -1962,86 +1925,46 @@ class DBObjectSearch extends DBSearch
}
}
$bRootFirst = MetaModel::GetConfig()->Get('optimize_requests_for_join_count');
if ($bRootFirst)
// First query built from the root, adding all tables including the leaf
// Before N.1065 we were joining from the leaf first, but this wasn't a good choice :
// most of the time (obsolescence, friendlyname, ...) we want to get a root attribute !
//
$oSelectBase = null;
$aClassHierarchy = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, true);
$bIsClassStandaloneClass = (count($aClassHierarchy) == 1);
foreach($aClassHierarchy as $sSomeClass)
{
// First query built from the root, adding all tables including the leaf
// Before N.1065 we were joining from the leaf first, but this wasn't a good choice :
// most of the time (obsolescence, friendlyname, ...) we want to get a root attribute !
//
$oSelectBase = null;
$aClassHierarchy = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, true);
$bIsClassStandaloneClass = (count($aClassHierarchy) == 1);
foreach($aClassHierarchy as $sSomeClass)
if (!MetaModel::HasTable($sSomeClass))
{
if (!MetaModel::HasTable($sSomeClass))
{
continue;
}
self::DbgTrace("Adding join from root to leaf: $sSomeClass... let's call MakeSQLObjectQuerySingleTable()");
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSomeClass, $aExtKeys, $aValues);
if (is_null($oSelectBase))
{
$oSelectBase = $oSelectParentTable;
if (!$bIsClassStandaloneClass && (MetaModel::IsRootClass($sSomeClass)))
{
// As we're linking to root class first, we're adding a where clause on the finalClass attribute :
// COALESCE($sRootClassFinalClass IN ('$sExpectedClasses'), 1)
// If we don't, the child classes can be removed in the query optimisation phase, including the leaf that was queried
// So we still need to filter records to only those corresponding to the child classes !
// The coalesce is mandatory if we have a polymorphic query (left join)
$oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$sFinalClassSqlColumnName = MetaModel::DBGetClassField($sSomeClass);
$oClassExpr = new FieldExpression($sFinalClassSqlColumnName, $oSelectBase->GetTableAlias());
$oInExpression = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
$oTrueExpression = new TrueExpression();
$aCoalesceAttr = array($oInExpression, $oTrueExpression);
$oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr);
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
}
else
{
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass));
}
continue;
}
}
else
{
// First query built upon on the leaf (ie current) class
//
self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()");
if (MetaModel::HasTable($sClass))
self::DbgTrace("Adding join from root to leaf: $sSomeClass... let's call MakeSQLObjectQuerySingleTable()");
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSomeClass, $aExtKeys, $aValues);
if (is_null($oSelectBase))
{
$oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues);
$oSelectBase = $oSelectParentTable;
if (!$bIsClassStandaloneClass && (MetaModel::IsRootClass($sSomeClass)))
{
// As we're linking to root class first, we're adding a where clause on the finalClass attribute :
// COALESCE($sRootClassFinalClass IN ('$sExpectedClasses'), 1)
// If we don't, the child classes can be removed in the query optimisation phase, including the leaf that was queried
// So we still need to filter records to only those corresponding to the child classes !
// The coalesce is mandatory if we have a polymorphic query (left join)
$oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$sFinalClassSqlColumnName = MetaModel::DBGetClassField($sSomeClass);
$oClassExpr = new FieldExpression($sFinalClassSqlColumnName, $oSelectBase->GetTableAlias());
$oInExpression = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
$oTrueExpression = new TrueExpression();
$aCoalesceAttr = array($oInExpression, $oTrueExpression);
$oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr);
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
}
else
{
$oSelectBase = null;
// As the join will not filter on the expected classes, we have to specify it explicitely
$sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
// Then we join the queries of the eventual parent classes (compound model)
foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
if (!MetaModel::HasTable($sParentClass)) continue;
self::DbgTrace("Parent class: $sParentClass... let's call MakeSQLObjectQuerySingleTable()");
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues);
if (is_null($oSelectBase))
{
$oSelectBase = $oSelectParentTable;
}
else
{
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass));
}
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass));
}
}
@@ -2369,8 +2292,8 @@ class DBObjectSearch extends DBSearch
}
/**
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
* Simplifies the final expression by grouping classes having the same expression
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
* Simplifies the final expression by grouping classes having the same expression
* @param $sClass
* @param $sAttCode
* @return \FunctionExpression|mixed|null

File diff suppressed because it is too large Load Diff

View File

@@ -22,35 +22,24 @@ require_once('dbunionsearch.class.php');
/**
* An object search
*
* DBSearch provides an API that leverage the possibility to construct a search against iTop's persisted objects.
* In order to do so, it let you declare the classes you want to fetch, the conditions you want to apply, ...
*
*
* Note: in the ancient times of iTop, a search was named after DBObjectSearch.
* When the UNION has been introduced, it has been decided to:
* * declare a hierarchy of search classes : `DBObjectSearch` & `DBUnionSearch`
* * DBObjectSearch cope with single query (A JOIN B... WHERE...)
* * DBUnionSearch cope with several queries (query1 UNION query2)
* * in order to preserve forward/backward compatibility of the existing modules
* * keep the name of DBObjectSearch even if it a little bit confusing
* * do not provide a type-hint for function parameters defined in the modules
* * leave the statements DBObjectSearch::FromOQL in the modules, though DBSearch is more relevant
* When the UNION has been introduced, it has been decided to:
* - declare a hierarchy of search classes, with two leafs :
* - one class to cope with a single query (A JOIN B... WHERE...)
* - and the other to cope with several queries (query1 UNION query2)
* - in order to preserve forward/backward compatibility of the existing modules
* - keep the name of DBObjectSearch even if it a little bit confusing
* - do not provide a type-hint for function parameters defined in the modules
* - leave the statements DBObjectSearch::FromOQL in the modules, though DBSearch is more relevant
*
* @copyright Copyright (C) 2015-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*
*
* @package iTopORM
* @api
* @see DBObjectSearch::__construct()
* @see DBUnionSearch::__construct()
*/
abstract class DBSearch
{
/** @internal */
const JOIN_POINTING_TO = 0;
/** @internal */
const JOIN_REFERENCED_BY = 1;
protected $m_bNoContextParameters = false;
@@ -58,23 +47,14 @@ abstract class DBSearch
protected $m_bArchiveMode = false;
protected $m_bShowObsoleteData = true;
/**
* DBSearch constructor.
*
* @api
* @see DBSearch::FromOQL()
*/
public function __construct()
{
$this->Init();
}
/**
* called by the constructor
* @internal Set the obsolete and archive modes to the default ones
*/
protected function Init()
{
// Set the obsolete and archive modes to the default ones
$this->m_bArchiveMode = utils::IsArchiveMode();
$this->m_bShowObsoleteData = true;
}
@@ -82,8 +62,6 @@ abstract class DBSearch
/**
* Perform a deep clone (as opposed to "clone" which does copy a reference to the underlying objects)
*
* @internal
*
* @return \DBSearch
**/
public function DeepClone()
@@ -91,62 +69,22 @@ abstract class DBSearch
return unserialize(serialize($this)); // Beware this serializes/unserializes the search and its parameters as well
}
/**
* whether or not some information should be hidden to the current user.
*
* @api
* @see IsAllDataAllowed()
*
* @return mixed
*/
abstract public function AllowAllData();
/**
* Current state of AllowAllData
*
* @internal
* @see AllowAllData()
*
* @return mixed
*/
abstract public function IsAllDataAllowed();
/**
* Should the archives be fetched
*
* @internal
*
* @param $bEnable
*/
public function SetArchiveMode($bEnable)
{
$this->m_bArchiveMode = $bEnable;
}
/**
* @internal
* @return bool
*/
public function GetArchiveMode()
{
return $this->m_bArchiveMode;
}
/**
* Should the obsolete data be fetched
*
* @internal
* @param $bShow
*/
public function SetShowObsoleteData($bShow)
{
$this->m_bShowObsoleteData = $bShow;
}
/**
* @internal
* @return bool
*/
public function GetShowObsoleteData()
{
if ($this->m_bArchiveMode || $this->IsAllDataAllowed())
@@ -161,36 +99,14 @@ abstract class DBSearch
return $bRet;
}
/**
* @internal
*/
public function NoContextParameters() {$this->m_bNoContextParameters = true;}
/**
* @internal
* @return bool
*/
public function HasContextParameters() {return $this->m_bNoContextParameters;}
/**
* @internal
*
* @param $sPluginClass
* @param $sProperty
* @param $value
*/
public function SetModifierProperty($sPluginClass, $sProperty, $value)
{
$this->m_aModifierProperties[$sPluginClass][$sProperty] = $value;
}
/**
* @internal
*
* @param $sPluginClass
*
* @return array|mixed
*/
public function GetModifierProperties($sPluginClass)
{
if (array_key_exists($sPluginClass, $this->m_aModifierProperties))
@@ -203,44 +119,18 @@ abstract class DBSearch
}
}
/**
* @internal
* @param $sAlias
*
* @return mixed
*/
abstract public function GetClassName($sAlias);
/**
* @internal
* @return mixed
*/
abstract public function GetClass();
/**
* @internal
* @return mixed
*/
abstract public function GetClassAlias();
/**
* Change the class
*
* Defaults to the first selected class (most of the time it is also the first joined class
* only subclasses are supported as of now, because the conditions must fit the new class
*
* @internal
*/
* Change the class (only subclasses are supported as of now, because the conditions must fit the new class)
* Defaults to the first selected class (most of the time it is also the first joined class
*/
abstract public function ChangeClass($sNewClass, $sAlias = null);
/**
* @internal
* @return mixed
*/
abstract public function GetSelectedClasses();
/**
* @internal
* @param array $aSelectedClasses array of aliases
* @throws CoreException
*/
@@ -249,207 +139,64 @@ abstract class DBSearch
/**
* Change any alias of the query tree
*
* @internal
*
* @param $sOldName
* @param $sNewName
* @return bool True if the alias has been found and changed
*/
abstract public function RenameAlias($sOldName, $sNewName);
/**
* @internal
* @return mixed
*/
abstract public function IsAny();
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function Describe(){return 'deprecated - use ToOQL() instead';}
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function DescribeConditionPointTo($sExtKeyAttCode, $aPointingTo){return 'deprecated - use ToOQL() instead';}
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function DescribeConditionRefBy($sForeignClass, $sForeignExtKeyAttCode){return 'deprecated - use ToOQL() instead';}
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function DescribeConditionRelTo($aRelInfo){return 'deprecated - use ToOQL() instead';}
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function DescribeConditions(){return 'deprecated - use ToOQL() instead';}
/**
* @deprecated use ToOQL() instead
* @internal
* @return string
*/
public function __DescribeHTML(){return 'deprecated - use ToOQL() instead';}
/**
* @internal
* @return mixed
*/
abstract public function ResetCondition();
/**
* add $oExpression as a OR
*
* @api
* @see DBSearch::AddConditionExpression()
*
* @param Expression $oExpression
*
* @return mixed
*/
abstract public function MergeConditionExpression($oExpression);
/**
* add $oExpression as a AND
*
* @api
* @see DBSearch::MergeConditionExpression()
*
* @param Expression $oExpression
*
* @return mixed
*/
abstract public function AddConditionExpression($oExpression);
/**
* Condition on the friendlyname
*
* Restrict the query to only the corresponding selected class' friendlyname
*
* @internal
*
* @param string $sName the desired friendlyname
*
* @return mixed
*/
abstract public function AddNameCondition($sName);
/**
* Add a condition
*
* This is the simplest way to express a AND condition. For complex use cases, use MergeConditionExpression or AddConditionExpression instead
*
* @api
*
* @param string $sFilterCode
* @param mixed $value
* @param string $sOpCode operator to use : '=' (default), '!=', 'IN', 'NOT IN'
*
* @throws \CoreException
*
*/
abstract public function AddCondition($sFilterCode, $value, $sOpCode = null);
/**
* Specify a condition on external keys or link sets
*
* @internal
*
* @param string $sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
* @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
* Example: infra_list->ci_id->location_id->country
* @param mixed $value The value to match (can be an array => IN(val1, val2...)
* @param value The value to match (can be an array => IN(val1, val2...)
* @return void
*/
abstract public function AddConditionAdvanced($sAttSpec, $value);
/**
* @internal
*
* @param string $sFullText
*
* @return mixed
*/
abstract public function AddCondition_FullText($sFullText);
/**
* Perform a join, the remote class being matched by the mean of its primary key
*
* The join is performed
* * from the searched class, based on the $sExtKeyAttCode attribute
* * against the oFilter searched class, based on its primary key
* Note : if several classes have already being joined (SELECT a join b ON...), the first joined class (a in the example) is considered as being the searched class.
*
* @api
* @see AddCondition_ReferencedBy()
*
* @param DBObjectSearch $oFilter
* @param string $sExtKeyAttCode
* @param int $iOperatorCode the comparison operator to use. For the list of all possible values, see the constant defined in core/oql/oqlquery.class.inc.php
* @param array|null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed in the newly attached oFilter (in case of collisions between the two filters)
*
* @param $sExtKeyAttCode
* @param int $iOperatorCode
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
* @throws CoreException
* @throws CoreWarning
*/
abstract public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null);
/**
* Inverse operation of AddCondition_PointingTo
*
* The join is performed
* * from the olFilter searched class, based on the $sExtKeyAttCode attribute
* * against the searched class, based on its primary key
* Note : if several classes have already being joined (SELECT a join b ON...), the first joined class (a in the example) is considered as being the searched class.
*
*
* @api
* @see AddCondition_PointingTo()
*
* @param DBObjectSearch $oFilter
* @param $sForeignExtKeyAttCode
* @param int $iOperatorCode
* @param array|null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed in the newly attached oFilter (in case of collisions between the two filters)
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
*/
abstract public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null);
/**
* Filter the result
*
* The filter is performed by returning only the values in common with the given $oFilter
* The impact on the resulting query performance/viability can be significant.
*
* @internal
*
* @param DBSearch $oFilter
*
* @return mixed
*/
abstract public function Intersect(DBSearch $oFilter);
/**
* Perform a join
*
* The join is performed against $oFilter selected class using $sExtKeyAttCode of the current selected class
*
* @internal
*
* @param DBSearch $oFilter The join is performed against $oFilter selected class
* @param integer $iDirection can be either DBSearch::JOIN_POINTING_TO or DBSearch::JOIN_REFERENCED_BY
* @param string $sExtKeyAttCode The join is performed against $sExtKeyAttCode wetheir it is compared aginst the current DBSearch or $oFilter depend of $iDirection
* @param integer $iOperatorCode See DBSearch::AddCondition_PointingTo()
* @param array|null $aRealiasingMap Map of aliases from the attached query, that could have been renamed by the optimization process
*
* @return DBSearch
* @throws CoreException
* @throws CoreWarning
*/
/**
* @param DBSearch $oFilter
* @param integer $iDirection
* @param string $sExtKeyAttCode
* @param integer $iOperatorCode
* @param array &$RealisasingMap Map of aliases from the attached query, that could have been renamed by the optimization process
* @return DBSearch
*/
public function Join(DBSearch $oFilter, $iDirection, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
{
$oSourceFilter = $this->DeepClone();
@@ -484,151 +231,33 @@ abstract class DBSearch
return $oRet;
}
/**
* Set the internal params.
*
* If any params pre-existed, they are lost.
*
* @internal
*
* @param mixed[string] $aParams array of mixed params index by string name
*
* @return mixed
*/
abstract public function SetInternalParams($aParams);
/**
* @internal
* @return mixed
*/
abstract public function GetInternalParams();
/**
* @internal
*
* @param bool $bExcludeMagicParams
*
* @return mixed
*/
abstract public function GetQueryParams($bExcludeMagicParams = true);
/**
* @internal
* @return mixed
*/
abstract public function ListConstantFields();
/**
* Turn the parameters (:xxx) into scalar values
*
* The goal is to easily serialize a search
*
* @internal
*
* @param array $aArgs
*
* @return string
* Turn the parameters (:xxx) into scalar values in order to easily
* serialize a search
*/
abstract public function ApplyParameters($aArgs);
/**
* Convert a query to a string representation
*
* This operation can be revert back to a DBSearch using DBSearch::unserialize()
*
* @api
* @see DBSearch::unserialize()
*
* @param bool $bDevelopParams
* @param array $aContextParams
*
* @return false|string
* @throws ArchivedObjectException
* @throws CoreException
*/
public function serialize($bDevelopParams = false, $aContextParams = array())
public function serialize($bDevelopParams = false, $aContextParams = null)
{
$aQueryParams = $this->GetQueryParams();
$aContextParams = array_merge($this->GetInternalParams(), $aContextParams);
foreach($aQueryParams as $sParam => $sValue)
{
if (isset($aContextParams[$sParam]))
{
$aQueryParams[$sParam] = $aContextParams[$sParam];
}
elseif (($iPos = strpos($sParam, '->')) !== false)
{
$sParamName = substr($sParam, 0, $iPos);
if (isset($aContextParams[$sParamName.'->object()']))
{
$sAttCode = substr($sParam, $iPos + 2);
/** @var \DBObject $oObj */
$oObj = $aContextParams[$sParamName.'->object()'];
if ($oObj->IsModified())
{
if ($sAttCode == 'id')
{
$aQueryParams[$sParam] = $oObj->GetKey();
}
else
{
$aQueryParams[$sParam] = $oObj->Get($sAttCode);
}
}
else
{
unset($aQueryParams[$sParam]);
// For database objects, serialize only class, key
$aQueryParams[$sParamName.'->id'] = $oObj->GetKey();
$aQueryParams[$sParamName.'->class'] = get_class($oObj);
}
}
}
}
$sOql = $this->ToOql($bDevelopParams, $aContextParams);
return json_encode(array($sOql, $aQueryParams, $this->m_aModifierProperties));
return rawurlencode(base64_encode(serialize(array($sOql, $this->GetInternalParams(), $this->m_aModifierProperties))));
}
/**
* Convert a serialized query back to an instance of DBSearch
*
* @api
*
* @param string $sValue Serialized OQL query
*
* @return \DBSearch
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*/
static public function unserialize($sValue)
{
$aData = json_decode($sValue, true);
if (is_null($aData))
{
throw new CoreException("Invalid filter parameter");
}
$aData = unserialize(base64_decode(rawurldecode($sValue)));
$sOql = $aData[0];
$aParams = $aData[1];
$aExtraParams = array();
foreach($aParams as $sParam => $sValue)
{
if (($iPos = strpos($sParam, '->class')) !== false)
{
$sParamName = substr($sParam, 0, $iPos);
if (isset($aParams[$sParamName.'->id']))
{
$sClass = $aParams[$sParamName.'->class'];
$iKey = $aParams[$sParamName.'->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aExtraParams[$sParamName.'->object()'] = $oObj;
}
}
}
$aParams = array_merge($aExtraParams, $aParams);
// We've tried to use gzcompress/gzuncompress, but for some specific queries
// it was not working at all (See Trac #193)
// gzuncompress was issuing a warning "data error" and the return object was null
@@ -640,13 +269,11 @@ abstract class DBSearch
/**
* Create a new DBObjectSearch from $oSearch with a new alias $sAlias
*
* @internal Note : This has not be tested with UNION queries.
* Note : This has not be tested with UNION queries.
*
* @param DBSearch $oSearch
* @param string $sAlias
*
* @param string $sAlias
* @return DBObjectSearch
* @throws CoreException
*/
static public function CloneWithAlias(DBSearch $oSearch, $sAlias)
{
@@ -655,37 +282,12 @@ abstract class DBSearch
return $oSearchWithAlias;
}
/**
* Convert the DBSearch to an OQL representation
*
* @api
* @see DBSearch::FromOQL()
*
* @param bool $bDevelopParams
* @param null $aContextParams
* @param bool $bWithAllowAllFlag
*
* @return mixed
*/
abstract public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false);
static protected $m_aOQLQueries = array();
/**
* FromOQL with AllowAllData enabled
*
* The goal is to not filter out depending on user rights.
* In particular when we are currently in the process of evaluating the user rights...
*
* @internal
* @see DBSearch::FromOQL()
*
* @param string $sQuery
* @param null $aParams
*
* @return DBSearch
* @throws OQLException
*/
// Do not filter out depending on user rights
// In particular when we are currently in the process of evaluating the user rights...
static public function FromOQL_AllData($sQuery, $aParams = null)
{
$oRes = self::FromOQL($sQuery, $aParams);
@@ -694,19 +296,9 @@ abstract class DBSearch
}
/**
* Create a new DBSearch from the given OQL.
*
* This is the simplest way to create a DBSearch.
* For almost every cases, this is the easiest way.
*
* @api
* @see DBSearch::ToOQL()
*
* @param string $sQuery The OQL to convert to a DBSearch
* @param mixed[string] $aParams array of <mixed> params index by <string> name
*
* @return DBObjectSearch|DBUnionSearch
*
* @param string $sQuery
* @param array $aParams
* @return self
* @throws OQLException
*/
static public function FromOQL($sQuery, $aParams = null)
@@ -743,7 +335,6 @@ abstract class DBSearch
}
}
/** @var DBObjectSearch | null $oResultFilter */
if (!isset($oResultFilter))
{
$oKPI = new ExecutionKPI();
@@ -782,26 +373,11 @@ abstract class DBSearch
return $oResultFilter;
}
// Alternative to object mapping: the data are transfered directly into an array
// This is 10 times faster than creating a set of objects, and makes sense when optimization is required
/**
* Fetch the result has an array structure.
*
* Alternative to object mapping: the data are transfered directly into an array
* This is 10 times faster than creating a set of objects, and makes sense when optimization is required
* But this speed comes at the cost of not obtaining the easy to manipulates DBObject instances but simple array structure.
*
* @internal
*
* @param array $aColumns The columns you'd like to fetch.
* @param array $aOrderBy Array of '[<classalias>.]attcode' => bAscending
* @param array $aArgs
*
* @return array|void
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
*/
public function ToDataArray($aColumns = array(), $aOrderBy = array(), $aArgs = array())
{
$sSQL = $this->MakeSelectQuery($aOrderBy, $aArgs);
@@ -853,11 +429,7 @@ abstract class DBSearch
protected static $m_aQueryStructCache = array();
/**
* Generate a Group By SQL query from the current search
*
* @internal
*
/** Generate a Group By SQL request from a search
* @param array $aArgs
* @param array $aGroupByExpr array('alias' => Expression)
* @param bool $bExcludeNullValues
@@ -865,9 +437,7 @@ abstract class DBSearch
* @param array $aOrderBy array('alias' => bool) true = ASC false = DESC
* @param int $iLimitCount
* @param int $iLimitStart
*
* @return string SQL query generated
*
* @throws Exception
*/
public function MakeGroupByQuery($aArgs, $aGroupByExpr, $bExcludeNullValues = false, $aSelectExpr = array(), $aOrderBy = array(), $iLimitCount = 0, $iLimitStart = 0)
@@ -943,10 +513,6 @@ abstract class DBSearch
/**
* Generate a SQL query from the current search
*
* @internal
*
* @param array|hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
* @param array $aArgs
* @param null $aAttToLoad
@@ -1041,33 +607,9 @@ abstract class DBSearch
return $sRes;
}
/**
* @internal
* @return mixed
*/
protected abstract function IsDataFiltered();
/**
* @internal
* @return mixed
*/
protected abstract function SetDataFiltered();
/**
* @internal
*
* @param $aOrderBy
* @param $aArgs
* @param $aAttToLoad
* @param $aExtendedDataSpec
* @param $iLimitCount
* @param $iLimitStart
* @param $bGetCount
* @param null $aGroupByExpr
* @param null $aSelectExpr
*
* @return mixed
*/
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
{
$oSearch = $this;
@@ -1108,46 +650,18 @@ abstract class DBSearch
return $oSQLQuery;
}
/**
* @internal
*
* @param $aAttToLoad
* @param $bGetCount
* @param null $aGroupByExpr
* @param null $aSelectedClasses
* @param null $aSelectExpr
*
* @return mixed
*/
public abstract function GetSQLQueryStructure(
$aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null
);
/**
* Get the current search conditions
*
* @internal
* @see DBSearch $m_oSearchCondition
*
* @return \Expression
*/
public abstract function GetCriteria();
/**
* Shortcut to add efficient IN condition
*
* @internal
*
* @param $sFilterCode
* @param $aValues
* @param bool $bPositiveMatch if true a `IN` is performed, if false, a `NOT IN` is performed
*
* @return mixed
*/
public abstract function AddConditionForInOperatorUsingParam($sFilterCode, $aValues, $bPositiveMatch = true);
/**
* @internal
* @return string a unique param name
*/
protected function GenerateUniqueParamName() {
@@ -1168,78 +682,36 @@ abstract class DBSearch
protected static $m_bIndentQueries = false;
protected static $m_bOptimizeQueries = false;
/**
* @internal
*/
public static function StartDebugQuery()
{
$aBacktrace = debug_backtrace();
self::$m_bDebugQuery = true;
}
/**
* @internal
*/
public static function StopDebugQuery()
{
self::$m_bDebugQuery = false;
}
/**
* @internal
*
* @param bool $bEnabled
* @param bool $bUseAPC
* @param int $iTimeToLive
*/
public static function EnableQueryCache($bEnabled, $bUseAPC, $iTimeToLive = 3600)
{
self::$m_bQueryCacheEnabled = $bEnabled;
self::$m_bUseAPCCache = $bUseAPC;
self::$m_iQueryCacheTTL = $iTimeToLive;
}
/**
* @internal
* @param $bEnabled
*/
public static function EnableQueryTrace($bEnabled)
{
self::$m_bTraceQueries = $bEnabled;
}
/**
* @internal
* @param $bEnabled
*/
public static function EnableQueryIndentation($bEnabled)
{
self::$m_bIndentQueries = $bEnabled;
}
/**
* @internal
* @param $bEnabled
*/
public static function EnableOptimizeQuery($bEnabled)
{
self::$m_bOptimizeQueries = $bEnabled;
}
/**
* @internal
*
* @param $aOrderBy
* @param $aArgs
* @param $aAttToLoad
* @param $aExtendedDataSpec
* @param $iLimitCount
* @param $iLimitStart
* @param $bGetCount
* @param $sSql
*
* @throws MySQLException
*/
protected function AddQueryTraceSelect($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sSql)
{
if (self::$m_bTraceQueries)
@@ -1259,16 +731,7 @@ abstract class DBSearch
self::AddQueryTrace($aQueryData, $sOql, $sSql);
}
}
/**
* @internal
*
* @param $aArgs
* @param $aGroupByExpr
* @param $sSql
*
* @throws MySQLException
*/
protected function AddQueryTraceGroupBy($aArgs, $aGroupByExpr, $sSql)
{
if (self::$m_bTraceQueries)
@@ -1284,15 +747,6 @@ abstract class DBSearch
}
}
/**
* @internal
*
* @param $aQueryData
* @param $sOql
* @param $sSql
*
* @throws MySQLException
*/
protected static function AddQueryTrace($aQueryData, $sOql, $sSql)
{
if (self::$m_bTraceQueries)
@@ -1323,9 +777,6 @@ abstract class DBSearch
}
}
/**
* @internal
*/
public static function RecordQueryTrace()
{
if (!self::$m_bTraceQueries)
@@ -1386,10 +837,6 @@ abstract class DBSearch
file_put_contents($sAllQueries, $sLog);
}
/**
* @internal
* @param $value
*/
protected static function DbgTrace($value)
{
if (!self::$m_bDebugQuery)
@@ -1425,9 +872,7 @@ abstract class DBSearch
/**
* Experimental!
* @todo implement the change tracking
*
* @internal
* todo: implement the change tracking
*
* @param $bArchive
* @throws Exception
@@ -1503,9 +948,6 @@ abstract class DBSearch
}
}
/**
* @internal
*/
public function UpdateContextFromUser()
{
$this->SetShowObsoleteData(utils::ShowObsoleteData());

View File

@@ -18,21 +18,10 @@
/**
* A union of DBObjectSearches
*
* This search class represent an union over a collection of DBObjectSearch.
* For clarity purpose, since only the constructor vary between DBObjectSearch and DBUnionSearch, all the API is documented on the common ancestor: DBSearch
* Please refer to DBSearch's documentation
* A union of DBObjectSearches
*
* @copyright Copyright (C) 2015-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*
*
* @package iTopORM
* @phpdoc-tuning-exclude-inherited this tag prevent PHPdoc from displaying inherited methods. This is done in order to force the API doc. location into DBSearch only.
* @api
* @see DBSearch
* @see DBObjectSearch
*/
class DBUnionSearch extends DBSearch
@@ -40,15 +29,6 @@ class DBUnionSearch extends DBSearch
protected $aSearches; // source queries
protected $aSelectedClasses; // alias => classes (lowest common ancestors) computed at construction
/**
* DBUnionSearch constructor.
*
* @api
*
* @param $aSearches
*
* @throws CoreException
*/
public function __construct($aSearches)
{
if (count ($aSearches) == 0)

View File

@@ -116,22 +116,6 @@ class Dict
self::$m_iErrorMode = $iErrorMode;
}
/**
* Check if a dictionary entry exists or not
* @param $sStringCode
*
* @return bool
*/
public static function Exists($sStringCode)
{
$sImpossibleString = 'aVlHYKEI3TZuDV5o0pghv7fvhYNYuzYkTk7WL0Zoqw8rggE7aq';
if (static::S($sStringCode, $sImpossibleString) === $sImpossibleString)
{
return false;
}
return true;
}
/**
* Returns a localised string from the dictonary
*
@@ -213,7 +197,7 @@ class Dict
/**
* Initialize a the entries for a given language (replaces the former Add() method)
* @param string $sLanguageCode Code identifying the language i.e. 'FR-FR', 'EN-US'
* @param array $aEntries Hash array of dictionnary entries
* @param hash $aEntries Hash array of dictionnary entries
*/
public static function SetEntries($sLanguageCode, $aEntries)
{

View File

@@ -188,16 +188,11 @@ EOF
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormTagSet)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);

View File

@@ -154,7 +154,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
/**
* @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
* @see https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Arich_text_limitations
*/
protected static $aTagsWhiteList = array(
'html' => array(),
@@ -211,7 +211,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
/**
* @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
* @see https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Arich_text_limitations
*/
protected static $aStylesWhiteList = array(
'background-color',
@@ -230,9 +230,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
'margin',
'padding',
'text-align',
'vertical-align',
'width',
'white-space',
);
public function __construct()
@@ -243,16 +241,10 @@ class HTMLDOMSanitizer extends HTMLSanitizer
{
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
// Mailto urls
$sMailtoPattern = '(mailto:(' . utils::GetConfig()->Get('email_validation_pattern') . ')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
// Notification placeholders
// eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
// Note: Authorize both $xxx$ and %24xxx%24 as the latter one is encoded when used in HTML attributes (eg. a[href])
$sPlaceholderPattern = '(\$|%24)[\w-]*(->[\w]*(\([\w-]*?\))?)?(\$|%24)';
$sPattern = $sUrlPattern . '|' . $sMailtoPattern . '|' . $sPlaceholderPattern;
$sPattern = $sUrlPattern . '|' . $sMailtoPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
@@ -267,7 +259,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
// We have to transform that into <p><br></p> (which is how Thunderbird implements empty lines)
// Unfortunately, DOMDocument::loadHTML does not take the tag namespaces into account (once loaded there is no way to know if the tag did have a namespace)
// therefore we have to do the transformation upfront
$sHTML = preg_replace('@<o:p>(\s|&nbsp;)*</o:p>@', '<br>', $sHTML);
$sHTML = preg_replace('@<o:p>\s*</o:p>@', '<br>', $sHTML);
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified

View File

@@ -166,7 +166,7 @@ class InlineImage extends DBObject
*/
public static function FinalizeInlineImages(DBObject $oObject)
{
$iTransactionId = utils::ReadParam('transaction_id', null, false, 'transaction_id');
$iTransactionId = utils::ReadParam('transaction_id', null);
if (!is_null($iTransactionId))
{
// Attach new (temporary) inline images
@@ -183,19 +183,6 @@ class InlineImage extends DBObject
$oInlineImage->DBUpdate();
}
}
// For tracing issues with Inline Images... but beware not all updates are interactive, so this trace happens when creating objects non-interactively (REST, Synchro...)
// else
// {
// IssueLog::Error('InlineImage: Error during FinalizeInlineImages(), no transaction ID for object '.get_class($oObject).'#'.$oObject->GetKey().'.');
//
// IssueLog::Error('|- Call stack:');
// $oException = new Exception();
// $sStackTrace = $oException->getTraceAsString();
// IssueLog::Error($sStackTrace);
//
// IssueLog::Error('|- POST vars:');
// IssueLog::Error(print_r($_POST, true));
// }
}
/**
@@ -312,12 +299,8 @@ EOF
/**
* Check if an the given mimeType is an image that can be processed by the system
*
* @param string $sMimeType
*
* @return boolean always false if php-gd not installed
* otherwise true if file is one of those type : image/gif, image/jpeg, image/png
* @uses php-gd extension
* @return boolean
*/
public static function IsImage($sMimeType)
{
@@ -463,11 +446,9 @@ EOF
* Get the fragment of javascript needed to complete the initialization of
* CKEditor when creating/modifying an object
*
* @param \DBObject $oObject The object being edited
* @param string $sTempId Generated through utils::GetUploadTempId($iTransactionId)
*
* @param DBObject $oObject The object being edited
* @param string $sTempId The concatenation of session_id().'_'.$iTransactionId.
* @return string The JS fragment to insert in "on document ready"
* @throws \Exception
*/
public static function EnableCKEditorImageUpload(DBObject $oObject, $sTempId)
{
@@ -560,67 +541,49 @@ class InlineImageGC implements iBackgroundProcess
{
public function GetPeriodicity()
{
return 1; // Runs every 8 hours
return 3600; // Runs every hour
}
/**
* @param int $iTimeLimit
*
* @return string
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \OQLException
*/
public function Process($iTimeLimit)
{
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time()); // Every temporary InlineImage/Attachment expired will be deleted
$aResults = array();
$aClasses = array('InlineImage', 'Attachment');
foreach($aClasses as $sClass)
{
$iProcessed = 0;
if(class_exists($sClass))
{
$iProcessed = $this->DeleteExpiredDocuments($sClass, $iTimeLimit, $sDateLimit);
}
$aResults[] = "$iProcessed old temporary $sClass(s)";
}
return "Cleaned ".implode(' and ', $aResults).".";
}
/**
* @param string $sClass
* @param int $iTimeLimit
* @param string $sDateLimit
*
* @return int
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \OQLException
*/
protected function DeleteExpiredDocuments($sClass, $iTimeLimit, $sDateLimit)
{
$iProcessed = 0;
$sOQL = "SELECT $sClass WHERE (item_id = 0) AND (expire < '$sDateLimit')";
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null,
1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
while ((time() < $iTimeLimit) && ($oResult = $oSet->Fetch()))
$sOQL = "SELECT InlineImage WHERE (item_id = 0) AND (expire < '$sDateLimit')";
while (time() < $iTimeLimit)
{
/** @var \ormDocument $oDocument */
$oDocument = $oResult->Get('contents');
IssueLog::Info($sClass.' GC: Removed temp. file '.$oDocument->GetFileName().' on "'.$oResult->Get('item_class').'" #'.$oResult->Get('item_id').' as it has expired.');
$oResult->DBDelete();
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
// Nothing to be done
break;
}
$iProcessed++;
$oResult->DBDelete();
}
return $iProcessed;
}
$iProcessed2 = 0;
if (class_exists('Attachment'))
{
$sOQL = "SELECT Attachment WHERE (item_id = 0) AND (expire < '$sDateLimit')";
while (time() < $iTimeLimit)
{
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
// Nothing to be done
break;
}
$iProcessed2++;
$oResult->DBDelete();
}
}
return "Cleaned $iProcessed old temporary InlineImage(s) and $iProcessed2 old temporary Attachment(s).";
}
}

View File

@@ -116,14 +116,13 @@ class ExecutionKPI
foreach (self::$m_aExecData as $aOpStats)
{
$sOperation = $aOpStats['op'];
$sBegin = $sEnd = $sDuration = $sMemBegin = $sMemEnd = $sMemPeak = '?';
$sBegin = round($aOpStats['time_begin'], 3);
$sEnd = round($aOpStats['time_end'], 3);
$fDuration = $aOpStats['time_end'] - $aOpStats['time_begin'];
$sDuration = round($fDuration, 3);
$sMemBegin = 'n/a';
$sMemEnd = 'n/a';
$sMemPeak = 'n/a';
if (isset($aOpStats['mem_begin']))
{
$sMemBegin = self::MemStr($aOpStats['mem_begin']);
@@ -198,13 +197,12 @@ class ExecutionKPI
self::Report("</div>");
self::Report("<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>");
// Report operation details
foreach (self::$m_aStats as $sOperation => $aOpStats)
{
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
self::Report("<h4>$sOperationHtml</h4>");
self::Report("<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>");
self::Report("<table border=\"1\" style=\"$sTableStyle\">");
self::Report("<thead>");
self::Report(" <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>");
@@ -253,9 +251,7 @@ class ExecutionKPI
self::Report("</tr>");
}
self::Report("</table>");
self::Report("<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>");
}
self::Report('<a name="end-'.md5($sExecId).'">&nbsp;</a>');
}

View File

@@ -97,9 +97,8 @@ define('MYSQL_ENGINE', 'innodb');
/**
* The objects definitions as well as their mapping to the database
* (API) The objects definitions as well as their mapping to the database
*
* @api
* @package iTopORM
*/
abstract class MetaModel
@@ -145,7 +144,7 @@ abstract class MetaModel
// $aBacktrace[1] is the info we want
if (!empty($sExpectedFunctionName))
{
assert($aBacktrace[2]['function'] == $sExpectedFunctionName);
assert('$aBacktrace[2]["function"] == $sExpectedFunctionName');
}
if ($bRecordSourceFile)
{
@@ -321,7 +320,8 @@ abstract class MetaModel
final static public function GetName($sClass)
{
self::_check_subclass($sClass);
return $sClass::GetClassName($sClass);
$sStringCode = 'Class:'.$sClass;
return Dict::S($sStringCode, str_replace('_', ' ', $sClass));
}
/**
@@ -411,7 +411,8 @@ abstract class MetaModel
final static public function GetClassDescription($sClass)
{
self::_check_subclass($sClass);
return $sClass::GetClassDescription($sClass);
$sStringCode = 'Class:'.$sClass.'+';
return Dict::S($sStringCode, '');
}
/**
@@ -527,170 +528,6 @@ abstract class MetaModel
return $oRet;
}
/**
* @param string $sClass
* @param bool $bClassDefinitionOnly if true then will only return properties defined in the specified class on not the properties
* from its parent classes
*
* @return array rule id as key, rule properties as value
* @throws \CoreException
* @since 2.6 N°659 uniqueness constraint
* @see #SetUniquenessRuleRootClass that fixes a specific 'root_class' property to know which class is root per rule
*/
final public static function GetUniquenessRules($sClass, $bClassDefinitionOnly = false)
{
if (!isset(self::$m_aClassParams[$sClass]))
{
return array();
}
$aCurrentUniquenessRules = array();
if (array_key_exists('uniqueness_rules', self::$m_aClassParams[$sClass]))
{
$aCurrentUniquenessRules = self::$m_aClassParams[$sClass]['uniqueness_rules'];
}
if ($bClassDefinitionOnly)
{
return $aCurrentUniquenessRules;
}
$sParentClass = self::GetParentClass($sClass);
if ($sParentClass)
{
$aParentUniquenessRules = self::GetUniquenessRules($sParentClass);
foreach ($aParentUniquenessRules as $sUniquenessRuleId => $aParentUniquenessRuleProperties)
{
$bCopyDisabledKey = true;
$bCurrentDisabledValue = null;
if (array_key_exists($sUniquenessRuleId, $aCurrentUniquenessRules))
{
if (self::IsUniquenessRuleContainingOnlyDisabledKey($aCurrentUniquenessRules[$sUniquenessRuleId]))
{
$bCopyDisabledKey = false;
}
else
{
continue;
}
}
$aMergedUniquenessProperties = $aParentUniquenessRuleProperties;
if (!$bCopyDisabledKey)
{
$aMergedUniquenessProperties['disabled'] = $aCurrentUniquenessRules[$sUniquenessRuleId]['disabled'];
}
$aCurrentUniquenessRules[$sUniquenessRuleId] = $aMergedUniquenessProperties;
}
}
return $aCurrentUniquenessRules;
}
/**
* @param string $sRootClass
* @param string $sRuleId
*
* @throws \CoreException
* @since 2.6.1 N°1918 (sous les pavés, la plage) initialize in 'root_class' property the class that has the first
* definition of the rule in the hierarchy
*/
final private static function SetUniquenessRuleRootClass($sRootClass, $sRuleId)
{
foreach (self::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_ALL) as $sClass)
{
self::$m_aClassParams[$sClass]['uniqueness_rules'][$sRuleId]['root_class'] = $sClass;
}
}
/**
* @param string $sRuleId
* @param string $sLeafClassName
*
* @return string name of the class, null if not present
*/
final public static function GetRootClassForUniquenessRule($sRuleId, $sLeafClassName)
{
$sFirstClassWithRuleId = null;
if (isset(self::$m_aClassParams[$sLeafClassName]['uniqueness_rules'][$sRuleId]))
{
$sFirstClassWithRuleId = $sLeafClassName;
}
$sParentClass = self::GetParentClass($sLeafClassName);
if ($sParentClass)
{
$sParentClassWithRuleId = self::GetRootClassForUniquenessRule($sRuleId, $sParentClass);
if (!is_null($sParentClassWithRuleId))
{
$sFirstClassWithRuleId = $sParentClassWithRuleId;
}
}
return $sFirstClassWithRuleId;
}
/**
* @param string $sRootClass
* @param string $sRuleId
*
* @return string[] child classes with the rule disabled, and that are concrete classes
*
* @throws \CoreException
* @since 2.6.1 N°1968 (soyez réalistes, demandez l'impossible)
*/
final public static function GetChildClassesWithDisabledUniquenessRule($sRootClass, $sRuleId)
{
$aClassesWithDisabledRule = array();
foreach (self::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_EXCLUDETOP) as $sChildClass)
{
if (array_key_exists($sChildClass, $aClassesWithDisabledRule))
{
continue;
}
if (!array_key_exists('uniqueness_rules', self::$m_aClassParams[$sChildClass]))
{
continue;
}
if (!array_key_exists($sRuleId, self::$m_aClassParams[$sChildClass]['uniqueness_rules']))
{
continue;
}
if (self::$m_aClassParams[$sChildClass]['uniqueness_rules'][$sRuleId]['disabled'] === true)
{
$aDisabledClassChildren = self::EnumChildClasses($sChildClass, ENUM_CHILD_CLASSES_ALL);
foreach ($aDisabledClassChildren as $sDisabledClassChild)
{
if (!self::IsAbstract($sDisabledClassChild))
{
$aClassesWithDisabledRule[] = $sDisabledClassChild;
}
}
}
}
return $aClassesWithDisabledRule;
}
/**
* @param array $aRuleProperties
*
* @return bool
* @since 2.6 N°659 uniqueness constraint
*/
private static function IsUniquenessRuleContainingOnlyDisabledKey($aRuleProperties)
{
$aNonNullRuleProperties = array_filter($aRuleProperties, function ($v) {
return (!is_null($v));
});
return ((count($aNonNullRuleProperties) == 1) && (array_key_exists('disabled', $aNonNullRuleProperties)));
}
/**
* @param string $sClass
*
@@ -1187,7 +1024,7 @@ abstract class MetaModel
/**
* array of ("classname" => array of attributes)
*
* @var \AttributeDefinition[]
* @var array
*/
private static $m_aAttribDefs = array();
/**
@@ -1234,7 +1071,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
*
* @return array
@@ -1287,12 +1123,9 @@ abstract class MetaModel
}
/**
* Check it the given attribute exists in the specified class
*
* @api
* @param string $sClass Class name
* @param string $sAttCode Attribute code
* @param bool $bExtended Allow the extended syntax: extkey_id->remote_attcode
* @param string $sClass
* @param string $sAttCode
* @param bool $bExtended
*
* @return bool
* @throws \Exception
@@ -1346,7 +1179,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1362,9 +1194,6 @@ abstract class MetaModel
}
/**
* Check if the given class name is actually a persistent class
*
* @api
* @param string $sClass
*
* @return bool
@@ -1639,20 +1468,17 @@ abstract class MetaModel
/**
* array of ("classname" => array filterdef)
*
* @deprecated
* @var array
*/
private static $m_aFilterDefs = array();
/**
* array of ("classname" => array of ("attcode"=>"sourceclass"))
*
* @deprecated
* @var array
*/
private static $m_aFilterOrigins = array();
/**
* @deprecated
* @param string $sClass
*
* @return mixed
@@ -1665,7 +1491,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1683,7 +1508,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1702,7 +1526,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1720,7 +1543,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1738,7 +1560,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
*
@@ -1757,7 +1578,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sClass
* @param string $sFilterCode
* @param string $sOpCode
@@ -1777,7 +1597,6 @@ abstract class MetaModel
}
/**
* @deprecated
* @param string $sFilterCode
*
* @return string
@@ -1875,7 +1694,7 @@ abstract class MetaModel
private static $m_aRelationInfos = array();
/**
* @deprecated Use EnumRelationsEx instead
* TO BE DEPRECATED: use EnumRelationsEx instead
*
* @param string $sClass
*
@@ -2780,7 +2599,7 @@ abstract class MetaModel
// Build the list of available extensions
//
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();
@@ -2863,30 +2682,6 @@ abstract class MetaModel
$oClassInit->OnAfterClassInitialization($sPHPClass);
}
}
$aCurrentClassUniquenessRules = MetaModel::GetUniquenessRules($sPHPClass, true);
if (!empty($aCurrentClassUniquenessRules))
{
$aClassFields = self::GetAttributesList($sPHPClass);
foreach ($aCurrentClassUniquenessRules as $sUniquenessRuleId => $aUniquenessRuleProperties)
{
$bIsRuleOverride = self::HasSameUniquenessRuleInParent($sPHPClass, $sUniquenessRuleId);
try
{
self::CheckUniquenessRuleValidity($aUniquenessRuleProperties, $bIsRuleOverride, $aClassFields);
}
catch (CoreUnexpectedValue $e)
{
throw new Exception("Invalid uniqueness rule declaration : class={$sPHPClass}, rule=$sUniquenessRuleId, reason={$e->getMessage()}");
}
if (!$bIsRuleOverride)
{
self::SetUniquenessRuleRootClass($sPHPClass, $sUniquenessRuleId);
}
}
}
}
catch (ReflectionException $e)
{
@@ -3155,107 +2950,6 @@ abstract class MetaModel
}
}
/**
* @param string $sClassName
* @param string $sUniquenessRuleId
*
* @return bool true if one of the parent class (recursive) has the same rule defined
* @throws \CoreException
*/
private static function HasSameUniquenessRuleInParent($sClassName, $sUniquenessRuleId)
{
$sParentClass = self::GetParentClass($sClassName);
if (empty($sParentClass))
{
return false;
}
$aParentClassUniquenessRules = self::GetUniquenessRules($sParentClass);
if (array_key_exists($sUniquenessRuleId, $aParentClassUniquenessRules))
{
return true;
}
return self::HasSameUniquenessRuleInParent($sParentClass, $sUniquenessRuleId);
}
/**
* @param array $aUniquenessRuleProperties
* @param bool $bRuleOverride if false then control an original declaration validity,
* otherwise an override validity (can only have the 'disabled' key)
* @param string[] $aExistingClassFields if non empty, will check that all fields declared in the rules exists in the class
*
* @throws \CoreUnexpectedValue if the rule is invalid
*
* @since 2.6 N°659 uniqueness constraint
* @since 2.6.1 N°1968 (joli mois de mai...) disallow overrides of 'attributes' properties
*/
public static function CheckUniquenessRuleValidity($aUniquenessRuleProperties, $bRuleOverride = true, $aExistingClassFields = array())
{
$MANDATORY_ATTRIBUTES = array('attributes');
$UNIQUENESS_MANDATORY_KEYS_NB = count($MANDATORY_ATTRIBUTES);
$bHasMissingMandatoryKey = true;
$iMissingMandatoryKeysNb = $UNIQUENESS_MANDATORY_KEYS_NB;
/** @var boolean $bHasNonDisabledKeys true if rule contains at least one key that is not 'disabled' */
$bHasNonDisabledKeys = false;
$bDisabledKeyValue = null;
foreach ($aUniquenessRuleProperties as $sUniquenessRuleKey => $aUniquenessRuleProperty)
{
if ($sUniquenessRuleKey === 'disabled')
{
$bDisabledKeyValue = $aUniquenessRuleProperty;
if (!is_null($aUniquenessRuleProperty))
{
continue;
}
}
if (is_null($aUniquenessRuleProperty))
{
continue;
}
$bHasNonDisabledKeys = true;
if (in_array($sUniquenessRuleKey, $MANDATORY_ATTRIBUTES, true)) {
$iMissingMandatoryKeysNb--;
}
if ($sUniquenessRuleKey === 'attributes')
{
if (!empty($aExistingClassFields))
{
foreach ($aUniquenessRuleProperties[$sUniquenessRuleKey] as $sRuleAttribute)
{
if (!in_array($sRuleAttribute, $aExistingClassFields, true))
{
throw new CoreUnexpectedValue("Uniqueness rule : non existing field '$sRuleAttribute'");
}
}
}
}
}
if ($iMissingMandatoryKeysNb === 0)
{
$bHasMissingMandatoryKey = false;
}
if ($bRuleOverride && $bHasNonDisabledKeys)
{
throw new CoreUnexpectedValue('Uniqueness rule : only the \'disabled\' key can be overridden');
}
if ($bRuleOverride && is_null($bDisabledKeyValue))
{
throw new CoreUnexpectedValue('Uniqueness rule : when overriding a rule, value must be set for the \'disabled\' key');
}
if (!$bRuleOverride && $bHasMissingMandatoryKey)
{
throw new CoreUnexpectedValue('Uniqueness rule : missing mandatory property');
}
}
/**
* To be overriden, must be called for any object class (optimization)
*/
@@ -3906,7 +3600,7 @@ abstract class MetaModel
/**
* @param string $sClass
* @param int $iOption one of ENUM_CHILD_CLASSES_EXCLUDETOP, ENUM_CHILD_CLASSES_ALL
* @param int $iOption
*
* @return array
* @throws \CoreException
@@ -4811,7 +4505,7 @@ abstract class MetaModel
}
}
// Check SQL columns uniqueness
// Check unicity of the SQL columns
//
if (self::HasTable($sClass))
{
@@ -5277,7 +4971,6 @@ abstract class MetaModel
$aCreateTableItems = array(); // array of <table> => array of <create definition>
$aAlterTableMetaData = array();
$aAlterTableItems = array(); // array of <table> => <alter specification>
$aPostTableAlteration = array(); // array of <table> => post alteration queries
foreach(self::GetClasses() as $sClass)
{
@@ -5372,7 +5065,6 @@ abstract class MetaModel
$aTableInfo['Fields'][$sField]['used'] = true;
$bIndexNeeded = $oAttDef->RequiresIndex();
$bFullTextIndexNeeded = false;
if (!$bIndexNeeded)
{
// Add an index on the columns of the friendlyname
@@ -5381,13 +5073,6 @@ abstract class MetaModel
$bIndexNeeded = true;
}
}
else
{
if ($oAttDef->RequiresFullTextIndex())
{
$bFullTextIndexNeeded = true;
}
}
$sFieldDefinition = "`$sField` $sDBFieldSpec";
if (!CMDBSource::IsField($sTable, $sField))
@@ -5407,37 +5092,21 @@ abstract class MetaModel
if ($bIndexNeeded)
{
$aTableInfo['Indexes'][$sField]['used'] = true;
$sIndexName = $sField;
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
$sColumns = '`'.$sField.'`';
if ($bFullTextIndexNeeded)
if (!is_null($aLength[0]))
{
$sIndexType = 'FULLTEXT INDEX';
$sColumns .= ' ('.$aLength[0].')';
}
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
if ($bTableToCreate)
{
$aCreateTableItems[$sTable][] = "INDEX `$sField` ($sColumns)";
}
else
{
$sIndexType = 'INDEX';
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
if (!is_null($aLength[0]))
{
$sColumns .= ' ('.$aLength[0].')';
}
}
$sSugFix = "ALTER TABLE `$sTable` ADD $sIndexType `$sIndexName` ($sColumns)";
$aSugFix[$sClass][$sAttCode][] = $sSugFix;
if ($bFullTextIndexNeeded)
{
// MySQL does not support multi fulltext index creation in a single query (mysql_errno = 1795)
$aPostTableAlteration[$sTable][] = $sSugFix;
}
elseif ($bTableToCreate)
{
$aCreateTableItems[$sTable][] = "$sIndexType `$sIndexName` ($sColumns)";
}
else
{
$aAlterTableItems[$sTable][] = "ADD $sIndexType `$sIndexName` ($sColumns)";
$aAlterTableItems[$sTable][] = "ADD INDEX `$sField` ($sColumns)";
}
}
@@ -5450,24 +5119,12 @@ abstract class MetaModel
$sAlterTableItemsAfterChange = '';
if ($bIndexNeeded)
{
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
$aTableInfo['Indexes'][$sField]['used'] = true;
if ($bFullTextIndexNeeded)
{
$sIndexType = 'FULLTEXT INDEX';
$aColumns = null;
$aLength = null;
}
else
{
$sIndexType = 'INDEX';
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
}
if (!CMDBSource::HasIndex($sTable, $sField, $aColumns, $aLength))
{
$sIndexName = $sField;
$sColumns = '`'.$sField.'`';
if (!is_null($aLength[0]))
{
@@ -5477,11 +5134,16 @@ abstract class MetaModel
$aErrors[$sClass][$sAttCode][] = "Foreign key '$sField' in table '$sTable' should have an index";
if (CMDBSource::HasIndex($sTable, $sField))
{
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` DROP INDEX `$sIndexName`";
$aAlterTableItems[$sTable][] = "DROP INDEX `$sIndexName`";
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` DROP INDEX `$sField`";
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
$aAlterTableItems[$sTable][] = "DROP INDEX `$sField`";
$sAlterTableItemsAfterChange = "ADD INDEX `$sField` ($sColumns)";
}
else
{
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
$sAlterTableItemsAfterChange = "ADD INDEX `$sField` ($sColumns)";
}
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD $sIndexType `$sIndexName` ($sColumns)";
$sAlterTableItemsAfterChange = "ADD $sIndexType `$sIndexName` ($sColumns)";
}
}
@@ -5505,15 +5167,7 @@ abstract class MetaModel
if (!empty($sSugFixAfterChange))
{
$aSugFix[$sClass][$sAttCode][] = $sSugFixAfterChange;
if ($bFullTextIndexNeeded)
{
// MySQL does not support multi fulltext index creation in a single query (mysql_errno = 1795)
$aPostTableAlteration[$sTable][] = $sSugFixAfterChange;
}
else
{
$aAlterTableItems[$sTable][] = $sAlterTableItemsAfterChange;
}
$aAlterTableItems[$sTable][] = $sAlterTableItemsAfterChange;
}
}
}
@@ -5637,10 +5291,6 @@ abstract class MetaModel
$sChangeList = implode(', ', $aChangeList);
$aCondensedQueries[] = "ALTER TABLE `$sTable` $sChangeList";
}
foreach($aPostTableAlteration as $sTable => $aChangeList)
{
$aCondensedQueries = array_merge($aCondensedQueries, $aChangeList);
}
return array($aErrors, $aSugFix, $aCondensedQueries);
}
@@ -6208,10 +5858,20 @@ abstract class MetaModel
CMDBSource::SelectDB(self::$m_sDBName);
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMetaModelStarted();
}
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMetaModelStarted');
call_user_func_array($aCallSpec, array());
}
}
// if (false)
// {
// echo "Debug<br/>\n";
// self::static_var_dump();
// }
ExpressionCache::Warmup();
}
@@ -6662,24 +6322,22 @@ abstract class MetaModel
}
/**
* Instantiate an object already persisted to the Database.
*
* @api
* @see MetaModel::GetObjectWithArchive to get object even if it's archived
* @see utils::PushArchiveMode() to enable search on archived objects
* Search for the specified class and id.
*
* @param string $sClass
* @param int $iKey id value of the object to retrieve
* @param bool $bMustBeFound see throws ArchivedObjectException
* @param bool $bAllowAllData if true then user rights will be bypassed - use with care!
* @param bool $bMustBeFound
* @param bool $bAllowAllData if true then no rights filtering
* @param null $aModifierProperties
*
* @return \cmdbAbstractObject null if : (the object is not found) or (archive mode disabled and object is archived and
* @return DBObject|null null if : (the object is not found) or (archive mode disabled and object is archived and
* $bMustBeFound=false)
* @throws CoreException if no result found and $bMustBeFound=true
* @throws ArchivedObjectException if archive mode disabled and result is archived and $bMustBeFound=true
* @throws \Exception
*
* @see MetaModel::GetObjectWithArchive to get object even if it's archived
* @see utils::PushArchiveMode() to enable search on archived objects
*/
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
{
@@ -6735,14 +6393,12 @@ abstract class MetaModel
}
catch(Exception $e)
{
// In the finally block we will pop the pushed archived mode
// otherwise the application stays in ArchiveMode true which has caused hazardious behavior!
// We need to pop the pushed archived mode before the exception is thrown, otherwise the application stays in ArchiveMode true which has caused hazardious behavior!
// Note: When switching to PHP 5.6, we can use a finally block instead of duplicating this line.
utils::PopArchiveMode();
throw $e;
}
finally
{
utils::PopArchiveMode();
}
utils::PopArchiveMode();
if (empty($aRow))
{
@@ -6880,11 +6536,8 @@ abstract class MetaModel
}
/**
* Instantiate a persistable object (not yet persisted)
*
* @api
* @param string $sClass A persistable class
* @param array|null $aValues array of attcode => attribute value to preset
* @param string $sClass
* @param array|null $aValues array of attcode => value
*
* @return DBObject
* @throws \CoreException
@@ -6929,8 +6582,6 @@ abstract class MetaModel
* @todo: protect it against forbidden usages (in such a case, delete objects one by one)
*
* @param \DBObjectSearch $oFilter
* @deprecated
* @experimental
*
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
@@ -6948,8 +6599,6 @@ abstract class MetaModel
* @param DBObjectSearch $oFilter
* @param array $aValues array of attcode => value
*
* @deprecated
* @experimental
* @return int Modified objects
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
@@ -7244,10 +6893,6 @@ abstract class MetaModel
{
// Expand the parameters for the object
$sName = substr($sSearch, 0, $iPos);
// Note: Capturing
// 1 - The delimiter
// 2 - The arrow
// 3 - The attribute code
$aRegExps = array(
'/(\\$)'.$sName.'-(>|&gt;)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this-&gt;xxx$ for HTML compatibility
'/(%24)'.$sName.'-(>|&gt;)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this-&gt;xxx%20)
@@ -7282,28 +6927,8 @@ abstract class MetaModel
}
else
{
$aRegExps = array(
'/(\$)'.$sSearch.'\$/', // Support for regular placeholders (eg. $APP_URL$)
'/(%24)'.$sSearch.'%24/', // Support for urlencoded in HTML attributes (eg. %24APP_URL%24)
);
foreach($aRegExps as $sRegExp)
{
if(preg_match_all($sRegExp, $sInput, $aMatches))
{
foreach($aMatches[1] as $idx => $sDelimiter)
{
try
{
$aReplacements[] = (string) $replace;
$aSearches[] = $aMatches[1][$idx] . $sSearch . $aMatches[1][$idx];
}
catch(Exception $e)
{
// No replacement will occur
}
}
}
}
$aSearches[] = '$'.$sSearch.'$';
$aReplacements[] = (string)$replace;
}
}
return str_replace($aSearches, $aReplacements, $sInput);

View File

@@ -56,11 +56,6 @@ abstract class ModelReflection
abstract public function GetFiltersList($sClass);
abstract public function IsValidFilterCode($sClass, $sFilterCode);
/**
* @param string $sOQL
*
* @return \DBObjectSearch
*/
abstract public function GetQuery($sOQL);
abstract public function DictString($sStringCode, $sDefault = null, $bUserLanguageOnly = false);
@@ -80,13 +75,6 @@ abstract class ModelReflection
return vsprintf($sLocalizedFormat, $aArguments);
}
/**
* @param $sCode
* @param string $sLabel
* @param string $defaultValue
*
* @return \RunTimeIconSelectionField
*/
abstract public function GetIconSelectionField($sCode, $sLabel = '', $defaultValue = '');
abstract public function GetRootClass($sClass);

View File

@@ -25,7 +25,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class ModuleHandlerAPI implements ModuleHandlerApiInterface
abstract class ModuleHandlerAPI
{
public static function OnMetaModelStarted()
{
@@ -34,19 +34,5 @@ abstract class ModuleHandlerAPI implements ModuleHandlerApiInterface
public static function OnMenuCreation()
{
}
public function __construct()
{
}
}
interface ModuleHandlerApiInterface
{
public static function OnMetaModelStarted();
public static function OnMenuCreation();
public function __construct(); //empty params is required in order to be instantiable by MetaModel::InitClasses()
}
?>

View File

@@ -42,7 +42,7 @@
* @copyright 2006 Gregory Beaver
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
*/
//require_once 'PEAR/Exception.php';
require_once 'PEAR/Exception.php';
/**
* @package PHP_LexerGenerator
* @author Gregory Beaver <cellog@php.net>
@@ -51,5 +51,5 @@
* @version @package_version@
* @since File available since Release 0.1.0
*/
class PHP_LexerGenerator_Exception extends Exception {}
class PHP_LexerGenerator_Exception extends PEAR_Exception {}
?>

View File

@@ -22,9 +22,6 @@ class MissingQueryArgument extends CoreException
}
/**
* @method Check($oModelReflection, array $aAliases, $sSourceQuery)
*/
abstract class Expression
{
/**
@@ -50,30 +47,13 @@ abstract class Expression
/**
* recursive rendering
*
* @deprecated use RenderExpression
*
* @param array $aArgs used as input by default, or used as output if bRetrofitParams set to True
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return $this->RenderExpression(false, $aArgs, $bRetrofitParams);
}
/**
* recursive rendering
*
* @param bool $bForSQL generates code for OQL if false, for SQL otherwise
* @param array $aArgs used as input by default, or used as output if bRetrofitParams set to True
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false);
abstract public function Render(&$aArgs = null, $bRetrofitParams = false);
/**
* @param DBObjectSearch $oSearch
@@ -86,7 +66,7 @@ abstract class Expression
*/
public function Display($oSearch, &$aArgs = null, $oAttDef = null, &$aCtx = array())
{
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
public function GetAttDef($aClasses = array())
@@ -124,7 +104,7 @@ abstract class Expression
public function serialize()
{
return base64_encode($this->RenderExpression(false));
return base64_encode($this->Render());
}
/**
@@ -192,7 +172,7 @@ abstract class Expression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
{
@@ -203,7 +183,7 @@ abstract class Expression
{
return array(
'widget' => AttributeDefinition::SEARCH_WIDGET_TYPE_RAW,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
'oql' => $this->Render($aArgs, $bRetrofitParams),
'label' => $this->Display($oSearch, $aArgs, $oAttDef),
'source' => get_class($this),
);
@@ -249,7 +229,7 @@ class SQLExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSql = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return $this->m_sSQL;
}
@@ -305,30 +285,7 @@ class BinaryExpression extends Expression
protected $m_oRightExpr;
protected $m_sOperator;
/**
* @param \Expression $oLeftExpr
* @param string $sOperator
* @param \Expression $oRightExpr
*
* @throws \CoreException
*/
public function __construct($oLeftExpr, $sOperator, $oRightExpr)
{
$this->ValidateConstructorParams($oLeftExpr, $sOperator, $oRightExpr);
$this->m_oLeftExpr = $oLeftExpr;
$this->m_oRightExpr = $oRightExpr;
$this->m_sOperator = $sOperator;
}
/**
* @param $oLeftExpr
* @param $sOperator
* @param $oRightExpr
*
* @throws \CoreException if one of the parameter is invalid
*/
protected function ValidateConstructorParams($oLeftExpr, $sOperator, $oRightExpr)
{
if (!is_object($oLeftExpr))
{
@@ -346,11 +303,13 @@ class BinaryExpression extends Expression
{
throw new CoreException('Expecting an Expression object on the right hand', array('found_class' => get_class($oRightExpr)));
}
if ((($sOperator == "IN") || ($sOperator == "NOT IN")) && !($oRightExpr instanceof ListExpression))
if ( (($sOperator == "IN") || ($sOperator == "NOT IN")) && !$oRightExpr instanceof ListExpression)
{
throw new CoreException("Expecting a List Expression object on the right hand for operator $sOperator",
array('found_class' => get_class($oRightExpr)));
throw new CoreException("Expecting a List Expression object on the right hand for operator $sOperator", array('found_class' => get_class($oRightExpr)));
}
$this->m_oLeftExpr = $oLeftExpr;
$this->m_oRightExpr = $oRightExpr;
$this->m_sOperator = $sOperator;
}
public function IsTrue()
@@ -382,11 +341,12 @@ class BinaryExpression extends Expression
return $this->m_sOperator;
}
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
// recursive rendering
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$sOperator = $this->GetOperator();
$sLeft = $this->GetLeftExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sLeft = $this->GetLeftExpr()->Render($aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->Render($aArgs, $bRetrofitParams);
return "($sLeft $sOperator $sRight)";
}
@@ -578,7 +538,6 @@ class BinaryExpression extends Expression
* @param null $oAttDef
*
* @return array
* @throws \MissingQueryArgument
*/
public function GetCriterion($oSearch, &$aArgs = null, $bRetrofitParams = false, $oAttDef = null)
{
@@ -646,7 +605,7 @@ class BinaryExpression extends Expression
$aCriteria = self::MergeCriteria($aCriteriaLeft, $aCriteriaRight, $this->GetOperator());
}
$aCriteria['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
$aCriteria['label'] = $this->Display($oSearch, $aArgs, $oAttDef);
if (isset($aCriteriaLeft['ref']) && isset($aCriteriaRight['ref']) && ($aCriteriaLeft['ref'] != $aCriteriaRight['ref']))
@@ -677,10 +636,6 @@ class BinaryExpression extends Expression
}
}
}
if (isset($aCriteriaLeft['widget']) && isset($aCriteriaRight['widget']) && ($aCriteriaLeft['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_TAG_SET) && ($aCriteriaRight['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_TAG_SET))
{
$aCriteriaOverride['operator'] = 'MATCHES';
}
}
return array_merge($aCriteriaLeft, $aCriteriaRight, $aCriteriaOverride);
@@ -688,58 +643,6 @@ class BinaryExpression extends Expression
}
/**
* @since 2.6 N°931 tag fields
*/
class MatchExpression extends BinaryExpression
{
/** @var \FieldExpression */
protected $m_oLeftExpr;
/** @var \ScalarExpression */
protected $m_oRightExpr;
/**
* MatchExpression constructor.
*
* @param \FieldExpression $oLeftExpr
* @param \ScalarExpression $oRightExpr
*
* @throws \CoreException
*/
public function __construct(FieldExpression $oLeftExpr, ScalarExpression $oRightExpr)
{
parent::__construct($oLeftExpr, 'MATCHES', $oRightExpr);
}
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
{
$sLeft = $this->GetLeftExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
if ($bForSQL)
{
$sRet = "MATCH ($sLeft) AGAINST ($sRight IN BOOLEAN MODE)";
}
else
{
$sRet = "$sLeft MATCHES $sRight";
}
return $sRet;
}
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
{
/** @var \FieldExpression $oLeft */
$oLeft = $this->GetLeftExpr()->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
/** @var \ScalarExpression $oRight */
$oRight = $this->GetRightExpr()->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
return new static($oLeft, $oRight);
}
}
class UnaryExpression extends Expression
{
protected $m_value;
@@ -761,7 +664,7 @@ class UnaryExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return CMDBSource::Quote($this->m_value);
}
@@ -869,11 +772,11 @@ class ScalarExpression extends UnaryExpression
return $aCtx['date_display']->MakeValueLabel($oSearch, $this->m_value, $this->m_value);
}
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (is_null($this->m_value))
{
@@ -893,23 +796,23 @@ class ScalarExpression extends UnaryExpression
public function GetCriterion($oSearch, &$aArgs = null, $bRetrofitParams = false, $oAttDef = null)
{
$aCriterion = array();
$aCriteria = array();
switch ((string)($this->m_value))
{
case '%Y-%m-%d':
$aCriterion['unit'] = 'DAY';
$aCriteria['unit'] = 'DAY';
break;
case '%Y-%m':
$aCriterion['unit'] = 'MONTH';
$aCriteria['unit'] = 'MONTH';
break;
case '%w':
$aCriterion['unit'] = 'WEEKDAY';
$aCriteria['unit'] = 'WEEKDAY';
break;
case '%H':
$aCriterion['unit'] = 'HOUR';
$aCriteria['unit'] = 'HOUR';
break;
default:
$aValue = array();
$aValue = array('value' => $this->GetValue());
if (!is_null($oAttDef))
{
switch (true)
@@ -919,7 +822,7 @@ class ScalarExpression extends UnaryExpression
{
$oFinalAttDef = $oAttDef->GetFinalAttDef();
if($oFinalAttDef instanceof AttributeExternalKey)
{
{
if ($this->GetValue() !== 0)
{
/** @var AttributeExternalKey $oFinalAttDef */
@@ -946,79 +849,42 @@ class ScalarExpression extends UnaryExpression
IssueLog::Error($e->getMessage());
}
break;
case ($oAttDef instanceof AttributeTagSet):
try
{
if (!empty($this->GetValue()))
{
$aValues = array();
$oValue = $this->GetValue();
if (is_string($oValue))
{
$oValue = $oAttDef->GetExistingTagsFromString($oValue, true);
}
/** @var \ormTagSet $oValue */
$aTags = $oValue->GetTags();
foreach($aTags as $oTag)
{
$aValue['label'] = $oTag->Get('label');
$aValue['value'] = $oTag->Get('code');
$aValues[] = $aValue;
}
$aCriterion['values'] = $aValues;
}
else
{
$aCriterion['has_undefined'] = true;
}
} catch (Exception $e)
{
IssueLog::Error($e->getMessage());
}
break;
case $oAttDef->IsExternalKey():
try
{
if ($this->GetValue() != 0)
if ($this->GetValue() == 0)
{
$aValue['label'] = Dict::S('UI:UndefinedObject');
}
else
{
/** @var AttributeExternalKey $oAttDef */
$sTarget = $oAttDef->GetTargetClass();
$oObj = MetaModel::GetObject($sTarget, $this->GetValue(), true, true);
$aValue['label'] = $oObj->Get("friendlyname");
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
else
{
$aValue['label'] = Dict::S('Enum:Undefined');
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
} catch (Exception $e)
}
catch (Exception $e)
{
// This object cannot be seen... ignore
IssueLog::Error($e->getMessage());
}
break;
default:
try
{
$aValue['label'] = $oAttDef->GetAsPlainText($this->GetValue());
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
} catch (Exception $e)
{
$aValue['label'] = $this->GetValue();
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
break;
}
}
$aCriteria['values'] = array($aValue);
break;
}
$aCriterion['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
return $aCriterion;
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
return $aCriteria;
}
}
@@ -1125,7 +991,7 @@ class FieldExpression extends UnaryExpression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (empty($this->m_sParent))
{
@@ -1231,7 +1097,7 @@ class FieldExpression extends UnaryExpression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
* @throws \CoreException
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
@@ -1471,18 +1337,19 @@ class VariableExpression extends UnaryExpression
return $oAttDef->GetAsPlainText($sValue);
}
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
// recursive rendering
/**
* @param bool $bForSQL
* @param array $aArgs
* @param null $aArgs
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (is_null($aArgs))
{
@@ -1600,12 +1467,12 @@ class ListExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes[] = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$aRes[] = $oExpr->Render($aArgs, $bRetrofitParams);
}
return '('.implode(', ', $aRes).')';
}
@@ -1621,11 +1488,12 @@ class ListExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aExpressions as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
{
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar($aArgs);
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar();
}
else
{
@@ -1682,6 +1550,7 @@ class ListExpression extends Expression
public function RenameParam($sOldName, $sNewName)
{
$aRes = array();
foreach ($this->m_aExpressions as $key => $oExpr)
{
$this->m_aExpressions[$key] = $oExpr->RenameParam($sOldName, $sNewName);
@@ -1690,6 +1559,7 @@ class ListExpression extends Expression
public function RenameAlias($sOldName, $sNewName)
{
$aRes = array();
foreach ($this->m_aExpressions as $key => $oExpr)
{
$oExpr->RenameAlias($sOldName, $sNewName);
@@ -1753,12 +1623,12 @@ class FunctionExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aArgs as $iPos => $oExpr)
{
$aRes[] = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$aRes[] = $oExpr->Render($aArgs, $bRetrofitParams);
}
return $this->m_sVerb.'('.implode(', ', $aRes).')';
}
@@ -1774,6 +1644,7 @@ class FunctionExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aArgs as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
@@ -1867,7 +1738,7 @@ class FunctionExpression extends Expression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
{
@@ -1943,7 +1814,6 @@ class FunctionExpression extends Expression
$sVerb = '';
switch ($this->m_sVerb)
{
case 'ISNULL':
case 'NOW':
$sVerb = $this->VerbToNaturalLanguage();
break;
@@ -1957,7 +1827,7 @@ class FunctionExpression extends Expression
$aCtx['date_display'] = $this;
break;
default:
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
foreach($this->m_aArgs as $oExpression)
@@ -1974,7 +1844,7 @@ class FunctionExpression extends Expression
{
$sOperation .= $sVerb;
}
return '('.$sOperation.')';
return $sOperation;
}
private function VerbToNaturalLanguage()
@@ -1994,7 +1864,7 @@ class FunctionExpression extends Expression
$aCriteria = array_merge($oExpression->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef), $aCriteria);
}
$aCriteria['has_undefined'] = true;
$aCriteria['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
break;
case 'NOW':
@@ -2022,9 +1892,6 @@ class FunctionExpression extends Expression
}
}
/**
* @see https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
*/
class IntervalExpression extends Expression
{
protected $m_oValue; // expression
@@ -2053,9 +1920,9 @@ class IntervalExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit;
return 'INTERVAL '.$this->m_oValue->Render($aArgs, $bRetrofitParams).' '.$this->m_sUnit;
}
public function Browse(Closure $callback)
@@ -2120,7 +1987,7 @@ class IntervalExpression extends Expression
public function Display($oSearch, &$aArgs = null, $oAttDef = null, &$aCtx = array())
{
return $this->m_oValue->RenderExpression(false, $aArgs).' '.Dict::S('Expression:Unit:Long:'.$this->m_sUnit, $this->m_sUnit);
return $this->m_oValue->Render($aArgs).' '.Dict::S('Expression:Unit:Long:'.$this->m_sUnit, $this->m_sUnit);
}
}
@@ -2145,12 +2012,12 @@ class CharConcatExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$sCol = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sCol = $oExpr->Render($aArgs, $bRetrofitParams);
// Concat will be globally NULL if one single argument is null !
$aRes[] = "COALESCE($sCol, '')";
}
@@ -2168,11 +2035,12 @@ class CharConcatExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aExpressions as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
{
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar($aArgs);
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar();
}
else
{
@@ -2256,12 +2124,12 @@ class CharConcatWSExpression extends CharConcatExpression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$sCol = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sCol = $oExpr->Render($aArgs, $bRetrofitParams);
// Concat will be globally NULL if one single argument is null !
$aRes[] = "COALESCE($sCol, '')";
}

View File

@@ -140,7 +140,6 @@ class OQLLexerRaw
'/\GNOT LIKE/ ',
'/\GIN/ ',
'/\GNOT IN/ ',
'/\GMATCHES/ ',
'/\GINTERVAL/ ',
'/\GIF/ ',
'/\GELT/ ',
@@ -442,209 +441,204 @@ class OQLLexerRaw
function yy_r1_33($yy_subpatterns)
{
$this->token = OQLParser::MATCHES;
$this->token = OQLParser::INTERVAL;
}
function yy_r1_34($yy_subpatterns)
{
$this->token = OQLParser::INTERVAL;
$this->token = OQLParser::F_IF;
}
function yy_r1_35($yy_subpatterns)
{
$this->token = OQLParser::F_IF;
$this->token = OQLParser::F_ELT;
}
function yy_r1_36($yy_subpatterns)
{
$this->token = OQLParser::F_ELT;
$this->token = OQLParser::F_COALESCE;
}
function yy_r1_37($yy_subpatterns)
{
$this->token = OQLParser::F_COALESCE;
$this->token = OQLParser::F_ISNULL;
}
function yy_r1_38($yy_subpatterns)
{
$this->token = OQLParser::F_ISNULL;
$this->token = OQLParser::F_CONCAT;
}
function yy_r1_39($yy_subpatterns)
{
$this->token = OQLParser::F_CONCAT;
$this->token = OQLParser::F_SUBSTR;
}
function yy_r1_40($yy_subpatterns)
{
$this->token = OQLParser::F_SUBSTR;
$this->token = OQLParser::F_TRIM;
}
function yy_r1_41($yy_subpatterns)
{
$this->token = OQLParser::F_TRIM;
$this->token = OQLParser::F_DATE;
}
function yy_r1_42($yy_subpatterns)
{
$this->token = OQLParser::F_DATE;
$this->token = OQLParser::F_DATE_FORMAT;
}
function yy_r1_43($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_FORMAT;
$this->token = OQLParser::F_CURRENT_DATE;
}
function yy_r1_44($yy_subpatterns)
{
$this->token = OQLParser::F_CURRENT_DATE;
$this->token = OQLParser::F_NOW;
}
function yy_r1_45($yy_subpatterns)
{
$this->token = OQLParser::F_NOW;
$this->token = OQLParser::F_TIME;
}
function yy_r1_46($yy_subpatterns)
{
$this->token = OQLParser::F_TIME;
$this->token = OQLParser::F_TO_DAYS;
}
function yy_r1_47($yy_subpatterns)
{
$this->token = OQLParser::F_TO_DAYS;
$this->token = OQLParser::F_FROM_DAYS;
}
function yy_r1_48($yy_subpatterns)
{
$this->token = OQLParser::F_FROM_DAYS;
$this->token = OQLParser::F_YEAR;
}
function yy_r1_49($yy_subpatterns)
{
$this->token = OQLParser::F_YEAR;
$this->token = OQLParser::F_MONTH;
}
function yy_r1_50($yy_subpatterns)
{
$this->token = OQLParser::F_MONTH;
$this->token = OQLParser::F_DAY;
}
function yy_r1_51($yy_subpatterns)
{
$this->token = OQLParser::F_DAY;
$this->token = OQLParser::F_HOUR;
}
function yy_r1_52($yy_subpatterns)
{
$this->token = OQLParser::F_HOUR;
$this->token = OQLParser::F_MINUTE;
}
function yy_r1_53($yy_subpatterns)
{
$this->token = OQLParser::F_MINUTE;
$this->token = OQLParser::F_SECOND;
}
function yy_r1_54($yy_subpatterns)
{
$this->token = OQLParser::F_SECOND;
$this->token = OQLParser::F_DATE_ADD;
}
function yy_r1_55($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_ADD;
$this->token = OQLParser::F_DATE_SUB;
}
function yy_r1_56($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_SUB;
$this->token = OQLParser::F_ROUND;
}
function yy_r1_57($yy_subpatterns)
{
$this->token = OQLParser::F_ROUND;
$this->token = OQLParser::F_FLOOR;
}
function yy_r1_58($yy_subpatterns)
{
$this->token = OQLParser::F_FLOOR;
$this->token = OQLParser::F_INET_ATON;
}
function yy_r1_59($yy_subpatterns)
{
$this->token = OQLParser::F_INET_ATON;
$this->token = OQLParser::F_INET_NTOA;
}
function yy_r1_60($yy_subpatterns)
{
$this->token = OQLParser::F_INET_NTOA;
$this->token = OQLParser::BELOW;
}
function yy_r1_61($yy_subpatterns)
{
$this->token = OQLParser::BELOW;
$this->token = OQLParser::BELOW_STRICT;
}
function yy_r1_62($yy_subpatterns)
{
$this->token = OQLParser::BELOW_STRICT;
$this->token = OQLParser::NOT_BELOW;
}
function yy_r1_63($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW;
$this->token = OQLParser::NOT_BELOW_STRICT;
}
function yy_r1_64($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW_STRICT;
$this->token = OQLParser::ABOVE;
}
function yy_r1_65($yy_subpatterns)
{
$this->token = OQLParser::ABOVE;
$this->token = OQLParser::ABOVE_STRICT;
}
function yy_r1_66($yy_subpatterns)
{
$this->token = OQLParser::ABOVE_STRICT;
$this->token = OQLParser::NOT_ABOVE;
}
function yy_r1_67($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE;
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
function yy_r1_68($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE_STRICT;
$this->token = OQLParser::HEXVAL;
}
function yy_r1_69($yy_subpatterns)
{
$this->token = OQLParser::HEXVAL;
$this->token = OQLParser::NUMVAL;
}
function yy_r1_70($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
$this->token = OQLParser::STRVAL;
}
function yy_r1_71($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
$this->token = OQLParser::NAME;
}
function yy_r1_72($yy_subpatterns)
{
$this->token = OQLParser::NAME;
}
function yy_r1_73($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
}
function yy_r1_74($yy_subpatterns)
function yy_r1_73($yy_subpatterns)
{
$this->token = OQLParser::DOT;
@@ -672,25 +666,25 @@ class OQLLexer extends OQLLexerRaw
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}

View File

@@ -139,7 +139,6 @@ f_round = "ROUND"
f_floor = "FLOOR"
f_inet_aton = "INET_ATON"
f_inet_ntoa = "INET_NTOA"
matches = "MATCHES"
below = "BELOW"
below_strict = "BELOW STRICT"
not_below = "NOT BELOW"
@@ -274,9 +273,6 @@ in {
not_in {
$this->token = OQLParser::NOT_IN;
}
matches {
$this->token = OQLParser::MATCHES;
}
interval {
$this->token = OQLParser::INTERVAL;
}
@@ -423,25 +419,25 @@ class OQLLexer extends OQLLexerRaw
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ Example:
%left TIMES DIVIDE MOD.
%right EXP NOT.
later : solve the 2 remaining shift-reduce conflicts (JOIN)
TODO : solve the 2 remaining shift-reduce conflicts (JOIN)
*/
@@ -108,16 +108,7 @@ expression_prio1(A) ::= expression_basic(X). { A = X; }
expression_prio1(A) ::= expression_prio1(X) operator1(Y) expression_basic(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression_prio2(A) ::= expression_prio1(X). { A = X; }
expression_prio2(A) ::= expression_prio2(X) operator2(Y) expression_prio1(Z).{
if (Y == 'MATCHES')
{
A = new MatchOqlExpression(X, Z);
}
else
{
A = new BinaryOqlExpression(X, Y, Z);
}
}
expression_prio2(A) ::= expression_prio2(X) operator2(Y) expression_prio1(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression_prio3(A) ::= expression_prio2(X). { A = X; }
expression_prio3(A) ::= expression_prio3(X) operator3(Y) expression_prio2(Z). { A = new BinaryOqlExpression(X, Y, Z); }
@@ -189,22 +180,18 @@ str_value(A) ::= STRVAL(X). {A=stripslashes(substr(X, 1, strlen(X) - 2));}
operator1(A) ::= num_operator1(X). {A=X;}
operator1(A) ::= bitwise_operator1(X). {A=X;}
operator2(A) ::= num_operator2(X). {A=X;}
operator2(A) ::= str_operator(X). {A=X;}
operator2(A) ::= REGEXP(X). {A=X;}
operator2(A) ::= EQ(X). {A=X;}
operator2(A) ::= NOT_EQ(X). {A=X;}
operator3(A) ::= LOG_AND(X). {A=X;}
operator3(A) ::= bitwise_operator3(X). {A=X;}
operator4(A) ::= LOG_OR(X). {A=X;}
operator4(A) ::= bitwise_operator4(X). {A=X;}
num_operator1(A) ::= MATH_DIV(X). {A=X;}
num_operator1(A) ::= MATH_MULT(X). {A=X;}
num_operator2(A) ::= MATH_PLUS(X). {A=X;}
num_operator2(A) ::= MATH_MINUS(X). {A=X;}
num_operator2(A) ::= GT(X). {A=X;}
@@ -214,13 +201,10 @@ num_operator2(A) ::= LE(X). {A=X;}
str_operator(A) ::= LIKE(X). {A=X;}
str_operator(A) ::= NOT_LIKE(X). {A=X;}
str_operator(A) ::= MATCHES(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_LEFT_SHIFT(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_RIGHT_SHIFT(X). {A=X;}
bitwise_operator3(A) ::= BITWISE_AND(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_OR(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_XOR(X). {A=X;}

Some files were not shown because too many files have changed in this diff Show More