Compare commits

...

71 Commits

Author SHA1 Message Date
odain
933b72195d be able to call cron locally/remotely via any authentication mode that implements iTokenLoginUIExtension (interface badly named) 2026-02-09 23:08:48 +01:00
odain
ee13dec3d1 new iTokenLoginUIExtension interface 2026-02-09 23:05:33 +01:00
odain
13baf6037a cron endpoints behind login mechanism via auth_user and auth_pwd + deal with status_only different output 2025-10-20 11:44:55 +02:00
odain
863e397fb2 be able to call cron asynchronously 2025-10-20 09:30:55 +02:00
jf-cbd
0fe2183369 Update itop-version-history.md 2025-10-07 15:19:08 +02:00
Anne-Catherine
8f038d2f95 N°2683 - EnhancedSLAComputation: use common extension mechanism (#744) 2025-10-02 15:40:16 +02:00
jf-cbd
fbf3dd8cf7 📝 Update CONTRIBUTING.md for Hacktoberfest 2025-10-01 11:34:28 +02:00
jf-cbd
01c9e73020 Improve OQLTest.php so data produced by test (added ub N°8522) is removed at the end of its execution 2025-09-30 16:46:58 +02:00
jf-cbd
0736045b90 Update .doc 2025-09-30 14:53:25 +02:00
Eduardo Mozart de Oliveira
86776edfb3 Improved PT-BR Translation (#362) 2025-09-29 11:01:25 +02:00
jf-cbd
d78805d8ae 👥 Update README.md 2025-09-22 17:10:59 +02:00
Håkon Harnes
03e1d46586 🐛 N°8522 - check if org id is null when filtering (#727) 2025-09-22 16:51:32 +02:00
Eric Espie
f3deb8be11 Merge remote-tracking branch 'origin/support/3.2' into develop 2025-09-22 16:44:22 +02:00
Eric Espie
981d5c6263 Allow KPIs for REST api 2025-09-22 16:43:24 +02:00
Stephen Abello
e000befc0f Dump autoloader 2025-09-22 16:26:12 +02:00
Stephen Abello
2eba58998b Merge branch 'support/3.2' into develop 2025-09-22 16:25:27 +02:00
Stephen Abello
4ed21dc21a N°7920 - Replace Symfony sendmail transport with PHP mail() transport 2025-09-22 16:24:58 +02:00
Anne-Cath
fa5cad0fdb N°2364 - API : remove old linkedset persistance - avoid deprecated message during setup 2025-09-22 12:02:28 +02:00
Thomas Casteleyn
5d28de1636 📝 Complete the version history (#753) 2025-09-19 17:22:18 +02:00
Timmy38
6be9255ca0 N°7071 - Remove CMDBSource::MYSQL_DEFAULT_PORT 2025-09-19 10:53:58 +02:00
Stephen Abello
1f4a2f0f56 N°8579 - Fix calls to Twig "spaceless" deprecated filter 2025-09-18 10:35:02 +02:00
Stephen Abello
edbe4974ac Re-dump autoloader and composer.lock 2025-09-18 10:26:38 +02:00
Stephen Abello
7e515e7216 Merge branch 'support/3.2' into develop 2025-09-18 10:13:09 +02:00
Stephen Abello
bf7a756714 Add symfony/mailer/Test to denied dirs 2025-09-17 16:25:22 +02:00
Stephen Abello
428d2c6356 N°7920 - laminas-mail is an abandoned package, replace it with symfony/mailer (#742)
* N°7920 - laminas-mail is an abandoned package, replace it with symfony/mailer

* Fix composer following merge
2025-09-17 16:04:20 +02:00
odain
d589d9d05a N°4789 - fix broken tests in ci 2025-09-16 16:37:31 +02:00
odain
c0c9ea9287 N°4789 - Parse datamodel module.xxx.php files instead of interpreting them (#746) - namespacing ModuleFileReader classes 2025-09-16 15:38:30 +02:00
odain
fae2bcc6e9 N°4720 - deprecation removal RenderLinks 2025-09-15 16:40:10 +02:00
Stephen Abello
53047d35fe N°8617 - New portal theme doesn't work with Safari 2025-09-15 14:30:07 +02:00
Stephen Abello
8982f7e0e3 Dump autoloader 2025-09-15 14:16:03 +02:00
Anne-Catherine
909469ce97 N°2364 - API : remove old linkedset persistance (#733) 2025-09-12 16:16:02 +02:00
Anne-Cath
dacb54285c N°4820 - Remove pre-3.0 console files - date.js, hovertip.js jquery.layout.min.js 2025-09-12 16:01:55 +02:00
Benjamin Dalsass
5af93ca92a N°8637 - Alerts from dependabot, vulnerable libraries
- remove deprecated call to getExpressionParser
2025-09-12 15:38:01 +02:00
Benjamin Dalsass
3fa500c9c1 N°8699 - attributedef.class.inc.php to PSR4 [3-PSR4]
- Add namespaces
- Add use statements
- reformat code
2025-09-12 15:23:42 +02:00
Benjamin Dalsass
f0adbbba29 N°8699 - attributedef.class.inc.php to PSR4 [2-DISPATCH]
- Restore attributedef.class.inc.php with requires
- Update each attribute file code
2025-09-12 15:23:42 +02:00
Benjamin Dalsass
bbdb30f421 N°8699 - attributedef.class.inc.php to PSR4 [1-DUPLICATE]
- Duplicates attributedef.class.inc.php as attributedefrequires.class.inc.php (will contains the require_once directives)
- Duplicates attributedef.class.inc.php for each final class files AttributeApplicationLanguage.php, AttributeArchiveDate.php... to keep VCS
 history
- Remove attributedef.class.inc.php file
2025-09-12 15:23:42 +02:00
odain
897b5d452e N°8715 - Broken UIFieldSet/UIFieldInput via twig rendering 2025-09-12 15:00:40 +02:00
odain
fdd1479c8e N°4720 - fix portal issue 2025-09-12 14:36:19 +02:00
Anne-Cath
7851109794 N°3749 - Remove old JS tooltip libs (qTip, jQuery tooltip, Bootstrap tooltip) calls - remove qtip 2025-09-12 10:02:12 +02:00
Anne-Cath
810e6c1bda N°3817 - Audit and fix calls to deprecated jQuery method 2025-09-12 09:59:02 +02:00
Anne-Cath
d164f48cfe N°3817 - Audit and fix calls to deprecated jQuery method 2025-09-12 09:56:30 +02:00
odain
506def4340 code cleanup : fix PHP Warning: Undefined variable 2025-09-12 09:41:03 +02:00
odain
08b8e919b7 N°4720 - Remove old unreferenced methods - portal broken due to remaining method in portal-base 2025-09-12 07:19:11 +02:00
odain-cbd
696e2c9565 N°4720 - Remove old unreferenced methods or pages that are @deprecated (#747)
* N°4720 - Remove old unreferenced methods that are @deprecated

* N°4720-Config addson getter/setter removal

* small deprecation removal

* revert @deprecation 3.3 removal: ResizeImageToFit

* small deprecation removal

* revert deprecation 3.3 removal: Config/GSetAddons
2025-09-11 15:52:00 +02:00
Anne-Cath
d728be119c N°4456 - Remove jquery.layout.js 2025-09-11 15:27:57 +02:00
Benjamin Dalsass
463869b89d N°8637 - Alerts from dependabot, vulnerable libraries
- restore itop version history
2025-09-11 11:03:58 +02:00
Benjamin Dalsass
1d4c0b8e7f N°8637 - Alerts from dependabot, vulnerable libraries
- Update twig/twig from 3.16.0 to 3.21.1
- Update tecnickcom/tcpdf from 6.7.5 to 6.10.0
2025-09-10 09:08:04 +02:00
Benjamin Dalsass
bf1b2a5104 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	.doc/README.md
#	.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
#	composer.lock
#	lib/composer/InstalledVersions.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_psr4.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.json
#	lib/composer/installed.php
#	lib/symfony/cache/Traits/Relay/MoveTrait.php
#	lib/symfony/http-foundation/Request.php
#	lib/symfony/runtime/SymfonyRuntime.php
2025-09-10 07:57:41 +02:00
odain-cbd
15103dc49f N°4789 - Parse datamodel module.xxx.php files instead of interpreting them (#746)
* N°4789 - Parse datamodel module.xxx.php files instead of interpreting them - refactoring all in a dedicated service first

* N°4789 - fix broken setup + tests

* N°4789 - replace legacy eval by module file parsing

* N°4789 - handle constants and if conditional structures

* N°4789 - compute boolean expressions

* N°4789 - make autoselect and dependencies work as well

* cleanup

* N°4789 - fix BeforeWritingConfig calls during setup

* N°4789 - refactor and split in ModuleDiscoveryEvaluationService + handle ModuleInstallerAPI methods calls during setup

* N°4789 - PR review changes with Romain

* PR review + code cleanup + added usecases and test cover

* temp evaluation work

* replace eval by iTop custom evaluation classes

* move PhpParser/Evaluation classes in a specific namespave + composer dumpautoload

* fix broken setup

* fix broken setup

* complete Evaluators list + autoload

* cleanup useless testing resources

* cleanup + replace last eval call in VariableEvaluator

* fix few Evaluators code

* enhance nikic evaluators + test with/without nikic lib

* Evaluator fixes/enhancements + tests

* bump to nikic fork temporarly

* bump nikic-parser fork + use only nikic fork  evaluation + cleanup itop redondant evaluators

* review with Romain: use distinct whitelists in setup time/runtime + move ModuleFileParser internal logic into ModuleFileReader

* PhpExpressionEvaluator used via constructor and not as a service

* dumpautoload again after rebase
2025-09-09 17:54:18 +02:00
Benjamin Dalsass
bb8a09d8e2 N°8637 - Alerts from dependabot, vulnerable libraries
* Update twig/twig from 3.16.0 to 3.21.1

* Update tecnickcom/tcpdf from 6.7.5 to 6.10.0

* Correct font folder case failing on linux server

* Suppress documentation generator from project in favor of the online version

* Update symfony/http-foundation from 6.4.2 to 6.4.14
Update symfony/runtime from 6.4.0 to 6.4.24
2025-09-09 16:15:21 +02:00
Stephen Abello
901f8f2a7b N°8691 - Backup modal icon spins around the text 2025-09-09 14:24:18 +02:00
Stephen Abello
ba6fff801b N°8497 - Fix typo in French dictionaries 2025-09-08 14:25:54 +02:00
Stephen Abello
50098bad73 N°5200 - Activity panel entries' relative date isn't translated 2025-09-08 14:03:43 +02:00
jf-cbd
2ee68ff819 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	sources/SessionTracker/iSessionHandlerExtension.php
2025-09-05 15:19:38 +02:00
Benjamin Dalsass
44972f34e5 N°8210 - Remove iApplicationObjectExtension (#737) 2025-09-05 09:27:55 +02:00
jf-cbd
65c9145b10 N°8570 - Allow @ as part of url - add test 2025-09-04 17:04:21 +02:00
Stephen Abello
a104310379 N°8579 - Fix calls to Twig "spaceless" deprecated filter 2025-09-04 14:57:24 +02:00
Anne-Cath
f5cce23bb4 Revert "N°8579 - remove "spaceless" in twig files"
This reverts commit ee993ef80a.
2025-09-03 10:37:26 +02:00
Stephen Abello
0f39106b56 N°7761 - De-hardcode SCSS values 2025-09-02 16:30:20 +02:00
Anne-Cath
ee993ef80a N°8579 - remove "spaceless" in twig files 2025-08-29 17:15:47 +02:00
Anne-Cath
0a4180f7fc N°7257 - Check and migrate old Combodo JS functions 2025-08-29 16:15:31 +02:00
Anne-Cath
b56113aada N°8190 - Userrights management override is deprecated - add deprecated 2025-08-29 15:12:36 +02:00
Anne-Cath
c82c150411 N°7257 - Check and migrate old Combodo JS functions 2025-08-29 14:27:38 +02:00
Anne-Cath
00818f411f N°3817 - Audit and fix calls to deprecated jQuery method - rollback change on caselog-entry-form.js 2025-08-29 11:07:44 +02:00
Timmy38
a6a459967e N°6759 factorize config (#738)
* N°6759 - Factorize code in config
2025-08-28 11:04:49 +02:00
Stephen Abello
437296eab9 N°8634 - Newsroom providers are hardly visible if there's more than 2 2025-08-20 16:00:14 +02:00
Stephen Abello
7cf6f65265 Fix typo thanks to @jbostoen 2025-08-06 09:04:36 +02:00
Björn Rudner
491f55c7bd 🐛 Allow @ as part of url (#729) 2025-08-01 15:27:37 +02:00
Stephen Abello
7b44ec23a1 Fix return type in PHPDoc thanks to @jbostoen 2025-07-28 16:14:13 +02:00
BenGrenoble
f00b8d529c N°8286 - Be able to add additional data in iTop session files via custom classes
Change to fit convention.
2025-07-24 10:59:48 +02:00
BenGrenoble
af44ffd0ad N°8286 - Be able to add additional data in iTop session files via custom classes
Experimental warning
2025-07-24 10:28:15 +02:00
1744 changed files with 50073 additions and 121096 deletions

View File

@@ -1,101 +0,0 @@
# Phpdoc dokuwiki template
This directory contains a template for rendering iTop phpdoc as dokuwiki pages.
Conventional tags that you should use:
* `@internal` : exclude from the documentation.
* `@api` : it means that a method is an api, thus it may be interacted with.
* `@see` : it points to another documented method
* `@link` : external url
* if you point to another page of the wiki, please use relative links.
* `@example` : let you provide example of code
* `@param`, `@return`, `@throws`, ...
## Special instructions
Some iTop specific tags were added :
* `@api-advanced`: it means that a method is an `@api` but mark it also as "complex" to use
* `@overwritable-hook`: used to mark a method as "designed to be extended"
* `@extension-hook`: not used for now
* `@phpdoc-tuning-exclude-inherited`: once this tag is present on a class, it's inherited methods won't be showed.
### known limitations:
#### `@see` tags must be very specific:
* always prefix class members (attributes or methods) with `ClassName::` (do not use self)
* for methods always suffix them with `()`,
* do not reference variables since they are not documented. If you have to, always prefix them with `$`
examples:
```
/**
* @see DBObject
* @see DBObject::Get()
* @see DBObject::$foo
*/
```
#### Do not use inline tags, they do not work properly, example:
```
/**
* This is a texts with an inline tag {@see [FQSEN] [<description>]} it must never be used
*/
```
#### The `@example` tag must respect this very precise syntax
* the sentence in the first line (next to the tag) is the title, it must be enclosed by double quotes
* the following lines are the sample code.
* 💔 since we simply hack the official tag, this syntax must be respected carefully 💔
example:
```
/**
* @example "This is the title of the multiline example"
* $foo = DBObject::Get('foo');
* DBObject::Set('foo', ++$foo);
*/
```
## How content is included into the documentation
**For a class** those requirements have to be respected:
- the file containing the class must be listed in `/phpdoc/files/file[]` of `.doc/phpdoc-objects-manipulation.dist.xml`
- the class **must not** have the tag `@internal`
- the class **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
Then, **for a method** of an eligible class:
- **public** methods **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
- **protected** methods **must** have at least one of: `@overwritable-hook`, `@extension-hook`
- **private** methods are **always excluded**
**Class properties** and **constants** are never documented (this is subject to change).
## A note about the rendering engine
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
## Installation
Note : PHP7 is required. Migrating to PHP8 requires some additional work which is questionable as an alternative way to generate a documentation is being considered.
```
cd .doc
composer require phpdocumentor/phpdocumentor:~2 --dev
```
## Generation
1. Switch to this directory : `cd /path/to/itop/.doc`
2. `composer install`
3. `./bin/build-doc-object-manipulation`
3. `./bin/build-doc-extensions`
4. Get the generated files from `/path/to/itop/data/phpdocumentor/output`
## Dokuwiki requirements
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
* the generated files have to be placed under an arbitrary directory of `[/path/to/dokuwiki]/data/pages`.
* the html has to be activated [config:htmlok](https://www.dokuwiki.org/config:htmlok)
* the generated files have to be in lowercase

View File

@@ -1,6 +0,0 @@
#!/bin/sh -x
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && ./vendor/bin/phpdoc -c ./phpdoc-extensions.dist.xml -vvv
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
cd ../data/phpdocumentor/output/extensions/ && for i in $(ls | grep [A-Z]); do mv -i $i $(echo $i | tr 'A-Z' 'a-z'); done

View File

@@ -1,7 +0,0 @@
#!/bin/sh -x
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf ../data/phpdocumentor/output/objects-manipulation/ && rm -rf ../data/phpdocumentor/temp/objects-manipulation/ && ./vendor/bin/phpdoc -c ./phpdoc-objects-manipulation.dist.xml -vvv
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
cd ../data/phpdocumentor/output/objects-manipulation/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done

View File

@@ -1,6 +0,0 @@
{
"require-dev": {
"phpdocumentor/phpdocumentor": "~2",
"jms/serializer": "1.7.*"
}
}

3015
.doc/composer.lock generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -86,19 +86,24 @@ gitGraph
commit id: "2024-01-17a" tag: "2.7.10"
checkout support/3.0
commit id: "2024-01-17b" tag: "3.0.4"
checkout support/2.7
commit id: "2024-09-28" tag: "2.7.11"
checkout support/3.1
commit id: "2024-09-27" tag: "3.1.2"
checkout support/3.2
commit id: "2024-06-25" tag: "3.2.0-beta1" type: REVERSE
commit id: "2024-08-07" tag: "3.2.0"
commit id: "2024-09-13" tag: "3.2.0-2"
checkout support/3.1
commit id: "2024-09-27" tag: "3.1.2"
checkout support/2.7
commit id: "2024-09-28" tag: "2.7.11"
checkout support/2.7
commit id: "2025-02-25" tag: "2.7.12"
checkout support/3.1
commit id: "2025-02-25 " tag: "3.1.3"
checkout support/3.2
commit id: "2025-02-25 " tag: "3.2.1"
commit id: "2025-04-08" tag: "3.2.1-1"
commit id: "2025-08-19" tag: "3.2.2-1"
checkout support/2.7
commit id: "2025-10-07" tag: "2.7.13"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

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').on('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 information]]
</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

@@ -7,6 +7,17 @@ Here are some guidelines that will help us integrate your work!
## Contributions
```
_ _ _ _ _ __ _
| | | | __ _ ___| | _| |_ ___ | |__ ___ _ __ / _| ___ ___| |_
| |_| |/ _` |/ __| |/ / __/ _ \| '_ \ / _ \ '__| |_ / _ \/ __| __|
| _ | (_| | (__| <| || (_) | |_) | __/ | | _| __/\__ \ |_
|_| |_|\__,_|\___|_|\_\\__\___/|_.__/ \___|_| |_| \___||___/\__|
```
This repository is part of Hacktoberfest. Contributions are welcome! Feel free to suggest improvements, add translation, fix bugs, or propose new features. Thank you for contributing !
### Subjects
You are welcome to create pull requests on any of those subjects:
@@ -161,4 +172,4 @@ We have one sticker per contribution type. You might get multiple stickers with
Here is the design of each stickers for year 2024:
![iTop stickers 2024](.doc/contributing-guide/2024.contributing-stickers-side-by-side.png)
![iTop stickers 2025](.doc/contributing-guide/2025.contributing-stickers-side-by-side.png)

View File

@@ -53,7 +53,7 @@ iTop also offers mass import tools to help you become even more efficient.
[4]: https://www.itophub.io/wiki/page?id=latest:install:requirements
[5]: https://www.itophub.io/wiki
[6]: https://store.itophub.io/en_US/
[7]: .doc/itop-version-history.md
[7]: itop-version-history.md
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
@@ -99,6 +99,7 @@ We would like to give a special thank you 🤗 to the people from the community
- Goethals, Stefan
- Giuva, Vincenzo Katriel (a.k.a [@DarkNight97boss](https://github.com/DarkNight97boss))
- Gumble, David
- Håkon, Harnes (a.k.a [@hakonharnes](https://github.com/hakonharnes))
- Heloir, Arthur
- Janssens, Jelle (a.k.a [@janssensjelle](https://github.com/janssensjelle))
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))

View File

@@ -57,12 +57,6 @@ require_once(APPROOT.'application/applicationextension/backoffice/SeparatorPopup
require_once(APPROOT.'application/applicationextension/backoffice/URLButtonItem.php');
require_once(APPROOT.'application/applicationextension/backoffice/URLPopupMenuItem.php');
//deprecated class and interface
require_once(APPROOT.'application/applicationextension/backoffice/iApplicationObjectExtension.php');
require_once(APPROOT.'application/applicationextension/backoffice/AbstractApplicationObjectExtension.php');
require_once(APPROOT.'application/applicationextension/iBackupExtraFilesExtension.php');
require_once(APPROOT.'application/applicationextension/iKPILoggerExtension.php');
require_once(APPROOT.'application/applicationextension/iModuleExtension.php');

View File

@@ -1,58 +0,0 @@
<?php
/**
* Extend this class instead of iApplicationObjectExtension if you don't need to overload all methods
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method
* @package ORMExtensibilityAPI
* @since 2.7.0
*/
abstract class AbstractApplicationObjectExtension implements iApplicationObjectExtension
{
/**
* @inheritDoc
*/
public function OnIsModified($oObject)
{
return false;
}
/**
* @inheritDoc
*/
public function OnCheckToWrite($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function OnCheckToDelete($oObject)
{
return array();
}
/**
* @inheritDoc
*/
public function OnDBUpdate($oObject, $oChange = null)
{
}
/**
* @inheritDoc
*/
public function OnDBInsert($oObject, $oChange = null)
{
}
/**
* @inheritDoc
*/
public function OnDBDelete($oObject, $oChange = null)
{
}
}

View File

@@ -1,111 +0,0 @@
<?php
/**
* Implement this interface to perform specific operations when objects are manipulated
*
* Note that those methods will be called when objects are manipulated, either in a programmatic way
* or through the GUI.
*
* @api
* @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method. More details on each method PHPDoc.
* @package ORMExtensibilityAPI
*/
interface iApplicationObjectExtension
{
/**
* Invoked to determine whether an object has been modified in memory
*
* The GUI calls this verb to determine the message that will be displayed to the end-user.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* If the extension returns false, then the framework will perform the usual evaluation.
* Otherwise, the answer is definitively "yes, the object has changed".
*
* @param /cmdbAbstractObject $oObject The target object
*
* @return boolean True if something has changed for the target object
* @api
* @deprecated 3.1.0 N°4756 No alternative available, this API was unstable and is abandoned
*/
public function OnIsModified($oObject);
/**
* Invoked to determine whether an object can be written to the database
*
* The GUI calls this verb and reports any issue.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_WRITE event instead
*/
public function OnCheckToWrite($oObject);
/**
* Invoked to determine wether an object can be deleted from the database
*
* The GUI calls this verb and stops the deletion process if any issue is reported.
*
* Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled.
*
* @param \cmdbAbstractObject $oObject The target object
*
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
* @api
* @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_DELETE event instead
*/
public function OnCheckToDelete($oObject);
/**
* Invoked when an object is updated into the database. The method is called right <b>after</b> the object has been written to the
* database.
*
* Useful methods you can call on $oObject :
*
* * {@see DBObject::ListPreviousValuesForUpdatedAttributes()} : list of changed attributes and their values before the change
* * {@see DBObject::Get()} : for a given attribute the new value that was persisted
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
*
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @api
* @since 2.7.0 N°2293 can access object changes by calling {@see DBObject::ListPreviousValuesForUpdatedAttributes()} on $oObject
*/
public function OnDBUpdate($oObject, $oChange = null);
/**
* Invoked when an object is created into the database
*
* The method is called right <b>after</b> the object has been written to the database.
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead
* @api
*/
public function OnDBInsert($oObject, $oChange = null);
/**
* Invoked when an object is deleted from the database
*
* The method is called right <b>before</b> the object will be deleted from the database.
*
* @param \cmdbAbstractObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information
* once for all the changes made within the current page
*
* @return void
* @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_DELETE event instead
* @api
*/
public function OnDBDelete($oObject, $oChange = null);
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* Login page extensibility
*
* @api
* @package UIExtensibilityAPI
* @since 3.x.x
*/
interface iTokenLoginUIExtension
{
/**
* @return array
* @api
*/
public function GetTokenInfo() : array;
/**
* @return array
* @api
*/
public function GetUserLogin(array $aTokenInfo) : string;
}

View File

@@ -214,6 +214,15 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
*/
protected static bool $bBlockEventDBLinksChanged = false;
/**
* If set to true, the object is considered as modified, whatever the actual state is.
* This is used when an object is modified indirectly (eg. through a linked set)
*
* @var bool
*
* @since 3.3.0 N°8210 - Remove iApplicationObjectExtension
*/
private bool $bIsMarkedAsModified = false;
/**
* Constructor from a row of data (as a hash 'attcode' => value)
@@ -750,10 +759,10 @@ HTML
$oPage->SetCurrentTab($sTabCode, $oAttDef->GetLabel().$sCount, $sTabDescription);
$aArgs = array('this' => $this);
$sEditWhen = $oAttDef->GetEditWhen();
// Calculate if edit_when allows to edit based on current $bEditMode
$bIsEditableBasedOnEditWhen = ($sEditWhen === LINKSET_EDITWHEN_ALWAYS) ||
$bIsEditableBasedOnEditWhen = ($sEditWhen === LINKSET_EDITWHEN_ALWAYS) ||
($bEditMode ? $sEditWhen === LINKSET_EDITWHEN_ON_HOST_EDITION : $sEditWhen === LINKSET_EDITWHEN_ON_HOST_DISPLAY);
$bReadOnly = ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE)) || !$bIsEditableBasedOnEditWhen;
@@ -1209,35 +1218,6 @@ HTML
return DataTableUIBlockFactory::MakeForObject($oPage, $sTableId, $oSet, $aExtraParams);
}
/**
* Get the HTML fragment corresponding to the display of a table representing a set of objects
*
* @param WebPage $oPage The page object is used for out-of-band information (mostly scripts) output
* @param \DBObjectSet $oSet The set of objects to display
* @param array $aExtraParams key used :
* <ul>
* <li>view_link : if true then for extkey will display links with friendly name and make column sortable, default true
* <li>menu : if true prints DisplayBlock menu, default true
* <li>display_aliases : list of query aliases that will be printed, defaults to [] (displays all)
* <li>zlist : name of the zlist to use, false to disable zlist lookup, default to 'list'
* <li>extra_fields : list of <alias>.<attcode> to add to the result, separator ',', defaults to empty string
* </ul>
*
* @return String The HTML fragment representing the table of objects. <b>Warning</b> : no JS added to handled
* pagination or table sorting !
*
* @see DisplayBlock to get a similar table but with the JS for pagination & sorting
*
* @deprecated 3.0.0 use GetDisplaySetBlock
*/
public static function GetDisplaySet(WebPage $oPage, DBObjectSet $oSet, $aExtraParams = array())
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use GetDisplaySetBlock');
$oPage->AddUiBlock(static::GetDisplaySetBlock($oPage, $oSet, $aExtraParams));
return "";
}
/**
* @param WebPage $oPage
* @param \DBObjectSet $oSet
@@ -1411,129 +1391,6 @@ HTML
//DataTableUIBlockFactory::MakeForStaticData('', $aHeader, $aRows);
}
/**
* @param WebPage $oPage
* @param \CMDBObjectSet $oSet
* @param array $aExtraParams key used :
* <ul>
* <li>view_link : if true then for extkey will display links with friendly name and make column sortable, default true
* <li>menu : if true prints DisplayBlock menu, default true
* <li>display_aliases : list of query aliases that will be printed, defaults to [] (displays all)
* <li>zlist : name of the zlist to use, false to disable zlist lookup, default to 'list'
* <li>extra_fields : list of <alias>.<attcode> to add to the result, separator ',', defaults to empty string
* </ul>
*
* @return string
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @deprecated 3.0.0
*/
public static function GetDisplayExtendedSet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
if (empty($aExtraParams['currentId'])) {
$iListId = utils::GetUniqueId(); // Works only if not in an Ajax page !!
} else {
$iListId = $aExtraParams['currentId'];
}
$aList = array();
// Initialize and check the parameters
$bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true;
$bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true;
// Check if there is a list of aliases to limit the display to...
$aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',',
$aExtraParams['display_aliases']) : array();
$sZListName = isset($aExtraParams['zlist']) ? ($aExtraParams['zlist']) : 'list';
$aExtraFieldsRaw = isset($aExtraParams['extra_fields']) ? explode(',',
trim($aExtraParams['extra_fields'])) : array();
$aExtraFields = array();
$sAttCode = '';
foreach($aExtraFieldsRaw as $sFieldName)
{
// Ignore attributes not of the main queried class
if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches))
{
$sClassAlias = $aMatches[1];
$sAttCode = $aMatches[2];
if (array_key_exists($sClassAlias, $oSet->GetSelectedClasses()))
{
$aExtraFields[$sClassAlias][] = $sAttCode;
}
}
else
{
$aExtraFields['*'] = $sAttCode;
}
}
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
$aAuthorizedClasses = array();
foreach($aClasses as $sAlias => $sClassName)
{
if ((UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) &&
((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases))))
{
$aAuthorizedClasses[$sAlias] = $sClassName;
}
}
foreach($aAuthorizedClasses as $sAlias => $sClassName)
{
if (array_key_exists($sAlias, $aExtraFields))
{
$aList[$sAlias] = $aExtraFields[$sAlias];
}
else
{
$aList[$sAlias] = array();
}
if ($sZListName !== false)
{
$aDefaultList = self::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName));
$aList[$sAlias] = array_merge($aDefaultList, $aList[$sAlias]);
}
// Filter the list to removed linked set since we are not able to display them here
foreach ($aList[$sAlias] as $index => $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
if ($oAttDef instanceof AttributeLinkedSet)
{
// Removed from the display list
unset($aList[$sAlias][$index]);
}
}
if (empty($aList[$sAlias]))
{
unset($aList[$sAlias], $aAuthorizedClasses[$sAlias]);
}
}
$sSelectMode = 'none';
$oDataTable = new DataTable($iListId, $oSet, $aAuthorizedClasses);
$oSettings = DataTableSettings::GetDataModelSettings($aAuthorizedClasses, $bViewLink, $aList);
$bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true;
if ($bDisplayLimit)
{
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size',
MetaModel::GetConfig()->GetMinDisplayLimit());
$oSettings->iDefaultPageSize = $iDefaultPageSize;
}
$oSettings->aSortOrder = MetaModel::GetOrderByDefault($sClassName);
return $oDataTable->Display($oPage, $oSettings, $bDisplayMenu, $sSelectMode, $bViewLink, $aExtraParams);
}
/**
* @param WebPage $oPage
* @param \CMDBObjectSet $oSet
@@ -1722,7 +1579,7 @@ HTML
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \Exception
*
*
* @internal Only to be used by `/webservices/export.php` : this is a legacy method that produces wrong HTML (no TR on table body rows)
*/
public static function GetSetAsHTMLSpreadsheet(DBObjectSet $oSet, $aParams = array())
@@ -2223,7 +2080,7 @@ JS
);
// test query link
$sTestResId = 'query_res_'.$sFieldPrefix.$sAttCode.$sNameSuffix; //$oPage->GetUniqueId();
$sTestResId = 'query_res_'.$sFieldPrefix.$sAttCode.$sNameSuffix;
$sBaseUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?expression=';
$sTestQueryLbl = Dict::S('UI:Edit:TestQuery');
$oTestQueryButton = ButtonUIBlockFactory::MakeIconAction(
@@ -2673,7 +2530,7 @@ HTML;
}
break;
}
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
if (!empty($aEventsList))
{
if (!is_numeric($sNullValue))
@@ -3584,15 +3441,13 @@ EOF
} else {
//we can directly apply the stimuli
$sExceptionMessage = null;
$bApplyStimulus = false;
try {
$bApplyStimulus = $this->ApplyStimulus($sStimulus); // will write the object in the DB
}
catch (Exception $oException) {
$bApplyStimulus = $this->ApplyStimulus($sStimulus); // will write the object in the DB
} catch (Exception $oException) {
// Catch any exception happening during the stimulus
$bApplyStimulus = false;
$sExceptionMessage = ($oException instanceof CoreCannotSaveObjectException) ? $oException->getHtmlMessage() : $oException->getMessage();
}
finally {
} finally {
if ($sOwnershipToken !== null) {
// Release the concurrent lock, if any
iTopOwnershipLock::ReleaseLock($sClass, $iKey, $sOwnershipToken);
@@ -3600,9 +3455,8 @@ EOF
if (!$bApplyStimulus) {
// Throw an application oriented exception if necessary
throw new ApplicationException($sExceptionMessage ?? Dict::S('UI:FailedToApplyStimuli'));
} else {
return true;
}
return true;
}
}
@@ -3842,7 +3696,7 @@ HTML;
public function GetHilightClass()
{
// Possible return values are:
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
$current = parent::GetHilightClass(); // Default computation
// Invoke extensions before the deletion (the deletion will do some cleanup and we might loose some information
@@ -4542,21 +4396,6 @@ HTML;
return $res;
}
protected function PostInsertActions(): void
{
parent::PostInsertActions();
// Invoke extensions after insertion (the object must exist, have an id, etc.)
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins(iApplicationObjectExtension::class) as $oExtensionInstance) {
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBInsert()");
$oKPI = new ExecutionKPI();
$oExtensionInstance->OnDBInsert($this, self::GetCurrentChange());
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBInsert');
}
}
/**
* @inheritdoc
* Attaches InlineImages to the current object
@@ -4589,21 +4428,6 @@ HTML;
return $res;
}
protected function PostUpdateActions(array $aChanges): void
{
parent::PostUpdateActions($aChanges);
// Invoke extensions after the update (could be before)
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins(iApplicationObjectExtension::class) as $oExtensionInstance) {
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBUpdate()");
$oKPI = new ExecutionKPI();
$oExtensionInstance->OnDBUpdate($this, self::GetCurrentChange());
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBUpdate');
}
}
/**
* @param string $sMessageIdPrefix
*
@@ -4639,21 +4463,6 @@ HTML;
return $oDeletionPlan;
}
final protected function PreDeleteActions(): void
{
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBDelete()");
$oKPI = new ExecutionKPI();
$oExtensionInstance->OnDBDelete($this, self::GetCurrentChange());
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBDelete');
}
parent::PreDeleteActions();
}
final protected function PostDeleteActions(): void
{
parent::PostDeleteActions();
@@ -4666,25 +4475,20 @@ HTML;
return true;
}
// Plugins
//
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified()");
$oKPI = new ExecutionKPI();
$bIsModified = $oExtensionInstance->OnIsModified($this);
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnIsModified');
if ($bIsModified) {
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified() -> true");
return true;
} else {
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified() -> false");
}
}
return $this->bIsMarkedAsModified;
}
return false;
/**
* Override the default modification state of the object.
*
* The object is considered as modified, whatever the actual state is.
* This is used when an object is modified indirectly (eg. through a linked set)
*
* @return void
*/
public function MarkObjectAsModified(): void
{
$this->bIsMarkedAsModified = true;
}
/**
@@ -4698,7 +4502,7 @@ HTML;
}
/**
* Whether to bypass the checks of user rights when writing this object, could be used in {@link \iApplicationObjectExtension::OnCheckToWrite()}
* Whether to bypass the checks of user rights when writing this object
*
* @return bool
*/
@@ -4727,22 +4531,6 @@ HTML;
{
parent::DoCheckToWrite();
// Plugins
//
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnCheckToWrite()");
$oKPI = new ExecutionKPI();
$aNewIssues = $oExtensionInstance->OnCheckToWrite($this);
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnCheckToWrite');
if (is_array($aNewIssues) && (count($aNewIssues) > 0)) // Some extensions return null instead of an empty array
{
$this->m_aCheckIssues = array_merge($this->m_aCheckIssues, $aNewIssues);
}
}
// User rights
//
if (!$this->bAllowWrite)
@@ -4779,22 +4567,6 @@ HTML;
{
parent::DoCheckToDelete($oDeletionPlan);
// Plugins
//
/** @var \iApplicationObjectExtension $oExtensionInstance */
foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$sExtensionClass = get_class($oExtensionInstance);
$this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnCheckToDelete()");
$oKPI = new ExecutionKPI();
$aNewIssues = $oExtensionInstance->OnCheckToDelete($this);
$oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnCheckToDelete');
if (is_array($aNewIssues) && count($aNewIssues) > 0)
{
$this->m_aDeleteIssues = array_merge($this->m_aDeleteIssues, $aNewIssues);
}
}
// User rights
//
if (! $this->bAllowDelete)
@@ -4874,66 +4646,6 @@ HTML;
}
}
/**
* @param $sCurrentState
* @param $sStimulus
* @param $bOnlyNewOnes
*
* @return array
* @throws \ApplicationException
* @throws \CoreException
* @deprecated Since iTop 2.4, use DBObject::GetTransitionAttributes() instead.
*/
public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('Since iTop 2.4, use DBObject::GetTransitionAttributes() instead');
$aTransitions = $this->EnumTransitions();
if (!isset($aTransitions[$sStimulus])) {
// Invalid stimulus
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus,
$this->GetName(), $this->GetStateLabel()));
}
$aTransition = $aTransitions[$sStimulus];
$sTargetState = $aTransition['target_state'];
$aTargetStates = MetaModel::EnumStates(get_class($this));
$aTargetState = $aTargetStates[$sTargetState];
$aCurrentState = $aTargetStates[$this->GetState()];
$aExpectedAttributes = $aTargetState['attribute_list'];
$aCurrentAttributes = $aCurrentState['attribute_list'];
$aComputedAttributes = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
if (!array_key_exists($sAttCode, $aCurrentAttributes))
{
$aComputedAttributes[$sAttCode] = $iExpectCode;
}
else
{
if (!($aCurrentAttributes[$sAttCode] & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)))
{
$iExpectCode = $iExpectCode & ~(OPT_ATT_MUSTPROMPT | OPT_ATT_MUSTCHANGE); // Already prompted/changed, reset the flags
}
// Later: better check if the attribute is not *null*
if (($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) != ''))
{
$iExpectCode = $iExpectCode & ~(OPT_ATT_MANDATORY); // If the attribute is present, then no need to request its presence
}
$aComputedAttributes[$sAttCode] = $iExpectCode;
}
$aComputedAttributes[$sAttCode] = $aComputedAttributes[$sAttCode] & ~(OPT_ATT_READONLY | OPT_ATT_HIDDEN); // Don't care about this form now
if ($aComputedAttributes[$sAttCode] == 0)
{
unset($aComputedAttributes[$sAttCode]);
}
}
return $aComputedAttributes;
}
/**
* Display a form for modifying several objects at once
* The form will be submitted to the current page, with the specified additional values
@@ -5809,7 +5521,7 @@ JS
{
$this->NotifyAttachedObjectsOnLinkClassModification();
$this->RemoveObjectAwaitingEventDbLinksChanged(get_class($this), $this->GetKey());
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied]);
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied, 'cmdb_change' => self::GetCurrentChange()]);
}
//////////////
@@ -5847,7 +5559,7 @@ JS
final protected function FireEventAfterDelete(): void
{
$this->NotifyAttachedObjectsOnLinkClassModification();
$this->FireEvent(EVENT_DB_AFTER_DELETE);
$this->FireEvent(EVENT_DB_AFTER_DELETE, ['cmdb_change' => self::GetCurrentChange()]);
}
/**

View File

@@ -419,7 +419,7 @@ class DisplayBlock
$oSet->OptimizeColumnLoad(array($oSet->GetClassAlias() => array())); // No need to load all the columns just to get the id
while($oObject = $oSet->Fetch())
{
$aKeys[] = $oObject->GetKey();
$aKeys[] = $oObject->GetKey();
}
$oSet->Rewind();
if (count($aKeys) > 0)
@@ -772,10 +772,6 @@ class DisplayBlock
$oBlock = $this->RenderList($aExtraParams, $oPage);
break;
case 'links':
$oBlock = $this->RenderLinks($oPage, $aExtraParams);
break;
case static::ENUM_STYLE_ACTIONS:
$oBlock = $this->RenderActions($aExtraParams);
break;
@@ -795,11 +791,11 @@ class DisplayBlock
case static::ENUM_STYLE_CHART:
$oBlock = $this->RenderChart($sId, $aQueryParams, $aExtraParams);
break;
case static::ENUM_STYLE_CHART_AJAX:
$oBlock = $this->RenderChartAjax($aExtraParams);
break;
default:
// Unsupported style, do nothing.
$sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
@@ -897,7 +893,7 @@ JS
$sClass = $this->m_oFilter->GetClass();
$bConditionAdded = false;
// If the condition is an external key with a class having a hierarchy, use a "below" criteria
if (MetaModel::IsValidAttCode($sClass, $sFilterCode))
{
@@ -906,13 +902,13 @@ JS
if ($oAttDef->IsExternalKey())
{
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
if ($sHierarchicalKeyCode !== false)
{
$oFilter = new DBObjectSearch($oAttDef->GetTargetClass());
if (($sOpCode == 'IN') && is_array($condition))
{
$oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
$oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
}
else
{
@@ -935,21 +931,21 @@ JS
$bConditionAdded = true;
}
}
// In all other cases, just add the condition directly
if (!$bConditionAdded)
{
$this->m_oFilter->AddCondition($sFilterCode, $condition, null); // Use the default 'loose' operator
}
}
static protected function GetConditionIN($oFilter, $sFilterCode, $condition)
{
$oField = new FieldExpression($sFilterCode, $oFilter->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($condition)).')';
$sOQLCondition = $oField->RenderExpression()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
return $oNewCondition;
return $oNewCondition;
}
/**
@@ -1565,54 +1561,6 @@ JS
return $oContentBlock;
}
/**
* @deprecated 3.1.0 N°5957
*
* @param WebPage $oPage
* @param array $aExtraParams
*
* @return \Combodo\iTop\Application\UI\Base\Component\Html\Html|\Combodo\iTop\Application\UI\Base\Layout\UIContentBlock|string
* @throws \ApplicationException
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \ReflectionException
*/
protected function RenderLinks(WebPage $oPage, array $aExtraParams)
{
// Note: No deprecation ticket yet as we want to wait and see if people / code actually use this method, in which case we might keep it.
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('This method is most likely not used throughout the application and will be removed soon. If you ever see this message, please inform us.');
$oBlock = null;
if (($this->m_oSet->CountWithLimit(1) > 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)) {
$oBlock = cmdbAbstractObject::GetDisplaySetBlock($oPage, $this->m_oSet, $aExtraParams);
} else {
$sClass = $this->m_oFilter->GetClass();
$oAttDef = MetaModel::GetAttributeDef($sClass, $this->m_aParams['target_attr']);
$sTargetClass = $oAttDef->GetTargetClass();
$oBlock = new Html('<p>'.Dict::Format('UI:NoObject_Class_ToDisplay', MetaModel::GetName($sTargetClass)).'</p>');
$bDisplayMenu = isset($this->m_aParams['menu']) ? $this->m_aParams['menu'] == true : true;
if ($bDisplayMenu) {
if ((UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
$sDefaults = '';
if (isset($this->m_aParams['default'])) {
foreach ($this->m_aParams['default'] as $sName => $sValue) {
$sDefaults .= '&'.urlencode($sName).'='.urlencode($sValue);
}
}
$oBlock->AddHtml("<p><a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=modify_links&class=$sClass&sParams&link_attr=".$aExtraParams['link_attr']."&id=".$aExtraParams['object_id']."&target_class=$sTargetClass&addObjects=true$sDefaults\">".Dict::Format('UI:ClickToCreateNew',
Metamodel::GetName($sClass))."</a></p>\n");
}
}
}
return $oBlock;
}
/**
* @param string|null $sChartId
* @param array $aQueryParams

View File

@@ -9,7 +9,7 @@ use Combodo\iTop\Application\Helper\Session;
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginBasic extends AbstractLoginFSMExtension
class LoginBasic extends AbstractLoginFSMExtension implements iTokenLoginUIExtension
{
/**
* Return the list of supported login modes for this plugin
@@ -143,4 +143,21 @@ class LoginBasic extends AbstractLoginFSMExtension
}
return array($sAuthUser, $sAuthPwd);
}
public function GetTokenInfo(): array
{
return $this->GetAuthUserAndPassword();
}
public function GetUserLogin(array $aTokenInfo): string
{
$sLogin = $aTokenInfo[0];
$sLoginMode = 'basic';
if (UserRights::CheckCredentials($sLogin, $aTokenInfo[1], $sLoginMode, 'internal'))
{
return $sLogin;
}
throw new Exception("Cannot CheckCredentials user login ($sLogin) with ($sLoginMode) mode");
}
}

View File

@@ -12,7 +12,7 @@ use Combodo\iTop\Application\Helper\Session;
*
* @since 2.7.0
*/
class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension, iTokenLoginUIExtension
{
private $bForceFormOnError = false;
@@ -32,8 +32,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
protected function OnReadCredentials(&$iErrorCode)
{
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'form') {
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
list($sAuthUser, $sAuthPwd) = $this->GetTokenInfo();
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
{
if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER))
@@ -68,8 +67,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
{
if (Session::Get('login_mode') == 'form')
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
list($sAuthUser, $sAuthPwd) = $this->GetTokenInfo();
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
@@ -153,4 +151,23 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
return $oLoginContext;
}
public function GetTokenInfo(): array
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
return [$sAuthUser, $sAuthPwd];
}
public function GetUserLogin(array $aTokenInfo): string
{
$sLogin = $aTokenInfo[0];
$sLoginMode = 'form';
if (UserRights::CheckCredentials($sLogin, $aTokenInfo[1], $sLoginMode, 'internal'))
{
return $sLogin;
}
throw new Exception("Cannot CheckCredentials user login ($sLogin) with ($sLoginMode) mode");
}
}

View File

@@ -9,7 +9,7 @@ use Combodo\iTop\Application\Helper\Session;
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginURL extends AbstractLoginFSMExtension
class LoginURL extends AbstractLoginFSMExtension implements iTokenLoginUIExtension
{
/**
* @var bool
@@ -30,9 +30,7 @@ class LoginURL extends AbstractLoginFSMExtension
{
if (!Session::IsSet('login_mode') && !$this->bErrorOccurred)
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd))
list($sAuthUser, $sAuthPwd) = $this->GetTokenInfo();
{
Session::Set('login_mode', 'url');
}
@@ -53,8 +51,7 @@ class LoginURL extends AbstractLoginFSMExtension
{
if (Session::Get('login_mode') == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
list($sAuthUser, $sAuthPwd) = $this->GetTokenInfo();
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
@@ -92,4 +89,23 @@ class LoginURL extends AbstractLoginFSMExtension
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
public function GetTokenInfo(): array
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
return [$sAuthUser, $sAuthPwd];
}
public function GetUserLogin(array $aTokenInfo): string
{
$sLogin = $aTokenInfo[0];
$sLoginMode = 'url';
if (UserRights::CheckCredentials($sLogin, $aTokenInfo[1], $sLoginMode, 'internal'))
{
return $sLogin;
}
throw new Exception("Cannot CheckCredentials user login ($sLogin) with ($sLoginMode) mode");
}
}

View File

@@ -581,6 +581,26 @@ class LoginWebPage extends NiceWebPage
return $aPlugins;
}
public static function GetCurrentLoginPlugin(string $sCurrentLoginMode) : iLoginExtension
{
/** @var iLoginExtension $oLoginExtensionInstance */
foreach (MetaModel::EnumPlugins('iLoginFSMExtension') as $oLoginExtensionInstance)
{
$aLoginModes = $oLoginExtensionInstance->ListSupportedLoginModes();
$aLoginModes = (is_array($aLoginModes) ? $aLoginModes : array());
foreach ($aLoginModes as $sLoginMode)
{
// Keep only the plugins for the current login mode + before + after
if ($sLoginMode == $sCurrentLoginMode)
{
return $oLoginExtensionInstance;
}
}
}
throw new \Exception("should not happen");
}
/**
* Advance Login Finite State Machine to the next step
*

View File

@@ -358,50 +358,6 @@ class ApplicationMenu
return $aSubMenuNodes;
}
/**
* Entry point to display the whole menu into the web page, used by iTopWebPage
* @param WebPage $oPage
* @param array $aExtraParams
* @throws DictExceptionMissingString
*
* @deprecated Will be removed in 3.0.0, use static::GetMenuGroups() instead
*/
public static function DisplayMenu($oPage, $aExtraParams)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetMenuGroups() instead');
self::LoadAdditionalMenus();
// 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) {
if (!self::CanDisplayMenu($aMenu)) {
continue;
}
$oMenuNode = self::GetMenuNode($aMenu['index']);
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$oMenuNode->GetMenuID()).'" class="navigation-menu-group" data-menu-id="'.$oMenuNode->GetMenuId().'">'.$oMenuNode->GetTitle().'</h3>');
$oPage->AddToMenu('<div>');
$oPage->AddToMenu('<ul>');
$aChildren = self::GetChildren($aMenu['index']);
$bActive = self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
$oPage->AddToMenu('</ul>');
if ($bActive)
{
$iActiveAccordion = $iAccordion;
}
$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
);
}
/**
* Recursively check if the menu and at least one of his sub-menu is enabled
* @param array $aMenu menu entry
@@ -431,73 +387,6 @@ EOF
return false;
}
/**
* Handles the display of the sub-menus (called recursively if necessary)
*
* @param WebPage $oPage
* @param array $aMenus
* @param array $aExtraParams
* @param int $iActiveMenu
*
* @return bool True if the currently selected menu is one of the submenus
* @throws DictExceptionMissingString
* @throws \Exception
* @deprecated Will be removed in 3.0.0, use static::GetSubMenuNodes() instead
*/
protected static function DisplaySubMenu($oPage, $aMenus, $aExtraParams, $iActiveMenu = -1)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetSubMenuNodes() instead');
// Sort the menu based on the rank
$bActive = false;
usort($aMenus, array('ApplicationMenu', 'CompareOnRank'));
foreach ($aMenus as $aMenu) {
if (!self::CanDisplayMenu($aMenu)) {
continue;
}
$index = $aMenu['index'];
$oMenu = self::GetMenuNode($index);
if ($oMenu->IsEnabled())
{
$aChildren = self::GetChildren($index);
$aCSSClasses = array('navigation-menu-item');
if (count($aChildren) > 0)
{
$aCSSClasses[] = 'submenu';
}
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
$sItemHtml = '<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" class="'.implode(' ', $aCSSClasses).'" data-menu-id="'.$oMenu->GetMenuID().'">';
if ($sHyperlink != '')
{
$sLinkTarget = '';
if ($oMenu->IsHyperLinkInNewWindow())
{
$sLinkTarget .= ' target="_blank"';
}
$sURL = '"'.$oMenu->GetHyperlink($aExtraParams).'"'.$sLinkTarget;
$sTitle = utils::HtmlEntities($oMenu->GetTitle());
$sItemHtml .= "<a href={$sURL}>{$sTitle}</a>";
}
else
{
$sItemHtml .= $oMenu->GetTitle();
}
$sItemHtml .= '</li>';
$oPage->AddToMenu($sItemHtml);
if ($iActiveMenu == $index)
{
$bActive = true;
}
if (count($aChildren) > 0)
{
$oPage->AddToMenu('<ul>');
$bActive |= self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
$oPage->AddToMenu('</ul>');
}
}
}
return $bActive;
}
/**
* Helper function to sort the menus based on their rank
* @param array $a

View File

@@ -2424,19 +2424,6 @@ SQL;
return $bRet;
}
/**
* @param $sPath
*
* @return false|\ormDocument
* @throws \Exception
*
* @deprecated 3.2.1 use utils::GetDocumentFromSelfURL instead
*/
public static function IsSelfURL($sPath)
{
return self::GetDocumentFromSelfURL($sPath);
}
/**
* Check if the given URL is a link to download a document/image on the CURRENT iTop
* In such a case we can read the content of the file directly in the database (if the users rights allow) and return the ormDocument

View File

@@ -3,7 +3,7 @@
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -31,7 +31,7 @@ require_once(APPROOT.'/application/uiwizard.class.inc.php');
class WizardHelper
{
protected $m_aData;
public function __construct()
{
}
@@ -39,7 +39,7 @@ class WizardHelper
* Constructs the PHP target object from the parameters sent to the web page by the wizard
* @param boolean $bReadUploadedFiles True to also read any uploaded file (for blob/document fields)
* @return object
*/
*/
public function GetTargetObject($bReadUploadedFiles = false)
{
if (isset($this->m_aData['m_oCurrentValues']['id']))
@@ -207,7 +207,7 @@ class WizardHelper
else
{
$oObj->Set($sAttCode, $value);
}
}
}
}
if (isset($this->m_aData['m_sState']) && !empty($this->m_aData['m_sState']))
@@ -217,12 +217,12 @@ class WizardHelper
$oObj->DoComputeValues();
return $oObj;
}
public function GetFieldsForDefaultValue()
{
return $this->m_aData['m_aDefaultValueRequested'];
}
public function SetDefaultValue($sAttCode, $value)
{
// Protect against a request for a non existing field
@@ -247,7 +247,7 @@ class WizardHelper
$aData[] = $aRow;
}
$this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData);
}
else
{
@@ -256,12 +256,12 @@ class WizardHelper
}
}
}
public function GetFieldsForAllowedValues()
{
return $this->m_aData['m_aAllowedValuesRequested'];
}
public function SetAllowedValuesHtml($sAttCode, $sHtml)
{
// Protect against a request for a non existing field
@@ -270,12 +270,12 @@ class WizardHelper
$this->m_aData['m_oAllowedValues'][$sAttCode] = $sHtml;
}
}
public function ToJSON()
{
return json_encode($this->m_aData);
}
static public function FromJSON($sJSON)
{
$oWizHelper = new WizardHelper();
@@ -283,7 +283,7 @@ class WizardHelper
$oWizHelper->m_aData = $aData;
return $oWizHelper;
}
protected function GetLinkedWizardStructure($oAttDef)
{
$oWizard = new UIWizard(null, $oAttDef->GetLinkedClass());
@@ -310,7 +310,7 @@ class WizardHelper
}
return $aFields;
}
public function GetTargetClass()
{
return $this->m_aData['m_sClass'];
@@ -330,7 +330,7 @@ class WizardHelper
{
return isset($this->m_aData['m_sStimulus']) ? $this->m_aData['m_sStimulus'] : null;
}
public function GetIdForField($sFieldName)
{
$sResult = '';
@@ -375,31 +375,4 @@ JS
);
}
/*
* Function with an old pattern of code
* @deprecated 3.1.0
*/
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
{
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object
$oSet = CMDBObjectSet::FromScratch($sLinkClass);
foreach ($aSet as $aLinkObj) {
$oLink = MetaModel::NewObject($sLinkClass);
foreach ($aLinkObj as $sAttCode => $value) {
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0))
{
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value);
$oLink->Set($sAttCode, $oTargetObj);
}
$oLink->Set($sAttCode, $value);
}
$oLink->Set($sExtKeyToMe, $oMe->GetKey());
$oSet->AddObject($oLink);
}
return $oSet;
}
}

View File

@@ -15,32 +15,35 @@
"apereo/phpcas": "~1.6.0",
"firebase/php-jwt": "^6.4.0",
"guzzlehttp/guzzle": "^7.5.1",
"laminas/laminas-mail": "^2.11",
"laminas/laminas-servicemanager": "^3.5",
"league/oauth2-google": "^4.0.1",
"nikic/php-parser": "~5.6.0",
"nikic/php-parser": "dev-master",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "^7.2.0",
"psr/log": "^3.0.0",
"scssphp/scssphp": "^1.12.1",
"soundasleep/html2text": "~2.1",
"symfony/console": "~6.4.0",
"symfony/dotenv": "~6.4.0",
"symfony/framework-bundle": "~6.4.0",
"symfony/http-foundation": "~6.4.0",
"symfony/http-kernel": "~6.4.0",
"symfony/mailer": "^6.4",
"symfony/runtime": "~6.4.0",
"symfony/twig-bundle": "~6.4.0",
"symfony/var-dumper": "~6.4.0",
"symfony/yaml": "~6.4.0",
"tecnickcom/tcpdf": "^6.6.0",
"thenetworg/oauth2-azure": "^2.0",
"soundasleep/html2text": "~2.1"
"thenetworg/oauth2-azure": "^2.0"
},
"require-dev": {
"symfony/debug-bundle": "~6.4.0",
"symfony/stopwatch": "~6.4.0",
"symfony/web-profiler-bundle": "~6.4.0"
},
"repositories": [{
"type": "vcs",
"url": "https://github.com/Combodo/PHP-Parser"
}],
"suggest": {
"ext-libsodium": "Required to use the AttributeEncryptedString.",
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",

1668
composer.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ class BulkExportException extends Exception
parent::__construct($message, $code, $previous);
$this->sLocalizedMessage = $sLocalizedMessage;
}
public function GetLocalizedMessage()
{
return $this->sLocalizedMessage;
@@ -42,7 +42,7 @@ class BulkExportMissingParameterException extends BulkExportException
{
parent::__construct('Missing parameter: '.$sFieldCode, Dict::Format('Core:BulkExport:MissingParameter_Param', $sFieldCode));
}
}
/**
@@ -146,7 +146,7 @@ abstract class BulkExport
protected $oBulkExportResult;
protected $sTmpFile;
protected $bLocalizeOutput;
public function __construct()
{
$this->oSearch = null;
@@ -247,7 +247,7 @@ abstract class BulkExport
fclose($hFile);
}
}
public function GetTmpFilePath()
{
return $this->sTmpFile;
@@ -289,7 +289,7 @@ abstract class BulkExport
{
$this->bLocalizeOutput = $bLocalizeOutput;
}
/**
* (non-PHPdoc)
* @see iBulkExport::SetObjectList()
@@ -299,12 +299,12 @@ abstract class BulkExport
$oSearch->SetShowObsoleteData($this->aStatusInfo['show_obsolete_data']);
$this->oSearch = $oSearch;
}
public function SetFormat($sFormatCode)
{
$this->sFormatCode = $sFormatCode;
$this->sFormatCode = $sFormatCode;
}
/**
* (non-PHPdoc)
* @see iBulkExport::IsFormatSupported()
@@ -322,7 +322,7 @@ abstract class BulkExport
{
return array(); // return array('csv' => Dict::S('UI:ExportFormatCSV'));
}
public function SetHttpHeaders(WebPage $oPage)
{
@@ -344,7 +344,7 @@ abstract class BulkExport
{
return '';
}
public function SaveState()
{
if ($this->oBulkExportResult === null)
@@ -362,7 +362,7 @@ abstract class BulkExport
utils::PopArchiveMode();
return $ret;
}
public function Cleanup()
{
if (($this->oBulkExportResult && (!$this->oBulkExportResult->IsNew())))
@@ -383,16 +383,6 @@ abstract class BulkExport
return array();
}
/**
* @deprecated 3.0.0 use GetFormPart instead
*/
public function DisplayFormPart(WebPage $oP, $sPartId)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use GetFormPart instead');
$oP->AddSubBlock($this->GetFormPart($oP, $sPartId));
}
/**
* @param WebPage $oP
* @param $sPartId
@@ -412,14 +402,14 @@ abstract class BulkExport
{
$this->bLocalizeOutput = !((bool)utils::ReadParam('no_localize', 0, true, 'integer'));
}
public function GetResultAsHtml()
{
}
public function GetRawResult()
{
}
/**
@@ -441,17 +431,17 @@ abstract class BulkExport
{
return 'UTF-8';
}
public function GetStatistics()
{
}
public function SetFields($sFields)
{
}
public function GetDownloadFileName()
{
return Dict::Format('Core:BulkExportOf_Class', MetaModel::GetName($this->oSearch->GetClass())).'.'.$this->GetFileExtension();
@@ -461,7 +451,7 @@ abstract class BulkExport
{
$this->aStatusInfo = $aStatusInfo;
}
public function GetStatusInfo()
{
return $this->aStatusInfo;
@@ -493,7 +483,7 @@ abstract class BulkExport
$hFile = @fopen($sFileName, 'x');
}
while($hFile === false);
fclose($hFile);
return $sFileName;
}

View File

@@ -42,11 +42,6 @@ class CMDBSource
const ENUM_DB_VENDOR_MARIADB = 'MariaDB';
const ENUM_DB_VENDOR_PERCONA = 'Percona';
/**
* @since 2.7.10 3.0.4 3.1.2 3.0.2 N°6889 constant creation
* @internal will be removed in a future version
*/
const MYSQL_DEFAULT_PORT = 3306;
/**
* Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
@@ -220,7 +215,7 @@ class CMDBSource
* @param string $sServer server variable to update
* @param int|null $iPort port variable to update, will return null if nothing is specified in $sDbHost
*
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°6889 will return null in $iPort if port isn't present in $sDbHost. Use {@see MYSQL_DEFAULT_PORT} if needed
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°6889 will return null in $iPort if port isn't present in $sDbHost.
*
* @link http://php.net/manual/en/mysqli.persistconns.php documentation for the "p:" prefix (persistent connexion)
*/
@@ -363,15 +358,6 @@ class CMDBSource
return static::QueryToScalar('SELECT VERSION()', 0);
}
/**
* @deprecated Use `CMDBSource::GetDBVersion` instead.
* @uses mysqli_get_server_info
*/
public static function GetServerInfo()
{
return mysqli_get_server_info(DbConnectionWrapper::GetDbConnection());
}
/**
* Get the DB vendor between MySQL and its main forks
* @return string

View File

@@ -20,6 +20,9 @@
*/
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
@@ -1816,6 +1819,7 @@ class Config
return (array_key_exists($sPropCode, $this->m_aSettings));
}
/**
* @return string identifier that can be used for example to name WebStorage/SessionStorage keys (they
* are related to a whole domain, and a domain can host multiple itop)
@@ -2255,6 +2259,9 @@ class Config
$this->m_aModuleSettings[$sModule][$sProperty] = $value;
}
/**
* @deprecated 3.3.0 N°8190
*/
public function GetAddons()
{
if (array_key_exists("user rights", $this->m_aAddons)) {
@@ -2264,6 +2271,9 @@ class Config
}
}
/**
* @deprecated 3.3.0 N°8190
*/
public function SetAddons($aAddons)
{
$this->m_aAddons = $aAddons;
@@ -2842,20 +2852,8 @@ class Config
}
}
}
if (isset($aModuleInfo['installer']))
{
$sModuleInstallerClass = $aModuleInfo['installer'];
if (!class_exists($sModuleInstallerClass))
{
throw new Exception("Wrong installer class: '$sModuleInstallerClass' is not a PHP class - Module: ".$aModuleInfo['label']);
}
if (!is_subclass_of($sModuleInstallerClass, 'ModuleInstallerAPI'))
{
throw new Exception("Wrong installer class: '$sModuleInstallerClass' is not derived from 'ModuleInstallerAPI' - Module: ".$aModuleInfo['label']);
}
$aCallSpec = array($sModuleInstallerClass, 'BeforeWritingConfig');
call_user_func_array($aCallSpec, array($this));
}
RunTimeEnvironment::CallInstallerHandler($aModuleInfo, "BeforeWritingConfig", [$this]);
}
}
$this->SetAddOns($aAddOns);
@@ -3023,4 +3021,6 @@ class ConfigPlaceholdersResolver
IssueLog::Error($sErrorMessage, self::class, array($sSourceName, $sKey, $sDefault, $sWholeMask));
throw new ConfigException($sErrorMessage);
}
}

View File

@@ -62,7 +62,7 @@ require_once('mutex.class.inc.php');
/**
* A persistent object, as defined by the metamodel
* A persistent object, as defined by the metamodel
*
* @package iTopORM
* @api
@@ -314,9 +314,9 @@ abstract class DBObject implements iDisplay
/**
* Whether the object is already persisted in DB or not.
*
*
* @api
*
*
* @return bool
*/
public function IsNew()
@@ -326,9 +326,9 @@ abstract class DBObject implements iDisplay
/**
* Returns an Id for memory objects
*
*
* @internal
*
*
* @param string $sClass
*
* @return int
@@ -365,7 +365,7 @@ abstract class DBObject implements iDisplay
$sRet .= "<b title=\"$sRootClass\">$sClass</b>::$iPKey ($sFriendlyname)<br/>\n";
return $sRet;
}
/**
* Alias of DBObject::Reload()
*
@@ -388,7 +388,7 @@ abstract class DBObject implements iDisplay
*
* @internal
* @see m_bFullyLoaded
*
*
* @return bool
* @throws CoreException
*/
@@ -411,11 +411,9 @@ abstract class DBObject implements iDisplay
* This is mostly used after a lazy load (automatically performed by the framework)
* This will erase any pending changes.
*
* @param bool $bAllowAllData @deprecated This parameter is ignored!!
*
* @throws CoreException
*/
public function Reload($bAllowAllData = false)
public function Reload()
{
assert($this->m_bIsInDB);
$this->FireEvent(EVENT_DB_OBJECT_RELOAD);
@@ -511,7 +509,7 @@ abstract class DBObject implements iDisplay
{
$aAttList = $aAttToLoad[$sClassAlias];
}
foreach($aAttList as $sAttCode=>$oAttDef)
{
// Skip links (could not be loaded by the mean of this query)
@@ -571,7 +569,7 @@ abstract class DBObject implements iDisplay
$bFullyLoaded = false;
}
}
// Load extended data
if ($aExtendedDataSpec != null)
{
@@ -595,7 +593,7 @@ abstract class DBObject implements iDisplay
*
* @internal
* @see Set()
*
*
* @param string $sAttCode
* @param mixed $value
*/
@@ -850,11 +848,11 @@ abstract class DBObject implements iDisplay
/**
* Get the label of an attribute.
*
*
* Shortcut to the field's AttributeDefinition->GetLabel()
*
* @api
*
*
* @param string $sAttCode
*
* @return string
@@ -927,7 +925,7 @@ abstract class DBObject implements iDisplay
*
* @internal
* @see Get
*
*
* @param string $sAttCode
*
* @return int|mixed|null
@@ -1032,7 +1030,7 @@ abstract class DBObject implements iDisplay
* Returns the default value of the $sAttCode.
*
* Returns the default value of the given attribute.
*
*
* @internal
*
* @param string $sAttCode
@@ -1053,12 +1051,12 @@ abstract class DBObject implements iDisplay
* @internal
*
* @return array|null
*/
*/
public function GetExtendedData()
{
return $this->m_aExtendedData;
}
/**
* Set the HighlightCode
*
@@ -1080,7 +1078,7 @@ abstract class DBObject implements iDisplay
{
$fCurrentRank = $aHighlightScale[$this->m_sHighlightCode]['rank'];
}
if (array_key_exists($sCode, $aHighlightScale))
{
$fRank = $aHighlightScale[$sCode]['rank'];
@@ -1090,13 +1088,13 @@ abstract class DBObject implements iDisplay
}
}
}
/**
* Get the current HighlightCode
*
*
* @internal
* @used-by DBObject::ComputeHighlightCode()
*
*
* @return string|null The Hightlight code (null if none set, meaning rank = 0)
*/
protected function GetHighlightCode()
@@ -1145,7 +1143,7 @@ abstract class DBObject implements iDisplay
* corresponding to the external key and getting the value from it
*
* UNUSED ?
*
*
* @internal
* @todo: check if this is dead code.
*
@@ -1216,7 +1214,7 @@ abstract class DBObject implements iDisplay
/**
* @api
*
*
* @param string $sAttCode
* @param bool $bLocalize
*
@@ -1262,11 +1260,11 @@ abstract class DBObject implements iDisplay
/**
* Get the value as it must be in the edit areas (forms)
*
*
* Makes a raw text representation of the value.
*
* @internal
*
*
* @param string $sAttCode
*
* @return int|mixed|string
@@ -1296,7 +1294,7 @@ abstract class DBObject implements iDisplay
else
{
$sEditValue = 0;
}
}
}
else
{
@@ -1312,14 +1310,14 @@ abstract class DBObject implements iDisplay
/**
* Get $sAttCode formatted as XML
*
*
* The returned value is a text that is suitable for insertion into an XML node.
* Depending on the type of attribute, the returned text is either:
* * A literal, with XML entities already escaped,
* * XML
*
* @api
*
*
* @param string $sAttCode
* @param bool $bLocalize
*
@@ -1357,10 +1355,10 @@ abstract class DBObject implements iDisplay
}
/**
*
*
* @see GetAsHTML()
* @see GetOriginal()
*
*
* @param string $sAttCode
* @param bool $bLocalize
*
@@ -1535,7 +1533,7 @@ abstract class DBObject implements iDisplay
/**
* @internal
*
*
* @param string $sClass
*
* @return mixed
@@ -1590,7 +1588,7 @@ abstract class DBObject implements iDisplay
* Get the id
*
* @api
*
*
* @return string|null
*/
public function GetKey()
@@ -1601,7 +1599,7 @@ abstract class DBObject implements iDisplay
/**
* Primary key Setter
* Usable only for not yet persisted DBObjects
*
*
* @internal
*
* @param int $iNewKey the desired identifier
@@ -1614,7 +1612,7 @@ abstract class DBObject implements iDisplay
{
throw new CoreException("An object id must be an integer value ($iNewKey)");
}
if ($this->m_bIsInDB && !empty($this->m_iKey) && ($this->m_iKey != $iNewKey))
{
throw new CoreException("Changing the key ({$this->m_iKey} to $iNewKey) on an object (class {".get_class($this).") wich already exists in the Database");
@@ -1624,7 +1622,7 @@ abstract class DBObject implements iDisplay
/**
* Get the icon representing this object
*
*
* @api
*
* @param boolean $bImgTag If true the result is a full IMG tag (or an empty string if no icon is defined)
@@ -1714,7 +1712,7 @@ abstract class DBObject implements iDisplay
*
* Returns the label as defined in the dictionary for the language of the current user
*
* @api
* @api
*
* @return string (empty for default name scheme)
*/
@@ -1781,7 +1779,7 @@ abstract class DBObject implements iDisplay
/**
* Helper to get the state
*
*
* @api
*
* @return mixed|string '' if no state attribute, object representing its value otherwise
@@ -1803,9 +1801,9 @@ abstract class DBObject implements iDisplay
/**
* Get the label (raw text) of the current state
* helper for MetaModel::GetStateLabel()
*
*
* @api
*
*
* @return mixed|string
*
* @throws ArchivedObjectException
@@ -1852,7 +1850,7 @@ abstract class DBObject implements iDisplay
* Define attributes read-only from the end-user perspective
*
* @return array|null List of attcodes
*/
*/
public static function GetReadOnlyAttributes()
{
return null;
@@ -1861,14 +1859,14 @@ abstract class DBObject implements iDisplay
/**
* Get predefined objects
*
*
* The predefined objects will be synchronized with the DB at each install/upgrade
* As soon as a class has predefined objects, then nobody can create nor delete objects
*
* @internal
*
* @return array An array of id => array of attcode => php value(so-called "real value": integer, string, ormDocument, DBObjectSet, etc.)
*/
*/
public static function GetPredefinedObjects()
{
return null;
@@ -1997,7 +1995,7 @@ abstract class DBObject implements iDisplay
* Note: Attributes (and flags) from the target state and the transition are combined.
*
* @internal
*
*
* @param string $sStimulus
* @param string $sOriginState Default is current state
*
@@ -2197,7 +2195,7 @@ abstract class DBObject implements iDisplay
/**
* @internal
*
*
* @throws \CoreException
* @throws \OQLException
*
@@ -4929,7 +4927,7 @@ abstract class DBObject implements iDisplay
{
if (is_null($sWorkingTimeComputer))
{
$sWorkingTimeComputer = class_exists('SLAComputation') ? 'SLAComputation' : 'DefaultWorkingTimeComputer';
$sWorkingTimeComputer = MetaModel::GetWorkingTime(get_class($this));
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetOpenDuration');
@@ -5323,7 +5321,7 @@ abstract class DBObject implements iDisplay
// Keep track of link changes
//
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_DETAILS) == 0) continue;
$iLinkSetOwnerId = $this->Get($sExtKeyAttCode);
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, 'CMDBChangeOpSetAttributeLinksTune');
if ($oMyChangeOp)
@@ -5520,27 +5518,6 @@ abstract class DBObject implements iDisplay
set_time_limit(intval($iPreviousTimeLimit));
}
/**
* Caching relying on an object set is not efficient since 2.0.3
* Use GetSynchroData instead
*
* Get all the synchro replica related to this object
*
* @internal
* @deprecated
*
* @return DBObjectSet Set with two columns: R=SynchroReplica S=SynchroDataSource
* @throws \OQLException
*/
public function GetMasterReplica()
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
$sOQL = "SELECT replica,datasource FROM SynchroReplica AS replica JOIN SynchroDataSource AS datasource ON replica.sync_source_id=datasource.id WHERE replica.dest_class = :dest_class AND replica.dest_id = :dest_id";
$oReplicaSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array() /* order by*/, array('dest_class' => get_class($this), 'dest_id' => $this->GetKey()));
return $oReplicaSet;
}
/**
* Get all the synchro data related to this object
*

View File

@@ -236,78 +236,6 @@ abstract class DBSearch
*/
abstract public function IsAny();
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function Describe()
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function DescribeConditionPointTo($sExtKeyAttCode, $aPointingTo)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function DescribeConditionRefBy($sForeignClass, $sForeignExtKeyAttCode)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function DescribeConditionRelTo($aRelInfo)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function DescribeConditions()
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @deprecated use ToOQL() instead
* @return string
*/
public function __DescribeHTML()
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use ToOQL() instead');
return 'deprecated - use ToOQL() instead';
}
/**
* @internal
* @return mixed
@@ -1716,16 +1644,6 @@ abstract class DBSearch
return $this->ToOQL(true);
}
/**
* @return array{\VariableExpression}
*
* @deprecated use DBSearch::GetExpectedArguments() instead
*/
public function ListParameters(): array
{
return $this->GetExpectedArguments();
}
/**
* Get parameters from the condition expression(s)
*

View File

@@ -114,9 +114,6 @@ class EMail implements iEMail
* @param string $sSerializedMessage The serialized representation of the message
*
* @return \Email
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
public static function UnSerializeV2($sSerializedMessage)
{

View File

@@ -110,7 +110,7 @@ class InlineImage extends DBObject
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
$iOrgId = $oItem->Get($sAttCode);
@@ -146,7 +146,7 @@ class InlineImage extends DBObject
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
// Second: check that the organization CAN be fetched from the current user
@@ -156,7 +156,7 @@ class InlineImage extends DBObject
$aCallSpec = array($sClass, 'MapContextParam');
if (is_callable($aCallSpec))
{
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
{
// OK - try it
@@ -192,7 +192,7 @@ class InlineImage extends DBObject
if (!is_null($iTransactionId))
{
// Attach new (temporary) inline images
$sTempId = utils::GetUploadTempId($iTransactionId);
// The object is being created from a form, check if there are pending inline images for this object
$sOQL = 'SELECT InlineImage WHERE temp_id = :temp_id';
@@ -366,10 +366,10 @@ CombodoInlineImage.FixImagesWidth();
JS
;
}
return $sJS;
}
/**
* Check if an the given mimeType is an image that can be processed by the system
*
@@ -382,7 +382,7 @@ JS
public static function IsImage($sMimeType)
{
if (!function_exists('gd_info')) return false; // no image processing capability on this system
$bRet = false;
$aInfo = gd_info(); // What are the capabilities
switch($sMimeType)
@@ -390,19 +390,19 @@ JS
case 'image/gif':
return $aInfo['GIF Read Support'];
break;
case 'image/jpeg':
return $aInfo['JPEG Support'];
break;
case 'image/png':
return $aInfo['PNG Support'];
break;
}
return $bRet;
}
/**
* Resize an image so that it fits the maximum width/height defined in the config file
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
@@ -444,7 +444,7 @@ JS
}
return $sRet;
}
/**
* Get the fragment of javascript needed to complete the initialization of
* CKEditor when creating/modifying an object

View File

@@ -399,6 +399,32 @@ abstract class MetaModel
return null;
}
final public static function GetDefaultWorkingTime()
{
return 'DefaultWorkingTimeComputer';
}
/**
* @param string $sClass
*
* @return string the working time class
* @throws \CoreException
* @since 3.3.0
*/
final public static function GetWorkingTime($sClass)
{
self::_check_subclass($sClass);
if (array_key_exists('working_time', self::$m_aClassParams[$sClass])) {
return self::$m_aClassParams[$sClass]['working_time'];
} else {
$sParentClass = self::GetParentPersistentClass($sClass);
if (strlen($sParentClass) > 0) {
return self::GetWorkingTime($sParentClass);
}
}
return self::GetDefaultWorkingTime();
}
/**
* @param string $sClass
*
@@ -2105,55 +2131,6 @@ abstract class MetaModel
*/
private static $m_aRelationInfos = array();
/**
* @deprecated Use EnumRelationsEx instead
*
* @param string $sClass
*
* @return array multitype:string unknown |Ambigous <string, multitype:>
* @throws \CoreException
* @throws \Exception
* @throws \OQLException
*/
public static function EnumRelations($sClass = '')
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('Use EnumRelationsEx instead');
$aResult = array_keys(self::$m_aRelationInfos);
if (!empty($sClass)) {
// Return only the relations that have a meaning (i.e. for which at least one query is defined)
// for the specified class
$aClassRelations = array();
foreach ($aResult as $sRelCode) {
$aQueriesDown = self::EnumRelationQueries($sClass, $sRelCode);
if (count($aQueriesDown) > 0) {
$aClassRelations[] = $sRelCode;
}
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
if ($sRelCode == 'impacts') {
$aQueriesUp = self::EnumRelationQueries($sClass, 'impacts', false);
if (count($aQueriesUp) > 0)
{
$aClassRelations[] = 'depends on';
}
}
}
return $aClassRelations;
}
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
if (in_array('impacts', $aResult))
{
$aResult[] = 'depends on';
}
return $aResult;
}
/**
* @param string $sClass
*
@@ -5143,7 +5120,7 @@ abstract class MetaModel
*/
protected static function DBCreateViews()
{
[$aErrors, $aSugFix] = self::DBCheckViews();
[$aErrors, $aSugFix] = self::DBCleanLegacyViews();
foreach($aSugFix as $sClass => $aTarget)
{
@@ -5789,18 +5766,18 @@ abstract class MetaModel
/**
* @deprecated 2.7.0 N°2369 Method will not be removed any time soon as we still need to drop view if the instance is migrating from an iTop 2.x to an iTop 3.0 or newer, even if they skip iTop 3.0.
* @since 3.0.0 Does not recreate SQL views, only drops them. Method has not been renamed to avoid regressions
* @internal
* @deprecated will be remove when 2.7 will not be supported anymore
*
* @return array
* @throws \CoreException
* @throws \Exception
* @throws \MissingQueryArgument
*/
public static function DBCheckViews()
public static function DBCleanLegacyViews()
{
$aErrors = array();
$aSugFix = array();
$aErrors = [];
$aSugFix = [];
// Reporting views (must be created after any other table)
//
@@ -5815,7 +5792,7 @@ abstract class MetaModel
}
}
return array($aErrors, $aSugFix);
return [$aErrors, $aSugFix];
}
/**
@@ -7027,7 +7004,7 @@ abstract class MetaModel
* @param array $aParams
* @param bool $bAllowAllData
*
* @return \DBObject
* @return \DBObject|null
* @throws \OQLException
*/
public static function GetObjectFromOQL($sQuery, $aParams = null, $bAllowAllData = false)
@@ -7509,42 +7486,6 @@ abstract class MetaModel
SetupUtils::rrmdir(utils::GetCachePath($sEnvironment));
}
/**
* @internal
* @param string $sEnvironmentId
* @deprecated 3.2.1
*/
public static function ResetCache($sEnvironmentId = null)
{
if (is_null($sEnvironmentId))
{
$sEnvironmentId = MetaModel::GetEnvironmentId();
}
$sAppIdentity = 'itop-'.$sEnvironmentId;
require_once(APPROOT.'/core/dict.class.inc.php');
Dict::ResetCache($sAppIdentity);
if (function_exists('apc_delete'))
{
foreach(self::GetCacheEntries($sEnvironmentId) as $sKey => $aAPCInfo)
{
$sAPCKey = $aAPCInfo['info'];
apc_delete($sAPCKey);
}
}
require_once(APPROOT.'core/userrights.class.inc.php');
UserRights::FlushPrivileges();
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
if (function_exists('opcache_reset'))
{
// Zend opcode cache
opcache_reset();
}
}
/**
* Given a field spec, get the most relevant (unique) representation
* Examples for a user request:
@@ -7709,7 +7650,6 @@ abstract class MetaModel
'iLoginUIExtension',
'iPreferencesExtension',
'iApplicationUIExtension',
'iApplicationObjectExtension',
'iPopupMenuExtension',
'iPageUIBlockExtension',
'iBackofficeLinkedScriptsExtension',

View File

@@ -495,8 +495,8 @@ class OqlObjectQuery extends OqlQuery
{
throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sSourceQuery, $oRightField->GetParentDetails(), array_keys($aAliases));
}
$aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], 'AttributeExternalKey');
$aObjKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], 'AttributeObjectKey');
$aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeExternalKey::class);
$aObjKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeObjectKey::class);
$aAllKeys = array_merge($aExtKeys, $aObjKeys);
if (!array_key_exists($sExtKeyAttCode, $aAllKeys))
{
@@ -557,7 +557,7 @@ class OqlObjectQuery extends OqlQuery
}
$aAttList = $oModelReflection->ListAttributes($aAliases[$sFromClass]);
$sAttType = $aAttList[$sExtKeyAttCode];
if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, 'AttributeHierarchicalKey') && ($sAttType != 'AttributeHierarchicalKey'))
if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class) && ($sAttType != \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class))
{
throw new OqlNormalizeException("The specified tree operator $sOperator is not applicable to the key", $sSourceQuery, $oLeftField->GetNameDetails());
}

View File

@@ -240,25 +240,6 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
return $aRet;
}
/**
* @param bool $bWithId
* @return array
* @deprecated Since iTop 2.4, use foreach($this as $oItem){} instead
*/
public function ToArray($bWithId = true)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use foreach($this as $oItem){} instead');
$aRet = array();
foreach ($this as $oItem) {
if ($bWithId) {
$aRet[$oItem->GetKey()] = $oItem;
} else {
$aRet[] = $oItem;
}
}
return $aRet;
}
/**
* @param string $sAttCode
* @param bool $bWithId
@@ -532,6 +513,17 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
{
$bUpdateFromDelta = true;
}
} else {
//@since 3.2.2 N°2364 - API : remove old linkedset persistance
/* Goo pattern to use:
* $oCISet = $oTicket->Get(functioncis_list);
* $oCISet->AddItem(MetaModel::NewObject(lnkFunctionCIToTicket, array(ci_id=> 12345));
* $oCISet->RemoveItem(123456);
* $oTicket->Set(functionalcis_list, $oCISet);
*/
if (!ContextTag::Check(ContextTag::TAG_SETUP)) {
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('old pattern - please get previous value of the linked set, modify it and set it back to the host object');
}
}
if ($bUpdateFromDelta)
@@ -547,7 +539,6 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
else
{
// For backward compatibility reasons, let's rebuild a delta...
// Reset the delta
$this->iCursor = 0;
$this->aAdded = array();

View File

@@ -289,7 +289,7 @@ class ormStopWatch
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
if ($sWorkingTimeComputer == '')
{
$sWorkingTimeComputer = class_exists('SLAComputation') ? 'SLAComputation' : 'DefaultWorkingTimeComputer';
$sWorkingTimeComputer = MetaModel::GetWorkingTime(get_class($oObject));
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetDeadline');
@@ -318,7 +318,7 @@ class ormStopWatch
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
if ($sWorkingTimeComputer == '')
{
$sWorkingTimeComputer = class_exists('SLAComputation') ? 'SLAComputation' : 'DefaultWorkingTimeComputer';
$sWorkingTimeComputer = MetaModel::GetWorkingTime(get_class($oObject));
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetOpenDuration');

View File

@@ -142,7 +142,9 @@ abstract class UserRightsAddOnAPI
$oFilter = new DBObjectSearch($sClass);
$oListExpr = ListExpression::FromScalars($aAllowedOrgs);
$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
$oNullCondition = new FunctionExpression('ISNULL', [$oExpression]);
$oInCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
$oCondition = $oNullCondition->LogOr($oInCondition);
$oFilter->AddConditionExpression($oCondition);
if ($this->HasSharing())

View File

@@ -3,7 +3,7 @@
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -105,7 +105,7 @@ abstract class ValueSetDefinition
/**
* Set of existing values for an attribute, given a search filter
* Set of existing values for an attribute, given a search filter
*
* @package iTopORM
*/
@@ -125,7 +125,7 @@ class ValueSetObjects extends ValueSetDefinition
/**
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
*/
*/
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
{
$this->m_sContains = '';
@@ -146,17 +146,6 @@ class ValueSetObjects extends ValueSetDefinition
$this->m_bIsLoaded = false;
}
/**
* @deprecated use SetCondition instead
*
* @param \DBSearch $oFilter
*/
public function AddCondition(DBSearch $oFilter)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use SetCondition instead');
$this->SetCondition($oFilter);
}
public function SetCondition(DBSearch $oFilter)
{
$this->m_oExtraCondition = $oFilter;
@@ -457,7 +446,7 @@ class ValueSetObjects extends ValueSetDefinition
/**
* Fixed set values (could be hardcoded in the business model)
* Fixed set values (could be hardcoded in the business model)
*
* @package iTopORM
*/
@@ -542,7 +531,7 @@ class ValueSetEnum extends ValueSetDefinition
foreach (explode(",", $this->m_values) as $sVal)
{
$sVal = trim($sVal);
$sKey = $sVal;
$sKey = $sVal;
$aValues[$sKey] = $sVal;
}
}
@@ -613,7 +602,7 @@ class ValueSetRange extends ValueSetDefinition
/**
* Data model classes
* Data model classes
*
* @package iTopORM
*/
@@ -631,7 +620,7 @@ class ValueSetEnumClasses extends ValueSetEnum
{
// Call the parent to parse the additional values...
parent::LoadValues($aArgs);
// Translate the labels of the additional values
foreach($this->m_aValues as $sClass => $void)
{

View File

@@ -39,6 +39,23 @@
//
// .site-nav a { color:#BADA55!important; }
$ibo-shame--switch--width: 36px !default;
$ibo-shame--switch--height: 20px !default;
$ibo-shame--slider--background-color: $ibo-color-secondary-600 !default;
$ibo-shame--slider--before--height: 15px !default;
$ibo-shame--slider--before--width: 15px !default;
$ibo-shame--slider--before--background-color: $ibo-color-secondary-300 !default;
$ibo-shame--slider--is-checked--background-color: $ibo-color-primary-600 !default;
$ibo-shame--slider--is-focus--box-shadow: 0 0 1px $ibo-color-primary-600 !default;
$ibo-shame--slider--is-round--border-radius: 20px !default;
$ibo-shame--slider--is-round--before--border-radius: 7px !default;
// N°2847 - Recolor svg illustrations with iTop's primary color
.ibo-svg-illustration--container > svg *[fill="#6c63ff"]{
fill: $ibo-svg-illustration--fill;
@@ -56,8 +73,8 @@
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
width: $ibo-shame--switch--width;
height: $ibo-shame--switch--height;
vertical-align: baseline;
}
@@ -74,27 +91,27 @@
left: 0;
right: 0;
bottom: 0;
background-color: $ibo-color-secondary-600;
background-color: $ibo-shame--slider--background-color;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
height: $ibo-shame--slider--before--height;
width: $ibo-shame--slider--before--width;
left: 3px;
bottom: 3px;
background-color: $ibo-color-secondary-300;
background-color: $ibo-shame--slider--before--background-color;
transition: .4s;
}
input:checked + .slider {
background-color: $ibo-color-primary-600;
background-color: $ibo-shame--slider--is-checked--background-color;
}
input:focus + .slider {
box-shadow: 0 0 1px $ibo-color-primary-600;
box-shadow: $ibo-shame--slider--is-focus--box-shadow;
}
input:checked + .slider:before {
@@ -103,9 +120,9 @@ input:checked + .slider:before {
/* Rounded sliders */
.slider.round {
border-radius: 20px;
border-radius: $ibo-shame--slider--is-round--border-radius;
}
.slider.round:before {
border-radius: 7px;
border-radius: $ibo-shame--slider--is-round--before--border-radius;
}

View File

@@ -3,12 +3,14 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
.ibo-bulk--bulk-modify--incompatible-attribute {
$ibo-bulk--bulk-modify--incompatible-attribute--color--margin-right: $ibo-vendors-selectize--item--icon--margin-right !default;
$ibo-bulk--bulk-modify--incompatible-attribute--color: $ibo-color-information-500 !default;
.ibo-bulk--bulk-modify--incompatible-attribute {
&:before{
margin-right: $ibo-vendors-selectize--item--icon--margin-right;
margin-right: $ibo-bulk--bulk-modify--incompatible-attribute--color--margin-right;
@extend %fa-solid-base;
content: '\f05a';
color: $ibo-color-information-500;
color: $ibo-bulk--bulk-modify--incompatible-attribute--color;
}
}

View File

@@ -3,12 +3,16 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-linked-set--bulk-tooltip-info--content: '\f05a' !default;
$ibo-linked-set--bulk-tooltip-info--color: $ibo-color-information-500 !default;
$ibo-linked-set--bulk-tooltip-info--margin-right: $ibo-vendors-selectize--item--icon--margin-right !default;
.ibo-linked-set--bulk-tooltip-info {
font-size: $ibo-font-size-100;
@extend %ibo-font-ral-nor-100;
&:before{
margin-right: $ibo-vendors-selectize--item--icon--margin-right;
margin-right: $ibo-linked-set--bulk-tooltip-info--margin-right;
@extend %fa-solid-base;
content: '\f05a';
color: $ibo-color-information-500;
content: $ibo-linked-set--bulk-tooltip-info--content;
color: $ibo-linked-set--bulk-tooltip-info--color;
}
}

View File

@@ -16,7 +16,7 @@
@import "panel/all";
@import "pill/all";
@import "dashlet/all";
@import "add-to-dashboard";
@import "prop-within-details";
@import "caselog-entry-form-within-activity-panel";
@import "tab-container-within-panel";
@import "medallion-with-blocklist";

View File

@@ -3,13 +3,17 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-medallion-with-blocklist--icon--image--margin-x: auto !default;
$ibo-medallion-with-blocklist--icon--image--margin-y: 0 !default;
$ibo-medallion-with-blocklist--icon--description--margin-top: $ibo-spacing-400 !default;
.ibo-block-list--medallion{
flex-direction: column;
align-items: center;
> .ibo-medallion-icon--image{
margin: 0 auto;
margin: $ibo-medallion-with-blocklist--icon--image--margin-y $ibo-medallion-with-blocklist--icon--image--margin-x;
~ .ibo-medallion-icon--description{
margin-top: 12px;
margin-top: $ibo-medallion-with-blocklist--icon--description--margin-top;
}
}
> .ibo-medallion-icon--description{

View File

@@ -9,8 +9,4 @@
.ibo-details .ibo-prop--apply {
display: table-column;
}
.ibo-details {
margin-top: 5px;
}

View File

@@ -15,6 +15,13 @@ $ibo-panel-with-tab-container--margin-bottom: -1 * $ibo-panel--body--padding-bot
$ibo-panel-with-tab-container--tab-toggler--font-size--is-sticking: $ibo-font-size-100 !default;
$ibo-tab-container-within-panel--tabs-list--padding-top: $ibo-spacing-800 !default;
// I'm not sure where these values come from, might need to be replaced by variables
$ibo-tab-container-within-panel--tabs-list--min-width: calc(32px + 90px + 32px) !default;
$ibo-tab-container-within-panel--tabs-header--height: $ibo-spacing-800 !default;
$ibo-tab-container-within-panel--tabs--list--is-sticking--z-index: 10 !default;
$ibo-tab-container-within-panel--tabs--list--is-sticking--is-not-vertical--padding-left: $ibo-spacing-0 !default;
// Note: We use the child ">" selector to ensure this applies only to the child tab container, not another one that would be nested
.ibo-panel {
> .ibo-panel--body {
@@ -35,15 +42,15 @@ $ibo-panel-with-tab-container--tab-toggler--font-size--is-sticking: $ibo-font-si
flex-direction: row;
> .ibo-tab-container--tabs-list {
padding-top: 50px;
padding-top: $ibo-tab-container-within-panel--tabs-list--padding-top;
flex-direction: column;
height: auto;
padding-left: unset;
margin-right: unset;
min-width: calc(32px + 90px + 32px);
min-width: $ibo-tab-container-within-panel--tabs-list--min-width;
> .ibo-tab-container--tab-header {
height: 50px;
height: $ibo-tab-container-within-panel--tabs-header--height;
width: 100%;
justify-content: left;
@@ -68,12 +75,12 @@ $ibo-panel-with-tab-container--tab-toggler--font-size--is-sticking: $ibo-font-si
> .ibo-tab-container {
> .ibo-tab-container--tabs-list.ibo-is-sticking {
position: fixed;
z-index: 10;
z-index: $ibo-tab-container-within-panel--tabs--list--is-sticking--z-index;
}
&:not(.ibo-is-vertical){
> .ibo-tab-container--tabs-list.ibo-is-sticking {
padding-left: 0;
padding-left: $ibo-tab-container-within-panel--tabs--list--is-sticking--is-not-vertical--padding-left;
.ibo-tab-container--tab-toggler,
.ibo-tab-container--extra-tabs-list-toggler {

View File

@@ -3,8 +3,11 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-datatable-within-panel--panel-body--width: 100% !default;
.ibo-panel .ibo-panel--body{
.ibo-datatable{
width: 100%
width: $ibo-datatable-within-panel--panel-body--width;
}
}

View File

@@ -3,6 +3,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-object-details-with-tab-container--tab-list--padding-left: calc(#{$ibo-object-details--icon--spacing--as-medallion} + #{$ibo-object-details--icon--size} + #{$ibo-object-details--icon--spacing--as-medallion} - #{$ibo-tab-container--tab-toggler--padding-x}) !default;
// Note: We use the child ">" selector to ensure this applies only the child tab container, not another one that would be nested
.ibo-object-details.ibo-has-medallion-icon {
> .ibo-panel--body {
@@ -10,7 +12,7 @@
> .ibo-tab-container:not(.ibo-is-vertical) {
> .ibo-tab-container--tabs-list {
// Align tab toggler's title with the panel's title
padding-left: calc(#{$ibo-object-details--icon--spacing--as-medallion} + #{$ibo-object-details--icon--size} + #{$ibo-object-details--icon--spacing--as-medallion} - #{$ibo-tab-container--tab-toggler--padding-x});
padding-left: $ibo-object-details-with-tab-container--tab-list--padding-left;
}
}
}

View File

@@ -9,6 +9,12 @@ $ibo-dashlet--width--is-inline: auto !default;
$ibo-dashlet--elements-spacing-x: $ibo-spacing-600 !default;
$ibo-dashlet--elements-spacing-y: $ibo-spacing-600 !default;
$ibo-dashlet-blocker--z-index: 9 !default; /* To be above calendar links & all, but below .close-box (9) */
$ibo-dashlet-blocker--top: 0 !default;
$ibo-dashlet-blocker--left: 0 !default;
$ibo-dashlet-blocker--width: 100% !default;
$ibo-dashlet-blocker--height: 100% !default;
/* Rules */
.ibo-dashlet {
position: relative;
@@ -23,18 +29,13 @@ $ibo-dashlet--elements-spacing-y: $ibo-spacing-600 !default;
.ibo-dashlet--is-inline {
width: $ibo-dashlet--width--is-inline;
}
.ibo-details > .ibo-prop--apply {
display: table-column;
}
.ibo-details{
margin-top: 5px;
}
.ibo-dashlet-blocker{
position: absolute;
z-index: 9; /* To be above calendar links & all, but below .close-box (9) */
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: $ibo-dashlet-blocker--z-index;
top: $ibo-dashlet-blocker--top;
left: $ibo-dashlet-blocker--left;
width: $ibo-dashlet-blocker--width;
height: $ibo-dashlet-blocker--height;
cursor: not-allowed;
}

View File

@@ -24,6 +24,8 @@ $ibo-datatable--sort-order--color: $ibo-color-primary-600 !default;
$ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
$ibo-datatable--selected-result-count--padding-right: 0.2em !default;
$ibo-datatable--selected-result-count--padding-left: 0.1em !default;
/* CSS variables (can be changed directly from the browser) */
:root {
@@ -134,8 +136,8 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
}
.ibo-datatable--selected-count, .ibo-datatable--result-count{
padding-right: 0.2em;
padding-left: 0.1em;
padding-right: $ibo-datatable--selected-result-count--padding-right;
padding-left: $ibo-datatable--selected-result-count--padding-left;
}
//

View File

@@ -3,7 +3,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-image--image-view--min-height: 96px !default;
$ibo-input-image--image-view--min-height: $ibo-size-500 !default;
$ibo-input-image--image-view--background-color: $ibo-color-grey-200 !default;
$ibo-input-image--image-view--border-radius: $ibo-border-radius-500 !default;

View File

@@ -1,5 +1,14 @@
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-richtext-placeholder--height: $ibo-size-600 !default;
$ibo-input-richtext-placeholder--width: 100% !default;
.ibo-input-richtext-placeholder{
height: 200px;
width: 100%;
height: $ibo-input-richtext-placeholder--height;
width: $ibo-input-richtext-placeholder--width;
visibility: hidden;
}

View File

@@ -3,6 +3,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-select-icon--menu--icon--max-height: 100% !default;
$ibo-input-select-icon--menu--icon--max-width: 100% !default;
$ibo-input-select-icon--icon--padding-right: $ibo-spacing-200 !default;
$ibo-input-select-icon--menu--z-index: 21 !default;
@@ -16,8 +18,8 @@ $ibo-input-select-icon--menu--icon--margin-right: 10px !default;
display: inline-flex;
text-align: left;
>img{
max-height: 100%;
max-width: 100%;
max-height: $ibo-input-select-icon--menu--icon--max-height;
max-width: $ibo-input-select-icon--menu--icon--max-width;
padding-right: $ibo-input-select-icon--icon--padding-right;
}
>span{

View File

@@ -20,6 +20,7 @@ $ibo-input-select-selectize--item--active--background-color: $ibo-color-blue-100
$ibo-input-select-wrapper--width: 100% !default;
$ibo-input-select-wrapper--after--content: "\f0d7" !default;
$ibo-input-select-wrapper--after--right: 8px !default;
$ibo-input-select-wrapper--after--height: 28px !default;
$ibo-input-select-wrapper--after--margin-left: -16px !default;
@@ -32,6 +33,7 @@ $ibo-input-select--action-button--height: 28px !default;
$ibo-input-select--action-button--width: 23px !default;
$ibo-input-select--action-button--margin-top: $ibo-spacing-0 !default;
$ibo-input-select--action-button--margin-right: 3px !default;
$ibo-input-select--action-button--font-size: $ibo-font-size-100 !default;
$ibo-input-select--action-button--background-color: inherit !default;
$ibo-input-select--action-button--color: $ibo-color-grey-800 !default;
$ibo-input-select--action-button--padding-x: $ibo-spacing-100 !default;
@@ -57,7 +59,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
min-width: $ibo-input-select-selectize--value--min-midth !important;
input {
border-width: 0px;
border-width: 0;
color: inherit;
border-color: $ibo-color-white-100;
padding-left: $ibo-input-select--padding-x;
@@ -121,7 +123,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
.ibo-input-select-wrapper::after{
position: absolute;
z-index: 1;
content: "\f0d7";
content: $ibo-input-select-wrapper--after--content;
font-family: "Font Awesome 5 Free";
font-weight: 600;
@@ -145,7 +147,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
.ibo-input-select-wrapper--with-buttons:not(.ibo-input-select-autocomplete-wrapper)::after {
position: absolute;
z-index: 1;
content: "\f0d7";
content: $ibo-input-select-wrapper--after--content;
font-family: "Font Awesome 5 Free";
font-weight: 600;
cursor: pointer;
@@ -168,7 +170,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
margin-top: $ibo-input-select--action-button--margin-top;
margin-right: $ibo-input-select--action-button--margin-right;
font-size: $ibo-font-size-100;
font-size: $ibo-input-select--action-button--font-size;
background-color: $ibo-input-select--action-button--background-color;
color: $ibo-input-select--action-button--color;
padding: $ibo-input-select--action-button--padding-y $ibo-input-select--action-button--padding-x;

View File

@@ -8,6 +8,9 @@ $ibo-input-text--min-height: 12rem !default;
$ibo-input-text--padding-x: $ibo-spacing-400 !default;
$ibo-input-text--padding-y: 10px !default;
$ibo-input-text--export--width: 100% !default;
$ibo-input-text--export--min-height: 15em !default;
.ibo-input-text {
width: $ibo-input-text--width;
min-height: $ibo-input-text--min-height;
@@ -23,6 +26,6 @@ $ibo-input-text--padding-y: 10px !default;
}
.ibo-input-text--export {
width: 100%;
min-height: 15em;
width: $ibo-input-text--export--width;
min-height: $ibo-input-text--export--min-height;
}

View File

@@ -9,6 +9,8 @@ $ibo-toggler--wrapper--height: 20px !default;
$ibo-toggler--slider--border-radius: $ibo-border-radius-900 !default;
$ibo-toggler--slider--background-color: $ibo-color-secondary-600 !default;
$ibo-toggler--slider--before--left: 3px !default;
$ibo-toggler--slider--before--bottom: 3px !default;
$ibo-toggler--slider--before--height: 15px !default;
$ibo-toggler--slider--before--width: 15px !default;
$ibo-toggler--slider--before--border-radius: $ibo-border-radius-full !default;
@@ -46,8 +48,8 @@ $ibo-toggler--label--margin-left: 4px !default;
.ibo-toggler--slider:before {
content: "";
position: absolute;
left: 3px;
bottom: 3px;
left: $ibo-toggler--slider--before--left;
bottom: $ibo-toggler--slider--before--bottom;
height: $ibo-toggler--slider--before--height;
width: $ibo-toggler--slider--before--width;
border-radius: $ibo-toggler--slider--before--border-radius;

View File

@@ -27,6 +27,9 @@ $ibo-input--disabled--background-color: $ibo-color-grey-300 !default;
$ibo-input--placeholder--color: $ibo-color-grey-700 !default;
$ibo-input-wrapper--is-error--border-color: $ibo-color-red-600 !default;
$ibo-input-wrapper--vanilla--is-error--border: 0 !default;
$ibo-input-wrapper--vanilla--is-error--background-color: $ibo-color-transparent !default;
$ibo-field-validation: $ibo-color-red-700 !default;
$ibo-input--margin-x: $ibo-spacing-200 !default;
@@ -62,8 +65,8 @@ textarea.ibo-input{
border-color: $ibo-input-wrapper--is-error--border-color;
}
.ibo-input-vanilla input{
border: 0;
background-color: #11ffee00;
border: $ibo-input-wrapper--vanilla--is-error--border;
background-color: $ibo-input-wrapper--vanilla--is-error--background-color;
}
}
input.ibo-input-vanilla{

View File

@@ -10,6 +10,10 @@ $ibo-popover-menu--padding: $ibo-spacing-0 !default;
$ibo-popover-menu--toggler-visual-hint--margin-left: 0.5rem !default;
$ibo-popover-menu--section--height: 100% !default;
$ibo-popover-menu--section--margin-x: $ibo-spacing-0 !default;
$ibo-popover-menu--section--margin-y: $ibo-spacing-0 !default;
$ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !default;
.ibo-popover-menu {
@@ -35,8 +39,8 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
display: flex;
flex-direction: column;
align-self: flex-start;
margin: $ibo-spacing-0 $ibo-spacing-0;
width: 100%;
margin: $ibo-popover-menu--section--margin-y $ibo-popover-menu--section--margin-x;
width: $ibo-popover-menu--section--height;
white-space: nowrap;
overflow: hidden; /* To avoid first/last entries of the menu to have no border-radius on hover */

View File

@@ -6,6 +6,7 @@
@import "navigation-menu";
@import "top-bar";
@import "content";
@import "details";
@import "tab-container/tab-container";
@import "tab-container/tab";
@import "multi-column/multi-column";

View File

@@ -2,6 +2,9 @@
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-v-spacer--padding-top: 1em !default;
$ibo-side-content--background-color: $ibo-content-block--background-color !default;
$ibo-side-content--border-left: $ibo-content-block--border !default;
/* Note: We have to wrap it in the ID in order to overload its rules, otherwise, the ID takes over the simple CSS class... */
#ibo-center-container {
@@ -16,10 +19,10 @@
}
.ibo-v-spacer {
padding-top: 1em;
padding-top: $ibo-v-spacer--padding-top;
}
#ibo-side-content {
background-color: $ibo-content-block--background-color;
border-left: $ibo-content-block--border;
background-color: $ibo-side-content--background-color;
border-left: $ibo-side-content--border-left;
}

View File

@@ -0,0 +1,9 @@
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-details--margin-top: 5px !default;
.ibo-details {
margin-top: $ibo-details--margin-top;
}

View File

@@ -218,7 +218,8 @@ $ibo-navigation-menu--user-info--height--is-expanded: 100% !default;
.ibo-navigation-menu--body{
width: $ibo-navigation-menu--body--width-expanded;
.ibo-navigation-menu--toggler-bar{
/* Values are hardcoded to ease the animation and there's no point in overloading them */
.ibo-navigation-menu--toggler-bar{
&:nth-child(1){
top: 4px;
left: 7px;
@@ -412,6 +413,7 @@ $ibo-navigation-menu--user-info--height--is-expanded: 100% !default;
transition: all 0.2s linear;
background-color: $ibo-navigation-menu--body--text-color;
/* Values are hardcoded to ease the animation and there's no point in overloading them */
&:nth-child(1){
top: 0;
}

View File

@@ -18,6 +18,7 @@ $ibo-activity-entry--medallion--has-no-image--background-color: $ibo-color-blue-
$ibo-activity-entry--medallion--has-no-image--text-color: $ibo-color-white-100 !default;
$ibo-activity-entry--medallion--has-no-image--border: 1px solid $ibo-color-grey-200 !default;
$ibo-activity-entry--information--margin-to-side: $ibo-spacing-0 !default;
$ibo-activity-entry--information--margin-to-other-side: $ibo-activity-entry--medallion--diameter + $ibo-activity-entry--medallion--margin-with-information !default;
$ibo-activity-entry--main-information--padding-x: $ibo-spacing-500 !default;
@@ -88,7 +89,7 @@ $ibo-activity-panel--load-all-entries--is-hover--margin-left: ($ibo-activity-pan
margin-left: $ibo-activity-entry--medallion--margin-with-information;
}
.ibo-activity-entry--information{
margin-right: 0;
margin-right: $ibo-activity-entry--information--margin-to-side;
margin-left: $ibo-activity-entry--information--margin-to-other-side;
}
.ibo-activity-entry--main-information{
@@ -109,7 +110,7 @@ $ibo-activity-panel--load-all-entries--is-hover--margin-left: ($ibo-activity-pan
&:not(.ibo-is-current-user){
.ibo-activity-entry--information{
margin-right: $ibo-activity-entry--information--margin-to-other-side;
margin-left: 0;
margin-left: $ibo-activity-entry--information--margin-to-side;
}
/* Bubble tip on the left for last entry of the group */
&:last-child{

View File

@@ -104,6 +104,7 @@ $ibo-activity-panel--add-caselog-entry-button--icon--line-height: 33px !default;
$ibo-activity-panel--entry-forms-confirmation-explanation--spacing: $ibo-spacing-500 !default;
$ibo-activity-panel--entry-forms-confirmation-preference-input--spacing: 0.5rem !default;
$ibo-activity-panel--closed-cover--z-index: 2 !default;
$ibo-activity-panel--closed-cover--background-color: $ibo-activity-panel--header--background-color !default;
$ibo-activity-panel--open-icon--margin-left: 0.75rem !default;
@@ -433,14 +434,12 @@ $ibo-activity-panel--open-icon--margin-left: 0.75rem !default;
.ibo-activity-panel--closed-cover {
display: none;
position: absolute;
z-index: 2; // Above the compose button and all
// padding-top: 64px;
z-index: $ibo-activity-panel--closed-cover--z-index; // Above the compose button and all
top: 0;
bottom: 0;
left: 0;
right: 0;
@extend %ibo-fully-centered-content;
// align-items: flex-start;
background-color: $ibo-activity-panel--closed-cover--background-color;
cursor: pointer;
}

View File

@@ -11,7 +11,7 @@ $ibo-caselog-entry-form--actions--margin-top: $ibo-spacing-300 !default;
$ibo-caselog-entry-form--actions--margin-bottom: $ibo-caselog-entry-form--actions--margin-top !default;
$ibo-caselog-entry-form--lock-indicator--margin-top: $ibo-caselog-entry-form--padding-bottom !default;
$ibo-caselog-entry-form--lock-icon--size: 32px !default;
$ibo-caselog-entry-form--lock-icon--size: $ibo-size-350 !default;
$ibo-caselog-entry-form--lock-icon--text-color: $ibo-color-grey-50 !default;
$ibo-caselog-entry-form--lock-icon--background-color: $ibo-color-grey-800 !default;
$ibo-caselog-entry-form--lock-icon--border-radius: $ibo-border-radius-full !default;

View File

@@ -25,6 +25,10 @@ $ibo-dashboard-editor--delete-dashlet-icon--right: 9px !default;
$ibo-dashboard-editor--delete-dashlet-icon--padding: $ibo-spacing-100 6px !default;
$ibo-dashboard-editor--delete-dashlet-icon--z-index: 21 !default;
$ibo-dashlet--properties--padding-bottom: 20px !default;
$ibo-dashlet--properties--table--width: 100% !default;
$ibo-dashlet--properties--table--cell--margin-bottom: 14px !default;
.ibo-dashboard-editor--pane{
flex-grow: 1;
@@ -47,13 +51,13 @@ $ibo-dashboard-editor--delete-dashlet-icon--z-index: 21 !default;
.ibo-dashlet--properties{
display: flex;
flex-direction: column;
padding-bottom: 20px;
padding-bottom: $ibo-dashlet--properties--padding-bottom;
table{
width: 100%;
width: $ibo-dashlet--properties--table--width;
text-align: left;
td, th {
margin-bottom: 14px;
margin-bottom: $ibo-dashlet--properties--table--cell--margin-bottom;
.ibo-field {
@extend %ibo-font-size-100;

View File

@@ -7,8 +7,38 @@
$ibo-dashboard--grid--width: 100% !default;
$ibo-dashboard--grid--elements-spacing-x: $ibo-dashlet--elements-spacing-x !default;
$ibo-dashboard--grid--elements-spacing-y: $ibo-dashlet--elements-spacing-y !default;
$ibo-dashboard--grid--edit-mode--margin: 1px !default;
$ibo-dashboard--grid--edit-mode--border-color: $ibo-color-grey-400 !default;
$ibo-dashboard--grid--edit-mode--border: 2px $ibo-dashboard--grid--edit-mode--border-color dashed !default;
$ibo-dashboard--grid--edit-mode--width: 100% !default;
$ibo-dashboard--grid--edit-mode--min-height: 40px !default;
$ibo-dashboard--top-bar-padding-bottom: 20px !default;
$ibo-dashboard--selector--margin-left: $ibo-spacing-400 !default;
$ibo-dashboard--selector--margin-right: 1 !default;
$ibo-dashboard--selector--hover--background-color: $ibo-color-secondary-100 !default;
$ibo-dashboard--selector--hover--border-radius: $ibo-button--border-radius !default;
$ibo-dashboard--selector--selector-label--margin-x: 10px !default;
$ibo-dashboard--switch--width: 30px !default;
$ibo-dashboard--switch--height: $ibo-size-300 !default;
$ibo-dashboard--slider--before--content: "\f007" !default;
$ibo-dashboard--slider--before--font-size: $ibo-font-size-50 !default;
$ibo-dashboard--slider--before--color: $ibo-color-secondary-800 !default;
$ibo-dashboard--slider--before--right: 5px !default;
$ibo-dashboard--slider--before--bottom: 3px !default;
$ibo-dashboard--slider--after--content: "\f1ad" !default;
$ibo-dashboard--slider--after--font-size: $ibo-font-size-150 !default;
$ibo-dashboard--slider--after--color: $ibo-color-primary-600 !default;
$ibo-dashboard--slider--after--left: 6px !default;
$ibo-dashboard--slider--after--bottom: 1px !default;
/* Rules */
.ibo-dashboard--top-bar {
@extend %ibo-full-height-content;
@@ -30,18 +60,18 @@ $ibo-dashboard--top-bar-padding-bottom: 20px !default;
.ibo-dashboard--selector {
display: flex;
align-items: center;
margin-left: 12px;
margin-right: 1px;
margin-left: $ibo-dashboard--selector--margin-left;
margin-right: $ibo-dashboard--selector--margin-right;
&:hover {
background-color: $ibo-color-secondary-100;
border-radius: $ibo-button--border-radius;
background-color: $ibo-dashboard--selector--hover--background-color;
border-radius: $ibo-dashboard--selector--hover--border-radius;
}
.selector-label {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
margin-left: $ibo-dashboard--selector--selector-label--margin-x;
margin-right: $ibo-dashboard--selector--selector-label--margin-x;
vertical-align: super;
}
}
@@ -75,7 +105,7 @@ $ibo-dashboard--top-bar-padding-bottom: 20px !default;
margin: calc(-1 * #{$ibo-dashboard--grid--elements-spacing-y} / 2) calc(-1 * #{$ibo-dashboard--grid--elements-spacing-x} / 2); /* Because of the margin all around the dashlets, we need to compensate it */
min-width: 0;
/* Compensate negative margin on inner borders to simulate egal dashlets spacing between columns */
/* Compensate negative margin on inner borders to simulate equal dashlets spacing between columns */
&:not(:last-child) {
margin-right: 0;
}
@@ -85,10 +115,10 @@ $ibo-dashboard--top-bar-padding-bottom: 20px !default;
}
&.edit_mode {
margin: 1px;
border: 2px #ccc dashed;
width: 100%;
min-height: 40px;
margin: $ibo-dashboard--grid--edit-mode--margin;
border: $ibo-dashboard--grid--edit-mode--border;
width: $ibo-dashboard--grid--edit-mode--width;
min-height: $ibo-dashboard--grid--edit-mode--min-height;
}
}
@@ -98,8 +128,8 @@ $ibo-dashboard--top-bar-padding-bottom: 20px !default;
.ibo-dashboard--switch {
position: relative;
display: inline-block;
width: 30px;
height: 24px;
width: $ibo-dashboard--switch--width;
height: $ibo-dashboard--switch--height;
vertical-align: baseline;
}
@@ -119,31 +149,29 @@ $ibo-dashboard--top-bar-padding-bottom: 20px !default;
}
.ibo-dashboard--slider:before {
@extend %fa-solid-base;
content: $ibo-dashboard--slider--before--content;
font-size: $ibo-dashboard--slider--before--font-size;
color: $ibo-dashboard--slider--before--color;
position: absolute;
right: 5px;
bottom: 3px;
color: $ibo-color-secondary-800;
content: "\f007";
font-family: "Font Awesome 5 Free", serif;
font-size: $ibo-font-size-50;
font-weight: 900;
right: $ibo-dashboard--slider--before--right;
bottom: $ibo-dashboard--slider--before--bottom;
}
.ibo-dashboard--slider:after {
@extend %fa-solid-base;
content: $ibo-dashboard--slider--after--content;
font-size: $ibo-dashboard--slider--after--font-size;
color: $ibo-dashboard--slider--after--color;
position: absolute;
left: 6px;
bottom: 1px;
color: $ibo-color-primary-600;
content: "\f1ad";
font-family: "Font Awesome 5 Free", serif;
font-size: $ibo-font-size-150;
font-weight: 900;
left: $ibo-dashboard--slider--after--left;
bottom: $ibo-dashboard--slider--after--bottom;
}
input:checked + .ibo-dashboard--slider:before {
content: "\f1ad";
content: $ibo-dashboard--slider--after--content;
}
input:checked + .ibo-dashboard--slider:after {
content: "\f007";
content: $ibo-dashboard--slider--before--content;
}

View File

@@ -4,10 +4,15 @@
*/
$ibo-column--min-width: 300px !default;
$ibo-mini-column--min-width: 30px !default;
$ibo-column--padding-x: abs($ibo-multi-column--margin-x) !default;
$ibo-column--padding-y: $ibo-spacing-0 !default;
$ibo-mini-column--min-width: 30px !default;
$ibo-mini-column--padding-x: $ibo-column--padding-x !default;
$ibo-mini-column--padding-y: $ibo-column--padding-y !default;
$ibo-mini-column--button-margin-left: $ibo-spacing-0 !default;
$ibo-mini-column--button-margin-right: $ibo-spacing-0 !default;
$ibo-column--margin-bottom--is-last-element: $ibo-spacing-800 !default;
.ibo-column {
@@ -26,14 +31,14 @@ $ibo-column--margin-bottom--is-last-element: $ibo-spacing-800 !default;
min-width: $ibo-mini-column--min-width;
flex-grow: 1;
flex-shrink: 1;
padding: $ibo-column--padding-y $ibo-column--padding-x;
padding: $ibo-mini-column--padding-y $ibo-mini-column--padding-x;
flex-basis: 10%;
display: flex;
flex-direction: column;
>.ibo-button{
margin-left: 0;
margin-right: 0;
margin-left: $ibo-mini-column--button-margin-left;
margin-right: $ibo-mini-column--button-margin-right;
}
&:not(:last-child) {
margin-bottom: $ibo-column--margin-bottom--is-last-element;

View File

@@ -3,7 +3,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-multi-column--margin-x: -16px !default; /* This is to compensate columns padding and make the whole multicolumn align with the parent borders (cf. Bootstrap rows / cols) */
$ibo-multi-column--margin-x: -$ibo-spacing-500 !default; /* This is to compensate columns padding and make the whole multicolumn align with the parent borders (cf. Bootstrap rows / cols) */
$ibo-multi-column--margin-y: $ibo-spacing-0 !default;
.ibo-multi-column {

View File

@@ -16,6 +16,8 @@ $ibo-object-details--icon--spacing--as-medallion--is-sticking: $ibo-object-detai
$ibo-object-details--status-dot--size: 10px !default;
$ibo-object-details--status-dot--spacing: $ibo-spacing-300 !default;
$ibo-object-details--status-dot--border-radius: $ibo-border-radius-full !default;
$ibo-object-details--status--class--before--content: "(" !default;
$ibo-object-details--status--class--after--content: ")" !default;
$ibo-object-details--tag--sibling-spacing: $ibo-spacing-400 !default;
$ibo-object-details--tag--color: $ibo-panel--subtitle--color !default;
@@ -86,11 +88,11 @@ $ibo-object-details--header-right--padding-right--is-sticking: $ibo-spacing-300
display: inline-flex; /* To avoid having spaces around the class name due to the indentation */
&::before {
content: "(";
content: $ibo-object-details--status--class--before--content;
}
&::after {
content: ")";
content: $ibo-object-details--status--class--after--content;
}
}

View File

@@ -5,12 +5,13 @@
$ibo-wizard-container--padding: 10px $ibo-spacing-500 !default;
$ibo-wizard-container--background-color: $ibo-color-blue-200 !default;
$ibo-wizard-container--border-radius: $ibo-border-radius-300 !default;
$ibo-wizard-container--border-color: $ibo-color-blue-600 !default;
$ibo-wizard-container--border-width: 3px !default;
.ibo-wizard-container {
padding: $ibo-wizard-container--padding;
background: $ibo-wizard-container--background-color;
border-radius: $ibo-border-radius-300;
border-radius: $ibo-wizard-container--border-radius;
border-left: $ibo-wizard-container--border-width solid $ibo-wizard-container--border-color;
}

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