mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-14 16:04:10 +01:00
Compare commits
365 Commits
feature/fa
...
2.7.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fd9523c16 | ||
|
|
a4f6f6e877 | ||
|
|
94c604a6af | ||
|
|
6995a3c641 | ||
|
|
9865bf0779 | ||
|
|
d5449cca42 | ||
|
|
5d38d22c50 | ||
|
|
99d69493d1 | ||
|
|
c9bb628c30 | ||
|
|
08e8d15d78 | ||
|
|
7b59df216b | ||
|
|
cb5eab812e | ||
|
|
c9b73a7fe2 | ||
|
|
3b2da39469 | ||
|
|
fc22d91232 | ||
|
|
b10bcb976d | ||
|
|
5a43448644 | ||
|
|
77409eed99 | ||
|
|
83a70daf68 | ||
|
|
a49a4e6c2b | ||
|
|
7419749ba6 | ||
|
|
037dfe1df6 | ||
|
|
0b26d45014 | ||
|
|
4fd8177165 | ||
|
|
a2cdf214f0 | ||
|
|
013173019f | ||
|
|
9469681a0c | ||
|
|
c72cb7e70e | ||
|
|
9df92665e0 | ||
|
|
8ecebee511 | ||
|
|
35cd965360 | ||
|
|
e5dd51f637 | ||
|
|
0a6c82dfe1 | ||
|
|
24c0f4950f | ||
|
|
d4dbbc59d4 | ||
|
|
dc0cd44c79 | ||
|
|
6c6131ce03 | ||
|
|
e76728b2bf | ||
|
|
e946fc65fc | ||
|
|
0d8ff7bbac | ||
|
|
bf768311c2 | ||
|
|
a8c689c6c0 | ||
|
|
1990ccb5d8 | ||
|
|
e107be56e4 | ||
|
|
ed6df77cbb | ||
|
|
1ad28312ec | ||
|
|
f002aa04cd | ||
|
|
b86d70623e | ||
|
|
fe3467309d | ||
|
|
851ab9c356 | ||
|
|
aef3c2e609 | ||
|
|
6d13397ba1 | ||
|
|
c0c8a13864 | ||
|
|
cd9beec313 | ||
|
|
8295eaed90 | ||
|
|
5475b9fbbe | ||
|
|
6f8e7c7002 | ||
|
|
bc7c1b4744 | ||
|
|
4d8246c4d8 | ||
|
|
5c61d725e1 | ||
|
|
2c4cad4dac | ||
|
|
da45651121 | ||
|
|
d388ce9a06 | ||
|
|
47e71d8838 | ||
|
|
2b5973ec67 | ||
|
|
78396d8e4a | ||
|
|
9afc22bd8f | ||
|
|
264a8cd70a | ||
|
|
aa1834170b | ||
|
|
f94d67ab35 | ||
|
|
3048c8c41f | ||
|
|
246e4a9f50 | ||
|
|
6d58adb6dd | ||
|
|
5a0b5364d6 | ||
|
|
76eed2eba0 | ||
|
|
1ec671ef61 | ||
|
|
72716b7ec8 | ||
|
|
4f999de844 | ||
|
|
ea49c0a87c | ||
|
|
6cc971849b | ||
|
|
2405810864 | ||
|
|
fff46d99fc | ||
|
|
3a891f707c | ||
|
|
8b6ea43ebe | ||
|
|
90cf7502e8 | ||
|
|
c596fa2967 | ||
|
|
a45177410e | ||
|
|
9e96ea2873 | ||
|
|
1172159745 | ||
|
|
fa038ded3d | ||
|
|
e7ea1b831c | ||
|
|
4aff65f98b | ||
|
|
3c94974d9d | ||
|
|
fbd72b2783 | ||
|
|
4e95ca3c7b | ||
|
|
1114ed9562 | ||
|
|
34368fe795 | ||
|
|
0f016d7511 | ||
|
|
5ee6223434 | ||
|
|
d908827787 | ||
|
|
4cea418517 | ||
|
|
97965277c7 | ||
|
|
18ed5ed526 | ||
|
|
94c4f8c929 | ||
|
|
822922df5c | ||
|
|
cac7e94a67 | ||
|
|
6d019615d0 | ||
|
|
dbd58cfeb6 | ||
|
|
f65e14397c | ||
|
|
c696a81c3a | ||
|
|
845adf43c6 | ||
|
|
5916e4ea39 | ||
|
|
fbc0a898ae | ||
|
|
36f8e58e25 | ||
|
|
6a7dbb06b0 | ||
|
|
5721a324c1 | ||
|
|
7de6c72154 | ||
|
|
c0cee02351 | ||
|
|
bb674fb873 | ||
|
|
6136eadd31 | ||
|
|
87cb73c038 | ||
|
|
11d8547cef | ||
|
|
0998c73a1a | ||
|
|
471f66649a | ||
|
|
e8bf9cf688 | ||
|
|
4f88a0e7d2 | ||
|
|
c6b0e273e6 | ||
|
|
d9539f9d01 | ||
|
|
a3e309acb5 | ||
|
|
c06cbfd4a9 | ||
|
|
1d7e4e1a42 | ||
|
|
92a36dcfdd | ||
|
|
b37e74b407 | ||
|
|
0d49c605e2 | ||
|
|
7c2f8f4d93 | ||
|
|
1f76ff940d | ||
|
|
bb26e48d38 | ||
|
|
cf433f2f80 | ||
|
|
ae94e58a43 | ||
|
|
cda017fa4f | ||
|
|
dad22f6f83 | ||
|
|
9077f7ba37 | ||
|
|
957ff40f30 | ||
|
|
aff9c7748b | ||
|
|
e518d34bc9 | ||
|
|
f0141530b9 | ||
|
|
ce5096a896 | ||
|
|
23e0ed5e56 | ||
|
|
d412a52fcc | ||
|
|
3e18ad590f | ||
|
|
22111bf667 | ||
|
|
6d0c46595d | ||
|
|
d292a6b0c3 | ||
|
|
74702c8d06 | ||
|
|
e9c91d986d | ||
|
|
70a6b276ca | ||
|
|
f77361ceb2 | ||
|
|
75f4751b82 | ||
|
|
b56f2f56f1 | ||
|
|
68d44fa981 | ||
|
|
7e5307bd96 | ||
|
|
cd010afb48 | ||
|
|
0cf8d731bb | ||
|
|
189ca3c555 | ||
|
|
1e1f1f78bf | ||
|
|
1494604740 | ||
|
|
583ab98210 | ||
|
|
88d743b1cc | ||
|
|
7ac4bc95bb | ||
|
|
d431811725 | ||
|
|
7512f721e9 | ||
|
|
bdfe3a3b35 | ||
|
|
5cf391c3bb | ||
|
|
4c1df9927d | ||
|
|
74003f12c1 | ||
|
|
3bc12b0434 | ||
|
|
02a0969b53 | ||
|
|
d78a25ee4e | ||
|
|
7a6a3d1ac0 | ||
|
|
6b32be0899 | ||
|
|
33c2168af2 | ||
|
|
ae021064a4 | ||
|
|
0a61169326 | ||
|
|
d7e5705520 | ||
|
|
35a8b501c9 | ||
|
|
8fa616f440 | ||
|
|
5829e698da | ||
|
|
df347b90e5 | ||
|
|
bb861aa262 | ||
|
|
f9ac07830e | ||
|
|
0f4c7ac90f | ||
|
|
0687f9a0a9 | ||
|
|
6e75ab2889 | ||
|
|
b90d29d448 | ||
|
|
1f78bf4119 | ||
|
|
5d25e77189 | ||
|
|
d9dabf25da | ||
|
|
73af605892 | ||
|
|
f70f95c119 | ||
|
|
53c50cf6fc | ||
|
|
f19d1472c5 | ||
|
|
eef00502cd | ||
|
|
0b1caac195 | ||
|
|
e900a44d47 | ||
|
|
a3de9fa898 | ||
|
|
8b0154cc62 | ||
|
|
1a225bf55b | ||
|
|
24d19cd8d6 | ||
|
|
c25a4a7346 | ||
|
|
20fb7b241f | ||
|
|
a0553e1195 | ||
|
|
f40141072a | ||
|
|
c759856a61 | ||
|
|
237b181eec | ||
|
|
48957fd2f0 | ||
|
|
8a99c37200 | ||
|
|
d388c3fd3d | ||
|
|
1b8e48539d | ||
|
|
104beff158 | ||
|
|
4712569a36 | ||
|
|
2392f4a902 | ||
|
|
a0f28a9098 | ||
|
|
6df622e8ed | ||
|
|
54eb9d081b | ||
|
|
9f60f27636 | ||
|
|
ba59643f52 | ||
|
|
01c02a75a8 | ||
|
|
f5b3e5f341 | ||
|
|
9b825cb529 | ||
|
|
3f326f0913 | ||
|
|
ec86bd246a | ||
|
|
aa90d5b6ab | ||
|
|
53d2129bd1 | ||
|
|
00e8c11ec2 | ||
|
|
617b6b991f | ||
|
|
b3ea1050eb | ||
|
|
ca98066d68 | ||
|
|
352f7c8675 | ||
|
|
df5d514c28 | ||
|
|
16663797b2 | ||
|
|
4099376472 | ||
|
|
6d3118d9e9 | ||
|
|
4c585614cd | ||
|
|
9674378c56 | ||
|
|
9e314ba77b | ||
|
|
cdd7dcdc5c | ||
|
|
34bed5ec4f | ||
|
|
3ea82e37d5 | ||
|
|
596c62aec8 | ||
|
|
265415030e | ||
|
|
3d26f28f9b | ||
|
|
0abec767e3 | ||
|
|
9fd10bd73e | ||
|
|
95dafc87c0 | ||
|
|
fe1790793e | ||
|
|
ddb95dc64e | ||
|
|
f6f9ee26e1 | ||
|
|
21faa92904 | ||
|
|
622f40c06c | ||
|
|
964134cb60 | ||
|
|
72f498a63b | ||
|
|
f9a1f68295 | ||
|
|
9b67b0b9d5 | ||
|
|
f798ef1d76 | ||
|
|
754946bf62 | ||
|
|
a6580e3cd8 | ||
|
|
da6621f2ff | ||
|
|
f2d42a7e56 | ||
|
|
d01e4b4a85 | ||
|
|
f57d1f1de3 | ||
|
|
a3f122184c | ||
|
|
16fcddc249 | ||
|
|
2a9c9be36a | ||
|
|
ca3aae23a1 | ||
|
|
4dd384e418 | ||
|
|
80e7313b24 | ||
|
|
183c3c1baf | ||
|
|
160c52fe81 | ||
|
|
5f0a820b4a | ||
|
|
03ef4246bf | ||
|
|
534e7cf59d | ||
|
|
e1645f6903 | ||
|
|
61a2d200b4 | ||
|
|
3d6bbe4029 | ||
|
|
44eda676a3 | ||
|
|
eac6f07823 | ||
|
|
424e2a5745 | ||
|
|
0ef4fee0b4 | ||
|
|
1d45eff9b0 | ||
|
|
8e97279401 | ||
|
|
932ef780fd | ||
|
|
59424c3126 | ||
|
|
562dd8fc21 | ||
|
|
cf745554fb | ||
|
|
e909eac98e | ||
|
|
5e42efc3ec | ||
|
|
eb1d56f439 | ||
|
|
644e1ac4f6 | ||
|
|
4c88dbd9ac | ||
|
|
11d2e62e67 | ||
|
|
58b27a9daa | ||
|
|
caf939bf58 | ||
|
|
8c217fdac9 | ||
|
|
6b80bbeaa2 | ||
|
|
134736dce5 | ||
|
|
4b870bcf1e | ||
|
|
dd8a4a0082 | ||
|
|
c2607c4223 | ||
|
|
1fb0911710 | ||
|
|
b348e0ff27 | ||
|
|
4646a05c7a | ||
|
|
c5527c106c | ||
|
|
5eac1b8730 | ||
|
|
0de15d040f | ||
|
|
c4ae94fd4c | ||
|
|
1e8818984e | ||
|
|
a023f73509 | ||
|
|
6f0e1a7f47 | ||
|
|
0ef9bb1a47 | ||
|
|
71ceedc4bb | ||
|
|
73c3c1249f | ||
|
|
88a10dba28 | ||
|
|
001e222f67 | ||
|
|
af8bcdc242 | ||
|
|
f4c7afc148 | ||
|
|
b19c73a36e | ||
|
|
5fe0d0b94f | ||
|
|
f8d435d5f3 | ||
|
|
f15ef36fd1 | ||
|
|
64b25c4daa | ||
|
|
d0ba0d193b | ||
|
|
8e6e2432d3 | ||
|
|
83ec19dfca | ||
|
|
6e619f2c35 | ||
|
|
163ba41e8d | ||
|
|
ec143c43db | ||
|
|
cacf0004a5 | ||
|
|
cb39541e2a | ||
|
|
b9ddadeb44 | ||
|
|
11e811cc4b | ||
|
|
e422adb0d0 | ||
|
|
e02d9f3f0e | ||
|
|
e831d66b76 | ||
|
|
6fa2d47780 | ||
|
|
e691454339 | ||
|
|
92997e3e57 | ||
|
|
631b38a160 | ||
|
|
7ce5712b71 | ||
|
|
61137a6f65 | ||
|
|
0080a2e733 | ||
|
|
7f4fddb378 | ||
|
|
a71cb97db3 | ||
|
|
4c99f497cc | ||
|
|
0205cdf713 | ||
|
|
39fc59a8b2 | ||
|
|
107c9adf60 | ||
|
|
d29880b1b8 | ||
|
|
2d156bd77b | ||
|
|
d122dbfdd6 | ||
|
|
46d58e6512 | ||
|
|
93a138606f | ||
|
|
70074ee1cb | ||
|
|
d28ccb264f | ||
|
|
8ab38854a8 | ||
|
|
0001e8ffc4 |
@@ -77,20 +77,24 @@ Then, **for a method** of an eligible class:
|
||||
|
||||
: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
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
```
|
||||
cd .doc
|
||||
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||
```
|
||||
|
||||
## Generation
|
||||
`./bin/build-doc-object-manipulation` and `./bin/build-doc-extensions` contains examples of doc. generation, beware: they have to be called from the .doc directory:
|
||||
```shell
|
||||
cd /path/to/itop/.doc
|
||||
./bin/build-doc-object-manipulation
|
||||
```
|
||||
|
||||
the resulting documentation is written into `data/phpdocumentor/output`
|
||||
|
||||
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).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && ./vendor/bin/phpdoc -c ./phpdoc-extensions.dist.xml -vvv
|
||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && .doc/vendor/bin/phpdoc -c .doc/phpdoc-extensions.dist.xml -vvv
|
||||
|
||||
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||
cd ../data/phpdocumentor/output/extensions/ && for i in $(ls | grep [A-Z]); do mv -i $i $(echo $i | tr 'A-Z' 'a-z'); done
|
||||
cd data/phpdocumentor/output/extensions/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 MiB |
@@ -11,7 +11,7 @@ tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = true
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = 300
|
||||
ij_wrap_on_typing = true
|
||||
@@ -78,7 +78,7 @@ ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
ij_editorconfig_spaces_around_assignment_operators = true
|
||||
|
||||
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
||||
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul, phpunit.xml.dist}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_smart_tabs = true
|
||||
@@ -280,17 +280,16 @@ ij_javascript_while_brace_force = always
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
|
||||
[{*.ctp, *.hphp, *.inc, *.module, *.php, *.php4, *.php5, *.phtml}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = true
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_group_field_declarations = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_key_value_pairs = true
|
||||
ij_php_align_match_arm_bodies = false
|
||||
ij_php_align_multiline_array_initializer_expression = true
|
||||
ij_php_align_multiline_binary_operation = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
@@ -299,7 +298,6 @@ ij_php_align_multiline_for = true
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_parameters_in_calls = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_named_arguments = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_align_phpdoc_param_names = false
|
||||
ij_php_anonymous_brace_style = end_of_line
|
||||
@@ -419,7 +417,6 @@ ij_php_see_weight = 3
|
||||
ij_php_since_weight = 28
|
||||
ij_php_sort_phpdoc_elements = true
|
||||
ij_php_space_after_colon = true
|
||||
ij_php_space_after_colon_in_enum_backed_type = true
|
||||
ij_php_space_after_colon_in_named_argument = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_after_comma = true
|
||||
@@ -434,7 +431,6 @@ ij_php_space_before_catch_parentheses = true
|
||||
ij_php_space_before_class_left_brace = true
|
||||
ij_php_space_before_closure_left_parenthesis = true
|
||||
ij_php_space_before_colon = true
|
||||
ij_php_space_before_colon_in_enum_backed_type = false
|
||||
ij_php_space_before_colon_in_named_argument = false
|
||||
ij_php_space_before_colon_in_return_type = false
|
||||
ij_php_space_before_comma = false
|
||||
@@ -470,7 +466,6 @@ ij_php_spaces_around_equality_operators = true
|
||||
ij_php_spaces_around_logical_operators = true
|
||||
ij_php_spaces_around_multiplicative_operators = true
|
||||
ij_php_spaces_around_null_coalesce_operator = true
|
||||
ij_php_spaces_around_pipe_in_union_type = false
|
||||
ij_php_spaces_around_relational_operators = true
|
||||
ij_php_spaces_around_shift_operators = true
|
||||
ij_php_spaces_around_unary_operator = false
|
||||
@@ -545,6 +540,7 @@ ij_html_space_after_tag_name = false
|
||||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
ij_html_uniform_ident = false
|
||||
|
||||
[{*.markdown,*.md}]
|
||||
ij_visual_guides = none
|
||||
|
||||
48
.gitattributes
vendored
Normal file
48
.gitattributes
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.bash text eol=lf
|
||||
*.bat text eol=lf
|
||||
*.cmd text eol=lf
|
||||
*.css text eol=lf
|
||||
*.scss text eol=lf
|
||||
*.dist text eol=lf
|
||||
.editorconfig text eol=lf
|
||||
.env* text eol=lf
|
||||
.gitignore text eol=lf
|
||||
.htaccess text eol=lf
|
||||
*.htm text eol=lf
|
||||
*.html text eol=lf
|
||||
*.ini text eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.lock text eol=lf
|
||||
*.md text eol=lf
|
||||
*.php text eol=lf
|
||||
*.php_cs text eol=lf
|
||||
*.php8 text eol=lf
|
||||
*.plex text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.svg text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.twig text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.xml text eol=lf
|
||||
*.xsd text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpeg binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.pdf binary
|
||||
*.swf binary
|
||||
*.zip binary
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
23
.gitignore
vendored
23
.gitignore
vendored
@@ -1,15 +1,4 @@
|
||||
|
||||
################################### Temporary ignore rules during 2.8 UI/UX dev - START
|
||||
/css/backoffice/main.css
|
||||
|
||||
# Sass converter
|
||||
/**/.sass-cache/
|
||||
################################### Temporary ignore rules during 2.8 UI/UX dev - END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# no slash at the end to handle also symlinks
|
||||
/toolkit
|
||||
/env-*
|
||||
@@ -19,7 +8,7 @@
|
||||
|
||||
# composer reserver directory, from sources, populate/update using "composer install"
|
||||
vendor/*
|
||||
test/vendor/*
|
||||
tests/*/vendor/*
|
||||
|
||||
# all conf but listing prevention
|
||||
/conf/**
|
||||
@@ -32,12 +21,12 @@ test/vendor/*
|
||||
!/data/.htaccess
|
||||
!/data/index.php
|
||||
!/data/web.config
|
||||
!/data/exclude.txt
|
||||
!/data/.compilation-symlinks
|
||||
|
||||
# iTop extensions
|
||||
/extensions/**
|
||||
!/extensions/.htaccess
|
||||
!/extensions/readme.txt
|
||||
!/extensions/web.config
|
||||
|
||||
# all logs but listing prevention
|
||||
/log/**
|
||||
@@ -45,9 +34,15 @@ test/vendor/*
|
||||
!/log/index.php
|
||||
!/log/web.config
|
||||
|
||||
# PHPUnit: Cache file, local XML working copies
|
||||
/tests/php-unit-tests/.phpunit.result.cache
|
||||
/tests/php-unit-tests/phpunit.xml
|
||||
/tests/php-unit-tests/postbuild_integration.xml
|
||||
|
||||
|
||||
# Jetbrains
|
||||
/.idea/**
|
||||
!/.idea/IntelliLang.xml
|
||||
|
||||
# doc. generation
|
||||
/.doc/vendor
|
||||
|
||||
15
.idea/IntelliLang.xml
generated
Normal file
15
.idea/IntelliLang.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="LanguageInjectionConfiguration">
|
||||
<injection language="InjectablePHP" injector-id="xml">
|
||||
<display-name>iTop - Class method code</display-name>
|
||||
<place><![CDATA[xmlTag().withLocalName(string().equalTo("code"))]]></place>
|
||||
<xpath-condition>name(..) = 'method' and count(/itop_design) = 1</xpath-condition>
|
||||
</injection>
|
||||
<injection language="InjectablePHP" injector-id="xml">
|
||||
<display-name>iTop - Snippet code</display-name>
|
||||
<place><![CDATA[xmlTag().withLocalName(string().equalTo("snippet"))]]></place>
|
||||
<xpath-condition>name(..) = 'snippets' and count(/itop_design) = 1</xpath-condition>
|
||||
</injection>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2010-2021 Combodo SARL
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2021 Combodo SARL
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2021 Combodo SARL
|
||||
* Copyright (C) 2010-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -50,14 +50,24 @@ foreach ($aDeniedButStillPresent as $sDir)
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
SetupUtils::rrmdir($sDir);
|
||||
echo "OK Remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
catch (\Exception $e) {
|
||||
echo "\nFAILED to remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oiTopComposer->ListAllowedTestDir(),
|
||||
$oiTopComposer->ListDeniedTestDir()
|
||||
);
|
||||
$aExistingDirs = $oiTopComposer->ListAllTestDir();
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
if (false === empty($aMissing)) {
|
||||
echo "Some new tests dirs exists !\n"
|
||||
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
# Git hooks for iTop
|
||||
|
||||
## ❓ Goal
|
||||
|
||||
Those [git hooks](https://git-scm.com/docs/githooks) aims to ease developing on [iTop](https://github.com/Combodo/iTop).
|
||||
|
||||
## ☑ Available hooks
|
||||
|
||||
* pre-commit : rejects commit if you have at least one SCSS file staged, and no CSS file
|
||||
|
||||
## ⚙ Install
|
||||
|
||||
Just run install.php !
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
$aHooks = [
|
||||
'pre-commit.php',
|
||||
];
|
||||
|
||||
$sAppRoot = dirname(__DIR__, 2);
|
||||
|
||||
|
||||
foreach ($aHooks as $sSourceHookFileName) {
|
||||
echo "Processing for `{$sSourceHookFileName}`...\n";
|
||||
$sSourceHookPath = __DIR__.DIRECTORY_SEPARATOR.$sSourceHookFileName;
|
||||
|
||||
$aPathParts = pathinfo($sSourceHookFileName);
|
||||
$sTargetHookPath = $sAppRoot.DIRECTORY_SEPARATOR.'.git'.DIRECTORY_SEPARATOR.'hooks'.DIRECTORY_SEPARATOR.$aPathParts['filename'];
|
||||
|
||||
if (file_exists($sTargetHookPath) || is_link($sTargetHookPath)) {
|
||||
echo "Existing $sTargetHookPath ! Removing...";
|
||||
unlink($sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
echo "Creating symlink for hook in $sTargetHookPath...";
|
||||
symlink($sSourceHookPath, $sTargetHookPath);
|
||||
echo "OK !\n";
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
/**
|
||||
* Reject any commit containing .scss files, but no .css file !
|
||||
*/
|
||||
|
||||
echo "Checking files staged...\n";
|
||||
$sFilesToCommit = shell_exec('git diff --cached --name-only --diff-filter=ACMRT');
|
||||
$aFilesToCommit = explode("\n", $sFilesToCommit);
|
||||
|
||||
$aScssFiles = GetFilesWithExtension('scss', $aFilesToCommit);
|
||||
if (count($aScssFiles) === 0) {
|
||||
echo "No scss file : OK to go !\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$aCssFiles = GetFilesWithExtension('css', $aFilesToCommit);
|
||||
if (count($aCssFiles) === 0) {
|
||||
echo "There are SCSS files staged but no CSS file : REJECTING commit.\n";
|
||||
echo "You must add the compiled SCSS files by running the setup !\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "We have SCSS but also CSS => OK to commit !\n";
|
||||
exit(0);
|
||||
|
||||
|
||||
|
||||
function GetFilesWithExtension($sExtension, $aFiles) {
|
||||
return array_filter(
|
||||
$aFiles,
|
||||
function($item) use ($sExtension) {
|
||||
return (endsWith($item, '.'.$sExtension));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function endsWith( $haystack, $needle ) {
|
||||
$length = strlen( $needle );
|
||||
if( !$length ) {
|
||||
return true;
|
||||
}
|
||||
return substr( $haystack, -$length ) === $needle;
|
||||
}
|
||||
|
||||
function exitWithMessage($sMessage, $iCode) {
|
||||
echo $sMessage;
|
||||
exit($iCode);
|
||||
}
|
||||
@@ -19,17 +19,24 @@
|
||||
* The target license file path is in `$xmlFilePath`
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
$xmlFilePath = $iTopFolder . "setup/licenses/community-licenses.xml";
|
||||
$iTopFolder = __DIR__."/../../";
|
||||
$xmlFilePath = $iTopFolder."setup/licenses/community-licenses.xml";
|
||||
|
||||
function get_scope($product_node)
|
||||
{
|
||||
$jqExec = shell_exec("jq -V"); // a param is mandatory otherwise the script will freeze
|
||||
if ((null === $jqExec) || (false === $jqExec)) {
|
||||
echo "/!\ JQ is required but cannot be launched :( \n";
|
||||
echo "Check this script PHPDoc block for instructions\n";
|
||||
die(-1);
|
||||
}
|
||||
|
||||
|
||||
function get_scope($product_node) {
|
||||
$scope = $product_node->getAttribute("scope");
|
||||
|
||||
if ($scope === "")
|
||||
{ //put iTop first
|
||||
if ($scope === "") { //put iTop first
|
||||
return "aaaaaaaaa";
|
||||
}
|
||||
|
||||
return $scope;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php');
|
||||
/** @var \FileVersionUpdater[] $aFilesUpdaters */
|
||||
$aFilesUpdaters = array(
|
||||
new iTopVersionFileUpdater(),
|
||||
new CssVariablesFileUpdater(),
|
||||
new DatamodelsModulesFiles(),
|
||||
new ConstantFileUpdater('ITOP_CORE_VERSION', 'approot.inc.php'),
|
||||
);
|
||||
|
||||
@@ -123,6 +123,26 @@ class iTopVersionFileUpdater extends AbstractSingleFileVersionUpdater
|
||||
}
|
||||
}
|
||||
|
||||
class CssVariablesFileUpdater extends AbstractSingleFileVersionUpdater
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('css/css-variables.scss');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath)
|
||||
{
|
||||
return preg_replace(
|
||||
'/(\$version: "v)[^"]*(";)/',
|
||||
'${1}'.$sVersionLabel.'${2}',
|
||||
$sFileContent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractGlobFileVersionUpdater extends FileVersionUpdater
|
||||
{
|
||||
protected $sGlobPattern;
|
||||
|
||||
@@ -42,7 +42,7 @@ If you want to use another license, you may [create an extension][wiki new ext].
|
||||
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
|
||||
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
|
||||
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
|
||||
we don't have a `master` branch anymore.
|
||||
we don't have anymore a `master` branch.
|
||||
|
||||
Here are the branches we use and their meaning :
|
||||
|
||||
@@ -52,23 +52,23 @@ Here are the branches we use and their meaning :
|
||||
|
||||
For example, if no version is currently prepared for shipping we could have:
|
||||
|
||||
- `develop` containing future 3.0.0 version
|
||||
- `develop` containing future 2.8.0 version
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
In this example, when 3.0.0-beta is shipped that will become:
|
||||
In this example, when 2.8.0-beta is shipped that will become:
|
||||
|
||||
- `develop`: future 3.1.0 version
|
||||
- `release/3.0.0`: 3.0.0-beta
|
||||
- `develop`: future 2.9.0 version
|
||||
- `release/2.8`: 2.8.0-beta
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
And when 3.0.0 final will be out:
|
||||
And when 2.8.0 final will be out:
|
||||
|
||||
- `develop`: future 3.1.0 version
|
||||
- `support/3.0`: 3.0.x maintenance version (will host developments for 3.0.1)
|
||||
- `develop`: future 2.9.0 version
|
||||
- `support/2.8`: 2.8.x maintenance version (will host developments for 2.8.1)
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
@@ -111,9 +111,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
|
||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||
Emoji examples :
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)).
|
||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||
Emoji examples :
|
||||
* 🌐 `:globe_with_meridians:` for translations
|
||||
* 🎨 `:art:` when improving the format/structure of the code
|
||||
* ⚡️ `:zap:` when improving performance
|
||||
@@ -125,36 +125,15 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* ⬆️ `:arrow_up:` when upgrading dependencies
|
||||
* ⬇️ `:arrow_down:` when downgrading dependencies
|
||||
* ♻️ `:recycle:` code refactoring
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
|
||||
|
||||
## 👥 Pull request
|
||||
|
||||
When your code is working, please:
|
||||
|
||||
* stash as much as possible your commits,
|
||||
* squash as much as possible your commits,
|
||||
* rebase your branch on our repo last commit,
|
||||
* create a pull request.
|
||||
|
||||
Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
||||
|
||||
You might check the ["Allow edits from maintainers" PR checkbox][allow_edits_checkbox] to ease review.
|
||||
|
||||
[allow_edits_checkbox]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork#enabling-repository-maintainer-permissions-on-existing-pull-requests
|
||||
|
||||
### 🙏 We are thankful
|
||||
|
||||
We are thankful for all your contributions to the iTop universe! As a thank you gift, we will send stickers to every iTop (& extensions) contributors!
|
||||
|
||||
Stickers' design might change from one year to another. For the first year we wanted to try a "craft beer label" look, see examples below:
|
||||
|
||||
* Bug hunter: Fix a bug
|
||||
* Translator: Add/update translations
|
||||
* White hat: Find and/or fix a vulnerability
|
||||
* Contributor: Contribute by finding a bug, making an extension or any other way
|
||||
* Partner: For Combodo's official partners
|
||||
* Graduated: Follow a Combodo's iTop training
|
||||
* Ambassador: Outstanding community contributors
|
||||
* Beta tester: Test and give feedback on beta releases
|
||||
* Extension developer: Develop and publish an extension
|
||||
|
||||

|
||||
|
||||
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -1,6 +1,14 @@
|
||||
def infra
|
||||
|
||||
node(){
|
||||
properties([
|
||||
buildDiscarder(
|
||||
logRotator(
|
||||
daysToKeepStr: "28",
|
||||
numToKeepStr: "500")
|
||||
)
|
||||
])
|
||||
|
||||
checkout scm
|
||||
|
||||
infra = load '/var/lib/jenkins/workspace/itop-test-infra_master/src/Infra.groovy'
|
||||
|
||||
101
README.md
101
README.md
@@ -23,10 +23,10 @@ iTop also offers mass import tools and web services to integrate with your IT
|
||||
|
||||
## Latest release
|
||||
|
||||
- [Changes since the previous version][62]
|
||||
- [New features][63]
|
||||
- [Installation notes][64]
|
||||
- [Download][65]
|
||||
- [Changes since the previous version][62]
|
||||
- [New features][63]
|
||||
- [Installation notes][64]
|
||||
- [Download][65]
|
||||
|
||||
[62]: https://www.itophub.io/wiki/page?id=latest:release:change_log
|
||||
[63]: https://www.itophub.io/wiki/page?id=latest:release:start
|
||||
@@ -39,17 +39,16 @@ iTop also offers mass import tools and web services to integrate with your IT
|
||||
- [iTop Forums][1]: community support
|
||||
- [iTop Tickets][2]: for feature requests and bug reports
|
||||
- [Releases download][3]
|
||||
- [Software requirements][4]
|
||||
- [Documentation][5] covering both iTop and its official extensions
|
||||
- [iTop Hub][6] : discover and install extensions !
|
||||
- [Documentation][4] covering both iTop and its official extensions
|
||||
- [iTop Hub][5] : discover and install extensions !
|
||||
|
||||
|
||||
|
||||
[1]: https://sourceforge.net/p/itop/discussion/
|
||||
[2]: https://sourceforge.net/p/itop/tickets/
|
||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||
[4]: https://www.itophub.io/wiki/page?id=latest:install:upgrading_itop
|
||||
[5]: https://www.itophub.io/wiki
|
||||
[6]: https://store.itophub.io/en_US/
|
||||
[4]: https://www.itophub.io/wiki
|
||||
[5]: https://store.itophub.io/en_US/
|
||||
|
||||
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
||||
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
||||
@@ -72,57 +71,51 @@ iTop development is sponsored, led and supported by [Combodo][0].
|
||||
|
||||
## Contributors
|
||||
|
||||
We would like to give a special thank you 🤗 to the people from the community who contributed to this project, including:
|
||||
We would like to give a special thank you to the people from the community who contributed to this project, including:
|
||||
|
||||
### Names
|
||||
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Bilger, Jean-François
|
||||
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
||||
- Cardoso, Anderson
|
||||
- Cassaro, Bruno
|
||||
- Casteleyn, Thomas (a.k.a @Hipska)
|
||||
- Castro, Randall Badilla
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Gumble, David
|
||||
- Kaltefleiter, Lars (a.k.a @larhip)
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Bilger, Jean-François
|
||||
- Bostoen, Jeffrey
|
||||
- Cardoso, Anderson
|
||||
- Cassaro, Bruno
|
||||
- Casteleyn, Thomas
|
||||
- Castro, Randall Badilla
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Gumble, David
|
||||
- Hippler, Lars
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Malik, Remie
|
||||
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||
- Raenker, Martin
|
||||
- Rosenke, Stephan
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Stukalov, Ilya (a.k.a @ilya-stukalov)
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
|
||||
### Aliases
|
||||
|
||||
- chifu1234
|
||||
- cprobst
|
||||
- DudekArtur
|
||||
- Karkoff1212
|
||||
- Laura
|
||||
- Purple Grape
|
||||
- Schlobinux
|
||||
- theBigOne
|
||||
- ulmerspatz
|
||||
- chifu1234
|
||||
- cprobst
|
||||
- Karkoff1212
|
||||
- larhip
|
||||
- Laura
|
||||
- Purple Grape
|
||||
- Schlobinux
|
||||
- theBigOne
|
||||
- ulmerspatz
|
||||
|
||||
### Companies
|
||||
|
||||
- [Hardis](https://www.hardis-group.com/)
|
||||
- [ITOMIG](https://www.itomig.de/)
|
||||
- [Pimkie](https://www.pimkie.com/)
|
||||
- [Super-Visions](https://www.super-visions.com/)
|
||||
- Hardis
|
||||
- ITOMIG
|
||||
- Pimkie
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ responsible disclosure and will make every effort to acknowledge your contributi
|
||||
### iTop vulnerabilities
|
||||
Please send a procedure to reproduce iTop vulnerabilities to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
||||
|
||||
You can send us a standard "given / when / then" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||
You can send us a standard "given / then / when" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||
needed to reproduce.
|
||||
|
||||
### Dependencies vulnerabilities
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -19,7 +19,7 @@
|
||||
/**
|
||||
* UserRightsMatrix (User management Module)
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,7 +20,7 @@
|
||||
* UserRightsNull
|
||||
* User management Module - say Yeah! to everything
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
define('ADMIN_PROFILE_NAME', 'Administrator');
|
||||
@@ -10,7 +23,7 @@ define('PORTAL_PROFILE_NAME', 'Portal user');
|
||||
class UserRightsBaseClassGUI extends cmdbAbstractObject
|
||||
{
|
||||
// Whenever something changes, reload the privileges
|
||||
|
||||
|
||||
protected function AfterInsert()
|
||||
{
|
||||
UserRights::FlushPrivileges();
|
||||
@@ -34,7 +47,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights,grant_by_profile,filter",
|
||||
"category" => "addon/userrights,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
@@ -42,6 +55,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
"db_table" => "priv_urp_profiles",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -59,7 +73,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
}
|
||||
|
||||
protected static $m_aCacheProfiles = null;
|
||||
|
||||
|
||||
public static function DoCreateProfile($sName, $sDescription)
|
||||
{
|
||||
if (is_null(self::$m_aCacheProfiles))
|
||||
@@ -71,7 +85,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sCacheKey = $sName;
|
||||
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
|
||||
@@ -82,10 +96,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
$oNewObj->Set('name', $sName);
|
||||
$oNewObj->Set('description', $sDescription);
|
||||
$iId = $oNewObj->DBInsertNoReload();
|
||||
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
||||
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
||||
return $iId;
|
||||
}
|
||||
|
||||
|
||||
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
||||
{
|
||||
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
|
||||
@@ -102,7 +116,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function DoShowGrantSumary($oPage)
|
||||
{
|
||||
if ($this->GetRawName() == "Administrator")
|
||||
@@ -114,7 +128,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
|
||||
// Note: for sure, we assume that the instance is derived from UserRightsProfile
|
||||
$oUserRights = UserRights::GetModuleInstance();
|
||||
|
||||
|
||||
$aDisplayData = array();
|
||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
|
||||
{
|
||||
@@ -123,12 +137,12 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
|
||||
if ($bGrant === true)
|
||||
{
|
||||
{
|
||||
$aStimuli[] = '<span title="'.$sStimulusCode.': '.htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8').'">'.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').'</span>';
|
||||
}
|
||||
}
|
||||
$sStimuli = implode(', ', $aStimuli);
|
||||
|
||||
|
||||
$aDisplayData[] = array(
|
||||
'class' => MetaModel::GetName($sClass),
|
||||
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
|
||||
@@ -140,7 +154,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
'stimuli' => $sStimuli,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$aDisplayConfig = array();
|
||||
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
|
||||
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
|
||||
@@ -156,9 +170,11 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
}
|
||||
}
|
||||
|
||||
public static function GetReadOnlyAttributes()
|
||||
@@ -198,7 +214,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
|
||||
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
|
||||
* @return integer Flags: the binary combination of the flags applicable to this attribute
|
||||
*/
|
||||
*/
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
@@ -219,14 +235,15 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "addon/userrights,grant_by_profile,filter",
|
||||
"category" => "addon/userrights,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "profile"),
|
||||
"name_attcode" => "userid",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_urp_userprofile",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -246,54 +263,22 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function CheckToDelete(&$oDeletionPlan)
|
||||
public function GetName()
|
||||
{
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
// Users deletion is NOT allowed in demo mode
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||
}
|
||||
catch (SecurityException $e) {
|
||||
// Users deletion is NOT allowed
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::CheckToDelete($oDeletionPlan);
|
||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
||||
}
|
||||
|
||||
public function DoCheckToDelete(&$oDeletionPlan)
|
||||
public function CheckToDelete(&$oDeletionPlan)
|
||||
{
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
// Users deletion is NOT allowed in demo mode
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||
}
|
||||
catch (SecurityException $e) {
|
||||
// Users deletion is NOT allowed
|
||||
$oDeletionPlan->AddToDelete($this, null);
|
||||
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||
$oDeletionPlan->ComputeResults();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::DoCheckToDelete($oDeletionPlan);
|
||||
return parent::CheckToDelete($oDeletionPlan);
|
||||
}
|
||||
|
||||
protected function OnInsert()
|
||||
@@ -308,6 +293,7 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
|
||||
protected function OnDelete()
|
||||
{
|
||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,12 +343,13 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
(
|
||||
"category" => "addon/userrights,grant_by_profile",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||
"name_attcode" => "userid",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_urp_userorg",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -382,6 +369,12 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function GetName()
|
||||
{
|
||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Org', $this->Get('userlogin'), $this->Get('allowed_org_name'));
|
||||
}
|
||||
|
||||
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->CheckIfOrgIsAllowed();
|
||||
@@ -404,7 +397,7 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
{
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$oAddon = UserRights::GetModuleInstance();
|
||||
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
|
||||
if (count($aOrgs) > 0)
|
||||
@@ -432,6 +425,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
UR_ACTION_BULK_DELETE => 'bd',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
|
||||
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
|
||||
*/
|
||||
private $aUsersProfilesList = [];
|
||||
|
||||
// Installation: create the very first user
|
||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||
{
|
||||
@@ -528,7 +527,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oSearch->AllowAllData();
|
||||
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
|
||||
$oSearch->AddConditionExpression($oCondition);
|
||||
|
||||
|
||||
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
|
||||
while ($oUserOrg = $oUserOrgSet->Fetch())
|
||||
{
|
||||
@@ -610,115 +609,30 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
$this->LoadCache();
|
||||
|
||||
// Let us pass an administrator for bypassing the grant matrix check in order to test this method without the need to set up a complex profile
|
||||
// In the nominal case Administrators never end up here (since they completely bypass GetSelectFilter)
|
||||
if (!static::IsAdministrator($oUser) && (MetaModel::HasCategory($sClass, 'silo') || MetaModel::HasCategory($sClass, 'bizmodel')))
|
||||
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
|
||||
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
|
||||
{
|
||||
// N°4354 - Categories 'silo' and 'bizmodel' do check the grant matrix. Whereas 'filter' always allows to read (but the result can be filtered)
|
||||
$aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
|
||||
if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$oFilter = true;
|
||||
$aConditions = array();
|
||||
|
||||
// Determine if this class is part of a silo and build the filter for it
|
||||
// Determine how to position the objects of this class
|
||||
//
|
||||
$sAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||
if (!is_null($sAttCode))
|
||||
if (is_null($sAttCode))
|
||||
{
|
||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||
if (count($aUserOrgs) > 0)
|
||||
{
|
||||
$oFilter = $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
|
||||
}
|
||||
// else: No org means 'any org'
|
||||
// No filtering for this object
|
||||
return true;
|
||||
}
|
||||
// else: No silo for this class
|
||||
|
||||
// Specific conditions to hide, for non-administrators, the Administrator Users, the Administrator Profile and related links
|
||||
// Note: when logged as an administrator, GetSelectFilter is completely bypassed.
|
||||
if ($this->AdministratorsAreHidden())
|
||||
// Position the user
|
||||
//
|
||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||
if (count($aUserOrgs) == 0)
|
||||
{
|
||||
if ($sClass == 'URP_Profiles')
|
||||
{
|
||||
$oExpression = new FieldExpression('id', $sClass);
|
||||
$oScalarExpr = new ScalarExpression(1);
|
||||
|
||||
$aConditions[] = new BinaryExpression($oExpression, '!=', $oScalarExpr);
|
||||
}
|
||||
else if (($sClass == 'URP_UserProfile') || ($sClass == 'User') || (is_subclass_of($sClass, 'User')))
|
||||
{
|
||||
$aAdministrators = $this->GetAdministrators();
|
||||
if (count($aAdministrators) > 0)
|
||||
{
|
||||
$sAttCode = ($sClass == 'URP_UserProfile') ? 'userid' : 'id';
|
||||
$oExpression = new FieldExpression($sAttCode, $sClass);
|
||||
$oListExpr = ListExpression::FromScalars($aAdministrators);
|
||||
$aConditions[] = new BinaryExpression($oExpression, 'NOT IN', $oListExpr);
|
||||
}
|
||||
}
|
||||
// No org means 'any org'
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handling of the added conditions
|
||||
if (count($aConditions) > 0)
|
||||
{
|
||||
if($oFilter === true)
|
||||
{
|
||||
// No 'silo' filter, let's build a clean one
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
}
|
||||
|
||||
// Add the conditions to the filter
|
||||
foreach($aConditions as $oCondition)
|
||||
{
|
||||
$oFilter->AddConditionExpression($oCondition);
|
||||
}
|
||||
}
|
||||
|
||||
return $oFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve (and memoize) the list of administrator accounts.
|
||||
* Note that there should always be at least one administrator account
|
||||
* @return number[]
|
||||
*/
|
||||
private function GetAdministrators()
|
||||
{
|
||||
static $aAdministrators = null;
|
||||
|
||||
if ($aAdministrators === null)
|
||||
{
|
||||
// Find all administrators
|
||||
$aAdministrators = array();
|
||||
$oAdministratorsFilter = new DBObjectSearch('User');
|
||||
$oLnkFilter = new DBObjectSearch('URP_UserProfile');
|
||||
$oExpression = new FieldExpression('profileid', 'URP_UserProfile');
|
||||
$oScalarExpr = new ScalarExpression(1);
|
||||
$oCondition = new BinaryExpression($oExpression, '=', $oScalarExpr);
|
||||
$oLnkFilter->AddConditionExpression($oCondition);
|
||||
$oAdministratorsFilter->AddCondition_ReferencedBy($oLnkFilter, 'userid');
|
||||
$oAdministratorsFilter->AllowAllData(true); // Mandatory to prevent infinite recursion !!
|
||||
$oSet = new DBObjectSet($oAdministratorsFilter);
|
||||
$oSet->OptimizeColumnLoad(array('User' => array('login')));
|
||||
while($oUser = $oSet->Fetch())
|
||||
{
|
||||
$aAdministrators[] = $oUser->GetKey();
|
||||
}
|
||||
}
|
||||
return $aAdministrators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not to hide the 'Administrator' profile and the administrator accounts
|
||||
* @return boolean
|
||||
*/
|
||||
private function AdministratorsAreHidden()
|
||||
{
|
||||
return ((bool)MetaModel::GetConfig()->Get('security.hide_administrators'));
|
||||
return $this->MakeSelectFilter($sClass, $aUserOrgs, $aSettings, $sAttCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -738,14 +652,20 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// load and cache permissions for the current user on the given class
|
||||
//
|
||||
$iUser = $oUser->GetKey();
|
||||
$aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) return $aTest;
|
||||
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])){
|
||||
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) return $aTest;
|
||||
}
|
||||
|
||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||
|
||||
$bStatus = null;
|
||||
// Cache user's profiles
|
||||
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
|
||||
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
|
||||
{
|
||||
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
|
||||
if (!is_null($bGrant))
|
||||
@@ -871,11 +791,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// Note: this code is VERY close to the code of IsActionAllowed()
|
||||
$iUser = $oUser->GetKey();
|
||||
|
||||
// Cache user's profiles
|
||||
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
|
||||
// Note: The object set is ignored because it was interesting to optimize for huge data sets
|
||||
// and acceptable to consider only the root class of the object set
|
||||
$bStatus = null;
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
|
||||
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
|
||||
{
|
||||
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
|
||||
if (!is_null($bGrant))
|
||||
@@ -904,9 +829,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out which attribute is corresponding the the dimension 'owner org'
|
||||
* returns null if no such attribute has been found (no filtering should occur)
|
||||
*/
|
||||
* @param string $sClass
|
||||
* @return string|null Find out which attribute is corresponding the dimension 'owner org'
|
||||
* returns null if no such attribute has been found (no filtering should occur)
|
||||
*/
|
||||
public static function GetOwnerOrganizationAttCode($sClass)
|
||||
{
|
||||
$sAttCode = null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -77,6 +77,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
"db_table" => "priv_urp_profiles",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -311,9 +312,11 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,12 +330,13 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "profile"),
|
||||
"name_attcode" => "userid",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_urp_userprofile",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -351,6 +355,11 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function GetName()
|
||||
{
|
||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
||||
}
|
||||
}
|
||||
|
||||
class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
@@ -361,12 +370,13 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||
"name_attcode" => "userid",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_urp_userorg",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -385,6 +395,11 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function GetName()
|
||||
{
|
||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Org', $this->Get('userlogin'), $this->Get('allowed_org_name'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -402,6 +417,7 @@ class URP_ActionGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_actions",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -438,6 +454,7 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_stimulus",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -474,6 +491,7 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_attributes",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -586,10 +604,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
/**
|
||||
* Read and cache organizations allowed to the given user
|
||||
*
|
||||
* @param $oUser
|
||||
* @param $sClass (not used here but can be used in overloads)
|
||||
* @param User $oUser
|
||||
* @param string $sClass (not used here but can be used in overloads)
|
||||
*
|
||||
* @return array
|
||||
* @return array keys of the User allowed org
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -58,6 +58,7 @@ class URP_Profiles extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_profiles",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -143,9 +144,11 @@ class URP_Profiles extends UserRightsBaseClass
|
||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||
$this->DoShowGrantSumary($oPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +167,7 @@ class URP_Dimensions extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_dimensions",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -270,12 +274,13 @@ class URP_UserProfile extends UserRightsBaseClass
|
||||
(
|
||||
"category" => "addon/userrights",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => array("userlogin", "profile"),
|
||||
"name_attcode" => "userid",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_urp_userprofile",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -294,6 +299,11 @@ class URP_UserProfile extends UserRightsBaseClass
|
||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function GetName()
|
||||
{
|
||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,6 +321,7 @@ class URP_ProfileProjection extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_profileprojection",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -391,6 +402,7 @@ class URP_ClassProjection extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_classprojection",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -462,6 +474,7 @@ class URP_ActionGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_actions",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -498,6 +511,7 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_stimulus",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -534,6 +548,7 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
||||
"db_table" => "priv_urp_grant_attributes",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class DBSearchHelper
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class DBSearchHelper
|
||||
{
|
||||
/**
|
||||
* Add context filter to DBUnionSearch
|
||||
*
|
||||
* @param \DBSearch|null $oSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function AddContextFilter(?DBSearch $oSearch): void
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sClass = $oSearch->GetClass();
|
||||
foreach ($oAppContext->GetNames() as $key) {
|
||||
// Find the value of the object corresponding to each 'context' parameter
|
||||
$aCallSpec = [$sClass, 'MapContextParam'];
|
||||
$sAttCode = '';
|
||||
if (is_callable($aCallSpec)) {
|
||||
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
|
||||
}
|
||||
|
||||
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
||||
// Add Hierarchical condition if hierarchical key
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if (isset($oAttDef) && ($oAttDef->IsExternalKey())) {
|
||||
$iDefaultValue = intval($oAppContext->GetCurrentValue($key));
|
||||
if ($iDefaultValue != 0) {
|
||||
try {
|
||||
/** @var AttributeExternalKey $oAttDef */
|
||||
$sTargetClass = $oAttDef->GetTargetClass();
|
||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass);
|
||||
if ($sHierarchicalKeyCode !== false) {
|
||||
$oFilter = new DBObjectSearch($sTargetClass);
|
||||
$oFilter->AddCondition('id', $iDefaultValue);
|
||||
$oHKFilter = new DBObjectSearch($sTargetClass);
|
||||
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
||||
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// If filtering fails just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,11 +30,8 @@ function mb_str_replace($search, $replace, $subject, &$count = 0) {
|
||||
$replacements = array_pad($replacements, count($searches), '');
|
||||
foreach ($searches as $key => $search) {
|
||||
$parts = mb_split(preg_quote($search), $subject);
|
||||
if (is_array($parts))
|
||||
{
|
||||
$count += count($parts) - 1;
|
||||
$subject = implode($replacements[$key], $parts);
|
||||
}
|
||||
$count += count($parts) - 1;
|
||||
$subject = implode($replacements[$key], $parts);
|
||||
}
|
||||
} else {
|
||||
// Call mb_str_replace for each subject in array, recursively
|
||||
|
||||
@@ -1,20 +1,425 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||
|
||||
/**
|
||||
* Class ajax_page
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* @deprecated will be removed in 3.1.0 - moved to AjaxPage
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
class ajax_page extends AjaxPage
|
||||
{
|
||||
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class ajax_page extends WebPage implements iTabbedPage
|
||||
{
|
||||
/**
|
||||
* Jquery style ready script
|
||||
* @var array
|
||||
*/
|
||||
protected $m_sReadyScript;
|
||||
protected $m_oTabs;
|
||||
private $m_sMenu; // If set, then the menu will be updated
|
||||
|
||||
/**
|
||||
* constructor for the web page
|
||||
*
|
||||
* @param string $s_title Not used
|
||||
*/
|
||||
function __construct($s_title) {
|
||||
$sPrintable = utils::ReadParam('printable', '0');
|
||||
$bPrintable = ($sPrintable == '1');
|
||||
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
$this->m_sReadyScript = "";
|
||||
//$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->no_cache();
|
||||
$this->add_http_headers();
|
||||
$this->m_oTabs = new TabManager();
|
||||
$this->sContentType = 'text/html';
|
||||
$this->sContentDisposition = 'inline';
|
||||
$this->m_sMenu = "";
|
||||
|
||||
utils::InitArchiveMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disabling sending the header so that resource won't be blocked by CORB. See parent method documentation.
|
||||
* @return void
|
||||
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation
|
||||
*/
|
||||
public function add_xcontent_type_options()
|
||||
{
|
||||
// Nothing to do !
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '')
|
||||
{
|
||||
$this->add($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabCode, $sHtml)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabCode, $sHtml));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTab($sTabCode = '', $sTabTitle = null)
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTab($sTabCode, $sTabTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddAjaxTab($sTabCode, $sUrl, $bCache, $sTabTitle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_oTabs->GetCurrentTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function RemoveTab($sTabCode, $sTabContainer = null)
|
||||
{
|
||||
$this->m_oTabs->RemoveTab($sTabCode, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null)
|
||||
{
|
||||
return $this->m_oTabs->FindTab($sPattern, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given tab the active one, as if it were clicked
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*/
|
||||
public function SelectTab($sTabContainer, $sTabCode)
|
||||
{
|
||||
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*/
|
||||
public function AddToMenu($sHtml)
|
||||
{
|
||||
$this->m_sMenu .= $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
if (!empty($this->sContentType))
|
||||
{
|
||||
$this->add_header('Content-type: '.$this->sContentType);
|
||||
}
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
if ($this->m_oTabs->TabsContainerCount() > 0)
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
// The "tab widgets" to handle.
|
||||
var tabs = $('div[id^=tabbedContent]');
|
||||
|
||||
// Ugly patch for a change in the behavior of jQuery UI:
|
||||
// Before jQuery UI 1.9, tabs were always considered as "local" (opposed to Ajax)
|
||||
// when their href was beginning by #. Starting with 1.9, a <base> tag in the page
|
||||
// is taken into account and causes "local" tabs to be considered as Ajax
|
||||
// unless their URL is equal to the URL of the page...
|
||||
if ($('base').length > 0)
|
||||
{
|
||||
$('div[id^=tabbedContent] > ul > li > a').each(function() {
|
||||
var sHash = location.hash;
|
||||
var sCleanLocation = location.href.toString().replace(sHash, '').replace(/#$/, '');
|
||||
$(this).attr("href", sCleanLocation+$(this).attr("href"));
|
||||
});
|
||||
}
|
||||
if ($.bbq)
|
||||
{
|
||||
// This selector will be reused when selecting actual tab widget A elements.
|
||||
var tab_a_selector = 'ul.ui-tabs-nav a';
|
||||
|
||||
// Enable tabs on all tab widgets. The `event` property must be overridden so
|
||||
// that the tabs aren't changed on click, and any custom event name can be
|
||||
// specified. Note that if you define a callback for the 'select' event, it
|
||||
// will be executed for the selected tab whenever the hash changes.
|
||||
tabs.tabs({ event: 'change' });
|
||||
|
||||
// Define our own click handler for the tabs, overriding the default.
|
||||
tabs.find( tab_a_selector ).click(function()
|
||||
{
|
||||
var state = {};
|
||||
|
||||
// Get the id of this tab widget.
|
||||
var id = $(this).closest( 'div[id^=tabbedContent]' ).attr( 'id' );
|
||||
|
||||
// Get the index of this tab.
|
||||
var idx = $(this).parent().prevAll().length;
|
||||
|
||||
// Set the state!
|
||||
state[ id ] = idx;
|
||||
$.bbq.pushState( state );
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
tabs.tabs();
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
// Render the tabs in the page (if any)
|
||||
$this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content, $this);
|
||||
|
||||
// Additional UI widgets to be activated inside the ajax fragment
|
||||
// Important: Testing the content type is not enough because some ajax handlers have not correctly positionned the flag (e.g json response corrupted by the script)
|
||||
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
EOF
|
||||
);
|
||||
}
|
||||
$this->outputCollapsibleSectionInit();
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
{
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
echo self::FilterXSS($this->s_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $this->s_content;
|
||||
}
|
||||
if (!empty($this->m_sMenu))
|
||||
{
|
||||
$uid = time();
|
||||
echo "<div id=\"accordion_temp_$uid\">\n";
|
||||
echo "<div id=\"accordion\">\n";
|
||||
echo "<!-- Beginning of the accordion menu -->\n";
|
||||
echo self::FilterXSS($this->m_sMenu);
|
||||
echo "<!-- End of the accordion menu-->\n";
|
||||
echo "</div>\n";
|
||||
echo "</div>\n";
|
||||
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo "$('#inner_menu').html($('#accordion_temp_$uid').html());\n";
|
||||
echo "$('#accordion_temp_$uid').remove();\n";
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
|
||||
//echo $this->s_deferred_content;
|
||||
if (count($this->a_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo implode("\n", $this->a_scripts);
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (count($this->a_linked_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
foreach($this->a_linked_scripts as $sScriptUrl)
|
||||
{
|
||||
echo '$.getScript('.json_encode($sScriptUrl).");\n";
|
||||
}
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (!empty($this->s_deferred_content))
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo "\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');\n";
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (!empty($this->m_sReadyScript))
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if(count($this->a_linked_stylesheets) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">";
|
||||
foreach($this->a_linked_stylesheets as $aStylesheet)
|
||||
{
|
||||
$sStylesheetUrl = $aStylesheet['link'];
|
||||
echo "if (!$('link[href=\"{$sStylesheetUrl}\"]').length) $('<link href=\"{$sStylesheetUrl}\" rel=\"stylesheet\">').appendTo('head');\n";
|
||||
}
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
|
||||
if (trim($s_captured_output) != "")
|
||||
{
|
||||
echo self::FilterXSS($s_captured_output);
|
||||
}
|
||||
|
||||
$oKPI->ComputeAndReport('Echoing');
|
||||
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a paragraph with a smaller font into the page
|
||||
* NOT implemented (i.e does nothing)
|
||||
* @param string $sText Content of the (small) paragraph
|
||||
* @return void
|
||||
*/
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add($sHtml)
|
||||
{
|
||||
if (($this->m_oTabs->GetCurrentTabContainer() != '') && ($this->m_oTabs->GetCurrentTab() != ''))
|
||||
{
|
||||
$this->m_oTabs->AddToTab($this->m_oTabs->GetCurrentTabContainer(), $this->m_oTabs->GetCurrentTab(), $sHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent::add($sHtml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function start_capture()
|
||||
{
|
||||
$sCurrentTabContainer = $this->m_oTabs->GetCurrentTabContainer();
|
||||
$sCurrentTab = $this->m_oTabs->GetCurrentTab();
|
||||
|
||||
if (!empty($sCurrentTabContainer) && !empty($sCurrentTab))
|
||||
{
|
||||
$iOffset = $this->m_oTabs->GetCurrentTabLength();
|
||||
return array('tc' => $sCurrentTabContainer, 'tab' => $sCurrentTab, 'offset' => $iOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::start_capture();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function end_capture($offset)
|
||||
{
|
||||
if (is_array($offset))
|
||||
{
|
||||
if ($this->m_oTabs->TabExists($offset['tc'], $offset['tab']))
|
||||
{
|
||||
$sCaptured = $this->m_oTabs->TruncateTab($offset['tc'], $offset['tab'], $offset['offset']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCaptured = '';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCaptured = parent::end_capture($offset);
|
||||
}
|
||||
return $sCaptured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_at_the_end($s_html, $sId = '')
|
||||
{
|
||||
if ($sId != '')
|
||||
{
|
||||
$this->add_script("$('#{$sId}').remove();"); // Remove any previous instance of the same Id
|
||||
}
|
||||
$this->s_deferred_content .= $s_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_ready_script($sScript)
|
||||
{
|
||||
$this->m_sReadyScript .= $sScript."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetUniqueId()
|
||||
{
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function FilterXSS($sHTML)
|
||||
{
|
||||
return str_ireplace(array('<script', '</script>'), array('<!-- <removed-script', '</removed-script> -->'), $sHTML);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Includes all the classes to have the application up and running
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
||||
@@ -15,4 +31,10 @@ require_once(APPROOT.'/application/audit.category.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||
require_once(APPROOT.'/application/query.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||
//require_once(APPROOT.'/application/menunode.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
|
||||
class ApplicationException extends CoreException
|
||||
{
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2018 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,28 +20,23 @@
|
||||
/**
|
||||
* Class ApplicationContext
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
|
||||
require_once(APPROOT."/application/utils.inc.php");
|
||||
|
||||
/**
|
||||
* Interface for directing end-users to the relevant application
|
||||
*/
|
||||
*/
|
||||
interface iDBObjectURLMaker
|
||||
{
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $iId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function MakeObjectURL($sClass, $iId);
|
||||
}
|
||||
|
||||
@@ -205,60 +200,23 @@ class ApplicationContext
|
||||
}
|
||||
return implode("&", $aParams);
|
||||
}
|
||||
/**
|
||||
* @since 3.0.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
|
||||
* Returns the params as c[menu]:..., c[org_id]:....
|
||||
* @return string The params
|
||||
*/
|
||||
public function GetForPostParams()
|
||||
{
|
||||
return json_encode($this->aValues);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||
*
|
||||
* @return string The context as a sequence of <input type="hidden" /> tags
|
||||
*/
|
||||
public function GetForForm()
|
||||
{
|
||||
$sContext = "";
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
foreach($this->aValues as $sName => $sValue)
|
||||
{
|
||||
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||
}
|
||||
return $sContext;
|
||||
}
|
||||
/**
|
||||
* Returns the context an array of input blocks
|
||||
*
|
||||
* @return array The context as a sequence of <input type="hidden" /> tags
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetForUIForm()
|
||||
{
|
||||
$aContextInputBlocks = [];
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", htmlentities($sValue, ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
return $aContextInputBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||
*
|
||||
*/
|
||||
public function GetForFormBlock(): UIBlock
|
||||
{
|
||||
$oContext = new UIContentBlock();
|
||||
foreach ($this->aValues as $sName => $sValue) {
|
||||
$oContext->AddSubBlock(InputUIBlockFactory::MakeForHidden('c[$sName]', utils::HtmlEntities($sValue)));
|
||||
}
|
||||
return $oContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context as a hash array 'parameter_name' => value
|
||||
*
|
||||
* @return array The context information
|
||||
*/
|
||||
public function GetAsHash()
|
||||
@@ -336,7 +294,7 @@ class ApplicationContext
|
||||
$sPrevious = self::GetUrlMakerClass();
|
||||
|
||||
self::$m_sUrlMakerClass = $sClass;
|
||||
Session::Set('UrlMakerClass', $sClass);
|
||||
$_SESSION['UrlMakerClass'] = $sClass;
|
||||
|
||||
return $sPrevious;
|
||||
}
|
||||
@@ -349,9 +307,9 @@ class ApplicationContext
|
||||
{
|
||||
if (is_null(self::$m_sUrlMakerClass))
|
||||
{
|
||||
if (Session::IsSet('UrlMakerClass'))
|
||||
if (isset($_SESSION['UrlMakerClass']))
|
||||
{
|
||||
self::$m_sUrlMakerClass = Session::Get('UrlMakerClass');
|
||||
self::$m_sUrlMakerClass = $_SESSION['UrlMakerClass'];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -404,9 +362,9 @@ class ApplicationContext
|
||||
*/
|
||||
protected static function LoadPluginProperties()
|
||||
{
|
||||
if (Session::IsSet('PluginProperties'))
|
||||
if (isset($_SESSION['PluginProperties']))
|
||||
{
|
||||
self::$m_aPluginProperties = Session::Get('PluginProperties');
|
||||
self::$m_aPluginProperties = $_SESSION['PluginProperties'];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -426,7 +384,7 @@ class ApplicationContext
|
||||
if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties();
|
||||
|
||||
self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value;
|
||||
Session::Set(['PluginProperties', $sPluginClass, $sProperty], $value);
|
||||
$_SESSION['PluginProperties'][$sPluginClass][$sProperty] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -22,7 +22,7 @@
|
||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
||||
* inside the set
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -23,7 +23,7 @@
|
||||
* or the "bad" ones. The core audit engines computes the complement to the definition
|
||||
* set when needed to obtain either the valid objects, or the ones with an error
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -43,6 +43,7 @@ class AuditRule extends cmdbAbstractObject
|
||||
"db_table" => "priv_auditrule",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
@@ -1,8 +1,84 @@
|
||||
<?php
|
||||
// Copyright (C) 2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||
* Adapter class: when an API requires WebPage and you want to produce something else
|
||||
*
|
||||
* @copyright Copyright (C) 2016 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CaptureWebPage extends WebPage
|
||||
{
|
||||
protected $aReadyScripts;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('capture web page');
|
||||
$this->aReadyScripts = array();
|
||||
}
|
||||
|
||||
public function GetHtml()
|
||||
{
|
||||
$trash = $this->ob_get_clean_safe();
|
||||
return $this->s_content;
|
||||
}
|
||||
|
||||
public function GetJS()
|
||||
{
|
||||
$sRet = implode("\n", $this->a_scripts);
|
||||
if (!empty($this->s_deferred_content))
|
||||
{
|
||||
$sRet .= "\n\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');";
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function GetReadyJS()
|
||||
{
|
||||
return "\$(document).ready(function() {\n".implode("\n", $this->aReadyScripts)."\n});";
|
||||
}
|
||||
|
||||
public function GetCSS()
|
||||
{
|
||||
return $this->a_styles;
|
||||
}
|
||||
|
||||
public function GetJSFiles()
|
||||
{
|
||||
return $this->a_linked_scripts;
|
||||
}
|
||||
|
||||
public function GetCSSFiles()
|
||||
{
|
||||
return $this->a_linked_stylesheets;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
throw new Exception(__method__.' should not be called');
|
||||
}
|
||||
|
||||
public function add_ready_script($sScript)
|
||||
{
|
||||
$this->aReadyScripts[] = $sScript;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,97 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader
|
||||
* CLI page
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CLIPage implements Page
|
||||
{
|
||||
function __construct($s_title)
|
||||
{
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
echo $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function pre($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
echo "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CompileCSSService : used to ease testing ThemeHander class via mocks
|
||||
*
|
||||
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||
* @since 3.0.0 N°2982
|
||||
*/
|
||||
class CompileCSSService
|
||||
{
|
||||
/**
|
||||
* CompileCSSService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,111 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader
|
||||
* Simple web page with no includes or fancy formatting, useful to generateXML documents
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
|
||||
class CSVPage extends WebPage
|
||||
{
|
||||
function __construct($s_title) {
|
||||
parent::__construct($s_title);
|
||||
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
|
||||
$this->no_cache();
|
||||
$this->add_http_headers();
|
||||
//$this->add_header("Content-Transfer-Encoding: binary");
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
|
||||
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
echo trim($this->s_content);
|
||||
echo "\n";
|
||||
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
$this->s_content .= $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
$this->s_content .= $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
$this->s_content .= "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||
|
||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
||||
@@ -431,19 +438,22 @@ abstract class Dashboard
|
||||
public function RenderProperties($oPage, $aExtraParams = array())
|
||||
{
|
||||
// menu to pick a layout and edit other properties of the dashboard
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashboard-editor--properties"><div class="ui-widget-header ui-corner-all ibo-dashboard-editor--properties-title">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
|
||||
$oPage->add('<div class="ibo-dashboard-editor--properties-subtitle" data-role="ibo-dashboard-editor--properties-subtitle">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
|
||||
$oPage->add('<div id="select_layout" class="ibo-dashboard-editor--layout-list" data-role="ibo-dashboard-editor--layout-list">');
|
||||
foreach (get_declared_classes() as $sLayoutClass) {
|
||||
if (is_subclass_of($sLayoutClass, 'DashboardLayout')) {
|
||||
$oPage->add('<div style="text-align:center">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
|
||||
$oPage->add('<div id="select_layout" style="text-align:center">');
|
||||
foreach( get_declared_classes() as $sLayoutClass)
|
||||
{
|
||||
if (is_subclass_of($sLayoutClass, 'DashboardLayout'))
|
||||
{
|
||||
$oReflection = new ReflectionClass($sLayoutClass);
|
||||
if (!$oReflection->isAbstract()) {
|
||||
if (!$oReflection->isAbstract())
|
||||
{
|
||||
$aCallSpec = array($sLayoutClass, 'GetInfo');
|
||||
$aInfo = call_user_func($aCallSpec);
|
||||
$sChecked = ($this->sLayoutClass == $sLayoutClass) ? 'checked' : '';
|
||||
$oPage->add('<input type="radio" name="layout_class" '.$sChecked.' value="'.$sLayoutClass.'" id="layout_'.$sLayoutClass.'"><label for="layout_'.$sLayoutClass.'"><img src="'.$sUrl.$aInfo['icon'].'" class="ibo-dashboard--properties--icon" data-role="ibo-dashboard--properties--icon"/></label>'); // title="" on either the img or the label does nothing !
|
||||
$oPage->add('<input type="radio" name="layout_class" '.$sChecked.' value="'.$sLayoutClass.'" id="layout_'.$sLayoutClass.'"><label for="layout_'.$sLayoutClass.'"><img src="'.$sUrl.$aInfo['icon'].'" /></label>'); // title="" on either the img or the label does nothing !
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,15 +484,14 @@ abstract class Dashboard
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
// Note: the title gets deleted by the validation mechanism
|
||||
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
|
||||
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
|
||||
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||
|
||||
$('#attr_auto_reload').change( function(ev) {
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
|
||||
} );
|
||||
|
||||
$('#select_layout').controlgroup();
|
||||
$('#select_layout').buttonset();
|
||||
$('#select_dashlet').droppable({
|
||||
accept: '.dashlet',
|
||||
drop: function(event, ui) {
|
||||
@@ -492,7 +501,7 @@ abstract class Dashboard
|
||||
},
|
||||
});
|
||||
|
||||
$('#event_bus').on('dashlet-selected', function(event, data){
|
||||
$('#event_bus').bind('dashlet-selected', function(event, data){
|
||||
var sDashletId = data.dashlet_id;
|
||||
var sPropId = 'dashlet_properties_'+sDashletId;
|
||||
$('.dashlet_properties').each(function() {
|
||||
@@ -517,55 +526,34 @@ EOF
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams
|
||||
* @param bool $bCanEdit
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
||||
{
|
||||
if (!array_key_exists('dashboard_div_id', $aExtraParams)) {
|
||||
if (!array_key_exists('dashboard_div_id', $aExtraParams))
|
||||
{
|
||||
$aExtraParams['dashboard_div_id'] = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||
}
|
||||
|
||||
$oPage->add('<div class="dashboard-title-line"><div class="dashboard-title">'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</div></div>');
|
||||
|
||||
/** @var \DashboardLayoutMultiCol $oLayout */
|
||||
$oLayout = new $this->sLayoutClass();
|
||||
|
||||
foreach ($this->aCells as $iCellIdx => $aDashlets) {
|
||||
foreach ($aDashlets as $oDashlet) {
|
||||
foreach($this->aCells as $iCellIdx => $aDashlets)
|
||||
{
|
||||
foreach($aDashlets as $oDashlet)
|
||||
{
|
||||
$aDashletCoordinates = $oLayout->GetDashletCoordinates($iCellIdx);
|
||||
$this->PrepareDashletForRendering($oDashlet, $aDashletCoordinates, $aExtraParams);
|
||||
}
|
||||
}
|
||||
|
||||
$oDashboard = $oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||
$oPage->AddUiBlock($oDashboard);
|
||||
|
||||
$bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
||||
|
||||
if ($bFromDasboardPage) {
|
||||
$sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
|
||||
$sHtml = "<div class=\"ibo-top-bar--toolbar-dashboard-title\" title=\"{$sTitleForHTML}\">{$sTitleForHTML}</div>";
|
||||
if ($oPage instanceof iTopWebPage) {
|
||||
$oTopBar = $oPage->GetTopBarLayout();
|
||||
$oToolbar = ToolbarUIBlockFactory::MakeStandard();
|
||||
$oTopBar->SetToolbar($oToolbar);
|
||||
|
||||
$oToolbar->AddHtml($sHtml);
|
||||
} else {
|
||||
$oPage->add_script(<<<JS
|
||||
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML").attr("title", $('<div>').html("$sTitleForHTML").text());
|
||||
JS
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$oDashboard->SetTitle(Dict::S($this->sTitle));
|
||||
}
|
||||
|
||||
if (!$bEditMode) {
|
||||
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$oPage->add_linked_script('../js/dashlet.js');
|
||||
$oPage->add_linked_script('../js/dashboard.js');
|
||||
}
|
||||
|
||||
return $oDashboard;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,18 +565,19 @@ JS
|
||||
public function RenderDashletsSelection(WebPage $oPage)
|
||||
{
|
||||
// Toolbox/palette to drag and drop dashlets
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashboard--available-dashlets"><div class="ui-widget-header ui-corner-all ibo-dashboard--available-dashlet--title">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
|
||||
$oPage->add('<div id="select_dashlet" class="ibo-dashboard--available-dashlets--list" data-role="ibo-dashboard--available-dashlets--list">');
|
||||
$oPage->add('<div id="select_dashlet" style="text-align:center; max-height:120px; overflow-y:auto;">');
|
||||
$aAvailableDashlets = $this->GetAvailableDashlets();
|
||||
foreach ($aAvailableDashlets as $sDashletClass => $aInfo) {
|
||||
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="ibo-dashboard-editor--available-dashlet-icon dashlet_icon ui-widget-content ui-corner-all" data-role="ibo-dashboard-editor--available-dashlet-icon" id="dashlet_'.$sDashletClass.'" data-tooltip-content="'.$aInfo['label'].'" title="'.$aInfo['label'].'"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
|
||||
foreach($aAvailableDashlets as $sDashletClass => $aInfo)
|
||||
{
|
||||
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="dashlet_icon ui-widget-content ui-corner-all" id="dashlet_'.$sDashletClass.'" title="'.$aInfo['label'].'" style="width:34px; height:34px; display:inline-block; margin:2px;"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
|
||||
}
|
||||
$oPage->add('</div>');
|
||||
|
||||
$oPage->add('</div>');
|
||||
$oPage->add_ready_script("$('.dashlet_icon').draggable({cursor: 'move', helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
|
||||
$oPage->add_ready_script("$('.dashlet_icon').draggable({helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,12 +587,12 @@ JS
|
||||
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
// Toolbox/palette to edit the properties of each dashlet
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashlet--properties"><div class="ui-widget-header ui-corner-all ibo-dashlet--properties--title">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
|
||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
|
||||
|
||||
/** @var \DashboardLayoutMultiCol $oLayout */
|
||||
$oLayout = new $this->sLayoutClass();
|
||||
|
||||
$oPage->add('<div id="dashlet_properties">');
|
||||
$oPage->add('<div id="dashlet_properties" style="text-align:center">');
|
||||
foreach($this->aCells as $iCellIdx => $aCell)
|
||||
{
|
||||
/** @var \Dashlet $oDashlet */
|
||||
@@ -636,13 +625,16 @@ JS
|
||||
|
||||
foreach( get_declared_classes() as $sDashletClass)
|
||||
{
|
||||
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instantiated.
|
||||
if (is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, array('DashletUnknown', 'DashletProxy'))) {
|
||||
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instanciated.
|
||||
if ( is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, array('DashletUnknown', 'DashletProxy')) )
|
||||
{
|
||||
$oReflection = new ReflectionClass($sDashletClass);
|
||||
if (!$oReflection->isAbstract()) {
|
||||
if (!$oReflection->isAbstract())
|
||||
{
|
||||
$aCallSpec = array($sDashletClass, 'IsVisible');
|
||||
$bVisible = call_user_func($aCallSpec);
|
||||
if ($bVisible) {
|
||||
if ($bVisible)
|
||||
{
|
||||
$aCallSpec = array($sDashletClass, 'GetInfo');
|
||||
$aInfo = call_user_func($aCallSpec);
|
||||
$aDashlets[$sDashletClass] = $aInfo;
|
||||
@@ -891,53 +883,11 @@ class RuntimeDashboard extends Dashboard
|
||||
$oDashboard->FromXml($sDashboardDefinition);
|
||||
$oDashboard->SetCustomFlag($bCustomized);
|
||||
$oDashboard->SetDefinitionFile($sDashboardFileSanitized);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDashboard = null;
|
||||
}
|
||||
|
||||
return $oDashboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDashboardFile file name relative to the current module folder
|
||||
* @param string $sDashBoardId code of the dashboard either menu_id or <class>__<attcode>
|
||||
*
|
||||
* @return null|RuntimeDashboard
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function GetDashboardToEdit($sDashboardFile, $sDashBoardId)
|
||||
{
|
||||
$bCustomized = false;
|
||||
|
||||
// Search for an eventual user defined dashboard
|
||||
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oUDSearch->AddCondition('menu_code', $sDashBoardId, '=');
|
||||
$oUDSet = new DBObjectSet($oUDSearch);
|
||||
if ($oUDSet->Count() > 0) {
|
||||
// Assuming there is at most one couple {user, menu}!
|
||||
$oUserDashboard = $oUDSet->Fetch();
|
||||
$sDashboardDefinition = $oUserDashboard->Get('contents');
|
||||
$bCustomized = true;
|
||||
} else {
|
||||
$sDashboardDefinition = @file_get_contents($sDashboardFile);
|
||||
}
|
||||
|
||||
|
||||
if ($sDashboardDefinition !== false) {
|
||||
$oDashboard = new RuntimeDashboard($sDashBoardId);
|
||||
$oDashboard->FromXml($sDashboardDefinition);
|
||||
$oDashboard->SetCustomFlag($bCustomized);
|
||||
$oDashboard->SetDefinitionFile($sDashboardFile);
|
||||
} else {
|
||||
$oDashboard = null;
|
||||
}
|
||||
|
||||
return $oDashboard;
|
||||
}
|
||||
|
||||
@@ -947,33 +897,40 @@ class RuntimeDashboard extends Dashboard
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
||||
{
|
||||
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class'])) {
|
||||
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class']))
|
||||
{
|
||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRenderParams = $aExtraParams;
|
||||
}
|
||||
|
||||
$oDashboard = parent::Render($oPage, $bEditMode, $aRenderParams);
|
||||
parent::Render($oPage, $bEditMode, $aRenderParams);
|
||||
|
||||
if (isset($aExtraParams['query_params']['this->object()'])) {
|
||||
if (isset($aExtraParams['query_params']['this->object()']))
|
||||
{
|
||||
/** @var \DBObject $oObj */
|
||||
$oObj = $aExtraParams['query_params']['this->object()'];
|
||||
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
|
||||
if (isset($aExtraParams['from_dashboard_page'])) {
|
||||
$aAjaxParams['from_dashboard_page'] = $aExtraParams['from_dashboard_page'];
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAjaxParams = $aExtraParams;
|
||||
}
|
||||
if (!$bEditMode && !$oPage->IsPrintableVersion()) {
|
||||
if (!$bEditMode && !$oPage->IsPrintableVersion())
|
||||
{
|
||||
$sId = $this->GetId();
|
||||
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
||||
if ($this->GetAutoReload()) {
|
||||
if ($this->GetAutoReload())
|
||||
{
|
||||
$sFile = addslashes($this->GetDefinitionFile());
|
||||
$sExtraParams = json_encode($aAjaxParams);
|
||||
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
|
||||
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
$oPage->add_script(
|
||||
<<<JS
|
||||
<<<EOF
|
||||
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
||||
{
|
||||
clearInterval(AutoReloadDashboardId$sDivId);
|
||||
@@ -985,18 +942,25 @@ class RuntimeDashboard extends Dashboard
|
||||
function ReloadDashboard$sDivId()
|
||||
{
|
||||
// Do not reload when a dialog box is active
|
||||
if (!($('.ui-dialog:visible').length > 0) && $('.ibo-dashboard#$sDivId').is(':visible'))
|
||||
if (!($('.ui-dialog:visible').length > 0) && $('.dashboard_contents#$sDivId').is(':visible'))
|
||||
{
|
||||
updateDashboard$sDivId();
|
||||
$('.dashboard_contents#$sDivId').block();
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL'},
|
||||
function(data){
|
||||
$('.dashboard_contents#$sDivId').html(data);
|
||||
$('.dashboard_contents#$sDivId').unblock();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
JS
|
||||
EOF
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
||||
{
|
||||
clearInterval(AutoReloadDashboardId$sDivId);
|
||||
@@ -1006,75 +970,60 @@ EOF
|
||||
);
|
||||
}
|
||||
|
||||
if ($bCanEdit) {
|
||||
$this->RenderSelector($oPage, $oDashboard, $aAjaxParams);
|
||||
$this->RenderEditionTools($oPage, $oDashboard, $aAjaxParams);
|
||||
if ($bCanEdit)
|
||||
{
|
||||
$this->RenderSelector($oPage, $aAjaxParams);
|
||||
$this->RenderEditionTools($oPage, $aAjaxParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebPage $oPage
|
||||
* @param \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout $oDashboard
|
||||
* @param bool $bFromDashboardPage
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param array $aAjaxParams
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = array())
|
||||
protected function RenderSelector($oPage, $aAjaxParams = array())
|
||||
{
|
||||
if (!$this->HasCustomDashboard()) {
|
||||
return;
|
||||
}
|
||||
$sId = $this->GetId();
|
||||
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
||||
$sExtraParams = json_encode($aAjaxParams);
|
||||
|
||||
$sSwitchToStandard = Dict::S('UI:Toggle:SwitchToStandardDashboard');
|
||||
$sSwitchToCustom = Dict::S('UI:Toggle:SwitchToCustomDashboard');
|
||||
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
||||
$sSelectorHtml = '<div class="dashboard-selector">';
|
||||
if ($this->HasCustomDashboard())
|
||||
{
|
||||
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
||||
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
|
||||
$sSelectorHtml .= '<div class="selector-label">'.$sStandard.'</div>';
|
||||
$sSelectorHtml .= '<label class="switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="slider round"></span></label></input></label>';
|
||||
$sCustom = Dict::S('UI:Toggle:CustomDashboard');
|
||||
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
|
||||
|
||||
$sSelectorHtml = '<div id="ibo-dashboard-selector'.$sDivId.'" class="ibo-dashboard--selector" data-tooltip-content="'.($bStandardSelected ? $sSwitchToCustom : $sSwitchToStandard).'">';
|
||||
$sSelectorHtml .= '<label class="ibo-dashboard--switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="ibo-dashboard--slider"></span></label></input></label>';
|
||||
}
|
||||
$sSelectorHtml .= '</div>';
|
||||
|
||||
$sSelectorHtml = addslashes($sSelectorHtml);
|
||||
$sFile = addslashes($this->GetDefinitionFile());
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
|
||||
$bFromDashboardPage = isset($aAjaxParams['from_dashboard_page']) ? isset($aAjaxParams['from_dashboard_page']) : false;
|
||||
if ($bFromDashboardPage) {
|
||||
if ($oPage instanceof iTopWebPage) {
|
||||
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||
$oToolbar->AddHtml($sSelectorHtml);
|
||||
}
|
||||
} else {
|
||||
$oToolbar = $oDashboard->GetToolbar();
|
||||
$oToolbar->AddHtml($sSelectorHtml);
|
||||
}
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('.dashboard-title').after('$sSelectorHtml');
|
||||
EOF
|
||||
);
|
||||
|
||||
$oPage->add_script(
|
||||
<<<JS
|
||||
<<<EOF
|
||||
function ToggleDashboardSelector$sDivId()
|
||||
{
|
||||
var dashboard = $('.ibo-dashboard#$sDivId')
|
||||
dashboard.block();
|
||||
$('.dashboard_contents#$sDivId').block();
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
|
||||
function(data) {
|
||||
dashboard.html(data);
|
||||
dashboard.unblock();
|
||||
if ($('#ibo-dashboard-selector$sDivId input').prop("checked")) {
|
||||
$('#ibo-dashboard-selector$sDivId').attr('data-tooltip-content', '$sSwitchToStandard');
|
||||
} else {
|
||||
$('#ibo-dashboard-selector$sDivId').attr('data-tooltip-content', '$sSwitchToCustom');
|
||||
}
|
||||
CombodoTooltip.InitAllNonInstantiatedTooltips($('#ibo-dashboard-selector$sDivId').parent(), true);
|
||||
$('.dashboard_contents#$sDivId').html(data);
|
||||
$('.dashboard_contents#$sDivId').unblock();
|
||||
}
|
||||
);
|
||||
}
|
||||
JS
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1105,59 +1054,45 @@ JS
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aExtraParams)
|
||||
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
|
||||
{
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
||||
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||
|
||||
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
||||
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
||||
$sName = 'UI:Dashboard:Actions';
|
||||
|
||||
$bFromDashboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
||||
if ($bFromDashboardPage) {
|
||||
if (!($oPage instanceof iTopWebPage)) {
|
||||
// TODO 3.0 change the menu
|
||||
return;
|
||||
}
|
||||
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||
} else {
|
||||
$oToolbar = $oDashboard->GetToolbar();
|
||||
}
|
||||
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S($sName), $sName, '', false, $sMenuTogglerId)
|
||||
->AddCSSClass('ibo-top-bar--toolbar-dashboard-menu-toggler')
|
||||
->AddCSSClass('ibo-action-button');
|
||||
|
||||
$oToolbar->AddSubBlock($oActionButton);
|
||||
|
||||
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><i class=\"top-right-icon icon-additional-arrow fas fa-pencil-alt\"></i><ul>";
|
||||
|
||||
$aActions = array();
|
||||
$sFile = addslashes($this->sDefinitionFile);
|
||||
$sJSExtraParams = json_encode($aExtraParams);
|
||||
if ($this->HasCustomDashboard()) {
|
||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:DeleteCustom'),
|
||||
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
||||
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
||||
} else {
|
||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||
$bCanEdit = true;
|
||||
if ($this->HasCustomDashboard())
|
||||
{
|
||||
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
|
||||
}
|
||||
if ($bCanEdit)
|
||||
{
|
||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||
}
|
||||
|
||||
|
||||
if ($this->bCustomized)
|
||||
{
|
||||
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
|
||||
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
||||
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
||||
}
|
||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
||||
|
||||
$oActionsMenu = $oPage->GetPopoverMenu($sPopoverMenuId, $aActions)
|
||||
->SetTogglerJSSelector("#$sMenuTogglerId")
|
||||
->SetContainer(PopoverMenu::ENUM_CONTAINER_BODY);
|
||||
|
||||
$oToolbar->AddSubBlock($oActionButton)
|
||||
->AddSubBlock($oActionsMenu);
|
||||
|
||||
$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
|
||||
$sEditMenu = addslashes($sEditMenu);
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('.dashboard-title').after('$sEditMenu');
|
||||
$('#DashboardMenu>ul').popupmenu();
|
||||
|
||||
EOF
|
||||
);
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
function EditDashboard(sId, sDashboardFile, aExtraParams)
|
||||
{
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile, extra_params: aExtraParams, reload_url: '$sReloadURL'},
|
||||
@@ -1191,7 +1126,7 @@ EOF
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('#select_layout input').on('click', function() {
|
||||
$('#select_layout input').click( function() {
|
||||
var sLayoutClass = $(this).val();
|
||||
$('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass});
|
||||
} );
|
||||
@@ -1230,37 +1165,40 @@ EOF
|
||||
*/
|
||||
public function RenderEditor($oPage, $aExtraParams = array())
|
||||
{
|
||||
if (isset($aExtraParams['this->class'])) {
|
||||
if (isset($aExtraParams['this->class']))
|
||||
{
|
||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRenderParams = $aExtraParams;
|
||||
}
|
||||
$aRenderParams['dashboard_div_id'] = $aExtraParams['dashboard_div_id'];
|
||||
$sJSExtraParams = json_encode($aExtraParams);
|
||||
$oPage->add('<div id="dashboard_editor" class="ibo-dashboard-editor" data-role="ibo-dashboard-editor">');
|
||||
$oPage->add('<div id="dashboard_editor">');
|
||||
$oPage->add('<div class="ui-layout-center">');
|
||||
$this->SetCustomFlag(true);
|
||||
$this->Render($oPage, true, $aRenderParams);
|
||||
$oPage->add('</div>');
|
||||
$oPage->add('<div class="ui-layout-east ibo-dashboard-editor--pane" data-role="ibo-dashboard-editor--pane">');
|
||||
$oPage->add('<div class="ui-layout-east">');
|
||||
$this->RenderProperties($oPage, $aExtraParams);
|
||||
$this->RenderDashletsSelection($oPage);
|
||||
$this->RenderDashletsProperties($oPage, $aExtraParams);
|
||||
$oPage->add('</div>');
|
||||
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
|
||||
$oPage->add('</div>');
|
||||
|
||||
|
||||
$sDialogTitle = Dict::S('UI:DashboardEdit:Title');
|
||||
$sOkButtonLabel = Dict::S('UI:Button:Save');
|
||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||
|
||||
$sId = addslashes($this->sId);
|
||||
$sLayoutClass = addslashes($this->sLayoutClass);
|
||||
$sId = utils::HtmlEntities($this->sId);
|
||||
$sLayoutClass = utils::HtmlEntities($this->sLayoutClass);
|
||||
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
|
||||
$sAutoReloadSec = (string) $this->iAutoReloadSec;
|
||||
$sTitle = addslashes($this->sTitle);
|
||||
$sFile = addslashes($this->GetDefinitionFile());
|
||||
$sTitle = utils::HtmlEntities($this->sTitle);
|
||||
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
|
||||
@@ -1278,24 +1216,7 @@ $('#dashboard_editor').dialog({
|
||||
modal: true,
|
||||
title: '$sDialogTitle',
|
||||
buttons: [
|
||||
{ text: "$sCancelButtonLabel",
|
||||
class: "ibo-is-alternative",
|
||||
click: function() {
|
||||
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
||||
if (oDashboard.is_modified())
|
||||
{
|
||||
if (!confirm('$sCancelConfirmationMessage'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
window.bLeavingOnUserAction = true;
|
||||
$(this).dialog( "close" );
|
||||
$(this).remove();
|
||||
} },
|
||||
{ text: "$sOkButtonLabel",
|
||||
class: "ibo-is-primary",
|
||||
click: function() {
|
||||
{ text: "$sOkButtonLabel", click: function() {
|
||||
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
||||
if (oDashboard.is_dirty())
|
||||
{
|
||||
@@ -1311,6 +1232,19 @@ $('#dashboard_editor').dialog({
|
||||
window.bLeavingOnUserAction = true;
|
||||
oDashboard.save($(this));
|
||||
} },
|
||||
{ text: "$sCancelButtonLabel", click: function() {
|
||||
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
||||
if (oDashboard.is_modified())
|
||||
{
|
||||
if (!confirm('$sCancelConfirmationMessage'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
window.bLeavingOnUserAction = true;
|
||||
$(this).dialog( "close" );
|
||||
$(this).remove();
|
||||
} },
|
||||
],
|
||||
close: function() { $(this).remove(); }
|
||||
});
|
||||
@@ -1328,16 +1262,20 @@ $('#dashboard_editor .ui-layout-center').runtimedashboard({
|
||||
new_dashlet_parameters: {operation: 'new_dashlet'}
|
||||
});
|
||||
|
||||
var dashboard_prop_size = GetUserPreference('dashboard_prop_size', 400);
|
||||
$('#dashboard_editor > .itop-dashboard').width($('#dashboard_editor').width() - dashboard_prop_size);
|
||||
|
||||
// We check when we finish click on the pane with the resize slider
|
||||
// if the pane size changed (% 5px), if it's the case we save the value in userpref
|
||||
$('#dashboard_editor > .itop-dashboard').on('mouseup',function (){
|
||||
var iWidthDiff = $(this).width() - ($('#dashboard_editor').width() - dashboard_prop_size);
|
||||
if( Math.abs(iWidthDiff) > 5){
|
||||
dashboard_prop_size = iWidthDiff;
|
||||
SetUserPreference('dashboard_prop_size', $('#dashboard_editor').width() - $(this).width(), true);
|
||||
dashboard_prop_size = GetUserPreference('dashboard_prop_size', 350);
|
||||
$('#dashboard_editor').layout({
|
||||
east: {
|
||||
minSize: 200,
|
||||
size: dashboard_prop_size,
|
||||
togglerLength_open: 0,
|
||||
togglerLength_closed: 0,
|
||||
onresize_end: function(name, elt, state, options, layout)
|
||||
{
|
||||
if (state.isSliding == false)
|
||||
{
|
||||
SetUserPreference('dashboard_prop_size', state.size, true);
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1499,37 +1437,32 @@ JS
|
||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
<<<JS
|
||||
$('#dashlet_creation_dlg').dialog({
|
||||
width: 600,
|
||||
modal: true,
|
||||
title: '$sDialogTitle',
|
||||
buttons: [
|
||||
{ text: "$sCancelButtonLabel",
|
||||
click: function() {
|
||||
{ text: "$sOkButtonLabel", click: function() {
|
||||
var oForm = $(this).find('form');
|
||||
var sFormId = oForm.attr('id');
|
||||
var oParams = null;
|
||||
var aErrors = ValidateForm(sFormId, false);
|
||||
if (aErrors.length == 0)
|
||||
{
|
||||
oParams = ReadFormParams(sFormId);
|
||||
}
|
||||
oParams.operation = 'add_dashlet';
|
||||
var me = $(this);
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
|
||||
me.dialog( "close" );
|
||||
me.remove();
|
||||
$('body').append(data);
|
||||
});
|
||||
} },
|
||||
{ text: "$sCancelButtonLabel", click: function() {
|
||||
$(this).dialog( "close" ); $(this).remove();
|
||||
} ,
|
||||
'class': 'ibo-button ibo-is-alternative ibo-is-neutral action cancel'
|
||||
},
|
||||
{ text: "$sOkButtonLabel",
|
||||
click: function() {
|
||||
var oForm = $(this).find('form');
|
||||
var sFormId = oForm.attr('id');
|
||||
var oParams = null;
|
||||
var aErrors = ValidateForm(sFormId, false);
|
||||
if (aErrors.length == 0)
|
||||
{
|
||||
oParams = ReadFormParams(sFormId);
|
||||
}
|
||||
oParams.operation = 'add_dashlet';
|
||||
var me = $(this);
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
|
||||
me.dialog( "close" );
|
||||
me.remove();
|
||||
$('body').append(data);
|
||||
});
|
||||
},
|
||||
'class': 'ibo-button ibo-is-regular ibo-is-primary action' }
|
||||
} },
|
||||
],
|
||||
close: function() { $(this).remove(); }
|
||||
});
|
||||
@@ -1545,6 +1478,29 @@ JS
|
||||
return $this->sDefinitionFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDashboardFileRelative can also be an absolute path (compatibility with old URL)
|
||||
*
|
||||
* @return string full path to the Dashboard file
|
||||
* @throws \SecurityException if path isn't under approot
|
||||
* @uses utils::RealPath()
|
||||
* @since 2.7.8 3.0.3 3.1.0 N°4449 remove FPD
|
||||
*/
|
||||
public static function GetDashboardFileFromRelativePath($sDashboardFileRelative)
|
||||
{
|
||||
if (utils::RealPath($sDashboardFileRelative, APPROOT)) {
|
||||
// compatibility with old URL containing absolute path !
|
||||
return $sDashboardFileRelative;
|
||||
}
|
||||
|
||||
$sDashboardFile = APPROOT.$sDashboardFileRelative;
|
||||
if (false === utils::RealPath($sDashboardFile, APPROOT)) {
|
||||
throw new SecurityException('Invalid dashboard file !');
|
||||
}
|
||||
|
||||
return $sDashboardFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDefinitionFile
|
||||
*/
|
||||
@@ -1643,10 +1599,12 @@ JS
|
||||
{
|
||||
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
|
||||
$aClassAliases = array();
|
||||
try {
|
||||
try{
|
||||
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
|
||||
$aClassAliases = $oFilter->GetSelectedClasses();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
//on error, return default value
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -15,17 +15,15 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow;
|
||||
|
||||
/**
|
||||
* Dashboard presentation
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
abstract class DashboardLayout
|
||||
{
|
||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||
@@ -116,59 +114,61 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||
$aCells = $this->TrimCellsArray($aCells);
|
||||
|
||||
$oDashboardLayout = new DashboardLayoutUIBlock();
|
||||
//$oPage->AddUiBlock($oDashboardLayout);
|
||||
|
||||
$oPage->add('<table style="width:100%;table-layout:fixed;"><tbody>');
|
||||
$iCellIdx = 0;
|
||||
$fColSize = 100 / $this->iNbCols;
|
||||
$sStyle = $bEditMode ? 'border: 1px #ccc dashed; width:'.$fColSize.'%;' : 'width: '.$fColSize.'%;';
|
||||
$sClass = $bEditMode ? 'layout_cell edit_mode' : 'dashboard';
|
||||
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||
|
||||
//Js given by each dashlet to reload
|
||||
$sJSReload = "";
|
||||
|
||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||
$oDashboardRow = new DashboardRow();
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
|
||||
if (array_key_exists($iCellIdx, $aCells)) {
|
||||
for($iRows = 0; $iRows < $iNbRows; $iRows++)
|
||||
{
|
||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$sCellClass = ($iRows == $iNbRows-1) ? $sClass.' layout_last_used_rank' : $sClass;
|
||||
$oPage->add("<td style=\"$sStyle\" class=\"$sCellClass\" data-dashboard-column-index=\"$iCols\" data-dashboard-cell-index=\"$iCellIdx\">");
|
||||
if (array_key_exists($iCellIdx, $aCells))
|
||||
{
|
||||
$aDashlets = $aCells[$iCellIdx];
|
||||
if (count($aDashlets) > 0) {
|
||||
if (count($aDashlets) > 0)
|
||||
{
|
||||
/** @var \Dashlet $oDashlet */
|
||||
foreach ($aDashlets as $oDashlet) {
|
||||
if ($oDashlet::IsVisible()) {
|
||||
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||
foreach($aDashlets as $oDashlet)
|
||||
{
|
||||
if ($oDashlet::IsVisible())
|
||||
{
|
||||
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
$oPage->add('</td>');
|
||||
$iCellIdx++;
|
||||
}
|
||||
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
|
||||
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||
|
||||
if ($bEditMode) // Add one row for extensibility
|
||||
{
|
||||
$oDashboardRow = new DashboardRow();
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode, true);
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
$sStyle = 'style="border: 1px #ccc dashed; width:'.$fColSize.'%;" class="layout_cell edit_mode layout_extension" data-dashboard-cell-index="'.$iCellIdx.'"';
|
||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$oPage->add("<td $sStyle data-dashboard-column-index=\"$iCols\">");
|
||||
$oPage->add(' ');
|
||||
$oPage->add('</td>');
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
|
||||
return $oDashboardLayout;
|
||||
$oPage->add('</tbody></table>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<classes>
|
||||
<class id="AbstractResource" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<comment>/* Resource access control abstraction. Can be herited by abstract resource access control classes. Generaly controlled using UR_ACTION_MODIFY access right. */</comment>
|
||||
<abstract>true</abstract>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceAdminMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* AdminTools menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceRunQueriesMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* RunQueriesMenu menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ResourceSystemMenu" _delta="define">
|
||||
<parent>AbstractResource</parent>
|
||||
<properties>
|
||||
<comment>/* System menu access control. */</comment>
|
||||
<abstract>true</abstract>
|
||||
<category>grant_by_profile</category>
|
||||
</properties>
|
||||
<presentation/>
|
||||
<methods/>
|
||||
</class>
|
||||
</classes>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
|
||||
<portals>
|
||||
<portal id="backoffice" _delta="define">
|
||||
<url>pages/UI.php</url>
|
||||
@@ -53,424 +12,13 @@
|
||||
</portal>
|
||||
</portals>
|
||||
<menus>
|
||||
<menu id="WelcomeMenu" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>10</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-home</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="WelcomeMenuPage" xsi:type="DashboardMenuNode" _delta="define">
|
||||
<rank>10</rank>
|
||||
<parent>WelcomeMenu</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title>Menu:WelcomeMenuPage</title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="MyShortcuts" xsi:type="ShortcutContainerMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>WelcomeMenu</parent>
|
||||
</menu>
|
||||
<menu id="UserManagement" xsi:type="TemplateMenuNode" _delta="define">
|
||||
<rank>10</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="UserAccountsMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>11</rank>
|
||||
<parent>UserManagement</parent>
|
||||
<oql><![CDATA[SELECT User]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<search_form_open>1</search_form_open>
|
||||
<enable_class>User</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ProfilesMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>12</rank>
|
||||
<parent>UserManagement</parent>
|
||||
<oql><![CDATA[SELECT URP_Profiles]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>URP_Profiles</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="AuditCategories" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<oql><![CDATA[SELECT AuditCategory]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>AuditCategory</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="Queries" xsi:type="TemplateMenuNode" _delta="define">
|
||||
<rank>30</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="RunQueriesMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>31</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$pages/run_query.php</url>
|
||||
<enable_class>ResourceRunQueriesMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="QueryMenu" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>32</rank>
|
||||
<parent>Queries</parent>
|
||||
<oql><![CDATA[SELECT Query]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>Query</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ExportMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>33</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$webservices/export-v2.php?interactive=1</url>
|
||||
<enable_class>ResourceAdminMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="DataModelMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>40</rank>
|
||||
<parent>AdminTools</parent>
|
||||
<url>$pages/schema.php</url>
|
||||
<enable_class>ResourceRunQueriesMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="UniversalSearchMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>35</rank>
|
||||
<parent>Queries</parent>
|
||||
<url>$pages/UniversalSearch.php</url>
|
||||
<enable_class>ResourceAdminMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="ConfigurationTools" xsi:type="MenuGroup" _delta="define_if_not_exists">
|
||||
<rank>90</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-cog</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="DataSources" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>20</rank>
|
||||
<parent>ConfigurationTools</parent>
|
||||
<oql><![CDATA[SELECT SynchroDataSource]]></oql>
|
||||
<do_search>1</do_search>
|
||||
<enable_class>SynchroDataSource</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="NotificationsMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>40</rank>
|
||||
<parent>ConfigurationTools</parent>
|
||||
<url>$pages/notifications.php</url>
|
||||
<enable_class>Trigger</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>80</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-tools</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>100</rank>
|
||||
<enable_class>ResourceSystemMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
<style>
|
||||
<decoration_classes>fas fa-terminal</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
</menus>
|
||||
<meta>
|
||||
<classes>
|
||||
<class id="cmdbAbstractObject" _delta="define">
|
||||
<methods>
|
||||
<method id="Set">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
<type id="AttributeLinkedSetIndirect"/>
|
||||
<type id="AttributeLinkedSet"/>
|
||||
<type id="AttributeImage"/>
|
||||
<type id="AttributeBlob"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
<type id="AttributeLinkedSetIndirect"/>
|
||||
<type id="AttributeLinkedSet"/>
|
||||
<type id="AttributeImage"/>
|
||||
<type id="AttributeBlob"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="AddValue">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeDecimal"/>
|
||||
<type id="AttributePercentage"/>
|
||||
<type id="AttributeDuration"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetComputedDate">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>attcode</type>
|
||||
<mandatory>false</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetComputedDateIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>attcode</type>
|
||||
<mandatory>false</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentDate">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentDateIfNull">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentUser">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeExternalKey"/>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentPerson">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeExternalKey"/>
|
||||
<type id="AttributeInteger"/>
|
||||
<type id="AttributeString"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetElapsedTime">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDuration"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeDate"/>
|
||||
<type id="AttributeDateTime"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="3">
|
||||
<type>string</type>
|
||||
<mandatory>false</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Reset">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="ResetStopWatch">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>allow</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Copy">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<type_restrictions>
|
||||
<operation>deny</operation>
|
||||
<types>
|
||||
<type id="AttributeStopWatch"/>
|
||||
<type id="AttributeSubItem"/>
|
||||
<type id="AttributeExternalField"/>
|
||||
</types>
|
||||
</type_restrictions>
|
||||
</argument>
|
||||
<argument id="2">
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="ApplyStimulus">
|
||||
<arguments>
|
||||
<argument id="1">
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
</classes>
|
||||
</meta>
|
||||
</itop_design>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -18,8 +15,6 @@ use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
* @deprecated since 3.0.0 use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable
|
||||
*/
|
||||
|
||||
class DataTable
|
||||
@@ -30,7 +25,7 @@ class DataTable
|
||||
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
|
||||
protected $oSet; // The set of objects to display
|
||||
protected $aClassAliases; // The aliases (alias => class) inside the set
|
||||
protected $iNbObjects; // Total number of objects in the set
|
||||
protected $iNbObjects; // Total number of objects inthe set
|
||||
protected $bUseCustomSettings; // Whether or not the current display uses custom settings
|
||||
protected $oDefaultSettings; // the default settings for displaying such a list
|
||||
protected $bShowObsoleteData;
|
||||
@@ -48,7 +43,6 @@ class DataTable
|
||||
*/
|
||||
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable');
|
||||
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
|
||||
$this->sDatatableContainerId = 'datatable_'.utils::GetSafeId($iListId);
|
||||
$this->oSet = $oSet;
|
||||
@@ -116,7 +110,8 @@ class DataTable
|
||||
// See if this column is a must to load
|
||||
$sClass = $this->aClassAliases[$sAlias];
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef->AlwaysLoadInTables()) {
|
||||
if ($oAttDef->alwaysLoadInTables())
|
||||
{
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
@@ -162,17 +157,17 @@ class DataTable
|
||||
$sPager = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
||||
$sActionsMenu = '';
|
||||
$sToolkitMenu = '';
|
||||
if ($bActionsMenu) {
|
||||
if ($bActionsMenu)
|
||||
{
|
||||
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
|
||||
}
|
||||
// if ($bToolkitMenu)
|
||||
// {
|
||||
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
||||
// }
|
||||
|
||||
if ($bToolkitMenu)
|
||||
{
|
||||
$sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
||||
}
|
||||
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
||||
|
||||
|
||||
$sHtml = "<table id=\"{$this->sDatatableContainerId}\" class=\"datatable\">";
|
||||
$sHtml .= "<tr><td>";
|
||||
$sHtml .= "<table style=\"width:100%;\">";
|
||||
@@ -213,7 +208,7 @@ class DataTable
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When refreshing the body of a paginated table, get the rows of the table (inside the TBODY)
|
||||
* return string The HTML rows to insert inside the <tbody> node
|
||||
@@ -352,26 +347,17 @@ EOF;
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \ReflectionException
|
||||
* @throws \Twig\Error\LoaderError
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*/
|
||||
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
||||
{
|
||||
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
||||
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
||||
|
||||
return ConsoleBlockRenderer::RenderBlockTemplateInPage($oPage, $oBlock);
|
||||
|
||||
$sHtml = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +372,7 @@ EOF;
|
||||
if (!$oPage->IsPrintableVersion())
|
||||
{
|
||||
$sMenuTitle = Dict::S('UI:ConfigureThisList');
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li aria-label="'.Dict::S('UI:Menu:Toolkit').'"><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||
|
||||
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
|
||||
$aActions = array(
|
||||
@@ -527,7 +513,6 @@ EOF;
|
||||
return $aAttribs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
@@ -875,3 +860,396 @@ class PrintableDataTable extends DataTable
|
||||
return $sHtml;
|
||||
}
|
||||
}
|
||||
|
||||
class DataTableSettings implements Serializable
|
||||
{
|
||||
public $aClassAliases;
|
||||
public $sTableId;
|
||||
public $iDefaultPageSize;
|
||||
public $aColumns;
|
||||
|
||||
|
||||
/**
|
||||
* DataTableSettings constructor.
|
||||
*
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
*/
|
||||
public function __construct($aClassAliases, $sTableId = null)
|
||||
{
|
||||
$this->aClassAliases = $aClassAliases;
|
||||
$this->sTableId = $sTableId;
|
||||
$this->iDefaultPageSize = 10;
|
||||
$this->aColumns = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $iDefaultPageSize
|
||||
* @param $aSortOrder
|
||||
* @param $aColumns
|
||||
*/
|
||||
protected function Init($iDefaultPageSize, $aSortOrder, $aColumns)
|
||||
{
|
||||
$this->iDefaultPageSize = $iDefaultPageSize;
|
||||
$this->aColumns = $aColumns;
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
// Save only the 'visible' columns
|
||||
$aColumns = array();
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
$aColumns[$sAlias] = array();
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
unset($aData['label']); // Don't save the display name
|
||||
unset($aData['alias']); // Don't save the alias (redundant)
|
||||
unset($aData['code']); // Don't save the code (redundant)
|
||||
if ($aData['checked'])
|
||||
{
|
||||
$aColumns[$sAlias][$sAttCode] = $aData;
|
||||
}
|
||||
}
|
||||
}
|
||||
return serialize(
|
||||
array(
|
||||
'iDefaultPageSize' => $this->iDefaultPageSize,
|
||||
'aColumns' => $aColumns,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sData
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unserialize($sData)
|
||||
{
|
||||
$aData = unserialize($sData);
|
||||
$this->iDefaultPageSize = $aData['iDefaultPageSize'];
|
||||
$this->aColumns = $aData['aColumns'];
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
$aFieldData = false;
|
||||
if ($sAttCode == '_key_')
|
||||
{
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, null, true /* bChecked */, $aData['sort']);
|
||||
}
|
||||
else if (MetaModel::isValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $aData['sort']);
|
||||
}
|
||||
|
||||
if ($aFieldData)
|
||||
{
|
||||
$this->aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param $bViewLink
|
||||
* @param $aDefaultLists
|
||||
*
|
||||
* @return \DataTableSettings
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
static public function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
|
||||
{
|
||||
$oSettings = new DataTableSettings($aClassAliases);
|
||||
// Retrieve the class specific settings for each class/alias based on the 'list' ZList
|
||||
//TODO let the caller pass some other default settings (another Zlist, extre fields...)
|
||||
$aColumns = array();
|
||||
foreach($aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
if ($aDefaultLists == null)
|
||||
{
|
||||
$aList = cmdbAbstract::FlattenZList(MetaModel::GetZListItems($sClass, 'list'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aList = $aDefaultLists[$sAlias];
|
||||
}
|
||||
|
||||
$aSortOrder = MetaModel::GetOrderByDefault($sClass);
|
||||
if ($bViewLink)
|
||||
{
|
||||
$sSort = 'none';
|
||||
if(array_key_exists('friendlyname', $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder['friendlyname'] ? 'asc' : 'desc';
|
||||
}
|
||||
$sNormalizedFName = MetaModel::NormalizeFieldSpec($sClass, 'friendlyname');
|
||||
if(array_key_exists($sNormalizedFName, $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder[$sNormalizedFName] ? 'asc' : 'desc';
|
||||
}
|
||||
|
||||
$aColumns[$sAlias]['_key_'] = $oSettings->GetFieldData($sAlias, '_key_', null, true /* bChecked */, $sSort);
|
||||
}
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
$sSort = 'none';
|
||||
if(array_key_exists($sAttCode, $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder[$sAttCode] ? 'asc' : 'desc';
|
||||
}
|
||||
$oAttDef = Metamodel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $oSettings->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $sSort);
|
||||
if ($aFieldData) $aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
}
|
||||
}
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oSettings->Init($iDefaultPageSize, $aSortOrder, $aColumns);
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function FixVisibleColumns()
|
||||
{
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
if (!isset($this->aColumns[$sAlias]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
// Remove non-existent columns
|
||||
// TODO: check if the existing ones are still valid (in case their type changed)
|
||||
if (($sAttCode != '_key_') && (!MetaModel::IsValidAttCode($sClass, $sAttCode)))
|
||||
{
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
$aList = MetaModel::ListAttributeDefs($sClass);
|
||||
|
||||
// Add the other (non visible ones), sorted in alphabetical order
|
||||
$aTempData = array();
|
||||
foreach($aList as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!($oAttDef instanceof AttributeLinkedSet || $oAttDef instanceof AttributeDashboard)))
|
||||
{
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false /* bChecked */, 'none');
|
||||
if ($aFieldData) $aTempData[$aFieldData['label']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
ksort($aTempData);
|
||||
foreach($aTempData as $sLabel => $aFieldData)
|
||||
{
|
||||
$this->aColumns[$sAlias][$aFieldData['code']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
* @param bool $bOnlyOnTable
|
||||
*
|
||||
* @return \DataTableSettings|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
static public function GetTableSettings($aClassAliases, $sTableId = null, $bOnlyOnTable = false)
|
||||
{
|
||||
$pref = null;
|
||||
$oSettings = new DataTableSettings($aClassAliases, $sTableId);
|
||||
|
||||
if ($sTableId != null)
|
||||
{
|
||||
// An identified table, let's fetch its own settings (if any)
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey($sTableId), null);
|
||||
}
|
||||
|
||||
if ($pref == null)
|
||||
{
|
||||
if (!$bOnlyOnTable)
|
||||
{
|
||||
// Try the global preferred values for this class / set of classes
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey(null), null);
|
||||
}
|
||||
if ($pref == null)
|
||||
{
|
||||
// no such settings, use the default values provided by the data model
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$oSettings->unserialize($pref);
|
||||
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetSortOrder()
|
||||
{
|
||||
$aSortOrder = array();
|
||||
foreach($this->aColumns as $sAlias => $aColumns)
|
||||
{
|
||||
foreach($aColumns as $aColumn)
|
||||
{
|
||||
if ($aColumn['sort'] != 'none')
|
||||
{
|
||||
$sCode = ($aColumn['code'] == '_key_') ? 'friendlyname' : $aColumn['code'];
|
||||
$aSortOrder[$sCode] = ($aColumn['sort']=='asc'); // true for ascending, false for descending
|
||||
}
|
||||
}
|
||||
break; // TODO: For now the Set object supports only sorting on the first class of the set
|
||||
}
|
||||
return $aSortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTargetTableId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($sTargetTableId = null)
|
||||
{
|
||||
$sSaveId = is_null($sTargetTableId) ? $this->sTableId : $sTargetTableId;
|
||||
if ($sSaveId == null) return false; // Cannot save, the table is not identified, use SaveAsDefault instead
|
||||
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey($sSaveId), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAsDefault()
|
||||
{
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey(null), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the preferences for this particular table
|
||||
* @param $bResetAll boolean If true,the settings for all tables of the same class(es)/alias(es) are reset
|
||||
*/
|
||||
public function ResetToDefault($bResetAll)
|
||||
{
|
||||
if (($this->sTableId == null) && (!$bResetAll)) return false; // Cannot reset, the table is not identified, use force $bResetAll instead
|
||||
if ($bResetAll)
|
||||
{
|
||||
// Turn the key into a suitable PCRE pattern
|
||||
$sKey = $this->GetPrefsKey(null);
|
||||
$sPattern = str_replace(array('|'), array('\\|'), $sKey); // escape the | character
|
||||
$sPattern = '#^'.str_replace(array('*'), array('.*'), $sPattern).'$#'; // Don't use slash as the delimiter since it's used in our key to delimit aliases
|
||||
appUserPreferences::UnsetPref($sPattern, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
appUserPreferences::UnsetPref($this->GetPrefsKey($this->sTableId), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTableId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetPrefsKey($sTableId = null)
|
||||
{
|
||||
return static::GetAppUserPreferenceKey($this->aClassAliases, $sTableId);
|
||||
}
|
||||
|
||||
public static function GetAppUserPreferenceKey($aClassAliases, $sTableId)
|
||||
{
|
||||
if ($sTableId === null)
|
||||
{
|
||||
$sTableId = '*';
|
||||
}
|
||||
|
||||
$aKeys = array();
|
||||
foreach($aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
$aKeys[] = $sAlias.'-'.$sClass;
|
||||
}
|
||||
return implode('/', $aKeys).'|'.$sTableId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sAlias
|
||||
* @param $sAttCode
|
||||
* @param $oAttDef
|
||||
* @param $bChecked
|
||||
* @param $sSort
|
||||
*
|
||||
* @return array|bool
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
protected function GetFieldData($sAlias, $sAttCode, $oAttDef, $bChecked, $sSort)
|
||||
{
|
||||
$ret = false;
|
||||
if ($sAttCode == '_key_')
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', MetaModel::GetName($this->aClassAliases[$sAlias]));
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => true,
|
||||
'disabled' => true,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
}
|
||||
else if (!$oAttDef->IsLinkSet())
|
||||
{
|
||||
$sLabel = $oAttDef->GetLabel();
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', $oAttDef->GetLabel());
|
||||
}
|
||||
else if ($oAttDef->IsExternalField())
|
||||
{
|
||||
if ($oAttDef->IsFriendlyName())
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExtAttDef = $oAttDef->GetExtAttDef();
|
||||
$sLabel = Dict::Format('UI:ExtField_AsRemoteField', $oAttDef->GetLabel(), $oExtAttDef->GetLabel());
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeFriendlyName)
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => $bChecked,
|
||||
'disabled' => false,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||
|
||||
class ErrorPage extends NiceWebPage
|
||||
{
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
parent::__construct($sTitle);
|
||||
$this->add_linked_script("../js/jquery.blockUI.js");
|
||||
$this->add_linked_script("../setup/setup.js");
|
||||
$this->add_saas("css/setup.scss");
|
||||
}
|
||||
|
||||
public function info($sText)
|
||||
{
|
||||
$this->add("<p class=\"info\">$sText</p>\n");
|
||||
$this->log_info($sText);
|
||||
}
|
||||
|
||||
public function ok($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-valid\"><span class=\"message-title\">Success:</span>$sText</div>");
|
||||
$this->log_ok($sText);
|
||||
}
|
||||
|
||||
public function warning($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-warning\"><span class=\"message-title\">Warning:</span>$sText</div>");
|
||||
$this->log_warning($sText);
|
||||
}
|
||||
|
||||
public function error($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-error\">$sText</div>");
|
||||
$this->log_error($sText);
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$sLogo = utils::GetAbsoluteUrlAppRoot().'/images/itop-logo.png';
|
||||
$sTimeStamp = utils::GetCacheBusterTimestamp();
|
||||
$sTitle = utils::HtmlEntities($this->s_title);
|
||||
$this->s_content = <<<HTML
|
||||
<div id="header" class="error_page">
|
||||
<h1><a href="http://www.combodo.com/itop" target="_blank"><img title="iTop by Combodo" alt=" " src="{$sLogo}?t={$sTimeStamp}"></a> {$sTitle}</h1>
|
||||
</div>
|
||||
<div id="setup" class="error_page">
|
||||
{$this->s_content}
|
||||
</div>
|
||||
HTML;
|
||||
return parent::output();
|
||||
}
|
||||
|
||||
public static function log_error($sText)
|
||||
{
|
||||
IssueLog::Error($sText);
|
||||
}
|
||||
|
||||
public static function log_warning($sText)
|
||||
{
|
||||
IssueLog::Warning($sText);
|
||||
}
|
||||
|
||||
public static function log_info($sText)
|
||||
{
|
||||
IssueLog::Info($sText);
|
||||
}
|
||||
|
||||
public static function log_ok($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
|
||||
public static function log($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class ApplicationException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thrown when querying on an object that exists in the database but is archived
|
||||
*
|
||||
* @since 2.5.1 N°1108
|
||||
*/
|
||||
class ArchivedObjectException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class BulkChangeException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CSVParserException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class ConfigException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CoreCannotSaveObjectException
|
||||
*
|
||||
* Specialized exception to raise if {@link DBObject::CheckToWrite()} fails, which allow easy data retrieval
|
||||
*
|
||||
* @see \DBObject::DBInsertNoReload()
|
||||
* @see \DBObject::DBUpdate()
|
||||
*
|
||||
* @since 2.6.0 N°659 uniqueness constraint
|
||||
*/
|
||||
class CoreCannotSaveObjectException extends CoreException
|
||||
{
|
||||
/** @var string[] */
|
||||
private $aIssues;
|
||||
/** @var int */
|
||||
private $iObjectId;
|
||||
/** @var string */
|
||||
private $sObjectClass;
|
||||
|
||||
/**
|
||||
* CoreCannotSaveObjectException constructor.
|
||||
*
|
||||
* @param array $aContextData containing at least those keys : issues, id, class
|
||||
*/
|
||||
public function __construct($aContextData, $oPrevious = null)
|
||||
{
|
||||
$this->aIssues = $aContextData['issues'];
|
||||
$this->iObjectId = $aContextData['id'];
|
||||
$this->sObjectClass = $aContextData['class'];
|
||||
|
||||
$sIssues = implode(', ', $this->aIssues);
|
||||
parent::__construct($sIssues, $aContextData, '', $oPrevious);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHtmlMessage()
|
||||
{
|
||||
$sTitle = Dict::S('UI:Error:SaveFailed');
|
||||
$sContent = "<span><strong>{$sTitle}</strong></span>";
|
||||
|
||||
if (count($this->aIssues) == 1) {
|
||||
$sIssue = reset($this->aIssues);
|
||||
$sContent .= " <span>{$sIssue}</span>";
|
||||
} else {
|
||||
$sContent .= '<ul>';
|
||||
foreach ($this->aIssues as $sError) {
|
||||
$sContent .= "<li>$sError</li>";
|
||||
}
|
||||
$sContent .= '</ul>';
|
||||
}
|
||||
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
public function getIssues()
|
||||
{
|
||||
return $this->aIssues;
|
||||
}
|
||||
|
||||
public function getObjectId()
|
||||
{
|
||||
return $this->iObjectId;
|
||||
}
|
||||
|
||||
public function getObjectClass()
|
||||
{
|
||||
return $this->sObjectClass;
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreException extends Exception
|
||||
{
|
||||
/**
|
||||
* CoreException constructor.
|
||||
*
|
||||
* @param string $sIssue error message
|
||||
* @param array|null $aContextData key/value array, value MUST implements _toString
|
||||
* @param string $sImpact
|
||||
* @param Exception|null $oPrevious
|
||||
*/
|
||||
public function __construct($sIssue, $aContextData = null, $sImpact = '', $oPrevious = null)
|
||||
{
|
||||
$this->m_sIssue = $sIssue;
|
||||
$this->m_sImpact = $sImpact;
|
||||
|
||||
if (is_array($aContextData)) {
|
||||
$this->m_aContextData = $aContextData;
|
||||
} else {
|
||||
$this->m_aContextData = [];
|
||||
}
|
||||
|
||||
$sMessage = $sIssue;
|
||||
if (!empty($sImpact)) {
|
||||
$sMessage .= "($sImpact)";
|
||||
}
|
||||
if (count($this->m_aContextData) > 0) {
|
||||
$sMessage .= ": ";
|
||||
$aContextItems = array();
|
||||
foreach ($this->m_aContextData as $sKey => $value) {
|
||||
if (is_array($value)) {
|
||||
$aPairs = array();
|
||||
foreach ($value as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$aPairs[] = $key.'=>('.implode(', ', $val).')';
|
||||
} else {
|
||||
$aPairs[] = $key.'=>'.$val;
|
||||
}
|
||||
}
|
||||
$sValue = '{'.implode('; ', $aPairs).'}';
|
||||
} else {
|
||||
$sValue = $value;
|
||||
}
|
||||
$aContextItems[] = "$sKey = $sValue";
|
||||
}
|
||||
$sMessage .= implode(', ', $aContextItems);
|
||||
}
|
||||
parent::__construct($sMessage, 0, $oPrevious);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string code and message for log purposes
|
||||
*/
|
||||
public function getInfoLog()
|
||||
{
|
||||
return 'error_code='.$this->getCode().', message="'.$this->getMessage().'"';
|
||||
}
|
||||
|
||||
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
|
||||
{
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* getTraceAsString() cannot be overrided and it is limited as only current exception stack is returned.
|
||||
* we need stack of all previous exceptions
|
||||
*
|
||||
* @uses __tostring() already does the work.
|
||||
* @since 2.7.2/ 3.0.0
|
||||
*/
|
||||
public function getFullStackTraceAsString()
|
||||
{
|
||||
return "".$this;
|
||||
}
|
||||
|
||||
public function getTraceAsHtml()
|
||||
{
|
||||
$aBackTrace = $this->getTrace();
|
||||
|
||||
return MyHelpers::get_callstack_html(0, $this->getTrace());
|
||||
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
|
||||
}
|
||||
|
||||
public function addInfo($sKey, $value)
|
||||
{
|
||||
$this->m_aContextData[$sKey] = $value;
|
||||
}
|
||||
|
||||
public function getIssue()
|
||||
{
|
||||
return $this->m_sIssue;
|
||||
}
|
||||
|
||||
public function getImpact()
|
||||
{
|
||||
return $this->m_sImpact;
|
||||
}
|
||||
|
||||
public function getContextData()
|
||||
{
|
||||
return $this->m_aContextData;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 N°2555
|
||||
*/
|
||||
class CorePortalInvalidActionRuleException extends CoreException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 3.0.0 N°3522
|
||||
*/
|
||||
class CoreTemplateException extends CoreException
|
||||
{
|
||||
public function __construct(Exception $oTwigException, string $sTemplatePath)
|
||||
{
|
||||
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
|
||||
parent::__construct($sMessage, null, '', $oTwigException);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreUnexpectedValue extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class CoreWarning extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DeleteException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* A parameter stored in the {@link Config} is invalid
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class InvalidConfigParamException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thrown when the password is not valid
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class InvalidPasswordAttributeOneWayPassword extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\TwigBase\Controller;
|
||||
|
||||
use Exception;
|
||||
|
||||
class PageNotFoundException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class SecurityException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class SynchroExceptionNotStarted extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class UserRightException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DictException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DictExceptionMissingString extends DictException
|
||||
{
|
||||
public function __construct($sLanguageCode, $sStringCode)
|
||||
{
|
||||
$aContext = array();
|
||||
$aContext['language_code'] = $sLanguageCode;
|
||||
$aContext['string_code'] = $sStringCode;
|
||||
parent::__construct('Missing localized string', $aContext);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class DictExceptionUnknownLanguage extends DictException
|
||||
{
|
||||
public function __construct($sLanguageCode)
|
||||
{
|
||||
$aContext = array();
|
||||
$aContext['language_code'] = $sLanguageCode;
|
||||
parent::__construct('Unknown localization language', $aContext);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class MySQLException extends CoreException
|
||||
{
|
||||
/**
|
||||
* MySQLException constructor.
|
||||
*
|
||||
* @param string $sIssue
|
||||
* @param array $aContext
|
||||
* @param \Exception $oException
|
||||
* @param \mysqli $oMysqli to use when working with a custom mysqli instance
|
||||
*/
|
||||
public function __construct($sIssue, $aContext, $oException = null, $oMysqli = null)
|
||||
{
|
||||
if ($oException != null) {
|
||||
$aContext['mysql_errno'] = $oException->getCode();
|
||||
$this->code = $oException->getCode();
|
||||
$aContext['mysql_error'] = $oException->getMessage();
|
||||
} else if ($oMysqli != null) {
|
||||
$aContext['mysql_errno'] = $oMysqli->errno;
|
||||
$this->code = $oMysqli->errno;
|
||||
$aContext['mysql_error'] = $oMysqli->error;
|
||||
} else {
|
||||
$aContext['mysql_errno'] = CMDBSource::GetErrNo();
|
||||
$this->code = CMDBSource::GetErrNo();
|
||||
$aContext['mysql_error'] = CMDBSource::GetError();
|
||||
}
|
||||
parent::__construct($sIssue, $aContext);
|
||||
//if is connection error, don't log the default message with password in
|
||||
if (mysqli_connect_errno()) {
|
||||
error_log($this->message);
|
||||
error_reporting(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class MySQLHasGoneAwayException
|
||||
*
|
||||
* @see https://dev.mysql.com/doc/refman/5.7/en/gone-away.html
|
||||
* @since 2.5.0 N°1195
|
||||
*/
|
||||
class MySQLHasGoneAwayException extends MySQLException
|
||||
{
|
||||
/**
|
||||
* can not be a constant before PHP 5.6 (http://php.net/manual/fr/language.oop5.constants.php)
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public static function getErrorCodes()
|
||||
{
|
||||
return array(
|
||||
2006,
|
||||
2013,
|
||||
);
|
||||
}
|
||||
|
||||
public function __construct($sIssue, $aContext)
|
||||
{
|
||||
parent::__construct($sIssue, $aContext, null);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 N°679
|
||||
*/
|
||||
class MySQLNoTransactionException extends MySQLException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class MySQLQueryHasNoResultException
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
class MySQLQueryHasNoResultException extends MySQLException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 N°2555
|
||||
*/
|
||||
class CoreOqlException extends CoreException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 N°2555
|
||||
*/
|
||||
class CoreOqlMultipleResultsForbiddenException extends CoreOqlException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception for {@link iProcess} implementations.<br>
|
||||
* An error happened during the processing but we can go on with the next implementations.
|
||||
*
|
||||
* @since 2.5.0 N°1195
|
||||
*/
|
||||
class ProcessException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class ProcessFatalException
|
||||
* Exception for iProcess implementations.<br>
|
||||
* A big error occurred, we have to stop the iProcess processing.
|
||||
*
|
||||
* @since 2.5.0 N°1195
|
||||
*/
|
||||
class ProcessFatalException extends CoreException
|
||||
{
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 2.7.0 PR #89
|
||||
*/
|
||||
class ProcessInvalidConfigException extends ProcessException
|
||||
{
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FindStylesheetObject: dedicated class to store computations made in method ThemeHandler::FindStylesheetFile.
|
||||
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||
* @since 3.0.0 N°3588
|
||||
*/
|
||||
class FindStylesheetObject{
|
||||
|
||||
//file URIs
|
||||
private $aStylesheetFileURIs;
|
||||
|
||||
//fill paths
|
||||
private $aStylesheetImportPaths;
|
||||
private $aAllStylesheetFilePaths;
|
||||
private $sLastStyleSheetPath;
|
||||
|
||||
private $iLastModified;
|
||||
|
||||
/**
|
||||
* FindStylesheetObject constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->aStylesheetFileURIs = [];
|
||||
$this->aStylesheetImportPaths = [];
|
||||
$this->aAllStylesheetFilePaths = [];
|
||||
$this->sLastStyleSheetPath = "";
|
||||
$this->iLastModified = 0;
|
||||
}
|
||||
|
||||
public function GetLastStylesheetFile(): string
|
||||
{
|
||||
return $this->sLastStyleSheetPath;
|
||||
}
|
||||
|
||||
public function GetImportPaths(): array
|
||||
{
|
||||
return $this->aStylesheetImportPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array : main stylesheets URIs
|
||||
*/
|
||||
public function GetStylesheetFileURIs(): array
|
||||
{
|
||||
return $this->aStylesheetFileURIs;
|
||||
}
|
||||
|
||||
public function GetLastModified() : int
|
||||
{
|
||||
return $this->iLastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array : main stylesheets paths + included files paths
|
||||
*/
|
||||
public function GetAllStylesheetPaths(): array
|
||||
{
|
||||
return $this->aAllStylesheetFilePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string : last found stylesheet URI
|
||||
*/
|
||||
public function GetLastStyleSheetPath(): string
|
||||
{
|
||||
return $this->sLastStyleSheetPath;
|
||||
}
|
||||
|
||||
public function AddStylesheet(string $sStylesheetFileURI, string $sStylesheetFilePath): void
|
||||
{
|
||||
$this->aStylesheetFileURIs[] = $sStylesheetFileURI;
|
||||
$this->aAllStylesheetFilePaths[] = $sStylesheetFilePath;
|
||||
$this->sLastStyleSheetPath = $sStylesheetFilePath;
|
||||
}
|
||||
|
||||
public function AlreadyFetched(string $sStylesheetFilePath) : bool {
|
||||
return in_array($sStylesheetFilePath, $this->aAllStylesheetFilePaths);
|
||||
}
|
||||
|
||||
public function AddImport(string $sStylesheetFileURI, string $sStylesheetFilePath): void
|
||||
{
|
||||
$this->aStylesheetImportPaths[$sStylesheetFileURI] = $sStylesheetFilePath;
|
||||
$this->aAllStylesheetFilePaths[] = $sStylesheetFilePath;
|
||||
}
|
||||
|
||||
public function UpdateLastModified(string $sStylesheetFile): void
|
||||
{
|
||||
$this->iLastModified = max($this->iLastModified, @filemtime($sStylesheetFile));
|
||||
}
|
||||
|
||||
public function ResetLastStyleSheet(): void
|
||||
{
|
||||
$this->sLastStyleSheetPath = "";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,7 +20,7 @@
|
||||
* Helper class to build interactive forms to be used either in stand-alone
|
||||
* modal dialog or in "property-sheet" panes.
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
class DesignerForm
|
||||
@@ -102,27 +102,23 @@ class DesignerForm
|
||||
$sReturn .= '<fieldset>';
|
||||
$sReturn .= '<legend>'.$sLabel.'</legend>';
|
||||
}
|
||||
/** @var \DesignerFormField $oField */
|
||||
foreach($aFields as $oField) {
|
||||
foreach($aFields as $oField)
|
||||
{
|
||||
$aRow = $oField->Render($oP, $sFormId);
|
||||
if ($oField->IsVisible()) {
|
||||
$sValidation = '<span class="prop_apply ibo-prop--apply ibo-button ibo-is-alternative">'.$this->GetValidationArea($oField->GetFieldId()).'</span>';
|
||||
if ($oField->IsVisible())
|
||||
{
|
||||
$sValidation = ' <span class="prop_apply">'.$this->GetValidationArea($oField->GetFieldId()).'</span>';
|
||||
$sField = $aRow['value'].$sValidation;
|
||||
$aDetails[] = array(
|
||||
'label' => $aRow['label'],
|
||||
'value' => $sField,
|
||||
'attcode' => $oField->GetCode(),
|
||||
'attlabel' => $aRow['label'],
|
||||
'inputid' => $this->GetFieldId($oField->GetCode()),
|
||||
'inputtype' => $oField->GetInputType(),
|
||||
);
|
||||
} else {
|
||||
$aDetails[] = array('label' => $aRow['label'], 'value' => $sField);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHiddenFields .= $aRow['value'];
|
||||
}
|
||||
}
|
||||
$sReturn .= $oP->GetDetails($aDetails);
|
||||
|
||||
if ($sLabel != '') {
|
||||
if ($sLabel != '')
|
||||
{
|
||||
$sReturn .= '</fieldset>';
|
||||
}
|
||||
}
|
||||
@@ -211,41 +207,51 @@ class DesignerForm
|
||||
$sActionUrl = addslashes($this->sSubmitTo);
|
||||
$sJSSubmitParams = json_encode($this->aSubmitParams);
|
||||
$sFormId = $this->GetFormId();
|
||||
if ($this->oParentForm == null) {
|
||||
if ($this->oParentForm == null)
|
||||
{
|
||||
$sReturn = '<form id="'.$sFormId.'" onsubmit="return false;">';
|
||||
$sReturn .= '<table class="prop_table">';
|
||||
$sReturn .= '<thead><tr><th class="ibo-prop-header">'.Dict::S('UI:Form:Property').'</th><th class="ibo-prop-header">'.Dict::S('UI:Form:Value').'</th><th colspan="2" class="ibo-prop-header"> </th></tr></thead><tbody>';
|
||||
$sReturn .= '<thead><tr><th class="prop_header">'.Dict::S('UI:Form:Property').'</th><th class="prop_header">'.Dict::S('UI:Form:Value').'</th><th colspan="2" class="prop_header"> </th></tr></thead><tbody>';
|
||||
}
|
||||
|
||||
$sHiddenFields = '';
|
||||
foreach ($this->aFieldSets as $sLabel => $aFields) {
|
||||
foreach($this->aFieldSets as $sLabel => $aFields)
|
||||
{
|
||||
$aDetails = array();
|
||||
if ($sLabel != '') {
|
||||
if ($sLabel != '')
|
||||
{
|
||||
$sReturn .= $this->StartRow().'<th colspan="4">'.$sLabel.'</th>'.$this->EndRow();
|
||||
}
|
||||
|
||||
|
||||
foreach ($aFields as $oField) {
|
||||
foreach($aFields as $oField)
|
||||
{
|
||||
$aRow = $oField->Render($oP, $sFormId, 'property');
|
||||
if ($oField->IsVisible()) {
|
||||
if ($oField->IsVisible())
|
||||
{
|
||||
$sFieldId = $this->GetFieldId($oField->GetCode());
|
||||
$sValidation = $this->GetValidationArea($sFieldId, '<div class="ibo-button ibo-is-alternative ibo-is-success" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></div>');
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply ibo-prop--apply" >'.$sValidation.'</td><td class="prop_icon prop_cancel ibo-prop--cancel"><span><div class="ibo-button ibo-is-alternative ibo-is-neutral" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-undo"></i></div></span></td>'
|
||||
.$this->EndRow();
|
||||
|
||||
if (is_null($aRow['label'])) {
|
||||
$sValidation = $this->GetValidationArea($sFieldId, '<span title="Apply" class="ui-icon ui-icon-circle-check"/>');
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply">'.$sValidation.'</td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td>'.$this->EndRow();
|
||||
|
||||
$sPath = $this->GetHierarchyPath().'/'.$oField->GetCode();
|
||||
|
||||
if (is_null($aRow['label']))
|
||||
{
|
||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_value" colspan="2">'.$aRow['value'];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_label">'.$aRow['label'].'</td><td class="prop_value">'.$aRow['value'];
|
||||
}
|
||||
if (!($oField instanceof DesignerFormSelectorField) && !($oField instanceof DesignerMultipleSubFormField)) {
|
||||
if (!($oField instanceof DesignerFormSelectorField) && !($oField instanceof DesignerMultipleSubFormField))
|
||||
{
|
||||
$sReturn .= $sValidationFields;
|
||||
}
|
||||
$sNotifyParentSelectorJS = is_null($sNotifyParentSelector) ? 'null' : "'".addslashes($sNotifyParentSelector)."'";
|
||||
$sAutoApply = $oField->IsAutoApply() ? 'true' : 'false';
|
||||
$sHandlerEquals = $oField->GetHandlerEquals();
|
||||
$sHandlerGetValue = $oField->GetHandlerGetValue();
|
||||
|
||||
|
||||
$sWidgetClass = $oField->GetWidgetClass();
|
||||
$sJSExtraParams = '';
|
||||
if (count($oField->GetWidgetExtraParams()) > 0)
|
||||
@@ -260,7 +266,6 @@ class DesignerForm
|
||||
$this->AddReadyScript(
|
||||
<<<EOF
|
||||
$('#row_$sFieldId').$sWidgetClass({parent_selector: $sNotifyParentSelectorJS, field_id: '$sFieldId', equals: $sHandlerEquals, get_field_value: $sHandlerGetValue, auto_apply: $sAutoApply, value: '', submit_to: '$sActionUrl', submit_parameters: $sJSSubmitParams $sJSExtraParams });
|
||||
CombodoTooltip.InitTooltipFromMarkup($('#$sFormId [data-tooltip-content]'));
|
||||
EOF
|
||||
);
|
||||
}
|
||||
@@ -286,6 +291,7 @@ EOF
|
||||
}
|
||||
$this->AddReadyScript(
|
||||
<<<EOF
|
||||
$('.prop_table').tableHover();
|
||||
var idx = 0;
|
||||
$('.prop_table tbody tr').each(function() {
|
||||
if ((idx % 2) == 0)
|
||||
@@ -354,7 +360,7 @@ EOF
|
||||
<<<EOF
|
||||
$('#$sDialogId').dialog({
|
||||
height: 'auto',
|
||||
maxHeight: $(window).height() * 0.9,
|
||||
maxHeight: $(window).height() - 8,
|
||||
width: $iDialogWidth,
|
||||
modal: true,
|
||||
autoOpen: $sAutoOpen,
|
||||
@@ -542,7 +548,7 @@ EOF
|
||||
|
||||
public function GetValidationArea($sId, $sContent = '')
|
||||
{
|
||||
return "<span id=\"v_{$sId}\">$sContent</span>";
|
||||
return "<span style=\"display:inline-block;width:20px;\" id=\"v_{$sId}\"><span class=\"ui-icon ui-icon-alert\"></span>$sContent</span>";
|
||||
}
|
||||
public function GetAsyncActionClass()
|
||||
{
|
||||
@@ -710,27 +716,11 @@ class DesignerFormField
|
||||
$this->bMandatory = false;
|
||||
$this->bReadOnly = false;
|
||||
$this->bAutoApply = false;
|
||||
$this->aCSSClasses = [];
|
||||
if (ContextTag::Check(ContextTag::TAG_CONSOLE)) {
|
||||
$this->aCSSClasses[] = 'ibo-input';
|
||||
}
|
||||
$this->aCSSClasses = array();
|
||||
$this->bDisplayed = true;
|
||||
$this->aWidgetExtraParams = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Important, for now we use constants from the \cmdbAbstractObject class, introducing a coupling that should not exist.
|
||||
* This has been traced under N°4241 and will be discussed during the next modernization batch.
|
||||
*
|
||||
* @return string|null Return the input type of the field
|
||||
* @see \cmdbAbstractObject::ENUM_INPUT_TYPE_XXX
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_SINGLE_INPUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -1030,10 +1020,10 @@ class DesignerTextField extends DesignerFormField
|
||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||
{
|
||||
var myTimer = null;
|
||||
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
}
|
||||
EOF
|
||||
);
|
||||
@@ -1065,23 +1055,6 @@ EOF
|
||||
|
||||
class DesignerLongTextField extends DesignerTextField
|
||||
{
|
||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||
{
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
|
||||
if (ContextTag::Check(ContextTag::TAG_CONSOLE)) {
|
||||
$this->aCSSClasses[] = 'ibo-input-text';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): string
|
||||
{
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_TEXTAREA;
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
@@ -1105,10 +1078,10 @@ class DesignerLongTextField extends DesignerTextField
|
||||
{
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||
{
|
||||
var myTimer = null;
|
||||
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
}
|
||||
EOF
|
||||
);
|
||||
@@ -1156,10 +1129,10 @@ class DesignerIntegerField extends DesignerFormField
|
||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').on('change keyup validate', function() { ValidateInteger('$sId', $sMandatory, $(this).closest('form').attr('id'), $sMin, $sMax); } );
|
||||
$('#$sId').bind('change keyup validate', function() { ValidateInteger('$sId', $sMandatory, $(this).closest('form').attr('id'), $sMin, $sMax); } );
|
||||
{
|
||||
var myTimer = null;
|
||||
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
}
|
||||
EOF
|
||||
);
|
||||
@@ -1206,34 +1179,12 @@ class DesignerComboField extends DesignerFormField
|
||||
$this->bOtherChoices = false;
|
||||
$this->sNullLabel = Dict::S('UI:SelectOne');
|
||||
|
||||
if (ContextTag::Check(ContextTag::TAG_CONSOLE)) {
|
||||
$this->aCSSClasses[] = 'ibo-input-select';
|
||||
}
|
||||
|
||||
$this->bAutoApply = true;
|
||||
$this->bSorted = true; // Sorted by default
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
|
||||
public function SetAllowedValues($aAllowedValues)
|
||||
{
|
||||
if ($this->bMultipleSelection) {
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_MULTIPLE_CHOICES;
|
||||
}
|
||||
else {
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetAllowedValues(?array $aAllowedValues)
|
||||
{
|
||||
// Make sure to have an actual array for values
|
||||
if (is_null($aAllowedValues)) {
|
||||
$aAllowedValues = [];
|
||||
}
|
||||
|
||||
$this->aAllowedValues = $aAllowedValues;
|
||||
}
|
||||
|
||||
@@ -1272,7 +1223,7 @@ class DesignerComboField extends DesignerFormField
|
||||
$sChecked = $this->defaultValue ? 'checked' : '';
|
||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||
if ($this->IsSorted())
|
||||
if ($this->IsSorted() )
|
||||
{
|
||||
asort($this->aAllowedValues);
|
||||
}
|
||||
@@ -1310,43 +1261,38 @@ class DesignerComboField extends DesignerFormField
|
||||
{
|
||||
if ($this->bMultipleSelection)
|
||||
{
|
||||
$sHtml = "<span><select $sCSSClasses multiple size=\"8\"id=\"$sId\" name=\"$sName\">";
|
||||
$sHtml = "<select $sCSSClasses multiple size=\"8\"id=\"$sId\" name=\"$sName\">";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml = "<span class=\"ibo-input-select-wrapper\"><select $sCSSClasses id=\"$sId\" name=\"$sName\">";
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\">";
|
||||
if ($this->sNullLabel != '')
|
||||
{
|
||||
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
|
||||
}
|
||||
}
|
||||
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
|
||||
{
|
||||
if ($this->bMultipleSelection)
|
||||
{
|
||||
foreach ($this->aAllowedValues as $sKey => $sDisplayValue) {
|
||||
if ($this->bMultipleSelection) {
|
||||
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
|
||||
}
|
||||
// Quick and dirty: display the menu parents as a tree
|
||||
$sHtmlValue = str_replace(' ', ' ', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
|
||||
$sHtmlValue = str_replace(' ', ' ', $sDisplayValue);
|
||||
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
|
||||
}
|
||||
$sHtml .= "</select></span>";
|
||||
$sHtml .= "</select>";
|
||||
if ($this->bOtherChoices)
|
||||
{
|
||||
$sHtml .= '<br/><input type="checkbox" id="other_chk_'.$sId.'"><label for="other_chk_'.$sId.'"> Other:</label> <input type="text" id="other_'.$sId.'" name="other_'.$sName.'" size="30"/>';
|
||||
}
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').on('change validate', function() { ValidateWithPattern('$sId', $sMandatory, '', $(this).closest('form').attr('id'), null, null); } );
|
||||
$('#$sId').bind('change validate', function() { ValidateWithPattern('$sId', $sMandatory, '', $(this).closest('form').attr('id'), null, null); } );
|
||||
EOF
|
||||
);
|
||||
}
|
||||
return array('label' => $this->sLabel, 'value' => $sHtml);
|
||||
|
||||
}
|
||||
|
||||
public function ReadParam(&$aValues)
|
||||
@@ -1365,17 +1311,6 @@ class DesignerBooleanField extends DesignerFormField
|
||||
{
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
$this->bAutoApply = true;
|
||||
if (ContextTag::Check(ContextTag::TAG_CONSOLE)) {
|
||||
$this->aCSSClasses[] = 'ibo-input-checkbox';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_CHECKBOX;
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
@@ -1436,14 +1371,6 @@ class DesignerHiddenField extends DesignerFormField
|
||||
{
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function IsVisible()
|
||||
{
|
||||
@@ -1471,14 +1398,6 @@ class DesignerIconSelectionField extends DesignerFormField
|
||||
$this->bAutoApply = true;
|
||||
$this->sUploadUrl = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return cmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_DECORATED;
|
||||
}
|
||||
|
||||
public function SetAllowedValues($aAllowedValues)
|
||||
{
|
||||
@@ -1495,33 +1414,28 @@ class DesignerIconSelectionField extends DesignerFormField
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
$idx = 0;
|
||||
$idxFallback = 0;
|
||||
foreach ($this->aAllowedValues as $index => $aValue) {
|
||||
if ($aValue['value'] == $this->defaultValue) {
|
||||
foreach($this->aAllowedValues as $index => $aValue)
|
||||
{
|
||||
if ($aValue['value'] == $this->defaultValue)
|
||||
{
|
||||
$idx = $index;
|
||||
break;
|
||||
}
|
||||
//fallback if url of default value contains ../
|
||||
//for contact, icon is http://localhost/env-production/itop-structure/../../images/icons/icons8-customer.svg => not found http://localhost/images/icons/icons8-customer.svg
|
||||
if (basename($aValue['value']) == basename($this->defaultValue)) {
|
||||
$idxFallback = $index;
|
||||
}
|
||||
}
|
||||
if ($idx == 0) {
|
||||
$idx = $idxFallback;
|
||||
}
|
||||
$sJSItems = json_encode($this->aAllowedValues);
|
||||
$sPostUploadTo = ($this->sUploadUrl == null) ? 'null' : "'{$this->sUploadUrl}'";
|
||||
if (!$this->IsReadOnly()) {
|
||||
if (!$this->IsReadOnly())
|
||||
{
|
||||
$sDefaultValue = ($this->defaultValue !== '') ? $this->defaultValue : $this->aAllowedValues[$idx]['value'];
|
||||
$sCSSClasses = ContextTag::Check(ContextTag::TAG_CONSOLE) ? 'class="ibo-input-select-wrapper"' : '';
|
||||
$sValue = "<span $sCSSClasses><input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/></span>";
|
||||
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/>";
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
$('#$sId').icon_select({current_idx: $idx, items: $sJSItems, post_upload_to: $sPostUploadTo});
|
||||
EOF
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sValue = '<span style="display:inline-block;line-height:48px;height:48px;"><span><img style="vertical-align:middle" src="'.$this->aAllowedValues[$idx]['icon'].'" /> '.htmlentities($this->aAllowedValues[$idx]['label'], ENT_QUOTES, 'UTF-8').'</span></span>';
|
||||
}
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled' : '';
|
||||
@@ -1536,21 +1450,18 @@ class RunTimeIconSelectionField extends DesignerIconSelectionField
|
||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||
{
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
$aFolderList = [
|
||||
APPROOT.'env-'.utils::GetCurrentEnvironment() => utils::GetAbsoluteUrlModulesRoot(),
|
||||
APPROOT.'images/icons' => utils::GetAbsoluteUrlAppRoot().'images/icons',
|
||||
];
|
||||
if (count(self::$aAllIcons) == 0) {
|
||||
foreach ($aFolderList as $sFolderPath => $sUrlPrefix) {
|
||||
$aIcons = self::FindIconsOnDisk($sFolderPath);
|
||||
ksort($aIcons);
|
||||
|
||||
foreach ($aIcons as $sFilePath) {
|
||||
self::$aAllIcons[] = array('value' => $sFilePath, 'label' => basename($sFilePath), 'icon' => $sUrlPrefix.$sFilePath);
|
||||
}
|
||||
}
|
||||
if (count(self::$aAllIcons) == 0)
|
||||
{
|
||||
self::$aAllIcons = self::FindIconsOnDisk(APPROOT.'env-'.utils::GetCurrentEnvironment());
|
||||
ksort(self::$aAllIcons);
|
||||
}
|
||||
$this->SetAllowedValues(self::$aAllIcons);
|
||||
$aValues = array();
|
||||
foreach(self::$aAllIcons as $sFilePath)
|
||||
{
|
||||
$aValues[] = array('value' => $sFilePath, 'label' => basename($sFilePath), 'icon' => utils::GetAbsoluteUrlModulesRoot().$sFilePath);
|
||||
}
|
||||
$this->SetAllowedValues($aValues);
|
||||
}
|
||||
|
||||
static protected function FindIconsOnDisk($sBaseDir, $sDir = '')
|
||||
@@ -1581,29 +1492,26 @@ class RunTimeIconSelectionField extends DesignerIconSelectionField
|
||||
SetupUtils::builddir(dirname($sCacheFile));
|
||||
file_put_contents($sCacheFile, $sAvailableIcons, LOCK_EX);
|
||||
}
|
||||
|
||||
return $aFiles;
|
||||
}
|
||||
|
||||
static protected function _FindIconsOnDisk($sBaseDir, $sDir = '', &$aFilesSpecs = [])
|
||||
static protected function _FindIconsOnDisk($sBaseDir, $sDir = '')
|
||||
{
|
||||
$aResult = [];
|
||||
$aResult = array();
|
||||
// Populate automatically the list of icon files
|
||||
if ($hDir = @opendir($sBaseDir.'/'.$sDir)) {
|
||||
while (($sFile = readdir($hDir)) !== false) {
|
||||
if ($hDir = @opendir($sBaseDir.'/'.$sDir))
|
||||
{
|
||||
while (($sFile = readdir($hDir)) !== false)
|
||||
{
|
||||
$aMatches = array();
|
||||
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile)) {
|
||||
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile))
|
||||
{
|
||||
$sDirSubPath = ($sDir == '') ? $sFile : $sDir.'/'.$sFile;
|
||||
$aResult = array_merge($aResult, self::_FindIconsOnDisk($sBaseDir, $sDirSubPath, $aFilesSpecs));
|
||||
$aResult = array_merge($aResult, self::_FindIconsOnDisk($sBaseDir, $sDirSubPath));
|
||||
}
|
||||
$sSize = filesize($sBaseDir.'/'.$sDir.'/'.$sFile);
|
||||
if (isset($aFilesSpecs[$sFile]) && $aFilesSpecs[$sFile] == $sSize) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match("/\.(png|jpg|jpeg|gif|svg)$/i", $sFile, $aMatches)) // png, jp(e)g, gif and svg are considered valid
|
||||
if (preg_match("/\.(png|jpg|jpeg|gif)$/i", $sFile, $aMatches)) // png, jp(e)g and gif are considered valid
|
||||
{
|
||||
$aResult[$sFile.'_'.$sDir] = $sDir.'/'.$sFile;
|
||||
$aFilesSpecs[$sFile] = $sSize;
|
||||
}
|
||||
}
|
||||
closedir($hDir);
|
||||
@@ -1649,14 +1557,6 @@ class DesignerSortableField extends DesignerFormField
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
$this->aAllowedValues = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function SetAllowedValues($aAllowedValues)
|
||||
{
|
||||
@@ -1693,17 +1593,6 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
$this->defaultRealValue = $defaultValue;
|
||||
$this->aSubForms = array();
|
||||
$this->bSorted = true;
|
||||
if (ContextTag::Check(ContextTag::TAG_CONSOLE)) {
|
||||
$this->aCSSClasses[] = 'ibo-input-select';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function IsSorted()
|
||||
@@ -1746,23 +1635,27 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||
|
||||
$this->aCSSClasses[] = 'formSelector';
|
||||
|
||||
|
||||
$sCSSClasses = '';
|
||||
if (count($this->aCSSClasses) > 0) {
|
||||
if (count($this->aCSSClasses) > 0)
|
||||
{
|
||||
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
||||
}
|
||||
|
||||
if ($this->IsSorted()) {
|
||||
if ($this->IsSorted())
|
||||
{
|
||||
uasort($this->aSubForms, array(get_class($this), 'SortOnFormLabel'));
|
||||
}
|
||||
|
||||
if ($this->IsReadOnly()) {
|
||||
|
||||
if ($this->IsReadOnly())
|
||||
{
|
||||
$sDisplayValue = '';
|
||||
$sHiddenValue = '';
|
||||
foreach ($this->aSubForms as $iKey => $aFormData) {
|
||||
foreach($this->aSubForms as $iKey => $aFormData)
|
||||
{
|
||||
if ($iKey == $this->defaultValue) // Default value is actually the index
|
||||
{
|
||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');
|
||||
@@ -1771,29 +1664,35 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
}
|
||||
}
|
||||
$sHtml = "<span $sCSSClasses>".$sDisplayValue.$sHiddenValue."</span>";
|
||||
} else {
|
||||
$sHtml = "<span class=\"ibo-input-select-wrapper\"><select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||
foreach ($this->aSubForms as $iKey => $aFormData) {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||
foreach($this->aSubForms as $iKey => $aFormData)
|
||||
{
|
||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');
|
||||
$sValue = htmlentities($aFormData['value'], ENT_QUOTES, 'UTF-8');
|
||||
$sSelected = ($iKey == $this->defaultValue) ? 'selected' : '';
|
||||
$sHtml .= "<option data-value=\"$sValue\" value=\"$iKey\" $sSelected>".$sDisplayValue."</option>";
|
||||
}
|
||||
$sHtml .= "</select></span>";
|
||||
$sHtml .= "</select>";
|
||||
}
|
||||
|
||||
if ($sRenderMode == 'property') {
|
||||
$sHtml .= '</td><td class="prop_icon prop_apply ibo-prop--apply"><span><button class="ibo-button ibo-is-alternative ibo-is-success" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Apply').'"><i class="fas fa-check"></i></button></span></td><td class="prop_icon prop_cancel ibo-prop--cancel"><span><button class="ibo-button ibo-is-alternative ibo-is-neutral" data-tooltip-content="'.Dict::Format('UI:DashboardEdit:Revert').'"><i class="fas fa-times"></i></button></span></td></tr>';
|
||||
|
||||
if ($sRenderMode == 'property')
|
||||
{
|
||||
$sHtml .= '</td><td class="prop_icon prop_apply"><span title="Apply" class="ui-icon ui-icon-circle-check"/></td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td></tr>';
|
||||
}
|
||||
foreach ($this->aSubForms as $sKey => $aFormData) {
|
||||
foreach($this->aSubForms as $sKey => $aFormData)
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sStyle = (($sKey == $this->defaultValue) && $this->oForm->IsDisplayed()) ? '' : 'style="display:none"';
|
||||
$oSubForm = $aFormData['form'];
|
||||
$oSubForm->SetParentForm($this->oForm);
|
||||
$oSubForm->CopySubmitParams($this->oForm);
|
||||
$oSubForm->SetPrefix($this->oForm->GetPrefix().$sKey.'_');
|
||||
|
||||
if ($sRenderMode == 'property') {
|
||||
|
||||
if ($sRenderMode == 'property')
|
||||
{
|
||||
// Note: Managing the visibility of nested subforms had several implications
|
||||
// 1) Attributes are displayed in a table and we have to group them in as many tbodys as necessary to hide/show the various options depending on the current selection
|
||||
// 2) It is not possible to nest tbody tags. Therefore, it is not possible to manage the visibility the same way as it is done for the dialog mode (using nested divs).
|
||||
@@ -1827,7 +1726,7 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
{
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').on('change reverted', function() { $('.subform_{$sId}').hide(); $('.{$sId}_'+this.value).show(); } );
|
||||
$('#$sId').bind('change reverted', function() { $('.subform_{$sId}').hide(); $('.{$sId}_'+this.value).show(); } );
|
||||
EOF
|
||||
);
|
||||
}
|
||||
@@ -1891,14 +1790,6 @@ class DesignerSubFormField extends DesignerFormField
|
||||
parent::__construct('', $sLabel, '');
|
||||
$this->oSubForm = $oSubForm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
@@ -1943,14 +1834,6 @@ class DesignerStaticTextField extends DesignerFormField
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetInputType(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
return array('label' => $this->sLabel, 'value' => $this->defaultValue);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Persistent class InputOutputTask
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -44,6 +44,7 @@ class InputOutputTask extends cmdbAbstractObject
|
||||
"db_table" => "priv_iotask",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,57 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
|
||||
* Class iTopWizardWebPage
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');
|
||||
require_once('itopwebpage.class.inc.php');
|
||||
/**
|
||||
* Web page to display a wizard in the iTop framework
|
||||
*/
|
||||
class iTopWizardWebPage extends iTopWebPage
|
||||
{
|
||||
var $m_iCurrentStep;
|
||||
var $m_aSteps;
|
||||
public function __construct($sTitle, $currentOrganization, $iCurrentStep, $aSteps)
|
||||
{
|
||||
parent::__construct($sTitle." - step $iCurrentStep of ".count($aSteps)." - ".$aSteps[$iCurrentStep - 1], $currentOrganization);
|
||||
$this->m_iCurrentStep = $iCurrentStep;
|
||||
$this->m_aSteps = $aSteps;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$aSteps = array();
|
||||
$iIndex = 0;
|
||||
foreach($this->m_aSteps as $sStepTitle)
|
||||
{
|
||||
$iIndex++;
|
||||
$sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep';
|
||||
$aSteps[] = "<div class=\"$sStyle\"><span>$sStepTitle</span></div>";
|
||||
}
|
||||
$sWizardHeader = "<div class=\"wizHeader\"><h1>".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</h1>\n".implode("<div class=\"wizSeparator\"><img align=\"bottom\" src=\"../images/wizArrow.gif\"></div>", $aSteps)."<br style=\"clear:both;\"/></div>\n";
|
||||
$this->s_content = "$sWizardHeader<div class=\"wizContainer\">".$this->s_content."</div>";
|
||||
parent::output();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginBasic
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -23,19 +20,19 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode'))
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
|
||||
{
|
||||
Session::Set('login_mode', 'basic');
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
}
|
||||
elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
|
||||
{
|
||||
Session::Set('login_mode', 'basic');
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
}
|
||||
elseif (isset($_SERVER['PHP_AUTH_USER']))
|
||||
{
|
||||
Session::Set('login_mode', 'basic');
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -43,10 +40,10 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'basic')
|
||||
if (!isset($_SESSION['login_mode']) || $_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser) = $this->GetAuthUserAndPassword();
|
||||
Session::Set('login_temp_auth_user', $sAuthUser);
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -54,32 +51,39 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
// Save the checked user
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser) = $this->GetAuthUserAndPassword();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
$iOnExit = LoginWebPage::getIOnExit();
|
||||
if ($iOnExit === LoginWebPage::EXIT_RETURN)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
|
||||
}
|
||||
LoginWebPage::HTTP401Error();
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -87,9 +91,9 @@ class LoginBasic extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'basic')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
Session::Set('can_logoff', true);
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginDefaultBefore
|
||||
*/
|
||||
@@ -25,7 +23,7 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_OK;
|
||||
|
||||
Session::Unset('login_temp_auth_user');
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
|
||||
// Check if proposed login mode is present and allowed
|
||||
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
|
||||
@@ -34,11 +32,11 @@ class LoginDefaultBefore extends AbstractLoginFSMExtension
|
||||
if ($index !== false)
|
||||
{
|
||||
// Force login mode
|
||||
Session::Set('login_mode', $sProposedLoginMode);
|
||||
$_SESSION['login_mode'] = $sProposedLoginMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Session::Unset('login_mode');
|
||||
unset($_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -79,7 +77,7 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
{
|
||||
self::ResetLoginSession();
|
||||
$iOnExit = LoginWebPage::getIOnExit();
|
||||
if ($iOnExit == LoginWebPage::EXIT_RETURN)
|
||||
if ($iOnExit === LoginWebPage::EXIT_RETURN)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
|
||||
}
|
||||
@@ -93,8 +91,14 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
|
||||
protected function OnCredentialsOk(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode'))
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
// N°6358 - if EXIT_RETURN was asked, send an error
|
||||
if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) {
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
|
||||
// If no plugin validated the user, exit
|
||||
self::ResetLoginSession();
|
||||
exit();
|
||||
@@ -112,7 +116,7 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
Session::Unset('login_temp_auth_user');
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -120,11 +124,11 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
private static function ResetLoginSession()
|
||||
{
|
||||
LoginWebPage::ResetSession();
|
||||
foreach (Session::ListVariables() as $sKey)
|
||||
foreach (array_keys($_SESSION) as $sKey)
|
||||
{
|
||||
if (utils::StartsWith($sKey, 'login_'))
|
||||
{
|
||||
Session::Unset($sKey);
|
||||
unset($_SESSION[$sKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginExternal
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -24,12 +22,12 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode'))
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if ($sAuthUser && (strlen($sAuthUser) > 0))
|
||||
{
|
||||
Session::Set('login_mode', 'external');
|
||||
$_SESSION['login_mode'] = 'external';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -37,33 +35,35 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, '', Session::Get('login_mode'), 'external'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
// Save the checked user
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', Session::Get('login_mode'));
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
Session::Set('can_logoff', false);
|
||||
$_SESSION['can_logoff'] = false;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -71,8 +71,13 @@ class LoginExternal extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'external')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$iOnExit = LoginWebPage::getIOnExit();
|
||||
if ($iOnExit === LoginWebPage::EXIT_RETURN)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
|
||||
}
|
||||
LoginWebPage::HTTP401Error();
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginForm
|
||||
*
|
||||
@@ -31,7 +29,8 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode') || Session::Get('login_mode') == 'form') {
|
||||
if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form'))
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
|
||||
@@ -44,6 +43,10 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
exit;
|
||||
}
|
||||
|
||||
if (LoginWebPage::getIOnExit() === LoginWebPage::EXIT_RETURN) {
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
// No credentials yet, display the form
|
||||
$oPage = LoginWebPage::NewLoginWebPage();
|
||||
$oPage->DisplayLoginForm($this->bForceFormOnError);
|
||||
@@ -51,8 +54,9 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
$this->bForceFormOnError = false;
|
||||
exit;
|
||||
}
|
||||
Session::Set('login_temp_auth_user', $sAuthUser);
|
||||
Session::Set('login_mode', 'form');
|
||||
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
$_SESSION['login_mode'] = 'form';
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -62,15 +66,17 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
// Save the checked user
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -80,19 +86,11 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
if (Session::IsSet('auth_user'))
|
||||
{
|
||||
// If FSM reenter this state (example 2FA) then the auth_user is not resubmitted
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
}
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
// Store 'auth_user' in session for further use
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
@@ -102,7 +100,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
$this->bForceFormOnError = true;
|
||||
}
|
||||
@@ -114,9 +112,9 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
*/
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'form')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
Session::Set('can_logoff', true);
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\TwigExtension;
|
||||
|
||||
/**
|
||||
@@ -225,7 +224,7 @@ class LoginTwigRenderer
|
||||
}
|
||||
|
||||
$oCoreLoader = new Twig_Loader_Filesystem(array(), APPROOT.'templates');
|
||||
$aCoreTemplatesPaths = array('pages/login', 'pages/login/password');
|
||||
$aCoreTemplatesPaths = array('login', 'login/password');
|
||||
// Having this path declared after the plugins let the plugins replace the core templates
|
||||
$oCoreLoader->setPaths($aCoreTemplatesPaths);
|
||||
// Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them
|
||||
@@ -239,9 +238,16 @@ class LoginTwigRenderer
|
||||
|
||||
public function GetDefaultVars()
|
||||
{
|
||||
$sLogo = 'itop-logo-external.png';
|
||||
$sBrandingLogo = 'login-logo.png';
|
||||
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo))
|
||||
{
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
|
||||
$aVars = array(
|
||||
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Class LoginURL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -28,13 +26,13 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!Session::IsSet('login_mode') && !$this->bErrorOccurred)
|
||||
if (!isset($_SESSION['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))
|
||||
{
|
||||
Session::Set('login_mode', 'url');
|
||||
$_SESSION['login_mode'] = 'url';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
@@ -42,41 +40,43 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
Session::Set('login_temp_auth_user', utils::ReadParam('auth_user', '', false, 'raw_data'));
|
||||
$_SESSION['login_temp_auth_user'] = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, Session::Get('login_mode'), 'internal'))
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
// Save the checked user
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', Session::Get('login_mode'));
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
if (isset($_SESSION['login_mode']) && $_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$this->bErrorOccurred = true;
|
||||
}
|
||||
@@ -85,9 +85,9 @@ class LoginURL extends AbstractLoginFSMExtension
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if (Session::Get('login_mode') == 'url')
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
Session::Set('can_logoff', true);
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2017 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,13 +20,10 @@
|
||||
/**
|
||||
* Class LoginWebPage
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* Web page used for displaying the login form
|
||||
*/
|
||||
@@ -35,7 +32,7 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
const EXIT_PROMPT = 0;
|
||||
const EXIT_HTTP_401 = 1;
|
||||
const EXIT_RETURN = 2;
|
||||
const EXIT_RETURN = 2; // Non interactive mode (ajax, rest, ...)
|
||||
|
||||
const EXIT_CODE_OK = 0;
|
||||
const EXIT_CODE_MISSINGLOGIN = 1;
|
||||
@@ -88,13 +85,14 @@ class LoginWebPage extends NiceWebPage
|
||||
parent::__construct($sTitle);
|
||||
$this->SetStyleSheet();
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->add_http_headers();
|
||||
}
|
||||
|
||||
public function SetStyleSheet()
|
||||
{
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
|
||||
}
|
||||
|
||||
public static function SetLoginFailedMessage($sMessage)
|
||||
@@ -102,49 +100,18 @@ class LoginWebPage extends NiceWebPage
|
||||
self::$m_sLoginFailedMessage = $sMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oUser
|
||||
* @param array $aProfiles
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
public static function SynchronizeProfiles(&$oUser, array $aProfiles, $sOrigin)
|
||||
{
|
||||
$oProfilesSet = $oUser->Get(‘profile_list’);
|
||||
//delete old profiles
|
||||
$aExistingProfiles = [];
|
||||
while ($oProfile = $oProfilesSet->Fetch())
|
||||
{
|
||||
array_push($aExistingProfiles, $oProfile->Get('profileid'));
|
||||
$iArrayKey = array_search($oProfile->Get('profileid'), $aProfiles);
|
||||
if (!$iArrayKey)
|
||||
{
|
||||
$oProfilesSet->RemoveItem($oProfile->Get('profileid'));
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($aProfiles[$iArrayKey]);
|
||||
}
|
||||
}
|
||||
//add profiles not already linked with user
|
||||
foreach ($aProfiles as $iProfileId)
|
||||
{
|
||||
$oLink = new URP_UserProfile();
|
||||
$oLink->Set('profileid', $iProfileId);
|
||||
$oLink->Set('reason', $sOrigin);
|
||||
|
||||
$oProfilesSet->AddItem(MetaModel::NewObject('URP_UserProfile', array('profileid' => $iProfileId, 'reason' => $sOrigin)));
|
||||
}
|
||||
$oUser->Set('profile_list', $oProfilesSet);
|
||||
}
|
||||
|
||||
public function DisplayLoginHeader($bMainAppLogo = false)
|
||||
{
|
||||
$sLogo = 'itop-logo-external.png';
|
||||
$sBrandingLogo = 'login-logo.png';
|
||||
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = Branding::GetLoginLogoAbsoluteUrl();
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo))
|
||||
{
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
$this->add("<div id=\"login-logo\"><a href=\"".htmlentities($sIconUrl, ENT_QUOTES,
|
||||
self::PAGES_CHARSET)."\"><img title=\"$sVersionShort\" src=\"$sDisplayIcon\"></a></div>\n");
|
||||
}
|
||||
@@ -241,7 +208,7 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
|
||||
// This token allows the user to change the password without knowing the previous one
|
||||
$sToken = substr(md5(APPROOT.uniqid()), 0, 16);
|
||||
$sToken = bin2hex(random_bytes(32));
|
||||
$oUser->Set('reset_pwd_token', $sToken);
|
||||
CMDBObject::SetTrackInfo('Reset password');
|
||||
$oUser->AllowWrite(true);
|
||||
@@ -385,14 +352,20 @@ class LoginWebPage extends NiceWebPage
|
||||
$this->output();
|
||||
}
|
||||
|
||||
public static function ResetSession()
|
||||
public static function ResetSession($bFullCleanup = false)
|
||||
{
|
||||
// Unset all of the session variables.
|
||||
Session::Unset('auth_user');
|
||||
Session::Unset('login_state');
|
||||
Session::Unset('can_logoff');
|
||||
Session::Unset('archive_mode');
|
||||
Session::Unset('impersonate_user');
|
||||
if ($bFullCleanup) {
|
||||
// Unset all of the session variables.
|
||||
foreach (array_keys($_SESSION) as $sKey) {
|
||||
unset($_SESSION[$sKey]);
|
||||
}
|
||||
} else {
|
||||
unset($_SESSION['auth_user']);
|
||||
unset($_SESSION['login_state']);
|
||||
unset($_SESSION['can_logoff']);
|
||||
unset($_SESSION['archive_mode']);
|
||||
unset($_SESSION['impersonate_user']);
|
||||
}
|
||||
UserRights::_ResetSessionCache();
|
||||
// If it's desired to kill the session, also delete the session cookie.
|
||||
// Note: This will destroy the session, and not just the session data!
|
||||
@@ -438,11 +411,11 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
$bLoginDebug = MetaModel::GetConfig()->Get('login_debug');
|
||||
|
||||
if (Session::Get('login_state') == self::LOGIN_STATE_ERROR)
|
||||
if (!isset($_SESSION['login_state']) || ($_SESSION['login_state'] == self::LOGIN_STATE_ERROR))
|
||||
{
|
||||
Session::Set('login_state', self::LOGIN_STATE_START);
|
||||
$_SESSION['login_state'] = self::LOGIN_STATE_START;
|
||||
}
|
||||
$sLoginState = Session::Get('login_state');
|
||||
$sLoginState = $_SESSION['login_state'];
|
||||
|
||||
$sSessionLog = '';
|
||||
if ($bLoginDebug)
|
||||
@@ -483,7 +456,6 @@ class LoginWebPage extends NiceWebPage
|
||||
$iResponse = $oLoginFSMExtensionInstance->LoginAction($sLoginState, $iErrorCode);
|
||||
if ($iResponse == self::LOGIN_FSM_RETURN)
|
||||
{
|
||||
Session::WriteClose();
|
||||
return $iErrorCode; // Asked to exit FSM, generally login OK
|
||||
}
|
||||
if ($iResponse == self::LOGIN_FSM_ERROR)
|
||||
@@ -497,7 +469,7 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
// Every plugin has nothing else to do in this state, go forward
|
||||
$sLoginState = self::AdvanceLoginFSMState($sLoginState);
|
||||
Session::Set('login_state', $sLoginState);
|
||||
$_SESSION['login_state'] = $sLoginState;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
@@ -523,7 +495,7 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
if ($bFilterWithMode)
|
||||
{
|
||||
$sCurrentLoginMode = Session::Get('login_mode', '');
|
||||
$sCurrentLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : '';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -662,8 +634,8 @@ class LoginWebPage extends NiceWebPage
|
||||
$oLog->DBInsertNoReload();
|
||||
}
|
||||
|
||||
Session::Set('auth_user', $sAuthUser);
|
||||
Session::Set('login_mode', $sLoginMode);
|
||||
$_SESSION['auth_user'] = $sAuthUser;
|
||||
$_SESSION['login_mode'] = $sLoginMode;
|
||||
UserRights::_InitSessionCache();
|
||||
}
|
||||
|
||||
@@ -678,10 +650,10 @@ class LoginWebPage extends NiceWebPage
|
||||
*/
|
||||
public static function CheckLoggedUser(&$iErrorCode)
|
||||
{
|
||||
if (Session::IsSet('auth_user'))
|
||||
if (isset($_SESSION['auth_user']))
|
||||
{
|
||||
// Already authenticated
|
||||
$bRet = UserRights::Login(Session::Get('auth_user')); // Login & set the user's language
|
||||
$bRet = UserRights::Login($_SESSION['auth_user']); // Login & set the user's language
|
||||
if ($bRet)
|
||||
{
|
||||
$iErrorCode = self::EXIT_CODE_OK;
|
||||
@@ -709,11 +681,11 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
public static function SetLoginModeAndReload($sNewLoginMode)
|
||||
{
|
||||
if (Session::Get('login_mode') == $sNewLoginMode)
|
||||
if (isset($_SESSION['login_mode']) && ($_SESSION['login_mode'] == $sNewLoginMode))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Session::Set('login_mode', $sNewLoginMode);
|
||||
$_SESSION['login_mode'] = $sNewLoginMode;
|
||||
self::HTTPReload();
|
||||
}
|
||||
|
||||
@@ -826,9 +798,9 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
CMDBObject::SetTrackOrigin('custom-extension');
|
||||
$sInfo = 'External User provisioning';
|
||||
if (Session::IsSet('login_mode'))
|
||||
if (isset($_SESSION['login_mode']))
|
||||
{
|
||||
$sInfo .= " (".Session::Get('login_mode').")";
|
||||
$sInfo .= " ({$_SESSION['login_mode']})";
|
||||
}
|
||||
CMDBObject::SetTrackInfo($sInfo);
|
||||
|
||||
@@ -880,9 +852,9 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
CMDBObject::SetTrackOrigin('custom-extension');
|
||||
$sInfo = 'External User provisioning';
|
||||
if (Session::IsSet('login_mode'))
|
||||
if (isset($_SESSION['login_mode']))
|
||||
{
|
||||
$sInfo .= " (".Session::Get('login_mode').")";
|
||||
$sInfo .= " ({$_SESSION['login_mode']})";
|
||||
}
|
||||
CMDBObject::SetTrackInfo($sInfo);
|
||||
|
||||
@@ -920,12 +892,20 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
|
||||
// Now synchronize the profiles
|
||||
$oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
|
||||
$sOrigin = 'External User provisioning';
|
||||
if (Session::IsSet('login_mode'))
|
||||
if (isset($_SESSION['login_mode']))
|
||||
{
|
||||
$sOrigin .= " (".Session::Get('login_mode').")";
|
||||
$sOrigin .= " ({$_SESSION['login_mode']})";
|
||||
}
|
||||
$aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin);
|
||||
foreach ($aProfiles as $iProfileId)
|
||||
{
|
||||
$oLink = new URP_UserProfile();
|
||||
$oLink->Set('profileid', $iProfileId);
|
||||
$oLink->Set('reason', $sOrigin);
|
||||
$oProfilesSet->AddObject($oLink);
|
||||
}
|
||||
$oUser->Set('profile_list', $oProfilesSet);
|
||||
if ($oUser->IsModified())
|
||||
{
|
||||
$oUser->DBWrite();
|
||||
@@ -957,7 +937,7 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($iOnExit == self::EXIT_RETURN)
|
||||
if ($iOnExit === self::EXIT_RETURN)
|
||||
{
|
||||
return self::EXIT_CODE_PORTALUSERNOTAUTHORIZED;
|
||||
}
|
||||
@@ -1008,11 +988,12 @@ class LoginWebPage extends NiceWebPage
|
||||
$sMessage = self::HandleOperations($operation); // May exit directly
|
||||
|
||||
$iRet = self::Login($iOnExit);
|
||||
|
||||
if ($iRet == self::EXIT_CODE_OK)
|
||||
{
|
||||
if ($bMustBeAdmin && !UserRights::IsAdministrator())
|
||||
{
|
||||
if ($iOnExit == self::EXIT_RETURN)
|
||||
if ($iOnExit === self::EXIT_RETURN)
|
||||
{
|
||||
return self::EXIT_CODE_MUSTBEADMIN;
|
||||
}
|
||||
@@ -1028,7 +1009,7 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
$iRet = call_user_func(array(self::$sHandlerClass, 'ChangeLocation'), $sRequestedPortalId, $iOnExit);
|
||||
}
|
||||
if ($iOnExit == self::EXIT_RETURN)
|
||||
if ($iOnExit === self::EXIT_RETURN)
|
||||
{
|
||||
return $iRet;
|
||||
}
|
||||
@@ -1087,23 +1068,19 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
else if ($operation == 'change_pwd')
|
||||
{
|
||||
if (Session::IsSet('auth_user'))
|
||||
if (isset($_SESSION['auth_user']))
|
||||
{
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
$sIssue = Session::Get('pwd_issue');
|
||||
Session::Unset('pwd_issue');
|
||||
$bFailedLogin = ($sIssue != null); // Force the "failed login" flag to display the "issue" message
|
||||
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
$oPage = self::NewLoginWebPage();
|
||||
$oPage->DisplayChangePwdForm($bFailedLogin, $sIssue);
|
||||
$oPage->DisplayChangePwdForm();
|
||||
$oPage->output();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else if ($operation == 'check_pwd_policy')
|
||||
{
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
|
||||
$aPwdMap = array();
|
||||
@@ -1121,9 +1098,9 @@ class LoginWebPage extends NiceWebPage
|
||||
}
|
||||
if ($operation == 'do_change_pwd')
|
||||
{
|
||||
if (Session::IsSet('auth_user'))
|
||||
if (isset($_SESSION['auth_user']))
|
||||
{
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
UserRights::Login($sAuthUser); // Set the user's language
|
||||
$sOldPwd = utils::ReadPostedParam('old_pwd', '', 'raw_data');
|
||||
$sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -77,28 +77,17 @@ function _MaintenanceHtmlMessage($sMessage)
|
||||
*/
|
||||
function _MaintenanceJsonMessage($sTitle, $sMessage)
|
||||
{
|
||||
if (class_exists('JsonPage'))
|
||||
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
|
||||
if (class_exists('ajax_page'))
|
||||
{
|
||||
$oP = new JsonPage($sTitle);
|
||||
$oP = new ajax_page($sTitle);
|
||||
$oP->add_header('Access-Control-Allow-Origin: *');
|
||||
|
||||
$aMessage = [
|
||||
'code' => 100,
|
||||
'message' =>$sMessage
|
||||
];
|
||||
|
||||
$oP->AddData($aMessage);
|
||||
$oP->SetContentType('application/json');
|
||||
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
|
||||
$oP->Output();
|
||||
} else {
|
||||
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
|
||||
if (class_exists('ajax_page')) {
|
||||
$oP = new ajax_page($sTitle);
|
||||
$oP->add_header('Access-Control-Allow-Origin: *');
|
||||
$oP->SetContentType('application/json');
|
||||
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
|
||||
$oP->Output();
|
||||
} else {
|
||||
_MaintenanceTextMessage($sMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_MaintenanceTextMessage($sMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\Title;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/application/template.class.inc.php');
|
||||
require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
||||
@@ -42,10 +51,7 @@ require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
||||
* new OQLMenuNode('PersonsMenu', 'SELECT bizPerson', $oContactsMenu->GetIndex(), 0);
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class ApplicationMenu
|
||||
*/
|
||||
|
||||
class ApplicationMenu
|
||||
{
|
||||
/**
|
||||
@@ -60,19 +66,12 @@ class ApplicationMenu
|
||||
* @var array
|
||||
*/
|
||||
static $aMenusIndex = array();
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
static $aMenusById = [];
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
static $sFavoriteSiloQuery = 'SELECT Organization';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function LoadAdditionalMenus()
|
||||
static public function LoadAdditionalMenus()
|
||||
{
|
||||
if (!self::$bAdditionalMenusLoaded)
|
||||
{
|
||||
@@ -98,10 +97,10 @@ class ApplicationMenu
|
||||
|
||||
/**
|
||||
* Set the query used to limit the list of displayed organizations in the drop-down menu
|
||||
* @param string $sOQL The OQL query returning a list of Organization objects
|
||||
* @param $sOQL string The OQL query returning a list of Organization objects
|
||||
* @return void
|
||||
*/
|
||||
public static function SetFavoriteSiloQuery($sOQL)
|
||||
static public function SetFavoriteSiloQuery($sOQL)
|
||||
{
|
||||
self::$sFavoriteSiloQuery = $sOQL;
|
||||
}
|
||||
@@ -110,7 +109,7 @@ class ApplicationMenu
|
||||
* Get the query used to limit the list of displayed organizations in the drop-down menu
|
||||
* @return string The OQL query returning a list of Organization objects
|
||||
*/
|
||||
public static function GetFavoriteSiloQuery()
|
||||
static public function GetFavoriteSiloQuery()
|
||||
{
|
||||
return self::$sFavoriteSiloQuery;
|
||||
}
|
||||
@@ -118,11 +117,11 @@ class ApplicationMenu
|
||||
/**
|
||||
* Check whether a menu Id is enabled or not
|
||||
*
|
||||
* @param string $sMenuId
|
||||
* @param $sMenuId
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function CheckMenuIdEnabled($sMenuId)
|
||||
static public function CheckMenuIdEnabled($sMenuId)
|
||||
{
|
||||
self::LoadAdditionalMenus();
|
||||
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
|
||||
@@ -141,11 +140,11 @@ class ApplicationMenu
|
||||
* Main function to add a menu entry into the application, can be called during the definition
|
||||
* of the data model objects
|
||||
* @param MenuNode $oMenuNode
|
||||
* @param int $iParentIndex
|
||||
* @param float $fRank
|
||||
* @param $iParentIndex
|
||||
* @param $fRank
|
||||
* @return int
|
||||
*/
|
||||
public static function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
|
||||
static public function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
|
||||
{
|
||||
$index = self::GetMenuIndexById($oMenuNode->GetMenuId());
|
||||
if ($index == -1)
|
||||
@@ -172,7 +171,6 @@ class ApplicationMenu
|
||||
$aBacktrace = debug_backtrace();
|
||||
$sFile = isset($aBacktrace[2]["file"]) ? $aBacktrace[2]["file"] : $aBacktrace[1]["file"];
|
||||
self::$aMenusIndex[$index] = array('node' => $oMenuNode, 'children' => array(), 'parent' => $sParentId, 'rank' => $fRank, 'source_file' => $sFile);
|
||||
self::$aMenusById[$oMenuNode->GetMenuId()] = $index;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -187,166 +185,30 @@ class ApplicationMenu
|
||||
|
||||
/**
|
||||
* Reflection API - Get menu entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function ReflectionMenuNodes()
|
||||
static public function ReflectionMenuNodes()
|
||||
{
|
||||
self::LoadAdditionalMenus();
|
||||
return self::$aMenusIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entries count for all the menus
|
||||
*
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return array
|
||||
* @throws \DictExceptionMissingString
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function GetMenusCount($aExtraParams = array())
|
||||
{
|
||||
$aMenuGroups = static::GetMenuGroups($aExtraParams);
|
||||
|
||||
$aMenusCount = [];
|
||||
foreach ($aMenuGroups as $aMenuGroup) {
|
||||
$aSubMenuNodes = $aMenuGroup['aSubMenuNodes'];
|
||||
$aMenusCount = array_merge($aMenusCount, static::GetSubMenusCount($aSubMenuNodes));
|
||||
}
|
||||
|
||||
return $aMenusCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recurse sub menus for counts
|
||||
*
|
||||
* @param array $aSubMenuNodes
|
||||
*
|
||||
* @return array
|
||||
* @since 3.0.0
|
||||
*/
|
||||
private static function GetSubMenusCount(array $aSubMenuNodes)
|
||||
{
|
||||
$aSubMenusCount = [];
|
||||
foreach ($aSubMenuNodes as $aSubMenuNode) {
|
||||
if ($aSubMenuNode['bHasCount']) {
|
||||
$oMenuNode = static::GetMenuNode(static::GetMenuIndexById($aSubMenuNode['sId']));
|
||||
$aSubMenusCount[$aSubMenuNode['sId']] = $oMenuNode->GetEntriesCount();
|
||||
}
|
||||
$aSubMenusCount = array_merge($aSubMenusCount, static::GetSubMenusCount($aSubMenuNode['aSubMenuNodes']));
|
||||
}
|
||||
return $aSubMenusCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of menu groups
|
||||
*
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return array
|
||||
* @throws \DictExceptionMissingString
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function GetMenuGroups($aExtraParams = array())
|
||||
{
|
||||
self::LoadAdditionalMenus();
|
||||
|
||||
// Sort the root menu based on the rank
|
||||
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
|
||||
|
||||
$aMenuGroups = [];
|
||||
foreach(static::$aRootMenus as $aMenuGroup)
|
||||
{
|
||||
if(!static::CanDisplayMenu($aMenuGroup))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$sMenuGroupIdx = $aMenuGroup['index'];
|
||||
/** @var \MenuGroup $oMenuNode */
|
||||
$oMenuNode = static::GetMenuNode($sMenuGroupIdx);
|
||||
|
||||
$aMenuGroups[] = [
|
||||
'sId' => $oMenuNode->GetMenuID(),
|
||||
'sIconCssClasses' => $oMenuNode->GetDecorationClasses(),
|
||||
'sInitials' => $oMenuNode->GetInitials(),
|
||||
'sTitle' => $oMenuNode->GetTitle(),
|
||||
'aSubMenuNodes' => static::GetSubMenuNodes($sMenuGroupIdx, $aExtraParams),
|
||||
];
|
||||
}
|
||||
|
||||
return $aMenuGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of sub-menu nodes for $sMenuGroupIdx
|
||||
*
|
||||
* @param string $sMenuGroupIdx
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return array
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \Exception
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function GetSubMenuNodes($sMenuGroupIdx, $aExtraParams = array())
|
||||
{
|
||||
$aSubMenuItems = self::GetChildren($sMenuGroupIdx);
|
||||
|
||||
// Sort the children based on the rank
|
||||
usort($aSubMenuItems, array('ApplicationMenu', 'CompareOnRank'));
|
||||
|
||||
$aSubMenuNodes = [];
|
||||
foreach($aSubMenuItems as $aSubMenuItem)
|
||||
{
|
||||
if(!static::CanDisplayMenu($aSubMenuItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$sSubMenuItemIdx = $aSubMenuItem['index'];
|
||||
$oSubMenuNode = static::GetMenuNode($sSubMenuItemIdx);
|
||||
|
||||
if(!$oSubMenuNode->IsEnabled())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$aSubMenuNodes[] = [
|
||||
'sId' => $oSubMenuNode->GetMenuId(),
|
||||
'sTitle' => $oSubMenuNode->GetTitle(),
|
||||
'bHasCount' => $oSubMenuNode->HasCount(),
|
||||
'sUrl' => $oSubMenuNode->GetHyperlink($aExtraParams),
|
||||
'bOpenInNewWindow' => $oSubMenuNode->IsHyperLinkInNewWindow(),
|
||||
'aSubMenuNodes' => static::GetSubMenuNodes($sSubMenuItemIdx, $aExtraParams),
|
||||
];
|
||||
}
|
||||
|
||||
return $aSubMenuNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point to display the whole menu into the web page, used by iTopWebPage
|
||||
* @param \WebPage $oPage
|
||||
* @param array $aExtraParams
|
||||
* @param $aExtraParams
|
||||
* @throws DictExceptionMissingString
|
||||
*
|
||||
* @deprecated Will be removed in 3.0.0, use static::GetMenuGroups() instead
|
||||
*/
|
||||
public static function DisplayMenu($oPage, $aExtraParams)
|
||||
static public 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;
|
||||
}
|
||||
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>');
|
||||
@@ -375,7 +237,7 @@ EOF
|
||||
* @param array $aMenu menu entry
|
||||
* @return bool true if at least one menu is enabled
|
||||
*/
|
||||
private static function CanDisplayMenu($aMenu)
|
||||
static private function CanDisplayMenu($aMenu)
|
||||
{
|
||||
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
||||
if ($oMenuNode->IsEnabled())
|
||||
@@ -407,19 +269,19 @@ EOF
|
||||
* @param array $aExtraParams
|
||||
* @param int $iActiveMenu
|
||||
*
|
||||
* @return bool True if the currently selected menu is one of the submenus
|
||||
* @return 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)
|
||||
static protected 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)) {
|
||||
foreach($aMenus as $aMenu)
|
||||
{
|
||||
if (!self::CanDisplayMenu($aMenu))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$index = $aMenu['index'];
|
||||
@@ -468,11 +330,11 @@ EOF
|
||||
|
||||
/**
|
||||
* Helper function to sort the menus based on their rank
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @param $a
|
||||
* @param $b
|
||||
* @return int
|
||||
*/
|
||||
public static function CompareOnRank($a, $b)
|
||||
static public function CompareOnRank($a, $b)
|
||||
{
|
||||
$result = 1;
|
||||
if ($a['rank'] == $b['rank'])
|
||||
@@ -491,7 +353,7 @@ EOF
|
||||
* @param int $index
|
||||
* @return MenuNode|null
|
||||
*/
|
||||
public static function GetMenuNode($index)
|
||||
static public function GetMenuNode($index)
|
||||
{
|
||||
return isset(self::$aMenusIndex[$index]) ? self::$aMenusIndex[$index]['node'] : null;
|
||||
}
|
||||
@@ -501,7 +363,7 @@ EOF
|
||||
* @param int $index
|
||||
* @return array
|
||||
*/
|
||||
public static function GetChildren($index)
|
||||
static public function GetChildren($index)
|
||||
{
|
||||
return self::$aMenusIndex[$index]['children'];
|
||||
}
|
||||
@@ -511,20 +373,26 @@ EOF
|
||||
* @param string $sTitle Title of the menu (as passed when creating the menu)
|
||||
* @return integer ID of the menu, or -1 if not found
|
||||
*/
|
||||
public static function GetMenuIndexById($sTitle)
|
||||
static public function GetMenuIndexById($sTitle)
|
||||
{
|
||||
if (isset(self::$aMenusById[$sTitle])) {
|
||||
return self::$aMenusById[$sTitle];
|
||||
$index = -1;
|
||||
/** @var MenuNode[] $aMenu */
|
||||
foreach(self::$aMenusIndex as $aMenu)
|
||||
{
|
||||
if ($aMenu['node']->GetMenuId() == $sTitle)
|
||||
{
|
||||
$index = $aMenu['node']->GetIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the currently active menu (if any, otherwise the first menu is the default)
|
||||
* @return string The Id of the currently active menu
|
||||
*/
|
||||
public static function GetActiveNodeId()
|
||||
static public function GetActiveNodeId()
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
|
||||
@@ -538,7 +406,7 @@ EOF
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public static function GetDefaultMenuId()
|
||||
static public function GetDefaultMenuId()
|
||||
{
|
||||
static $sDefaultMenuId = null;
|
||||
if (is_null($sDefaultMenuId))
|
||||
@@ -558,7 +426,7 @@ EOF
|
||||
* @param $sMenuId
|
||||
* @return string
|
||||
*/
|
||||
public static function GetRootMenuId($sMenuId)
|
||||
static public function GetRootMenuId($sMenuId)
|
||||
{
|
||||
$iMenuIndex = self::GetMenuIndexById($sMenuId);
|
||||
if ($iMenuIndex == -1)
|
||||
@@ -695,62 +563,29 @@ abstract class MenuNode
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws DictExceptionMissingString
|
||||
*/
|
||||
public function GetTitle()
|
||||
{
|
||||
return Dict::S("Menu:$this->sMenuId", str_replace('_', ' ', $this->sMenuId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the page corresponding to this menu node is countable
|
||||
*
|
||||
* @return bool true if corresponding page is countable
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function HasCount()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function GetEntriesCountFromOQL(string $sOQL)
|
||||
{
|
||||
// Count the entries up to 99
|
||||
$oSearch = DBSearch::FromOQL($sOQL);
|
||||
$oSearch->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
DBSearchHelper::AddContextFilter($oSearch);
|
||||
|
||||
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$iCount = $oSet->CountWithLimit(99);
|
||||
if ($iCount > 99) {
|
||||
$iCount = "99+";
|
||||
}
|
||||
|
||||
return $iCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of entries of the page corresponding to this menu item.
|
||||
*
|
||||
* @return int the number of entries
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetEntriesCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws DictExceptionMissingString
|
||||
*/
|
||||
public function GetLabel()
|
||||
{
|
||||
$sRet = Dict::S("Menu:$this->sMenuId+", "");
|
||||
if ($sRet === '') {
|
||||
if ($this->iParentIndex != -1) {
|
||||
if ($sRet === '')
|
||||
{
|
||||
if ($this->iParentIndex != -1)
|
||||
{
|
||||
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
||||
$sRet = $oParentMenu->GetTitle().' / '.$this->GetTitle();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRet = $this->GetTitle();
|
||||
}
|
||||
//$sRet = $this->GetTitle();
|
||||
@@ -765,10 +600,7 @@ abstract class MenuNode
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function PopulateChildMenus()
|
||||
{
|
||||
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu)
|
||||
@@ -893,64 +725,18 @@ abstract class MenuNode
|
||||
*/
|
||||
class MenuGroup extends MenuNode
|
||||
{
|
||||
/** @var string DEFAULT_DECORATION_CLASSES Set to null by default so it is replaced by initials when none is specified */
|
||||
const DEFAULT_DECORATION_CLASSES = null;
|
||||
|
||||
/** @var string The CSS classes used to display the menu group's icon */
|
||||
protected $sDecorationClasses = self::DEFAULT_DECORATION_CLASSES;
|
||||
|
||||
/**
|
||||
* Create a top-level menu group and inserts it into the application's main menu
|
||||
*
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
* @param float $fRank Number used to order the list, the groups are sorted based on this value
|
||||
* @param string|null $sDecorationClasses CSS classes used to display the menu group's icon
|
||||
* @param string $sEnableClass Name of class of object
|
||||
* @param integer $iActionCode Either UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_DELETE, UR_ACTION_BULKREAD, UR_ACTION_BULKMODIFY or UR_ACTION_BULKDELETE
|
||||
* @param integer $iAllowedResults Expected "rights" for the action: either UR_ALLOWED_YES, UR_ALLOWED_NO, UR_ALLOWED_DEPENDS or a mix of them...
|
||||
* @param string $sEnableStimulus
|
||||
*/
|
||||
public function __construct($sMenuId, $fRank, $sDecorationClasses = null, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
|
||||
public function __construct($sMenuId, $fRank, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
|
||||
{
|
||||
parent::__construct($sMenuId, -1 /* no parent, groups are at root level */, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
|
||||
|
||||
if(!empty($sDecorationClasses))
|
||||
{
|
||||
$this->sDecorationClasses = $sDecorationClasses;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the menu group has some decoration classes
|
||||
*
|
||||
* @return bool
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function HasDecorationClasses()
|
||||
{
|
||||
return (empty($this->GetDecorationClasses()) === false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CSS classes used for decorating the menu group (typically the icon in the navigation menu)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetDecorationClasses()
|
||||
{
|
||||
return $this->sDecorationClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initials of the menu group, used by the rendering in case there is no decoration classes
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function GetInitials()
|
||||
{
|
||||
return mb_substr($this->GetTitle(), 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1127,45 +913,30 @@ class OQLMenuNode extends MenuNode
|
||||
{
|
||||
$sUsageId = utils::GetSafeId($sUsageId);
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
$sClass= $oSearch->GetClass();
|
||||
$sIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
if ($bSearchPane) {
|
||||
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams);
|
||||
$sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
|
||||
|
||||
if ($bSearchPane)
|
||||
{
|
||||
$aParams = array_merge(array('open' => $bSearchOpen, 'table_id' => $sUsageId), $aExtraParams);
|
||||
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oPage, 0);
|
||||
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>");
|
||||
}
|
||||
else {
|
||||
$oPage->add("<div class='sf_results_area' data-target='search_results'>");
|
||||
}
|
||||
$aExtraParams['panel_class'] =$sClass;
|
||||
$aExtraParams['panel_title'] = $sTitle;
|
||||
$aExtraParams['panel_icon'] = $sIcon;
|
||||
|
||||
|
||||
$oPage->add("<p class=\"page-header\">$sIcon ".utils::HtmlEntities(Dict::S($sTitle))."</p>");
|
||||
|
||||
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
|
||||
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oPage, $sUsageId);
|
||||
|
||||
$oPage->add("</div>");
|
||||
|
||||
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage)) {
|
||||
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage))
|
||||
{
|
||||
// Breadcrumb
|
||||
//$iCount = $oBlock->GetDisplayedCount();
|
||||
$sPageId = "ui-search-".$oSearch->GetClass();
|
||||
$sLabel = MetaModel::GetName($oSearch->GetClass());
|
||||
$oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', 'fas fa-list', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
$oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', '../images/breadcrumb-search.png');
|
||||
}
|
||||
}
|
||||
|
||||
public function HasCount()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetEntriesCount()
|
||||
{
|
||||
return $this->GetEntriesCountFromOQL($this->sOQL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1210,11 +981,10 @@ class SearchMenuNode extends MenuNode
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
|
||||
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png');
|
||||
|
||||
$oSearch = new DBObjectSearch($this->sClass);
|
||||
$sUsageId = 'Menu_'.utils::GetSafeId($this->GetMenuId());
|
||||
$aParams = array_merge(array('table_id' =>$sUsageId), $aExtraParams);
|
||||
$aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
|
||||
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oPage, 0);
|
||||
}
|
||||
@@ -1420,35 +1190,41 @@ class DashboardMenuNode extends MenuNode
|
||||
$oDashboard = $this->GetDashboard();
|
||||
if ($oDashboard != null)
|
||||
{
|
||||
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
||||
|
||||
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
||||
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
|
||||
$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
|
||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||
$aExtraParams['from_dashboard_page'] = true;
|
||||
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||
$oPage->add('</div>');
|
||||
|
||||
$bEdit = utils::ReadParam('edit', false);
|
||||
if ($bEdit) {
|
||||
if ($bEdit)
|
||||
{
|
||||
$sId = addslashes($this->sMenuId);
|
||||
$oPage->add_ready_script("EditDashboard('$sId');");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
||||
$sParentTitle = $oParentMenu->GetTitle();
|
||||
$sThisTitle = $this->GetTitle();
|
||||
if ($sParentTitle != $sThisTitle) {
|
||||
if ($sParentTitle != $sThisTitle)
|
||||
{
|
||||
$sDescription = $sParentTitle.' / '.$sThisTitle;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDescription = $sThisTitle;
|
||||
}
|
||||
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId()) {
|
||||
$sIcon = 'fas fa-home';
|
||||
} else {
|
||||
$sIcon = 'fas fa-chart-pie';
|
||||
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId())
|
||||
{
|
||||
$sIcon = '../images/breadcrumb_home.png';
|
||||
}
|
||||
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
else
|
||||
{
|
||||
$sIcon = '../images/breadcrumb-dashboard.png';
|
||||
}
|
||||
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1617,23 +1393,5 @@ class ShortcutMenuNode extends MenuNode
|
||||
{
|
||||
return $this->oShortcut->Get('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the page corresponding to this menu node is countable
|
||||
*
|
||||
* @return bool true if corresponding page is countable
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function HasCount()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function GetEntriesCount()
|
||||
{
|
||||
return $this->GetEntriesCountFromOQL($this->oShortcut->Get('oql'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
|
||||
@@ -1,8 +1,262 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
||||
/**
|
||||
* Web page with some associated CSS and scripts (jquery) for a fancier display
|
||||
*/
|
||||
class NiceWebPage extends WebPage
|
||||
{
|
||||
var $m_aReadyScripts;
|
||||
var $m_sRootUrl;
|
||||
|
||||
public function __construct($s_title, $bPrintable = false)
|
||||
{
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
$this->m_aReadyScripts = array();
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.min.js');
|
||||
if(utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
|
||||
{
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev.js');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.prod.min.js');
|
||||
}
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/hovertip.js');
|
||||
// table sorting
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.pager.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablehover.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.popupmenu.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/searchformforeignkeys.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/latinise/latinise.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_handler.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_handler_history.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_raw.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_string.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_field.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_numeric.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_enum.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_tag_set.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_key.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_hierarchical_key.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_abstract.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_time.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/clipboard.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/clipboardwidget.js');
|
||||
|
||||
$this->add_dict_entries('UI:Combo');
|
||||
|
||||
$this->add_ready_script(
|
||||
<<< EOF
|
||||
//add new widget called TruncatedList to properly display truncated lists when they are sorted
|
||||
$.tablesorter.addWidget({
|
||||
// give the widget a id
|
||||
id: "truncatedList",
|
||||
// format is called when the on init and when a sorting has finished
|
||||
format: function(table)
|
||||
{
|
||||
// Check if there is a "truncated" line
|
||||
this.truncatedList = false;
|
||||
if ($("tr td.truncated",table).length > 0)
|
||||
{
|
||||
this.truncatedList = true;
|
||||
}
|
||||
if (this.truncatedList)
|
||||
{
|
||||
$("tr td",table).removeClass('truncated');
|
||||
$("tr:last td",table).addClass('truncated');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.tablesorter.addWidget({
|
||||
// give the widget a id
|
||||
id: "myZebra",
|
||||
// format is called when the on init and when a sorting has finished
|
||||
format: function(table)
|
||||
{
|
||||
// Replace the 'red even' lines by 'red_even' since most browser do not support 2 classes selector in CSS, etc..
|
||||
$("tbody tr:even",table).addClass('even');
|
||||
$("tbody tr.red:even",table).removeClass('red').removeClass('even').addClass('red_even');
|
||||
$("tbody tr.orange:even",table).removeClass('orange').removeClass('even').addClass('orange_even');
|
||||
$("tbody tr.green:even",table).removeClass('green').removeClass('even').addClass('green_even');
|
||||
// In case we sort again the table, we need to remove the added 'even' classes on odd rows
|
||||
$("tbody tr:odd",table).removeClass('even');
|
||||
$("tbody tr.red_even:odd",table).removeClass('even').removeClass('red_even').addClass('red');
|
||||
$("tbody tr.orange_even:odd",table).removeClass('even').removeClass('orange_even').addClass('orange');
|
||||
$("tbody tr.green_even:odd",table).removeClass('even').removeClass('green_even').addClass('green');
|
||||
}
|
||||
});
|
||||
$("table.listResults").tableHover(); // hover tables
|
||||
EOF
|
||||
);
|
||||
$this->LoadTheme();
|
||||
|
||||
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
|
||||
$sAbsURLAppRoot = addslashes($this->m_sRootUrl);
|
||||
$sAbsURLModulesRoot = addslashes($this->GetAbsoluteUrlModulesRoot());
|
||||
$sEnvironment = addslashes(utils::GetCurrentEnvironment());
|
||||
|
||||
$sAppContext = addslashes($this->GetApplicationContext());
|
||||
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
function GetAbsoluteUrlAppRoot()
|
||||
{
|
||||
return '$sAbsURLAppRoot';
|
||||
}
|
||||
|
||||
function GetAbsoluteUrlModulesRoot()
|
||||
{
|
||||
return '$sAbsURLModulesRoot';
|
||||
}
|
||||
|
||||
function GetAbsoluteUrlModulePage(sModule, sPage, aArguments)
|
||||
{
|
||||
// aArguments is optional, it default to an empty hash
|
||||
aArguments = typeof aArguments !== 'undefined' ? aArguments : {};
|
||||
|
||||
var sUrl = '$sAbsURLAppRoot'+'pages/exec.php?exec_module='+sModule+'&exec_page='+sPage+'&exec_env='+'$sEnvironment';
|
||||
for (var sArgName in aArguments)
|
||||
{
|
||||
if (aArguments.hasOwnProperty(sArgName))
|
||||
{
|
||||
sUrl = sUrl + '&'+sArgName+'='+aArguments[sArgname];
|
||||
}
|
||||
}
|
||||
return sUrl;
|
||||
}
|
||||
|
||||
function AddAppContext(sURL)
|
||||
{
|
||||
var sContext = '$sAppContext';
|
||||
if (sContext.length > 0)
|
||||
{
|
||||
if (sURL.indexOf('?') == -1)
|
||||
{
|
||||
return sURL+'?'+sContext;
|
||||
}
|
||||
return sURL+'&'+sContext;
|
||||
}
|
||||
return sURL;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
public function SetRootUrl($sRootUrl)
|
||||
{
|
||||
$this->m_sRootUrl = $sRootUrl;
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
$this->add("<p style=\"font-size:smaller\">$sText</p>\n");
|
||||
}
|
||||
|
||||
public function GetAbsoluteUrlAppRoot()
|
||||
{
|
||||
return utils::GetAbsoluteUrlAppRoot();
|
||||
}
|
||||
|
||||
public function GetAbsoluteUrlModulesRoot()
|
||||
{
|
||||
return utils::GetAbsoluteUrlModulesRoot();
|
||||
}
|
||||
|
||||
function GetApplicationContext()
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
return $oAppContext->GetForLink();
|
||||
}
|
||||
|
||||
// By Rom, used by CSVImport and Advanced search
|
||||
public function MakeClassesSelect($sName, $sDefaultValue, $iWidthPx, $iActionCode = null)
|
||||
{
|
||||
// $aTopLevelClasses = array('bizService', 'bizContact', 'logInfra', 'bizDocument');
|
||||
// These are classes wich root class is cmdbAbstractObject !
|
||||
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
|
||||
$aValidClasses = array();
|
||||
foreach(MetaModel::GetClasses('bizmodel') as $sClassName)
|
||||
{
|
||||
if (is_null($iActionCode) || UserRights::IsActionAllowed($sClassName, $iActionCode))
|
||||
{
|
||||
$sSelected = ($sClassName == $sDefaultValue) ? " SELECTED" : "";
|
||||
$sDescription = MetaModel::GetClassDescription($sClassName);
|
||||
$sDisplayName = MetaModel::GetName($sClassName);
|
||||
$aValidClasses[$sDisplayName] = "<option style=\"width: ".$iWidthPx." px;\" title=\"$sDescription\" value=\"$sClassName\"$sSelected>$sDisplayName</option>";
|
||||
}
|
||||
}
|
||||
ksort($aValidClasses);
|
||||
$this->add(implode("\n", $aValidClasses));
|
||||
|
||||
$this->add("</select>");
|
||||
}
|
||||
|
||||
// By Rom, used by Advanced search
|
||||
public function add_select($aChoices, $sName, $sDefaultValue, $iWidthPx)
|
||||
{
|
||||
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
|
||||
foreach($aChoices as $sKey => $sValue)
|
||||
{
|
||||
$sSelected = ($sKey == $sDefaultValue) ? " SELECTED" : "";
|
||||
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"".htmlspecialchars($sKey)."\"$sSelected>".htmlentities($sValue,
|
||||
ENT_QUOTES, self::PAGES_CHARSET)."</option>");
|
||||
}
|
||||
$this->add("</select>");
|
||||
}
|
||||
|
||||
public function add_ready_script($sScript)
|
||||
{
|
||||
$this->m_aReadyScripts[] = $sScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
//$this->set_base($this->m_sRootUrl.'pages/');
|
||||
if (count($this->m_aReadyScripts)>0)
|
||||
{
|
||||
$this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});");
|
||||
}
|
||||
parent::output();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected function LoadTheme()
|
||||
{
|
||||
$sCssThemeUrl = ThemeHandler::GetCurrentThemeUrl();
|
||||
$this->add_linked_stylesheet($sCssThemeUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader');
|
||||
require_once(APPROOT.'application/utils.inc.php');
|
||||
|
||||
/**
|
||||
* Custom class derived from TCPDF for providing custom headers and footers
|
||||
*
|
||||
* @author denis
|
||||
*
|
||||
*/
|
||||
class iTopPDF extends TCPDF
|
||||
{
|
||||
protected $sDocumentTitle;
|
||||
|
||||
/**
|
||||
* Shortcut for {@link TCPDF::SetFont}, to use the font configured
|
||||
*
|
||||
* @param string $style
|
||||
* @param int $size
|
||||
* @param string $fontfile
|
||||
* @param string $subset
|
||||
* @param bool $out
|
||||
*
|
||||
* @uses \TCPDF::SetFont()
|
||||
* @uses \iTopPDF::GetPdfFont()
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function SetFontParams($style, $size, $fontfile='', $subset='default', $out=true)
|
||||
{
|
||||
$siTopFont = self::GetPdfFont();
|
||||
$this->SetFont($siTopFont, $style, $size, $fontfile, $subset, $out);
|
||||
}
|
||||
|
||||
public function SetDocumentTitle($sDocumentTitle)
|
||||
{
|
||||
$this->sDocumentTitle = $sDocumentTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the custom header. Called for each new page.
|
||||
*
|
||||
* @see TCPDF::Header()
|
||||
*/
|
||||
public function Header()
|
||||
{
|
||||
// Title
|
||||
// Set font
|
||||
$this->SetFontParams('B', 10);
|
||||
|
||||
$iPageNumberWidth = 25;
|
||||
$aMargins = $this->getMargins();
|
||||
|
||||
// Display the title (centered)
|
||||
$this->SetXY($aMargins['left'] + $iPageNumberWidth, 0);
|
||||
$this->MultiCell($this->getPageWidth() - $aMargins['left'] - $aMargins['right'] - 2 * $iPageNumberWidth, 15, $this->sDocumentTitle,
|
||||
0, 'C', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
$this->SetFontParams('', 10);
|
||||
|
||||
// Display the page number (right aligned)
|
||||
// Warning: the 'R'ight alignment does not work when using placeholders like $this->getAliasNumPage() or $this->getAliasNbPages()
|
||||
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber', $this->page), 0, 'R', false, 0 /* $ln */, '',
|
||||
'', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
|
||||
// Branding logo
|
||||
$sBrandingIcon = APPROOT.'images/itop-logo.png';
|
||||
if (file_exists(MODULESROOT.'branding/main-logo.png'))
|
||||
{
|
||||
$sBrandingIcon = MODULESROOT.'branding/main-logo.png';
|
||||
}
|
||||
$this->Image($sBrandingIcon, $aMargins['left'], 5, 0, 10);
|
||||
}
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
// No footer
|
||||
}
|
||||
|
||||
/**
|
||||
* dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
* @return string font in the config file (export_pdf_font)
|
||||
*/
|
||||
public static function GetPdfFont()
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$sPdfFont = $oConfig->Get('export_pdf_font');
|
||||
|
||||
return $sPdfFont;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special class of WebPage for printing into a PDF document
|
||||
*/
|
||||
class PDFPage extends WebPage
|
||||
{
|
||||
/** @var \iTopPDF Instance of the TCPDF object for creating the PDF */
|
||||
protected $oPdf;
|
||||
|
||||
public function __construct($s_title, $sPageFormat = 'A4', $sPageOrientation = 'L')
|
||||
{
|
||||
parent::__construct($s_title);
|
||||
define(K_PATH_FONTS, APPROOT.'lib/combodo/tcpdf/fonts');
|
||||
$this->oPdf = new iTopPDF($sPageOrientation, 'mm', $sPageFormat, true, self::PAGES_CHARSET, false);
|
||||
|
||||
// set document information
|
||||
$this->oPdf->SetCreator(PDF_CREATOR);
|
||||
$this->oPdf->SetAuthor('iTop');
|
||||
$this->oPdf->SetTitle($s_title);
|
||||
$this->oPdf->SetDocumentTitle($s_title);
|
||||
|
||||
$this->oPdf->setFontSubsetting(true);
|
||||
|
||||
// dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
$this->oPdf->SetFontParams('', 10, '', true);
|
||||
|
||||
// set auto page breaks
|
||||
$this->oPdf->SetAutoPageBreak(true, 15); // 15 mm break margin at the bottom
|
||||
$this->oPdf->SetTopMargin(15);
|
||||
|
||||
// Add a page, we're ready to start
|
||||
$this->oPdf->AddPage();
|
||||
|
||||
$this->SetContentDisposition('inline', $s_title.'.pdf');
|
||||
$this->SetDefaultStyle();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default style (suitable for printing) to be included each time $this->oPdf->writeHTML() is called
|
||||
*/
|
||||
protected function SetDefaultStyle()
|
||||
{
|
||||
$this->add_style(
|
||||
<<<EOF
|
||||
table {
|
||||
padding: 2pt;
|
||||
}
|
||||
table.listResults td {
|
||||
border: 0.5pt solid #000 ;
|
||||
}
|
||||
table.listResults th {
|
||||
background-color: #eee;
|
||||
border: 0.5pt solid #000 ;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
table.section td {
|
||||
vertical-align: middle;
|
||||
font-size: 10pt;
|
||||
background-color:#eee;
|
||||
}
|
||||
td.icon {
|
||||
width: 30px;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access to the underlying TCPDF object
|
||||
*
|
||||
* @return \iTopPDF
|
||||
*/
|
||||
public function get_tcpdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the currently buffered HTML content into the PDF. This can be useful:
|
||||
* - to sync the flow in case you want to access the underlying TCPDF object for some specific/graphic output
|
||||
* - to process the HTML by smaller chunks instead of processing the whole page at once for performance reasons
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
if (strlen($this->s_content) > 0)
|
||||
{
|
||||
$sHtml = '';
|
||||
if (count($this->a_styles) > 0)
|
||||
{
|
||||
$sHtml .= "<style>\n".implode("\n", $this->a_styles)."\n</style>\n";
|
||||
}
|
||||
$sHtml .= $this->s_content;
|
||||
$this->oPdf->writeHTML($sHtml); // The style(s) must be supplied each time we call writeHtml
|
||||
$this->s_content = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the page is a PDF page
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_pdf()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the PDF document and returns the PDF content as a string
|
||||
*
|
||||
* @return string
|
||||
* @see WebPage::output()
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$this->add_header('Content-type: application/x-pdf');
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach ($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$this->flush();
|
||||
echo $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
}
|
||||
|
||||
public function get_pdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2010-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Field\Field;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
|
||||
|
||||
/**
|
||||
* Persistent class Event and derived
|
||||
* Application internal events
|
||||
* There is also a file log
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
abstract class Query extends cmdbAbstractObject
|
||||
{
|
||||
/**
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0 N°3227 add is_template field for predefined queries
|
||||
*/
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
@@ -41,41 +40,20 @@ abstract class Query extends cmdbAbstractObject
|
||||
"db_table" => "priv_query",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "realclass",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeString("name", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "name",
|
||||
"default_value" => null,
|
||||
"is_null_allowed" => false,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("description", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "description",
|
||||
"default_value" => null,
|
||||
"is_null_allowed" => false,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("is_template", array(
|
||||
'allowed_values' => new ValueSetEnum('yes,no'),
|
||||
'sql' => 'is_template',
|
||||
'default_value' => 'no',
|
||||
'is_null_allowed' => false,
|
||||
'depends_on' => [],
|
||||
'display_style' => 'radio_horizontal',
|
||||
)));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details',
|
||||
array('name', 'is_template', 'description')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'is_template')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search',
|
||||
array('name', 'description', 'is_template')); // Criteria of the default search form
|
||||
MetaModel::Init_SetZListItems('standard_search', array('name', 'description')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
}
|
||||
@@ -90,73 +68,59 @@ class QueryOQL extends Query
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('oql', 'is_template'),
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_query_oql",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "oql",
|
||||
"default_value" => null,
|
||||
"is_null_allowed" => false,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("fields", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "fields",
|
||||
"default_value" => null,
|
||||
"is_null_allowed" => true,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
|
||||
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details',
|
||||
array('name', 'is_template', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search',
|
||||
array('name', 'description', 'is_template', 'fields', 'oql')); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'fields', 'oql')); // Criteria of the std search form
|
||||
}
|
||||
|
||||
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
|
||||
{
|
||||
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
|
||||
$oPage->add_script("$('[name=\"attr_oql\"]').addClass('ibo-query-oql ibo-is-code'); $('[data-attribute-code=\"oql\"]').addClass('ibo-query-oql ibo-is-code');");
|
||||
|
||||
if (!$bEditMode) {
|
||||
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$sFields = trim($this->Get('fields'));
|
||||
$bExportV1Recommended = ($sFields == '');
|
||||
if ($bExportV1Recommended) {
|
||||
if ($bExportV1Recommended)
|
||||
{
|
||||
$oFieldAttDef = MetaModel::GetAttributeDef('QueryOQL', 'fields');
|
||||
$oAlert = AlertUIBlockFactory::MakeForFailure()
|
||||
->SetIsClosable(false)
|
||||
->SetIsCollapsible(false);
|
||||
$oAlert->AddCSSClass('mb-5');
|
||||
$oAlert->AddSubBlock(new Html(Dict::Format('UI:Query:UrlV1', '')));
|
||||
$oPage->AddSubBlock($oAlert);
|
||||
$oPage->add('<div class="message message_error" style="padding-left: 30px;"><div style="padding: 10px;">'.Dict::Format('UI:Query:UrlV1', $oFieldAttDef->GetLabel()).'</div></div>');
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
|
||||
}
|
||||
$sOql = $this->Get('oql');
|
||||
$sMessage = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
$aParameters = $oSearch->GetQueryParams();
|
||||
foreach ($aParameters as $sParam => $val) {
|
||||
foreach($aParameters as $sParam => $val)
|
||||
{
|
||||
$sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]';
|
||||
}
|
||||
|
||||
$oTextArea = new TextArea("", $sUrl, null, 80, 3);
|
||||
$oFieldUrl = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:Query:UrlForExcel'), $oTextArea, Field::ENUM_FIELD_LAYOUT_LARGE);
|
||||
$oPage->AddSubBlock($oFieldUrl);
|
||||
$oPage->p(Dict::S('UI:Query:UrlForExcel').':<br/><textarea cols="80" rows="3" READONLY>'.$sUrl.'</textarea>');
|
||||
|
||||
if (count($aParameters) == 0) {
|
||||
if (count($aParameters) == 0)
|
||||
{
|
||||
$oBlock = new DisplayBlock($oSearch, 'list');
|
||||
$aExtraParams = array(
|
||||
//'menu' => $sShowMenu,
|
||||
@@ -166,13 +130,10 @@ class QueryOQL extends Query
|
||||
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
|
||||
}
|
||||
}
|
||||
catch
|
||||
(OQLException $e) {
|
||||
$oAlert = AlertUIBlockFactory::MakeForFailure(Dict::Format('UI:RunQuery:Error'), $e->getHtmlDesc())
|
||||
->SetIsClosable(false)
|
||||
->SetIsCollapsible(false);
|
||||
$oAlert->AddCSSClass('mb-5');
|
||||
$oPage->AddSubBlock($oAlert);
|
||||
catch (OQLException $e)
|
||||
{
|
||||
$sMessage = '<div class="message message_error" style="padding-left: 30px;"><div style="padding: 10px;">'.Dict::Format('UI:RunQuery:Error', $e->getHtmlDesc()).'</div></div>';
|
||||
$oPage->p($sMessage);
|
||||
}
|
||||
}
|
||||
return $aFieldsMap;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -15,14 +15,13 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||
|
||||
|
||||
/**
|
||||
* Persistent class Shortcut and derived
|
||||
* Shortcuts of any kind
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -40,6 +39,7 @@ abstract class Shortcut extends DBObject implements iDisplay
|
||||
"db_table" => "priv_shortcut",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "realclass",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
@@ -101,7 +101,7 @@ function ShortcutRenameOK()
|
||||
});
|
||||
}
|
||||
|
||||
$('#shortcut_rename_dlg form').on('submit', function() { return false; });
|
||||
$('#shortcut_rename_dlg form').bind('submit', function() { return false; });
|
||||
|
||||
$('#shortcut_rename_dlg').dialog({
|
||||
width: 400,
|
||||
@@ -161,6 +161,7 @@ class ShortcutOQL extends Shortcut
|
||||
"db_table" => "priv_shortcut_oql",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
@@ -286,10 +287,10 @@ class ShortcutOQL extends Shortcut
|
||||
$sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval')));
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
<<<EOF
|
||||
|
||||
// Note: the title gets deleted by the validation mechanism
|
||||
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
|
||||
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
|
||||
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||
|
||||
$('#attr_auto_reload').change( function(ev) {
|
||||
@@ -315,30 +316,23 @@ function ShortcutCreationOK()
|
||||
});
|
||||
}
|
||||
|
||||
$('#shortcut_creation_dlg form').on('submit', function() { ShortcutCreationOK(); return false; });
|
||||
$('#shortcut_creation_dlg form').bind('submit', function() { ShortcutCreationOK(); return false; });
|
||||
|
||||
$('#shortcut_creation_dlg').dialog({
|
||||
width: 400,
|
||||
modal: true,
|
||||
title: '$sDialogTitle',
|
||||
buttons: [
|
||||
{
|
||||
text: "$sCancelButtonLabel",
|
||||
class: "ibo-is-alternative",
|
||||
click: function() {
|
||||
$(this).dialog( "close" );
|
||||
$(this).remove();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: "$sOkButtonLabel",
|
||||
class: "ibo-is-primary",
|
||||
click: ShortcutCreationOK
|
||||
},
|
||||
{ text: "$sOkButtonLabel", click: ShortcutCreationOK },
|
||||
{ text: "$sCancelButtonLabel", click: function() {
|
||||
$(this).dialog( "close" ); $(this).remove();
|
||||
} },
|
||||
],
|
||||
close: function() { $(this).remove(); }
|
||||
});
|
||||
JS
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -15,24 +15,18 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
* File to include to initialize the datamodel in memory
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
ExecutionKPI::EnableDuration(1);
|
||||
ExecutionKPI::EnableMemory(1);
|
||||
|
||||
// This storage is freed on error (case of allowed memory exhausted)
|
||||
$sReservedMemory = str_repeat('*', 1024 * 1024);
|
||||
register_shutdown_function(function()
|
||||
@@ -64,15 +58,14 @@ register_shutdown_function(function()
|
||||
}
|
||||
}
|
||||
});
|
||||
$oKPI = new ExecutionKPI();
|
||||
Session::Start();
|
||||
$oKPI->ComputeAndReport("Session Start");
|
||||
|
||||
session_name('itop-'.md5(APPROOT));
|
||||
session_start();
|
||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||
$bAllowCache = true;
|
||||
if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE) &&( Session::Get('itop_env') !== $sSwitchEnv))
|
||||
if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE)) && isset($_SESSION['itop_env']) && ($_SESSION['itop_env'] !== $sSwitchEnv))
|
||||
{
|
||||
Session::Set('itop_env', $sSwitchEnv);
|
||||
$_SESSION['itop_env'] = $sSwitchEnv;
|
||||
$sEnv = $sSwitchEnv;
|
||||
$bAllowCache = false;
|
||||
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
|
||||
@@ -88,14 +81,20 @@ if (($sSwitchEnv != null) && file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FIL
|
||||
}
|
||||
// TODO: reset the credentials as well ??
|
||||
}
|
||||
else if (Session::IsSet('itop_env'))
|
||||
else if (isset($_SESSION['itop_env']))
|
||||
{
|
||||
$sEnv = Session::Get('itop_env');
|
||||
$sEnv = $_SESSION['itop_env'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sEnv = ITOP_DEFAULT_ENV;
|
||||
Session::Set('itop_env', ITOP_DEFAULT_ENV);
|
||||
$_SESSION['itop_env'] = ITOP_DEFAULT_ENV;
|
||||
}
|
||||
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||
try {
|
||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||
}
|
||||
catch (MySQLException $e) {
|
||||
IssueLog::Debug($e->getMessage());
|
||||
throw new MySQLException('Could not connect to the DB server', []);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
@@ -20,8 +20,6 @@
|
||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||
/**
|
||||
* This class manages the special template format used internally to build the iTop web pages
|
||||
*
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
class DisplayTemplate
|
||||
{
|
||||
@@ -31,15 +29,14 @@ class DisplayTemplate
|
||||
|
||||
public function __construct($sTemplate)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
$this->m_aTags = array(
|
||||
$this->m_aTags = array (
|
||||
'itopblock',
|
||||
'itopcheck',
|
||||
'itoptabs',
|
||||
'itoptab',
|
||||
'itoptoggle',
|
||||
'itopstring',
|
||||
'sqlblock',
|
||||
'sqlblock'
|
||||
);
|
||||
$this->m_sTemplate = $sTemplate;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class ThemeHandlerService : used to ease testing MFCompiler::CompileThemes class via mocks
|
||||
*
|
||||
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||
* @since 3.0.0 N°2982
|
||||
*/
|
||||
class ThemeHandlerService
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp = "", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null){
|
||||
return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp, $aThemeParameters, $aImportsPaths, $sWorkingPath);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -15,7 +15,6 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
|
||||
/**
|
||||
* This class records the pending "transactions" corresponding to forms that have not been
|
||||
@@ -24,7 +23,7 @@ use Combodo\iTop\Application\Helper\Session;
|
||||
* which choice is configured via the parameter 'transaction_storage'
|
||||
*
|
||||
* @package iTop
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
class privUITransaction
|
||||
@@ -102,8 +101,6 @@ class privUITransaction
|
||||
*
|
||||
* Warning, since 2.6.0 the session is regenerated on each login (see PR #20) !
|
||||
* Also, we saw some problems when using memcached as the PHP session implementation (see N°1835)
|
||||
*
|
||||
* @see \Combodo\iTop\Application\Helper\Session
|
||||
*/
|
||||
class privUITransactionSession
|
||||
{
|
||||
@@ -114,15 +111,15 @@ class privUITransactionSession
|
||||
*/
|
||||
public static function GetNewTransactionId()
|
||||
{
|
||||
if (!Session::IsSet('transactions'))
|
||||
if (!isset($_SESSION['transactions']))
|
||||
{
|
||||
Session::Set('transactions', []);
|
||||
$_SESSION['transactions'] = array();
|
||||
}
|
||||
// Strictly speaking, the two lines below should be grouped together
|
||||
// by a critical section
|
||||
// sem_acquire($rSemIdentified);
|
||||
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime());
|
||||
Session::Set(['transactions', $id], true);
|
||||
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
|
||||
$_SESSION['transactions'][$id] = true;
|
||||
// sem_release($rSemIdentified);
|
||||
|
||||
return (string)$id;
|
||||
@@ -139,17 +136,17 @@ class privUITransactionSession
|
||||
public static function IsTransactionValid($id, $bRemoveTransaction = true)
|
||||
{
|
||||
$bResult = false;
|
||||
if (Session::IsSet('transactions'))
|
||||
if (isset($_SESSION['transactions']))
|
||||
{
|
||||
// Strictly speaking, the eight lines below should be grouped together
|
||||
// inside the same critical section as above
|
||||
// sem_acquire($rSemIdentified);
|
||||
if (Session::IsSet(['transactions', $id]))
|
||||
if (isset($_SESSION['transactions'][$id]))
|
||||
{
|
||||
$bResult = true;
|
||||
if ($bRemoveTransaction)
|
||||
{
|
||||
Session::Unset(['transactions', $id]);
|
||||
unset($_SESSION['transactions'][$id]);
|
||||
}
|
||||
}
|
||||
// sem_release($rSemIdentified);
|
||||
@@ -164,14 +161,14 @@ class privUITransactionSession
|
||||
*/
|
||||
public static function RemoveTransaction($id)
|
||||
{
|
||||
if (Session::IsSet('transactions'))
|
||||
if (isset($_SESSION['transactions']))
|
||||
{
|
||||
// Strictly speaking, the three lines below should be grouped together
|
||||
// inside the same critical section as above
|
||||
// sem_acquire($rSemIdentified);
|
||||
if (Session::IsSet(['transactions', $id]))
|
||||
if (isset($_SESSION['transactions'][$id]))
|
||||
{
|
||||
Session::Unset(['transactions', $id]);
|
||||
unset($_SESSION['transactions'][$id]);
|
||||
}
|
||||
// sem_release($rSemIdentified);
|
||||
}
|
||||
|
||||
@@ -2,23 +2,14 @@
|
||||
|
||||
namespace Combodo\iTop;
|
||||
|
||||
use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Twig_Environment;
|
||||
use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Class TwigExtension
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop
|
||||
* @deprecated 3.1.0 N°4034
|
||||
*/
|
||||
class TwigExtension
|
||||
{
|
||||
/**
|
||||
@@ -56,10 +47,6 @@ class TwigExtension
|
||||
{
|
||||
return AttributeDateTime::GetFormat()->Format($sDate);
|
||||
}
|
||||
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate)))
|
||||
{
|
||||
return AttributeDate::GetFormat()->Format($sDate);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
@@ -92,14 +79,30 @@ class TwigExtension
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'itopversion', ITOP_VERSION);
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?itopversion=".ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&itopversion=".ITOP_VERSION;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
|
||||
// Filter to add a module's version to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'moduleversion', $sModuleVersion);
|
||||
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
@@ -111,22 +114,6 @@ class TwigExtension
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
}));
|
||||
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_config_parameter', function($sParamName)
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->Get($sParamName);
|
||||
}));
|
||||
|
||||
// Function to get a module setting
|
||||
// Usage in twig: {{ get_module_setting(<MODULE_CODE>, <PROPERTY_CODE> [, <DEFAULT_VALUE>]) }}
|
||||
// since 3.0.0, but see N°4034 for upcoming evolutions in the 3.1
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_module_setting', function (string $sModuleCode, string $sPropertyCode, $defaultValue = null) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->GetModuleSetting($sModuleCode, $sPropertyCode, $defaultValue);
|
||||
}));
|
||||
|
||||
// Function to get the URL of a static page in a module
|
||||
// Usage in twig: {{ get_static_page_module_url('itop-my-module', 'path-to-my-page') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_static_page_module_url', function($sModuleName, $sPage)
|
||||
@@ -141,5 +128,4 @@ class TwigExtension
|
||||
return utils::GetAbsoluteUrlModulePage($sModuleName, $sPage);
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user