mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-22 01:58:47 +02:00
Compare commits
726 Commits
2.7.9
...
3.0.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc24746862 | ||
|
|
d0baf298be | ||
|
|
fb70026966 | ||
|
|
ad19a89fc5 | ||
|
|
7b937016d0 | ||
|
|
e8f7c7dafe | ||
|
|
d9264e5181 | ||
|
|
f893603332 | ||
|
|
a49a56def8 | ||
|
|
2f138db4ac | ||
|
|
8d19958d6d | ||
|
|
11b6429e3c | ||
|
|
dccffc91b1 | ||
|
|
6c5e1c429f | ||
|
|
7d0f1f46d3 | ||
|
|
1e7d4e5c31 | ||
|
|
b12dadb0dc | ||
|
|
c6506c9f13 | ||
|
|
af11577450 | ||
|
|
91ab66453b | ||
|
|
b1102bc68c | ||
|
|
0443197c04 | ||
|
|
32e0c8f9bf | ||
|
|
26d912f059 | ||
|
|
3cb5f3d07e | ||
|
|
675a408ab9 | ||
|
|
2f938814e0 | ||
|
|
8042afa20f | ||
|
|
aef77d8f93 | ||
|
|
05c53d35b7 | ||
|
|
ea169e8358 | ||
|
|
28e80e5568 | ||
|
|
487e0ad5a7 | ||
|
|
106dfc63d5 | ||
|
|
5115db1b01 | ||
|
|
9621ff4d5e | ||
|
|
1c5cb4e125 | ||
|
|
dc6a900f6d | ||
|
|
0d23faba1c | ||
|
|
c861941e92 | ||
|
|
313df4551f | ||
|
|
07cc8bf508 | ||
|
|
c2e31de263 | ||
|
|
103b5bfd22 | ||
|
|
4c78ecab91 | ||
|
|
48bf954387 | ||
|
|
89c35f0345 | ||
|
|
434c829f7e | ||
|
|
4c8a8fc510 | ||
|
|
0a02c10287 | ||
|
|
d4516c214c | ||
|
|
931225ed5a | ||
|
|
18ed151e50 | ||
|
|
0046834b2c | ||
|
|
6835ebd11d | ||
|
|
62880b04eb | ||
|
|
6d82a85b12 | ||
|
|
64134ff428 | ||
|
|
c7661bcfcf | ||
|
|
291041610b | ||
|
|
a729c6c1e3 | ||
|
|
23452804aa | ||
|
|
1098182720 | ||
|
|
77ecd055b4 | ||
|
|
38fbc49e51 | ||
|
|
f9b905403d | ||
|
|
96130735c4 | ||
|
|
448afc640d | ||
|
|
f2ff5a4e83 | ||
|
|
b44e6a4a53 | ||
|
|
866a93c0c8 | ||
|
|
d7b1e60219 | ||
|
|
63d52787f0 | ||
|
|
bc809b0f3b | ||
|
|
f64cad75cd | ||
|
|
6237b5565c | ||
|
|
d76e4255f2 | ||
|
|
fa0bb2b466 | ||
|
|
8954d02796 | ||
|
|
87a2d30c78 | ||
|
|
f718b26b7b | ||
|
|
7cfd888516 | ||
|
|
cd10c41362 | ||
|
|
eb391d52fc | ||
|
|
1fc54edf21 | ||
|
|
cfbfaad154 | ||
|
|
b7543b54e8 | ||
|
|
10afd1cede | ||
|
|
b454958742 | ||
|
|
680f522065 | ||
|
|
50421f4753 | ||
|
|
7864461d85 | ||
|
|
be338e385b | ||
|
|
235b4be790 | ||
|
|
dfcc3b22a6 | ||
|
|
f3e47a15f6 | ||
|
|
a70ed7fcc2 | ||
|
|
c43d52277c | ||
|
|
8a1d17551b | ||
|
|
6e584cded4 | ||
|
|
6c7efb2448 | ||
|
|
3548d5e264 | ||
|
|
bd606ca3f9 | ||
|
|
6c5c71a0ee | ||
|
|
dfd9dd3352 | ||
|
|
6583c9495a | ||
|
|
93132dc3b4 | ||
|
|
f257dcfb85 | ||
|
|
776f32dbe1 | ||
|
|
8502fa7721 | ||
|
|
48b3716278 | ||
|
|
5f9cdc0431 | ||
|
|
6df74073a7 | ||
|
|
b59c40570b | ||
|
|
444f60c251 | ||
|
|
2425ccb8f2 | ||
|
|
4fd65a8a62 | ||
|
|
664d3251cc | ||
|
|
f31f991365 | ||
|
|
bb1a8a92dd | ||
|
|
27e1f3d64b | ||
|
|
95a2ffa0f2 | ||
|
|
b1e29cbd81 | ||
|
|
2e97b3b593 | ||
|
|
e419060e8a | ||
|
|
cfd9dba66e | ||
|
|
f72ddd72f3 | ||
|
|
d85d29155f | ||
|
|
91ee5ebfeb | ||
|
|
a6ea75f5fe | ||
|
|
dc789f51e9 | ||
|
|
116c0c0138 | ||
|
|
7fa7ebb59c | ||
|
|
0119f6c395 | ||
|
|
c8a30b0ccb | ||
|
|
8e31d77afb | ||
|
|
c7dce73116 | ||
|
|
71bb071f38 | ||
|
|
deda05351b | ||
|
|
5d1de543cc | ||
|
|
be9a428529 | ||
|
|
e7360661be | ||
|
|
6edb308480 | ||
|
|
43a4d9fcd2 | ||
|
|
9a47e3cf74 | ||
|
|
e7f01e7597 | ||
|
|
910358e04d | ||
|
|
4eebb538df | ||
|
|
d304284e36 | ||
|
|
6e6557e909 | ||
|
|
548342159b | ||
|
|
2221e0541c | ||
|
|
b15ed80732 | ||
|
|
986c08aa81 | ||
|
|
8e6351d346 | ||
|
|
9b19ae5944 | ||
|
|
e35965c065 | ||
|
|
5b2c279eac | ||
|
|
72fc22c49a | ||
|
|
b7b1ef1a1f | ||
|
|
64a96ac001 | ||
|
|
eb3ad0999a | ||
|
|
ecf678f39f | ||
|
|
5bc01d3950 | ||
|
|
2ae50dfb06 | ||
|
|
b25a6a2f04 | ||
|
|
1bd9d35979 | ||
|
|
1dd4d1479c | ||
|
|
00212e8127 | ||
|
|
061f3e9f51 | ||
|
|
e6111609b0 | ||
|
|
3556a95f3b | ||
|
|
82735254e7 | ||
|
|
44351784e6 | ||
|
|
f87002dce3 | ||
|
|
c616e9b65f | ||
|
|
03418663f2 | ||
|
|
5a072c75eb | ||
|
|
10a945eb92 | ||
|
|
6239c29422 | ||
|
|
bb53aef09f | ||
|
|
6cbc7fdb20 | ||
|
|
6a87ce48e1 | ||
|
|
7770cb31fb | ||
|
|
3adcee6da8 | ||
|
|
ff3ade7d62 | ||
|
|
ad59e81144 | ||
|
|
67ab33e727 | ||
|
|
e81e3a0f1c | ||
|
|
e89afa163e | ||
|
|
e48d257b00 | ||
|
|
51669d0479 | ||
|
|
f983655c68 | ||
|
|
157e0a6915 | ||
|
|
7d26b6092e | ||
|
|
f5e92359d9 | ||
|
|
8994f82e0f | ||
|
|
8551322cd7 | ||
|
|
be075dd695 | ||
|
|
0691fca412 | ||
|
|
3298966174 | ||
|
|
79514358db | ||
|
|
aa38be4578 | ||
|
|
e911290b3d | ||
|
|
dc24bbcd97 | ||
|
|
ea8a8e3afa | ||
|
|
6fb5d20971 | ||
|
|
b3522017e7 | ||
|
|
e5b22d270e | ||
|
|
b8af22baad | ||
|
|
5626da7a5e | ||
|
|
79ad75a2c2 | ||
|
|
41c833d0c6 | ||
|
|
29f58103b0 | ||
|
|
15a9856f89 | ||
|
|
b3bb77c8ee | ||
|
|
c2fe1bc5cb | ||
|
|
7f56911f41 | ||
|
|
83a547bbf4 | ||
|
|
8e16d537ff | ||
|
|
d9fe4599ff | ||
|
|
50bf0c9a27 | ||
|
|
261131d6d7 | ||
|
|
5276b48ed4 | ||
|
|
6fd56f750e | ||
|
|
57fda98981 | ||
|
|
ce001a8097 | ||
|
|
d49dd8b993 | ||
|
|
eeec5989d9 | ||
|
|
f25ef7f5ac | ||
|
|
5862ecde69 | ||
|
|
f8129fab74 | ||
|
|
ee9343cf40 | ||
|
|
1b2dd04409 | ||
|
|
40f3d6efbe | ||
|
|
5c07591519 | ||
|
|
f0f7653884 | ||
|
|
de54d28c6b | ||
|
|
292457595c | ||
|
|
a99f03e510 | ||
|
|
fd3f972948 | ||
|
|
12bf77d9ca | ||
|
|
c0337eaa23 | ||
|
|
b8d71b2bfb | ||
|
|
5ef6b6c5d0 | ||
|
|
078f81e853 | ||
|
|
11a79501da | ||
|
|
3dc7b66f6f | ||
|
|
2b0bdda1e0 | ||
|
|
794ee89d12 | ||
|
|
c37aabfc8c | ||
|
|
987ab4cbfb | ||
|
|
0aaa0a33bf | ||
|
|
3fd9aa01ed | ||
|
|
97380fd5f4 | ||
|
|
bcd41dfe96 | ||
|
|
54eb86a16b | ||
|
|
795b28263a | ||
|
|
8306ce36a0 | ||
|
|
6c46c7ff3a | ||
|
|
bfd4ba16d9 | ||
|
|
6969e4db1b | ||
|
|
661d84fc77 | ||
|
|
9eac12bd9c | ||
|
|
ecd5a7aadf | ||
|
|
7bf473d2a3 | ||
|
|
98d2e42bad | ||
|
|
9e9b192b3c | ||
|
|
98789f28bb | ||
|
|
33f11d2a43 | ||
|
|
40efaf0360 | ||
|
|
74160d2447 | ||
|
|
08eada82f4 | ||
|
|
9cd719ab56 | ||
|
|
e83dfe5982 | ||
|
|
077ac81208 | ||
|
|
36f8344ec9 | ||
|
|
745e4aa424 | ||
|
|
5405ae1d91 | ||
|
|
ed1bb3e93a | ||
|
|
0773660ef2 | ||
|
|
68b8490288 | ||
|
|
f100e9bd09 | ||
|
|
0ffe76e359 | ||
|
|
e3739641b4 | ||
|
|
410a637598 | ||
|
|
eded4814a1 | ||
|
|
b9f9322418 | ||
|
|
4badb90344 | ||
|
|
0542a8e4f8 | ||
|
|
f0434f9125 | ||
|
|
43cadb0ede | ||
|
|
11f00cc229 | ||
|
|
163c1ebc91 | ||
|
|
580e8ffa08 | ||
|
|
f5a3bb2baa | ||
|
|
63f8ec594c | ||
|
|
2df2392cc6 | ||
|
|
d2e5e96a63 | ||
|
|
8193ada159 | ||
|
|
46fe1661db | ||
|
|
2ff6658a56 | ||
|
|
f25cd70e73 | ||
|
|
b5cfd1c61e | ||
|
|
3c9c3204ac | ||
|
|
7ab274cb7b | ||
|
|
7d1a61a2f9 | ||
|
|
3c299654e3 | ||
|
|
1eba8ba4ac | ||
|
|
9daf23576d | ||
|
|
b9f23177e7 | ||
|
|
6542cf9d30 | ||
|
|
610e74e642 | ||
|
|
c3ecd51153 | ||
|
|
ff722b579b | ||
|
|
7e0fbd8c25 | ||
|
|
9f592223d9 | ||
|
|
99fc41a0f8 | ||
|
|
76fbd3790f | ||
|
|
d3b57c3bda | ||
|
|
a61ffaf3c0 | ||
|
|
cc6ab8a7b7 | ||
|
|
432a565221 | ||
|
|
7d8aaf91db | ||
|
|
eb99dc9f3f | ||
|
|
f59f2b2109 | ||
|
|
2840f6930b | ||
|
|
c50b6c806a | ||
|
|
84cd18bcb8 | ||
|
|
c2fcadd54d | ||
|
|
26ba45a8da | ||
|
|
4cc31bf941 | ||
|
|
0d878a52a2 | ||
|
|
d1af851fcd | ||
|
|
ec72d1c767 | ||
|
|
3add77308a | ||
|
|
d0ea3665be | ||
|
|
ae19737472 | ||
|
|
4c236b4422 | ||
|
|
c4b7be5b6f | ||
|
|
1afc6cd4c5 | ||
|
|
3b6a03d703 | ||
|
|
a4842f9e5c | ||
|
|
0bef32cf8d | ||
|
|
825c70c001 | ||
|
|
77cd764b1c | ||
|
|
2864d48fa7 | ||
|
|
b5c97e35bf | ||
|
|
9a0d9d2c38 | ||
|
|
8bdaec0129 | ||
|
|
3b0ca9d771 | ||
|
|
fa406c1f17 | ||
|
|
dd18430e70 | ||
|
|
7f3c10b69d | ||
|
|
0a5e4effc0 | ||
|
|
737e17066f | ||
|
|
8108dc8803 | ||
|
|
61ec7f8053 | ||
|
|
d5f44ffd7b | ||
|
|
d2bf4de84c | ||
|
|
5320f69c44 | ||
|
|
eb1322dc3e | ||
|
|
e8e259dde9 | ||
|
|
5df7c8bb07 | ||
|
|
bf142e5e07 | ||
|
|
8319d655b9 | ||
|
|
f5c8411a07 | ||
|
|
2ad4fd1707 | ||
|
|
761c2a46a3 | ||
|
|
c986927de9 | ||
|
|
e8eb6d0e31 | ||
|
|
077772ea9c | ||
|
|
3119af6c29 | ||
|
|
83ef7cff8a | ||
|
|
93eace9e5b | ||
|
|
2142ffedc3 | ||
|
|
23c0a67914 | ||
|
|
3b00911f62 | ||
|
|
b9b1e436ec | ||
|
|
87312d4457 | ||
|
|
9dcb4bbfe5 | ||
|
|
11f27019e4 | ||
|
|
dd81c76aaa | ||
|
|
4e5bbcde35 | ||
|
|
7d7270296e | ||
|
|
44e188fa2c | ||
|
|
e6bab46854 | ||
|
|
0a4ce0865e | ||
|
|
da1d3db204 | ||
|
|
880be200ae | ||
|
|
c5b8d3fa72 | ||
|
|
417008f549 | ||
|
|
8077e5aa62 | ||
|
|
2ce1c2efec | ||
|
|
c69e83f779 | ||
|
|
91006351d3 | ||
|
|
e43f55df03 | ||
|
|
0f741f28f3 | ||
|
|
4d2633a9ea | ||
|
|
c5d265f66b | ||
|
|
0311fe330b | ||
|
|
4648e436ac | ||
|
|
e39947f72c | ||
|
|
74db53d51d | ||
|
|
0b9ba4d053 | ||
|
|
700d11fa8f | ||
|
|
f64e081c1f | ||
|
|
54b6a29ba0 | ||
|
|
e0bf262343 | ||
|
|
3a276715d6 | ||
|
|
9516e7f023 | ||
|
|
223b063c60 | ||
|
|
fabc92eb89 | ||
|
|
71848cb56b | ||
|
|
d011c4e8f5 | ||
|
|
46909c210c | ||
|
|
71b725420a | ||
|
|
fcd4ad6872 | ||
|
|
e3f1deda00 | ||
|
|
a538e3c1a2 | ||
|
|
ac91c4d970 | ||
|
|
3ffe3dd4bd | ||
|
|
f70065b2fc | ||
|
|
4b98f2ac25 | ||
|
|
398621693e | ||
|
|
b9d7967c0e | ||
|
|
0c5c2eccad | ||
|
|
a1f5d8041e | ||
|
|
d679deba02 | ||
|
|
df20d10afa | ||
|
|
f2725c5a5c | ||
|
|
91c6916d86 | ||
|
|
f90a5b77ad | ||
|
|
703161157b | ||
|
|
55c896bcd3 | ||
|
|
ef844c396e | ||
|
|
dfdeb21023 | ||
|
|
47c0f946b3 | ||
|
|
f90105c107 | ||
|
|
b0973263e3 | ||
|
|
4be0d8895d | ||
|
|
6436e8cef4 | ||
|
|
f8b6b37288 | ||
|
|
8996117929 | ||
|
|
9be4743cf6 | ||
|
|
4195cd011c | ||
|
|
440cda87b1 | ||
|
|
efb3f7f9cd | ||
|
|
e5487edbfb | ||
|
|
3cae585f78 | ||
|
|
7b8c390a80 | ||
|
|
c3b9c6963e | ||
|
|
e907c7825a | ||
|
|
ea7924663a | ||
|
|
93871308d1 | ||
|
|
f20310b437 | ||
|
|
af87a04d13 | ||
|
|
521536526e | ||
|
|
1e3771dffa | ||
|
|
6666f3d033 | ||
|
|
470b566c1a | ||
|
|
c81f521d2e | ||
|
|
3ed73ac020 | ||
|
|
1604e233f9 | ||
|
|
46f8fadac0 | ||
|
|
001e937568 | ||
|
|
94ffcf4207 | ||
|
|
7b139ea893 | ||
|
|
76274557a3 | ||
|
|
1231528ab5 | ||
|
|
a5216de232 | ||
|
|
87b027e3bf | ||
|
|
b0609e86d1 | ||
|
|
b9145ca996 | ||
|
|
4e0c6e5614 | ||
|
|
da34383363 | ||
|
|
b628bb5e80 | ||
|
|
4c294cb09c | ||
|
|
dc5ee13ed1 | ||
|
|
8707ae6024 | ||
|
|
ec0f726c26 | ||
|
|
66d6db5174 | ||
|
|
2493fd57b2 | ||
|
|
e3a653010a | ||
|
|
c98c364714 | ||
|
|
a545bb8729 | ||
|
|
c9dab08324 | ||
|
|
18b653f641 | ||
|
|
56e2f63385 | ||
|
|
4f04031183 | ||
|
|
cdc3bbcb0c | ||
|
|
2db7611368 | ||
|
|
f4f846496b | ||
|
|
d6ab310d24 | ||
|
|
bc4b36fda6 | ||
|
|
c61a66ca69 | ||
|
|
bd0480b5c5 | ||
|
|
c93c53488d | ||
|
|
19b5290e80 | ||
|
|
a15235d522 | ||
|
|
c7e95676d2 | ||
|
|
4aeb3ed448 | ||
|
|
4e7b68aa9a | ||
|
|
e22c36c503 | ||
|
|
7264defc35 | ||
|
|
baa2fb2906 | ||
|
|
1d954b80a8 | ||
|
|
1d13181135 | ||
|
|
ed1f3aa950 | ||
|
|
e2e62eca5e | ||
|
|
a85c7e9f8f | ||
|
|
ac2280df50 | ||
|
|
61d611c136 | ||
|
|
f59de920c1 | ||
|
|
7b13078bf9 | ||
|
|
3406ebf1fd | ||
|
|
1f0211b45a | ||
|
|
b207ae1bb3 | ||
|
|
e788a44382 | ||
|
|
71dbccd034 | ||
|
|
3df3619b7c | ||
|
|
a969d352ec | ||
|
|
59b6dd735e | ||
|
|
1766d42350 | ||
|
|
3b6654588a | ||
|
|
b58a084de5 | ||
|
|
5d686d733f | ||
|
|
ea92973e9b | ||
|
|
14505fc5e6 | ||
|
|
90b60f90ae | ||
|
|
a26c2cbcdb | ||
|
|
cc708f6ccc | ||
|
|
d4694b271f | ||
|
|
d56f6e684a | ||
|
|
8999108fe3 | ||
|
|
929eccc88d | ||
|
|
75812ca151 | ||
|
|
ec238569c4 | ||
|
|
b6117b157c | ||
|
|
b3dcfea8dc | ||
|
|
00dc1d3f3b | ||
|
|
da5d55a542 | ||
|
|
6a3bbd8d49 | ||
|
|
46deb9590d | ||
|
|
20ed4fe2d1 | ||
|
|
87d7693be5 | ||
|
|
fa153d8504 | ||
|
|
5d3009646a | ||
|
|
ec70d3546d | ||
|
|
10a14a3844 | ||
|
|
0516862632 | ||
|
|
ad379d3ef4 | ||
|
|
8efd8008fc | ||
|
|
6f9565d979 | ||
|
|
6f3ec99501 | ||
|
|
ab681b0954 | ||
|
|
c9b80074f4 | ||
|
|
f5df442e8b | ||
|
|
fab58d503b | ||
|
|
1a3411e99d | ||
|
|
ddcd6d4e91 | ||
|
|
9eb826bb0b | ||
|
|
a88df33167 | ||
|
|
ec48b397ad | ||
|
|
f8af900c73 | ||
|
|
7d4455baf4 | ||
|
|
e37c620d2d | ||
|
|
dd4ef8f91a | ||
|
|
5edcc91182 | ||
|
|
e2b5992e80 | ||
|
|
a2af061a34 | ||
|
|
a53ce32e54 | ||
|
|
08414296b6 | ||
|
|
06ee1f3a15 | ||
|
|
27ed1f3307 | ||
|
|
4f72336301 | ||
|
|
868c157ae4 | ||
|
|
c2b72c7688 | ||
|
|
307713d326 | ||
|
|
2d8b888a18 | ||
|
|
6b2b56cf72 | ||
|
|
52baed7960 | ||
|
|
7ae895d701 | ||
|
|
120452d2ee | ||
|
|
25791a1d18 | ||
|
|
919a7a8ef5 | ||
|
|
da0e0a99c7 | ||
|
|
82ba53d40b | ||
|
|
7ed1feff3e | ||
|
|
6bdfdad09f | ||
|
|
8c3417adeb | ||
|
|
e4ab543aff | ||
|
|
11ef705816 | ||
|
|
b3b440362a | ||
|
|
ee9e747b1c | ||
|
|
1baf8a6424 | ||
|
|
7a89bfc108 | ||
|
|
68c7b9a0e8 | ||
|
|
9e3b1bfc78 | ||
|
|
01f9a6f758 | ||
|
|
8e028753b7 | ||
|
|
343d626025 | ||
|
|
6078f39730 | ||
|
|
78dc57bdb5 | ||
|
|
94a468efc8 | ||
|
|
864572c02a | ||
|
|
d353d56e7b | ||
|
|
a3e6600195 | ||
|
|
51ab8706e8 | ||
|
|
24f832de78 | ||
|
|
7e970ee93c | ||
|
|
e7fa9eda65 | ||
|
|
e295226bd6 | ||
|
|
78d23261ca | ||
|
|
edefa4da4f | ||
|
|
4ba76f95b2 | ||
|
|
6320879fe1 | ||
|
|
acf0548c4c | ||
|
|
b1fa429234 | ||
|
|
78516f437a | ||
|
|
ea75092bb3 | ||
|
|
df4dfe4803 | ||
|
|
fddf30e6c3 | ||
|
|
b718e26c7f | ||
|
|
e564f71c14 | ||
|
|
4f3931e828 | ||
|
|
d73fdce3c5 | ||
|
|
0787c622d4 | ||
|
|
4c11eb099b | ||
|
|
9628a1d028 | ||
|
|
5585385d08 | ||
|
|
98870b06e3 | ||
|
|
46d91322c1 | ||
|
|
ca28f8f3c4 | ||
|
|
0aaa55b35b | ||
|
|
e9a1167da6 | ||
|
|
a67fce66fc | ||
|
|
491d1d7d53 | ||
|
|
54b48dc908 | ||
|
|
dadeab58eb | ||
|
|
0ecdc6620b | ||
|
|
80161b909e | ||
|
|
888232e8c3 | ||
|
|
d904883bdd | ||
|
|
35d2c3afac | ||
|
|
7cee8c3cd0 | ||
|
|
27622bbcec | ||
|
|
219270ce81 | ||
|
|
16dd47a3b9 | ||
|
|
70835984de | ||
|
|
d9224f43f2 | ||
|
|
5b9643d6fb | ||
|
|
d3525190d5 | ||
|
|
f20808d929 | ||
|
|
aee80e41ca | ||
|
|
56ea6c8848 | ||
|
|
b7136c0b7a | ||
|
|
ea94986247 | ||
|
|
d8363067e6 | ||
|
|
6e4f9a9b93 | ||
|
|
29c4ca7e65 | ||
|
|
4d3aefe2a4 | ||
|
|
c798e0a9cd | ||
|
|
1b9c7b7766 | ||
|
|
19ee8e4071 | ||
|
|
b302569feb | ||
|
|
4741012fb9 | ||
|
|
f5886f603b | ||
|
|
d82086240b | ||
|
|
f47b16c571 | ||
|
|
728b082a7d | ||
|
|
31482ccef7 | ||
|
|
ca99e612cf | ||
|
|
c9c833a868 | ||
|
|
7cad4ac444 | ||
|
|
001680906d | ||
|
|
ed355cb8cf | ||
|
|
fa036ee724 | ||
|
|
e04548a61c | ||
|
|
25c55bdaf4 | ||
|
|
c1c43c7d5d | ||
|
|
b970d81272 | ||
|
|
b7ffa9e3c0 | ||
|
|
e94d5418f4 | ||
|
|
44008fc179 | ||
|
|
c2f62a13e6 | ||
|
|
d13591ca85 | ||
|
|
f88f321d79 | ||
|
|
c1b3cb1e7b | ||
|
|
d43c72b3ac | ||
|
|
1457faa53a | ||
|
|
3ee4b564f0 | ||
|
|
0988c8ccbf | ||
|
|
accda04a37 | ||
|
|
f364e7b043 | ||
|
|
42afe033ef | ||
|
|
5cfa06e36f | ||
|
|
8de4c0360d | ||
|
|
24130dd94f | ||
|
|
427326d074 | ||
|
|
59cc6d3f76 | ||
|
|
ee37373cfa | ||
|
|
56d9653f15 | ||
|
|
d5670abdcc | ||
|
|
0360a3160d | ||
|
|
bcd21aefb4 | ||
|
|
3cbcdd4f13 | ||
|
|
c46d0f5662 | ||
|
|
b2454d44ae | ||
|
|
79cfb95f6e | ||
|
|
ff2e1a3507 | ||
|
|
503afb9831 | ||
|
|
b6772917ae | ||
|
|
00971f9ec7 | ||
|
|
a3a97fa228 | ||
|
|
18c4ca9131 | ||
|
|
466ddf768e | ||
|
|
76d26e8ef9 | ||
|
|
b526d6422b | ||
|
|
63c02ff33d | ||
|
|
4688c92e7c | ||
|
|
75ba9101a6 | ||
|
|
df64c184b6 | ||
|
|
1ab09702d9 | ||
|
|
618326d01f | ||
|
|
9b8dace833 |
@@ -141,7 +141,7 @@ ij_javascript_chained_call_dot_on_new_line = true
|
|||||||
ij_javascript_class_brace_style = end_of_line
|
ij_javascript_class_brace_style = end_of_line
|
||||||
ij_javascript_comma_on_new_line = false
|
ij_javascript_comma_on_new_line = false
|
||||||
ij_javascript_do_while_brace_force = always
|
ij_javascript_do_while_brace_force = always
|
||||||
ij_javascript_else_on_new_line = true
|
ij_javascript_else_on_new_line = false
|
||||||
ij_javascript_enforce_trailing_comma = keep
|
ij_javascript_enforce_trailing_comma = keep
|
||||||
ij_javascript_extends_keyword_wrap = off
|
ij_javascript_extends_keyword_wrap = off
|
||||||
ij_javascript_extends_list_wrap = off
|
ij_javascript_extends_list_wrap = off
|
||||||
|
|||||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,4 +1,15 @@
|
|||||||
|
|
||||||
|
################################### 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
|
# no slash at the end to handle also symlinks
|
||||||
/toolkit
|
/toolkit
|
||||||
/env-*
|
/env-*
|
||||||
@@ -6,12 +17,6 @@
|
|||||||
# maintenance mode (N°2240)
|
# maintenance mode (N°2240)
|
||||||
/.maintenance
|
/.maintenance
|
||||||
|
|
||||||
# listing prevention in conf directory
|
|
||||||
/conf/**
|
|
||||||
!/conf/.htaccess
|
|
||||||
!/conf/index.php
|
|
||||||
!/conf/web.config
|
|
||||||
|
|
||||||
# composer reserver directory, from sources, populate/update using "composer install"
|
# composer reserver directory, from sources, populate/update using "composer install"
|
||||||
vendor/*
|
vendor/*
|
||||||
test/vendor/*
|
test/vendor/*
|
||||||
@@ -19,6 +24,7 @@ test/vendor/*
|
|||||||
# all conf but listing prevention
|
# all conf but listing prevention
|
||||||
/conf/**
|
/conf/**
|
||||||
!/conf/.htaccess
|
!/conf/.htaccess
|
||||||
|
!/conf/index.php
|
||||||
!/conf/web.config
|
!/conf/web.config
|
||||||
|
|
||||||
# all datas but listing prevention
|
# all datas but listing prevention
|
||||||
@@ -134,3 +140,5 @@ local.properties
|
|||||||
.cache-main
|
.cache-main
|
||||||
.scala_dependencies
|
.scala_dependencies
|
||||||
.worksheet
|
.worksheet
|
||||||
|
|
||||||
|
/css/setup.css
|
||||||
|
|||||||
@@ -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:
|
For example, if no version is currently prepared for shipping we could have:
|
||||||
|
|
||||||
- `develop` containing future 2.8.0 version
|
- `develop` containing future 3.0.0 version
|
||||||
- `support/2.7`: 2.7.x maintenance version
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
- `support/2.6`: 2.6.x maintenance version
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
- `support/2.5`: 2.5.x maintenance version
|
- `support/2.5`: 2.5.x maintenance version
|
||||||
|
|
||||||
In this example, when 2.8.0-beta is shipped that will become:
|
In this example, when 3.0.0-beta is shipped that will become:
|
||||||
|
|
||||||
- `develop`: future 2.9.0 version
|
- `develop`: future 3.1.0 version
|
||||||
- `release/2.8`: 2.8.0-beta
|
- `release/3.0.0`: 3.0.0-beta
|
||||||
- `support/2.7`: 2.7.x maintenance version
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
- `support/2.6`: 2.6.x maintenance version
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
- `support/2.5`: 2.5.x maintenance version
|
- `support/2.5`: 2.5.x maintenance version
|
||||||
|
|
||||||
And when 2.8.0 final will be out:
|
And when 3.0.0 final will be out:
|
||||||
|
|
||||||
- `develop`: future 2.9.0 version
|
- `develop`: future 3.1.0 version
|
||||||
- `support/2.8`: 2.8.x maintenance version (will host developments for 2.8.1)
|
- `support/2.8`: 2.8.x maintenance version (will host developments for 3.0.1)
|
||||||
- `support/2.7`: 2.7.x maintenance version
|
- `support/2.7`: 2.7.x maintenance version
|
||||||
- `support/2.6`: 2.6.x maintenance version
|
- `support/2.6`: 2.6.x maintenance version
|
||||||
- `support/2.5`: 2.5.x maintenance version
|
- `support/2.5`: 2.5.x maintenance version
|
||||||
|
|||||||
70
README.md
70
README.md
@@ -21,21 +21,35 @@ iTop also offers mass import tools and web services to integrate with your IT
|
|||||||
- [Data synchronization][18] (for data federation)
|
- [Data synchronization][18] (for data federation)
|
||||||
|
|
||||||
|
|
||||||
|
## Latest release
|
||||||
|
|
||||||
|
- [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
|
||||||
|
[64]: https://www.itophub.io/wiki/page?id=latest:install:start
|
||||||
|
[65]: https://sourceforge.net/projects/itop/files/latest/download
|
||||||
|
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- [iTop Forums][1]: community support
|
- [iTop Forums][1]: community support
|
||||||
- [iTop Tickets][2]: for feature requests and bug reports
|
- [iTop Tickets][2]: for feature requests and bug reports
|
||||||
- [Releases download][3]
|
- [Releases download][3]
|
||||||
- [Documentation][4] covering both iTop and its official extensions
|
- [Software requirements][4]
|
||||||
- [iTop Hub][5] : discover and install extensions !
|
- [Documentation][5] covering both iTop and its official extensions
|
||||||
|
- [iTop Hub][6] : discover and install extensions !
|
||||||
|
|
||||||
|
|
||||||
[1]: https://sourceforge.net/p/itop/discussion/
|
[1]: https://sourceforge.net/p/itop/discussion/
|
||||||
[2]: https://sourceforge.net/p/itop/tickets/
|
[2]: https://sourceforge.net/p/itop/tickets/
|
||||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||||
[4]: https://www.itophub.io/wiki
|
[4]: https://www.itophub.io/wiki/page?id=latest:install:upgrading_itop
|
||||||
[5]: https://store.itophub.io/en_US/
|
[5]: https://www.itophub.io/wiki
|
||||||
|
[6]: https://store.itophub.io/en_US/
|
||||||
|
|
||||||
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
[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
|
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
||||||
@@ -49,47 +63,6 @@ iTop also offers mass import tools and web services to integrate with your IT
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Last releases
|
|
||||||
|
|
||||||
### Versions 2.7.*
|
|
||||||
- 2.7.1 published on April 8, 2020
|
|
||||||
- [Changes since the previous version][62]
|
|
||||||
- [New features][63]
|
|
||||||
- [Migration notes][64]
|
|
||||||
- [Download iTop 2.7.0-2][65]
|
|
||||||
|
|
||||||
[62]: https://www.itophub.io/wiki/page?id=2_7_0:release:change_log
|
|
||||||
[63]: https://www.itophub.io/wiki/page?id=2_7_0:release:2_7_whats_new
|
|
||||||
[64]: https://www.itophub.io/wiki/page?id=2_7_0:install:260_to_270_migration_notes
|
|
||||||
[65]: https://sourceforge.net/projects/itop/files/itop/2.7.0-2
|
|
||||||
|
|
||||||
|
|
||||||
### Versions 2.6.*
|
|
||||||
- 2.6.0 published on January 9, 2019
|
|
||||||
- [Changes since the previous version][58]
|
|
||||||
- [New features][59]
|
|
||||||
- [Migration notes][60]
|
|
||||||
- [Download iTop 2.6.3][61]
|
|
||||||
|
|
||||||
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
|
|
||||||
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
|
|
||||||
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
|
|
||||||
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.3
|
|
||||||
|
|
||||||
|
|
||||||
### Versions 2.5.*
|
|
||||||
- 2.5.0 published on July 11, 2018
|
|
||||||
- [Changes since the previous version][54]
|
|
||||||
- [New features][55]
|
|
||||||
- [Migration notes][56]
|
|
||||||
- [Download iTop 2.5.1][57]
|
|
||||||
|
|
||||||
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
|
|
||||||
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
|
|
||||||
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
|
|
||||||
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
|
|
||||||
|
|
||||||
|
|
||||||
## About Us
|
## About Us
|
||||||
|
|
||||||
iTop development is sponsored, led and supported by [Combodo][0].
|
iTop development is sponsored, led and supported by [Combodo][0].
|
||||||
@@ -105,10 +78,10 @@ We would like to give a special thank you to the people from the community who c
|
|||||||
- Alves, David
|
- Alves, David
|
||||||
- Beck, Pedro
|
- Beck, Pedro
|
||||||
- Bilger, Jean-François
|
- Bilger, Jean-François
|
||||||
- Bostoen, Jeffrey
|
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
||||||
- Cardoso, Anderson
|
- Cardoso, Anderson
|
||||||
- Cassaro, Bruno
|
- Cassaro, Bruno
|
||||||
- Casteleyn, Thomas
|
- Casteleyn, Thomas (a.k.a @Hipska)
|
||||||
- Castro, Randall Badilla
|
- Castro, Randall Badilla
|
||||||
- Colantoni, Maria Laura
|
- Colantoni, Maria Laura
|
||||||
- Couronné, Guy
|
- Couronné, Guy
|
||||||
@@ -124,6 +97,7 @@ We would like to give a special thank you to the people from the community who c
|
|||||||
- Lazcano, Federico
|
- Lazcano, Federico
|
||||||
- Lucas, Jonathan
|
- Lucas, Jonathan
|
||||||
- Malik, Remie
|
- Malik, Remie
|
||||||
|
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||||
- Rosenke, Stephan
|
- Rosenke, Stephan
|
||||||
- Seki, Shoji
|
- Seki, Shoji
|
||||||
- Shilov, Vladimir
|
- Shilov, Vladimir
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ responsible disclosure and will make every effort to acknowledge your contributi
|
|||||||
### iTop vulnerabilities
|
### iTop vulnerabilities
|
||||||
Please send a procedure to reproduce iTop vulnerabilities to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
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 / then / when" report, including iTop version, impacts, and maybe installed modules or data if they are
|
You can send us a standard "given / when / then" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||||
needed to reproduce.
|
needed to reproduce.
|
||||||
|
|
||||||
### Dependencies vulnerabilities
|
### Dependencies vulnerabilities
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_profiles",
|
"db_table" => "priv_urp_profiles",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -170,11 +169,9 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||||
{
|
{
|
||||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||||
if (!$bEditMode)
|
|
||||||
{
|
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
$this->DoShowGrantSumary($oPage);
|
||||||
$this->DoShowGrantSumary($oPage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetReadOnlyAttributes()
|
public static function GetReadOnlyAttributes()
|
||||||
@@ -243,7 +240,6 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -349,7 +345,6 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_userorg",
|
"db_table" => "priv_urp_userorg",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_profiles",
|
"db_table" => "priv_urp_profiles",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -312,11 +311,9 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
|||||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||||
{
|
{
|
||||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||||
if (!$bEditMode)
|
|
||||||
{
|
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
$this->DoShowGrantSumary($oPage);
|
||||||
$this->DoShowGrantSumary($oPage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +333,6 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -376,7 +372,6 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
"db_table" => "priv_urp_userorg",
|
"db_table" => "priv_urp_userorg",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -417,7 +412,6 @@ class URP_ActionGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_actions",
|
"db_table" => "priv_urp_grant_actions",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -454,7 +448,6 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_stimulus",
|
"db_table" => "priv_urp_grant_stimulus",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -491,7 +484,6 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_attributes",
|
"db_table" => "priv_urp_grant_attributes",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ class URP_Profiles extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_profiles",
|
"db_table" => "priv_urp_profiles",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -144,11 +143,9 @@ class URP_Profiles extends UserRightsBaseClass
|
|||||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||||
{
|
{
|
||||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||||
if (!$bEditMode)
|
|
||||||
{
|
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
$this->DoShowGrantSumary($oPage);
|
||||||
$this->DoShowGrantSumary($oPage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +164,6 @@ class URP_Dimensions extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_dimensions",
|
"db_table" => "priv_urp_dimensions",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -280,7 +276,6 @@ class URP_UserProfile extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -321,7 +316,6 @@ class URP_ProfileProjection extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_profileprojection",
|
"db_table" => "priv_urp_profileprojection",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -402,7 +396,6 @@ class URP_ClassProjection extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_classprojection",
|
"db_table" => "priv_urp_classprojection",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -474,7 +467,6 @@ class URP_ActionGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_actions",
|
"db_table" => "priv_urp_grant_actions",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -511,7 +503,6 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_stimulus",
|
"db_table" => "priv_urp_grant_stimulus",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -548,7 +539,6 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
|||||||
"db_table" => "priv_urp_grant_attributes",
|
"db_table" => "priv_urp_grant_attributes",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -30,8 +30,11 @@ function mb_str_replace($search, $replace, $subject, &$count = 0) {
|
|||||||
$replacements = array_pad($replacements, count($searches), '');
|
$replacements = array_pad($replacements, count($searches), '');
|
||||||
foreach ($searches as $key => $search) {
|
foreach ($searches as $key => $search) {
|
||||||
$parts = mb_split(preg_quote($search), $subject);
|
$parts = mb_split(preg_quote($search), $subject);
|
||||||
$count += count($parts) - 1;
|
if (is_array($parts))
|
||||||
$subject = implode($replacements[$key], $parts);
|
{
|
||||||
|
$count += count($parts) - 1;
|
||||||
|
$subject = implode($replacements[$key], $parts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Call mb_str_replace for each subject in array, recursively
|
// Call mb_str_replace for each subject in array, recursively
|
||||||
|
|||||||
@@ -1,417 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
/**
|
||||||
|
* Class ajax_page
|
||||||
class ajax_page extends WebPage implements iTabbedPage
|
* @deprecated will be removed in 3.1.0 - moved to AjaxPage
|
||||||
|
*/
|
||||||
|
class ajax_page extends AjaxPage
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* 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->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
|
||||||
$this->add_header('Pragma: no-cache');
|
|
||||||
$this->add_header('Expires: 0');
|
|
||||||
$this->add_header('X-Frame-Options: deny');
|
|
||||||
$this->m_oTabs = new TabManager();
|
|
||||||
$this->sContentType = 'text/html';
|
|
||||||
$this->sContentDisposition = 'inline';
|
|
||||||
$this->m_sMenu = "";
|
|
||||||
|
|
||||||
utils::InitArchiveMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,3 @@ require_once(APPROOT.'/application/utils.inc.php');
|
|||||||
class ApplicationException extends CoreException
|
class ApplicationException extends CoreException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
@@ -24,19 +24,23 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Component\Input\InputFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||||
|
use Combodo\iTop\Application\UI\UIBlock;
|
||||||
|
|
||||||
require_once(APPROOT."/application/utils.inc.php");
|
require_once(APPROOT."/application/utils.inc.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for directing end-users to the relevant application
|
* Interface for directing end-users to the relevant application
|
||||||
*/
|
*/
|
||||||
interface iDBObjectURLMaker
|
interface iDBObjectURLMaker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $iId
|
* @param string $iId
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function MakeObjectURL($sClass, $iId);
|
public static function MakeObjectURL($sClass, $iId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,23 +204,46 @@ class ApplicationContext
|
|||||||
}
|
}
|
||||||
return implode("&", $aParams);
|
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
|
* Returns the context as sequence of input tags to be inserted inside a <form> tag
|
||||||
|
*
|
||||||
* @return string The context as a sequence of <input type="hidden" /> tags
|
* @return string The context as a sequence of <input type="hidden" /> tags
|
||||||
*/
|
*/
|
||||||
public function GetForForm()
|
public function GetForForm()
|
||||||
{
|
{
|
||||||
$sContext = "";
|
$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";
|
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||||
}
|
}
|
||||||
return $sContext;
|
return $sContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(InputFactory::MakeForHidden('c[$sName]', utils::HtmlEntities($sValue)));
|
||||||
|
}
|
||||||
|
return $oContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the context as a hash array 'parameter_name' => value
|
* Returns the context as a hash array 'parameter_name' => value
|
||||||
|
*
|
||||||
* @return array The context information
|
* @return array The context information
|
||||||
*/
|
*/
|
||||||
public function GetAsHash()
|
public function GetAsHash()
|
||||||
|
|||||||
@@ -869,7 +869,7 @@ abstract class ApplicationPopupMenuItem
|
|||||||
class URLPopupMenuItem extends ApplicationPopupMenuItem
|
class URLPopupMenuItem extends ApplicationPopupMenuItem
|
||||||
{
|
{
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
protected $sURL;
|
protected $sUrl;
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
protected $sTarget;
|
protected $sTarget;
|
||||||
|
|
||||||
@@ -878,20 +878,32 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
*
|
*
|
||||||
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
|
||||||
* @param string $sLabel The display label of the menu (must be localized)
|
* @param string $sLabel The display label of the menu (must be localized)
|
||||||
* @param string $sURL If the menu is an hyperlink, provide the absolute hyperlink here
|
* @param string $sUrl If the menu is an hyperlink, provide the absolute hyperlink here
|
||||||
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
|
* @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here
|
||||||
*/
|
*/
|
||||||
public function __construct($sUID, $sLabel, $sURL, $sTarget = '_top')
|
public function __construct($sUID, $sLabel, $sUrl, $sTarget = '_top')
|
||||||
{
|
{
|
||||||
parent::__construct($sUID, $sLabel);
|
parent::__construct($sUID, $sLabel);
|
||||||
$this->sURL = $sURL;
|
$this->sUrl = $sUrl;
|
||||||
$this->sTarget = $sTarget;
|
$this->sTarget = $sTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
public function GetMenuItem()
|
public function GetMenuItem()
|
||||||
{
|
{
|
||||||
return array('label' => $this->GetLabel(), 'url' => $this->sURL, 'target' => $this->sTarget, 'css_classes' => $this->aCssClasses);
|
return array('label' => $this->GetLabel(), 'url' => $this->GetUrl(), 'target' => $this-> GetTarget(), 'css_classes' => $this->aCssClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @ignore */
|
||||||
|
public function GetUrl()
|
||||||
|
{
|
||||||
|
return $this->sUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @ignore */
|
||||||
|
public function GetTarget()
|
||||||
|
{
|
||||||
|
return $this->sTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,7 +917,9 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
class JSPopupMenuItem extends ApplicationPopupMenuItem
|
class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||||
{
|
{
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
protected $sJSCode;
|
protected $sJsCode;
|
||||||
|
/** @ignore */
|
||||||
|
protected $sUrl;
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
protected $aIncludeJSFiles;
|
protected $aIncludeJSFiles;
|
||||||
|
|
||||||
@@ -923,7 +937,8 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = array())
|
public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = array())
|
||||||
{
|
{
|
||||||
parent::__construct($sUID, $sLabel);
|
parent::__construct($sUID, $sLabel);
|
||||||
$this->sJSCode = $sJSCode;
|
$this->sJsCode = $sJSCode;
|
||||||
|
$this->sUrl = '#';
|
||||||
$this->aIncludeJSFiles = $aIncludeJSFiles;
|
$this->aIncludeJSFiles = $aIncludeJSFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,9 +948,9 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
// Note: the semicolumn is a must here!
|
// Note: the semicolumn is a must here!
|
||||||
return array(
|
return array(
|
||||||
'label' => $this->GetLabel(),
|
'label' => $this->GetLabel(),
|
||||||
'onclick' => $this->sJSCode.'; return false;',
|
'onclick' => $this->GetJsCode().'; return false;',
|
||||||
'url' => '#',
|
'url' => $this->GetUrl(),
|
||||||
'css_classes' => $this->aCssClasses,
|
'css_classes' => $this->GetCssClasses(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,6 +959,18 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
{
|
{
|
||||||
return $this->aIncludeJSFiles;
|
return $this->aIncludeJSFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @ignore */
|
||||||
|
public function GetJsCode()
|
||||||
|
{
|
||||||
|
return $this->sJsCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @ignore */
|
||||||
|
public function GetUrl()
|
||||||
|
{
|
||||||
|
return $this->sUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1019,7 +1046,7 @@ class JSButtonItem extends JSPopupMenuItem
|
|||||||
interface iPageUIExtension
|
interface iPageUIExtension
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Add content to the North pane
|
* Add content to the header of the page
|
||||||
*
|
*
|
||||||
* @param iTopWebPage $oPage The page to insert stuff into.
|
* @param iTopWebPage $oPage The page to insert stuff into.
|
||||||
*
|
*
|
||||||
@@ -1028,7 +1055,7 @@ interface iPageUIExtension
|
|||||||
public function GetNorthPaneHtml(iTopWebPage $oPage);
|
public function GetNorthPaneHtml(iTopWebPage $oPage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add content to the South pane
|
* Add content to the footer of the page
|
||||||
*
|
*
|
||||||
* @param iTopWebPage $oPage The page to insert stuff into.
|
* @param iTopWebPage $oPage The page to insert stuff into.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ class AuditRule extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_auditrule",
|
"db_table" => "priv_auditrule",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|||||||
@@ -1,84 +1,7 @@
|
|||||||
<?php
|
<?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/>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter class: when an API requires WebPage and you want to produce something else
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2016 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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,97 +1,7 @@
|
|||||||
<?php
|
<?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/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CLI page
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php
|
||||||
* 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
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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,113 +1,7 @@
|
|||||||
<?php
|
<?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/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple web page with no includes or fancy formatting, useful to generateXML documents
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php
|
||||||
* 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
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
|
||||||
$this->add_header('Pragma: no-cache');
|
|
||||||
$this->add_header('Expires: 0');
|
|
||||||
$this->add_header('X-Frame-Options: deny');
|
|
||||||
//$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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Component\Toolbar\Toolbar;
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
||||||
|
|
||||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||||
require_once(APPROOT.'application/dashlet.class.inc.php');
|
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||||
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
||||||
@@ -491,7 +496,7 @@ abstract class Dashboard
|
|||||||
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
|
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
|
||||||
} );
|
} );
|
||||||
|
|
||||||
$('#select_layout').buttonset();
|
$('#select_layout').controlgroup();
|
||||||
$('#select_dashlet').droppable({
|
$('#select_dashlet').droppable({
|
||||||
accept: '.dashlet',
|
accept: '.dashlet',
|
||||||
drop: function(event, ui) {
|
drop: function(event, ui) {
|
||||||
@@ -529,28 +534,37 @@ EOF
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
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');
|
$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>');
|
$sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
|
||||||
|
|
||||||
|
$sHtml = "<div class=\"ibo-top-bar--toolbar-dashboard-title\">{$sTitleForHTML}</div>";
|
||||||
|
if ($oPage instanceof iTopWebPage) {
|
||||||
|
$oTopBar = $oPage->GetTopBarLayout();
|
||||||
|
$oToolbar = new Toolbar();
|
||||||
|
$oTopBar->SetToolbar($oToolbar);
|
||||||
|
$oToolbar->AddHtml($sHtml);
|
||||||
|
} else {
|
||||||
|
$oPage->add_script(<<<JS
|
||||||
|
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML");
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** @var \DashboardLayoutMultiCol $oLayout */
|
/** @var \DashboardLayoutMultiCol $oLayout */
|
||||||
$oLayout = new $this->sLayoutClass();
|
$oLayout = new $this->sLayoutClass();
|
||||||
|
|
||||||
foreach($this->aCells as $iCellIdx => $aDashlets)
|
foreach ($this->aCells as $iCellIdx => $aDashlets) {
|
||||||
{
|
foreach ($aDashlets as $oDashlet) {
|
||||||
foreach($aDashlets as $oDashlet)
|
|
||||||
{
|
|
||||||
$aDashletCoordinates = $oLayout->GetDashletCoordinates($iCellIdx);
|
$aDashletCoordinates = $oLayout->GetDashletCoordinates($iCellIdx);
|
||||||
$this->PrepareDashletForRendering($oDashlet, $aDashletCoordinates, $aExtraParams);
|
$this->PrepareDashletForRendering($oDashlet, $aDashletCoordinates, $aExtraParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||||
if (!$bEditMode)
|
if (!$bEditMode) {
|
||||||
{
|
|
||||||
$oPage->add_linked_script('../js/dashlet.js');
|
$oPage->add_linked_script('../js/dashlet.js');
|
||||||
$oPage->add_linked_script('../js/dashboard.js');
|
$oPage->add_linked_script('../js/dashboard.js');
|
||||||
}
|
}
|
||||||
@@ -928,6 +942,9 @@ class RuntimeDashboard extends Dashboard
|
|||||||
$sExtraParams = json_encode($aAjaxParams);
|
$sExtraParams = json_encode($aAjaxParams);
|
||||||
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
|
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
|
||||||
$sReloadURL = $this->GetReloadURL();
|
$sReloadURL = $this->GetReloadURL();
|
||||||
|
$oAppContext = new ApplicationContext();
|
||||||
|
$sContext=$oAppContext->GetForPostParams();
|
||||||
|
//$sContext is named "c" because it use the existing code for context parameters c[org_id] and c[menu]
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
||||||
@@ -941,14 +958,14 @@ class RuntimeDashboard extends Dashboard
|
|||||||
function ReloadDashboard$sDivId()
|
function ReloadDashboard$sDivId()
|
||||||
{
|
{
|
||||||
// Do not reload when a dialog box is active
|
// Do not reload when a dialog box is active
|
||||||
if (!($('.ui-dialog:visible').length > 0) && $('.dashboard_contents#$sDivId').is(':visible'))
|
if (!($('.ui-dialog:visible').length > 0) && $('.ibo-dashboard#$sDivId').is(':visible'))
|
||||||
{
|
{
|
||||||
$('.dashboard_contents#$sDivId').block();
|
$('.ibo-dashboard#$sDivId').block();
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||||
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL'},
|
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, c: $sContext, reload_url: '$sReloadURL'},
|
||||||
function(data){
|
function(data){
|
||||||
$('.dashboard_contents#$sDivId').html(data);
|
$('.ibo-dashboard#$sDivId').html(data);
|
||||||
$('.dashboard_contents#$sDivId').unblock();
|
$('.ibo-dashboard#$sDivId').unblock();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -978,52 +995,58 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \iTopWebPage $oPage
|
* @param WebPage $oPage
|
||||||
* @param array $aAjaxParams
|
* @param array $aAjaxParams
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
protected function RenderSelector($oPage, $aAjaxParams = array())
|
protected function RenderSelector(WebPage $oPage, $aAjaxParams = array())
|
||||||
{
|
{
|
||||||
$sId = $this->GetId();
|
$sId = $this->GetId();
|
||||||
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
||||||
$sExtraParams = json_encode($aAjaxParams);
|
$sExtraParams = json_encode($aAjaxParams);
|
||||||
|
|
||||||
$sSelectorHtml = '<div class="dashboard-selector">';
|
$sSelectorHtml = '<div class="ibo-top-bar--toolbar-dashboard-selector">';
|
||||||
if ($this->HasCustomDashboard())
|
if ($this->HasCustomDashboard()) {
|
||||||
{
|
|
||||||
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
||||||
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
|
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
|
||||||
$sSelectorHtml .= '<div class="selector-label">'.$sStandard.'</div>';
|
$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>';
|
$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');
|
$sCustom = Dict::S('UI:Toggle:CustomDashboard');
|
||||||
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
|
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
|
||||||
|
|
||||||
}
|
}
|
||||||
$sSelectorHtml .= '</div>';
|
$sSelectorHtml .= '</div>';
|
||||||
$sSelectorHtml = addslashes($sSelectorHtml);
|
|
||||||
$sFile = addslashes($this->GetDefinitionFile());
|
$sFile = addslashes($this->GetDefinitionFile());
|
||||||
$sReloadURL = $this->GetReloadURL();
|
$sReloadURL = $this->GetReloadURL();
|
||||||
|
|
||||||
$oPage->add_ready_script(
|
if ($oPage instanceof iTopWebPage) {
|
||||||
<<<EOF
|
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||||
$('.dashboard-title').after('$sSelectorHtml');
|
$oToolbar->AddHtml($sSelectorHtml);
|
||||||
EOF
|
|
||||||
);
|
|
||||||
|
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
function ToggleDashboardSelector$sDivId()
|
function ToggleDashboardSelector$sDivId()
|
||||||
{
|
{
|
||||||
$('.dashboard_contents#$sDivId').block();
|
$('.ibo-dashboard#$sDivId').block();
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||||
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
|
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
|
||||||
function(data) {
|
function(data) {
|
||||||
$('.dashboard_contents#$sDivId').html(data);
|
$('.ibo-dashboard#$sDivId').html(data);
|
||||||
$('.dashboard_contents#$sDivId').unblock();
|
$('.ibo-dashboard#$sDivId').unblock();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$sSelectorHtml = addslashes($sSelectorHtml);
|
||||||
|
$oPage->add_script(<<<JS
|
||||||
|
$(".ibo-top-bar--toolbar-dashboard-selector").replaceWith("$sSelectorHtml");
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1055,43 +1078,67 @@ EOF
|
|||||||
*/
|
*/
|
||||||
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
|
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
|
if (!($oPage instanceof iTopWebPage)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
||||||
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><i class=\"top-right-icon icon-additional-arrow fas fa-pencil-alt\"></i><ul>";
|
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||||
|
|
||||||
|
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
||||||
|
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
||||||
|
$sName = 'UI:Dashboard:Actions';
|
||||||
|
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||||
|
$oActionButton = ButtonFactory::MakeLinkNeutral('', '', 'fas fa-ellipsis-v', $sName, '', $sMenuTogglerId);
|
||||||
|
$oActionButton->AddCSSClasses("ibo-top-bar--toolbar-dashboard-menu-toggler");
|
||||||
|
|
||||||
|
$oToolbar->AddSubBlock($oActionButton);
|
||||||
|
|
||||||
$aActions = array();
|
$aActions = array();
|
||||||
$sFile = addslashes($this->sDefinitionFile);
|
$sFile = addslashes($this->sDefinitionFile);
|
||||||
$sJSExtraParams = json_encode($aExtraParams);
|
$sJSExtraParams = json_encode($aExtraParams);
|
||||||
$bCanEdit = true;
|
$bCanEdit = true;
|
||||||
if ($this->HasCustomDashboard())
|
if ($this->HasCustomDashboard()) {
|
||||||
{
|
|
||||||
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
|
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
|
||||||
}
|
}
|
||||||
if ($bCanEdit)
|
if ($bCanEdit) {
|
||||||
{
|
|
||||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||||
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->bCustomized)
|
if ($this->bCustomized) {
|
||||||
{
|
|
||||||
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
|
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
|
||||||
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
||||||
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
||||||
$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
|
|
||||||
$sEditMenu = addslashes($sEditMenu);
|
$oToolbar->AddSubBlock($oPage->GetPopoverMenu($sPopoverMenuId, $aActions));
|
||||||
$sReloadURL = $this->GetReloadURL();
|
$oActionButton->AddCSSClasses('ibo-action-button')
|
||||||
$oPage->add_ready_script(
|
->SetJsCode(<<<JS
|
||||||
<<<EOF
|
$("#{$sPopoverMenuId}").popover_menu({toggler: "#{$sMenuTogglerId}"});
|
||||||
$('.dashboard-title').after('$sEditMenu');
|
$('#{$sMenuTogglerId}').on('click', function(oEvent) {
|
||||||
$('#DashboardMenu>ul').popupmenu();
|
var oEventTarget = $('#{$sMenuTogglerId}');
|
||||||
|
var aEventTargetPos = oEventTarget.position();
|
||||||
|
var popover = $("#{$sPopoverMenuId}");
|
||||||
|
|
||||||
EOF
|
popover.css({
|
||||||
);
|
// 'top': (aEventTargetPos.top + parseInt(oEventTarget.css('marginTop'), 10) + oEventTarget.height()) + 'px',
|
||||||
|
// 'left': (aEventTargetPos.left + parseInt(oEventTarget.css('marginLeft'), 10) + oEventTarget.width() - popover.width()) + 'px',
|
||||||
|
'top': (aEventTargetPos.top + oEventTarget.outerHeight(true)) + 'px',
|
||||||
|
'left': (aEventTargetPos.left + oEventTarget.outerWidth(true) - popover.width()) + 'px',
|
||||||
|
'z-index': 10060
|
||||||
|
});
|
||||||
|
popover.popover_menu("togglePopup");
|
||||||
|
});
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
|
||||||
|
$sReloadURL = $this->GetReloadURL();
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
function EditDashboard(sId, sDashboardFile, aExtraParams)
|
function EditDashboard(sId, sDashboardFile, aExtraParams)
|
||||||
{
|
{
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile, extra_params: aExtraParams, reload_url: '$sReloadURL'},
|
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile, extra_params: aExtraParams, reload_url: '$sReloadURL'},
|
||||||
@@ -1575,12 +1622,10 @@ JS
|
|||||||
{
|
{
|
||||||
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
|
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
|
||||||
$aClassAliases = array();
|
$aClassAliases = array();
|
||||||
try{
|
try {
|
||||||
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
|
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
|
||||||
$aClassAliases = $oFilter->GetSelectedClasses();
|
$aClassAliases = $oFilter->GetSelectedClasses();
|
||||||
}
|
} catch (Exception $e) {
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
//on error, return default value
|
//on error, return default value
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,17 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||||
|
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardColumn;
|
||||||
|
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardLayout as UIDashboardLayout;
|
||||||
|
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardRow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard presentation
|
* Dashboard presentation
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
abstract class DashboardLayout
|
abstract class DashboardLayout
|
||||||
{
|
{
|
||||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||||
@@ -114,61 +116,52 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
// Trim the list of cells to remove the invisible/empty ones at the end of the array
|
||||||
$aCells = $this->TrimCellsArray($aCells);
|
$aCells = $this->TrimCellsArray($aCells);
|
||||||
|
|
||||||
$oPage->add('<table style="width:100%;table-layout:fixed;"><tbody>');
|
$oDashboardLayout = new UIDashboardLayout();
|
||||||
|
$oPage->AddUiBlock($oDashboardLayout);
|
||||||
|
|
||||||
$iCellIdx = 0;
|
$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);
|
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||||
|
|
||||||
for($iRows = 0; $iRows < $iNbRows; $iRows++)
|
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||||
{
|
$oDashboardRow = new DashboardRow();
|
||||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
|
||||||
{
|
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||||
$sCellClass = ($iRows == $iNbRows-1) ? $sClass.' layout_last_used_rank' : $sClass;
|
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||||
$oPage->add("<td style=\"$sStyle\" class=\"$sCellClass\" data-dashboard-column-index=\"$iCols\" data-dashboard-cell-index=\"$iCellIdx\">");
|
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||||
if (array_key_exists($iCellIdx, $aCells))
|
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||||
{
|
|
||||||
|
if (array_key_exists($iCellIdx, $aCells)) {
|
||||||
$aDashlets = $aCells[$iCellIdx];
|
$aDashlets = $aCells[$iCellIdx];
|
||||||
if (count($aDashlets) > 0)
|
if (count($aDashlets) > 0) {
|
||||||
{
|
|
||||||
/** @var \Dashlet $oDashlet */
|
/** @var \Dashlet $oDashlet */
|
||||||
foreach($aDashlets as $oDashlet)
|
foreach ($aDashlets as $oDashlet) {
|
||||||
{
|
if ($oDashlet::IsVisible()) {
|
||||||
if ($oDashlet::IsVisible())
|
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||||
{
|
|
||||||
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||||
$oPage->add(' ');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$oPage->add(' ');
|
|
||||||
}
|
|
||||||
$oPage->add('</td>');
|
|
||||||
$iCellIdx++;
|
$iCellIdx++;
|
||||||
}
|
}
|
||||||
$oPage->add('</tr>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bEditMode) // Add one row for extensibility
|
if ($bEditMode) // Add one row for extensibility
|
||||||
{
|
{
|
||||||
$sStyle = 'style="border: 1px #ccc dashed; width:'.$fColSize.'%;" class="layout_cell edit_mode layout_extension" data-dashboard-cell-index="'.$iCellIdx.'"';
|
$oDashboardRow = new DashboardRow();
|
||||||
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
|
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
|
||||||
{
|
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||||
$oPage->add("<td $sStyle data-dashboard-column-index=\"$iCols\">");
|
$oDashboardColumn = new DashboardColumn($bEditMode, true);
|
||||||
$oPage->add(' ');
|
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||||
$oPage->add('</td>');
|
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||||
}
|
}
|
||||||
$oPage->add('</tr>');
|
|
||||||
}
|
}
|
||||||
$oPage->add('</tbody></table>');
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,13 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Component\Dashlet\DashletContainer;
|
||||||
|
use Combodo\iTop\Application\UI\Component\Dashlet\DashletFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||||
|
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
||||||
|
use Combodo\iTop\Application\UI\iUIBlock;
|
||||||
|
use Combodo\iTop\Application\UI\UIBlock;
|
||||||
|
|
||||||
require_once(APPROOT.'application/forms.class.inc.php');
|
require_once(APPROOT.'application/forms.class.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +57,7 @@ abstract class Dashlet
|
|||||||
$this->bRedrawNeeded = true; // By default: redraw each time a property changes
|
$this->bRedrawNeeded = true; // By default: redraw each time a property changes
|
||||||
$this->bFormRedrawNeeded = false; // By default: no need to redraw the form (independent fields)
|
$this->bFormRedrawNeeded = false; // By default: no need to redraw the form (independent fields)
|
||||||
$this->aProperties = array(); // By default: there is no property
|
$this->aProperties = array(); // By default: there is no property
|
||||||
$this->aCSSClasses = array('dashlet');
|
$this->aCSSClasses = array('ibo-dashlet');
|
||||||
$this->sDashletType = get_class($this);
|
$this->sDashletType = get_class($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,21 +73,17 @@ abstract class Dashlet
|
|||||||
{
|
{
|
||||||
$refValue = $this->aProperties[$sProperty];
|
$refValue = $this->aProperties[$sProperty];
|
||||||
$sRefType = gettype($refValue);
|
$sRefType = gettype($refValue);
|
||||||
if (gettype($sValue) == $sRefType)
|
|
||||||
{
|
if (gettype($sValue) == $sRefType) {
|
||||||
// Do not change anything in that case!
|
// Do not change anything in that case!
|
||||||
$ret = $sValue;
|
$ret = $sValue;
|
||||||
}
|
} elseif ($sRefType == 'boolean') {
|
||||||
elseif ($sRefType == 'boolean')
|
|
||||||
{
|
|
||||||
$ret = ($sValue == 'true');
|
$ret = ($sValue == 'true');
|
||||||
}
|
} elseif ($sRefType == 'array') {
|
||||||
elseif ($sRefType == 'array')
|
|
||||||
{
|
|
||||||
$ret = explode(',', $sValue);
|
$ret = explode(',', $sValue);
|
||||||
}
|
} elseif (is_array($sValue)) {
|
||||||
else
|
$ret = $sValue;
|
||||||
{
|
} else {
|
||||||
$ret = $sValue;
|
$ret = $sValue;
|
||||||
settype($ret, $sRefType);
|
settype($ret, $sRefType);
|
||||||
}
|
}
|
||||||
@@ -191,10 +194,8 @@ abstract class Dashlet
|
|||||||
*/
|
*/
|
||||||
public function FromParams($aParams)
|
public function FromParams($aParams)
|
||||||
{
|
{
|
||||||
foreach ($this->aProperties as $sProperty => $value)
|
foreach ($this->aProperties as $sProperty => $value) {
|
||||||
{
|
if (array_key_exists($sProperty, $aParams)) {
|
||||||
if (array_key_exists($sProperty, $aParams))
|
|
||||||
{
|
|
||||||
$this->aProperties[$sProperty] = $aParams[$sProperty];
|
$this->aProperties[$sProperty] = $aParams[$sProperty];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,79 +208,59 @@ abstract class Dashlet
|
|||||||
* @param bool $bEnclosingDiv
|
* @param bool $bEnclosingDiv
|
||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
*/
|
*/
|
||||||
public function DoRender($oPage, $bEditMode = false, $bEnclosingDiv = true, $aExtraParams = array())
|
public function DoRender($oPage, $bEditMode = false, $bEnclosingDiv = true, $aExtraParams = array()): UIBlock
|
||||||
{
|
{
|
||||||
$sCSSClasses = implode(' ', $this->aCSSClasses);
|
|
||||||
$sId = $this->GetID();
|
$sId = $this->GetID();
|
||||||
if ($bEnclosingDiv)
|
|
||||||
{
|
$sCSSClasses = implode(' ', $this->aCSSClasses);
|
||||||
if ($bEditMode)
|
if ($bEnclosingDiv) {
|
||||||
{
|
if ($bEditMode) {
|
||||||
$oPage->add('<div class="'.$sCSSClasses.'" id="dashlet_'.$sId.'">');
|
$oDashletContainer = new DashletContainer("dashlet_{$sId}");
|
||||||
|
} else {
|
||||||
|
$oDashletContainer = new DashletContainer();
|
||||||
}
|
}
|
||||||
else
|
$oDashletContainer->AddCSSClasses($sCSSClasses);
|
||||||
{
|
} else {
|
||||||
$oPage->add('<div class="'.$sCSSClasses.'">');
|
$oDashletContainer = new DashletContainer();
|
||||||
}
|
|
||||||
}
|
foreach ($this->aCSSClasses as $sCSSClass) {
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach ($this->aCSSClasses as $sCSSClass)
|
|
||||||
{
|
|
||||||
$oPage->add_ready_script("$('#dashlet_".$sId."').addClass('$sCSSClass');");
|
$oPage->add_ready_script("$('#dashlet_".$sId."').addClass('$sCSSClass');");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
if (get_class($this->oModelReflection) == 'ModelReflectionRuntime') {
|
||||||
if (get_class($this->oModelReflection) == 'ModelReflectionRuntime')
|
$oBlock = $this->Render($oPage, $bEditMode, $aExtraParams);
|
||||||
{
|
} else {
|
||||||
$this->Render($oPage, $bEditMode, $aExtraParams);
|
$oBlock = $this->RenderNoData($oPage, $bEditMode, $aExtraParams);
|
||||||
}
|
}
|
||||||
else
|
$oDashletContainer->AddSubBlock($oBlock);
|
||||||
{
|
} catch (UnknownClassOqlException $e) {
|
||||||
$this->RenderNoData($oPage, $bEditMode, $aExtraParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(UnknownClassOqlException $e)
|
|
||||||
{
|
|
||||||
// Maybe the class is part of a non-installed module, fail silently
|
// Maybe the class is part of a non-installed module, fail silently
|
||||||
// Except in Edit mode
|
// Except in Edit mode
|
||||||
if ($bEditMode)
|
if ($bEditMode) {
|
||||||
{
|
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer->AddHtml('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
||||||
$oPage->add('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
}
|
||||||
}
|
} catch (OqlException $e) {
|
||||||
catch(OqlException $e)
|
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||||
{
|
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
|
||||||
$oPage->add('<div class="dashlet-content">');
|
} catch (Exception $e) {
|
||||||
$oPage->p($e->GetUserFriendlyDescription());
|
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||||
$oPage->add('</div>');
|
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
|
||||||
$oPage->p($e->getMessage());
|
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bEnclosingDiv)
|
if ($bEditMode) {
|
||||||
{
|
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bEditMode)
|
|
||||||
{
|
|
||||||
$sClass = get_class($this);
|
$sClass = get_class($this);
|
||||||
$sType = $this->sDashletType;
|
$sType = $this->sDashletType;
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#dashlet_$sId').dashlet({dashlet_id: '$sId', dashlet_class: '$sClass', 'dashlet_type': '$sType'});
|
$('#dashlet_$sId').dashlet({dashlet_id: '$sId', dashlet_class: '$sClass', 'dashlet_type': '$sType'});
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,7 +284,7 @@ EOF
|
|||||||
* @param bool $bEditMode
|
* @param bool $bEditMode
|
||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return iUIBlock
|
||||||
*/
|
*/
|
||||||
abstract public function Render($oPage, $bEditMode = false, $aExtraParams = array());
|
abstract public function Render($oPage, $bEditMode = false, $aExtraParams = array());
|
||||||
|
|
||||||
@@ -313,10 +294,12 @@ EOF
|
|||||||
* @param \WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param bool $bEditMode
|
* @param bool $bEditMode
|
||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
|
*
|
||||||
|
* @return iUIBlock
|
||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$this->Render($oPage, $bEditMode, $aExtraParams);
|
return $this->Render($oPage, $bEditMode, $aExtraParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -619,12 +602,12 @@ class DashletUnknown extends Dashlet
|
|||||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||||
$sExplainText = ($bEditMode) ? Dict::Format('UI:DashletUnknown:RenderText:Edit', $this->GetDashletType()) : Dict::S('UI:DashletUnknown:RenderText:View');
|
$sExplainText = ($bEditMode) ? Dict::Format('UI:DashletUnknown:RenderText:Edit', $this->GetDashletType()) : Dict::S('UI:DashletUnknown:RenderText:View');
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||||
$oPage->add('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||||
|
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -639,12 +622,12 @@ class DashletUnknown extends Dashlet
|
|||||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||||
$sExplainText = Dict::Format('UI:DashletUnknown:RenderNoDataText:Edit', $this->GetDashletType());
|
$sExplainText = Dict::Format('UI:DashletUnknown:RenderNoDataText:Edit', $this->GetDashletType());
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||||
$oPage->add('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||||
|
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -763,9 +746,9 @@ class DashletProxy extends DashletUnknown
|
|||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
// This should never be called.
|
// This should never be called.
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
$oPage->add('<div>This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.</div>');
|
$oDashletContainer->AddHtml('<div>This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.</div>');
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -780,12 +763,14 @@ class DashletProxy extends DashletUnknown
|
|||||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||||
$sExplainText = Dict::Format('UI:DashletProxy:RenderNoDataText:Edit', $this->GetDashletType());
|
$sExplainText = Dict::Format('UI:DashletProxy:RenderNoDataText:Edit', $this->GetDashletType());
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>');
|
$sHtml = '';
|
||||||
$oPage->add('<div class="dashlet-pxy-text">'.$sExplainText.'</div>');
|
$sHtml .= '<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>';
|
||||||
|
$sHtml .= '<div class="dashlet-pxy-text">'.$sExplainText.'</div>';
|
||||||
|
|
||||||
$oPage->add('</div>');
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -816,7 +801,7 @@ class DashletEmptyCell extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$oPage->add(' ');
|
return new Html(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -866,8 +851,9 @@ class DashletPlainText extends Dashlet
|
|||||||
$sText = utils::HtmlEntities($this->aProperties['text']);
|
$sText = utils::HtmlEntities($this->aProperties['text']);
|
||||||
$sText = str_replace(array("\r\n", "\n", "\r"), "<br/>", $sText);
|
$sText = str_replace(array("\r\n", "\n", "\r"), "<br/>", $sText);
|
||||||
|
|
||||||
$sId = 'plaintext_'.($bEditMode? 'edit_' : '').$this->sId;
|
$sId = 'plaintext_'.($bEditMode ? 'edit_' : '').$this->sId;
|
||||||
$oPage->add('<div id="'.$sId.'" class="dashlet-content">'.$sText.'</div>');
|
|
||||||
|
return DashletFactory::MakeForDashletText($sId, $sText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -918,12 +904,8 @@ class DashletObjectList extends Dashlet
|
|||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
$sShowMenu = $this->aProperties['menu'] ? '1' : '0';
|
$sShowMenu = $this->aProperties['menu'] ? '1' : '0';
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
||||||
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
|
|
||||||
if ($sHtmlTitle != '')
|
|
||||||
{
|
|
||||||
$oPage->add('<div class="main_header"><h1> '.$sHtmlTitle.'</h1></div>');
|
|
||||||
}
|
|
||||||
$oFilter = $this->GetDBSearch($aExtraParams);
|
$oFilter = $this->GetDBSearch($aExtraParams);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'list');
|
$oBlock = new DisplayBlock($oFilter, 'list');
|
||||||
$aParams = array(
|
$aParams = array(
|
||||||
@@ -931,28 +913,9 @@ class DashletObjectList extends Dashlet
|
|||||||
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
|
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
|
||||||
);
|
);
|
||||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||||
$oBlock->Display($oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetDBSearch($aExtraParams = array())
|
return $oPanel;
|
||||||
{
|
|
||||||
$sQuery = $this->aProperties['query'];
|
|
||||||
if (isset($aExtraParams['query_params']))
|
|
||||||
{
|
|
||||||
$aQueryParams = $aExtraParams['query_params'];
|
|
||||||
}
|
|
||||||
elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id']))
|
|
||||||
{
|
|
||||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
|
||||||
$aQueryParams = $oObj->ToArgsForQuery();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aQueryParams = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
return DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -966,22 +929,35 @@ class DashletObjectList extends Dashlet
|
|||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oPage->add('<div class="dashlet-content">');
|
||||||
$sHtmlTitle = utils::HtmlEntities($this->oModelReflection->DictString($sTitle)); // done in the itop block
|
$sHtmlTitle = utils::HtmlEntities($this->oModelReflection->DictString($sTitle)); // done in the itop block
|
||||||
if ($sHtmlTitle != '')
|
if ($sHtmlTitle != '') {
|
||||||
{
|
|
||||||
$oPage->add('<h1>'.$sHtmlTitle.'</h1>');
|
$oPage->add('<h1>'.$sHtmlTitle.'</h1>');
|
||||||
}
|
}
|
||||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||||
$sClass = $oQuery->GetClass();
|
$sClass = $oQuery->GetClass();
|
||||||
$oPage->add('<div id="block_fake_'.$this->sId.'" class="display_block">');
|
$oPage->add('<div id="block_fake_'.$this->sId.'" class="display_block">');
|
||||||
$oPage->p(Dict::S('UI:NoObjectToDisplay'));
|
$oPage->p(Dict::S('UI:NoObjectToDisplay'));
|
||||||
if ($bShowMenu)
|
if ($bShowMenu) {
|
||||||
{
|
|
||||||
$oPage->p('<a>'.Dict::Format('UI:ClickToCreateNew', $this->oModelReflection->GetName($sClass)).'</a>');
|
$oPage->p('<a>'.Dict::Format('UI:ClickToCreateNew', $this->oModelReflection->GetName($sClass)).'</a>');
|
||||||
}
|
}
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetDBSearch($aExtraParams = array())
|
||||||
|
{
|
||||||
|
$sQuery = $this->aProperties['query'];
|
||||||
|
if (isset($aExtraParams['query_params'])) {
|
||||||
|
$aQueryParams = $aExtraParams['query_params'];
|
||||||
|
} elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id'])) {
|
||||||
|
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||||
|
$aQueryParams = $oObj->ToArgsForQuery();
|
||||||
|
} else {
|
||||||
|
$aQueryParams = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
@@ -1199,93 +1175,81 @@ abstract class DashletGroupBy extends Dashlet
|
|||||||
$sStyle = $this->aProperties['style'];
|
$sStyle = $this->aProperties['style'];
|
||||||
|
|
||||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||||
if (isset($aExtraParams['query_params']))
|
if (isset($aExtraParams['query_params'])) {
|
||||||
{
|
|
||||||
$aQueryParams = $aExtraParams['query_params'];
|
$aQueryParams = $aExtraParams['query_params'];
|
||||||
}
|
} elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id'])) {
|
||||||
elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id']))
|
|
||||||
{
|
|
||||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||||
$aQueryParams = $oObj->ToArgsForQuery();
|
$aQueryParams = $oObj->ToArgsForQuery();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aQueryParams = array();
|
$aQueryParams = array();
|
||||||
}
|
}
|
||||||
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||||
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
|
|
||||||
$sClass = $oFilter->GetClass();
|
$sClass = $oFilter->GetClass();
|
||||||
if (!$this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode))
|
if (!$this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode)) {
|
||||||
{
|
return new Html('<p>'.Dict::S('UI:DashletGroupBy:MissingGroupBy').'</p>');
|
||||||
$oPage->add('<p>'.Dict::S('UI:DashletGroupBy:MissingGroupBy').'</p>');
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
switch($sStyle)
|
|
||||||
{
|
|
||||||
case 'bars':
|
|
||||||
$sType = 'chart';
|
|
||||||
$aParams = array(
|
|
||||||
'chart_type' => 'bars',
|
|
||||||
'chart_title' => $sTitle,
|
|
||||||
'group_by' => $this->sGroupByExpr,
|
|
||||||
'group_by_label' => $this->sGroupByLabel,
|
|
||||||
'aggregation_function' => $this->sAggregationFunction,
|
|
||||||
'aggregation_attribute' => $this->sAggregationAttribute,
|
|
||||||
'limit' => $this->sLimit,
|
|
||||||
'order_direction' => $this->sOrderDirection,
|
|
||||||
'order_by' => $this->sOrderBy,
|
|
||||||
);
|
|
||||||
$sHtmlTitle = ''; // done in the itop block
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'pie':
|
switch ($sStyle) {
|
||||||
$sType = 'chart';
|
case 'bars':
|
||||||
$aParams = array(
|
$sType = 'chart';
|
||||||
'chart_type' => 'pie',
|
$aParams = array(
|
||||||
'chart_title' => $sTitle,
|
'chart_type' => 'bars',
|
||||||
'group_by' => $this->sGroupByExpr,
|
'chart_title' => $sTitle,
|
||||||
'group_by_label' => $this->sGroupByLabel,
|
'group_by' => $this->sGroupByExpr,
|
||||||
'aggregation_function' => $this->sAggregationFunction,
|
'group_by_label' => $this->sGroupByLabel,
|
||||||
'aggregation_attribute' => $this->sAggregationAttribute,
|
'aggregation_function' => $this->sAggregationFunction,
|
||||||
'limit' => $this->sLimit,
|
'aggregation_attribute' => $this->sAggregationAttribute,
|
||||||
'order_direction' => $this->sOrderDirection,
|
'limit' => $this->sLimit,
|
||||||
'order_by' => $this->sOrderBy,
|
'order_direction' => $this->sOrderDirection,
|
||||||
);
|
'order_by' => $this->sOrderBy,
|
||||||
$sHtmlTitle = ''; // done in the itop block
|
);
|
||||||
break;
|
$sHtmlTitle = ''; // done in the itop block
|
||||||
|
break;
|
||||||
|
|
||||||
case 'table':
|
case 'pie':
|
||||||
default:
|
$sType = 'chart';
|
||||||
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
|
$aParams = array(
|
||||||
$sType = 'count';
|
'chart_type' => 'pie',
|
||||||
$aParams = array(
|
'chart_title' => $sTitle,
|
||||||
'group_by' => $this->sGroupByExpr,
|
'group_by' => $this->sGroupByExpr,
|
||||||
'group_by_label' => $this->sGroupByLabel,
|
'group_by_label' => $this->sGroupByLabel,
|
||||||
'aggregation_function' => $this->sAggregationFunction,
|
'aggregation_function' => $this->sAggregationFunction,
|
||||||
'aggregation_attribute' => $this->sAggregationAttribute,
|
'aggregation_attribute' => $this->sAggregationAttribute,
|
||||||
'limit' => $this->sLimit,
|
'limit' => $this->sLimit,
|
||||||
'order_direction' => $this->sOrderDirection,
|
'order_direction' => $this->sOrderDirection,
|
||||||
'order_by' => $this->sOrderBy,
|
'order_by' => $this->sOrderBy,
|
||||||
);
|
);
|
||||||
break;
|
$sHtmlTitle = ''; // done in the itop block
|
||||||
}
|
break;
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
case 'table':
|
||||||
if ($sHtmlTitle != '')
|
default:
|
||||||
{
|
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
|
||||||
$oPage->add('<div class="main_header"><h1> '.$sHtmlTitle.'</h1></div>');
|
$sType = 'count';
|
||||||
}
|
$aParams = array(
|
||||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
'group_by' => $this->sGroupByExpr,
|
||||||
$oBlock = new DisplayBlock($oFilter, $sType);
|
'group_by_label' => $this->sGroupByLabel,
|
||||||
$oBlock->Display($oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
'aggregation_function' => $this->sAggregationFunction,
|
||||||
if($bEditMode)
|
'aggregation_attribute' => $this->sAggregationAttribute,
|
||||||
{
|
'limit' => $this->sLimit,
|
||||||
$oPage->add('<div class="dashlet-blocker"></div>');
|
'order_direction' => $this->sOrderDirection,
|
||||||
}
|
'order_by' => $this->sOrderBy,
|
||||||
$oPage->add('</div>');
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
||||||
|
|
||||||
|
|
||||||
|
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||||
|
$oBlock = new DisplayBlock($oFilter, $sType);
|
||||||
|
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||||
|
if ($bEditMode) {
|
||||||
|
$oPanel->AddHtml('<div class="dashlet-blocker"></div>');
|
||||||
|
}
|
||||||
|
return $oPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1368,9 +1332,9 @@ abstract class DashletGroupBy extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
$oPage->add('error!');
|
$oDashletContainer->AddHtml('error!');
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1691,26 +1655,27 @@ class DashletGroupByPie extends DashletGroupBy
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
|
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
|
|
||||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||||
|
|
||||||
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
||||||
$oPage->add("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
$oDashletContainer->AddHtml("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||||
|
|
||||||
$aDisplayValues = $this->MakeSimulatedData();
|
$aDisplayValues = $this->MakeSimulatedData();
|
||||||
|
|
||||||
$aColumns = array();
|
$aColumns = array();
|
||||||
$aNames = array();
|
$aNames = array();
|
||||||
foreach($aDisplayValues as $idx => $aValue)
|
foreach ($aDisplayValues as $idx => $aValue) {
|
||||||
{
|
|
||||||
$aColumns[] = array('series_'.$idx, (int)$aValue['value']);
|
$aColumns[] = array('series_'.$idx, (int)$aValue['value']);
|
||||||
$aNames['series_'.$idx] = $aValue['label'];
|
$aNames['series_'.$idx] = $aValue['label'];
|
||||||
}
|
}
|
||||||
$sJSColumns = json_encode($aColumns);
|
$sJSColumns = json_encode($aColumns);
|
||||||
$sJSNames = json_encode($aNames);
|
$sJSNames = json_encode($aNames);
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
var chart = c3.generate({
|
var chart = c3.generate({
|
||||||
bindto: '#{$sBlockId}',
|
bindto: '#{$sBlockId}',
|
||||||
@@ -1731,6 +1696,8 @@ var chart = c3.generate({
|
|||||||
});}, 100);
|
});}, 100);
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1763,25 +1730,26 @@ class DashletGroupByBars extends DashletGroupBy
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
|
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
|
|
||||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||||
|
|
||||||
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
||||||
$oPage->add("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
$oDashletContainer->AddHtml("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||||
|
|
||||||
$aDisplayValues = $this->MakeSimulatedData();
|
$aDisplayValues = $this->MakeSimulatedData();
|
||||||
|
|
||||||
$aNames = array();
|
$aNames = array();
|
||||||
foreach($aDisplayValues as $idx => $aValue)
|
foreach ($aDisplayValues as $idx => $aValue) {
|
||||||
{
|
|
||||||
$aNames[$idx] = $aValue['label'];
|
$aNames[$idx] = $aValue['label'];
|
||||||
}
|
}
|
||||||
$sJSNames = json_encode($aNames);
|
$sJSNames = json_encode($aNames);
|
||||||
|
|
||||||
$sJson = json_encode($aDisplayValues);
|
$sJson = json_encode($aDisplayValues);
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
var chart = c3.generate({
|
var chart = c3.generate({
|
||||||
bindto: '#{$sBlockId}',
|
bindto: '#{$sBlockId}',
|
||||||
@@ -1829,6 +1797,8 @@ window.setTimeout(function() {
|
|||||||
}, 100);
|
}, 100);
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1860,40 +1830,44 @@ class DashletGroupByTable extends DashletGroupBy
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
|
$oDashletContainer = new DashletContainer();
|
||||||
|
|
||||||
$aDisplayValues = $this->MakeSimulatedData();
|
$aDisplayValues = $this->MakeSimulatedData();
|
||||||
$iTotal = 0;
|
$iTotal = 0;
|
||||||
foreach($aDisplayValues as $iRow => $aDisplayData)
|
foreach ($aDisplayValues as $iRow => $aDisplayData) {
|
||||||
{
|
|
||||||
$iTotal += $aDisplayData['value'];
|
$iTotal += $aDisplayData['value'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||||
|
|
||||||
$oPage->add('<div id="'.$sBlockId.'" class="display_block">');
|
$sHtml = '';
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$sHtml .= '<div id="'.$sBlockId.'" class="display_block">';
|
||||||
$oPage->add('<p>'.Dict::Format('UI:Pagination:HeaderNoSelection', $iTotal).'</p>');
|
$sHtml .= '<div class="dashlet-content">';
|
||||||
$oPage->add('<table class="listResults">');
|
$sHtml .= '<p>'.Dict::Format('UI:Pagination:HeaderNoSelection', $iTotal).'</p>';
|
||||||
$oPage->add('<thead>');
|
$sHtml .= '<table class="listResults">';
|
||||||
$oPage->add('<tr>');
|
$sHtml .= '<thead>';
|
||||||
$oPage->add('<th class="header" title="">'.$this->sGroupByLabel.'</th>');
|
$sHtml .= '<tr>';
|
||||||
$oPage->add('<th class="header" title="'.Dict::S('UI:GroupBy:Count+').'">'.Dict::S('UI:GroupBy:Count').'</th>');
|
$sHtml .= '<th class="header" title="">'.$this->sGroupByLabel.'</th>';
|
||||||
$oPage->add('</tr>');
|
$sHtml .= '<th class="header" title="'.Dict::S('UI:GroupBy:Count+').'">'.Dict::S('UI:GroupBy:Count').'</th>';
|
||||||
$oPage->add('</thead>');
|
$sHtml .= '</tr>';
|
||||||
$oPage->add('<tbody>');
|
$sHtml .= '</thead>';
|
||||||
foreach($aDisplayValues as $aDisplayData)
|
$sHtml .= '<tbody>';
|
||||||
{
|
foreach ($aDisplayValues as $aDisplayData) {
|
||||||
$oPage->add('<tr class="even">');
|
$sHtml .= '<tr class="even">';
|
||||||
$oPage->add('<td class=""><span title="Active">'.$aDisplayData['label'].'</span></td>');
|
$sHtml .= '<td class=""><span title="Active">'.$aDisplayData['label'].'</span></td>';
|
||||||
$oPage->add('<td class=""><a>'.$aDisplayData['value'].'</a></td>');
|
$sHtml .= '<td class=""><a>'.$aDisplayData['value'].'</a></td>';
|
||||||
$oPage->add('</tr>');
|
$sHtml .= '</tr>';
|
||||||
}
|
}
|
||||||
$oPage->add('</tbody>');
|
$sHtml .= '</tbody>';
|
||||||
$oPage->add('</table>');
|
$sHtml .= '</table>';
|
||||||
$oPage->add('</div>');
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$oPage->add('</div>');
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1922,14 +1896,7 @@ class DashletHeaderStatic extends Dashlet
|
|||||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
return DashletFactory::MakeForDashletHeaderStatic($this->oModelReflection->DictString($sTitle), $sIconPath);
|
||||||
$oPage->add('<div class="main_header">');
|
|
||||||
|
|
||||||
$oPage->add('<img src="'.$sIconPath.'">');
|
|
||||||
$oPage->add('<div class="main_header"><h1> '.$this->oModelReflection->DictString($sTitle).'</h1></div>');
|
|
||||||
|
|
||||||
$oPage->add('</div>');
|
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2056,8 +2023,7 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||||
|
|
||||||
$aValues = $this->GetValues();
|
$aValues = $this->GetValues();
|
||||||
if (count($aValues) > 0)
|
if (count($aValues) > 0) {
|
||||||
{
|
|
||||||
// Stats grouped by <group_by>
|
// Stats grouped by <group_by>
|
||||||
$sCSV = implode(',', $aValues);
|
$sCSV = implode(',', $aValues);
|
||||||
$aParams = array(
|
$aParams = array(
|
||||||
@@ -2067,9 +2033,7 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
'status_codes[block]' => $sCSV,
|
'status_codes[block]' => $sCSV,
|
||||||
'context_filter' => 1,
|
'context_filter' => 1,
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Simple stats
|
// Simple stats
|
||||||
$aParams = array(
|
$aParams = array(
|
||||||
'title[block]' => $sTitle,
|
'title[block]' => $sTitle,
|
||||||
@@ -2078,31 +2042,29 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oPanel = PanelFactory::MakeEnhancedNeutral(Dict::S(str_replace('_', ':', $sTitle)), $sIconPath);
|
||||||
$oPage->add('<div class="main_header">');
|
|
||||||
|
|
||||||
$oPage->add('<img src="'.$sIconPath.'">');
|
if (isset($aExtraParams['query_params'])) {
|
||||||
|
|
||||||
if (isset($aExtraParams['query_params']))
|
|
||||||
{
|
|
||||||
$aQueryParams = $aExtraParams['query_params'];
|
$aQueryParams = $aExtraParams['query_params'];
|
||||||
}
|
} elseif (isset($aExtraParams['this->class'])) {
|
||||||
elseif (isset($aExtraParams['this->class']))
|
|
||||||
{
|
|
||||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||||
$aQueryParams = $oObj->ToArgsForQuery();
|
$aQueryParams = $oObj->ToArgsForQuery();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aQueryParams = array();
|
$aQueryParams = array();
|
||||||
}
|
}
|
||||||
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'summary');
|
$oBlock = new DisplayBlock($oFilter, 'summary');
|
||||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||||
$oBlock->Display($oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||||
|
|
||||||
$oPage->add('</div>');
|
$oSubTitle = $oPanel->GetSubTitle();
|
||||||
$oPage->add('</div>');
|
$oSet = new DBObjectSet($oFilter);
|
||||||
|
$iCount = $oSet->Count();
|
||||||
|
$oAppContext = new ApplicationContext();
|
||||||
|
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($oFilter->serialize());
|
||||||
|
$oSubTitle->AddHtml('<a class="summary" href="'.$sHyperlink.'">'.Dict::Format(str_replace('_', ':', $sSubtitle), $iCount).'</a>');
|
||||||
|
|
||||||
|
return $oPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2122,46 +2084,48 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||||
$oPage->add('<div class="main_header">');
|
|
||||||
|
|
||||||
$oPage->add('<img src="'.$sIconPath.'">');
|
$sHtml = '';
|
||||||
|
$sHtml .= '<img src="'.$sIconPath.'">';
|
||||||
|
|
||||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||||
|
|
||||||
$iTotal = 0;
|
$iTotal = 0;
|
||||||
$aValues = $this->GetValues();
|
$aValues = $this->GetValues();
|
||||||
|
|
||||||
$oPage->add('<div class="display_block" id="'.$sBlockId.'">');
|
$sHtml .= '<div class="display_block" id="'.$sBlockId.'">';
|
||||||
$oPage->add('<div class="summary-details">');
|
$sHtml .= '<div class="summary-details">';
|
||||||
$oPage->add('<table><tbody>');
|
$sHtml .= '<table><tbody>';
|
||||||
$oPage->add('<tr>');
|
$sHtml .= '<tr>';
|
||||||
foreach ($aValues as $sValue)
|
foreach ($aValues as $sValue) {
|
||||||
{
|
|
||||||
$sValueLabel = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
|
$sValueLabel = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
|
||||||
$oPage->add(' <th>'.$sValueLabel.'</th>');
|
$sHtml .= ' <th>'.$sValueLabel.'</th>';
|
||||||
}
|
}
|
||||||
$oPage->add('</tr>');
|
$sHtml .= '</tr>';
|
||||||
$oPage->add('<tr>');
|
$sHtml .= '<tr>';
|
||||||
foreach ($aValues as $sValue)
|
foreach ($aValues as $sValue) {
|
||||||
{
|
$iCount = (int)rand(2, 100);
|
||||||
$iCount = (int) rand(2, 100);
|
|
||||||
$iTotal += $iCount;
|
$iTotal += $iCount;
|
||||||
$oPage->add(' <td>'.$iCount.'</td>');
|
$sHtml .= ' <td>'.$iCount.'</td>';
|
||||||
}
|
}
|
||||||
$oPage->add('</tr>');
|
$sHtml .= '</tr>';
|
||||||
$oPage->add('</tbody></table>');
|
$sHtml .= '</tbody></table>';
|
||||||
$oPage->add('</div>');
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$sTitle = $this->oModelReflection->DictString($sTitle);
|
$sTitle = $this->oModelReflection->DictString($sTitle);
|
||||||
$sSubtitle = $this->oModelReflection->DictFormat($sSubtitle, $iTotal);
|
$sSubtitle = $this->oModelReflection->DictFormat($sSubtitle, $iTotal);
|
||||||
|
|
||||||
$oPage->add('<h1>'.utils::HtmlEntities($sTitle).'</h1>');
|
$sHtml .= '<h1>'.utils::HtmlEntities($sTitle).'</h1>';
|
||||||
$oPage->add('<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>');
|
$sHtml .= '<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>';
|
||||||
$oPage->add('</div>');
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
|
|
||||||
$oPage->add('</div>');
|
|
||||||
$oPage->add('</div>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2306,8 +2270,8 @@ class DashletBadge extends Dashlet
|
|||||||
{
|
{
|
||||||
parent::__construct($oModelReflection, $sId);
|
parent::__construct($oModelReflection, $sId);
|
||||||
$this->aProperties['class'] = 'Contact';
|
$this->aProperties['class'] = 'Contact';
|
||||||
$this->aCSSClasses[] = 'dashlet-inline';
|
$this->aCSSClasses[] = 'ibo-dashlet--is-inline';
|
||||||
$this->aCSSClasses[] = 'dashlet-badge';
|
$this->aCSSClasses[] = 'ibo-dashlet-badge';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2317,17 +2281,16 @@ class DashletBadge extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
|
$oDashletContainer = new DashletContainer($this->sId, 'dashlet-content');
|
||||||
|
|
||||||
$sClass = $this->aProperties['class'];
|
$sClass = $this->aProperties['class'];
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
|
||||||
|
|
||||||
$oFilter = new DBObjectSearch($sClass);
|
$oFilter = new DBObjectSearch($sClass);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'actions');
|
$oBlock = new DisplayBlock($oFilter, 'actions');
|
||||||
$aExtraParams['context_filter'] = 1;
|
$aExtraParams['context_filter'] = 1;
|
||||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||||
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
|
$oBlock->DisplayIntoContentBlock($oDashletContainer, $oPage, $sBlockId, $aExtraParams);
|
||||||
|
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2335,25 +2298,25 @@ class DashletBadge extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$sClass = $this->aProperties['class'];
|
$oDashletContainer = new DashletContainer($this->sId, 'dashlet-content');
|
||||||
|
|
||||||
|
$sClass = $this->aProperties['class'];
|
||||||
$sIconUrl = $this->oModelReflection->GetClassIcon($sClass, false);
|
$sIconUrl = $this->oModelReflection->GetClassIcon($sClass, false);
|
||||||
$sClassLabel = $this->oModelReflection->GetName($sClass);
|
$sClassLabel = $this->oModelReflection->GetName($sClass);
|
||||||
|
|
||||||
$oPage->add('<div class="dashlet-content">');
|
$sHtml = '';
|
||||||
|
$sHtml .= '<div id="block_fake_'.$this->sId.'" class="display_block">';
|
||||||
|
$sHtml .= '<p>';
|
||||||
|
$sHtml .= ' <a class="actions"><img src="'.utils::HtmlEntities($sIconUrl).'" style="vertical-align:middle;float;left;margin-right:10px;border:0;">'.$sClassLabel.': 947</a>';
|
||||||
|
$sHtml .= '</p>';
|
||||||
|
$sHtml .= '<p>';
|
||||||
|
$sHtml .= ' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>';
|
||||||
|
$sHtml .= '</p>';
|
||||||
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$oPage->add('<div id="block_fake_'.$this->sId.'" class="display_block">');
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
$oPage->add('<p>');
|
|
||||||
$oPage->add(' <a class="actions"><img src="'.utils::HtmlEntities($sIconUrl).'" style="vertical-align:middle;float;left;margin-right:10px;border:0;">'.$sClassLabel.': 947</a>');
|
|
||||||
$oPage->add('</p>');
|
|
||||||
$oPage->add('<p>');
|
|
||||||
$oPage->add(' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>');
|
|
||||||
$oPage->add(' <br/>');
|
|
||||||
$oPage->add(' <a>'.Dict::Format('UI:SearchFor_Class', $sClassLabel).'</a>');
|
|
||||||
$oPage->add('</p>');
|
|
||||||
$oPage->add('</div>');
|
|
||||||
|
|
||||||
$oPage->add('</div>');
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected $aClassList = null;
|
static protected $aClassList = null;
|
||||||
|
|||||||
@@ -1,5 +1,46 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
|
<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>
|
||||||
<portals>
|
<portals>
|
||||||
<portal id="backoffice" _delta="define">
|
<portal id="backoffice" _delta="define">
|
||||||
<url>pages/UI.php</url>
|
<url>pages/UI.php</url>
|
||||||
@@ -12,13 +53,351 @@
|
|||||||
</portal>
|
</portal>
|
||||||
</portals>
|
</portals>
|
||||||
<menus>
|
<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/>
|
||||||
|
<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">
|
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
||||||
<rank>80</rank>
|
<rank>80</rank>
|
||||||
|
<style>
|
||||||
|
<decoration_classes>fas fa-tools</decoration_classes>
|
||||||
|
</style>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
<menu id="SystemTools" xsi:type="MenuGroup" _delta="define">
|
||||||
<rank>100</rank>
|
<rank>100</rank>
|
||||||
<enable_class>ResourceSystemMenu</enable_class>
|
<enable_class>ResourceSystemMenu</enable_class>
|
||||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||||
|
<style>
|
||||||
|
<decoration_classes>fas fa-terminal</decoration_classes>
|
||||||
|
</style>
|
||||||
</menu>
|
</menu>
|
||||||
</menus>
|
</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="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="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>
|
||||||
|
<method id="PrefillCreationForm">
|
||||||
|
<arguments>
|
||||||
|
<argument id="1">
|
||||||
|
<type>reference</type>
|
||||||
|
<mandatory>true</mandatory>
|
||||||
|
</argument>
|
||||||
|
</arguments>
|
||||||
|
</method>
|
||||||
|
<method id="PrefillTransitionForm">
|
||||||
|
<arguments>
|
||||||
|
<argument id="1">
|
||||||
|
<type>reference</type>
|
||||||
|
<mandatory>true</mandatory>
|
||||||
|
</argument>
|
||||||
|
</arguments>
|
||||||
|
</method>
|
||||||
|
<method id="PrefillSearchForm">
|
||||||
|
<arguments>
|
||||||
|
<argument id="1">
|
||||||
|
<type>reference</type>
|
||||||
|
<mandatory>true</mandatory>
|
||||||
|
</argument>
|
||||||
|
</arguments>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
</class>
|
||||||
|
</classes>
|
||||||
|
</meta>
|
||||||
</itop_design>
|
</itop_design>
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Combodo\iTop\Renderer\BlockRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
*
|
*
|
||||||
@@ -25,7 +28,7 @@ class DataTable
|
|||||||
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
|
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
|
||||||
protected $oSet; // The set of objects to display
|
protected $oSet; // The set of objects to display
|
||||||
protected $aClassAliases; // The aliases (alias => class) inside the set
|
protected $aClassAliases; // The aliases (alias => class) inside the set
|
||||||
protected $iNbObjects; // Total number of objects inthe set
|
protected $iNbObjects; // Total number of objects in the set
|
||||||
protected $bUseCustomSettings; // Whether or not the current display uses custom settings
|
protected $bUseCustomSettings; // Whether or not the current display uses custom settings
|
||||||
protected $oDefaultSettings; // the default settings for displaying such a list
|
protected $oDefaultSettings; // the default settings for displaying such a list
|
||||||
protected $bShowObsoleteData;
|
protected $bShowObsoleteData;
|
||||||
@@ -157,17 +160,17 @@ class DataTable
|
|||||||
$sPager = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
$sPager = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
||||||
$sActionsMenu = '';
|
$sActionsMenu = '';
|
||||||
$sToolkitMenu = '';
|
$sToolkitMenu = '';
|
||||||
if ($bActionsMenu)
|
if ($bActionsMenu) {
|
||||||
{
|
|
||||||
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
|
$sActionsMenu = $this->GetActionsMenu($oPage, $aExtraParams);
|
||||||
}
|
}
|
||||||
if ($bToolkitMenu)
|
// if ($bToolkitMenu)
|
||||||
{
|
// {
|
||||||
$sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
// $sToolkitMenu = $this->GetToolkitMenu($oPage, $aExtraParams);
|
||||||
}
|
// }
|
||||||
|
|
||||||
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||||
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
||||||
|
|
||||||
$sHtml = "<table id=\"{$this->sDatatableContainerId}\" class=\"datatable\">";
|
$sHtml = "<table id=\"{$this->sDatatableContainerId}\" class=\"datatable\">";
|
||||||
$sHtml .= "<tr><td>";
|
$sHtml .= "<tr><td>";
|
||||||
$sHtml .= "<table style=\"width:100%;\">";
|
$sHtml .= "<table style=\"width:100%;\">";
|
||||||
@@ -208,7 +211,7 @@ class DataTable
|
|||||||
|
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When refreshing the body of a paginated table, get the rows of the table (inside the TBODY)
|
* 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
|
* return string The HTML rows to insert inside the <tbody> node
|
||||||
@@ -355,9 +358,18 @@ EOF;
|
|||||||
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
||||||
|
|
||||||
$sHtml = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
||||||
return $sHtml;
|
foreach ($oBlock->GetCssFilesUrlRecursively(true) as $sFileAbsUrl) {
|
||||||
|
$oPage->add_linked_stylesheet($sFileAbsUrl);
|
||||||
|
}
|
||||||
|
// JS files
|
||||||
|
foreach ($oBlock->GetJsFilesUrlRecursively(true) as $sFileAbsUrl) {
|
||||||
|
$oPage->add_linked_script($sFileAbsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oPage->RenderInlineScriptsAndCSSRecursively($oBlock);
|
||||||
|
return BlockRenderer::RenderBlockTemplates($oBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -513,6 +525,7 @@ EOF;
|
|||||||
return $aAttribs;
|
return $aAttribs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $aColumns
|
* @param $aColumns
|
||||||
* @param $sSelectMode
|
* @param $sSelectMode
|
||||||
@@ -860,396 +873,3 @@ class PrintableDataTable extends DataTable
|
|||||||
return $sHtml;
|
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,82 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ class InputOutputTask extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_iotask",
|
"db_table" => "priv_iotask",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("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,57 +1,7 @@
|
|||||||
<?php
|
<?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/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class iTopWizardWebPage
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ class LoginTwigRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
$oCoreLoader = new Twig_Loader_Filesystem(array(), APPROOT.'templates');
|
$oCoreLoader = new Twig_Loader_Filesystem(array(), APPROOT.'templates');
|
||||||
$aCoreTemplatesPaths = array('login', 'login/password');
|
$aCoreTemplatesPaths = array('pages/login', 'pages/login/password');
|
||||||
// Having this path declared after the plugins let the plugins replace the core templates
|
// Having this path declared after the plugins let the plugins replace the core templates
|
||||||
$oCoreLoader->setPaths($aCoreTemplatesPaths);
|
$oCoreLoader->setPaths($aCoreTemplatesPaths);
|
||||||
// Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them
|
// Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ class LoginWebPage extends NiceWebPage
|
|||||||
{
|
{
|
||||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css');
|
$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/all.min.css');
|
||||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function SetLoginFailedMessage($sMessage)
|
public static function SetLoginFailedMessage($sMessage)
|
||||||
@@ -102,6 +101,44 @@ class LoginWebPage extends NiceWebPage
|
|||||||
self::$m_sLoginFailedMessage = $sMessage;
|
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)
|
public function DisplayLoginHeader($bMainAppLogo = false)
|
||||||
{
|
{
|
||||||
$sLogo = 'itop-logo-external.png';
|
$sLogo = 'itop-logo-external.png';
|
||||||
@@ -888,20 +925,12 @@ class LoginWebPage extends NiceWebPage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now synchronize the profiles
|
// Now synchronize the profiles
|
||||||
$oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
|
|
||||||
$sOrigin = 'External User provisioning';
|
$sOrigin = 'External User provisioning';
|
||||||
if (isset($_SESSION['login_mode']))
|
if (isset($_SESSION['login_mode']))
|
||||||
{
|
{
|
||||||
$sOrigin .= " ({$_SESSION['login_mode']})";
|
$sOrigin .= " ({$_SESSION['login_mode']})";
|
||||||
}
|
}
|
||||||
foreach ($aProfiles as $iProfileId)
|
$aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin);
|
||||||
{
|
|
||||||
$oLink = new URP_UserProfile();
|
|
||||||
$oLink->Set('profileid', $iProfileId);
|
|
||||||
$oLink->Set('reason', $sOrigin);
|
|
||||||
$oProfilesSet->AddObject($oLink);
|
|
||||||
}
|
|
||||||
$oUser->Set('profile_list', $oProfilesSet);
|
|
||||||
if ($oUser->IsModified())
|
if ($oUser->IsModified())
|
||||||
{
|
{
|
||||||
$oUser->DBWrite();
|
$oUser->DBWrite();
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Component\Title\TitleFactory;
|
||||||
|
|
||||||
require_once(APPROOT.'/application/utils.inc.php');
|
require_once(APPROOT.'/application/utils.inc.php');
|
||||||
require_once(APPROOT.'/application/template.class.inc.php');
|
require_once(APPROOT.'/application/template.class.inc.php');
|
||||||
require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
||||||
@@ -51,7 +53,10 @@ require_once(APPROOT."/application/user.dashboard.class.inc.php");
|
|||||||
* new OQLMenuNode('PersonsMenu', 'SELECT bizPerson', $oContactsMenu->GetIndex(), 0);
|
* new OQLMenuNode('PersonsMenu', 'SELECT bizPerson', $oContactsMenu->GetIndex(), 0);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApplicationMenu
|
||||||
|
*/
|
||||||
class ApplicationMenu
|
class ApplicationMenu
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +76,10 @@ class ApplicationMenu
|
|||||||
*/
|
*/
|
||||||
static $sFavoriteSiloQuery = 'SELECT Organization';
|
static $sFavoriteSiloQuery = 'SELECT Organization';
|
||||||
|
|
||||||
static public function LoadAdditionalMenus()
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function LoadAdditionalMenus()
|
||||||
{
|
{
|
||||||
if (!self::$bAdditionalMenusLoaded)
|
if (!self::$bAdditionalMenusLoaded)
|
||||||
{
|
{
|
||||||
@@ -97,10 +105,10 @@ class ApplicationMenu
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the query used to limit the list of displayed organizations in the drop-down menu
|
* Set the query used to limit the list of displayed organizations in the drop-down menu
|
||||||
* @param $sOQL string The OQL query returning a list of Organization objects
|
* @param string $sOQL The OQL query returning a list of Organization objects
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
static public function SetFavoriteSiloQuery($sOQL)
|
public static function SetFavoriteSiloQuery($sOQL)
|
||||||
{
|
{
|
||||||
self::$sFavoriteSiloQuery = $sOQL;
|
self::$sFavoriteSiloQuery = $sOQL;
|
||||||
}
|
}
|
||||||
@@ -109,7 +117,7 @@ class ApplicationMenu
|
|||||||
* Get the query used to limit the list of displayed organizations in the drop-down menu
|
* 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
|
* @return string The OQL query returning a list of Organization objects
|
||||||
*/
|
*/
|
||||||
static public function GetFavoriteSiloQuery()
|
public static function GetFavoriteSiloQuery()
|
||||||
{
|
{
|
||||||
return self::$sFavoriteSiloQuery;
|
return self::$sFavoriteSiloQuery;
|
||||||
}
|
}
|
||||||
@@ -117,11 +125,11 @@ class ApplicationMenu
|
|||||||
/**
|
/**
|
||||||
* Check whether a menu Id is enabled or not
|
* Check whether a menu Id is enabled or not
|
||||||
*
|
*
|
||||||
* @param $sMenuId
|
* @param string $sMenuId
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
static public function CheckMenuIdEnabled($sMenuId)
|
public static function CheckMenuIdEnabled($sMenuId)
|
||||||
{
|
{
|
||||||
self::LoadAdditionalMenus();
|
self::LoadAdditionalMenus();
|
||||||
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
|
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
|
||||||
@@ -140,11 +148,11 @@ class ApplicationMenu
|
|||||||
* Main function to add a menu entry into the application, can be called during the definition
|
* Main function to add a menu entry into the application, can be called during the definition
|
||||||
* of the data model objects
|
* of the data model objects
|
||||||
* @param MenuNode $oMenuNode
|
* @param MenuNode $oMenuNode
|
||||||
* @param $iParentIndex
|
* @param int $iParentIndex
|
||||||
* @param $fRank
|
* @param float $fRank
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
static public function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
|
public static function InsertMenu(MenuNode $oMenuNode, $iParentIndex, $fRank)
|
||||||
{
|
{
|
||||||
$index = self::GetMenuIndexById($oMenuNode->GetMenuId());
|
$index = self::GetMenuIndexById($oMenuNode->GetMenuId());
|
||||||
if ($index == -1)
|
if ($index == -1)
|
||||||
@@ -185,20 +193,154 @@ class ApplicationMenu
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reflection API - Get menu entries
|
* Reflection API - Get menu entries
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
static public function ReflectionMenuNodes()
|
public static function ReflectionMenuNodes()
|
||||||
{
|
{
|
||||||
self::LoadAdditionalMenus();
|
self::LoadAdditionalMenus();
|
||||||
return self::$aMenusIndex;
|
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
|
* Entry point to display the whole menu into the web page, used by iTopWebPage
|
||||||
* @param \WebPage $oPage
|
* @param \WebPage $oPage
|
||||||
* @param $aExtraParams
|
* @param array $aExtraParams
|
||||||
* @throws DictExceptionMissingString
|
* @throws DictExceptionMissingString
|
||||||
|
*
|
||||||
|
* @deprecated Will be removed in 3.0.0, use static::GetMenuGroups() instead
|
||||||
*/
|
*/
|
||||||
static public function DisplayMenu($oPage, $aExtraParams)
|
public static function DisplayMenu($oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
self::LoadAdditionalMenus();
|
self::LoadAdditionalMenus();
|
||||||
// Sort the root menu based on the rank
|
// Sort the root menu based on the rank
|
||||||
@@ -237,7 +379,7 @@ EOF
|
|||||||
* @param array $aMenu menu entry
|
* @param array $aMenu menu entry
|
||||||
* @return bool true if at least one menu is enabled
|
* @return bool true if at least one menu is enabled
|
||||||
*/
|
*/
|
||||||
static private function CanDisplayMenu($aMenu)
|
private static function CanDisplayMenu($aMenu)
|
||||||
{
|
{
|
||||||
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
||||||
if ($oMenuNode->IsEnabled())
|
if ($oMenuNode->IsEnabled())
|
||||||
@@ -269,11 +411,12 @@ EOF
|
|||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
* @param int $iActiveMenu
|
* @param int $iActiveMenu
|
||||||
*
|
*
|
||||||
* @return true if the currently selected menu is one of the submenus
|
* @return bool True if the currently selected menu is one of the submenus
|
||||||
* @throws DictExceptionMissingString
|
* @throws DictExceptionMissingString
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
* @deprecated Will be removed in 3.0.0, use static::GetSubMenuNodes() instead
|
||||||
*/
|
*/
|
||||||
static protected function DisplaySubMenu($oPage, $aMenus, $aExtraParams, $iActiveMenu = -1)
|
protected static function DisplaySubMenu($oPage, $aMenus, $aExtraParams, $iActiveMenu = -1)
|
||||||
{
|
{
|
||||||
// Sort the menu based on the rank
|
// Sort the menu based on the rank
|
||||||
$bActive = false;
|
$bActive = false;
|
||||||
@@ -330,11 +473,11 @@ EOF
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to sort the menus based on their rank
|
* Helper function to sort the menus based on their rank
|
||||||
* @param $a
|
* @param array $a
|
||||||
* @param $b
|
* @param array $b
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
static public function CompareOnRank($a, $b)
|
public static function CompareOnRank($a, $b)
|
||||||
{
|
{
|
||||||
$result = 1;
|
$result = 1;
|
||||||
if ($a['rank'] == $b['rank'])
|
if ($a['rank'] == $b['rank'])
|
||||||
@@ -353,7 +496,7 @@ EOF
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @return MenuNode|null
|
* @return MenuNode|null
|
||||||
*/
|
*/
|
||||||
static public function GetMenuNode($index)
|
public static function GetMenuNode($index)
|
||||||
{
|
{
|
||||||
return isset(self::$aMenusIndex[$index]) ? self::$aMenusIndex[$index]['node'] : null;
|
return isset(self::$aMenusIndex[$index]) ? self::$aMenusIndex[$index]['node'] : null;
|
||||||
}
|
}
|
||||||
@@ -363,7 +506,7 @@ EOF
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
static public function GetChildren($index)
|
public static function GetChildren($index)
|
||||||
{
|
{
|
||||||
return self::$aMenusIndex[$index]['children'];
|
return self::$aMenusIndex[$index]['children'];
|
||||||
}
|
}
|
||||||
@@ -373,7 +516,7 @@ EOF
|
|||||||
* @param string $sTitle Title of the menu (as passed when creating the menu)
|
* @param string $sTitle Title of the menu (as passed when creating the menu)
|
||||||
* @return integer ID of the menu, or -1 if not found
|
* @return integer ID of the menu, or -1 if not found
|
||||||
*/
|
*/
|
||||||
static public function GetMenuIndexById($sTitle)
|
public static function GetMenuIndexById($sTitle)
|
||||||
{
|
{
|
||||||
$index = -1;
|
$index = -1;
|
||||||
/** @var MenuNode[] $aMenu */
|
/** @var MenuNode[] $aMenu */
|
||||||
@@ -392,7 +535,7 @@ EOF
|
|||||||
* Retrieves the currently active menu (if any, otherwise the first menu is the default)
|
* Retrieves the currently active menu (if any, otherwise the first menu is the default)
|
||||||
* @return string The Id of the currently active menu
|
* @return string The Id of the currently active menu
|
||||||
*/
|
*/
|
||||||
static public function GetActiveNodeId()
|
public static function GetActiveNodeId()
|
||||||
{
|
{
|
||||||
$oAppContext = new ApplicationContext();
|
$oAppContext = new ApplicationContext();
|
||||||
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
|
$sMenuId = $oAppContext->GetCurrentValue('menu', null);
|
||||||
@@ -406,7 +549,7 @@ EOF
|
|||||||
/**
|
/**
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
static public function GetDefaultMenuId()
|
public static function GetDefaultMenuId()
|
||||||
{
|
{
|
||||||
static $sDefaultMenuId = null;
|
static $sDefaultMenuId = null;
|
||||||
if (is_null($sDefaultMenuId))
|
if (is_null($sDefaultMenuId))
|
||||||
@@ -426,7 +569,7 @@ EOF
|
|||||||
* @param $sMenuId
|
* @param $sMenuId
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
static public function GetRootMenuId($sMenuId)
|
public static function GetRootMenuId($sMenuId)
|
||||||
{
|
{
|
||||||
$iMenuIndex = self::GetMenuIndexById($sMenuId);
|
$iMenuIndex = self::GetMenuIndexById($sMenuId);
|
||||||
if ($iMenuIndex == -1)
|
if ($iMenuIndex == -1)
|
||||||
@@ -563,29 +706,45 @@ abstract class MenuNode
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
* @throws DictExceptionMissingString
|
|
||||||
*/
|
*/
|
||||||
public function GetTitle()
|
public function GetTitle()
|
||||||
{
|
{
|
||||||
return Dict::S("Menu:$this->sMenuId", str_replace('_', ' ', $this->sMenuId));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* @return string
|
||||||
* @throws DictExceptionMissingString
|
|
||||||
*/
|
*/
|
||||||
public function GetLabel()
|
public function GetLabel()
|
||||||
{
|
{
|
||||||
$sRet = Dict::S("Menu:$this->sMenuId+", "");
|
$sRet = Dict::S("Menu:$this->sMenuId+", "");
|
||||||
if ($sRet === '')
|
if ($sRet === '') {
|
||||||
{
|
if ($this->iParentIndex != -1) {
|
||||||
if ($this->iParentIndex != -1)
|
|
||||||
{
|
|
||||||
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
||||||
$sRet = $oParentMenu->GetTitle().' / '.$this->GetTitle();
|
$sRet = $oParentMenu->GetTitle().' / '.$this->GetTitle();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sRet = $this->GetTitle();
|
$sRet = $this->GetTitle();
|
||||||
}
|
}
|
||||||
//$sRet = $this->GetTitle();
|
//$sRet = $this->GetTitle();
|
||||||
@@ -600,7 +759,10 @@ abstract class MenuNode
|
|||||||
{
|
{
|
||||||
return $this->index;
|
return $this->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function PopulateChildMenus()
|
public function PopulateChildMenus()
|
||||||
{
|
{
|
||||||
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu)
|
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu)
|
||||||
@@ -725,18 +887,64 @@ abstract class MenuNode
|
|||||||
*/
|
*/
|
||||||
class MenuGroup extends 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
|
* 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 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 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 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 $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 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
|
* @param string $sEnableStimulus
|
||||||
*/
|
*/
|
||||||
public function __construct($sMenuId, $fRank, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
|
public function __construct($sMenuId, $fRank, $sDecorationClasses = null, $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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -913,30 +1121,51 @@ class OQLMenuNode extends MenuNode
|
|||||||
{
|
{
|
||||||
$sUsageId = utils::GetSafeId($sUsageId);
|
$sUsageId = utils::GetSafeId($sUsageId);
|
||||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||||
$sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
|
//$sIcon = MetaModel::GetClassIcon($oSearch->GetClass(), false);
|
||||||
|
|
||||||
if ($bSearchPane)
|
if ($bSearchPane) {
|
||||||
{
|
|
||||||
$aParams = array_merge(array('open' => $bSearchOpen, 'table_id' => $sUsageId), $aExtraParams);
|
$aParams = array_merge(array('open' => $bSearchOpen, 'table_id' => $sUsageId), $aExtraParams);
|
||||||
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
||||||
$oBlock->Display($oPage, 0);
|
$oBlock->Display($oPage, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPage->add("<p class=\"page-header\">$sIcon ".utils::HtmlEntities(Dict::S($sTitle))."</p>");
|
//$oPage->add("<p class=\"page-header\">$sIcon ".utils::HtmlEntities(Dict::S($sTitle))."</p>");
|
||||||
|
$oPage->add("<div class='sf_results_area'>");
|
||||||
|
$oTitle = TitleFactory::MakeForPage($sTitle);
|
||||||
|
$oPage->AddUiBlock($oTitle);
|
||||||
|
|
||||||
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
|
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
|
||||||
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
|
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
|
||||||
$oBlock->Display($oPage, $sUsageId);
|
$oBlock->Display($oPage, $sUsageId);
|
||||||
|
|
||||||
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage))
|
$oPage->add("</div>");
|
||||||
{
|
|
||||||
|
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage)) {
|
||||||
// Breadcrumb
|
// Breadcrumb
|
||||||
//$iCount = $oBlock->GetDisplayedCount();
|
//$iCount = $oBlock->GetDisplayedCount();
|
||||||
$sPageId = "ui-search-".$oSearch->GetClass();
|
$sPageId = "ui-search-".$oSearch->GetClass();
|
||||||
$sLabel = MetaModel::GetName($oSearch->GetClass());
|
$sLabel = MetaModel::GetName($oSearch->GetClass());
|
||||||
$oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', '../images/breadcrumb-search.png');
|
$oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', 'fas fa-list', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function HasCount()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetEntriesCount()
|
||||||
|
{
|
||||||
|
// Count the entries up to 99
|
||||||
|
|
||||||
|
$oSet = new DBObjectSet(DBSearch::FromOQL($this->sOQL));
|
||||||
|
$iCount = $oSet->CountWithLimit(99);
|
||||||
|
if ($iCount > 99) {
|
||||||
|
$iCount = "99+";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $iCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -981,7 +1210,7 @@ class SearchMenuNode extends MenuNode
|
|||||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
|
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
|
||||||
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png');
|
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||||
|
|
||||||
$oSearch = new DBObjectSearch($this->sClass);
|
$oSearch = new DBObjectSearch($this->sClass);
|
||||||
$aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
|
$aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
|
||||||
@@ -1191,7 +1420,7 @@ class DashboardMenuNode extends MenuNode
|
|||||||
if ($oDashboard != null)
|
if ($oDashboard != null)
|
||||||
{
|
{
|
||||||
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
|
||||||
$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
|
$oPage->add('<div class="ibo-dashboard" id="'.$sDivId.'">');
|
||||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||||
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
||||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||||
@@ -1218,13 +1447,13 @@ class DashboardMenuNode extends MenuNode
|
|||||||
}
|
}
|
||||||
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId())
|
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId())
|
||||||
{
|
{
|
||||||
$sIcon = '../images/breadcrumb_home.png';
|
$sIcon = 'fas fa-home';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sIcon = '../images/breadcrumb-dashboard.png';
|
$sIcon = 'fas fa-chart-pie';
|
||||||
}
|
}
|
||||||
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon);
|
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,262 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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,248 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2019 Combodo SARL
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ abstract class Query extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_query",
|
"db_table" => "priv_query",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -72,7 +71,6 @@ class QueryOQL extends Query
|
|||||||
"db_table" => "priv_query_oql",
|
"db_table" => "priv_query_oql",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +40,6 @@ abstract class Shortcut extends DBObject implements iDisplay
|
|||||||
"db_table" => "priv_shortcut",
|
"db_table" => "priv_shortcut",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -161,7 +161,6 @@ class ShortcutOQL extends Shortcut
|
|||||||
"db_table" => "priv_shortcut_oql",
|
"db_table" => "priv_shortcut_oql",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
/**
|
/**
|
||||||
* This class manages the special template format used internally to build the iTop web pages
|
* This class manages the special template format used internally to build the iTop web pages
|
||||||
|
*
|
||||||
|
* @deprecated Since 3.0.0
|
||||||
*/
|
*/
|
||||||
class DisplayTemplate
|
class DisplayTemplate
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,15 @@
|
|||||||
*/
|
*/
|
||||||
class ThemeHandler
|
class ThemeHandler
|
||||||
{
|
{
|
||||||
|
const IMAGE_EXTENSIONS = ['png', 'gif', 'jpg', 'jpeg'];
|
||||||
|
|
||||||
|
private static $oCompileCSSService;
|
||||||
|
|
||||||
|
public static function GetAppRootWithSlashes()
|
||||||
|
{
|
||||||
|
return str_replace('\\', '/', APPROOT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return default theme name and parameters
|
* Return default theme name and parameters
|
||||||
*
|
*
|
||||||
@@ -33,19 +42,19 @@ class ThemeHandler
|
|||||||
*/
|
*/
|
||||||
public static function GetDefaultThemeInformation()
|
public static function GetDefaultThemeInformation()
|
||||||
{
|
{
|
||||||
return array(
|
return [
|
||||||
'name' => 'light-grey',
|
'name' => 'light-grey',
|
||||||
'parameters' => array(
|
'parameters' => [
|
||||||
'variables' => array(),
|
'variables' => [],
|
||||||
'imports' => array(
|
'imports' => [
|
||||||
'css-variables' => '../css/css-variables.scss',
|
'css-variables' => '../css/css-variables.scss',
|
||||||
),
|
],
|
||||||
'stylesheets' => array(
|
'stylesheets' => [
|
||||||
'jqueryui' => '../css/ui-lightness/jqueryui.scss',
|
'jqueryui' => '../css/ui-lightness/jqueryui.scss',
|
||||||
'main' => '../css/light-grey.scss',
|
'main' => '../css/light-grey.scss',
|
||||||
),
|
],
|
||||||
),
|
],
|
||||||
);
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,37 +121,49 @@ class ThemeHandler
|
|||||||
SetupUtils::builddir($sDefaultThemeDirPath);
|
SetupUtils::builddir($sDefaultThemeDirPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static::CompileTheme($sThemeId, $aDefaultTheme['parameters']);
|
static::CompileTheme($sThemeId, false, "", $aDefaultTheme['parameters']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return absolute url to theme compiled css
|
// Return absolute url to theme compiled css
|
||||||
return utils::GetAbsoluteUrlModulesRoot().'/branding/themes/'.$sThemeId.'/main.css';
|
return utils::GetAbsoluteUrlModulesRoot().'branding/themes/'.$sThemeId.'/main.css';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the $sThemeId theme
|
* Compile the $sThemeId theme, the actual compilation is skipped when either
|
||||||
|
* 1) The produced CSS file exists and is more recent than any of its components (imports, stylesheets)
|
||||||
|
* 2) The produced CSS file exists and its signature is equal to the expected signature (imports, stylesheets, variables)
|
||||||
*
|
*
|
||||||
* @param string $sThemeId
|
* @param string $sThemeId
|
||||||
|
* @param boolean $bSetup
|
||||||
|
* @param string $sSetupCompilationTimestamp : setup compilation timestamp in micro secunds
|
||||||
* @param array|null $aThemeParameters Parameters (variables, imports, stylesheets) for the theme, if not passed, will be retrieved from compiled DM
|
* @param array|null $aThemeParameters Parameters (variables, imports, stylesheets) for the theme, if not passed, will be retrieved from compiled DM
|
||||||
* @param array|null $aImportsPaths Paths where imports can be found. Must end with '/'
|
* @param array|null $aImportsPaths Paths where imports can be found. Must end with '/'
|
||||||
* @param string|null $sWorkingPath Path of the folder used during compilation. Must end with a '/'
|
* @param string|null $sWorkingPath Path of the folder used during compilation. Must end with a '/'
|
||||||
*
|
*
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
|
* @return boolean: indicate whether theme compilation occured
|
||||||
*/
|
*/
|
||||||
public static function CompileTheme($sThemeId, $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
|
public static function CompileTheme($sThemeId, $bSetup=false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
|
||||||
{
|
{
|
||||||
|
if ($sSetupCompilationTimestamp==="")
|
||||||
|
{
|
||||||
|
$sSetupCompilationTimestamp = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !==false) ? explode('.', $sSetupCompilationTimestamp)[0] : $sSetupCompilationTimestamp;
|
||||||
|
|
||||||
|
$sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
|
||||||
|
|
||||||
// Default working path
|
// Default working path
|
||||||
if($sWorkingPath === null)
|
if($sWorkingPath === null)
|
||||||
{
|
{
|
||||||
$sWorkingPath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
|
$sWorkingPath = $sEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default import paths (env-*)
|
// Default import paths (env-*)
|
||||||
if($aImportsPaths === null)
|
if($aImportsPaths === null)
|
||||||
{
|
{
|
||||||
$aImportsPaths = array(
|
$aImportsPaths = [ $sEnv];
|
||||||
APPROOT.'env-'.utils::GetCurrentEnvironment().'/',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We do NOT check that the folder exists!
|
// Note: We do NOT check that the folder exists!
|
||||||
@@ -152,6 +173,11 @@ class ThemeHandler
|
|||||||
// Save parameters if passed... (typically during DM compilation)
|
// Save parameters if passed... (typically during DM compilation)
|
||||||
if(is_array($aThemeParameters))
|
if(is_array($aThemeParameters))
|
||||||
{
|
{
|
||||||
|
if (!is_dir($sThemeFolderPath))
|
||||||
|
{
|
||||||
|
mkdir($sWorkingPath.'/branding/');
|
||||||
|
mkdir($sWorkingPath.'/branding/themes/');
|
||||||
|
}
|
||||||
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
||||||
}
|
}
|
||||||
// ... Otherwise, retrieve them from compiled DM (typically when switching current theme in the config. file)
|
// ... Otherwise, retrieve them from compiled DM (typically when switching current theme in the config. file)
|
||||||
@@ -164,31 +190,588 @@ class ThemeHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$aThemeParametersWithVersion = self::CloneThemeParameterAndIncludeVersion($aThemeParameters, $sSetupCompilationTimestampInSecunds);
|
||||||
|
|
||||||
$sTmpThemeScssContent = '';
|
$sTmpThemeScssContent = '';
|
||||||
$iStyleLastModified = 0;
|
$iStyleLastModified = 0;
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
// Loading files to import and stylesheet to compile, also getting most recent modification time on overall files
|
// Loading files to import and stylesheet to compile, also getting most recent modification time on overall files
|
||||||
|
|
||||||
|
$aStylesheetFiles = [];
|
||||||
foreach ($aThemeParameters['imports'] as $sImport)
|
foreach ($aThemeParameters['imports'] as $sImport)
|
||||||
{
|
{
|
||||||
$sTmpThemeScssContent .= '@import "'.$sImport.'";'."\n";
|
$sTmpThemeScssContent .= '@import "'.$sImport.'";'."\n";
|
||||||
|
|
||||||
$iImportLastModified = @filemtime($sWorkingPath.$sImport);
|
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
|
||||||
|
$iImportLastModified = @filemtime($sFile);
|
||||||
|
$aStylesheetFiles[] = $sFile;
|
||||||
$iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified;
|
$iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified;
|
||||||
}
|
}
|
||||||
foreach ($aThemeParameters['stylesheets'] as $sStylesheet)
|
foreach ($aThemeParameters['stylesheets'] as $sStylesheet)
|
||||||
{
|
{
|
||||||
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
|
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
|
||||||
|
|
||||||
$iStylesheetLastModified = @filemtime($sWorkingPath.$sStylesheet);
|
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
|
||||||
|
$iStylesheetLastModified = @filemtime($sFile);
|
||||||
|
$aStylesheetFiles[] = $sFile;
|
||||||
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
|
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checking if our compiled css is outdated
|
$aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $aStylesheetFiles, $sThemeId);
|
||||||
if (!file_exists($sThemeCssPath) || (is_writable($sThemeFolderPath) && (@filemtime($sThemeCssPath) < $iStyleLastModified)))
|
foreach ($aIncludedImages as $sImage)
|
||||||
{
|
{
|
||||||
$sTmpThemeCssContent = utils::CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, $aThemeParameters['variables']);
|
if (is_file($sImage))
|
||||||
file_put_contents($sThemeCssPath, $sTmpThemeCssContent);
|
{
|
||||||
|
$iStylesheetLastModified = @filemtime($sImage);
|
||||||
|
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checking if our compiled css is outdated
|
||||||
|
$iFilemetime = @filemtime($sThemeCssPath);
|
||||||
|
$bFileExists = file_exists($sThemeCssPath);
|
||||||
|
$bVarSignatureChanged=false;
|
||||||
|
if ($bFileExists && $bSetup)
|
||||||
|
{
|
||||||
|
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
|
||||||
|
//check variable signature has changed which is independant from any file modification
|
||||||
|
if (!empty($sPrecompiledSignature)){
|
||||||
|
$sPreviousVariableSignature = static::GetVarSignature($sPrecompiledSignature);
|
||||||
|
$sCurrentVariableSignature = md5(json_encode($aThemeParameters['variables']));
|
||||||
|
$bVarSignatureChanged= ($sPreviousVariableSignature!==$sCurrentVariableSignature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$bFileExists || $bVarSignatureChanged || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified)))
|
||||||
|
{
|
||||||
|
// Dates don't match. Second chance: check if the already compiled stylesheet exists and is consistent based on its signature
|
||||||
|
$sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages);
|
||||||
|
|
||||||
|
if ($bFileExists && !$bSetup)
|
||||||
|
{
|
||||||
|
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($sPrecompiledSignature) && $sActualSignature == $sPrecompiledSignature)
|
||||||
|
{
|
||||||
|
touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Alas, we really need to recompile
|
||||||
|
// Add the signature to the generated CSS file so that the file can be used as a precompiled stylesheet if needed
|
||||||
|
$sSignatureComment =
|
||||||
|
<<<CSS
|
||||||
|
/*
|
||||||
|
=== SIGNATURE BEGIN ===
|
||||||
|
$sActualSignature
|
||||||
|
=== SIGNATURE END ===
|
||||||
|
*/
|
||||||
|
|
||||||
|
CSS;
|
||||||
|
if (!static::$oCompileCSSService)
|
||||||
|
{
|
||||||
|
static::$oCompileCSSService = new CompileCSSService();
|
||||||
|
}
|
||||||
|
//store it again to change $version with latest compiled time
|
||||||
|
$sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths,
|
||||||
|
$aThemeParametersWithVersion);
|
||||||
|
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
||||||
|
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
|
||||||
|
SetupLog::Info("Theme $sThemeId file compiled.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the signature of a theme defined by its theme parameters. The signature is a JSON structure of
|
||||||
|
* 1) one MD5 of all the variables/values (JSON encoded)
|
||||||
|
* 2) the MD5 of each stylesheet file
|
||||||
|
* 3) the MD5 of each import file
|
||||||
|
* 3) the MD5 of each images referenced in style sheets
|
||||||
|
*
|
||||||
|
* @param string[] $aThemeParameters
|
||||||
|
* @param string[] $aImportsPaths
|
||||||
|
* @param string[] $aIncludedImages
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages)
|
||||||
|
{
|
||||||
|
$aSignature = [
|
||||||
|
'variables' => md5(json_encode($aThemeParameters['variables'])),
|
||||||
|
'stylesheets' => [],
|
||||||
|
'imports' => [],
|
||||||
|
'images' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($aThemeParameters['imports'] as $key => $sImport)
|
||||||
|
{
|
||||||
|
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
|
||||||
|
$aSignature['stylesheets'][$key] = md5_file($sFile);
|
||||||
|
}
|
||||||
|
foreach ($aThemeParameters['stylesheets'] as $key => $sStylesheet)
|
||||||
|
{
|
||||||
|
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
|
||||||
|
$aSignature['stylesheets'][$key] = md5_file($sFile);
|
||||||
|
}
|
||||||
|
foreach ($aIncludedImages as $sImage)
|
||||||
|
{
|
||||||
|
if (is_file($sImage)) {
|
||||||
|
$sUri = str_replace(self::GetAppRootWithSlashes(), '', $sImage);
|
||||||
|
$aSignature['images'][$sUri] = md5_file($sImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($aSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for images referenced in stylesheet files
|
||||||
|
*
|
||||||
|
* @param array $aThemeParametersVariables
|
||||||
|
* @param array $aStylesheetFiles
|
||||||
|
* @param string $sThemeId : used only for logging purpose
|
||||||
|
*
|
||||||
|
* @return array complete path of the images, but with slashes as dir separator instead of DIRECTORY_SEPARATOR
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetIncludedImages($aThemeParametersVariables, $aStylesheetFiles, $sThemeId)
|
||||||
|
{
|
||||||
|
$sTargetThemeFolderPath = static::GetCompiledThemeFolderAbsolutePath($sThemeId);
|
||||||
|
|
||||||
|
$aCompleteUrls = [];
|
||||||
|
$aToCompleteUrls = [];
|
||||||
|
$aMissingVariables = [];
|
||||||
|
$aFoundVariables = ['version'=>''];
|
||||||
|
$aMap = [
|
||||||
|
'aCompleteUrls' => $aCompleteUrls,
|
||||||
|
'aToCompleteUrls' => $aToCompleteUrls,
|
||||||
|
'aMissingVariables' => $aMissingVariables,
|
||||||
|
'aFoundVariables' => $aFoundVariables,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($aStylesheetFiles as $sStylesheetFile)
|
||||||
|
{
|
||||||
|
$aRes = static::GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile);
|
||||||
|
/** @var array $aVal */
|
||||||
|
foreach($aMap as $key => $aVal)
|
||||||
|
{
|
||||||
|
if (array_key_exists($key, $aMap))
|
||||||
|
{
|
||||||
|
$aMap[$key] = array_merge($aVal, $aRes[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aMap = static::ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFiles);
|
||||||
|
$aImages = [];
|
||||||
|
|
||||||
|
foreach ($aMap ['aCompleteUrls'] as $sUri => $sUrl)
|
||||||
|
{
|
||||||
|
$sImg = $sUrl;
|
||||||
|
if (preg_match("/(.*)\?/", $sUrl, $aMatches))
|
||||||
|
{
|
||||||
|
$sImg=$aMatches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static::HasImageExtension($sImg)
|
||||||
|
&& ! array_key_exists($sImg, $aImages))
|
||||||
|
{
|
||||||
|
$sFilePath = realpath($sImg);
|
||||||
|
if ($sFilePath !== false) {
|
||||||
|
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
|
||||||
|
$aImages[$sImg] = $sFilePathWithSlashes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sCanonicalPath = static::CanonicalizePath($sTargetThemeFolderPath.'/'.$sImg);
|
||||||
|
$sFilePath = realpath($sCanonicalPath);
|
||||||
|
if ($sFilePath !== false) {
|
||||||
|
$sFilePathWithSlashes = str_replace('\\', '/', $sFilePath);
|
||||||
|
$aImages[$sImg] = $sFilePathWithSlashes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupLog::Warning("Cannot find $sCanonicalPath ($sImg) during SCSS $sThemeId precompilation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($aImages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce path without using realpath (works only when file exists)
|
||||||
|
* @param $path
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function CanonicalizePath($path)
|
||||||
|
{
|
||||||
|
$path = explode('/', str_replace('//','/', $path));
|
||||||
|
$stack = array();
|
||||||
|
foreach ($path as $seg) {
|
||||||
|
if ($seg == '..') {
|
||||||
|
// Ignore this segment, remove last segment from stack
|
||||||
|
array_pop($stack);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($seg == '.') {
|
||||||
|
// Ignore this segment
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stack[] = $seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode('/', $stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete url using provided variables. Example with $var=1: XX + $var => XX1
|
||||||
|
* @param $aMap
|
||||||
|
* @param $aThemeParametersVariables
|
||||||
|
* @param $aStylesheetFile
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFile)
|
||||||
|
{
|
||||||
|
$sContent="";
|
||||||
|
foreach ($aStylesheetFile as $sStylesheetFile)
|
||||||
|
{
|
||||||
|
if (is_file($sStylesheetFile))
|
||||||
|
{
|
||||||
|
$sContent .= '\n' . file_get_contents($sStylesheetFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aMissingVariables=$aMap['aMissingVariables'];
|
||||||
|
$aFoundVariables=$aMap['aFoundVariables'];
|
||||||
|
$aToCompleteUrls=$aMap['aToCompleteUrls'];
|
||||||
|
$aCompleteUrls=$aMap['aCompleteUrls'];
|
||||||
|
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, true);
|
||||||
|
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
|
||||||
|
$aMap['aMissingVariables']=$aMissingVariables;
|
||||||
|
$aMap['aFoundVariables']=$aFoundVariables;
|
||||||
|
$aMap['aToCompleteUrls']=$aToCompleteUrls;
|
||||||
|
$aMap['aCompleteUrls']=$aCompleteUrls;
|
||||||
|
return $aMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find missing variable values from SCSS content based on their name.
|
||||||
|
*
|
||||||
|
* @param $aThemeParametersVariables
|
||||||
|
* @param $aMissingVariables
|
||||||
|
* @param $aFoundVariables
|
||||||
|
* @param $sContent : scss content
|
||||||
|
* @param bool $bForceEmptyValueWhenNotFound
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, $bForceEmptyValueWhenNotFound=false)
|
||||||
|
{
|
||||||
|
$aNewMissingVars = [];
|
||||||
|
if (!empty($aMissingVariables))
|
||||||
|
{
|
||||||
|
foreach ($aMissingVariables as $var)
|
||||||
|
{
|
||||||
|
if (array_key_exists($var, $aThemeParametersVariables))
|
||||||
|
{
|
||||||
|
$aFoundVariables[$var] = $aThemeParametersVariables[$var];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (preg_match_all("/\\\$$var\s*:\s*[\"']{0,1}(.*)[\"']{0,1};/", $sContent, $aValues))
|
||||||
|
{
|
||||||
|
$sValue = $aValues[1][0];
|
||||||
|
if (preg_match_all("/([^!]+)!/", $sValue, $aSubValues))
|
||||||
|
{
|
||||||
|
$sValue = trim($aSubValues[1][0], ' "\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($sValue, '$') === false)
|
||||||
|
{
|
||||||
|
$aFoundVariables[$var] = $sValue;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$aNewMissingVars[] = $var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($bForceEmptyValueWhenNotFound)
|
||||||
|
{
|
||||||
|
$aFoundVariables[$var] = '';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aNewMissingVars[] = $var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [ $aNewMissingVars, $aFoundVariables ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $aFoundVariables
|
||||||
|
* @param array $aToCompleteUrls
|
||||||
|
* @param array $aCompleteUrls
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function ResolveUrls($aFoundVariables, array $aToCompleteUrls, array $aCompleteUrls)
|
||||||
|
{
|
||||||
|
if (!empty($aFoundVariables))
|
||||||
|
{
|
||||||
|
$aFoundVariablesWithEmptyValue = [];
|
||||||
|
foreach ($aFoundVariables as $aFoundVariable => $sValue)
|
||||||
|
{
|
||||||
|
$aFoundVariablesWithEmptyValue[$aFoundVariable] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($aToCompleteUrls as $sUrlTemplate)
|
||||||
|
{
|
||||||
|
unset($aToCompleteUrls[$sUrlTemplate]);
|
||||||
|
$sResolvedUrl = static::ResolveUrl($sUrlTemplate, $aFoundVariables);
|
||||||
|
if ($sResolvedUrl == false)
|
||||||
|
{
|
||||||
|
$aToCompleteUrls[$sUrlTemplate] = $sUrlTemplate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sUri = static::ResolveUrl($sUrlTemplate, $aFoundVariablesWithEmptyValue);
|
||||||
|
$aExplodedUri = explode('?', $sUri);
|
||||||
|
if (empty($aExplodedUri))
|
||||||
|
{
|
||||||
|
$aCompleteUrls[$sUri] = $sResolvedUrl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aCompleteUrls[$aExplodedUri[0]] = $sResolvedUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [ $aToCompleteUrls, $aCompleteUrls];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all referenced URLs from a SCSS file.
|
||||||
|
* @param $aThemeParametersVariables
|
||||||
|
* @param $sStylesheetFile
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile)
|
||||||
|
{
|
||||||
|
$aCompleteUrls = [];
|
||||||
|
$aToCompleteUrls = [];
|
||||||
|
$aMissingVariables = [];
|
||||||
|
$aFoundVariables = [];
|
||||||
|
|
||||||
|
if (is_file($sStylesheetFile))
|
||||||
|
{
|
||||||
|
$sContent = file_get_contents($sStylesheetFile);
|
||||||
|
if (preg_match_all("/url\s*\((.*)\)/", $sContent, $aMatches))
|
||||||
|
{
|
||||||
|
foreach ($aMatches[1] as $path)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($path, $aCompleteUrls)
|
||||||
|
&& !array_key_exists($path, $aToCompleteUrls))
|
||||||
|
{
|
||||||
|
if (preg_match_all("/\\$([\w\-_]+)/", $path, $aCurrentVars))
|
||||||
|
{
|
||||||
|
/** @var string $aCurrentVars */
|
||||||
|
foreach ($aCurrentVars[1] as $var)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($var, $aMissingVariables))
|
||||||
|
{
|
||||||
|
$aMissingVariables[$var] = $var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aToCompleteUrls[$path] = $path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aCompleteUrls[$path] = trim($path, "\"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($aMissingVariables))
|
||||||
|
{
|
||||||
|
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent);
|
||||||
|
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'aCompleteUrls' => $aCompleteUrls,
|
||||||
|
'aToCompleteUrls' => $aToCompleteUrls,
|
||||||
|
'aMissingVariables' => $aMissingVariables,
|
||||||
|
'aFoundVariables' => $aFoundVariables
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate url based on its template + variables.
|
||||||
|
* @param $sUrlTemplate
|
||||||
|
* @param $aFoundVariables
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public static function ResolveUrl($sUrlTemplate, $aFoundVariables)
|
||||||
|
{
|
||||||
|
$aPattern= [];
|
||||||
|
$aReplacement= [];
|
||||||
|
foreach ($aFoundVariables as $aFoundVariable => $aFoundVariableValue)
|
||||||
|
{
|
||||||
|
//XX + $key + YY
|
||||||
|
$aPattern[]="/['\"]\s*\+\s*\\\$" . $aFoundVariable . "[\s\+]+\s*['\"]/";
|
||||||
|
$aReplacement[]=$aFoundVariableValue;
|
||||||
|
//$key + YY
|
||||||
|
$aPattern[]="/\\\$" . $aFoundVariable. "[\s\+]+\s*['\"]/";
|
||||||
|
$aReplacement[]=$aFoundVariableValue;
|
||||||
|
//XX + $key
|
||||||
|
$aPattern[]="/['\"]\s*[\+\s]+\\\$" . $aFoundVariable . "$/";
|
||||||
|
$aReplacement[]=$aFoundVariableValue;
|
||||||
|
}
|
||||||
|
$sResolvedUrl=preg_replace($aPattern, $aReplacement, $sUrlTemplate);
|
||||||
|
if (strpos($sResolvedUrl, "+")!==false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return trim($sResolvedUrl, "\"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* indicate whether a string ends with image suffix.
|
||||||
|
* @param $path
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function HasImageExtension($path)
|
||||||
|
{
|
||||||
|
foreach (static::IMAGE_EXTENSIONS as $sExt)
|
||||||
|
{
|
||||||
|
if (endsWith($path, $sExt))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the signature for a generated CSS file. The signature MUST be alone one line immediately
|
||||||
|
* followed (on the next line) by the === SIGNATURE END === pattern
|
||||||
|
*
|
||||||
|
* Note the signature can be place anywhere in the CSS file (obviously inside a CSS comment !) but the
|
||||||
|
* function will be faster if the signature is at the beginning of the file (since the file is scanned from the start)
|
||||||
|
*
|
||||||
|
* @param $sFilepath
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function GetSignature($sFilepath)
|
||||||
|
{
|
||||||
|
$sPreviousLine = '';
|
||||||
|
$hFile = @fopen($sFilepath, "r");
|
||||||
|
if ($hFile !== false)
|
||||||
|
{
|
||||||
|
$sLine = '';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
$sPreviousLine = $sLine;
|
||||||
|
$sLine = rtrim(fgets($hFile)); // Remove the trailing \n
|
||||||
|
}
|
||||||
|
while (($sLine !== false) && ($sLine != '=== SIGNATURE END ==='));
|
||||||
|
fclose($hFile);
|
||||||
|
}
|
||||||
|
return $sPreviousLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetVarSignature($JsonSignature)
|
||||||
|
{
|
||||||
|
$aJsonArray = json_decode($JsonSignature, true);
|
||||||
|
if (array_key_exists('variables', $aJsonArray))
|
||||||
|
{
|
||||||
|
return $aJsonArray['variables'];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the given file in the list of ImportsPaths directory
|
||||||
|
* @param string $sFile
|
||||||
|
* @param string[] $aImportsPaths
|
||||||
|
* @throws Exception
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function FindStylesheetFile($sFile, $aImportsPaths)
|
||||||
|
{
|
||||||
|
foreach($aImportsPaths as $sPath)
|
||||||
|
{
|
||||||
|
$sImportedFile = realpath($sPath.'/'.$sFile);
|
||||||
|
if (file_exists($sImportedFile))
|
||||||
|
{
|
||||||
|
return $sImportedFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''; // Not found, fail silently, maybe the SCSS compiler knowns better...
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function MockCompileCSSService($oCompileCSSServiceMock)
|
||||||
|
{
|
||||||
|
static::$oCompileCSSService = $oCompileCSSServiceMock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone variable array and include $version with bSetupCompilationTimestamp value
|
||||||
|
* @param $aThemeParameters
|
||||||
|
* @param $bSetupCompilationTimestamp
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp)
|
||||||
|
{
|
||||||
|
$aThemeParametersVariable = [];
|
||||||
|
if (array_key_exists('variables', $aThemeParameters))
|
||||||
|
{
|
||||||
|
if (is_array($aThemeParameters['variables']))
|
||||||
|
{
|
||||||
|
$aThemeParametersVariable = array_merge([], $aThemeParameters['variables']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
|
||||||
|
return $aThemeParametersVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CompileCSSService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* CompileCSSService constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
||||||
|
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
|
||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,6 +67,7 @@ class UIExtKeyWidget
|
|||||||
protected $iId;
|
protected $iId;
|
||||||
protected $sTargetClass;
|
protected $sTargetClass;
|
||||||
protected $sAttCode;
|
protected $sAttCode;
|
||||||
|
//@deprecated
|
||||||
protected $bSearchMode;
|
protected $bSearchMode;
|
||||||
|
|
||||||
//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
|
//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
|
||||||
@@ -86,7 +86,29 @@ class UIExtKeyWidget
|
|||||||
$sDisplayStyle = 'select'; // In search mode, always use a drop-down list
|
$sDisplayStyle = 'select'; // In search mode, always use a drop-down list
|
||||||
}
|
}
|
||||||
$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode);
|
$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode);
|
||||||
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle);
|
if(!$bSearchMode)
|
||||||
|
{
|
||||||
|
switch($sDisplayStyle)
|
||||||
|
{
|
||||||
|
case 'radio':
|
||||||
|
case 'radio_horizontal':
|
||||||
|
case 'radio_vertical':
|
||||||
|
|
||||||
|
return $oWidget->DisplayRadio($oPage, $iMaxComboLength, $bAllowTargetCreation, $oAllowedValues, $value, $sFieldName, $sDisplayStyle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'select':
|
||||||
|
case 'list':
|
||||||
|
default:
|
||||||
|
return $oWidget->DisplaySelect($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value,
|
||||||
|
$bMandatory, $sFieldName, $sFormPrefix, $aArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($sTargetClass, $iInputId, $sAttCode = '', $bSearchMode = false)
|
public function __construct($sTargetClass, $iInputId, $sAttCode = '', $bSearchMode = false)
|
||||||
@@ -98,6 +120,291 @@ class UIExtKeyWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete
|
||||||
|
* Get the HTML fragment corresponding to the ext key editing widget
|
||||||
|
* @param WebPage $oP The web page used for all the output
|
||||||
|
* @param array $aArgs Extra context arguments
|
||||||
|
* @return string The HTML fragment to be inserted into the page
|
||||||
|
*/
|
||||||
|
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array())
|
||||||
|
{
|
||||||
|
$sTitle = addslashes($sTitle);
|
||||||
|
$oPage->add_linked_script('../js/extkeywidget.js');
|
||||||
|
$oPage->add_linked_script('../js/forms-json-utils.js');
|
||||||
|
|
||||||
|
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
|
||||||
|
$bExtensions = true;
|
||||||
|
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
|
$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
|
||||||
|
|
||||||
|
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey ibo-input-wrapper ibo-input-select-wrapper\" data-validation=\"untouched\">";
|
||||||
|
$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
|
||||||
|
if($this->bSearchMode)
|
||||||
|
{
|
||||||
|
$sWizHelper = 'null';
|
||||||
|
$sWizHelperJSON = "''";
|
||||||
|
$sJSSearchMode = 'true';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isset($aArgs['wizHelper']))
|
||||||
|
{
|
||||||
|
$sWizHelper = $aArgs['wizHelper'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
|
}
|
||||||
|
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
|
||||||
|
$sJSSearchMode = 'false';
|
||||||
|
}
|
||||||
|
if (is_null($oAllowedValues))
|
||||||
|
{
|
||||||
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
|
}
|
||||||
|
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
|
// Don't automatically launch the search if the table is huge
|
||||||
|
$bDoSearch = !utils::IsHighCardinality($this->sTargetClass);
|
||||||
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
|
|
||||||
|
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||||
|
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
|
||||||
|
{
|
||||||
|
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||||
|
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
|
||||||
|
//$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
||||||
|
$aOptions = [];
|
||||||
|
$sDisplayValue = "";
|
||||||
|
|
||||||
|
$aOption = [];
|
||||||
|
$aOption['value'] = "";
|
||||||
|
$aOption['label'] = Dict::S('UI:SelectOne');
|
||||||
|
array_push($aOptions,$aOption);
|
||||||
|
|
||||||
|
$oAllowedValues->Rewind();
|
||||||
|
$bAddingValue=false;
|
||||||
|
|
||||||
|
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($oAllowedValues->GetClass());
|
||||||
|
$sFormatAdditionalField = $aComplementAttributeSpec[0];
|
||||||
|
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||||
|
|
||||||
|
if (count($aAdditionalField)>0)
|
||||||
|
{
|
||||||
|
$bAddingValue=true;
|
||||||
|
}
|
||||||
|
while($oObj = $oAllowedValues->Fetch())
|
||||||
|
{
|
||||||
|
$aOption=[];
|
||||||
|
$aOption['value'] = $oObj->GetKey();
|
||||||
|
$aOption['label'] = $oObj->GetName();//.'<span class=\"object-ref-icon fas fa-eye-slash object-obsolete fa-1x fa-fw\"></span>';
|
||||||
|
|
||||||
|
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
|
||||||
|
{
|
||||||
|
// When there is only once choice, select it by default
|
||||||
|
$sDisplayValue=$oObj->GetName();
|
||||||
|
if($value != $oObj->GetKey())
|
||||||
|
{
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<EOF
|
||||||
|
$('#$this->iId').attr('data-validate','dependencies');
|
||||||
|
EOF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((is_array($value) && in_array($oObj->GetKey(), $value)) || ($value == $oObj->GetKey()))
|
||||||
|
{
|
||||||
|
$sDisplayValue=$oObj->GetKey();
|
||||||
|
// $sHTMLValue.="<div class='item' data-value='".$oObj->GetKey)."'>".$oObj->GetName()."</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($oObj->IsObsolete()){
|
||||||
|
$aOption['obsolescence_flag'] ="1";
|
||||||
|
}
|
||||||
|
if ($bAddingValue)
|
||||||
|
{
|
||||||
|
$aArguments = [];
|
||||||
|
foreach ($aAdditionalField as $sAdditionalField)
|
||||||
|
{
|
||||||
|
array_push($aArguments,$oObj->Get($sAdditionalField));
|
||||||
|
}
|
||||||
|
$aOption['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
||||||
|
}
|
||||||
|
array_push($aOptions,$aOption);
|
||||||
|
}
|
||||||
|
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\"></select>";
|
||||||
|
$sJsonOptions=json_encode($aOptions);
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<EOF
|
||||||
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
|
oACWidget_{$this->iId}.AddSelectize('$sJsonOptions','$sDisplayValue');
|
||||||
|
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||||
|
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
|
||||||
|
|
||||||
|
EOF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Too many choices, use an autocomplete
|
||||||
|
// Check that the given value is allowed
|
||||||
|
$oSearch = $oAllowedValues->GetFilter();
|
||||||
|
$oSearch->AddCondition('id', $value);
|
||||||
|
$oSet = new DBObjectSet($oSearch);
|
||||||
|
if ($oSet->Count() == 0)
|
||||||
|
{
|
||||||
|
$value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
|
||||||
|
{
|
||||||
|
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sDisplayValue = $this->GetObjectName($value);
|
||||||
|
}
|
||||||
|
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
||||||
|
|
||||||
|
// the input for the auto-complete
|
||||||
|
$sHTMLValue .= "<input class=\"field_autocomplete ibo-input ibo-input-select ibo-input-select-autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
||||||
|
$sHTMLValue .= "<div class=\"field_input_btn ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div>";
|
||||||
|
|
||||||
|
// another hidden input to store & pass the object's Id
|
||||||
|
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||||
|
|
||||||
|
$JSSearchMode = $this->bSearchMode ? 'true' : 'false';
|
||||||
|
// Scripts to start the autocomplete and bind some events to it
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<EOF
|
||||||
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
|
oACWidget_{$this->iId}.AddAutocomplete($iMinChars, $sWizHelperJSON);
|
||||||
|
if ($('#ac_dlg_{$this->iId}').length == 0)
|
||||||
|
{
|
||||||
|
$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
||||||
|
{
|
||||||
|
$sHTMLValue .= "<div class=\"field_input_btn ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div>";
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<JS
|
||||||
|
if ($('#ac_tree_{$this->iId}').length == 0)
|
||||||
|
{
|
||||||
|
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
|
||||||
|
}
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($bCreate && $bExtensions)
|
||||||
|
{
|
||||||
|
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
||||||
|
|
||||||
|
$sHTMLValue .= "<div class=\"field_input_btn ibo-input-select--action-button ibo-input-select--action-button--create\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div>";
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<JS
|
||||||
|
if ($('#ajax_{$this->iId}').length == 0)
|
||||||
|
{
|
||||||
|
$('body').append('<div id="ajax_{$this->iId}"></div>');
|
||||||
|
}
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$sHTMLValue .= "</div>";
|
||||||
|
$sHTMLValue .= "<span class=\"form_validation ibo-field-validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
||||||
|
|
||||||
|
return $sHTMLValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete
|
||||||
|
* Get the HTML fragment corresponding to the ext key editing widget
|
||||||
|
* @param WebPage $oP The web page used for all the output
|
||||||
|
* @param array $aArgs Extra context arguments
|
||||||
|
* @return string The HTML fragment to be inserted into the page
|
||||||
|
*/
|
||||||
|
public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle)
|
||||||
|
{
|
||||||
|
$oPage->add_linked_script('../js/forms-json-utils.js');
|
||||||
|
|
||||||
|
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
|
||||||
|
$bExtensions = true;
|
||||||
|
$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
|
||||||
|
|
||||||
|
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
|
||||||
|
|
||||||
|
if (is_null($oAllowedValues))
|
||||||
|
{
|
||||||
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
|
}
|
||||||
|
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
|
|
||||||
|
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||||
|
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
|
||||||
|
{
|
||||||
|
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||||
|
$sValidationField = null;
|
||||||
|
|
||||||
|
$bVertical = ($sDisplayStyle != 'radio_horizontal');
|
||||||
|
$bExtensions = false;
|
||||||
|
$oAllowedValues->Rewind();
|
||||||
|
$aAllowedValues = array();
|
||||||
|
while($oObj = $oAllowedValues->Fetch())
|
||||||
|
{
|
||||||
|
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
|
||||||
|
}
|
||||||
|
$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField);
|
||||||
|
$aEventsList[] ='change';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sHTMLValue .= "unable to display. Too much values";
|
||||||
|
}
|
||||||
|
$sHTMLValue .= '<div class="ibo-input-select--action-buttons">';
|
||||||
|
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
||||||
|
{
|
||||||
|
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<JS
|
||||||
|
if ($('#ac_tree_{$this->iId}').length == 0)
|
||||||
|
{
|
||||||
|
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
|
||||||
|
}
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($bCreate && $bExtensions)
|
||||||
|
{
|
||||||
|
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
||||||
|
|
||||||
|
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
|
||||||
|
$oPage->add_ready_script(
|
||||||
|
<<<JS
|
||||||
|
if ($('#ajax_{$this->iId}').length == 0)
|
||||||
|
{
|
||||||
|
$('body').append('<div id="ajax_{$this->iId}"></div>');
|
||||||
|
}
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$sHTMLValue .= "</div>";
|
||||||
|
$sHTMLValue .= "</div>";
|
||||||
|
|
||||||
|
// Note: This test is no longer necessary as we changed the markup to extract validation decoration in the standard .field_input_xxx container
|
||||||
|
//if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
|
||||||
|
//{
|
||||||
|
$sHTMLValue .= "<span class=\"form_validation ibo-field-validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
||||||
|
//}
|
||||||
|
|
||||||
|
return $sHTMLValue;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated Use DisplayBob
|
||||||
* Get the HTML fragment corresponding to the ext key editing widget
|
* Get the HTML fragment corresponding to the ext key editing widget
|
||||||
* @param WebPage $oP The web page used for all the output
|
* @param WebPage $oP The web page used for all the output
|
||||||
* @param array $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
@@ -239,7 +546,7 @@ EOF
|
|||||||
$oPage->add_ready_script("$('.multiselect').multiselect($sJSOptions);");
|
$oPage->add_ready_script("$('.multiselect').multiselect($sJSOptions);");
|
||||||
}
|
}
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||||
@@ -269,10 +576,10 @@ EOF
|
|||||||
{
|
{
|
||||||
$sDisplayValue = $this->GetObjectName($value);
|
$sDisplayValue = $this->GetObjectName($value);
|
||||||
}
|
}
|
||||||
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 3; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
||||||
|
|
||||||
// the input for the auto-complete
|
// the input for the auto-complete
|
||||||
$sHTMLValue .= "<input class=\"field_autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
$sHTMLValue .= "<input class=\"field_autocomplete ibo-input-select\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
||||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
|
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
|
||||||
|
|
||||||
// another hidden input to store & pass the object's Id
|
// another hidden input to store & pass the object's Id
|
||||||
@@ -281,106 +588,100 @@ EOF
|
|||||||
$JSSearchMode = $this->bSearchMode ? 'true' : 'false';
|
$JSSearchMode = $this->bSearchMode ? 'true' : 'false';
|
||||||
// Scripts to start the autocomplete and bind some events to it
|
// Scripts to start the autocomplete and bind some events to it
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
$('#label_$this->iId').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'$sFilter',bSearchMode:$JSSearchMode, json: function() { return $sWizHelperJSON; } }});
|
oACWidget_{$this->iId}.AddAutocomplete($iMinChars, $sWizHelperJSON);
|
||||||
$('#label_$this->iId').keyup(function() { if ($(this).val() == '') { $('#$this->iId').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
|
|
||||||
$('#label_$this->iId').result( function(event, data, formatted) { OnAutoComplete('{$this->iId}', event, data, formatted); } );
|
|
||||||
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
|
||||||
if ($('#ac_dlg_{$this->iId}').length == 0)
|
if ($('#ac_dlg_{$this->iId}').length == 0)
|
||||||
{
|
{
|
||||||
$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
|
$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
||||||
{
|
{
|
||||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
|
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"ibo-input-select--action-button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<JS
|
||||||
if ($('#ac_tree_{$this->iId}').length == 0)
|
if ($('#ac_tree_{$this->iId}').length == 0)
|
||||||
{
|
{
|
||||||
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
|
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
|
||||||
}
|
}
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($bCreate && $bExtensions)
|
if ($bCreate && $bExtensions)
|
||||||
{
|
{
|
||||||
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
||||||
|
|
||||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
|
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"ibo-input-select--action-button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<JS
|
||||||
if ($('#ajax_{$this->iId}').length == 0)
|
if ($('#ajax_{$this->iId}').length == 0)
|
||||||
{
|
{
|
||||||
$('body').append('<div id="ajax_{$this->iId}"></div>');
|
$('body').append('<div id="ajax_{$this->iId}"></div>');
|
||||||
}
|
}
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$sHTMLValue .= "</div>";
|
$sHTMLValue .= "</div>";
|
||||||
|
$sHTMLValue .= "<span class=\"form_validation ibo-field-validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
||||||
// Note: This test is no longer necessary as we changed the markup to extract validation decoration in the standard .field_input_xxx container
|
|
||||||
//if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
|
|
||||||
//{
|
|
||||||
$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
|
||||||
//}
|
|
||||||
|
|
||||||
return $sHTMLValue;
|
return $sHTMLValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetSearchDialog(WebPage $oPage, $sTitle, $oCurrObject = null)
|
public function GetSearchDialog(WebPage $oPage, $sTitle, $oCurrObject = null)
|
||||||
{
|
{
|
||||||
$sHTML = '<div class="wizContainer" style="vertical-align:top;"><div id="dc_'.$this->iId.'">';
|
$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div id="dc_'.$this->iId.'">');
|
||||||
|
|
||||||
if ( ($oCurrObject != null) && ($this->sAttCode != ''))
|
if (($oCurrObject != null) && ($this->sAttCode != '')) {
|
||||||
{
|
|
||||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
|
||||||
/** @var \DBObject $oCurrObject */
|
/** @var \DBObject $oCurrObject */
|
||||||
$aArgs = $oCurrObject->ToArgsForQuery();
|
$aArgs = $oCurrObject->ToArgsForQuery();
|
||||||
$aParams = array('query_params' => $aArgs);
|
$aParams = array('query_params' => $aArgs);
|
||||||
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs);
|
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs);
|
||||||
$oFilter = $oSet->GetFilter();
|
$oFilter = $oSet->GetFilter();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aParams = array();
|
$aParams = array();
|
||||||
$oFilter = new DBObjectSearch($this->sTargetClass);
|
$oFilter = new DBObjectSearch($this->sTargetClass);
|
||||||
}
|
}
|
||||||
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
|
$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
|
||||||
$sHTML .= $oBlock->GetDisplay($oPage, $this->iId,
|
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, $this->iId,
|
||||||
array(
|
array(
|
||||||
'menu' => false,
|
'menu' => false,
|
||||||
'currentId' => $this->iId,
|
'currentId' => $this->iId,
|
||||||
'table_id' => "dr_{$this->iId}",
|
'table_id' => "dr_{$this->iId}",
|
||||||
'table_inner_id' => "{$this->iId}_results",
|
'table_inner_id' => "{$this->iId}_results",
|
||||||
'selection_mode' => true,
|
'selection_mode' => true,
|
||||||
'selection_type' => 'single',
|
'selection_type' => 'single',
|
||||||
'cssCount' => '#count_'.$this->iId)
|
'cssCount' => '#count_'.$this->iId
|
||||||
);
|
)
|
||||||
$sHTML .= "<form id=\"fr_{$this->iId}\" OnSubmit=\"return oACWidget_{$this->iId}.DoOk();\">\n";
|
));
|
||||||
$sHTML .= "<div id=\"dr_{$this->iId}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n";
|
$sCancel = Dict::S('UI:Button:Cancel');
|
||||||
$sHTML .= "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>".Dict::S('UI:Message:EmptyList:UseSearchForm')."</p></div>\n";
|
$sOK = Dict::S('UI:Button:Ok');
|
||||||
$sHTML .= "</div>\n";
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sHTML .= "<input type=\"button\" id=\"btn_cancel_{$this->iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#ac_dlg_{$this->iId}').dialog('close');\"> ";
|
$oPage->add(<<<HTML
|
||||||
$sHTML .= "<input type=\"button\" id=\"btn_ok_{$this->iId}\" value=\"".Dict::S('UI:Button:Ok')."\" onClick=\"oACWidget_{$this->iId}.DoOk();\">";
|
<form id="fr_{$this->iId}" OnSubmit="return oACWidget_{$this->iId}.DoOk();">
|
||||||
$sHTML .= "<input type=\"hidden\" id=\"count_{$this->iId}\" value=\"0\">";
|
<div id="dr_{$this->iId}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
||||||
$sHTML .= "</form>\n";
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
$sHTML .= '</div></div>';
|
</div>
|
||||||
|
<input type="button" id="btn_cancel_{$this->iId}" value="{$sCancel}" onClick="$('#ac_dlg_{$this->iId}').dialog('close');">
|
||||||
|
<input type="button" id="btn_ok_{$this->iId}_results" value="{$sOK}" onClick="oACWidget_{$this->iId}.DoOk();">
|
||||||
|
<input type="hidden" id="count_{$this->iId}_results" value="0">
|
||||||
|
</form>
|
||||||
|
</div></div>
|
||||||
|
HTML
|
||||||
|
);
|
||||||
|
|
||||||
$sDialogTitle = addslashes($sTitle);
|
$sDialogTitle = addslashes($sTitle);
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(<<<JS
|
||||||
<<<EOF
|
|
||||||
$('#ac_dlg_{$this->iId}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$sDialogTitle', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });
|
$('#ac_dlg_{$this->iId}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$sDialogTitle', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });
|
||||||
$('#fs_{$this->iId}').bind('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
|
$('#fs_{$this->iId}').bind('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
|
||||||
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
|
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
$oPage->add($sHTML);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -436,32 +737,53 @@ EOF
|
|||||||
|
|
||||||
// Current extkey value, so we can display event if it is not available anymore (eg. archived).
|
// Current extkey value, so we can display event if it is not available anymore (eg. archived).
|
||||||
$iCurrentExtKeyId = (is_null($oObj) || $this->sAttCode === '') ? 0 : $oObj->Get($this->sAttCode);
|
$iCurrentExtKeyId = (is_null($oObj) || $this->sAttCode === '') ? 0 : $oObj->Get($this->sAttCode);
|
||||||
|
|
||||||
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
|
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
|
||||||
$iMax = 150;
|
$iMax = 150;
|
||||||
$oValuesSet->SetLimit($iMax);
|
$oValuesSet->SetLimit($iMax);
|
||||||
$oValuesSet->SetSort(false);
|
$oValuesSet->SetSort(false);
|
||||||
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
||||||
$oValuesSet->SetLimit($iMax);
|
$oValuesSet->SetLimit($iMax);
|
||||||
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
|
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
|
||||||
asort($aValuesContains);
|
asort($aValuesContains);
|
||||||
$aValues = array();
|
$aValues = $aValuesContains;
|
||||||
foreach($aValuesContains as $sKey => $sFriendlyName)
|
if (sizeof($aValues) < $iMax)
|
||||||
{
|
{
|
||||||
if (!isset($aValues[$sKey]))
|
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
|
||||||
|
asort($aValuesContains);
|
||||||
|
$iSize = sizeof($aValuesContains);
|
||||||
|
foreach ($aValuesContains as $sKey => $sFriendlyName)
|
||||||
{
|
{
|
||||||
$aValues[$sKey] = $sFriendlyName;
|
if (!isset($aValues[$sKey]))
|
||||||
|
{
|
||||||
|
$aValues[$sKey] = $sFriendlyName;
|
||||||
|
if (++$iSize >= $iMax)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elseif (!in_array($sContains, $aValues))
|
||||||
|
{
|
||||||
|
$aValuesEquals = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals');
|
||||||
|
$aValues = array_merge($aValuesEquals, $aValues);
|
||||||
|
}
|
||||||
|
|
||||||
switch($sOutputFormat)
|
switch($sOutputFormat)
|
||||||
{
|
{
|
||||||
case static::ENUM_OUTPUT_FORMAT_JSON:
|
case static::ENUM_OUTPUT_FORMAT_JSON:
|
||||||
|
|
||||||
$aJsonMap = array();
|
$aJsonMap = array();
|
||||||
foreach ($aValues as $sKey => $sLabel)
|
foreach ($aValues as $sKey => $aValue)
|
||||||
{
|
{
|
||||||
$aJsonMap[] = array('value' => $sKey, 'label' => $sLabel);
|
if ($aValue['additional_field'] != '')
|
||||||
|
{
|
||||||
|
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag'], 'additional_field' => $aValue['additional_field']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oP->SetContentType('application/json');
|
$oP->SetContentType('application/json');
|
||||||
@@ -469,9 +791,9 @@ EOF
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case static::ENUM_OUTPUT_FORMAT_CSV:
|
case static::ENUM_OUTPUT_FORMAT_CSV:
|
||||||
foreach($aValues as $sKey => $sFriendlyName)
|
foreach($aValues as $sKey => $aValue)
|
||||||
{
|
{
|
||||||
$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
|
$oP->add(trim($aValue['label'])."\t".$sKey."\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ class UILinksWidgetDirect
|
|||||||
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
||||||
// and that the current user is allowed to create objects of this class
|
// and that the current user is allowed to create objects of this class
|
||||||
$sRealClass = '';
|
$sRealClass = '';
|
||||||
$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
|
//$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
|
||||||
$aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
$aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
||||||
$aPossibleClasses = array();
|
$aPossibleClasses = array();
|
||||||
foreach($aSubClasses as $sCandidateClass)
|
foreach($aSubClasses as $sCandidateClass)
|
||||||
@@ -294,20 +294,17 @@ class UILinksWidgetDirect
|
|||||||
*/
|
*/
|
||||||
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array())
|
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array())
|
||||||
{
|
{
|
||||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
//$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||||
|
|
||||||
$oHiddenFilter = new DBObjectSearch($this->sLinkedClass);
|
$oHiddenFilter = new DBObjectSearch($this->sLinkedClass);
|
||||||
if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($this->sLinkedClass, $this->sClass))
|
if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($this->sLinkedClass, $this->sClass)) {
|
||||||
{
|
|
||||||
// Prevent linking to self if the linked object is of the same family
|
// Prevent linking to self if the linked object is of the same family
|
||||||
// and already present in the database
|
// and already present in the database
|
||||||
if (!$oCurrentObj->IsNew())
|
if (!$oCurrentObj->IsNew()) {
|
||||||
{
|
|
||||||
$oHiddenFilter->AddCondition('id', $oCurrentObj->GetKey(), '!=');
|
$oHiddenFilter->AddCondition('id', $oCurrentObj->GetKey(), '!=');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count($aAlreadyLinked) > 0)
|
if (count($aAlreadyLinked) > 0) {
|
||||||
{
|
|
||||||
$oHiddenFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
|
$oHiddenFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
|
||||||
}
|
}
|
||||||
$oHiddenCriteria = $oHiddenFilter->GetCriteria();
|
$oHiddenCriteria = $oHiddenFilter->GetCriteria();
|
||||||
@@ -319,18 +316,14 @@ class UILinksWidgetDirect
|
|||||||
if ($valuesDef === null)
|
if ($valuesDef === null)
|
||||||
{
|
{
|
||||||
$oFilter = new DBObjectSearch($this->sLinkedClass);
|
$oFilter = new DBObjectSearch($this->sLinkedClass);
|
||||||
}
|
} else {
|
||||||
else
|
if (!$valuesDef instanceof ValueSetObjects) {
|
||||||
{
|
|
||||||
if (!$valuesDef instanceof ValueSetObjects)
|
|
||||||
{
|
|
||||||
throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').');
|
throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').');
|
||||||
}
|
}
|
||||||
$oFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression());
|
$oFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oCurrentObj != null)
|
if ($oCurrentObj != null) {
|
||||||
{
|
|
||||||
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
||||||
|
|
||||||
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
|
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
|
||||||
@@ -339,7 +332,7 @@ class UILinksWidgetDirect
|
|||||||
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
||||||
}
|
}
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||||
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}",
|
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}",
|
||||||
array(
|
array(
|
||||||
'result_list_outer_selector' => "SearchResultsToAdd_{$this->sInputid}",
|
'result_list_outer_selector' => "SearchResultsToAdd_{$this->sInputid}",
|
||||||
'table_id' => "add_{$this->sInputid}",
|
'table_id' => "add_{$this->sInputid}",
|
||||||
@@ -349,16 +342,21 @@ class UILinksWidgetDirect
|
|||||||
'query_params' => $oFilter->GetInternalParams(),
|
'query_params' => $oFilter->GetInternalParams(),
|
||||||
'hidden_criteria' => $sHiddenCriteria,
|
'hidden_criteria' => $sHiddenCriteria,
|
||||||
)
|
)
|
||||||
);
|
));
|
||||||
$sHtml .= "<form id=\"ObjectsAddForm_{$this->sInputid}\">\n";
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sHtml .= "<div id=\"SearchResultsToAdd_{$this->sInputid}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n";
|
$sCancel = Dict::S('UI:Button:Cancel');
|
||||||
$sHtml .= "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>".Dict::S('UI:Message:EmptyList:UseSearchForm')."</p></div>\n";
|
$sAdd = Dict::S('UI:Button:Add');
|
||||||
$sHtml .= "</div>\n";
|
|
||||||
$sHtml .= "<input type=\"hidden\" id=\"count_{$this->sInputid}\" value=\"0\"/>";
|
$oPage->add(<<<HTML
|
||||||
$sHtml .= "<button type=\"button\" class=\"cancel\">".Dict::S('UI:Button:Cancel')."</button> <button type=\"button\" class=\"ok\" disabled=\"disabled\">".Dict::S('UI:Button:Add')."</button>";
|
<form id="ObjectsAddForm_{$this->sInputid}">
|
||||||
$sHtml .= "</div>\n";
|
<div id="SearchResultsToAdd_{$this->sInputid}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
||||||
$sHtml .= "</form>\n";
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
$oPage->add($sHtml);
|
</div>
|
||||||
|
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
||||||
|
<button type="button" class="cancel">{$sCancel}</button> <button type="button" class="ok" disabled="disabled">{$sAdd}</button>
|
||||||
|
</form>
|
||||||
|
HTML
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,10 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'application/webpage.class.inc.php');
|
use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\FormTableRow\FormTableRow;
|
||||||
|
use Combodo\iTop\Renderer\BlockRenderer;
|
||||||
|
|
||||||
require_once(APPROOT.'application/displayblock.class.inc.php');
|
require_once(APPROOT.'application/displayblock.class.inc.php');
|
||||||
|
|
||||||
class UILinksWidget
|
class UILinksWidget
|
||||||
@@ -39,6 +42,7 @@ class UILinksWidget
|
|||||||
protected $m_sLinkedClass;
|
protected $m_sLinkedClass;
|
||||||
protected $m_sRemoteClass;
|
protected $m_sRemoteClass;
|
||||||
protected $m_bDuplicatesAllowed;
|
protected $m_bDuplicatesAllowed;
|
||||||
|
/** @var string[] list of editables attcodes */
|
||||||
protected $m_aEditableFields;
|
protected $m_aEditableFields;
|
||||||
protected $m_aTableConfig;
|
protected $m_aTableConfig;
|
||||||
|
|
||||||
@@ -46,7 +50,7 @@ class UILinksWidget
|
|||||||
* UILinksWidget constructor.
|
* UILinksWidget constructor.
|
||||||
*
|
*
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $sAttCode
|
* @param string $sAttCode AttributeLinkedSetIndirect attcode
|
||||||
* @param int $iInputId
|
* @param int $iInputId
|
||||||
* @param string $sNameSuffix
|
* @param string $sNameSuffix
|
||||||
* @param bool $bDuplicatesAllowed
|
* @param bool $bDuplicatesAllowed
|
||||||
@@ -73,41 +77,36 @@ class UILinksWidget
|
|||||||
/** @var AttributeExternalKey $oLinkingAttDef */
|
/** @var AttributeExternalKey $oLinkingAttDef */
|
||||||
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
|
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
|
||||||
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
|
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
|
||||||
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
|
|
||||||
$sDefaultState = MetaModel::GetDefaultState($this->m_sClass);
|
|
||||||
|
|
||||||
$this->m_aEditableFields = array();
|
$this->m_aEditableFields = array();
|
||||||
$this->m_aTableConfig = array();
|
$this->m_aTableConfig = array();
|
||||||
$this->m_aTableConfig['form::checkbox'] = array( 'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_iInputId.".OnSelectChange();\">", 'description' => Dict::S('UI:SelectAllToggle+'));
|
$this->m_aTableConfig['form::checkbox'] = array(
|
||||||
|
'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_iInputId.".OnSelectChange();\">",
|
||||||
|
'description' => Dict::S('UI:SelectAllToggle+'),
|
||||||
|
);
|
||||||
|
|
||||||
foreach(MetaModel::FlattenZList(MetaModel::GetZListItems($this->m_sLinkedClass, 'list')) as $sAttCode)
|
$aLnkAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode);
|
||||||
|
foreach ($aLnkAttDefsToDisplay as $oLnkAttDef)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sAttCode);
|
$sLnkAttCode = $oLnkAttDef->GetCode();
|
||||||
if ($sStateAttCode == $sAttCode)
|
$this->m_aEditableFields[] = $sLnkAttCode;
|
||||||
{
|
$this->m_aTableConfig[$sLnkAttCode] = array('label' => $oLnkAttDef->GetLabel(), 'description' => $oLnkAttDef->GetDescription());
|
||||||
// State attribute is always hidden from the UI
|
|
||||||
}
|
|
||||||
else if ($oAttDef->IsWritable() && ($sAttCode != $sExtKeyToMe) && ($sAttCode != $this->m_sExtKeyToRemote) && ($sAttCode != 'finalclass'))
|
|
||||||
{
|
|
||||||
$iFlags = MetaModel::GetAttributeFlags($this->m_sLinkedClass, $sDefaultState, $sAttCode);
|
|
||||||
if ( !($iFlags & OPT_ATT_HIDDEN) && !($iFlags & OPT_ATT_READONLY) )
|
|
||||||
{
|
|
||||||
$this->m_aEditableFields[] = $sAttCode;
|
|
||||||
$this->m_aTableConfig[$sAttCode] = array( 'label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->m_aTableConfig['static::key'] = array( 'label' => MetaModel::GetName($this->m_sRemoteClass), 'description' => MetaModel::GetClassDescription($this->m_sRemoteClass));
|
$this->m_aTableConfig['static::key'] = array(
|
||||||
foreach(MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
|
'label' => MetaModel::GetName($this->m_sRemoteClass),
|
||||||
|
'description' => MetaModel::GetClassDescription($this->m_sRemoteClass),
|
||||||
|
);
|
||||||
|
$this->m_aEditableFields[] = $this->m_sExtKeyToRemote;
|
||||||
|
|
||||||
|
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
|
||||||
|
foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef)
|
||||||
{
|
{
|
||||||
// TO DO: check the state of the attribute: hidden or visible ?
|
$sRemoteAttCode = $oRemoteAttDef->GetCode();
|
||||||
if ($sFieldCode != 'finalclass')
|
$this->m_aTableConfig['static::'.$sRemoteAttCode] = array(
|
||||||
{
|
'label' => $oRemoteAttDef->GetLabel(),
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sRemoteClass, $sFieldCode);
|
'description' => $oRemoteAttDef->GetDescription(),
|
||||||
$this->m_aTableConfig['static::'.$sFieldCode] = array( 'label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +115,7 @@ class UILinksWidget
|
|||||||
*
|
*
|
||||||
* @param WebPage $oP Web page used for the ouput
|
* @param WebPage $oP Web page used for the ouput
|
||||||
* @param DBObject $oLinkedObj Remote object
|
* @param DBObject $oLinkedObj Remote object
|
||||||
* @param mixed $linkObjOrId Either the object linked or a unique number for new link records to add
|
* @param DBObject|int $linkObjOrId Either the lnk object or a unique number for new link records to add
|
||||||
* @param array $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
* @param DBObject $oCurrentObj The object to which all the elements of the linked set refer to
|
* @param DBObject $oCurrentObj The object to which all the elements of the linked set refer to
|
||||||
* @param int $iUniqueId A unique identifier of new links
|
* @param int $iUniqueId A unique identifier of new links
|
||||||
@@ -134,43 +133,39 @@ class UILinksWidget
|
|||||||
$aRow = array();
|
$aRow = array();
|
||||||
$aFieldsMap = array();
|
$aFieldsMap = array();
|
||||||
$iKey = 0;
|
$iKey = 0;
|
||||||
if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
|
|
||||||
|
if (is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
|
||||||
{
|
{
|
||||||
$iKey = $linkObjOrId->GetKey();
|
$iKey = $linkObjOrId->GetKey();
|
||||||
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
|
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
|
||||||
$sPrefix .= "[$iKey][";
|
$sPrefix .= "[$iKey][";
|
||||||
$sNameSuffix = "]"; // To make a tabular form
|
$sNameSuffix = "]"; // To make a tabular form
|
||||||
$aArgs['prefix'] = $sPrefix;
|
$aArgs['prefix'] = $sPrefix;
|
||||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
|
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
|
||||||
$aArgs['this'] = $linkObjOrId;
|
$aArgs['this'] = $linkObjOrId;
|
||||||
|
|
||||||
if($bReadOnly)
|
if ($bReadOnly)
|
||||||
{
|
{
|
||||||
$aRow['form::checkbox'] = "";
|
$aRow['form::checkbox'] = "";
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach ($this->m_aEditableFields as $sFieldCode)
|
||||||
{
|
{
|
||||||
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
||||||
$aRow[$sFieldCode] = $sDisplayValue;
|
$aRow[$sFieldCode] = $sDisplayValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
|
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach ($this->m_aEditableFields as $sFieldCode)
|
||||||
{
|
{
|
||||||
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId->GetKey().']';
|
$sSafeFieldId = $this->GetFieldId($linkObjOrId->GetKey(), $sFieldCode);
|
||||||
$sSafeId = utils::GetSafeId($sFieldId);
|
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $linkObjOrId, $oP, $sNameSuffix, $sSafeFieldId);
|
||||||
$sValue = $linkObjOrId->Get($sFieldCode);
|
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||||
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
}
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
}
|
||||||
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
|
|
||||||
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs).
|
|
||||||
'</div></div></div>';
|
|
||||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sState = $linkObjOrId->GetState();
|
$sState = $linkObjOrId->GetState();
|
||||||
|
$sRemoteKeySafeFieldId = $this->GetFieldId($aArgs['this']->GetKey(), $this->m_sExtKeyToRemote);;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -180,15 +175,18 @@ class UILinksWidget
|
|||||||
// New link existing only in memory
|
// New link existing only in memory
|
||||||
$oNewLinkObj = $linkObjOrId;
|
$oNewLinkObj = $linkObjOrId;
|
||||||
$iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote);
|
$iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote);
|
||||||
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
$oNewLinkObj->Set($this->m_sExtKeyToMe,
|
||||||
|
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$iRemoteObjKey = $linkObjOrId;
|
$iRemoteObjKey = $linkObjOrId;
|
||||||
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
|
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
|
||||||
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey);
|
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey);
|
||||||
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
|
$oNewLinkObj->Set($this->m_sExtKeyToRemote,
|
||||||
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
$oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
|
||||||
|
$oNewLinkObj->Set($this->m_sExtKeyToMe,
|
||||||
|
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||||
}
|
}
|
||||||
$sPrefix .= "[-$iUniqueId][";
|
$sPrefix .= "[-$iUniqueId][";
|
||||||
$sNameSuffix = "]"; // To make a tabular form
|
$sNameSuffix = "]"; // To make a tabular form
|
||||||
@@ -222,112 +220,150 @@ EOF
|
|||||||
|
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach($this->m_aEditableFields as $sFieldCode)
|
||||||
{
|
{
|
||||||
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.-$iUniqueId.']';
|
$sSafeFieldId = $this->GetFieldId($iUniqueId, $sFieldCode);
|
||||||
$sSafeId = utils::GetSafeId($sFieldId);
|
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $oNewLinkObj, $oP, $sNameSuffix, $sSafeFieldId);
|
||||||
|
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||||
|
|
||||||
$sValue = $oNewLinkObj->Get($sFieldCode);
|
$sValue = $oNewLinkObj->Get($sFieldCode);
|
||||||
$sDisplayValue = $oNewLinkObj->GetEditValue($sFieldCode);
|
$oP->add_ready_script(
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
<<<JS
|
||||||
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
|
|
||||||
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
|
|
||||||
'</div></div></div>';
|
|
||||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
|
||||||
$oP->add_ready_script(<<<EOF
|
|
||||||
oWidget{$this->m_iInputId}.OnValueChange($iKey, $iUniqueId, '$sFieldCode', '$sValue');
|
oWidget{$this->m_iInputId}.OnValueChange($iKey, $iUniqueId, '$sFieldCode', '$sValue');
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sState = '';
|
$sState = '';
|
||||||
|
$sRemoteKeySafeFieldId = $this->GetFieldId($iUniqueId, $this->m_sExtKeyToRemote);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$bReadOnly)
|
if (!$bReadOnly)
|
||||||
{
|
|
||||||
$sExtKeyToMeId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToMe);
|
|
||||||
$aFieldsMap[$this->m_sExtKeyToMe] = $sExtKeyToMeId;
|
|
||||||
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToMeId\" value=\"".$oCurrentObj->GetKey()."\">";
|
|
||||||
|
|
||||||
$sExtKeyToRemoteId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToRemote);
|
|
||||||
$aFieldsMap[$this->m_sExtKeyToRemote] = $sExtKeyToRemoteId;
|
|
||||||
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToRemoteId\" value=\"$iRemoteObjKey\">";
|
|
||||||
}
|
|
||||||
|
|
||||||
$iFieldsCount = count($aFieldsMap);
|
|
||||||
$sJsonFieldsMap = json_encode($aFieldsMap);
|
|
||||||
|
|
||||||
$oP->add_script(
|
|
||||||
<<<EOF
|
|
||||||
var {$aArgs['wizHelper']} = new WizardHelper('{$this->m_sLinkedClass}', '', '$sState');
|
|
||||||
{$aArgs['wizHelper']}.SetFieldsMap($sJsonFieldsMap);
|
|
||||||
{$aArgs['wizHelper']}.SetFieldsCount($iFieldsCount);
|
|
||||||
EOF
|
|
||||||
);
|
|
||||||
$aRow['static::key'] = $oLinkedObj->GetHyperLink();
|
|
||||||
foreach(MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
|
|
||||||
{
|
{
|
||||||
$aRow['static::'.$sFieldCode] = $oLinkedObj->GetAsHTML($sFieldCode);
|
$sExtKeyToMeId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToMe);
|
||||||
|
$aFieldsMap[$this->m_sExtKeyToMe] = $sExtKeyToMeId;
|
||||||
|
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToMeId\" value=\"".$oCurrentObj->GetKey()."\">";
|
||||||
|
|
||||||
|
$sExtKeyToRemoteId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToRemote);
|
||||||
|
$aFieldsMap[$this->m_sExtKeyToRemote] = $sExtKeyToRemoteId;
|
||||||
|
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToRemoteId\" value=\"$iRemoteObjKey\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adding fields from remote class
|
||||||
|
// all fields are embedded in a span + added to $aFieldsMap array so that we can refresh them after extkey change
|
||||||
|
$aRemoteFieldsMap = [];
|
||||||
|
foreach (MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
|
||||||
|
{
|
||||||
|
$sSafeFieldId = $this->GetFieldId($aArgs['this']->GetKey(), $sFieldCode);
|
||||||
|
$aRow['static::'.$sFieldCode] = "<span id='field_$sSafeFieldId'>".$oLinkedObj->GetAsHTML($sFieldCode).'</span>';
|
||||||
|
$aRemoteFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||||
|
}
|
||||||
|
// id field is needed so that remote object could be load server side
|
||||||
|
$aRemoteFieldsMap['id'] = $sRemoteKeySafeFieldId;
|
||||||
|
|
||||||
|
// Generate WizardHelper to update dependant fields
|
||||||
|
$this->AddWizardHelperInit($oP, $aArgs['wizHelper'], $this->m_sLinkedClass, $sState, $aFieldsMap);
|
||||||
|
//instantiate specific WizarHelper instance for remote class fields refresh
|
||||||
|
$bHasExtKeyUpdatingRemoteClassFields = (
|
||||||
|
array_key_exists('replaceDependenciesByRemoteClassFields', $aArgs)
|
||||||
|
&& ($aArgs['replaceDependenciesByRemoteClassFields'])
|
||||||
|
);
|
||||||
|
if ($bHasExtKeyUpdatingRemoteClassFields)
|
||||||
|
{
|
||||||
|
$this->AddWizardHelperInit($oP, $aArgs['wizHelperRemote'], $this->m_sRemoteClass, $sState, $aRemoteFieldsMap);
|
||||||
|
}
|
||||||
|
|
||||||
return $aRow;
|
return $aRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function AddRowForFieldCode(&$aRow, $sFieldCode, &$aArgs, $oLnk, $oP, $sNameSuffix, $sSafeFieldId): void
|
||||||
* Display one row of the whole form
|
|
||||||
* @param WebPage $oP
|
|
||||||
* @param array $aConfig
|
|
||||||
* @param array $aRow
|
|
||||||
* @param int $iRowId
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId)
|
|
||||||
{
|
{
|
||||||
$sHtml = '';
|
if (($sFieldCode === $this->m_sExtKeyToRemote))
|
||||||
$sHtml .= "<tr id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_row_$iRowId\">\n";
|
|
||||||
foreach($aConfig as $sName=>$void)
|
|
||||||
{
|
{
|
||||||
$sHtml .= "<td>".$aRow[$sName]."</td>\n";
|
// current field is the lnk extkey to the remote class
|
||||||
|
$aArgs['replaceDependenciesByRemoteClassFields'] = true;
|
||||||
|
$sRowFieldCode = 'static::key';
|
||||||
|
$aArgs['wizHelperRemote'] = $aArgs['wizHelper'].'_remote';
|
||||||
|
$aRemoteAttDefs = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
|
||||||
|
$aRemoteCodes = array_map(
|
||||||
|
function ($value) {
|
||||||
|
return $value->GetCode();
|
||||||
|
},
|
||||||
|
$aRemoteAttDefs
|
||||||
|
);
|
||||||
|
$aArgs['remoteCodes'] = $aRemoteCodes;
|
||||||
}
|
}
|
||||||
$sHtml .= "</tr>\n";
|
else
|
||||||
|
{
|
||||||
return $sHtml;
|
$aArgs['replaceDependenciesByRemoteClassFields'] = false;
|
||||||
|
$sRowFieldCode = $sFieldCode;
|
||||||
|
}
|
||||||
|
$sValue = $oLnk->Get($sFieldCode);
|
||||||
|
$sDisplayValue = $oLnk->GetEditValue($sFieldCode);
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
||||||
|
|
||||||
|
$aRow[$sRowFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'
|
||||||
|
.cmdbAbstractObject::GetFormElementForField(
|
||||||
|
$oP,
|
||||||
|
$this->m_sLinkedClass,
|
||||||
|
$sFieldCode,
|
||||||
|
$oAttDef,
|
||||||
|
$sValue,
|
||||||
|
$sDisplayValue,
|
||||||
|
$sSafeFieldId,
|
||||||
|
$sNameSuffix,
|
||||||
|
0,
|
||||||
|
$aArgs
|
||||||
|
)
|
||||||
|
.'</div></div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function GetFieldId($iLnkId, $sFieldCode, $bSafe = true)
|
||||||
|
{
|
||||||
|
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$iLnkId.']';
|
||||||
|
|
||||||
|
return ($bSafe) ? utils::GetSafeId($sFieldId) : $sFieldId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function AddWizardHelperInit($oP, $sWizardHelperVarName, $sWizardHelperClass, $sState, $aFieldsMap): void
|
||||||
|
{
|
||||||
|
$iFieldsCount = count($aFieldsMap);
|
||||||
|
$sJsonFieldsMap = json_encode($aFieldsMap);
|
||||||
|
|
||||||
|
$oP->add_script(
|
||||||
|
<<<JS
|
||||||
|
var $sWizardHelperVarName = new WizardHelper('$sWizardHelperClass', '', '$sState');
|
||||||
|
$sWizardHelperVarName.SetFieldsMap($sJsonFieldsMap);
|
||||||
|
$sWizardHelperVarName.SetFieldsCount($iFieldsCount);
|
||||||
|
$sWizardHelperVarName.SetReturnNotEditableFields(true);
|
||||||
|
$sWizardHelperVarName.SetWizHelperJsVarName('$sWizardHelperVarName');
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the table with the form for editing all the links at once
|
* Display the table with the form for editing all the links at once
|
||||||
|
*
|
||||||
* @param WebPage $oP The web page used for the output
|
* @param WebPage $oP The web page used for the output
|
||||||
* @param array $aConfig The table's header configuration
|
* @param array $aConfig The table's header configuration
|
||||||
* @param array $aData The tabular data to be displayed
|
* @param array $aData The tabular data to be displayed
|
||||||
|
*
|
||||||
* @return string Html fragment representing the form table
|
* @return string Html fragment representing the form table
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws \Twig\Error\LoaderError
|
||||||
|
* @throws \Twig\Error\RuntimeError
|
||||||
|
* @throws \Twig\Error\SyntaxError
|
||||||
*/
|
*/
|
||||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
||||||
{
|
{
|
||||||
$sHtml = "<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">";
|
$oTable = DataTableFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig);
|
||||||
$sHtml .= "<table class=\"listResults\">\n";
|
|
||||||
// Header
|
foreach ($aData as $iRowId => $aRow)
|
||||||
$sHtml .= "<thead>\n";
|
|
||||||
$sHtml .= "<tr>\n";
|
|
||||||
foreach($aConfig as $sName=>$aDef)
|
|
||||||
{
|
{
|
||||||
$sHtml .= "<th title=\"".$aDef['description']."\">".$aDef['label']."</th>\n";
|
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aRow, $iRowId);
|
||||||
}
|
$oTable->AddRow($oRow);
|
||||||
$sHtml .= "</tr>\n";
|
|
||||||
$sHtml .= "</thead>\n";
|
|
||||||
|
|
||||||
// Content
|
|
||||||
$sHtml .= "</tbody>\n";
|
|
||||||
$sEmptyRowStyle = '';
|
|
||||||
if (count($aData) != 0)
|
|
||||||
{
|
|
||||||
$sEmptyRowStyle = 'style="display:none;"';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($aData as $iRowId => $aRow)
|
$sHtml = BlockRenderer::RenderBlockTemplates($oTable);
|
||||||
{
|
|
||||||
$sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId);
|
|
||||||
}
|
|
||||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
|
|
||||||
$sHtml .= "</tbody>\n";
|
|
||||||
|
|
||||||
// Footer
|
|
||||||
$sHtml .= "</table>\n";
|
|
||||||
|
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,20 +396,21 @@ EOF
|
|||||||
$bDoSearch = !utils::IsHighCardinality($this->m_sRemoteClass);
|
$bDoSearch = !utils::IsHighCardinality($this->m_sRemoteClass);
|
||||||
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
$oPage->add_ready_script(<<<EOF
|
$oPage->add_ready_script(<<<JS
|
||||||
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}', $sJSDoSearch);
|
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}', $sJSDoSearch);
|
||||||
oWidget{$this->m_iInputId}.Init();
|
oWidget{$this->m_iInputId}.Init();
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
|
|
||||||
while($oCurrentLink = $oValue->Fetch())
|
while ($oCurrentLink = $oValue->Fetch())
|
||||||
{
|
{
|
||||||
// We try to retrieve the remote object as usual
|
// We try to retrieve the remote object as usual
|
||||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */);
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote),
|
||||||
|
false /* Must not be found */);
|
||||||
// If successful, it means that we can edit its link
|
// If successful, it means that we can edit its link
|
||||||
if($oLinkedObj !== null)
|
if ($oLinkedObj !== null)
|
||||||
{
|
{
|
||||||
$bReadOnly = false;
|
$bReadOnly = false;
|
||||||
}
|
}
|
||||||
// Else we retrieve it without restrictions (silos) and will display its link as readonly
|
// Else we retrieve it without restrictions (silos) and will display its link as readonly
|
||||||
else
|
else
|
||||||
@@ -393,6 +430,7 @@ EOF
|
|||||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||||
}
|
}
|
||||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
||||||
|
// To prevent adding forms inside the main form
|
||||||
|
|
||||||
$sHtmlValue .= "<span style=\"float:left;\"> <img src=\"../images/tv-item-last.gif\"> <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";
|
$sHtmlValue .= "<span style=\"float:left;\"> <img src=\"../images/tv-item-last.gif\"> <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";
|
||||||
$sHtmlValue .= " <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnAdd\" type=\"button\" value=\"".Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sRemoteClass))."\" onClick=\"oWidget{$this->m_iInputId}.AddObjects();\"><span id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\"></span></span>\n";
|
$sHtmlValue .= " <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnAdd\" type=\"button\" value=\"".Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sRemoteClass))."\" onClick=\"oWidget{$this->m_iInputId}.AddObjects();\"><span id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\"></span></span>\n";
|
||||||
@@ -443,53 +481,55 @@ EOF
|
|||||||
*/
|
*/
|
||||||
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array())
|
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array())
|
||||||
{
|
{
|
||||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
//$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||||
|
|
||||||
$oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass);
|
$oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||||
if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0)
|
if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) {
|
||||||
{
|
|
||||||
$oAlreadyLinkedFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN');
|
$oAlreadyLinkedFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN');
|
||||||
$oAlreadyLinkedExpression = $oAlreadyLinkedFilter->GetCriteria();
|
$oAlreadyLinkedExpression = $oAlreadyLinkedFilter->GetCriteria();
|
||||||
$sAlreadyLinkedExpression = $oAlreadyLinkedExpression->Render();
|
$sAlreadyLinkedExpression = $oAlreadyLinkedExpression->RenderExpression();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sAlreadyLinkedExpression = '';
|
$sAlreadyLinkedExpression = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||||
|
|
||||||
if(!empty($oCurrentObj))
|
if (!empty($oCurrentObj)) {
|
||||||
{
|
|
||||||
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
||||||
$aPrefillFormParam['filter'] = $oFilter;
|
$aPrefillFormParam['filter'] = $oFilter;
|
||||||
$aPrefillFormParam['dest_class'] = $this->m_sRemoteClass;
|
$aPrefillFormParam['dest_class'] = $this->m_sRemoteClass;
|
||||||
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
||||||
}
|
}
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||||
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
||||||
array(
|
array(
|
||||||
'menu' => false,
|
'menu' => false,
|
||||||
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
||||||
'table_id' => 'add_'.$this->m_sAttCode,
|
'table_id' => "add_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
||||||
'table_inner_id' => "ResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
'table_inner_id' => "ResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
||||||
'selection_mode' => true,
|
'selection_mode' => true,
|
||||||
'json' => $sJson,
|
'json' => $sJson,
|
||||||
'cssCount' => '#count_'.$this->m_sAttCode.$this->m_sNameSuffix,
|
'cssCount' => '#count_'.$this->m_sAttCode.$this->m_sNameSuffix,
|
||||||
'query_params' => $oFilter->GetInternalParams(),
|
'query_params' => $oFilter->GetInternalParams(),
|
||||||
'hidden_criteria' => $sAlreadyLinkedExpression,
|
'hidden_criteria' => $sAlreadyLinkedExpression,
|
||||||
));
|
)));
|
||||||
$sHtml .= "<form id=\"ObjectsAddForm_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sHtml .= "<div id=\"SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n";
|
$sCancel = Dict::S('UI:Button:Cancel');
|
||||||
$sHtml .= "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>".Dict::S('UI:Message:EmptyList:UseSearchForm')."</p></div>\n";
|
$sAdd = Dict::S('UI:Button:Add');
|
||||||
$sHtml .= "</div>\n";
|
|
||||||
$sHtml .= "<input type=\"hidden\" id=\"count_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"0\"/>";
|
$oPage->add(<<<HTML
|
||||||
$sHtml .= "<input type=\"button\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('close');\"> <input id=\"btn_ok_{$this->m_sAttCode}{$this->m_sNameSuffix}\" disabled=\"disabled\" type=\"button\" onclick=\"return oWidget{$this->m_iInputId}.DoAddObjects(this.id);\" value=\"".Dict::S('UI:Button:Add')."\">";
|
<form id="ObjectsAddForm_{$this->m_sAttCode}{$this->m_sNameSuffix}">
|
||||||
$sHtml .= "</div>\n";
|
<div id="SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
||||||
$sHtml .= "</form>\n";
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
$oPage->add($sHtml);
|
</div>
|
||||||
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, resizeStop: oWidget{$this->m_iInputId}.UpdateSizes });");
|
<input type="hidden" id="count_{$this->m_sAttCode}{$this->m_sNameSuffix}" value="0"/>
|
||||||
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('option', {title:'".addslashes(Dict::Format('UI:AddObjectsOf_Class_LinkedWith_Class', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName($this->m_sClass)))."'});");
|
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('close');">
|
||||||
|
<input id="btn_ok_add_{$this->m_sAttCode}{$this->m_sNameSuffix}" disabled="disabled" type="button" onclick="return oWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||||
|
</form>
|
||||||
|
HTML
|
||||||
|
);
|
||||||
|
|
||||||
|
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, title:'".addslashes(Dict::Format('UI:AddObjectsOf_Class_LinkedWith_Class', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName($this->m_sClass)))."' , autoOpen: false, modal: true, resizeStop: oWidget{$this->m_iInputId}.UpdateSizes });");
|
||||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix} form').bind('submit.uilinksWizard', oWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix} form').bind('submit.uilinksWizard', oWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
||||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}').resize(oWidget{$this->m_iInputId}.UpdateSizes);");
|
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}').resize(oWidget{$this->m_iInputId}.UpdateSizes);");
|
||||||
}
|
}
|
||||||
@@ -547,7 +587,8 @@ EOF
|
|||||||
if (is_object($oLinkedObj))
|
if (is_object($oLinkedObj))
|
||||||
{
|
{
|
||||||
$aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids
|
$aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids
|
||||||
$oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iAdditionId));
|
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId);
|
||||||
|
$oP->AddUiBlock($oRow);
|
||||||
$iAdditionId++;
|
$iAdditionId++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
|
||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
|
|
||||||
class UIPasswordWidget
|
class UIPasswordWidget
|
||||||
@@ -66,7 +65,7 @@ class UIPasswordWidget
|
|||||||
$sHtmlValue .= '<input type="hidden" id="'.$this->iId.'_changed" name="attr_'.$sCode.'[changed]" value="'.$sChangedValue.'"/>';
|
$sHtmlValue .= '<input type="hidden" id="'.$this->iId.'_changed" name="attr_'.$sCode.'[changed]" value="'.$sChangedValue.'"/>';
|
||||||
$sHtmlValue .= '</div>';
|
$sHtmlValue .= '</div>';
|
||||||
|
|
||||||
$sHtmlValue .= '<span class="form_validation" id="v_'.$this->iId.'"></span><span class="field_status" id="fstatus_'.$this->iId.'"></span>';
|
$sHtmlValue .= '<span class="form_validation ibo-field-validation" id="v_'.$this->iId.'"></span><span class="field_status" id="fstatus_'.$this->iId.'"></span>';
|
||||||
|
|
||||||
$oPage->add_ready_script("$('#$this->iId').bind('keyup change', function(evt) { return PasswordFieldChanged('$this->iId') } );"); // Bind to a custom event: validate
|
$oPage->add_ready_script("$('#$this->iId').bind('keyup change', function(evt) { return PasswordFieldChanged('$this->iId') } );"); // Bind to a custom event: validate
|
||||||
$oPage->add_ready_script("$('#$this->iId').bind('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
$oPage->add_ready_script("$('#$this->iId').bind('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
|
||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
|
|
||||||
class UISearchFormForeignKeys
|
class UISearchFormForeignKeys
|
||||||
@@ -41,12 +40,11 @@ class UISearchFormForeignKeys
|
|||||||
*/
|
*/
|
||||||
public function ShowModalSearchForeignKeys($oPage, $sTitle)
|
public function ShowModalSearchForeignKeys($oPage, $sTitle)
|
||||||
{
|
{
|
||||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
|
||||||
|
|
||||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||||
|
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||||
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_iInputId}",
|
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_iInputId}",
|
||||||
array(
|
array(
|
||||||
'menu' => false,
|
'menu' => false,
|
||||||
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_iInputId}",
|
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_iInputId}",
|
||||||
@@ -55,16 +53,23 @@ class UISearchFormForeignKeys
|
|||||||
'selection_mode' => true,
|
'selection_mode' => true,
|
||||||
'cssCount' => "#count_{$this->m_iInputId}",
|
'cssCount' => "#count_{$this->m_iInputId}",
|
||||||
'query_params' => $oFilter->GetInternalParams(),
|
'query_params' => $oFilter->GetInternalParams(),
|
||||||
));
|
)));
|
||||||
$sHtml .= "<form id=\"ObjectsAddForm_{$this->m_iInputId}\">\n";
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sHtml .= "<div id=\"SearchResultsToAdd_{$this->m_iInputId}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n";
|
$sCancel = Dict::S('UI:Button:Cancel');
|
||||||
$sHtml .= "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>".Dict::S('UI:Message:EmptyList:UseSearchForm')."</p></div>\n";
|
$sAdd = Dict::S('UI:Button:Add');
|
||||||
$sHtml .= "</div>\n";
|
|
||||||
$sHtml .= "<input type=\"hidden\" id=\"count_{$this->m_iInputId}\" value=\"0\"/>";
|
$oPage->add(<<<HTML
|
||||||
$sHtml .= "<input type=\"button\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#dlg_{$this->m_iInputId}').dialog('close');\"> <input id=\"btn_ok_{$this->m_iInputId}\" disabled=\"disabled\" type=\"button\" onclick=\"return oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);\" value=\"".Dict::S('UI:Button:Add')."\">";
|
<form id="ObjectsAddForm_{$this->m_iInputId}">
|
||||||
$sHtml .= "</div>\n";
|
<div id="SearchResultsToAdd_{$this->m_iInputId}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
||||||
$sHtml .= "</form>\n";
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
$oPage->add($sHtml);
|
</div>
|
||||||
|
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
||||||
|
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_iInputId}').dialog('close');">
|
||||||
|
<input id="btn_ok_add_{$this->m_iInputId}" disabled="disabled" type="button" onclick="return oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||||
|
</form>
|
||||||
|
HTML
|
||||||
|
);
|
||||||
|
|
||||||
$oPage->add_ready_script("$('#dlg_{$this->m_iInputId}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, resizeStop: oForeignKeysWidget{$this->m_iInputId}.UpdateSizes });");
|
$oPage->add_ready_script("$('#dlg_{$this->m_iInputId}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, resizeStop: oForeignKeysWidget{$this->m_iInputId}.UpdateSizes });");
|
||||||
$oPage->add_ready_script("$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});");
|
$oPage->add_ready_script("$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});");
|
||||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_iInputId} form').bind('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_iInputId} form').bind('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
||||||
@@ -112,4 +117,4 @@ class UISearchFormForeignKeys
|
|||||||
array('menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}"));
|
array('menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,20 @@ require_once(APPROOT.'/core/userrights.class.inc.php');
|
|||||||
class appUserPreferences extends DBObject
|
class appUserPreferences extends DBObject
|
||||||
{
|
{
|
||||||
private static $oUserPrefs = null; // Local cache
|
private static $oUserPrefs = null; // Local cache
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of the given property/preference
|
* Get the value of the given property/preference
|
||||||
* If not set, the default value will be returned
|
* If not set, the default value will be returned
|
||||||
|
*
|
||||||
* @param string $sCode Code/Name of the property to set
|
* @param string $sCode Code/Name of the property to set
|
||||||
* @param string $sDefaultValue The default value
|
* @param mixed $defaultValue The default value
|
||||||
* @return string The value of the property for the current user
|
*
|
||||||
|
* @return mixed The value of the property for the current user
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
public static function GetPref($sCode, $sDefaultValue)
|
public static function GetPref($sCode, $defaultValue)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
if (self::$oUserPrefs == null)
|
||||||
{
|
{
|
||||||
@@ -56,29 +61,35 @@ class appUserPreferences extends DBObject
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return $sDefaultValue;
|
return $defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value for a given preference, and stores it into the database
|
* Set the value for a given preference, and stores it into the database
|
||||||
|
*
|
||||||
* @param string $sCode Code/Name of the property/preference to set
|
* @param string $sCode Code/Name of the property/preference to set
|
||||||
* @param string $sValue Value to set
|
* @param mixed $value Value to set
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
public static function SetPref($sCode, $sValue)
|
public static function SetPref($sCode, $value)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
if (self::$oUserPrefs == null)
|
||||||
{
|
{
|
||||||
self::Load();
|
self::Load();
|
||||||
}
|
}
|
||||||
$aPrefs = self::$oUserPrefs->Get('preferences');
|
$aPrefs = self::$oUserPrefs->Get('preferences');
|
||||||
if (array_key_exists($sCode, $aPrefs) && ($aPrefs[$sCode] === $sValue))
|
if (array_key_exists($sCode, $aPrefs) && ($aPrefs[$sCode] === $value))
|
||||||
{
|
{
|
||||||
// Do not write it again
|
// Do not write it again
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aPrefs[$sCode] = $sValue;
|
$aPrefs[$sCode] = $value;
|
||||||
self::$oUserPrefs->Set('preferences', $aPrefs);
|
self::$oUserPrefs->Set('preferences', $aPrefs);
|
||||||
self::Save();
|
self::Save();
|
||||||
}
|
}
|
||||||
@@ -86,8 +97,14 @@ class appUserPreferences extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the value for a given preference (or list of preferences that matches a pattern), and updates the database
|
* Clears the value for a given preference (or list of preferences that matches a pattern), and updates the database
|
||||||
|
*
|
||||||
* @param string $sCodeOrPattern Code/Pattern of the properties/preferences to reset
|
* @param string $sCodeOrPattern Code/Pattern of the properties/preferences to reset
|
||||||
* @param boolean $bPattern Whether or not the supplied code is a PCRE pattern
|
* @param boolean $bPattern Whether or not the supplied code is a PCRE pattern
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
public static function UnsetPref($sCodeOrPattern, $bPattern = false)
|
public static function UnsetPref($sCodeOrPattern, $bPattern = false)
|
||||||
{
|
{
|
||||||
@@ -119,10 +136,14 @@ class appUserPreferences extends DBObject
|
|||||||
self::Save();
|
self::Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function to get all the preferences for the user, packed as a JSON object
|
* Call this function to get all the preferences for the user, packed as a JSON object
|
||||||
|
*
|
||||||
* @return string JSON representation of the preferences
|
* @return string JSON representation of the preferences
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
public static function GetAsJSON()
|
public static function GetAsJSON()
|
||||||
{
|
{
|
||||||
@@ -136,19 +157,29 @@ class appUserPreferences extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function if the user has changed (like when doing a logoff...)
|
* Call this function if the user has changed (like when doing a logoff...)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function ResetPreferences()
|
public static function ResetPreferences()
|
||||||
{
|
{
|
||||||
self::$oUserPrefs = null;
|
self::$oUserPrefs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function to ERASE all the preferences from the current user
|
* Call this function to ERASE all the preferences from the current user
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function ClearPreferences()
|
public static function ClearPreferences()
|
||||||
{
|
{
|
||||||
self::$oUserPrefs = null;
|
self::$oUserPrefs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save preferences in the DB
|
||||||
|
*
|
||||||
|
* @return void;
|
||||||
|
*/
|
||||||
protected static function Save()
|
protected static function Save()
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs != null)
|
if (self::$oUserPrefs != null)
|
||||||
@@ -161,10 +192,15 @@ class appUserPreferences extends DBObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the preferences for the current user, creating the record in the database
|
* Loads the preferences for the current user, creating the record in the database
|
||||||
* if needed
|
* if needed
|
||||||
|
*
|
||||||
|
* @return void;
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
protected static function Load()
|
protected static function Load()
|
||||||
{
|
{
|
||||||
@@ -193,6 +229,9 @@ class appUserPreferences extends DBObject
|
|||||||
self::$oUserPrefs = $oObj;
|
self::$oUserPrefs = $oObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -213,9 +252,22 @@ class appUserPreferences extends DBObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overloading this function here to secure a fix done right before the release
|
* Overloading this function here to secure a fix done right before the release
|
||||||
* The real fix should be to implement this verb in DBObject
|
* The real fix should be to implement this verb in DBObject
|
||||||
*/
|
*
|
||||||
|
* @param \CMDBChange $oChange
|
||||||
|
* @param bool|null $bSkipStrongSecurity
|
||||||
|
* @param \DeletionPlan|null $oDeletionPlan
|
||||||
|
*
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreCannotSaveObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \DeleteException
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
|
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
|
||||||
{
|
{
|
||||||
utils::PushArchiveMode(false);
|
utils::PushArchiveMode(false);
|
||||||
|
|||||||
@@ -44,6 +44,57 @@ class FileUploadException extends Exception
|
|||||||
*/
|
*/
|
||||||
class utils
|
class utils
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_INTEGER = 'integer';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_CLASS = 'class';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_STRING = 'string';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_CONTEXT_PARAM = 'context_param';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_PARAMETER = 'parameter';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_FIELD_NAME = 'field_name';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_TRANSACTION_ID = 'transaction_id';
|
||||||
|
/**
|
||||||
|
* @var string For XML / HTML node identifiers
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER = 'element_identifier';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const ENUM_SANITIZATION_FILTER_RAW_DATA = 'raw_data';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public const DEFAULT_SANITIZATION_FILTER = self::ENUM_SANITIZATION_FILTER_RAW_DATA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache when getting config from disk or set externally (using {@link SetConfig})
|
* Cache when getting config from disk or set externally (using {@link SetConfig})
|
||||||
* @internal
|
* @internal
|
||||||
@@ -283,31 +334,32 @@ class utils
|
|||||||
*
|
*
|
||||||
* @since 2.5.2 2.6.0 new 'transaction_id' filter
|
* @since 2.5.2 2.6.0 new 'transaction_id' filter
|
||||||
* @since 2.7.0 new 'element_identifier' filter
|
* @since 2.7.0 new 'element_identifier' filter
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
protected static function Sanitize_Internal($value, $sSanitizationFilter)
|
protected static function Sanitize_Internal($value, $sSanitizationFilter)
|
||||||
{
|
{
|
||||||
switch ($sSanitizationFilter)
|
switch ($sSanitizationFilter)
|
||||||
{
|
{
|
||||||
case 'integer':
|
case static::ENUM_SANITIZATION_FILTER_INTEGER:
|
||||||
$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
|
$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'class':
|
case static::ENUM_SANITIZATION_FILTER_CLASS:
|
||||||
$retValue = $value;
|
$retValue = $value;
|
||||||
if (!MetaModel::IsValidClass($value))
|
if (($value != '') && !MetaModel::IsValidClass($value)) {
|
||||||
{
|
throw new CoreException(Dict::Format('UI:OQL:UnknownClassNoFix', utils::HtmlEntities($value)));
|
||||||
$retValue = false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'string':
|
case static::ENUM_SANITIZATION_FILTER_STRING:
|
||||||
$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
|
$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'context_param':
|
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
|
||||||
case 'parameter':
|
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
|
||||||
case 'field_name':
|
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
|
||||||
case 'transaction_id':
|
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
|
||||||
if (is_array($value))
|
if (is_array($value))
|
||||||
{
|
{
|
||||||
$retValue = array();
|
$retValue = array();
|
||||||
@@ -325,7 +377,7 @@ class utils
|
|||||||
{
|
{
|
||||||
switch ($sSanitizationFilter)
|
switch ($sSanitizationFilter)
|
||||||
{
|
{
|
||||||
case 'transaction_id':
|
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
|
||||||
// same as parameter type but keep the dot character
|
// same as parameter type but keep the dot character
|
||||||
// see N°1835 : when using file transaction_id on Windows you get *.tmp tokens
|
// see N°1835 : when using file transaction_id on Windows you get *.tmp tokens
|
||||||
// it must be included at the regexp beginning otherwise you'll get an invalid character error
|
// it must be included at the regexp beginning otherwise you'll get an invalid character error
|
||||||
@@ -333,18 +385,18 @@ class utils
|
|||||||
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
|
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'parameter':
|
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
|
||||||
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
||||||
array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
|
array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
|
||||||
// characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
|
// characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'field_name':
|
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
|
||||||
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
||||||
array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
|
array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'context_param':
|
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
|
||||||
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
|
||||||
array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
|
array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
|
||||||
break;
|
break;
|
||||||
@@ -353,13 +405,12 @@ class utils
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// For XML / HTML node identifiers
|
case static::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER:
|
||||||
case 'element_identifier':
|
$retValue = preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
|
||||||
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case 'raw_data':
|
case static::ENUM_SANITIZATION_FILTER_RAW_DATA:
|
||||||
$retValue = $value;
|
$retValue = $value;
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
@@ -767,19 +818,22 @@ class utils
|
|||||||
return new Config();
|
return new Config();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function InitTimeZone() {
|
public static function InitTimeZone($oConfig = null)
|
||||||
$oConfig = self::GetConfig();
|
{
|
||||||
|
if (is_null($oConfig))
|
||||||
|
{
|
||||||
|
$oConfig = self::GetConfig();
|
||||||
|
}
|
||||||
$sItopTimeZone = $oConfig->Get('timezone');
|
$sItopTimeZone = $oConfig->Get('timezone');
|
||||||
|
|
||||||
if (!empty($sItopTimeZone))
|
if (!empty($sItopTimeZone))
|
||||||
{
|
{
|
||||||
date_default_timezone_set($sItopTimeZone);
|
date_default_timezone_set($sItopTimeZone);
|
||||||
}
|
}
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
// Leave as is... up to the admin to set a value somewhere...
|
// // Leave as is... up to the admin to set a value somewhere...
|
||||||
// see http://php.net/manual/en/datetime.configuration.php#ini.date.timezone
|
// // see http://php.net/manual/en/datetime.configuration.php#ini.date.timezone
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -908,6 +962,28 @@ class utils
|
|||||||
return $sAppRootUrl;
|
return $sAppRootUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the complete revision number of the application
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetAppRevisionNumber()
|
||||||
|
{
|
||||||
|
if (ITOP_REVISION == 'svn')
|
||||||
|
{
|
||||||
|
// This is NOT a version built using the build system, just display the main version
|
||||||
|
$sRevisionNumber = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is a build made from SVN, let display the full information
|
||||||
|
$sRevisionNumber = Dict::Format('UI:iTopVersion:Long', ITOP_APPLICATION, ITOP_VERSION, ITOP_REVISION, ITOP_BUILD_DATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sRevisionNumber;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to handle the variety of HTTP servers
|
* Helper to handle the variety of HTTP servers
|
||||||
* See N°286 (fixed in [896]), and N°634 (this fix)
|
* See N°286 (fixed in [896]), and N°634 (this fix)
|
||||||
@@ -941,16 +1017,11 @@ class utils
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the _SESSION variable for logging purpose
|
* Get the _SESSION variable for logging purpose
|
||||||
* @return false|string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function GetSessionLog()
|
public static function GetSessionLog()
|
||||||
{
|
{
|
||||||
ob_start();
|
return print_r($_SESSION, true);
|
||||||
print_r($_SESSION);
|
|
||||||
$sSessionLog = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
|
|
||||||
return $sSessionLog;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function DebugBacktrace($iLimit = 5)
|
static function DebugBacktrace($iLimit = 5)
|
||||||
@@ -994,19 +1065,19 @@ class utils
|
|||||||
throw new Exception("The path to php must not be empty. Please set a value for 'php_path' in your configuration file.");
|
throw new Exception("The path to php must not be empty. Please set a value for 'php_path' in your configuration file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$sAuthUser = self::ReadParam('auth_user', '', 'raw_data');
|
if (!isset($aArguments['auth_user'])) {
|
||||||
$sAuthPwd = self::ReadParam('auth_pwd', '', 'raw_data');
|
$sAuthUser = self::ReadParam('auth_user', '', 'raw_data');
|
||||||
$sParamFile = self::GetParamSourceFile('auth_user');
|
|
||||||
if (is_null($sParamFile))
|
|
||||||
{
|
|
||||||
$aArguments['auth_user'] = $sAuthUser;
|
$aArguments['auth_user'] = $sAuthUser;
|
||||||
|
}
|
||||||
|
if (!isset($aArguments['auth_pwd'])) {
|
||||||
|
$sAuthPwd = self::ReadParam('auth_pwd', '', 'raw_data');
|
||||||
$aArguments['auth_pwd'] = $sAuthPwd;
|
$aArguments['auth_pwd'] = $sAuthPwd;
|
||||||
}
|
}
|
||||||
else
|
if (!isset($aArguments['param_file'])) {
|
||||||
{
|
$sParamFile = self::ReadParam('param_file', '', 'raw_data');
|
||||||
$aArguments['param_file'] = $sParamFile;
|
$aArguments['param_file'] = $sParamFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aArgs = array();
|
$aArgs = array();
|
||||||
foreach($aArguments as $sName => $value)
|
foreach($aArguments as $sName => $value)
|
||||||
{
|
{
|
||||||
@@ -1158,6 +1229,7 @@ class utils
|
|||||||
new JSPopupMenuItem('UI:Menu:ExportXLSX', Dict::S('ExcelExporter:ExportMenu'), "ExportListDlg('$sOQL', '', 'xlsx', ".json_encode(Dict::S('ExcelExporter:ExportMenu')).")"),
|
new JSPopupMenuItem('UI:Menu:ExportXLSX', Dict::S('ExcelExporter:ExportMenu'), "ExportListDlg('$sOQL', '', 'xlsx', ".json_encode(Dict::S('ExcelExporter:ExportMenu')).")"),
|
||||||
new SeparatorPopupMenuItem(),
|
new SeparatorPopupMenuItem(),
|
||||||
new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $sUrl.'&printable=1', '_blank'),
|
new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $sUrl.'&printable=1', '_blank'),
|
||||||
|
new JSPopupMenuItem('UI:Menu:SwitchTabMode', Dict::S('UI:Menu:SwitchTabMode'), "SwitchTabMode()"),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1388,13 +1460,12 @@ class utils
|
|||||||
// For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112
|
// For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112
|
||||||
// by setting the SSLVERSION to 3 as done below.
|
// by setting the SSLVERSION to 3 as done below.
|
||||||
$aHeaders = explode("\n", $sOptionnalHeaders);
|
$aHeaders = explode("\n", $sOptionnalHeaders);
|
||||||
|
// N°3267 - Webservices: Fix optional headers not being taken into account
|
||||||
|
// See https://www.php.net/curl_setopt CURLOPT_HTTPHEADER
|
||||||
$aHTTPHeaders = array();
|
$aHTTPHeaders = array();
|
||||||
foreach($aHeaders as $sHeaderString)
|
foreach($aHeaders as $sHeaderString)
|
||||||
{
|
{
|
||||||
if(preg_match('/^([^:]): (.+)$/', $sHeaderString, $aMatches))
|
$aHTTPHeaders[] = trim($sHeaderString);
|
||||||
{
|
|
||||||
$aHTTPHeaders[$aMatches[1]] = $aMatches[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Default options, can be overloaded/extended with the 4th parameter of this method, see above $aCurlOptions
|
// Default options, can be overloaded/extended with the 4th parameter of this method, see above $aCurlOptions
|
||||||
$aOptions = array(
|
$aOptions = array(
|
||||||
@@ -1626,7 +1697,7 @@ class utils
|
|||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
// Compiling SASS
|
// Compiling SASS
|
||||||
$sCss = $oSass->compile($sSassContent);
|
$sCss = $oSass->compile($sSassContent);
|
||||||
set_time_limit($iCurrentMaxExecTime);
|
set_time_limit(intval($iCurrentMaxExecTime));
|
||||||
|
|
||||||
return $sCss;
|
return $sCss;
|
||||||
}
|
}
|
||||||
@@ -2082,33 +2153,38 @@ class utils
|
|||||||
*/
|
*/
|
||||||
public static function GetCacheBusterTimestamp()
|
public static function GetCacheBusterTimestamp()
|
||||||
{
|
{
|
||||||
if(!defined('COMPILATION_TIMESTAMP'))
|
if (!defined('COMPILATION_TIMESTAMP')) {
|
||||||
{
|
|
||||||
return ITOP_VERSION;
|
return ITOP_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return COMPILATION_TIMESTAMP;
|
return COMPILATION_TIMESTAMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string eg : '2_7_0' ITOP_VERSION is '2.7.1-dev'
|
* @return string eg : '2_7_0' ITOP_VERSION is '2.7.1-dev'
|
||||||
*/
|
*/
|
||||||
public static function GetItopVersionWikiSyntax()
|
public static function GetItopVersionWikiSyntax() {
|
||||||
{
|
|
||||||
$sMinorVersion = self::GetItopMinorVersion();
|
$sMinorVersion = self::GetItopMinorVersion();
|
||||||
|
|
||||||
return str_replace('.', '_', $sMinorVersion).'_0';
|
return str_replace('.', '_', $sMinorVersion).'_0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param string $sPatchVersion if non provided, will call GetItopPatchVersion
|
||||||
|
*
|
||||||
* @return string eg 2.7 if ITOP_VERSION is '2.7.0-dev'
|
* @return string eg 2.7 if ITOP_VERSION is '2.7.0-dev'
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function GetItopMinorVersion()
|
public static function GetItopMinorVersion($sPatchVersion = null) {
|
||||||
{
|
if (is_null($sPatchVersion)) {
|
||||||
$sPatchVersion = self::GetItopPatchVersion();
|
$sPatchVersion = self::GetItopPatchVersion();
|
||||||
|
}
|
||||||
$aExplodedVersion = explode('.', $sPatchVersion);
|
$aExplodedVersion = explode('.', $sPatchVersion);
|
||||||
|
|
||||||
if (empty($aExplodedVersion[0]) || empty($aExplodedVersion[1]))
|
if (count($aExplodedVersion) < 2) {
|
||||||
{
|
throw new Exception('iTop version is wrongfully configured!');
|
||||||
|
}
|
||||||
|
if (($aExplodedVersion[0] == '') || ($aExplodedVersion[1] == '')) {
|
||||||
throw new Exception('iTop version is wrongfully configured!');
|
throw new Exception('iTop version is wrongfully configured!');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2118,9 +2194,9 @@ class utils
|
|||||||
/**
|
/**
|
||||||
* @return string eg '2.7.0' if ITOP_VERSION is '2.7.0-dev'
|
* @return string eg '2.7.0' if ITOP_VERSION is '2.7.0-dev'
|
||||||
*/
|
*/
|
||||||
public static function GetItopPatchVersion()
|
public static function GetItopPatchVersion() {
|
||||||
{
|
|
||||||
$aExplodedVersion = explode('-', ITOP_VERSION);
|
$aExplodedVersion = explode('-', ITOP_VERSION);
|
||||||
|
|
||||||
return $aExplodedVersion[0];
|
return $aExplodedVersion[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2153,6 +2229,18 @@ class utils
|
|||||||
return ITOP_REVISION === 'svn';
|
return ITOP_REVISION === 'svn';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if debug is enabled in the current environment.
|
||||||
|
* Currently just checking if the "debug=true" parameter is in the URL, but could be more complex.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function IsDebugEnabled()
|
||||||
|
{
|
||||||
|
return utils::ReadParam('debug') === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://php.net/manual/en/function.finfo-file.php
|
* @see https://php.net/manual/en/function.finfo-file.php
|
||||||
*
|
*
|
||||||
@@ -2316,12 +2404,17 @@ class utils
|
|||||||
return str_replace(' ', '', ucwords(strtr($sInput, '_-', ' ')));
|
return str_replace(' ', '', ucwords(strtr($sInput, '_-', ' ')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function FilterXSS($sHTML)
|
||||||
|
{
|
||||||
|
return str_ireplace('<script', '<script', $sHTML);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \cmdbAbstractObject $oCmdbAbstract
|
* @param \cmdbAbstractObject $oCmdbAbstract
|
||||||
* @param \Exception $oException
|
* @param \Exception $oException
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
* @since 2.7.2/ 2.8.0
|
* @since 2.7.2/ 3.0.0
|
||||||
*/
|
*/
|
||||||
public static function EnrichRaisedException($oCmdbAbstract, $oException)
|
public static function EnrichRaisedException($oCmdbAbstract, $oException)
|
||||||
{
|
{
|
||||||
@@ -2337,4 +2430,11 @@ class utils
|
|||||||
$e = new CoreException($sMessage, null, '', $oException);
|
$e = new CoreException($sMessage, null, '', $oException);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function IsEasterEggAllowed(){
|
||||||
|
return (stripos(ITOP_VERSION, 'alpha') !== false) || utils::IsDevelopmentEnvironment();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -335,20 +335,41 @@ class WizardHelper
|
|||||||
{
|
{
|
||||||
$sResult = $this->m_aData['m_oFieldsMap'][$sFieldName];
|
$sResult = $this->m_aData['m_oFieldsMap'][$sFieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sResult;
|
return $sResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetReturnNotEditableFields()
|
||||||
|
{
|
||||||
|
return $this->m_aData['m_bReturnNotEditableFields'] ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string JS code to be executed for fields update
|
||||||
|
* @since 3.0.0 N°3198
|
||||||
|
*/
|
||||||
|
public function GetJsForUpdateFields()
|
||||||
|
{
|
||||||
|
$sWizardHelperJsVar = ($this->m_aData['m_sWizHelperJsVarName']) ?? 'oWizardHelper'.$this->GetFormPrefix();
|
||||||
|
$sWizardHelperJson = $this->ToJSON();
|
||||||
|
|
||||||
|
return <<<JS
|
||||||
|
{$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson};
|
||||||
|
{$sWizardHelperJsVar}.UpdateFields();
|
||||||
|
JS;
|
||||||
|
}
|
||||||
|
|
||||||
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
|
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
|
||||||
{
|
{
|
||||||
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object
|
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object
|
||||||
$oSet = CMDBObjectSet::FromScratch($sLinkClass);
|
$oSet = CMDBObjectSet::FromScratch($sLinkClass);
|
||||||
foreach($aSet as $aLinkObj)
|
foreach ($aSet as $aLinkObj)
|
||||||
{
|
{
|
||||||
$oLink = MetaModel::NewObject($sLinkClass);
|
$oLink = MetaModel::NewObject($sLinkClass);
|
||||||
foreach($aLinkObj as $sAttCode => $value)
|
foreach ($aLinkObj as $sAttCode => $value)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
|
||||||
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0))
|
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0))
|
||||||
{
|
{
|
||||||
// For external keys: load the target object so that external fields
|
// For external keys: load the target object so that external fields
|
||||||
// get filled too
|
// get filled too
|
||||||
|
|||||||
@@ -1,111 +1,7 @@
|
|||||||
<?php
|
<?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/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class XMLPage
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/XMLPage.php
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT."/application/webpage.class.inc.php");
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
class XMLPage extends WebPage
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* For big XML files, it's better NOT to store everything in memory and output the XML piece by piece
|
|
||||||
*/
|
|
||||||
var $m_bPassThrough;
|
|
||||||
var $m_bHeaderSent;
|
|
||||||
|
|
||||||
function __construct($s_title, $bPassThrough = false)
|
|
||||||
{
|
|
||||||
parent::__construct($s_title);
|
|
||||||
$this->m_bPassThrough = $bPassThrough;
|
|
||||||
$this->m_bHeaderSent = false;
|
|
||||||
$this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET);
|
|
||||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
|
||||||
$this->add_header('Pragma: no-cache');
|
|
||||||
$this->add_header('Expires: 0');
|
|
||||||
$this->add_header('X-Frame-Options: deny');
|
|
||||||
$this->add_header("Content-location: export.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function output()
|
|
||||||
{
|
|
||||||
if (!$this->m_bPassThrough)
|
|
||||||
{
|
|
||||||
// Get the unexpected output but do nothing with it
|
|
||||||
$sTrash = $this->ob_get_clean_safe();
|
|
||||||
|
|
||||||
$sCharset = self::PAGES_CHARSET;
|
|
||||||
$this->s_content = "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n".trim($this->s_content);
|
|
||||||
$this->add_header("Content-Length: ".strlen($this->s_content));
|
|
||||||
foreach($this->a_headers as $s_header)
|
|
||||||
{
|
|
||||||
header($s_header);
|
|
||||||
}
|
|
||||||
echo $this->s_content;
|
|
||||||
}
|
|
||||||
if (class_exists('DBSearch'))
|
|
||||||
{
|
|
||||||
DBSearch::RecordQueryTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add($sText)
|
|
||||||
{
|
|
||||||
if (!$this->m_bPassThrough)
|
|
||||||
{
|
|
||||||
parent::add($sText);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ($this->m_bHeaderSent)
|
|
||||||
{
|
|
||||||
echo $sText;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$s_captured_output = $this->ob_get_clean_safe();
|
|
||||||
foreach($this->a_headers as $s_header)
|
|
||||||
{
|
|
||||||
header($s_header);
|
|
||||||
}
|
|
||||||
$sCharset = self::PAGES_CHARSET;
|
|
||||||
echo "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n";
|
|
||||||
echo trim($s_captured_output);
|
|
||||||
echo trim($this->s_content);
|
|
||||||
echo $sText;
|
|
||||||
$this->m_bHeaderSent = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function small_p($sText)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function table($aConfig, $aData, $aParams = array())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2019 Combodo SARL
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -18,16 +18,31 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks PHP version
|
||||||
|
*
|
||||||
|
* This is a hard-coded check that limits errors : we are stopping for anything < PHP 7.0.0
|
||||||
|
* The "real one" will be done in {@link \SetupUtils::CheckPhpVersion()}
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°2214
|
||||||
|
*/
|
||||||
|
$bIsValidPhpVersion = false;
|
||||||
|
if (PHP_MAJOR_VERSION >= 7) {
|
||||||
|
$bIsValidPhpVersion = true;
|
||||||
|
} else {
|
||||||
|
echo 'Your PHP version ('.PHP_VERSION.') isn\'t supported.';
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
define('ITOP_DEFAULT_ENV', 'production');
|
define('ITOP_DEFAULT_ENV', 'production');
|
||||||
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
|
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
|
||||||
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
|
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
|
||||||
|
|
||||||
if (function_exists('microtime'))
|
if (function_exists('microtime')) {
|
||||||
{
|
|
||||||
$fItopStarted = microtime(true);
|
$fItopStarted = microtime(true);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$fItopStarted = 1000 * time();
|
$fItopStarted = 1000 * time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"type": "project",
|
"type": "project",
|
||||||
"license": "AGPLv3",
|
"license": "AGPLv3",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.6.0",
|
"php": ">=7.1.3",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "5.6.0"
|
"php": "7.2.0"
|
||||||
},
|
},
|
||||||
"vendor-dir": "lib",
|
"vendor-dir": "lib",
|
||||||
"preferred-install": {
|
"preferred-install": {
|
||||||
@@ -52,7 +52,9 @@
|
|||||||
"application",
|
"application",
|
||||||
"sources/application",
|
"sources/application",
|
||||||
"sources/Composer",
|
"sources/Composer",
|
||||||
"sources/Controller"
|
"sources/Controller",
|
||||||
|
"sources/Form",
|
||||||
|
"sources/Renderer"
|
||||||
],
|
],
|
||||||
"exclude-from-classmap": [
|
"exclude-from-classmap": [
|
||||||
"core/dbobjectsearch.class.php",
|
"core/dbobjectsearch.class.php",
|
||||||
@@ -61,6 +63,7 @@
|
|||||||
"core/legacy/querybuildercontextlegacy.class.inc.php",
|
"core/legacy/querybuildercontextlegacy.class.inc.php",
|
||||||
"core/querybuilderexpressions.class.inc.php",
|
"core/querybuilderexpressions.class.inc.php",
|
||||||
"core/legacy/querybuilderexpressionslegacy.class.inc.php",
|
"core/legacy/querybuilderexpressionslegacy.class.inc.php",
|
||||||
|
"application/startup.inc.php",
|
||||||
"application/loginform.class.inc.php",
|
"application/loginform.class.inc.php",
|
||||||
"application/loginbasic.class.inc.php",
|
"application/loginbasic.class.inc.php",
|
||||||
"application/logindefault.class.inc.php",
|
"application/logindefault.class.inc.php",
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ require_once(APPROOT.'/core/email.class.inc.php');
|
|||||||
*/
|
*/
|
||||||
abstract class Action extends cmdbAbstractObject
|
abstract class Action extends cmdbAbstractObject
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -47,7 +51,6 @@ abstract class Action extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_action",
|
"db_table" => "priv_action",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -57,15 +60,32 @@ abstract class Action extends cmdbAbstractObject
|
|||||||
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list", array("linked_class"=>"lnkTriggerAction", "ext_key_to_me"=>"action_id", "ext_key_to_remote"=>"trigger_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list", array("linked_class"=>"lnkTriggerAction", "ext_key_to_me"=>"action_id", "ext_key_to_remote"=>"trigger_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); // Attributes to be displayed for the complete details
|
// - Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
|
||||||
|
// - Attributes to be displayed for a list
|
||||||
|
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status'));
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status')); // Criteria of the std search form
|
// - Criteria of the std search form
|
||||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status'));
|
||||||
|
// - Criteria of the advanced search form
|
||||||
|
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulate the execution of the action and handle failure & logging
|
||||||
|
*
|
||||||
|
* @param \Trigger $oTrigger
|
||||||
|
* @param array $aContextArgs
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
abstract public function DoExecute($oTrigger, $aContextArgs);
|
abstract public function DoExecute($oTrigger, $aContextArgs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public function IsActive()
|
public function IsActive()
|
||||||
{
|
{
|
||||||
switch($this->Get('status'))
|
switch($this->Get('status'))
|
||||||
@@ -79,6 +99,13 @@ abstract class Action extends cmdbAbstractObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the current action status is set on "test"
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public function IsBeingTested()
|
public function IsBeingTested()
|
||||||
{
|
{
|
||||||
switch($this->Get('status'))
|
switch($this->Get('status'))
|
||||||
@@ -99,6 +126,10 @@ abstract class Action extends cmdbAbstractObject
|
|||||||
*/
|
*/
|
||||||
abstract class ActionNotification extends Action
|
abstract class ActionNotification extends Action
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -111,17 +142,20 @@ abstract class ActionNotification extends Action
|
|||||||
"db_table" => "priv_action_notification",
|
"db_table" => "priv_action_notification",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); // Attributes to be displayed for the complete details
|
// - Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
|
||||||
|
// - Attributes to be displayed for a list
|
||||||
|
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status'));
|
||||||
// Search criteria
|
// Search criteria
|
||||||
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
|
// - Criteria of the std search form
|
||||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
// MetaModel::Init_SetZListItems('standard_search', array('name'));
|
||||||
|
// - Criteria of the advanced search form
|
||||||
|
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +166,9 @@ abstract class ActionNotification extends Action
|
|||||||
*/
|
*/
|
||||||
class ActionEmail extends ActionNotification
|
class ActionEmail extends ActionNotification
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -144,7 +181,6 @@ class ActionEmail extends ActionNotification
|
|||||||
"db_table" => "priv_action_email",
|
"db_table" => "priv_action_email",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -152,7 +188,9 @@ class ActionEmail extends ActionNotification
|
|||||||
MetaModel::Init_AddAttribute(new AttributeEmailAddress("test_recipient", array("allowed_values"=>null, "sql"=>"test_recipient", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeEmailAddress("test_recipient", array("allowed_values"=>null, "sql"=>"test_recipient", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("from", array("allowed_values"=>null, "sql"=>"from", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("from", array("allowed_values"=>null, "sql"=>"from", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeString("from_label", array("allowed_values"=>null, "sql"=>"from_label", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("reply_to", array("allowed_values"=>null, "sql"=>"reply_to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("reply_to", array("allowed_values"=>null, "sql"=>"reply_to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeString("reply_to_label", array("allowed_values"=>null, "sql"=>"reply_to_label", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeOQL("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("cc", array("allowed_values"=>null, "sql"=>"cc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeOQL("cc", array("allowed_values"=>null, "sql"=>"cc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("bcc", array("allowed_values"=>null, "sql"=>"bcc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeOQL("bcc", array("allowed_values"=>null, "sql"=>"bcc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
@@ -161,11 +199,15 @@ class ActionEmail extends ActionNotification
|
|||||||
MetaModel::Init_AddAttribute(new AttributeEnum("importance", array("allowed_values"=>new ValueSetEnum('low,normal,high'), "sql"=>"importance", "default_value"=>'normal', "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeEnum("importance", array("allowed_values"=>new ValueSetEnum('low,normal,high'), "sql"=>"importance", "default_value"=>'normal', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list')); // Attributes to be displayed for the complete details
|
// - Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'from_label', 'reply_to', 'reply_to_label', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list'));
|
||||||
|
// - Attributes to be displayed for a list
|
||||||
|
MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject'));
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', array('name','description', 'status', 'subject')); // Criteria of the std search form
|
// - Criteria of the std search form
|
||||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('standard_search', array('name','description', 'status', 'subject'));
|
||||||
|
// - Criteria of the advanced search form
|
||||||
|
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// count the recipients found
|
// count the recipients found
|
||||||
@@ -175,7 +217,18 @@ class ActionEmail extends ActionNotification
|
|||||||
// executed in the background, while making sure that any issue would be reported clearly
|
// executed in the background, while making sure that any issue would be reported clearly
|
||||||
protected $m_aMailErrors; //array of strings explaining the issue
|
protected $m_aMailErrors; //array of strings explaining the issue
|
||||||
|
|
||||||
// returns a the list of emails as a string, or a detailed error description
|
/**
|
||||||
|
* Return a the list of emails as a string, or a detailed error description
|
||||||
|
*
|
||||||
|
* @param string $sRecipAttCode
|
||||||
|
* @param array $aArgs
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
|
*/
|
||||||
protected function FindRecipients($sRecipAttCode, $aArgs)
|
protected function FindRecipients($sRecipAttCode, $aArgs)
|
||||||
{
|
{
|
||||||
$sOQL = $this->Get($sRecipAttCode);
|
$sOQL = $this->Get($sRecipAttCode);
|
||||||
@@ -224,9 +277,7 @@ class ActionEmail extends ActionNotification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Trigger $oTrigger
|
* @inheritDoc
|
||||||
* @param array $aContextArgs
|
|
||||||
*
|
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \CoreUnexpectedValue
|
* @throws \CoreUnexpectedValue
|
||||||
* @throws \CoreWarning
|
* @throws \CoreWarning
|
||||||
@@ -306,6 +357,7 @@ class ActionEmail extends ActionNotification
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
|
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
|
||||||
{
|
{
|
||||||
@@ -316,15 +368,17 @@ class ActionEmail extends ActionNotification
|
|||||||
$this->m_aMailErrors = array();
|
$this->m_aMailErrors = array();
|
||||||
$bRes = false; // until we do succeed in sending the email
|
$bRes = false; // until we do succeed in sending the email
|
||||||
|
|
||||||
// Determine recicipients
|
// Determine recipients
|
||||||
//
|
//
|
||||||
$sTo = $this->FindRecipients('to', $aContextArgs);
|
$sTo = $this->FindRecipients('to', $aContextArgs);
|
||||||
$sCC = $this->FindRecipients('cc', $aContextArgs);
|
$sCC = $this->FindRecipients('cc', $aContextArgs);
|
||||||
$sBCC = $this->FindRecipients('bcc', $aContextArgs);
|
$sBCC = $this->FindRecipients('bcc', $aContextArgs);
|
||||||
|
|
||||||
$sFrom = MetaModel::ApplyParams($this->Get('from'), $aContextArgs);
|
$sFrom = MetaModel::ApplyParams($this->Get('from'), $aContextArgs);
|
||||||
|
$sFromLabel = MetaModel::ApplyParams($this->Get('from_label'), $aContextArgs);
|
||||||
$sReplyTo = MetaModel::ApplyParams($this->Get('reply_to'), $aContextArgs);
|
$sReplyTo = MetaModel::ApplyParams($this->Get('reply_to'), $aContextArgs);
|
||||||
|
$sReplyToLabel = MetaModel::ApplyParams($this->Get('reply_to_label'), $aContextArgs);
|
||||||
|
|
||||||
$sSubject = MetaModel::ApplyParams($this->Get('subject'), $aContextArgs);
|
$sSubject = MetaModel::ApplyParams($this->Get('subject'), $aContextArgs);
|
||||||
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
||||||
|
|
||||||
@@ -347,7 +401,7 @@ class ActionEmail extends ActionNotification
|
|||||||
if (isset($sTo)) $oLog->Set('to', $sTo);
|
if (isset($sTo)) $oLog->Set('to', $sTo);
|
||||||
if (isset($sCC)) $oLog->Set('cc', $sCC);
|
if (isset($sCC)) $oLog->Set('cc', $sCC);
|
||||||
if (isset($sBCC)) $oLog->Set('bcc', $sBCC);
|
if (isset($sBCC)) $oLog->Set('bcc', $sBCC);
|
||||||
if (isset($sFrom)) $oLog->Set('from', $sFrom);
|
if (isset($sFrom)) $oLog->Set('from', empty($sFromLabel) ? $sFrom : "$sFromLabel <$sFrom>");
|
||||||
if (isset($sSubject)) $oLog->Set('subject', $sSubject);
|
if (isset($sSubject)) $oLog->Set('subject', $sSubject);
|
||||||
if (isset($sBody)) $oLog->Set('body', $sBody);
|
if (isset($sBody)) $oLog->Set('body', $sBody);
|
||||||
}
|
}
|
||||||
@@ -367,15 +421,15 @@ class ActionEmail extends ActionNotification
|
|||||||
$sTestBody .= "<li>TO: $sTo</li>\n";
|
$sTestBody .= "<li>TO: $sTo</li>\n";
|
||||||
$sTestBody .= "<li>CC: $sCC</li>\n";
|
$sTestBody .= "<li>CC: $sCC</li>\n";
|
||||||
$sTestBody .= "<li>BCC: $sBCC</li>\n";
|
$sTestBody .= "<li>BCC: $sBCC</li>\n";
|
||||||
$sTestBody .= "<li>From: $sFrom</li>\n";
|
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n": "<li>From: $sFromLabel <$sFrom></li>\n";
|
||||||
$sTestBody .= "<li>Reply-To: $sReplyTo</li>\n";
|
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n": "<li>Reply-To: $sReplyToLabel <$sReplyTo></li>\n";
|
||||||
$sTestBody .= "<li>References: $sReference</li>\n";
|
$sTestBody .= "<li>References: $sReference</li>\n";
|
||||||
$sTestBody .= "</ul>\n";
|
$sTestBody .= "</ul>\n";
|
||||||
$sTestBody .= "</p>\n";
|
$sTestBody .= "</p>\n";
|
||||||
$sTestBody .= "</div>\n";
|
$sTestBody .= "</div>\n";
|
||||||
$oEmail->SetBody($sTestBody, 'text/html', $sStyles);
|
$oEmail->SetBody($sTestBody, 'text/html', $sStyles);
|
||||||
$oEmail->SetRecipientTO($this->Get('test_recipient'));
|
$oEmail->SetRecipientTO($this->Get('test_recipient'));
|
||||||
$oEmail->SetRecipientFrom($sFrom);
|
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
|
||||||
$oEmail->SetReferences($sReference);
|
$oEmail->SetReferences($sReference);
|
||||||
$oEmail->SetMessageId($sMessageId);
|
$oEmail->SetMessageId($sMessageId);
|
||||||
}
|
}
|
||||||
@@ -386,8 +440,8 @@ class ActionEmail extends ActionNotification
|
|||||||
$oEmail->SetRecipientTO($sTo);
|
$oEmail->SetRecipientTO($sTo);
|
||||||
$oEmail->SetRecipientCC($sCC);
|
$oEmail->SetRecipientCC($sCC);
|
||||||
$oEmail->SetRecipientBCC($sBCC);
|
$oEmail->SetRecipientBCC($sBCC);
|
||||||
$oEmail->SetRecipientFrom($sFrom);
|
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
|
||||||
$oEmail->SetRecipientReplyTo($sReplyTo);
|
$oEmail->SetRecipientReplyTo($sReplyTo, $sReplyToLabel);
|
||||||
$oEmail->SetReferences($sReference);
|
$oEmail->SetReferences($sReference);
|
||||||
$oEmail->SetMessageId($sMessageId);
|
$oEmail->SetMessageId($sMessageId);
|
||||||
}
|
}
|
||||||
@@ -439,4 +493,3 @@ class ActionEmail extends ActionNotification
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ class ExecAsyncTask implements iBackgroundProcess
|
|||||||
*/
|
*/
|
||||||
abstract class AsyncTask extends DBObject
|
abstract class AsyncTask extends DBObject
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -77,7 +81,6 @@ abstract class AsyncTask extends DBObject
|
|||||||
"db_table" => "priv_async_task",
|
"db_table" => "priv_async_task",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
|
|
||||||
@@ -285,11 +288,13 @@ abstract class AsyncTask extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws an exception (message and code)
|
* Throws an exception (message and code)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
abstract public function DoProcess();
|
abstract public function DoProcess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the error codes that DoProcess can return by the mean of exceptions
|
* Describes the error codes that DoProcess can return by the mean of exceptions
|
||||||
*/
|
*/
|
||||||
static public function EnumErrorCodes()
|
static public function EnumErrorCodes()
|
||||||
{
|
{
|
||||||
@@ -316,7 +321,6 @@ class AsyncSendEmail extends AsyncTask
|
|||||||
"db_table" => "priv_async_send_email",
|
"db_table" => "priv_async_send_email",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -352,6 +356,11 @@ class AsyncSendEmail extends AsyncTask
|
|||||||
$oNew->DBInsert();
|
$oNew->DBInsert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public function DoProcess()
|
public function DoProcess()
|
||||||
{
|
{
|
||||||
$sMessage = $this->Get('message');
|
$sMessage = $this->Get('message');
|
||||||
|
|||||||
@@ -31,13 +31,9 @@ require_once('ormlinkset.class.inc.php');
|
|||||||
require_once('ormset.class.inc.php');
|
require_once('ormset.class.inc.php');
|
||||||
require_once('ormtagset.class.inc.php');
|
require_once('ormtagset.class.inc.php');
|
||||||
require_once('htmlsanitizer.class.inc.php');
|
require_once('htmlsanitizer.class.inc.php');
|
||||||
require_once(APPROOT.'sources/autoload.php');
|
|
||||||
require_once('customfieldshandler.class.inc.php');
|
require_once('customfieldshandler.class.inc.php');
|
||||||
require_once('ormcustomfieldsvalue.class.inc.php');
|
require_once('ormcustomfieldsvalue.class.inc.php');
|
||||||
require_once('datetimeformat.class.inc.php');
|
require_once('datetimeformat.class.inc.php');
|
||||||
// This should be changed to a use when we go full-namespace
|
|
||||||
require_once(APPROOT.'sources/form/validator/validator.class.inc.php');
|
|
||||||
require_once(APPROOT.'sources/form/validator/notemptyextkeyvalidator.class.inc.php');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MissingColumnException - sent if an attribute is being created but the column is missing in the row
|
* MissingColumnException - sent if an attribute is being created but the column is missing in the row
|
||||||
@@ -295,7 +291,7 @@ abstract class AttributeDefinition
|
|||||||
* @param \DBObject $oHostObject
|
* @param \DBObject $oHostObject
|
||||||
* @param $value Object error if any, null otherwise
|
* @param $value Object error if any, null otherwise
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool|string true for no errors, false or error message otherwise
|
||||||
*/
|
*/
|
||||||
public function CheckValue(DBObject $oHostObject, $value)
|
public function CheckValue(DBObject $oHostObject, $value)
|
||||||
{
|
{
|
||||||
@@ -1030,10 +1026,17 @@ abstract class AttributeDefinition
|
|||||||
$oFormField->AddValidator(new Validator($this->GetValidationPattern()));
|
$oFormField->AddValidator(new Validator($this->GetValidationPattern()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Description
|
||||||
|
$sAttDescription = $this->GetDescription();
|
||||||
|
if(!empty($sAttDescription))
|
||||||
|
{
|
||||||
|
$oFormField->SetDescription($this->GetDescription());
|
||||||
|
}
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
$oFormField->AddMetadata('attribute-code', $this->GetCode());
|
$oFormField->AddMetadata('attribute-code', $this->GetCode());
|
||||||
$oFormField->AddMetadata('attribute-type', get_class($this));
|
$oFormField->AddMetadata('attribute-type', get_class($this));
|
||||||
$oFormField->AddMetadata('attribute-label', utils::HtmlEntities($this->GetLabel()));
|
$oFormField->AddMetadata('attribute-label', $this->GetLabel());
|
||||||
// - Attribute flags
|
// - Attribute flags
|
||||||
$aPossibleAttFlags = MetaModel::EnumPossibleAttributeFlags();
|
$aPossibleAttFlags = MetaModel::EnumPossibleAttributeFlags();
|
||||||
foreach($aPossibleAttFlags as $sFlagCode => $iFlagValue)
|
foreach($aPossibleAttFlags as $sFlagCode => $iFlagValue)
|
||||||
@@ -1050,7 +1053,7 @@ abstract class AttributeDefinition
|
|||||||
// - Value raw
|
// - Value raw
|
||||||
if ($this::IsScalar())
|
if ($this::IsScalar())
|
||||||
{
|
{
|
||||||
$oFormField->AddMetadata('value-raw', utils::HtmlEntities($oObject->Get($this->GetCode())));
|
$oFormField->AddMetadata('value-raw', (string) $oObject->Get($this->GetCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $oFormField;
|
return $oFormField;
|
||||||
@@ -1270,6 +1273,15 @@ abstract class AttributeDefinition
|
|||||||
{
|
{
|
||||||
return (string)$value;
|
return (string)$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return string
|
||||||
|
*/
|
||||||
|
public function GetRenderForDataTable(string $sClassAlias) :string
|
||||||
|
{
|
||||||
|
$sRenderFunction = "return data;";
|
||||||
|
return $sRenderFunction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttributeDashboard extends AttributeDefinition
|
class AttributeDashboard extends AttributeDefinition
|
||||||
@@ -2273,22 +2285,17 @@ class AttributeLinkedSetIndirect extends AttributeLinkedSet
|
|||||||
/** @var \AttributeExternalKey $oExtKeyToRemote */
|
/** @var \AttributeExternalKey $oExtKeyToRemote */
|
||||||
$oExtKeyToRemote = MetaModel::GetAttributeDef($this->GetLinkedClass(), $this->GetExtKeyToRemote());
|
$oExtKeyToRemote = MetaModel::GetAttributeDef($this->GetLinkedClass(), $this->GetExtKeyToRemote());
|
||||||
$sRemoteClass = $oExtKeyToRemote->GetTargetClass();
|
$sRemoteClass = $oExtKeyToRemote->GetTargetClass();
|
||||||
foreach(MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef)
|
foreach(MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) {
|
||||||
{
|
if (!$oRemoteAttDef instanceof AttributeLinkedSetIndirect) {
|
||||||
if (!$oRemoteAttDef instanceof AttributeLinkedSetIndirect)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($oRemoteAttDef->GetLinkedClass() != $this->GetLinkedClass())
|
if ($oRemoteAttDef->GetLinkedClass() != $this->GetLinkedClass()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($oRemoteAttDef->GetExtKeyToMe() != $this->GetExtKeyToRemote())
|
if ($oRemoteAttDef->GetExtKeyToMe() != $this->GetExtKeyToRemote()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($oRemoteAttDef->GetExtKeyToRemote() != $this->GetExtKeyToMe())
|
if ($oRemoteAttDef->GetExtKeyToRemote() != $this->GetExtKeyToMe()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$oRet = $oRemoteAttDef;
|
$oRet = $oRemoteAttDef;
|
||||||
@@ -4994,6 +5001,7 @@ class AttributePhoneNumber extends AttributeString
|
|||||||
|
|
||||||
return '<a class="tel" href="'.$sUrl.'"><span class="text_decoration '.$sUrlDecorationClass.'"></span>'.parent::GetAsHTML($sValue).'</a>';
|
return '<a class="tel" href="'.$sUrl.'"><span class="text_decoration '.$sUrlDecorationClass.'"></span>'.parent::GetAsHTML($sValue).'</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -6654,6 +6662,23 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
|||||||
return (int)$proposedValue;
|
return (int)$proposedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetPrerequisiteAttributes($sClass = null)
|
||||||
|
{
|
||||||
|
$aAttributes = parent::GetPrerequisiteAttributes($sClass);
|
||||||
|
$oExpression = DBSearch::FromOQL($this->GetValuesDef()->GetFilterExpression())->GetCriteria();
|
||||||
|
foreach ($oExpression->GetParameters('this') as $sAttCode)
|
||||||
|
{
|
||||||
|
// Skip the id as it cannot change anyway
|
||||||
|
if ($sAttCode =='id') continue;
|
||||||
|
|
||||||
|
if (!in_array($sAttCode, $aAttributes))
|
||||||
|
{
|
||||||
|
$aAttributes[] = $sAttCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
public function GetMaximumComboLength()
|
public function GetMaximumComboLength()
|
||||||
{
|
{
|
||||||
return $this->GetOptional('max_combo_length', MetaModel::GetConfig()->Get('max_combo_length'));
|
return $this->GetOptional('max_combo_length', MetaModel::GetConfig()->Get('max_combo_length'));
|
||||||
@@ -6759,8 +6784,7 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
|||||||
|
|
||||||
public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
|
public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
|
||||||
{
|
{
|
||||||
if (!is_null($oHostObject))
|
if (!is_null($oHostObject)) {
|
||||||
{
|
|
||||||
return $oHostObject->GetAsHTML($this->GetCode(), $oHostObject);
|
return $oHostObject->GetAsHTML($this->GetCode(), $oHostObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7962,18 +7986,6 @@ class AttributeImage extends AttributeBlob
|
|||||||
return "Image";
|
return "Image";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
* @see AttributeBlob::MakeRealValue()
|
|
||||||
*/
|
|
||||||
public function MakeRealValue($proposedValue, $oHostObj)
|
|
||||||
{
|
|
||||||
$oDoc = parent::MakeRealValue($proposedValue, $oHostObj);
|
|
||||||
|
|
||||||
// The validation of the MIME Type is done by CheckFormat below
|
|
||||||
return $oDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the supplied ormDocument actually contains an image
|
* Check that the supplied ormDocument actually contains an image
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -10309,6 +10321,7 @@ class AttributeEnumSet extends AttributeSet
|
|||||||
return $sRes;
|
return $sRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ormSet $value
|
* @param ormSet $value
|
||||||
* @param string $sSeparator
|
* @param string $sSeparator
|
||||||
@@ -11590,7 +11603,17 @@ class AttributeFriendlyName extends AttributeDefinition
|
|||||||
|
|
||||||
public function GetPrerequisiteAttributes($sClass = null)
|
public function GetPrerequisiteAttributes($sClass = null)
|
||||||
{
|
{
|
||||||
return $this->GetOptional("depends_on", array());
|
// Code duplicated with AttributeObsolescenceFlag
|
||||||
|
$aAttributes = $this->GetOptional("depends_on", array());
|
||||||
|
$oExpression = $this->GetOQLExpression();
|
||||||
|
foreach ($oExpression->ListRequiredFields() as $sClass => $sAttCode)
|
||||||
|
{
|
||||||
|
if (!in_array($sAttCode, $aAttributes))
|
||||||
|
{
|
||||||
|
$aAttributes[] = $sAttCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function IsScalar()
|
public static function IsScalar()
|
||||||
@@ -12822,7 +12845,17 @@ class AttributeObsolescenceFlag extends AttributeBoolean
|
|||||||
|
|
||||||
public function GetPrerequisiteAttributes($sClass = null)
|
public function GetPrerequisiteAttributes($sClass = null)
|
||||||
{
|
{
|
||||||
return $this->GetOptional("depends_on", array());
|
// Code duplicated with AttributeFriendlyName
|
||||||
|
$aAttributes = $this->GetOptional("depends_on", array());
|
||||||
|
$oExpression = $this->GetOQLExpression();
|
||||||
|
foreach ($oExpression->ListRequiredFields() as $sClass => $sAttCode)
|
||||||
|
{
|
||||||
|
if (!in_array($sAttCode, $aAttributes))
|
||||||
|
{
|
||||||
|
$aAttributes[] = $sAttCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsDirectField()
|
public function IsDirectField()
|
||||||
|
|||||||
@@ -185,12 +185,9 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
|
|||||||
static::DEFAULT_MODULE_SETTING_ENABLED
|
static::DEFAULT_MODULE_SETTING_ENABLED
|
||||||
);
|
);
|
||||||
|
|
||||||
$sItopTimeZone = $this->getOConfig()->Get('timezone');
|
|
||||||
$timezone = new DateTimeZone($sItopTimeZone);
|
|
||||||
|
|
||||||
if (!$bEnabled)
|
if (!$bEnabled)
|
||||||
{
|
{
|
||||||
return new DateTime('3000-01-01', $timezone);
|
return new DateTime('3000-01-01');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1st - Interpret the list of days as ordered numbers (monday = 1)
|
// 1st - Interpret the list of days as ordered numbers (monday = 1)
|
||||||
@@ -209,7 +206,7 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
|
|||||||
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')");
|
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')");
|
||||||
}
|
}
|
||||||
|
|
||||||
$oNow = new DateTime($sCurrentTime, $timezone);
|
$oNow = new DateTime($sCurrentTime);
|
||||||
$iNextPos = false;
|
$iNextPos = false;
|
||||||
$sDay = $oNow->format('N');
|
$sDay = $oNow->format('N');
|
||||||
for ($iDay = (int) $sDay; $iDay <= 7; $iDay++)
|
for ($iDay = (int) $sDay; $iDay <= 7; $iDay++)
|
||||||
@@ -244,7 +241,6 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
|
|||||||
$oRet->modify('+'.$iMove.' days');
|
$oRet->modify('+'.$iMove.' days');
|
||||||
}
|
}
|
||||||
list($sHours, $sMinutes) = explode(':', $sProcessTime);
|
list($sHours, $sMinutes) = explode(':', $sProcessTime);
|
||||||
/** @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection non used new parameter in PHP 7.1 */
|
|
||||||
$oRet->setTime((int)$sHours, (int)$sMinutes);
|
$oRet->setTime((int)$sHours, (int)$sMinutes);
|
||||||
|
|
||||||
return $oRet;
|
return $oRet;
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ class BackgroundTask extends DBObject
|
|||||||
"db_table" => "priv_backgroundtask",
|
"db_table" => "priv_backgroundtask",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ class BackgroundTask extends DBObject
|
|||||||
MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", array("allowed_values"=>null, "sql"=>"average_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", array("allowed_values"=>null, "sql"=>"average_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeBoolean("running", array("allowed_values"=>null, "sql"=>"running", "default_value"=>false, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeBoolean("running", array("allowed_values"=>null, "sql"=>"running", "default_value"=>false, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused,removed'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("system_user", array("allowed_values"=>null, "sql"=>"system_user", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("system_user", array("allowed_values"=>null, "sql"=>"system_user", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -948,7 +948,7 @@ class BulkChange
|
|||||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||||
foreach($this->m_aData as $iRow => $aRowData)
|
foreach($this->m_aData as $iRow => $aRowData)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
if (isset($aResult[$iRow]["__STATUS__"]))
|
if (isset($aResult[$iRow]["__STATUS__"]))
|
||||||
{
|
{
|
||||||
// An issue at the earlier steps - skip the rest
|
// An issue at the earlier steps - skip the rest
|
||||||
@@ -1067,13 +1067,13 @@ class BulkChange
|
|||||||
$iObj = $oObj->GetKey();
|
$iObj = $oObj->GetKey();
|
||||||
if (!in_array($iObj, $aVisited))
|
if (!in_array($iObj, $aVisited))
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$iRow++;
|
$iRow++;
|
||||||
$this->UpdateMissingObject($aResult, $iRow, $oObj, $oChange);
|
$this->UpdateMissingObject($aResult, $iRow, $oObj, $oChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(itval($iPreviousTimeLimit));
|
||||||
|
|
||||||
// Fill in the blanks - the result matrix is expected to be 100% complete
|
// Fill in the blanks - the result matrix is expected to be 100% complete
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -52,12 +52,18 @@ class CMDBChange extends DBObject
|
|||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"User", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum('interactive,csv-interactive,csv-import.php,webservice-soap,webservice-rest,synchro-data-source,email-processing,custom-extension'), "sql"=>"origin", "default_value"=>"interactive", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum('interactive,csv-interactive,csv-import.php,webservice-soap,webservice-rest,synchro-data-source,email-processing,custom-extension'), "sql"=>"origin", "default_value"=>"interactive", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to keep track of the author of a given change,
|
/**
|
||||||
// taking into account a variety of cases (contact attached or not, impersonation)
|
* Helper to keep track of the author of a given change,
|
||||||
static public function GetCurrentUserName()
|
* taking into account a variety of cases (contact attached or not, impersonation)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function GetCurrentUserName()
|
||||||
{
|
{
|
||||||
if (UserRights::IsImpersonated())
|
if (UserRights::IsImpersonated())
|
||||||
{
|
{
|
||||||
@@ -70,6 +76,19 @@ class CMDBChange extends DBObject
|
|||||||
return $sUserString;
|
return $sUserString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current user
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \OQLException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetCurrentUserId()
|
||||||
|
{
|
||||||
|
// Note: We might have use only UserRights::GetRealUserId() as it would have done the same thing in the end
|
||||||
|
return UserRights::IsImpersonated() ? UserRights::GetRealUserId() : UserRights::GetUserId();
|
||||||
|
}
|
||||||
|
|
||||||
public function GetUserName()
|
public function GetUserName()
|
||||||
{
|
{
|
||||||
if (preg_match('/^(.*)\\(CSV\\)$/i', $this->Get('userinfo'), $aMatches))
|
if (preg_match('/^(.*)\\(CSV\\)$/i', $this->Get('userinfo'), $aMatches))
|
||||||
@@ -83,5 +102,3 @@ class CMDBChange extends DBObject
|
|||||||
return $sUser;
|
return $sUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -31,7 +31,22 @@
|
|||||||
* @package iTopORM
|
* @package iTopORM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CMDBChangeOp extends DBObject
|
/**
|
||||||
|
* Interface iCMDBChangeOp
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
interface iCMDBChangeOp
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Describe (as a text string) the modifications corresponding to this change
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function GetDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CMDBChangeOp extends DBObject implements iCMDBChangeOp
|
||||||
{
|
{
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
@@ -54,6 +69,7 @@ class CMDBChangeOp extends DBObject
|
|||||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date")));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date")));
|
||||||
MetaModel::Init_AddAttribute(new AttributeExternalField("userinfo", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"userinfo")));
|
MetaModel::Init_AddAttribute(new AttributeExternalField("userinfo", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"userinfo")));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeExternalField("user_id", array("allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"user_id")));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("objclass", array("allowed_values"=>null, "sql"=>"objclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("objclass", array("allowed_values"=>null, "sql"=>"objclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeObjectKey("objkey", array("allowed_values"=>null, "class_attcode"=>"objclass", "sql"=>"objkey", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeObjectKey("objkey", array("allowed_values"=>null, "class_attcode"=>"objclass", "sql"=>"objkey", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
@@ -62,7 +78,7 @@ class CMDBChangeOp extends DBObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
@@ -83,8 +99,6 @@ class CMDBChangeOp extends DBObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record the creation of an object
|
* Record the creation of an object
|
||||||
*
|
*
|
||||||
@@ -92,6 +106,9 @@ class CMDBChangeOp extends DBObject
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpCreate extends CMDBChangeOp
|
class CMDBChangeOpCreate extends CMDBChangeOp
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -110,7 +127,7 @@ class CMDBChangeOpCreate extends CMDBChangeOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
@@ -118,7 +135,6 @@ class CMDBChangeOpCreate extends CMDBChangeOp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record the deletion of an object
|
* Record the deletion of an object
|
||||||
*
|
*
|
||||||
@@ -126,6 +142,9 @@ class CMDBChangeOpCreate extends CMDBChangeOp
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpDelete extends CMDBChangeOp
|
class CMDBChangeOpDelete extends CMDBChangeOp
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -147,16 +166,16 @@ class CMDBChangeOpDelete extends CMDBChangeOp
|
|||||||
// Last friendly name of the object
|
// Last friendly name of the object
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("fname", array("allowed_values"=>null, "sql"=>"fname", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("fname", array("allowed_values"=>null, "sql"=>"fname", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
return Dict::S('Change:ObjectDeleted');
|
return Dict::S('Change:ObjectDeleted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record the modification of an attribute (abstract)
|
* Record the modification of an attribute (abstract)
|
||||||
*
|
*
|
||||||
@@ -164,6 +183,9 @@ class CMDBChangeOpDelete extends CMDBChangeOp
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttribute extends CMDBChangeOp
|
class CMDBChangeOpSetAttribute extends CMDBChangeOp
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -194,6 +216,9 @@ class CMDBChangeOpSetAttribute extends CMDBChangeOp
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -216,10 +241,10 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
@@ -250,7 +275,10 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
public static function Init()
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
(
|
(
|
||||||
@@ -273,10 +301,10 @@ class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
$sTargetObjectClass = $this->Get('objclass');
|
$sTargetObjectClass = $this->Get('objclass');
|
||||||
@@ -307,6 +335,9 @@ class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -329,10 +360,10 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
@@ -363,6 +394,9 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -384,10 +418,10 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||||
@@ -430,11 +464,15 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
|||||||
return $sResult;
|
return $sResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely record the modification of one way encrypted password
|
* Safely record the modification of one way encrypted password
|
||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -456,10 +494,10 @@ class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||||
@@ -495,6 +533,9 @@ class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -516,10 +557,10 @@ class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||||
@@ -558,6 +599,9 @@ class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -579,10 +623,10 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||||
@@ -623,6 +667,9 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -644,10 +691,10 @@ class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
@@ -685,6 +732,9 @@ class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
|
class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -705,8 +755,9 @@ class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
@@ -748,6 +799,9 @@ class CMDBChangeOpSetAttributeHTML extends CMDBChangeOpSetAttributeLongText
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -769,10 +823,10 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
|
|||||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||||
@@ -799,14 +853,18 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
|
|||||||
}
|
}
|
||||||
$oObj = $oMonoObjectSet->Fetch();
|
$oObj = $oMonoObjectSet->Fetch();
|
||||||
$oCaseLog = $oObj->Get($this->Get('attcode'));
|
$oCaseLog = $oObj->Get($this->Get('attcode'));
|
||||||
$iMaxVisibleLength = MetaModel::getConfig()->Get('max_history_case_log_entry_length', 0);
|
|
||||||
$sTextEntry = '<div class="history_entry history_entry_truncated"><div class="history_html_content">'.$oCaseLog->GetEntryAt($this->Get('lastentry')).'</div></div>';
|
$sTextEntry = '<div class="history_entry history_entry_truncated"><div class="history_html_content">'.$oCaseLog->GetEntryAt($this->Get('lastentry')).'</div></div>';
|
||||||
|
|
||||||
$sResult = Dict::Format('Change:AttName_EntryAdded', $sAttName, $sTextEntry);
|
$sResult = Dict::Format('Change:AttName_EntryAdded', $sAttName, $sTextEntry);
|
||||||
}
|
}
|
||||||
return $sResult;
|
return $sResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sRawText
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
protected function ToHtml($sRawText)
|
protected function ToHtml($sRawText)
|
||||||
{
|
{
|
||||||
return str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sRawText, ENT_QUOTES, 'UTF-8'));
|
return str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sRawText, ENT_QUOTES, 'UTF-8'));
|
||||||
@@ -820,6 +878,9 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpPlugin extends CMDBChangeOp
|
class CMDBChangeOpPlugin extends CMDBChangeOp
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -841,10 +902,10 @@ class CMDBChangeOpPlugin extends CMDBChangeOp
|
|||||||
*/
|
*/
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
return $this->Get('description');
|
return $this->Get('description');
|
||||||
@@ -858,6 +919,9 @@ class CMDBChangeOpPlugin extends CMDBChangeOp
|
|||||||
*/
|
*/
|
||||||
abstract class CMDBChangeOpSetAttributeLinks extends CMDBChangeOpSetAttribute
|
abstract class CMDBChangeOpSetAttributeLinks extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -888,6 +952,9 @@ abstract class CMDBChangeOpSetAttributeLinks extends CMDBChangeOpSetAttribute
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLinks
|
class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLinks
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -908,8 +975,8 @@ class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
@@ -952,6 +1019,9 @@ class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLin
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
|
class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -972,8 +1042,8 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
@@ -1039,6 +1109,9 @@ class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
|
|||||||
*/
|
*/
|
||||||
class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute
|
class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -1062,7 +1135,7 @@ class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe (as a text string) the modifications corresponding to this change
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function GetDescription()
|
public function GetDescription()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ abstract class CMDBObject extends DBObject
|
|||||||
// Note: this value is static, but that could be changed because it is sometimes a real issue (see update of interfaces / connected_to
|
// Note: this value is static, but that could be changed because it is sometimes a real issue (see update of interfaces / connected_to
|
||||||
protected static $m_oCurrChange = null;
|
protected static $m_oCurrChange = null;
|
||||||
protected static $m_sInfo = null; // null => the information is built in a standard way
|
protected static $m_sInfo = null; // null => the information is built in a standard way
|
||||||
|
protected static $m_sUserId = null; // null => the user doing the change is unknown
|
||||||
protected static $m_sOrigin = null; // null => the origin is 'interactive'
|
protected static $m_sOrigin = null; // null => the origin is 'interactive'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,6 +155,21 @@ abstract class CMDBObject extends DBObject
|
|||||||
self::$m_sInfo = $sInfo;
|
self::$m_sInfo = $sInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide information about the user doing the change
|
||||||
|
*
|
||||||
|
* @see static::SetTrackInfo
|
||||||
|
* @see static::SetCurrentChange
|
||||||
|
*
|
||||||
|
* @param string $sId ID of the user doing the change, null if not done by a user (eg. background task)
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function SetTrackUserId($sId)
|
||||||
|
{
|
||||||
|
self::$m_sUserId = $sId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides information about the origin of the change
|
* Provides information about the origin of the change
|
||||||
*
|
*
|
||||||
@@ -182,6 +198,25 @@ abstract class CMDBObject extends DBObject
|
|||||||
return self::$m_sInfo;
|
return self::$m_sInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of the user doing the change (defaulting to null)
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \OQLException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
protected static function GetTrackUserId()
|
||||||
|
{
|
||||||
|
if (is_null(self::$m_sUserId))
|
||||||
|
{
|
||||||
|
return CMDBChange::GetCurrentUserId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return self::$m_sUserId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the 'origin' information (defaulting to 'interactive')
|
* Get the 'origin' information (defaulting to 'interactive')
|
||||||
@@ -202,12 +237,21 @@ abstract class CMDBObject extends DBObject
|
|||||||
* Set to {@link $m_oCurrChange} a standard change record (done here 99% of the time, and nearly once per page)
|
* Set to {@link $m_oCurrChange} a standard change record (done here 99% of the time, and nearly once per page)
|
||||||
*
|
*
|
||||||
* The CMDBChange is persisted so that it has a key > 0, and any new CMDBChangeOp can link to it
|
* The CMDBChange is persisted so that it has a key > 0, and any new CMDBChangeOp can link to it
|
||||||
|
*
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreCannotSaveObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \CoreWarning
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \OQLException
|
||||||
*/
|
*/
|
||||||
protected static function CreateChange()
|
protected static function CreateChange()
|
||||||
{
|
{
|
||||||
self::$m_oCurrChange = MetaModel::NewObject("CMDBChange");
|
self::$m_oCurrChange = MetaModel::NewObject("CMDBChange");
|
||||||
self::$m_oCurrChange->Set("date", time());
|
self::$m_oCurrChange->Set("date", time());
|
||||||
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
|
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
|
||||||
|
self::$m_oCurrChange->Set("user_id", self::GetTrackUserId());
|
||||||
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
|
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
|
||||||
self::$m_oCurrChange->DBInsert();
|
self::$m_oCurrChange->DBInsert();
|
||||||
}
|
}
|
||||||
@@ -513,7 +557,14 @@ abstract class CMDBObject extends DBObject
|
|||||||
/**
|
/**
|
||||||
* Helper to ultimately check user rights before writing (Insert, Update or Delete)
|
* Helper to ultimately check user rights before writing (Insert, Update or Delete)
|
||||||
* The check should never fail, because the UI should prevent from such a usage
|
* The check should never fail, because the UI should prevent from such a usage
|
||||||
* Anyhow, if the user has found a workaround... the security gets enforced here
|
* Anyhow, if the user has found a workaround... the security gets enforced here
|
||||||
|
*
|
||||||
|
* @deprecated 3.0.0 N°2591 will be removed in 3.1.0
|
||||||
|
*
|
||||||
|
* @param bool $bSkipStrongSecurity
|
||||||
|
* @param int $iActionCode
|
||||||
|
*
|
||||||
|
* @throws \SecurityException
|
||||||
*/
|
*/
|
||||||
protected function CheckUserRights($bSkipStrongSecurity, $iActionCode)
|
protected function CheckUserRights($bSkipStrongSecurity, $iActionCode)
|
||||||
{
|
{
|
||||||
@@ -538,83 +589,6 @@ abstract class CMDBObject extends DBObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@link DBInsert} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
|
|
||||||
*
|
|
||||||
* @param \CMDBChange $oChange
|
|
||||||
* @param null $bSkipStrongSecurity
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
* @throws \ArchivedObjectException
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \CoreWarning
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \OQLException
|
|
||||||
* @throws \SecurityException
|
|
||||||
*/
|
|
||||||
public function DBInsertTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
|
||||||
{
|
|
||||||
self::SetCurrentChange($oChange);
|
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
|
||||||
$ret = $this->DBInsertTracked_Internal();
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@link DBInsertNoReload} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
|
|
||||||
*
|
|
||||||
* @param \CMDBChange $oChange
|
|
||||||
* @param null $bSkipStrongSecurity
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
* @throws \ArchivedObjectException
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \CoreWarning
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \OQLException
|
|
||||||
* @throws \SecurityException
|
|
||||||
*/
|
|
||||||
public function DBInsertTrackedNoReload(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
|
||||||
{
|
|
||||||
self::SetCurrentChange($oChange);
|
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
|
||||||
$ret = $this->DBInsertTracked_Internal(true);
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@link DBInsert} or {@link DBInsertNoReload} instead
|
|
||||||
*
|
|
||||||
* @param bool $bDoNotReload
|
|
||||||
*
|
|
||||||
* @return integer Identifier of the created object
|
|
||||||
* @throws \ArchivedObjectException
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \CoreWarning
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \OQLException
|
|
||||||
*/
|
|
||||||
protected function DBInsertTracked_Internal($bDoNotReload = false)
|
|
||||||
{
|
|
||||||
if ($bDoNotReload)
|
|
||||||
{
|
|
||||||
$ret = $this->DBInsertNoReload();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$ret = $this->DBInsert();
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DBClone($newKey = null)
|
public function DBClone($newKey = null)
|
||||||
{
|
{
|
||||||
return $this->DBCloneTracked_Internal();
|
return $this->DBCloneTracked_Internal();
|
||||||
@@ -647,24 +621,6 @@ abstract class CMDBObject extends DBObject
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@link DBUpdate} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
|
|
||||||
*
|
|
||||||
* @param \CMDBChange $oChange
|
|
||||||
* @param null $bSkipStrongSecurity
|
|
||||||
*
|
|
||||||
* @return int|void
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \SecurityException
|
|
||||||
*/
|
|
||||||
public function DBUpdateTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
|
||||||
{
|
|
||||||
self::SetCurrentChange($oChange);
|
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
|
||||||
$this->DBUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param null $oDeletionPlan
|
* @param null $oDeletionPlan
|
||||||
@@ -684,31 +640,6 @@ abstract class CMDBObject extends DBObject
|
|||||||
return $this->DBDeleteTracked_Internal($oDeletionPlan);
|
return $this->DBDeleteTracked_Internal($oDeletionPlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@link DBDelete} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
|
|
||||||
*
|
|
||||||
* @param \CMDBChange $oChange
|
|
||||||
* @param null $bSkipStrongSecurity
|
|
||||||
* @param null $oDeletionPlan
|
|
||||||
*
|
|
||||||
* @throws \ArchivedObjectException
|
|
||||||
* @throws \CoreCannotSaveObjectException
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \DeleteException
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \MySQLHasGoneAwayException
|
|
||||||
* @throws \OQLException
|
|
||||||
* @throws \SecurityException
|
|
||||||
*/
|
|
||||||
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
|
|
||||||
{
|
|
||||||
self::SetCurrentChange($oChange);
|
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_DELETE);
|
|
||||||
$this->DBDeleteTracked_Internal($oDeletionPlan);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param null $oDeletionPlan
|
* @param null $oDeletionPlan
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -859,25 +859,6 @@ class CMDBSource
|
|||||||
self::$m_iTransactionLevel = 0;
|
self::$m_iTransactionLevel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated 2.7.0 N°1627 use ItopCounter instead
|
|
||||||
*
|
|
||||||
* @param string $sTable
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \MySQLHasGoneAwayException
|
|
||||||
*/
|
|
||||||
public static function GetNextInsertId($sTable)
|
|
||||||
{
|
|
||||||
$sSQL = "SHOW TABLE STATUS LIKE '$sTable'";
|
|
||||||
$oResult = self::Query($sSQL);
|
|
||||||
$aRow = $oResult->fetch_assoc();
|
|
||||||
|
|
||||||
return $aRow['Auto_increment'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function GetInsertId()
|
public static function GetInsertId()
|
||||||
{
|
{
|
||||||
$iRes = self::$m_oMysqli->insert_id;
|
$iRes = self::$m_oMysqli->insert_id;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -93,7 +93,7 @@ class CoreException extends Exception
|
|||||||
* getTraceAsString() cannot be overrided and it is limited as only current exception stack is returned.
|
* getTraceAsString() cannot be overrided and it is limited as only current exception stack is returned.
|
||||||
* we need stack of all previous exceptions
|
* we need stack of all previous exceptions
|
||||||
* @uses __tostring() already does the work.
|
* @uses __tostring() already does the work.
|
||||||
* @since 2.7.2/ 2.8.0
|
* @since 2.7.2/ 3.0.0
|
||||||
*/
|
*/
|
||||||
public function getFullStackTraceAsString(){
|
public function getFullStackTraceAsString(){
|
||||||
return "" . $this;
|
return "" . $this;
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ EOF
|
|||||||
}
|
}
|
||||||
while($aRow = $oSet->FetchAssoc())
|
while($aRow = $oSet->FetchAssoc())
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$aData = array();
|
$aData = array();
|
||||||
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
||||||
{
|
{
|
||||||
@@ -339,7 +339,7 @@ EOF
|
|||||||
// Restore original date & time formats
|
// Restore original date & time formats
|
||||||
AttributeDateTime::SetFormat($oPrevDateTimeFormat);
|
AttributeDateTime::SetFormat($oPrevDateTimeFormat);
|
||||||
AttributeDate::SetFormat($oPrevDateFormat);
|
AttributeDate::SetFormat($oPrevDateFormat);
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||||
if ($this->aStatusInfo['total'] == 0)
|
if ($this->aStatusInfo['total'] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class CSVParser
|
|||||||
// More time for the next row
|
// More time for the next row
|
||||||
if ($this->m_iTimeLimitPerRow !== null)
|
if ($this->m_iTimeLimitPerRow !== null)
|
||||||
{
|
{
|
||||||
set_time_limit($this->m_iTimeLimitPerRow);
|
set_time_limit(intval($this->m_iTimeLimitPerRow));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected function __AddCellTrimmed($c = null, $aFieldMap = null)
|
protected function __AddCellTrimmed($c = null, $aFieldMap = null)
|
||||||
@@ -194,7 +194,7 @@ class CSVParser
|
|||||||
{
|
{
|
||||||
// Give some time for the first row
|
// Give some time for the first row
|
||||||
$iTimeLimit = ini_get('max_execution_time');
|
$iTimeLimit = ini_get('max_execution_time');
|
||||||
set_time_limit($this->m_iTimeLimitPerRow);
|
set_time_limit(intval($this->m_iTimeLimitPerRow));
|
||||||
}
|
}
|
||||||
for($i = 0; $i <= $iDataLength ; $i++)
|
for($i = 0; $i <= $iDataLength ; $i++)
|
||||||
{
|
{
|
||||||
@@ -255,7 +255,7 @@ class CSVParser
|
|||||||
if ($iTimeLimit !== null)
|
if ($iTimeLimit !== null)
|
||||||
{
|
{
|
||||||
// Restore the previous time limit
|
// Restore the previous time limit
|
||||||
set_time_limit($iTimeLimit);
|
set_time_limit(intval($iTimeLimit));
|
||||||
}
|
}
|
||||||
return $this->m_aDataSet;
|
return $this->m_aDataSet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||||
<user_rights>
|
<user_rights>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile id="1024" _delta="define">
|
<profile id="1024" _delta="define">
|
||||||
|
|||||||
@@ -547,74 +547,64 @@ abstract class DBObject implements iDisplay
|
|||||||
*/
|
*/
|
||||||
public function Set($sAttCode, $value)
|
public function Set($sAttCode, $value)
|
||||||
{
|
{
|
||||||
if ($sAttCode == 'finalclass')
|
if ($sAttCode == 'finalclass') {
|
||||||
{
|
|
||||||
// Ignore it - this attribute is set upon object creation and that's it
|
// Ignore it - this attribute is set upon object creation and that's it
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||||
|
|
||||||
if (!$oAttDef->IsWritable())
|
if (!$oAttDef->IsWritable()) {
|
||||||
{
|
|
||||||
$sClass = get_class($this);
|
$sClass = get_class($this);
|
||||||
throw new Exception("Attempting to set the value on the read-only attribute $sClass::$sAttCode");
|
throw new Exception("Attempting to set the value on the read-only attribute $sClass::$sAttCode");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->m_bIsInDB && !$this->m_bFullyLoaded && !$this->m_bDirty)
|
if ($this->m_bIsInDB && !$this->m_bFullyLoaded && !$this->m_bDirty) {
|
||||||
{
|
|
||||||
// First time Set is called... ensure that the object gets fully loaded
|
// First time Set is called... ensure that the object gets fully loaded
|
||||||
// Otherwise we would lose the values on a further Reload
|
// Otherwise we would lose the values on a further Reload
|
||||||
// + consistency does not make sense !
|
// + consistency does not make sense !
|
||||||
$this->Reload();
|
$this->Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oAttDef->IsExternalKey())
|
if ($oAttDef->IsExternalKey() && is_object($value)) {
|
||||||
{
|
// Setting an external key with a whole object (instead of just an ID)
|
||||||
if (is_object($value))
|
// let's initialize also the external fields that depend on it
|
||||||
{
|
// (useful when building objects in memory and not from a query)
|
||||||
// Setting an external key with a whole object (instead of just an ID)
|
/** @var \AttributeExternalKey $oAttDef */
|
||||||
// let's initialize also the external fields that depend on it
|
if ((get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass()))) {
|
||||||
// (useful when building objects in memory and not from a query)
|
throw new CoreUnexpectedValue("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored");
|
||||||
/** @var \AttributeExternalKey $oAttDef */
|
}
|
||||||
if ( (get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass())))
|
|
||||||
{
|
|
||||||
throw new CoreUnexpectedValue("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
|
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode) {
|
||||||
{
|
$oDef = MetaModel::GetAttributeDef(get_class($this), $sCode);
|
||||||
/** @var \AttributeExternalField $oDef */
|
/** @var \AttributeExternalField $oDef */
|
||||||
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
|
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode)) {
|
||||||
{
|
/** @var \DBObject $value */
|
||||||
/** @var \DBObject $value */
|
$this->m_aCurrValues[$sCode] = $value->Get($oDef->GetExtAttCode());
|
||||||
$this->m_aCurrValues[$sCode] = $value->Get($oDef->GetExtAttCode());
|
$this->m_aLoadedAtt[$sCode] = true;
|
||||||
$this->m_aLoadedAtt[$sCode] = true;
|
}
|
||||||
}
|
elseif ($oDef->IsBasedOnOQLExpression()) {
|
||||||
|
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
|
||||||
|
unset($this->m_aLoadedAtt[$sCode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ($this->m_aCurrValues[$sAttCode] != $value)
|
} else {
|
||||||
{
|
if ($this->m_aCurrValues[$sAttCode] !== $value) {
|
||||||
// Setting an external key, but no any other information is available...
|
// Invalidate dependent fields so that they get reloaded in case they are needed (See Get())
|
||||||
// Invalidate the corresponding fields so that they get reloaded in case they are needed (See Get())
|
//
|
||||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
|
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode) {
|
||||||
{
|
$oDef = MetaModel::GetAttributeDef(get_class($this), $sCode);
|
||||||
/** @var \AttributeExternalKey $oDef */
|
if (($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode)) || $oDef->IsBasedOnOQLExpression()) {
|
||||||
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
|
|
||||||
{
|
|
||||||
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
|
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
|
||||||
unset($this->m_aLoadedAtt[$sCode]);
|
unset($this->m_aLoadedAtt[$sCode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($oAttDef->IsLinkSet() && ($value != null))
|
if ($oAttDef->IsLinkSet() && ($value != null)) {
|
||||||
{
|
|
||||||
$realvalue = clone $this->m_aCurrValues[$sAttCode];
|
$realvalue = clone $this->m_aCurrValues[$sAttCode];
|
||||||
$realvalue->UpdateFromCompleteList($value);
|
$realvalue->UpdateFromCompleteList($value);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$realvalue = $oAttDef->MakeRealValue($value, $this);
|
$realvalue = $oAttDef->MakeRealValue($value, $this);
|
||||||
}
|
}
|
||||||
$this->_Set($sAttCode, $realvalue);
|
$this->_Set($sAttCode, $realvalue);
|
||||||
@@ -787,20 +777,20 @@ abstract class DBObject implements iDisplay
|
|||||||
{
|
{
|
||||||
// Standard case... we have the information directly
|
// Standard case... we have the information directly
|
||||||
}
|
}
|
||||||
elseif ($this->m_bIsInDB && !$this->m_bDirty)
|
elseif ($this->m_bIsInDB && !$this->m_bFullyLoaded && !$this->m_bDirty)
|
||||||
{
|
{
|
||||||
// Lazy load (polymorphism): complete by reloading the entire object
|
// Lazy load (polymorphism): complete by reloading the entire object
|
||||||
// #@# non-scalar attributes.... handle that differently?
|
|
||||||
$oKPI = new ExecutionKPI();
|
$oKPI = new ExecutionKPI();
|
||||||
$this->Reload();
|
$this->Reload();
|
||||||
$oKPI->ComputeStats('Reload', get_class($this).'/'.$sAttCode);
|
$oKPI->ComputeStats('Reload', get_class($this).'/'.$sAttCode);
|
||||||
}
|
}
|
||||||
elseif ($sAttCode == 'friendlyname')
|
elseif ($oAttDef->IsBasedOnOQLExpression())
|
||||||
{
|
{
|
||||||
// The friendly name is not computed and the object is dirty
|
// Recompute -which is likely to call Get()
|
||||||
// Todo: implement the computation of the friendly name based on sprintf()
|
//
|
||||||
//
|
/** @var AttributeFriendlyName|\AttributeObsolescenceFlag $oAttDef */
|
||||||
$this->m_aCurrValues[$sAttCode] = '';
|
$this->m_aCurrValues[$sAttCode] = $this->EvaluateExpression($oAttDef->GetOQLExpression());
|
||||||
|
$this->m_aLoadedAtt[$sAttCode] = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1683,6 +1673,7 @@ abstract class DBObject implements iDisplay
|
|||||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||||
{
|
{
|
||||||
$iFlags = 0; // By default (if no life cycle) no flag at all
|
$iFlags = 0; // By default (if no life cycle) no flag at all
|
||||||
|
$sClass = get_class($this);
|
||||||
|
|
||||||
$aReadOnlyAtts = $this->GetReadOnlyAttributes();
|
$aReadOnlyAtts = $this->GetReadOnlyAttributes();
|
||||||
if (($aReadOnlyAtts != null) && (in_array($sAttCode, $aReadOnlyAtts)))
|
if (($aReadOnlyAtts != null) && (in_array($sAttCode, $aReadOnlyAtts)))
|
||||||
@@ -1690,16 +1681,16 @@ abstract class DBObject implements iDisplay
|
|||||||
return OPT_ATT_READONLY;
|
return OPT_ATT_READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
|
if (MetaModel::HasLifecycle($sClass))
|
||||||
if (!empty($sStateAttCode))
|
|
||||||
{
|
{
|
||||||
if ($sTargetState != '')
|
if ($sTargetState != '')
|
||||||
{
|
{
|
||||||
$iFlags = MetaModel::GetAttributeFlags(get_class($this), $sTargetState, $sAttCode);
|
$iFlags = MetaModel::GetAttributeFlags($sClass, $sTargetState, $sAttCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$iFlags = MetaModel::GetAttributeFlags(get_class($this), $this->Get($sStateAttCode), $sAttCode);
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
|
$iFlags = MetaModel::GetAttributeFlags($sClass, $this->Get($sStateAttCode), $sAttCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$aReasons = array();
|
$aReasons = array();
|
||||||
@@ -1752,10 +1743,10 @@ abstract class DBObject implements iDisplay
|
|||||||
public function GetTransitionFlags($sAttCode, $sStimulus, &$aReasons = array(), $sOriginState = '')
|
public function GetTransitionFlags($sAttCode, $sStimulus, &$aReasons = array(), $sOriginState = '')
|
||||||
{
|
{
|
||||||
$iFlags = 0; // By default (if no lifecycle) no flag at all
|
$iFlags = 0; // By default (if no lifecycle) no flag at all
|
||||||
|
$sClass = get_class($this);
|
||||||
|
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
|
|
||||||
// If no state attribute, there is no lifecycle
|
// If no state attribute, there is no lifecycle
|
||||||
if (empty($sStateAttCode))
|
if (!MetaModel::HasLifecycle($sClass))
|
||||||
{
|
{
|
||||||
return $iFlags;
|
return $iFlags;
|
||||||
}
|
}
|
||||||
@@ -1763,6 +1754,7 @@ abstract class DBObject implements iDisplay
|
|||||||
// Retrieving current state if necessary
|
// Retrieving current state if necessary
|
||||||
if ($sOriginState === '')
|
if ($sOriginState === '')
|
||||||
{
|
{
|
||||||
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
$sOriginState = $this->Get($sStateAttCode);
|
$sOriginState = $this->Get($sStateAttCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1770,7 +1762,7 @@ abstract class DBObject implements iDisplay
|
|||||||
$iAttributeFlags = $this->GetAttributeFlags($sAttCode, $aReasons, $sOriginState);
|
$iAttributeFlags = $this->GetAttributeFlags($sAttCode, $aReasons, $sOriginState);
|
||||||
|
|
||||||
// Retrieving transition flags
|
// Retrieving transition flags
|
||||||
$iTransitionFlags = MetaModel::GetTransitionFlags(get_class($this), $sOriginState, $sStimulus, $sAttCode);
|
$iTransitionFlags = MetaModel::GetTransitionFlags($sClass, $sOriginState, $sStimulus, $sAttCode);
|
||||||
|
|
||||||
// Merging transition flags with attribute flags
|
// Merging transition flags with attribute flags
|
||||||
$iFlags = $iTransitionFlags | $iAttributeFlags;
|
$iFlags = $iTransitionFlags | $iAttributeFlags;
|
||||||
@@ -1821,10 +1813,12 @@ abstract class DBObject implements iDisplay
|
|||||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||||
{
|
{
|
||||||
$iFlags = 0;
|
$iFlags = 0;
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
|
$sClass = get_class($this);
|
||||||
if (!empty($sStateAttCode))
|
|
||||||
|
if (MetaModel::HasLifecycle($sClass))
|
||||||
{
|
{
|
||||||
$iFlags = MetaModel::GetInitialStateAttributeFlags(get_class($this), $this->Get($sStateAttCode), $sAttCode);
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
|
$iFlags = MetaModel::GetInitialStateAttributeFlags($sClass, $this->Get($sStateAttCode), $sAttCode);
|
||||||
}
|
}
|
||||||
return $iFlags; // No need to care about the synchro flags since we'll be creating a new object anyway
|
return $iFlags; // No need to care about the synchro flags since we'll be creating a new object anyway
|
||||||
}
|
}
|
||||||
@@ -1832,13 +1826,13 @@ abstract class DBObject implements iDisplay
|
|||||||
/**
|
/**
|
||||||
* Check if the given (or current) value is suitable for the attribute
|
* Check if the given (or current) value is suitable for the attribute
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @api-advanced
|
* @api-advanced
|
||||||
*
|
|
||||||
* @param string $sAttCode
|
|
||||||
* @param boolean|string $value true if successful, the error description otherwise
|
|
||||||
*
|
*
|
||||||
* @return bool|string
|
* @param string $sAttCode
|
||||||
|
* @param mixed $value if not passed, then will get value using Get method
|
||||||
|
*
|
||||||
|
* @return bool|string true if successful, the error description otherwise
|
||||||
* @throws \ArchivedObjectException
|
* @throws \ArchivedObjectException
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \OQLException
|
* @throws \OQLException
|
||||||
@@ -2118,23 +2112,75 @@ abstract class DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
|
|
||||||
$aChildClassesWithRuleDisabled = MetaModel::GetChildClassesWithDisabledUniquenessRule($sRuleRootClass, $sUniquenessRuleId);
|
$aChildClassesWithRuleDisabled = MetaModel::GetChildClassesWithDisabledUniquenessRule($sRuleRootClass, $sUniquenessRuleId);
|
||||||
if (!empty($aChildClassesWithRuleDisabled))
|
if (!empty($aChildClassesWithRuleDisabled)) {
|
||||||
{
|
|
||||||
$oUniquenessQuery->AddConditionForInOperatorUsingParam('finalclass', $aChildClassesWithRuleDisabled, false);
|
$oUniquenessQuery->AddConditionForInOperatorUsingParam('finalclass', $aChildClassesWithRuleDisabled, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $oUniquenessQuery;
|
return $oUniquenessQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @uses m_aCheckWarnings to log to user duplicates found
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°3198 check duplicates if necessary :<br>
|
||||||
|
* Before we could only add or remove lnk using the uilinks widget. This widget has a filter based on existing values, and so
|
||||||
|
* forbids to add duplicates.<br>
|
||||||
|
* Now we can modify existing entries using the extkey widget, and the widget doesn't have (yet !) such
|
||||||
|
* a filter. The widget will be updated later on, but as a first step we're checking for duplicates server side. This is a non
|
||||||
|
* blocking warning, as it was already possible to add duplicates by other means.
|
||||||
|
*/
|
||||||
|
protected function DoCheckLinkedSetDuplicates($sAttCode, $value)
|
||||||
|
{
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||||
|
|
||||||
|
if (!($oAttDef instanceof AttributeLinkedSetIndirect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($oAttDef->DuplicatesAllowed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \ormLinkSet $value */
|
||||||
|
$aModifiedLnk = $value->ListModifiedLinks();
|
||||||
|
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||||
|
$aExistingRemotesId = $value->GetColumnAsArray($sExtKeyToRemote, true);
|
||||||
|
$aExistingRemotesFriendlyName = $value->GetColumnAsArray($sExtKeyToRemote.'_friendlyname', true);
|
||||||
|
$aDuplicatesFields = [];
|
||||||
|
foreach ($aModifiedLnk as $oModifiedLnk) {
|
||||||
|
$iModifiedLnkId = $oModifiedLnk->GetKey();
|
||||||
|
$iModifiedLnkRemoteId = $oModifiedLnk->Get($sExtKeyToRemote);
|
||||||
|
$aExistingRemotesIdToCheck = array_filter($aExistingRemotesId, function ($iLnkKey) use ($iModifiedLnkId) {
|
||||||
|
return ($iLnkKey != $iModifiedLnkId);
|
||||||
|
}, ARRAY_FILTER_USE_KEY);
|
||||||
|
|
||||||
|
if (!in_array($iModifiedLnkRemoteId, $aExistingRemotesIdToCheck, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iLnkId = $oModifiedLnk->GetKey();
|
||||||
|
$aDuplicatesFields[] = $aExistingRemotesFriendlyName[$iLnkId];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($aDuplicatesFields)) {
|
||||||
|
$this->m_aCheckWarnings[] = Dict::Format('Core:AttributeLinkedSetDuplicatesFound',
|
||||||
|
$oAttDef->GetLabel(),
|
||||||
|
implode(', ', $aDuplicatesFields));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check integrity rules (before inserting or updating the object)
|
* Check integrity rules (before inserting or updating the object)
|
||||||
*
|
*
|
||||||
* **This method is not meant to be called directly, use DBObject::CheckToWrite()!**
|
* **This method is not meant to be called directly, use DBObject::CheckToWrite()!**
|
||||||
* Errors should be inserted in $m_aCheckIssues and $m_aCheckWarnings arrays
|
* Errors should be inserted in $m_aCheckIssues and $m_aCheckWarnings arrays
|
||||||
*
|
*
|
||||||
* @overwritable-hook You can extend this method in order to provide your own logic.
|
* @overwritable-hook You can extend this method in order to provide your own logic.
|
||||||
* @see CheckToWrite()
|
* @see CheckToWrite()
|
||||||
* @see $m_aCheckIssues
|
* @see $m_aCheckIssues
|
||||||
* @see $m_aCheckWarnings
|
* @see $m_aCheckWarnings
|
||||||
*
|
*
|
||||||
* @throws \ArchivedObjectException
|
* @throws \ArchivedObjectException
|
||||||
@@ -2150,14 +2196,14 @@ abstract class DBObject implements iDisplay
|
|||||||
|
|
||||||
$aChanges = $this->ListChanges();
|
$aChanges = $this->ListChanges();
|
||||||
|
|
||||||
foreach($aChanges as $sAttCode => $value)
|
foreach($aChanges as $sAttCode => $value) {
|
||||||
{
|
|
||||||
$res = $this->CheckValue($sAttCode);
|
$res = $this->CheckValue($sAttCode);
|
||||||
if ($res !== true)
|
if ($res !== true) {
|
||||||
{
|
|
||||||
// $res contains the error description
|
// $res contains the error description
|
||||||
$this->m_aCheckIssues[] = "Unexpected value for attribute '$sAttCode': $res";
|
$this->m_aCheckIssues[] = "Unexpected value for attribute '$sAttCode': $res";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->DoCheckLinkedSetDuplicates($sAttCode, $value);
|
||||||
}
|
}
|
||||||
if (count($this->m_aCheckIssues) > 0)
|
if (count($this->m_aCheckIssues) > 0)
|
||||||
{
|
{
|
||||||
@@ -2960,46 +3006,6 @@ abstract class DBObject implements iDisplay
|
|||||||
return $this->m_iKey;
|
return $this->m_iKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBInsert()} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
|
|
||||||
*
|
|
||||||
* @param CMDBChange $oChange
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
* @throws CoreException
|
|
||||||
*/
|
|
||||||
public function DBInsertTracked(CMDBChange $oChange)
|
|
||||||
{
|
|
||||||
CMDBObject::SetCurrentChange($oChange);
|
|
||||||
return $this->DBInsert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBInsertNoReload()} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
|
|
||||||
*
|
|
||||||
* @param CMDBChange $oChange
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
* @throws ArchivedObjectException
|
|
||||||
* @throws CoreCannotSaveObjectException
|
|
||||||
* @throws CoreException
|
|
||||||
* @throws CoreUnexpectedValue
|
|
||||||
* @throws CoreWarning
|
|
||||||
* @throws MySQLException
|
|
||||||
* @throws OQLException
|
|
||||||
*/
|
|
||||||
public function DBInsertTrackedNoReload(CMDBChange $oChange)
|
|
||||||
{
|
|
||||||
CMDBObject::SetCurrentChange($oChange);
|
|
||||||
return $this->DBInsertNoReload();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the current object into the database
|
* Creates a copy of the current object into the database
|
||||||
*
|
*
|
||||||
@@ -3358,25 +3364,6 @@ abstract class DBObject implements iDisplay
|
|||||||
$this->m_aPreviousValuesForUpdatedAttributes = $aPreviousValuesForUpdatedAttributes;
|
$this->m_aPreviousValuesForUpdatedAttributes = $aPreviousValuesForUpdatedAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBUpdate()} instead, that will automatically create and persist a CMDBChange object.
|
|
||||||
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
|
|
||||||
*
|
|
||||||
* @param CMDBChange $oChange
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
* @throws CoreCannotSaveObjectException
|
|
||||||
* @throws CoreException
|
|
||||||
*/
|
|
||||||
public function DBUpdateTracked(CMDBChange $oChange)
|
|
||||||
{
|
|
||||||
CMDBObject::SetCurrentChange($oChange);
|
|
||||||
return $this->DBUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the current changes persistent - clever wrapper for Insert or Update
|
* Make the current changes persistent - clever wrapper for Insert or Update
|
||||||
*
|
*
|
||||||
@@ -3612,7 +3599,7 @@ abstract class DBObject implements iDisplay
|
|||||||
// As a temporary fix: delete only the objects that are still to be deleted...
|
// As a temporary fix: delete only the objects that are still to be deleted...
|
||||||
if ($oToDelete->m_bIsInDB)
|
if ($oToDelete->m_bIsInDB)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oToDelete->DBDeleteSingleObject();
|
$oToDelete->DBDeleteSingleObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3627,43 +3614,18 @@ abstract class DBObject implements iDisplay
|
|||||||
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef)
|
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef)
|
||||||
{
|
{
|
||||||
$oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
|
$oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oToUpdate->DBUpdate();
|
$oToUpdate->DBUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
|
|
||||||
return $oDeletionPlan;
|
return $oDeletionPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBDelete()} instead.
|
|
||||||
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
|
|
||||||
*
|
|
||||||
* @param CMDBChange $oChange
|
|
||||||
* @param boolean $bSkipStrongSecurity
|
|
||||||
* @param \DeletionPlan $oDeletionPlan
|
|
||||||
*
|
|
||||||
* @throws ArchivedObjectException
|
|
||||||
* @throws CoreCannotSaveObjectException
|
|
||||||
* @throws CoreException
|
|
||||||
* @throws CoreUnexpectedValue
|
|
||||||
* @throws DeleteException
|
|
||||||
* @throws MySQLException
|
|
||||||
* @throws MySQLHasGoneAwayException
|
|
||||||
* @throws OQLException
|
|
||||||
*/
|
|
||||||
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
|
|
||||||
{
|
|
||||||
CMDBObject::SetCurrentChange($oChange);
|
|
||||||
$this->DBDelete($oDeletionPlan);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
@@ -3673,11 +3635,12 @@ abstract class DBObject implements iDisplay
|
|||||||
*/
|
*/
|
||||||
public function EnumTransitions()
|
public function EnumTransitions()
|
||||||
{
|
{
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
|
$sClass = get_class($this);
|
||||||
if (empty($sStateAttCode)) return array();
|
if (!MetaModel::HasLifecycle($sClass)) return array();
|
||||||
|
|
||||||
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
$sState = $this->Get($sStateAttCode);
|
$sState = $this->Get($sStateAttCode);
|
||||||
return MetaModel::EnumTransitions(get_class($this), $sState);
|
return MetaModel::EnumTransitions($sClass, $sState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3723,14 +3686,14 @@ abstract class DBObject implements iDisplay
|
|||||||
public function ApplyStimulus($sStimulusCode, $bDoNotWrite = false)
|
public function ApplyStimulus($sStimulusCode, $bDoNotWrite = false)
|
||||||
{
|
{
|
||||||
$sClass = get_class($this);
|
$sClass = get_class($this);
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
if (!MetaModel::HasLifecycle($sClass))
|
||||||
if (empty($sStateAttCode))
|
|
||||||
{
|
{
|
||||||
throw new CoreException('No lifecycle for the class '.$sClass);
|
throw new CoreException('No lifecycle for the class '.$sClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyHelpers::CheckKeyInArray('object lifecycle stimulus', $sStimulusCode, MetaModel::EnumStimuli($sClass));
|
MyHelpers::CheckKeyInArray('object lifecycle stimulus', $sStimulusCode, MetaModel::EnumStimuli($sClass));
|
||||||
|
|
||||||
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
$aStateTransitions = $this->EnumTransitions();
|
$aStateTransitions = $this->EnumTransitions();
|
||||||
if (!array_key_exists($sStimulusCode, $aStateTransitions))
|
if (!array_key_exists($sStimulusCode, $aStateTransitions))
|
||||||
{
|
{
|
||||||
@@ -4458,22 +4421,7 @@ abstract class DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* implement relations
|
|
||||||
*
|
|
||||||
* Return an empty set for the parent of all
|
|
||||||
*
|
|
||||||
* this way of implementing the relations suffers limitations (not handling the redundancy)
|
|
||||||
* and you should consider defining those things in XML
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public static function GetRelationQueries($sRelCode)
|
|
||||||
{
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserved: do not overload
|
* Reserved: do not overload
|
||||||
*
|
*
|
||||||
@@ -4484,72 +4432,6 @@ abstract class DBObject implements iDisplay
|
|||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Use GetRelatedObjectsDown/Up instead to take redundancy into account
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array())
|
|
||||||
{
|
|
||||||
// Temporary patch: until the impact analysis GUI gets rewritten,
|
|
||||||
// let's consider that "depends on" is equivalent to "impacts/up"
|
|
||||||
// The current patch has been implemented in DBObject and MetaModel
|
|
||||||
$sHackedRelCode = $sRelCode;
|
|
||||||
$bDown = true;
|
|
||||||
if ($sRelCode == 'depends on')
|
|
||||||
{
|
|
||||||
$sHackedRelCode = 'impacts';
|
|
||||||
$bDown = false;
|
|
||||||
}
|
|
||||||
foreach (MetaModel::EnumRelationQueries(get_class($this), $sHackedRelCode, $bDown) as $sDummy => $aQueryInfo)
|
|
||||||
{
|
|
||||||
$sQuery = $bDown ? $aQueryInfo['sQueryDown'] : $aQueryInfo['sQueryUp'];
|
|
||||||
//$bPropagate = $aQueryInfo["bPropagate"];
|
|
||||||
//$iDepth = $bPropagate ? $iMaxDepth - 1 : 0;
|
|
||||||
$iDepth = $iMaxDepth - 1;
|
|
||||||
|
|
||||||
// Note: the loop over the result set has been written in an unusual way for error reporting purposes
|
|
||||||
// In the case of a wrong query parameter name, the error occurs on the first call to Fetch,
|
|
||||||
// thus we need to have this first call into the try/catch, but
|
|
||||||
// we do NOT want to nest the try/catch for the error message to be clear
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$oFlt = DBObjectSearch::FromOQL($sQuery);
|
|
||||||
$oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgsForQuery());
|
|
||||||
$oObj = $oObjSet->Fetch();
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
$sClassOfDefinition = $aQueryInfo['_legacy_'] ? get_class($this).'(or a parent)::GetRelationQueries()' : $aQueryInfo['sDefinedInClass'];
|
|
||||||
throw new Exception("Wrong query for the relation $sRelCode/$sClassOfDefinition/{$aQueryInfo['sNeighbour']}: ".$e->getMessage());
|
|
||||||
}
|
|
||||||
if ($oObj)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
|
|
||||||
$sObjKey = $oObj->GetKey();
|
|
||||||
if (array_key_exists($sRootClass, $aResults))
|
|
||||||
{
|
|
||||||
if (array_key_exists($sObjKey, $aResults[$sRootClass]))
|
|
||||||
{
|
|
||||||
continue; // already visited, skip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$aResults[$sRootClass][$sObjKey] = $oObj;
|
|
||||||
if ($iDepth > 0)
|
|
||||||
{
|
|
||||||
$oObj->GetRelatedObjects($sRelCode, $iDepth, $aResults);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ($oObj = $oObjSet->Fetch());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $aResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the "RelatedObjects" (forward or "down" direction) for the object
|
* Compute the "RelatedObjects" (forward or "down" direction) for the object
|
||||||
* for the specified relation
|
* for the specified relation
|
||||||
@@ -4683,7 +4565,7 @@ abstract class DBObject implements iDisplay
|
|||||||
{
|
{
|
||||||
foreach ($aPotentialDeletes as $sRemoteExtKey => $aData)
|
foreach ($aPotentialDeletes as $sRemoteExtKey => $aData)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
|
|
||||||
/** @var \AttributeExternalKey $oAttDef */
|
/** @var \AttributeExternalKey $oAttDef */
|
||||||
$oAttDef = $aData['attribute'];
|
$oAttDef = $aData['attribute'];
|
||||||
@@ -4715,7 +4597,7 @@ abstract class DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5461,10 +5343,10 @@ abstract class DBObject implements iDisplay
|
|||||||
*/
|
*/
|
||||||
public static function MakeDefaultInstance($sClass)
|
public static function MakeDefaultInstance($sClass)
|
||||||
{
|
{
|
||||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
|
||||||
$oObj = MetaModel::NewObject($sClass);
|
$oObj = MetaModel::NewObject($sClass);
|
||||||
if (!empty($sStateAttCode))
|
if (MetaModel::HasLifecycle($sClass))
|
||||||
{
|
{
|
||||||
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
$sTargetState = MetaModel::GetDefaultState($sClass);
|
$sTargetState = MetaModel::GetDefaultState($sClass);
|
||||||
$oObj->Set($sStateAttCode, $sTargetState);
|
$oObj->Set($sStateAttCode, $sTargetState);
|
||||||
}
|
}
|
||||||
@@ -5561,5 +5443,33 @@ abstract class DBObject implements iDisplay
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function EvaluateExpression(Expression $oExpression)
|
||||||
|
{
|
||||||
|
$aFields = $oExpression->ListRequiredFields();
|
||||||
|
$aArgs = array();
|
||||||
|
foreach ($aFields as $sFieldDesc)
|
||||||
|
{
|
||||||
|
$aFieldParts = explode('.', $sFieldDesc);
|
||||||
|
if (count($aFieldParts) == 2)
|
||||||
|
{
|
||||||
|
$sClass = $aFieldParts[0];
|
||||||
|
$sAttCode = $aFieldParts[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sClass = get_class($this);
|
||||||
|
$sAttCode = $aFieldParts[0];
|
||||||
|
}
|
||||||
|
if (get_class($this) != $sClass) continue;
|
||||||
|
if (!MetaModel::IsValidAttCode(get_class($this), $sAttCode)) continue;
|
||||||
|
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||||
|
$aSQLValues = $oAttDef->GetSQLValues($this->m_aCurrValues[$sAttCode]);
|
||||||
|
$value = reset($aSQLValues);
|
||||||
|
$aArgs[$sFieldDesc] = $value;
|
||||||
|
}
|
||||||
|
return $oExpression->Evaluate($aArgs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -907,10 +907,14 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DBObjectSearch $oFilter (can be modified)
|
* Add a link to another filter, using an extkey already present in current filter
|
||||||
* @param $sExtKeyAttCode
|
*
|
||||||
|
* @param DBObjectSearch $oFilter filter to join to (can be modified)
|
||||||
|
* @param string $sExtKeyAttCode extkey present in current filter, that allows to points to $oFilter
|
||||||
* @param int $iOperatorCode
|
* @param int $iOperatorCode
|
||||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
* @param array $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed.
|
||||||
|
* Doesn't change existing alias, use {@link \DBObjectSearch::RenameAlias()} for that.
|
||||||
|
*
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
* @throws CoreWarning
|
* @throws CoreWarning
|
||||||
*/
|
*/
|
||||||
@@ -1372,7 +1376,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
|
|
||||||
// Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams($bExclude magic params)
|
// Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams($bExclude magic params)
|
||||||
$aNakedMagicArguments = array();
|
$aNakedMagicArguments = array();
|
||||||
foreach (MetaModel::PrepareQueryArguments(array()) as $sArgName => $value)
|
foreach (MetaModel::PrepareQueryArguments(array(),array(), $this->GetExpectedArguments()) as $sArgName => $value)
|
||||||
{
|
{
|
||||||
$iPos = strpos($sArgName, '->object()');
|
$iPos = strpos($sArgName, '->object()');
|
||||||
if ($iPos === false)
|
if ($iPos === false)
|
||||||
@@ -1435,7 +1439,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
$aParams = array_merge($aContextParams, $this->m_aParams);
|
$aParams = array_merge($aContextParams, $this->m_aParams);
|
||||||
}
|
}
|
||||||
$aParams = MetaModel::PrepareQueryArguments($aParams);
|
$aParams = MetaModel::PrepareQueryArguments($aParams,array(), $this->GetExpectedArguments());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1628,7 +1632,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
$aRet = array('selects' => array(), 'joins' => array(), 'where' => array());
|
$aRet = array('selects' => array(), 'joins' => array(), 'where' => array());
|
||||||
|
|
||||||
$aParams = array_merge($this->m_aParams);
|
$aParams = array_merge($this->m_aParams);
|
||||||
$aParams = MetaModel::PrepareQueryArguments($aParams);
|
$aParams = MetaModel::PrepareQueryArguments($aParams, array(), $this->GetExpectedArguments());
|
||||||
|
|
||||||
foreach ($this->m_aSelectedClasses as $sAlias => $sClass)
|
foreach ($this->m_aSelectedClasses as $sAlias => $sClass)
|
||||||
{
|
{
|
||||||
@@ -1835,7 +1839,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
||||||
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectDeleteQuery();
|
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectDeleteQuery();
|
||||||
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
|
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
|
||||||
$sRet = $oSQLQuery->RenderDelete($aScalarArgs);
|
$sRet = $oSQLQuery->RenderDelete($aScalarArgs);
|
||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
@@ -1851,7 +1855,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
||||||
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
|
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
|
||||||
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
|
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
|
||||||
$sRet = $oSQLQuery->RenderUpdate($aScalarArgs);
|
$sRet = $oSQLQuery->RenderUpdate($aScalarArgs);
|
||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
@@ -1870,7 +1874,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
|
||||||
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
|
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
|
||||||
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
|
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
|
||||||
$sRet = $oSQLQuery->RenderInsert($aScalarArgs);
|
$sRet = $oSQLQuery->RenderInsert($aScalarArgs);
|
||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
if (!is_array($aAttToLoad))
|
if (!is_array($aAttToLoad))
|
||||||
{
|
{
|
||||||
$this->m_aAttToLoad = null;
|
$this->m_aAttToLoad = null;
|
||||||
|
trigger_error ( "OptimizeColumnLoad : wrong format actual :(".print_r($aAttToLoad, true)."). should be [alias=>[attributes]]", E_USER_WARNING );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
foreach ($aAttToLoad as $sAlias => $aAttCodes)
|
foreach ($aAttToLoad as $sAlias => $aAttCodes)
|
||||||
@@ -229,6 +230,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
if (!is_array($aAttCodes))
|
if (!is_array($aAttCodes))
|
||||||
{
|
{
|
||||||
$this->m_aAttToLoad = null;
|
$this->m_aAttToLoad = null;
|
||||||
|
trigger_error ( "OptimizeColumnLoad : wrong format actual :(".print_r($aAttToLoad, true)."). should be [alias=>[attributes]]", E_USER_WARNING );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,6 +269,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the friendly name anytime
|
// Add the friendly name anytime
|
||||||
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
|
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
|
||||||
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;
|
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;
|
||||||
@@ -1312,34 +1315,6 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
return $oNewSet;
|
return $oNewSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Will be deprecated soon - use MetaModel::GetRelatedObjectsDown/Up instead to take redundancy into account
|
|
||||||
*
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99)
|
|
||||||
{
|
|
||||||
$aRelatedObjs = array();
|
|
||||||
|
|
||||||
$aVisited = array(); // optimization for consecutive calls of MetaModel::GetRelatedObjects
|
|
||||||
$this->Seek(0);
|
|
||||||
while ($oObject = $this->Fetch())
|
|
||||||
{
|
|
||||||
$aMore = $oObject->GetRelatedObjects($sRelCode, $iMaxDepth, $aVisited);
|
|
||||||
foreach ($aMore as $sClass => $aRelated)
|
|
||||||
{
|
|
||||||
foreach ($aRelated as $iObj => $oObj)
|
|
||||||
{
|
|
||||||
if (!isset($aRelatedObjs[$sClass][$iObj]))
|
|
||||||
{
|
|
||||||
$aRelatedObjs[$sClass][$iObj] = $oObj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $aRelatedObjs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the "RelatedObjects" (forward or "down" direction) for the set
|
* Compute the "RelatedObjects" (forward or "down" direction) for the set
|
||||||
* for the specified relation
|
* for the specified relation
|
||||||
@@ -1496,7 +1471,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
public function ListConstantFields()
|
public function ListConstantFields()
|
||||||
{
|
{
|
||||||
// The complete list of arguments will include magic arguments (e.g. current_user->attcode)
|
// The complete list of arguments will include magic arguments (e.g. current_user->attcode)
|
||||||
$aScalarArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs);
|
$aScalarArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs, $this->m_oFilter->ListParameters());
|
||||||
$aConst = $this->m_oFilter->ListConstantFields();
|
$aConst = $this->m_oFilter->ListConstantFields();
|
||||||
|
|
||||||
foreach($aConst as $sClassAlias => $aVals)
|
foreach($aConst as $sClassAlias => $aVals)
|
||||||
@@ -1515,7 +1490,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
|
|
||||||
public function ApplyParameters()
|
public function ApplyParameters()
|
||||||
{
|
{
|
||||||
$aAllArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs);
|
$aAllArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs, $this->m_oFilter->GetExpectedArguments());
|
||||||
$this->m_oFilter->ApplyParameters($aAllArgs);
|
$this->m_oFilter->ApplyParameters($aAllArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -603,11 +603,11 @@ abstract class DBSearch
|
|||||||
elseif (($iPos = strpos($sParam, '->')) !== false)
|
elseif (($iPos = strpos($sParam, '->')) !== false)
|
||||||
{
|
{
|
||||||
$sParamName = substr($sParam, 0, $iPos);
|
$sParamName = substr($sParam, 0, $iPos);
|
||||||
if (isset($aContextParams[$sParamName.'->object()']))
|
if (isset($aContextParams[$sParamName.'->object()']) || isset($aContextParams[$sParamName]))
|
||||||
{
|
{
|
||||||
$sAttCode = substr($sParam, $iPos + 2);
|
$sAttCode = substr($sParam, $iPos + 2);
|
||||||
/** @var \DBObject $oObj */
|
/** @var \DBObject $oObj */
|
||||||
$oObj = $aContextParams[$sParamName.'->object()'];
|
$oObj = isset($aContextParams[$sParamName.'->object()']) ? $aContextParams[$sParamName.'->object()'] : $aContextParams[$sParamName];
|
||||||
if ($oObj->IsModified())
|
if ($oObj->IsModified())
|
||||||
{
|
{
|
||||||
if ($sAttCode == 'id')
|
if ($sAttCode == 'id')
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class DeletionPlan
|
|||||||
{
|
{
|
||||||
foreach($aToUpdate as $iId => $aData)
|
foreach($aToUpdate as $iId => $aData)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$this->m_iToUpdate++;
|
$this->m_iToUpdate++;
|
||||||
|
|
||||||
$oObject = $aData['to_reset'];
|
$oObject = $aData['to_reset'];
|
||||||
@@ -142,7 +142,7 @@ class DeletionPlan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetIssues()
|
public function GetIssues()
|
||||||
|
|||||||
@@ -874,7 +874,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$oNodesIter = new RelationTypeIterator($oGraph, 'Node');
|
$oNodesIter = new RelationTypeIterator($oGraph, 'Node');
|
||||||
foreach($oNodesIter as $oNode)
|
foreach($oNodesIter as $oNode)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
switch(get_class($oNode))
|
switch(get_class($oNode))
|
||||||
{
|
{
|
||||||
case 'RelationObjectNode':
|
case 'RelationObjectNode':
|
||||||
@@ -921,7 +921,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$oEdgesIter = new RelationTypeIterator($oGraph, 'Edge');
|
$oEdgesIter = new RelationTypeIterator($oGraph, 'Edge');
|
||||||
foreach($oEdgesIter as $oEdge)
|
foreach($oEdgesIter as $oEdge)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oSourceNode = $oNewGraph->GetNode($oEdge->GetSourceNode()->GetId());
|
$oSourceNode = $oNewGraph->GetNode($oEdge->GetSourceNode()->GetId());
|
||||||
$oSinkNode = $oNewGraph->GetNode($oEdge->GetSinkNode()->GetId());
|
$oSinkNode = $oNewGraph->GetNode($oEdge->GetSinkNode()->GetId());
|
||||||
$oNewEdge = new DisplayableEdge($oNewGraph, $oEdge->GetId(), $oSourceNode, $oSinkNode);
|
$oNewEdge = new DisplayableEdge($oNewGraph, $oEdge->GetId(), $oSourceNode, $oSinkNode);
|
||||||
@@ -932,7 +932,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$aEdgeKeys = array();
|
$aEdgeKeys = array();
|
||||||
foreach($oEdgesIter as $oEdge)
|
foreach($oEdgesIter as $oEdge)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$sSourceId = $oEdge->GetSourceNode()->GetId();
|
$sSourceId = $oEdge->GetSourceNode()->GetId();
|
||||||
$sSinkId = $oEdge->GetSinkNode()->GetId();
|
$sSinkId = $oEdge->GetSinkNode()->GetId();
|
||||||
if ($sSourceId == $sSinkId)
|
if ($sSourceId == $sSinkId)
|
||||||
@@ -958,7 +958,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$oNodesIter = new RelationTypeIterator($oNewGraph, 'Node');
|
$oNodesIter = new RelationTypeIterator($oNewGraph, 'Node');
|
||||||
foreach($oNodesIter as $oNode)
|
foreach($oNodesIter as $oNode)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
if ($bDirectionDown && $oNode->GetProperty('source'))
|
if ($bDirectionDown && $oNode->GetProperty('source'))
|
||||||
{
|
{
|
||||||
$oNode->GroupSimilarNeighbours($oNewGraph, $iGroupingThreshold, true, $bDirectionDown);
|
$oNode->GroupSimilarNeighbours($oNewGraph, $iGroupingThreshold, true, $bDirectionDown);
|
||||||
@@ -973,7 +973,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$iGroupIdx = 0;
|
$iGroupIdx = 0;
|
||||||
foreach($oIterator as $oNode)
|
foreach($oIterator as $oNode)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
if ($oNode instanceof DisplayableGroupNode)
|
if ($oNode instanceof DisplayableGroupNode)
|
||||||
{
|
{
|
||||||
if ($oNode->GetObjectCount() == 0)
|
if ($oNode->GetObjectCount() == 0)
|
||||||
@@ -995,7 +995,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$aEdgeKeys = array();
|
$aEdgeKeys = array();
|
||||||
foreach($oEdgesIter as $oEdge)
|
foreach($oEdgesIter as $oEdge)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$sSourceId = $oEdge->GetSourceNode()->GetId();
|
$sSourceId = $oEdge->GetSourceNode()->GetId();
|
||||||
$sSinkId = $oEdge->GetSinkNode()->GetId();
|
$sSinkId = $oEdge->GetSinkNode()->GetId();
|
||||||
if ($sSourceId == $sSinkId)
|
if ($sSourceId == $sSinkId)
|
||||||
@@ -1017,7 +1017,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
|
|
||||||
return $oNewGraph;
|
return $oNewGraph;
|
||||||
}
|
}
|
||||||
@@ -1257,14 +1257,14 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||||
foreach($oIterator as $sId => $oEdge)
|
foreach($oIterator as $sId => $oEdge)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oEdge->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs);
|
$oEdge->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oIterator = new RelationTypeIterator($this, 'Node');
|
$oIterator = new RelationTypeIterator($this, 'Node');
|
||||||
foreach($oIterator as $sId => $oNode)
|
foreach($oIterator as $sId => $oNode)
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oNode->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs);
|
$oNode->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class EMail
|
|||||||
}
|
}
|
||||||
if (array_key_exists('reply_to', $aData))
|
if (array_key_exists('reply_to', $aData))
|
||||||
{
|
{
|
||||||
$oMessage->SetRecipientReplyTo($aData['reply_to']);
|
$oMessage->SetRecipientReplyTo($aData['reply_to']['address'], $aData['reply_to']['label']);
|
||||||
}
|
}
|
||||||
if (array_key_exists('to', $aData))
|
if (array_key_exists('to', $aData))
|
||||||
{
|
{
|
||||||
@@ -465,10 +465,14 @@ class EMail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetRecipientReplyTo($sAddress)
|
public function SetRecipientReplyTo($sAddress, $sLabel = '')
|
||||||
{
|
{
|
||||||
$this->m_aData['reply_to'] = $sAddress;
|
$this->m_aData['reply_to'] = array('address' => $sAddress, 'label' => $sLabel);
|
||||||
if (!empty($sAddress))
|
if ($sLabel != '')
|
||||||
|
{
|
||||||
|
$this->m_oMessage->setReplyTo(array($sAddress => $sLabel));
|
||||||
|
}
|
||||||
|
else if (!empty($sAddress))
|
||||||
{
|
{
|
||||||
$this->m_oMessage->setReplyTo($sAddress);
|
$this->m_oMessage->setReplyTo($sAddress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ class Event extends DBObject implements iDisplay
|
|||||||
"db_table" => "priv_event",
|
"db_table" => "priv_event",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false)
|
"order_by_default" => array('date' => false)
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
@@ -127,7 +126,6 @@ class EventNotification extends Event
|
|||||||
"db_table" => "priv_event_notification",
|
"db_table" => "priv_event_notification",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false),
|
"order_by_default" => array('date' => false),
|
||||||
'indexes' => array(
|
'indexes' => array(
|
||||||
array('object_id'),
|
array('object_id'),
|
||||||
@@ -163,7 +161,6 @@ class EventNotificationEmail extends EventNotification
|
|||||||
"db_table" => "priv_event_email",
|
"db_table" => "priv_event_email",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false)
|
"order_by_default" => array('date' => false)
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
@@ -201,7 +198,6 @@ class EventIssue extends Event
|
|||||||
"db_table" => "priv_event_issue",
|
"db_table" => "priv_event_issue",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false)
|
"order_by_default" => array('date' => false)
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
@@ -301,7 +297,6 @@ class EventWebService extends Event
|
|||||||
"db_table" => "priv_event_webservice",
|
"db_table" => "priv_event_webservice",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false)
|
"order_by_default" => array('date' => false)
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
@@ -337,7 +332,6 @@ class EventRestService extends Event
|
|||||||
"db_table" => "priv_event_restservice",
|
"db_table" => "priv_event_restservice",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"order_by_default" => array('date' => false)
|
"order_by_default" => array('date' => false)
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ EOF
|
|||||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||||
while($aRow = $oSet->FetchAssoc())
|
while($aRow = $oSet->FetchAssoc())
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$aData = array();
|
$aData = array();
|
||||||
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
||||||
{
|
{
|
||||||
@@ -314,7 +314,7 @@ EOF
|
|||||||
fwrite($hFile, json_encode($aData)."\n");
|
fwrite($hFile, json_encode($aData)."\n");
|
||||||
$iCount++;
|
$iCount++;
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||||
if ($this->aStatusInfo['total'] == 0)
|
if ($this->aStatusInfo['total'] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ EOF;
|
|||||||
{
|
{
|
||||||
$sKey = static::GetKey($sClass, $sAttCode);
|
$sKey = static::GetKey($sClass, $sAttCode);
|
||||||
$oExpr = DBObjectSearch::GetPolymorphicExpression($sClass, $sAttCode);
|
$oExpr = DBObjectSearch::GetPolymorphicExpression($sClass, $sAttCode);
|
||||||
return "'".$sKey."' => '".serialize($oExpr)."',\n";
|
return var_export($sKey, true)." => ".var_export(serialize($oExpr), true).",\n"; // Beware, string values can contain quotes, backslashes, etc!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class HTMLBulkExport extends TabularBulkExport
|
|||||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||||
while($aRow = $oSet->FetchAssoc())
|
while($aRow = $oSet->FetchAssoc())
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
$oMainObj = $aRow[$sFirstAlias];
|
$oMainObj = $aRow[$sFirstAlias];
|
||||||
$sHilightClass = '';
|
$sHilightClass = '';
|
||||||
if ($oMainObj)
|
if ($oMainObj)
|
||||||
@@ -160,7 +160,7 @@ class HTMLBulkExport extends TabularBulkExport
|
|||||||
$sData .= "</tr>";
|
$sData .= "</tr>";
|
||||||
$iCount++;
|
$iCount++;
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||||
if ($this->aStatusInfo['total'] == 0)
|
if ($this->aStatusInfo['total'] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ abstract class HTMLSanitizer
|
|||||||
{
|
{
|
||||||
// Do nothing..
|
// Do nothing..
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitizes the given HTML document
|
* Sanitizes the given HTML document
|
||||||
* @param string $sHTML
|
* @param string $sHTML
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
abstract public function DoSanitize($sHTML);
|
abstract public function DoSanitize($sHTML);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitize an HTML string with the configured sanitizer, falling back to HTMLDOMSanitizer in case of Exception or invalid configuration
|
* Sanitize an HTML string with the configured sanitizer, falling back to HTMLDOMSanitizer in case of Exception or invalid configuration
|
||||||
* @param string $sHTML
|
* @param string $sHTML
|
||||||
@@ -50,7 +50,7 @@ abstract class HTMLSanitizer
|
|||||||
IssueLog::Warning('The configured "html_sanitizer" class "'.$sSanitizerClass.'" is not a subclass of HTMLSanitizer. Will use HTMLDOMSanitizer as the default sanitizer.');
|
IssueLog::Warning('The configured "html_sanitizer" class "'.$sSanitizerClass.'" is not a subclass of HTMLSanitizer. Will use HTMLDOMSanitizer as the default sanitizer.');
|
||||||
$sSanitizerClass = 'HTMLDOMSanitizer';
|
$sSanitizerClass = 'HTMLDOMSanitizer';
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oSanitizer = new $sSanitizerClass();
|
$oSanitizer = new $sSanitizerClass();
|
||||||
@@ -70,7 +70,7 @@ abstract class HTMLSanitizer
|
|||||||
{
|
{
|
||||||
IssueLog::Error('Failed to sanitize an HTML string with "HTMLDOMSanitizer". The following exception occured: '.$e->getMessage());
|
IssueLog::Error('Failed to sanitize an HTML string with "HTMLDOMSanitizer". The following exception occured: '.$e->getMessage());
|
||||||
IssueLog::Error('The HTML will NOT be sanitized.');
|
IssueLog::Error('The HTML will NOT be sanitized.');
|
||||||
$sCleanHTML = $sHTML;
|
$sCleanHTML = $sHTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $sCleanHTML;
|
return $sCleanHTML;
|
||||||
@@ -97,7 +97,7 @@ class HTMLNullSanitizer extends HTMLSanitizer
|
|||||||
{
|
{
|
||||||
return $sHTML;
|
return $sHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +109,7 @@ class HTMLNullSanitizer extends HTMLSanitizer
|
|||||||
class HTMLPurifierSanitizer extends HTMLSanitizer
|
class HTMLPurifierSanitizer extends HTMLSanitizer
|
||||||
{
|
{
|
||||||
protected static $oPurifier = null;
|
protected static $oPurifier = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
if (self::$oPurifier == null)
|
if (self::$oPurifier == null)
|
||||||
@@ -120,7 +120,7 @@ class HTMLPurifierSanitizer extends HTMLSanitizer
|
|||||||
throw new Exception("Missing library '$sLibPath', cannot use HTMLPurifierSanitizer.");
|
throw new Exception("Missing library '$sLibPath', cannot use HTMLPurifierSanitizer.");
|
||||||
}
|
}
|
||||||
require_once($sLibPath);
|
require_once($sLibPath);
|
||||||
|
|
||||||
$oPurifierConfig = HTMLPurifier_Config::createDefault();
|
$oPurifierConfig = HTMLPurifier_Config::createDefault();
|
||||||
$oPurifierConfig->set('Core.Encoding', 'UTF-8'); // defaults to 'UTF-8'
|
$oPurifierConfig->set('Core.Encoding', 'UTF-8'); // defaults to 'UTF-8'
|
||||||
$oPurifierConfig->set('HTML.Doctype', 'XHTML 1.0 Strict'); // defaults to 'XHTML 1.0 Transitional'
|
$oPurifierConfig->set('HTML.Doctype', 'XHTML 1.0 Strict'); // defaults to 'XHTML 1.0 Transitional'
|
||||||
@@ -142,11 +142,11 @@ class HTMLPurifierSanitizer extends HTMLSanitizer
|
|||||||
self::$oPurifier = new HTMLPurifier($oPurifierConfig);
|
self::$oPurifier = new HTMLPurifier($oPurifierConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DoSanitize($sHTML)
|
public function DoSanitize($sHTML)
|
||||||
{
|
{
|
||||||
$sCleanHtml = self::$oPurifier->purify($sHTML);
|
$sCleanHtml = self::$oPurifier->purify($sHTML);
|
||||||
return $sCleanHtml;
|
return $sCleanHtml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@@ -278,13 +278,13 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
$sHTML = preg_replace('~\xc2\xa0~', ' ', $sHTML);
|
$sHTML = preg_replace('~\xc2\xa0~', ' ', $sHTML);
|
||||||
|
|
||||||
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified
|
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified
|
||||||
|
|
||||||
$this->CleanNode($this->oDoc);
|
$this->CleanNode($this->oDoc);
|
||||||
|
|
||||||
$oXPath = new DOMXPath($this->oDoc);
|
$oXPath = new DOMXPath($this->oDoc);
|
||||||
$sXPath = "//body";
|
$sXPath = "//body";
|
||||||
$oNodesList = $oXPath->query($sXPath);
|
$oNodesList = $oXPath->query($sXPath);
|
||||||
|
|
||||||
if ($oNodesList->length == 0)
|
if ($oNodesList->length == 0)
|
||||||
{
|
{
|
||||||
// No body, save the whole document
|
// No body, save the whole document
|
||||||
@@ -297,10 +297,10 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
// remove the body tag itself
|
// remove the body tag itself
|
||||||
$sCleanHtml = str_replace( array('<body>', '</body>'), '', $sCleanHtml);
|
$sCleanHtml = str_replace( array('<body>', '</body>'), '', $sCleanHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sCleanHtml;
|
return $sCleanHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function CleanNode(DOMNode $oElement)
|
protected function CleanNode(DOMNode $oElement)
|
||||||
{
|
{
|
||||||
$aAttrToRemove = array();
|
$aAttrToRemove = array();
|
||||||
@@ -341,7 +341,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
$oElement->removeAttribute($sName);
|
$oElement->removeAttribute($sName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oElement->hasChildNodes())
|
if ($oElement->hasChildNodes())
|
||||||
{
|
{
|
||||||
$aChildElementsToRemove = array();
|
$aChildElementsToRemove = array();
|
||||||
@@ -390,7 +390,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
}
|
}
|
||||||
return implode(';', $aAllowedStyles);
|
return implode(';', $aAllowedStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function IsValidAttributeContent($sAttributeName, $sValue)
|
protected function IsValidAttributeContent($sAttributeName, $sValue)
|
||||||
{
|
{
|
||||||
if (array_key_exists($sAttributeName, self::$aAttrsWhiteList))
|
if (array_key_exists($sAttributeName, self::$aAttrsWhiteList))
|
||||||
|
|||||||
@@ -1,30 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2016 Combodo SARL
|
/**
|
||||||
//
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
// This file is part of iTop.
|
*
|
||||||
//
|
* 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
|
* iTop is free software; you can redistribute it and/or modify
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
// (at your option) any later version.
|
* 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
|
* iTop is distributed in the hope that it will be useful,
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// GNU Affero General Public License for more details.
|
* 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/>
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
define('INLINEIMAGE_DOWNLOAD_URL', 'pages/ajax.document.php?operation=download_inlineimage&id=');
|
define('INLINEIMAGE_DOWNLOAD_URL', 'pages/ajax.document.php?operation=download_inlineimage&id=');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent classes (internal): store images referenced inside HTML formatted text fields
|
* Persistent classes (internal): store images referenced inside HTML formatted text fields
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2016 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class InlineImage extends DBObject
|
class InlineImage extends DBObject
|
||||||
{
|
{
|
||||||
/** @var string attribute to be added to IMG tags to contain ID */
|
/** @var string attribute to be added to IMG tags to contain ID */
|
||||||
@@ -32,6 +29,11 @@ class InlineImage extends DBObject
|
|||||||
/** @var string attribute to be added to IMG tags to contain secret */
|
/** @var string attribute to be added to IMG tags to contain secret */
|
||||||
const DOM_ATTR_SECRET = 'data-img-secret';
|
const DOM_ATTR_SECRET = 'data-img-secret';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -69,8 +71,9 @@ class InlineImage extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps the given context parameter name to the appropriate filter/search code for this class
|
* Maps the given context parameter name to the appropriate filter/search code for this class
|
||||||
|
*
|
||||||
* @param string $sContextParam Name of the context parameter, e.g. 'org_id'
|
* @param string $sContextParam Name of the context parameter, e.g. 'org_id'
|
||||||
* @return string Filter code, e.g. 'customer_id'
|
* @return string|null Filter code, e.g. 'customer_id'
|
||||||
*/
|
*/
|
||||||
public static function MapContextParam($sContextParam)
|
public static function MapContextParam($sContextParam)
|
||||||
{
|
{
|
||||||
@@ -86,8 +89,15 @@ class InlineImage extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set/Update all of the '_item' fields
|
* Set/Update all of the '_item' fields
|
||||||
|
*
|
||||||
* @param DBObject $oItem Container item
|
* @param DBObject $oItem Container item
|
||||||
|
* @param bool $bUpdateOnChange
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreCannotSaveObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
*/
|
*/
|
||||||
public function SetItem(DBObject $oItem, $bUpdateOnChange = false)
|
public function SetItem(DBObject $oItem, $bUpdateOnChange = false)
|
||||||
{
|
{
|
||||||
@@ -121,7 +131,12 @@ class InlineImage extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Give a default value for item_org_id (if relevant...)
|
* Give a default value for item_org_id (if relevant...)
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function SetDefaultOrgId()
|
public function SetDefaultOrgId()
|
||||||
{
|
{
|
||||||
@@ -157,12 +172,19 @@ class InlineImage extends DBObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When posting a form, finalize the creation of the inline images
|
* When posting a form, finalize the creation of the inline images
|
||||||
* related to the specified object
|
* related to the specified object
|
||||||
*
|
*
|
||||||
* @param DBObject $oObject
|
* @param DBObject $oObject
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \CoreCannotSaveObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \OQLException
|
||||||
*/
|
*/
|
||||||
public static function FinalizeInlineImages(DBObject $oObject)
|
public static function FinalizeInlineImages(DBObject $oObject)
|
||||||
{
|
{
|
||||||
@@ -203,10 +225,21 @@ class InlineImage extends DBObject
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanup the pending images if the form is not submitted
|
* Cleanup the pending images if the form is not submitted
|
||||||
|
*
|
||||||
* @param string $sTempId
|
* @param string $sTempId
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreCannotSaveObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \DeleteException
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
* @throws \OQLException
|
||||||
*/
|
*/
|
||||||
public static function OnFormCancel($sTempId)
|
public static function OnFormCancel($sTempId)
|
||||||
{
|
{
|
||||||
@@ -227,13 +260,16 @@ class InlineImage extends DBObject
|
|||||||
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
|
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the supplied HTML fragment to rebuild the attribute src="" for images
|
* Parses the supplied HTML fragment to rebuild the attribute src="" for images
|
||||||
* that refer to an InlineImage (detected via the attribute data-img-id="") so that
|
* that refer to an InlineImage (detected via the attribute data-img-id="") so that
|
||||||
* the URL is consistent with the current URL of the application.
|
* the URL is consistent with the current URL of the application.
|
||||||
|
*
|
||||||
* @param string $sHtml The HTML fragment to process
|
* @param string $sHtml The HTML fragment to process
|
||||||
|
*
|
||||||
* @return string The modified HTML
|
* @return string The modified HTML
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function FixUrls($sHtml)
|
public static function FixUrls($sHtml)
|
||||||
{
|
{
|
||||||
@@ -268,6 +304,9 @@ class InlineImage extends DBObject
|
|||||||
* so that we can later reconstruct the full "src" URL when needed
|
* so that we can later reconstruct the full "src" URL when needed
|
||||||
*
|
*
|
||||||
* @param \DOMElement $oElement
|
* @param \DOMElement $oElement
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function ProcessImageTag(DOMElement $oElement)
|
public static function ProcessImageTag(DOMElement $oElement)
|
||||||
{
|
{
|
||||||
@@ -301,6 +340,8 @@ class InlineImage extends DBObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the javascript fragment - to be added to "on document ready" - to adjust (on the fly) the width on Inline Images
|
* Get the javascript fragment - to be added to "on document ready" - to adjust (on the fly) the width on Inline Images
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function FixImagesWidth()
|
public static function FixImagesWidth()
|
||||||
{
|
{
|
||||||
@@ -309,15 +350,15 @@ class InlineImage extends DBObject
|
|||||||
if ($iMaxWidth != 0)
|
if ($iMaxWidth != 0)
|
||||||
{
|
{
|
||||||
$sJS =
|
$sJS =
|
||||||
<<<EOF
|
<<<JS
|
||||||
$('img[data-img-id]').each(function() {
|
$('img[data-img-id]').each(function() {
|
||||||
if ($(this).width() > $iMaxWidth)
|
if ($(this).width() > {$iMaxWidth})
|
||||||
{
|
{
|
||||||
$(this).css({'max-width': '{$iMaxWidth}px', width: '', height: '', 'max-height': ''});
|
$(this).css({'max-width': '{$iMaxWidth}px', width: '', height: '', 'max-height': ''});
|
||||||
}
|
}
|
||||||
$(this).addClass('inline-image').attr('href', $(this).attr('src'));
|
$(this).addClass('inline-image').attr('href', $(this).attr('src'));
|
||||||
}).magnificPopup({type: 'image', closeOnContentClick: true });
|
}).magnificPopup({type: 'image', closeOnContentClick: true });
|
||||||
EOF
|
JS
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,6 +604,9 @@ JS
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
protected function AfterInsert()
|
protected function AfterInsert()
|
||||||
{
|
{
|
||||||
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
||||||
@@ -581,6 +625,9 @@ JS
|
|||||||
parent::AfterInsert();
|
parent::AfterInsert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
protected function AfterUpdate()
|
protected function AfterUpdate()
|
||||||
{
|
{
|
||||||
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
||||||
@@ -599,7 +646,10 @@ JS
|
|||||||
parent::AfterUpdate();
|
parent::AfterUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function AfterDelete()
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function AfterDelete()
|
||||||
{
|
{
|
||||||
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
IssueLog::Trace(__METHOD__, 'InlineImage', array(
|
||||||
'id' => $this->GetKey(),
|
'id' => $this->GetKey(),
|
||||||
@@ -625,20 +675,16 @@ JS
|
|||||||
*/
|
*/
|
||||||
class InlineImageGC implements iBackgroundProcess
|
class InlineImageGC implements iBackgroundProcess
|
||||||
{
|
{
|
||||||
public function GetPeriodicity()
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function GetPeriodicity()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $iTimeLimit
|
* @inheritDoc
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws \CoreException
|
|
||||||
* @throws \CoreUnexpectedValue
|
|
||||||
* @throws \DeleteException
|
|
||||||
* @throws \MySQLException
|
|
||||||
* @throws \OQLException
|
|
||||||
*/
|
*/
|
||||||
public function Process($iTimeLimit)
|
public function Process($iTimeLimit)
|
||||||
{
|
{
|
||||||
@@ -692,5 +738,5 @@ class InlineImageGC implements iBackgroundProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $iProcessed;
|
return $iProcessed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2602,5 +2602,9 @@ class DBObjectSearch extends DBSearch
|
|||||||
return $oExpression;
|
return $oExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ListParameters()
|
||||||
|
{
|
||||||
|
return $this->GetCriteria()->ListParameters();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,8 +129,7 @@ abstract class RotatingLogFileNameBuilder implements iLogFileNameBuilder
|
|||||||
public function CheckAndRotateLogFile()
|
public function CheckAndRotateLogFile()
|
||||||
{
|
{
|
||||||
$oConfig = utils::GetConfig();
|
$oConfig = utils::GetConfig();
|
||||||
$sItopTimeZone = $oConfig->Get('timezone');
|
utils::InitTimeZone($oConfig);
|
||||||
$timezone = new DateTimeZone($sItopTimeZone);
|
|
||||||
|
|
||||||
if ($this->GetLastModifiedDateForFile() === null)
|
if ($this->GetLastModifiedDateForFile() === null)
|
||||||
{
|
{
|
||||||
@@ -145,11 +144,13 @@ abstract class RotatingLogFileNameBuilder implements iLogFileNameBuilder
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$oDateTime = DateTime::createFromFormat('U', $iLogDateLastModifiedTimeStamp);
|
$oDateTime = DateTime::createFromFormat('U', $iLogDateLastModifiedTimeStamp);
|
||||||
|
$sItopTimeZone = $oConfig->Get('timezone');
|
||||||
|
$timezone = new DateTimeZone($sItopTimeZone);
|
||||||
$oDateTime->setTimezone($timezone);
|
$oDateTime->setTimezone($timezone);
|
||||||
$this->SetLastModifiedDateForFile($oDateTime);
|
$this->SetLastModifiedDateForFile($oDateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oNow = new DateTime('now', $timezone);
|
$oNow = new DateTime();
|
||||||
$bShouldRotate = $this->ShouldRotate($this->GetLastModifiedDateForFile(), $oNow);
|
$bShouldRotate = $this->ShouldRotate($this->GetLastModifiedDateForFile(), $oNow);
|
||||||
if (!$bShouldRotate)
|
if (!$bShouldRotate)
|
||||||
{
|
{
|
||||||
@@ -830,4 +831,4 @@ class LogFileRotationProcess implements iScheduledProcess
|
|||||||
|
|
||||||
throw new ProcessException(self::class.' : The configured filename builder is invalid (log_filename_builder_impl="'.$sLogFileNameBuilder.'")');
|
throw new ProcessException(self::class.' : The configured filename builder is invalid (log_filename_builder_impl="'.$sLogFileNameBuilder.'")');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,13 @@ abstract class MetaModel
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
protected static $m_sEnvironment = 'production';
|
protected static $m_sEnvironment = 'production';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetaModel constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@@ -722,7 +729,51 @@ abstract class MetaModel
|
|||||||
return array('%1$s', array($nameRawSpec));
|
return array('%1$s', array($nameRawSpec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param string $sClass
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \DictExceptionMissingString
|
||||||
|
*/
|
||||||
|
final static public function GetComplementAttributeSpec($sClass)
|
||||||
|
{
|
||||||
|
self::_check_subclass($sClass);
|
||||||
|
if (!isset(self::$m_aClassParams[$sClass]["name_complement_for_select"]))
|
||||||
|
{
|
||||||
|
return array($sClass, array());
|
||||||
|
}
|
||||||
|
$nameRawSpec = self::$m_aClassParams[$sClass]["name_complement_for_select"];
|
||||||
|
if (is_array($nameRawSpec))
|
||||||
|
{
|
||||||
|
$sFormat = Dict::S("Class:$sClass/ComplementForSelect", '');
|
||||||
|
if (strlen($sFormat) == 0)
|
||||||
|
{
|
||||||
|
// Default to "%1$s %2$s..."
|
||||||
|
for($i = 1; $i <= count($nameRawSpec); $i++)
|
||||||
|
{
|
||||||
|
if (empty($sFormat))
|
||||||
|
{
|
||||||
|
$sFormat .= '%'.$i.'$s';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sFormat .= ' %'.$i.'$s';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array($sFormat, $nameRawSpec);
|
||||||
|
}
|
||||||
|
elseif (empty($nameRawSpec))
|
||||||
|
{
|
||||||
|
return array($sClass, array());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// string -> attcode
|
||||||
|
return array('%1$s', array($nameRawSpec));
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Get the friendly name expression for a given class
|
* Get the friendly name expression for a given class
|
||||||
*
|
*
|
||||||
@@ -802,12 +853,33 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Return true if the $sClass has a state attribute defined.
|
||||||
|
*
|
||||||
|
* Note that having a state attribute does NOT mean having a lifecycle!
|
||||||
|
* - A Person with active/inactive state won't have transitions and therefore no lifecycle
|
||||||
|
* - A UserRequest will have transitions between its states and so a lifecycle
|
||||||
|
*
|
||||||
|
* @see self::HasLifecycle($sClass)
|
||||||
|
* @param string $sClass Datamodel class to check
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
final public static function HasStateAttributeCode(string $sClass)
|
||||||
|
{
|
||||||
|
return !empty(self::GetStateAttributeCode($sClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the code of the attribute carrying the state of the instance of the class
|
||||||
|
*
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
final public static function GetStateAttributeCode($sClass)
|
final public static function GetStateAttributeCode(string $sClass)
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
self::_check_subclass($sClass);
|
||||||
|
|
||||||
@@ -821,7 +893,7 @@ abstract class MetaModel
|
|||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
final public static function GetDefaultState($sClass)
|
final public static function GetDefaultState(string $sClass)
|
||||||
{
|
{
|
||||||
$sDefaultState = '';
|
$sDefaultState = '';
|
||||||
$sStateAttrCode = self::GetStateAttributeCode($sClass);
|
$sStateAttrCode = self::GetStateAttributeCode($sClass);
|
||||||
@@ -833,6 +905,37 @@ abstract class MetaModel
|
|||||||
return $sDefaultState;
|
return $sDefaultState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the $sClass has an image attribute defined
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
final public static function HasImageAttributeCode(string $sClass)
|
||||||
|
{
|
||||||
|
return !empty(self::GetImageAttributeCode($sClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the code of the attribute carrying the image representing an instance of the class
|
||||||
|
*
|
||||||
|
* @param string $sClass Datamodel class to get the image attribute code for
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
final public static function GetImageAttributeCode(string $sClass)
|
||||||
|
{
|
||||||
|
self::_check_subclass($sClass);
|
||||||
|
|
||||||
|
// image_attcode isn't a mandatory class parameter, so it might not be in the $m_aClassParam array
|
||||||
|
return isset(self::$m_aClassParams[$sClass]["image_attcode"]) ? self::$m_aClassParams[$sClass]["image_attcode"] : '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
*
|
*
|
||||||
@@ -846,20 +949,6 @@ abstract class MetaModel
|
|||||||
return self::$m_aClassParams[$sClass]["reconc_keys"];
|
return self::$m_aClassParams[$sClass]["reconc_keys"];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $sClass
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws \CoreException
|
|
||||||
*/
|
|
||||||
final public static function GetDisplayTemplate($sClass)
|
|
||||||
{
|
|
||||||
self::_check_subclass($sClass);
|
|
||||||
|
|
||||||
return array_key_exists("display_template",
|
|
||||||
self::$m_aClassParams[$sClass]) ? self::$m_aClassParams[$sClass]["display_template"] : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param bool $bOnlyDeclared
|
* @param bool $bOnlyDeclared
|
||||||
@@ -926,11 +1015,6 @@ abstract class MetaModel
|
|||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
self::_check_subclass($sClass);
|
||||||
$oAtt = self::GetAttributeDef($sClass, $sAttCode);
|
$oAtt = self::GetAttributeDef($sClass, $sAttCode);
|
||||||
// Temporary implementation: later, we might be able to compute
|
|
||||||
// the dependencies, based on the attributes definition
|
|
||||||
// (allowed values and default values)
|
|
||||||
|
|
||||||
// Even non-writable attributes (like ExternalFields) can now have Prerequisites
|
|
||||||
return $oAtt->GetPrerequisiteAttributes();
|
return $oAtt->GetPrerequisiteAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1221,15 +1305,36 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Return an array of attributes codes for the $sClass. The list can be limited to some attribute types only.
|
||||||
|
*
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
|
* @param string[] $aDesiredAttTypes Array of AttributeDefinition classes to filter the list on
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
final public static function GetAttributesList($sClass)
|
final public static function GetAttributesList($sClass, $aDesiredAttTypes = [])
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
self::_check_subclass($sClass);
|
||||||
return array_keys(self::$m_aAttribDefs[$sClass]);
|
|
||||||
|
if(empty($aDesiredAttTypes))
|
||||||
|
{
|
||||||
|
return array_keys(self::$m_aAttribDefs[$sClass]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aMatchingAttCodes = [];
|
||||||
|
foreach(self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
|
||||||
|
{
|
||||||
|
foreach($aDesiredAttTypes as $sDesiredAttType)
|
||||||
|
{
|
||||||
|
if(is_a($oAttDef, $sDesiredAttType))
|
||||||
|
{
|
||||||
|
$aMatchingAttCodes[] = $sAttCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aMatchingAttCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1448,6 +1553,7 @@ abstract class MetaModel
|
|||||||
{
|
{
|
||||||
$aLinkedSets = array();
|
$aLinkedSets = array();
|
||||||
foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) {
|
foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) {
|
||||||
|
// Note: Careful, this will only return SUB-classes, which does NOT include AttributeLinkedset itself! We might want to use "is_a()" instead.
|
||||||
if (is_subclass_of($oAtt, 'AttributeLinkedSet')) {
|
if (is_subclass_of($oAtt, 'AttributeLinkedSet')) {
|
||||||
$aLinkedSets[$sAttCode] = $oAtt;
|
$aLinkedSets[$sAttCode] = $oAtt;
|
||||||
}
|
}
|
||||||
@@ -1495,6 +1601,27 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var array Cache for caselog attributes of the classes */
|
||||||
|
protected static $m_aCaseLogsAttributesCache = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of attribute codes for the caselogs attributes of $sClass
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
final public static function GetCaseLogs(string $sClass)
|
||||||
|
{
|
||||||
|
if (!isset(static::$m_aCaseLogsAttributesCache[$sClass])) {
|
||||||
|
static::$m_aCaseLogsAttributesCache[$sClass] = self::GetAttributesList($sClass, ['AttributeCaseLog']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::$m_aCaseLogsAttributesCache[$sClass];
|
||||||
|
}
|
||||||
|
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected static $m_aTrackForwardCache = array();
|
protected static $m_aTrackForwardCache = array();
|
||||||
|
|
||||||
@@ -1800,7 +1927,7 @@ abstract class MetaModel
|
|||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $sListCode
|
* @param string $sListCode
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array list of attribute codes
|
||||||
*/
|
*/
|
||||||
public static function GetZListItems($sClass, $sListCode)
|
public static function GetZListItems($sClass, $sListCode)
|
||||||
{
|
{
|
||||||
@@ -1820,6 +1947,82 @@ abstract class MetaModel
|
|||||||
return self::GetZListItems($sParentClass, $sListCode);
|
return self::GetZListItems($sParentClass, $sListCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sRemoteClass
|
||||||
|
*
|
||||||
|
* @return \AttributeDefinition[] list of attdefs to display by default for the remote class
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°2334
|
||||||
|
*/
|
||||||
|
public static function GetZListAttDefsFilteredForIndirectRemoteClass($sRemoteClass)
|
||||||
|
{
|
||||||
|
$aAttCodesToPrint = [];
|
||||||
|
|
||||||
|
foreach (MetaModel::GetZListItems($sRemoteClass, 'list') as $sFieldCode)
|
||||||
|
{
|
||||||
|
//TODO: check the state of the attribute: hidden or visible ?
|
||||||
|
if ($sFieldCode == 'finalclass')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oRemoteAttDef = MetaModel::GetAttributeDef($sRemoteClass, $sFieldCode);
|
||||||
|
$aAttCodesToPrint[] = $oRemoteAttDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aAttCodesToPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sClass left class
|
||||||
|
* @param string $sAttCode AttributeLinkedSetIndirect attcode
|
||||||
|
*
|
||||||
|
* @return \AttributeDefinition[] list of attdefs to display by default for lnk class
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0 N°2334
|
||||||
|
*/
|
||||||
|
public static function GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode)
|
||||||
|
{
|
||||||
|
$aAttCodesToPrint = [];
|
||||||
|
|
||||||
|
$oLinkedSetAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
|
$sLinkedClass = $oLinkedSetAttDef->GetLinkedClass();
|
||||||
|
$sExtKeyToRemote = $oLinkedSetAttDef->GetExtKeyToRemote();
|
||||||
|
$sExtKeyToMe = $oLinkedSetAttDef->GetExtKeyToMe();
|
||||||
|
|
||||||
|
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||||
|
$sDefaultState = MetaModel::GetDefaultState($sClass);
|
||||||
|
|
||||||
|
foreach (MetaModel::FlattenZList(MetaModel::GetZListItems($sLinkedClass, 'list')) as $sLnkAttCode)
|
||||||
|
{
|
||||||
|
$oLnkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLnkAttCode);
|
||||||
|
if ($sStateAttCode == $sLnkAttCode)
|
||||||
|
{
|
||||||
|
// State attribute is always hidden from the UI
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (($sLnkAttCode == $sExtKeyToMe)
|
||||||
|
|| ($sLnkAttCode == $sExtKeyToRemote)
|
||||||
|
|| ($sLnkAttCode == 'finalclass'))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!($oLnkAttDef->IsWritable()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iFlags = MetaModel::GetAttributeFlags($sLinkedClass, $sDefaultState, $sLnkAttCode);
|
||||||
|
if (!($iFlags & OPT_ATT_HIDDEN) && !($iFlags & OPT_ATT_READONLY))
|
||||||
|
{
|
||||||
|
$aAttCodesToPrint[] = $oLnkAttDef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aAttCodesToPrint;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $sListCode
|
* @param string $sListCode
|
||||||
@@ -1992,7 +2195,6 @@ abstract class MetaModel
|
|||||||
*/
|
*/
|
||||||
protected static function ComputeRelationQueries($sRelCode)
|
protected static function ComputeRelationQueries($sRelCode)
|
||||||
{
|
{
|
||||||
$bHasLegacy = false;
|
|
||||||
$aQueries = array();
|
$aQueries = array();
|
||||||
foreach(self::GetClasses() as $sClass)
|
foreach(self::GetClasses() as $sClass)
|
||||||
{
|
{
|
||||||
@@ -2078,158 +2280,8 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read legacy definitions
|
|
||||||
// The up/down queries have to be reconcilied, which can only be done later when all the classes have been browsed
|
|
||||||
//
|
|
||||||
// The keys used to store a query (up or down) into the array are built differently between the modern and legacy made data:
|
|
||||||
// Modern way: aQueries[sClass]['up'|'down'][sArrowId], where sArrowId is made of the source class + neighbour id (XML def)
|
|
||||||
// Legacy way: aQueries[sClass]['up'|'down'][sRemoteClass]
|
|
||||||
// The modern way does allow for several arrows between two classes
|
|
||||||
// The legacy way aims at simplifying the transformation (reconciliation between up and down)
|
|
||||||
if ($sRelCode == 'impacts')
|
|
||||||
{
|
|
||||||
$sRevertCode = 'depends on';
|
|
||||||
|
|
||||||
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRelCode));
|
|
||||||
foreach($aLegacy as $sId => $aLegacyEntry)
|
|
||||||
{
|
|
||||||
$bHasLegacy = true;
|
|
||||||
|
|
||||||
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
|
|
||||||
$sRemoteClass = $oFilter->GetClass();
|
|
||||||
|
|
||||||
// Determine wether the query is inherited from a parent or not
|
|
||||||
$bInherited = false;
|
|
||||||
foreach(self::EnumParentClasses($sClass) as $sParent)
|
|
||||||
{
|
|
||||||
if (!isset($aQueries[$sParent]['down'][$sRemoteClass]))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['down'][$sRemoteClass]['sQueryDown'])
|
|
||||||
{
|
|
||||||
$bInherited = true;
|
|
||||||
$aQueries[$sClass]['down'][$sRemoteClass] = $aQueries[$sParent]['down'][$sRemoteClass];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$bInherited)
|
|
||||||
{
|
|
||||||
$aQueries[$sClass]['down'][$sRemoteClass] = array(
|
|
||||||
'_legacy_' => true,
|
|
||||||
'sDefinedInClass' => $sClass,
|
|
||||||
'sFromClass' => $sClass,
|
|
||||||
'sToClass' => $sRemoteClass,
|
|
||||||
'sDirection' => 'down',
|
|
||||||
'sQueryDown' => $aLegacyEntry['sQuery'],
|
|
||||||
'sQueryUp' => null,
|
|
||||||
'sNeighbour' => $sRemoteClass // Normalize the neighbour id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRevertCode));
|
|
||||||
foreach($aLegacy as $sId => $aLegacyEntry)
|
|
||||||
{
|
|
||||||
$bHasLegacy = true;
|
|
||||||
|
|
||||||
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
|
|
||||||
$sRemoteClass = $oFilter->GetClass();
|
|
||||||
|
|
||||||
// Determine wether the query is inherited from a parent or not
|
|
||||||
$bInherited = false;
|
|
||||||
foreach(self::EnumParentClasses($sClass) as $sParent)
|
|
||||||
{
|
|
||||||
if (!isset($aQueries[$sParent]['up'][$sRemoteClass]))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['up'][$sRemoteClass]['sQueryUp'])
|
|
||||||
{
|
|
||||||
$bInherited = true;
|
|
||||||
$aQueries[$sClass]['up'][$sRemoteClass] = $aQueries[$sParent]['up'][$sRemoteClass];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$bInherited)
|
|
||||||
{
|
|
||||||
$aQueries[$sClass]['up'][$sRemoteClass] = array(
|
|
||||||
'_legacy_' => true,
|
|
||||||
'sDefinedInClass' => $sRemoteClass,
|
|
||||||
'sFromClass' => $sRemoteClass,
|
|
||||||
'sToClass' => $sClass,
|
|
||||||
'sDirection' => 'both',
|
|
||||||
'sQueryDown' => null,
|
|
||||||
'sQueryUp' => $aLegacyEntry['sQuery'],
|
|
||||||
'sNeighbour' => $sClass// Normalize the neighbour id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// Cannot take the legacy system into account... simply ignore it
|
|
||||||
//}
|
|
||||||
} // foreach class
|
} // foreach class
|
||||||
|
|
||||||
// Perform the up/down reconciliation for the legacy definitions
|
|
||||||
if ($bHasLegacy)
|
|
||||||
{
|
|
||||||
foreach(self::GetClasses() as $sClass)
|
|
||||||
{
|
|
||||||
// Foreach "up" legacy query, update its "down" counterpart
|
|
||||||
if (isset($aQueries[$sClass]['up']))
|
|
||||||
{
|
|
||||||
foreach($aQueries[$sClass]['up'] as $sNeighbourId => $aNeighbourData)
|
|
||||||
{
|
|
||||||
if (!array_key_exists('_legacy_', $aNeighbourData))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!$aNeighbourData['_legacy_'])
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
} // Skip modern definitions
|
|
||||||
|
|
||||||
$sLocalClass = $aNeighbourData['sToClass'];
|
|
||||||
foreach(self::EnumChildClasses($aNeighbourData['sFromClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
|
|
||||||
{
|
|
||||||
if (isset($aQueries[$sRemoteClass]['down'][$sLocalClass]))
|
|
||||||
{
|
|
||||||
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sQueryUp'] = $aNeighbourData['sQueryUp'];
|
|
||||||
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sDirection'] = 'both';
|
|
||||||
}
|
|
||||||
// Be silent in order to transparently support legacy data models where the counterpart query does not always exist
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// throw new Exception("Legacy definition of the relation '$sRelCode/$sRevertCode', defined on $sLocalClass (relation: $sRevertCode, inherited to $sClass), missing the counterpart query on class $sRemoteClass ($sRelCode)");
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Foreach "down" legacy query, update its "up" counterpart (if any)
|
|
||||||
foreach($aQueries[$sClass]['down'] as $sNeighbourId => $aNeighbourData)
|
|
||||||
{
|
|
||||||
if (!$aNeighbourData['_legacy_'])
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
} // Skip modern definitions
|
|
||||||
|
|
||||||
$sLocalClass = $aNeighbourData['sFromClass'];
|
|
||||||
foreach(self::EnumChildClasses($aNeighbourData['sToClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
|
|
||||||
{
|
|
||||||
if (isset($aQueries[$sRemoteClass]['up'][$sLocalClass]))
|
|
||||||
{
|
|
||||||
$aQueries[$sRemoteClass]['up'][$sLocalClass]['sQueryDown'] = $aNeighbourData['sQueryDown'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aQueries;
|
return $aQueries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2347,6 +2399,22 @@ abstract class MetaModel
|
|||||||
{
|
{
|
||||||
return self::$m_aStates[$sClass];
|
return self::$m_aStates[$sClass];
|
||||||
}
|
}
|
||||||
|
elseif (self::HasStateAttributeCode($sClass))
|
||||||
|
{
|
||||||
|
$sStateAttCode = self::GetStateAttributeCode($sClass);
|
||||||
|
$oAttDef = self::GetAttributeDef($sClass, $sStateAttCode);
|
||||||
|
|
||||||
|
$aStates = [];
|
||||||
|
foreach($oAttDef->GetAllowedValues() as $sStateCode => $sStateLabel)
|
||||||
|
{
|
||||||
|
$aStates[$sStateCode] = [
|
||||||
|
'attribute_inherit' => '',
|
||||||
|
'attribute_list' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aStates;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return array();
|
return array();
|
||||||
@@ -2404,6 +2472,21 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if $sClass has a lifecycle, which means that it has a state attribute AND stimuli
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
* @see self::HasStateAttributeCode($sClass)
|
||||||
|
*/
|
||||||
|
public static function HasLifecycle(string $sClass)
|
||||||
|
{
|
||||||
|
return self::HasStateAttributeCode($sClass) && !empty(self::EnumStimuli($sClass));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $sStateValue
|
* @param string $sStateValue
|
||||||
@@ -2492,17 +2575,13 @@ abstract class MetaModel
|
|||||||
public static function GetAttributeFlags($sClass, $sState, $sAttCode)
|
public static function GetAttributeFlags($sClass, $sState, $sAttCode)
|
||||||
{
|
{
|
||||||
$iFlags = 0; // By default (if no life cycle) no flag at all
|
$iFlags = 0; // By default (if no life cycle) no flag at all
|
||||||
$sStateAttCode = self::GetStateAttributeCode($sClass);
|
if (self::HasLifecycle($sClass)) {
|
||||||
if (!empty($sStateAttCode))
|
|
||||||
{
|
|
||||||
$aStates = MetaModel::EnumStates($sClass);
|
$aStates = MetaModel::EnumStates($sClass);
|
||||||
if (!array_key_exists($sState, $aStates))
|
if (!array_key_exists($sState, $aStates)) {
|
||||||
{
|
|
||||||
throw new CoreException("Invalid state '$sState' for class '$sClass', expecting a value in {".implode(', ', array_keys($aStates))."}");
|
throw new CoreException("Invalid state '$sState' for class '$sClass', expecting a value in {".implode(', ', array_keys($aStates))."}");
|
||||||
}
|
}
|
||||||
$aCurrentState = $aStates[$sState];
|
$aCurrentState = $aStates[$sState];
|
||||||
if ((array_key_exists('attribute_list', $aCurrentState)) && (array_key_exists($sAttCode, $aCurrentState['attribute_list'])))
|
if ((array_key_exists('attribute_list', $aCurrentState)) && (array_key_exists($sAttCode, $aCurrentState['attribute_list']))) {
|
||||||
{
|
|
||||||
$iFlags = $aCurrentState['attribute_list'][$sAttCode];
|
$iFlags = $aCurrentState['attribute_list'][$sAttCode];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2522,18 +2601,14 @@ abstract class MetaModel
|
|||||||
public static function GetTransitionFlags($sClass, $sState, $sStimulus, $sAttCode)
|
public static function GetTransitionFlags($sClass, $sState, $sStimulus, $sAttCode)
|
||||||
{
|
{
|
||||||
$iFlags = 0; // By default (if no lifecycle) no flag at all
|
$iFlags = 0; // By default (if no lifecycle) no flag at all
|
||||||
$sStateAttCode = self::GetStateAttributeCode($sClass);
|
if (self::HasLifecycle($sClass)) {
|
||||||
if (!empty($sStateAttCode))
|
|
||||||
{
|
|
||||||
$aTransitions = MetaModel::EnumTransitions($sClass, $sState);
|
$aTransitions = MetaModel::EnumTransitions($sClass, $sState);
|
||||||
if (!array_key_exists($sStimulus, $aTransitions))
|
if (!array_key_exists($sStimulus, $aTransitions)) {
|
||||||
{
|
|
||||||
throw new CoreException("Invalid transition '$sStimulus' for class '$sClass', expecting a value in {".implode(', ', array_keys($aTransitions))."}");
|
throw new CoreException("Invalid transition '$sStimulus' for class '$sClass', expecting a value in {".implode(', ', array_keys($aTransitions))."}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$aCurrentTransition = $aTransitions[$sStimulus];
|
$aCurrentTransition = $aTransitions[$sStimulus];
|
||||||
if ((array_key_exists('attribute_list', $aCurrentTransition)) && (array_key_exists($sAttCode, $aCurrentTransition['attribute_list'])))
|
if ((array_key_exists('attribute_list', $aCurrentTransition)) && (array_key_exists($sAttCode, $aCurrentTransition['attribute_list']))) {
|
||||||
{
|
|
||||||
$iFlags = $aCurrentTransition['attribute_list'][$sAttCode];
|
$iFlags = $aCurrentTransition['attribute_list'][$sAttCode];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2612,37 +2687,30 @@ abstract class MetaModel
|
|||||||
public static function GetInitialStateAttributeFlags($sClass, $sState, $sAttCode)
|
public static function GetInitialStateAttributeFlags($sClass, $sState, $sAttCode)
|
||||||
{
|
{
|
||||||
$iFlags = self::GetAttributeFlags($sClass, $sState, $sAttCode); // Be default set the same flags as the 'target' state
|
$iFlags = self::GetAttributeFlags($sClass, $sState, $sAttCode); // Be default set the same flags as the 'target' state
|
||||||
$sStateAttCode = self::GetStateAttributeCode($sClass);
|
if (self::HasLifecycle($sClass)) {
|
||||||
if (!empty($sStateAttCode))
|
|
||||||
{
|
|
||||||
$aStates = MetaModel::EnumInitialStates($sClass);
|
$aStates = MetaModel::EnumInitialStates($sClass);
|
||||||
if (array_key_exists($sState, $aStates))
|
if (array_key_exists($sState, $aStates)) {
|
||||||
{
|
|
||||||
$bReadOnly = (($iFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY);
|
$bReadOnly = (($iFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY);
|
||||||
$bHidden = (($iFlags & OPT_ATT_HIDDEN) == OPT_ATT_HIDDEN);
|
$bHidden = (($iFlags & OPT_ATT_HIDDEN) == OPT_ATT_HIDDEN);
|
||||||
foreach($aStates[$sState] as $sPrevState)
|
foreach($aStates[$sState] as $sPrevState) {
|
||||||
{
|
|
||||||
$iPrevFlags = self::GetAttributeFlags($sClass, $sPrevState, $sAttCode);
|
$iPrevFlags = self::GetAttributeFlags($sClass, $sPrevState, $sAttCode);
|
||||||
if (($iPrevFlags & OPT_ATT_HIDDEN) != OPT_ATT_HIDDEN)
|
if (($iPrevFlags & OPT_ATT_HIDDEN) != OPT_ATT_HIDDEN) {
|
||||||
{
|
|
||||||
$bReadOnly = $bReadOnly && (($iPrevFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY); // if it is/was not readonly => then it's not
|
$bReadOnly = $bReadOnly && (($iPrevFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY); // if it is/was not readonly => then it's not
|
||||||
}
|
}
|
||||||
$bHidden = $bHidden && (($iPrevFlags & OPT_ATT_HIDDEN) == OPT_ATT_HIDDEN); // if it is/was not hidden => then it's not
|
$bHidden = $bHidden && (($iPrevFlags & OPT_ATT_HIDDEN) == OPT_ATT_HIDDEN); // if it is/was not hidden => then it's not
|
||||||
}
|
}
|
||||||
if ($bReadOnly)
|
|
||||||
{
|
if ($bReadOnly) {
|
||||||
$iFlags = $iFlags | OPT_ATT_READONLY;
|
$iFlags = $iFlags | OPT_ATT_READONLY;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
$iFlags = $iFlags & ~OPT_ATT_READONLY;
|
$iFlags = $iFlags & ~OPT_ATT_READONLY;
|
||||||
}
|
}
|
||||||
if ($bHidden)
|
|
||||||
{
|
if ($bHidden) {
|
||||||
$iFlags = $iFlags | OPT_ATT_HIDDEN;
|
$iFlags = $iFlags | OPT_ATT_HIDDEN;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
$iFlags = $iFlags & ~OPT_ATT_HIDDEN;
|
$iFlags = $iFlags & ~OPT_ATT_HIDDEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2781,7 +2849,7 @@ abstract class MetaModel
|
|||||||
$aInterfaces = array('iApplicationUIExtension', 'iPreferencesExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iLoginUIExtension', 'iLogoutExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider', 'iModuleExtension');
|
$aInterfaces = array('iApplicationUIExtension', 'iPreferencesExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iLoginUIExtension', 'iLogoutExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider', 'iModuleExtension');
|
||||||
foreach($aInterfaces as $sInterface)
|
foreach($aInterfaces as $sInterface)
|
||||||
{
|
{
|
||||||
self::$m_aExtensionClasses[$sInterface] = array();
|
self::$m_aExtensionClassNames[$sInterface] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(get_declared_classes() as $sPHPClass)
|
foreach(get_declared_classes() as $sPHPClass)
|
||||||
@@ -2792,11 +2860,7 @@ abstract class MetaModel
|
|||||||
{
|
{
|
||||||
if ($oRefClass->implementsInterface($sInterface) && $oRefClass->isInstantiable())
|
if ($oRefClass->implementsInterface($sInterface) && $oRefClass->isInstantiable())
|
||||||
{
|
{
|
||||||
if (is_null($oExtensionInstance))
|
self::$m_aExtensionClassNames[$sInterface][$sPHPClass] = $sPHPClass;
|
||||||
{
|
|
||||||
$oExtensionInstance = new $sPHPClass;
|
|
||||||
}
|
|
||||||
self::$m_aExtensionClasses[$sInterface][$sPHPClass] = $oExtensionInstance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2856,6 +2920,25 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
self::$m_aClassParams[$sPHPClass]['obsolescence_expression'] = $sObsolescence;
|
self::$m_aClassParams[$sPHPClass]['obsolescence_expression'] = $sObsolescence;
|
||||||
|
|
||||||
|
// Inherit fields semantic
|
||||||
|
// - State attribute
|
||||||
|
$bParentHasStateAttribute = (isset(self::$m_aClassParams[$sParent]['state_attcode']) && !empty(self::$m_aClassParams[$sParent]['state_attcode']));
|
||||||
|
$bHasStateAttribute = (isset(self::$m_aClassParams[$sPHPClass]['state_attcode']) && !empty(self::$m_aClassParams[$sPHPClass]['state_attcode']));
|
||||||
|
if($bParentHasStateAttribute && !$bHasStateAttribute) {
|
||||||
|
// Set attribute code
|
||||||
|
self::$m_aClassParams[$sPHPClass]['state_attcode'] = self::$m_aClassParams[$sParent]['state_attcode'];
|
||||||
|
|
||||||
|
// Set states
|
||||||
|
self::$m_aStates[$sPHPClass] = self::$m_aStates[$sParent];
|
||||||
|
}
|
||||||
|
// - Image attribute
|
||||||
|
$bParentHasImageAttribute = (isset(self::$m_aClassParams[$sParent]['image_attcode']) && !empty(self::$m_aClassParams[$sParent]['image_attcode']));
|
||||||
|
$bHasImageAttribute = (isset(self::$m_aClassParams[$sPHPClass]['image_attcode']) && !empty(self::$m_aClassParams[$sPHPClass]['image_attcode']));
|
||||||
|
if($bParentHasImageAttribute && !$bHasImageAttribute) {
|
||||||
|
// Set attribute code
|
||||||
|
self::$m_aClassParams[$sPHPClass]['image_attcode'] = self::$m_aClassParams[$sParent]['image_attcode'];
|
||||||
|
}
|
||||||
|
|
||||||
foreach(MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
|
foreach(MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
|
||||||
{
|
{
|
||||||
$oClassInit->OnAfterClassInitialization($sPHPClass);
|
$oClassInit->OnAfterClassInitialization($sPHPClass);
|
||||||
@@ -3262,18 +3345,6 @@ abstract class MetaModel
|
|||||||
// In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation)
|
// In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* To be overloaded by biz model declarations
|
|
||||||
*
|
|
||||||
* @param string $sRelCode
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function GetRelationQueries($sRelCode)
|
|
||||||
{
|
|
||||||
// In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation)
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $aParams
|
* @param array $aParams
|
||||||
@@ -3283,11 +3354,12 @@ abstract class MetaModel
|
|||||||
public static function Init_Params($aParams)
|
public static function Init_Params($aParams)
|
||||||
{
|
{
|
||||||
// Check mandatory params
|
// Check mandatory params
|
||||||
|
// Warning: Do not put image_attcode as a mandatory attribute or it will break all PHP datamodel classes
|
||||||
$aMandatParams = array(
|
$aMandatParams = array(
|
||||||
"category" => "group classes by modules defining their visibility in the UI",
|
"category" => "group classes by modules defining their visibility in the UI",
|
||||||
"key_type" => "autoincrement | string",
|
"key_type" => "autoincrement | string",
|
||||||
"name_attcode" => "define wich attribute is the class name, may be an array of attributes (format specified in the dictionary as 'Class:myclass/Name' => '%1\$s %2\$s...'",
|
"name_attcode" => "define which attribute is the class name, may be an array of attributes (format specified in the dictionary as 'Class:myclass/Name' => '%1\$s %2\$s...'",
|
||||||
"state_attcode" => "define wich attribute is representing the state (object lifecycle)",
|
"state_attcode" => "define which attribute is representing the state (object lifecycle)",
|
||||||
"reconc_keys" => "define the attributes that will 'almost uniquely' identify an object in batch processes",
|
"reconc_keys" => "define the attributes that will 'almost uniquely' identify an object in batch processes",
|
||||||
"db_table" => "database table",
|
"db_table" => "database table",
|
||||||
"db_key_field" => "database field which is the key",
|
"db_key_field" => "database field which is the key",
|
||||||
@@ -5754,32 +5826,9 @@ abstract class MetaModel
|
|||||||
$sView = self::DBGetView($sClass);
|
$sView = self::DBGetView($sClass);
|
||||||
if (CMDBSource::IsTable($sView))
|
if (CMDBSource::IsTable($sView))
|
||||||
{
|
{
|
||||||
// Check that the view is complete
|
// Remove deprecated views
|
||||||
//
|
$aErrors[$sClass]['*'][] = "Remove view '$sView' (deprecated, consider installing combodo-views if needed)";
|
||||||
// Note: checking the list of attributes is not enough because the columns can be stable while the SELECT is not stable
|
$aSugFix[$sClass]['*'][] = "DROP VIEW `$sView`";
|
||||||
// Example: new way to compute the friendly name
|
|
||||||
// The correct comparison algorithm is to compare the queries,
|
|
||||||
// by using "SHOW CREATE VIEW" (MySQL 5.0.1 required) or to look into INFORMATION_SCHEMA/views
|
|
||||||
// both requiring some privileges
|
|
||||||
// Decision: to simplify, let's consider the views as being wrong anytime
|
|
||||||
// Rework the view
|
|
||||||
//
|
|
||||||
$oFilter = new DBObjectSearch($sClass, '');
|
|
||||||
$oFilter->AllowAllData();
|
|
||||||
$sSQL = $oFilter->MakeSelectQuery();
|
|
||||||
$aErrors[$sClass]['*'][] = "Redeclare view '$sView' (systematic - to support an eventual change in the friendly name computation)";
|
|
||||||
$aSugFix[$sClass]['*'][] = "ALTER VIEW `$sView` AS $sSQL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Create the view
|
|
||||||
//
|
|
||||||
$oFilter = new DBObjectSearch($sClass, '');
|
|
||||||
$oFilter->AllowAllData();
|
|
||||||
$sSQL = $oFilter->MakeSelectQuery();
|
|
||||||
$aErrors[$sClass]['*'][] = "Missing view for class: $sClass";
|
|
||||||
$aSugFix[$sClass]['*'][] = "DROP VIEW IF EXISTS `$sView`";
|
|
||||||
$aSugFix[$sClass]['*'][] = "CREATE VIEW `$sView` AS $sSQL";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return array($aErrors, $aSugFix);
|
return array($aErrors, $aSugFix);
|
||||||
@@ -6321,6 +6370,7 @@ abstract class MetaModel
|
|||||||
|
|
||||||
// N°2478 utils has his own private attribute
|
// N°2478 utils has his own private attribute
|
||||||
// @see utils::GetConfig : it always call MetaModel, but to be sure we're doing this extra copy anyway O:)
|
// @see utils::GetConfig : it always call MetaModel, but to be sure we're doing this extra copy anyway O:)
|
||||||
|
utils::InitTimeZone($oConfiguration);
|
||||||
utils::SetConfig($oConfiguration);
|
utils::SetConfig($oConfiguration);
|
||||||
|
|
||||||
// Set log ASAP
|
// Set log ASAP
|
||||||
@@ -6361,19 +6411,6 @@ abstract class MetaModel
|
|||||||
DBSearch::EnableQueryIndentation(self::$m_oConfig->Get('query_indentation_enabled'));
|
DBSearch::EnableQueryIndentation(self::$m_oConfig->Get('query_indentation_enabled'));
|
||||||
DBSearch::EnableOptimizeQuery(self::$m_oConfig->Get('query_optimization_enabled'));
|
DBSearch::EnableOptimizeQuery(self::$m_oConfig->Get('query_optimization_enabled'));
|
||||||
|
|
||||||
// PHP timezone first...
|
|
||||||
//
|
|
||||||
$sPHPTimezone = self::$m_oConfig->Get('timezone');
|
|
||||||
if ($sPHPTimezone == '')
|
|
||||||
{
|
|
||||||
// Leave as is... up to the admin to set a value somewhere...
|
|
||||||
//$sPHPTimezone = date_default_timezone_get();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
date_default_timezone_set($sPHPTimezone);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: load the dictionary as soon as possible, because it might be
|
// Note: load the dictionary as soon as possible, because it might be
|
||||||
// needed when some error occur
|
// needed when some error occur
|
||||||
$sAppIdentity = 'itop-'.MetaModel::GetEnvironmentId();
|
$sAppIdentity = 'itop-'.MetaModel::GetEnvironmentId();
|
||||||
@@ -6417,7 +6454,7 @@ abstract class MetaModel
|
|||||||
if (is_array($result))
|
if (is_array($result))
|
||||||
{
|
{
|
||||||
// todo - verifier que toutes les classes mentionnees ici sont chargees dans InitClasses()
|
// todo - verifier que toutes les classes mentionnees ici sont chargees dans InitClasses()
|
||||||
self::$m_aExtensionClasses = $result['m_aExtensionClasses'];
|
self::$m_aExtensionClassNames = $result['m_aExtensionClassNames'];
|
||||||
self::$m_Category2Class = $result['m_Category2Class'];
|
self::$m_Category2Class = $result['m_Category2Class'];
|
||||||
self::$m_aRootClasses = $result['m_aRootClasses'];
|
self::$m_aRootClasses = $result['m_aRootClasses'];
|
||||||
self::$m_aParentClasses = $result['m_aParentClasses'];
|
self::$m_aParentClasses = $result['m_aParentClasses'];
|
||||||
@@ -6454,7 +6491,7 @@ abstract class MetaModel
|
|||||||
$oKPI = new ExecutionKPI();
|
$oKPI = new ExecutionKPI();
|
||||||
|
|
||||||
$aCache = array();
|
$aCache = array();
|
||||||
$aCache['m_aExtensionClasses'] = self::$m_aExtensionClasses;
|
$aCache['m_aExtensionClassNames'] = self::$m_aExtensionClassNames;
|
||||||
$aCache['m_Category2Class'] = self::$m_Category2Class;
|
$aCache['m_Category2Class'] = self::$m_Category2Class;
|
||||||
$aCache['m_aRootClasses'] = self::$m_aRootClasses; // array of "classname" => "rootclass"
|
$aCache['m_aRootClasses'] = self::$m_aRootClasses; // array of "classname" => "rootclass"
|
||||||
$aCache['m_aParentClasses'] = self::$m_aParentClasses; // array of ("classname" => array of "parentclass")
|
$aCache['m_aParentClasses'] = self::$m_aParentClasses; // array of ("classname" => array of "parentclass")
|
||||||
@@ -6538,8 +6575,8 @@ abstract class MetaModel
|
|||||||
return md5(APPROOT).'-'.self::$m_sEnvironment;
|
return md5(APPROOT).'-'.self::$m_sEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected static $m_aExtensionClasses = array();
|
protected static $m_aExtensionClassNames = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sToInclude
|
* @param string $sToInclude
|
||||||
@@ -7185,99 +7222,11 @@ abstract class MetaModel
|
|||||||
return $aResult;
|
return $aResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.5.0 It is not recommended to use this function: call {@link MetaModel::GetLinkClasses} instead !
|
|
||||||
* The only difference with EnumLinkingClasses is the output format
|
|
||||||
*
|
|
||||||
* @see MetaModel::GetLinkClasses
|
|
||||||
* @return string[] classes having at least two external keys (thus too many classes as compared to GetLinkClasses)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static function EnumLinksClasses()
|
|
||||||
{
|
|
||||||
// Returns a flat array of classes having at least two external keys
|
|
||||||
$aResult = array();
|
|
||||||
foreach(self::$m_aAttribDefs as $sSomeClass => $aClassAttributes)
|
|
||||||
{
|
|
||||||
$iExtKeyCount = 0;
|
|
||||||
foreach($aClassAttributes as $sAttCode => $oAttDef)
|
|
||||||
{
|
|
||||||
if (self::$m_aAttribOrigins[$sSomeClass][$sAttCode] != $sSomeClass)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($oAttDef->IsExternalKey())
|
|
||||||
{
|
|
||||||
$iExtKeyCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($iExtKeyCount >= 2)
|
|
||||||
{
|
|
||||||
$aResult[] = $sSomeClass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $aResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 2.5.0 It is not recommended to use this function: call {@link MetaModel::GetLinkClasses} instead !
|
|
||||||
* The only difference with EnumLinksClasses is the output format
|
|
||||||
*
|
|
||||||
* @see MetaModel::GetLinkClasses
|
|
||||||
*
|
|
||||||
*@param string $sClass
|
|
||||||
*
|
|
||||||
* @return string[] classes having at least two external keys (thus too many classes as compared to GetLinkClasses)
|
|
||||||
* @throws \CoreException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static function EnumLinkingClasses($sClass = "")
|
|
||||||
{
|
|
||||||
// N-N links, array of sLinkClass => (array of sAttCode=>sClass)
|
|
||||||
$aResult = array();
|
|
||||||
foreach(self::EnumLinksClasses() as $sSomeClass)
|
|
||||||
{
|
|
||||||
$aTargets = array();
|
|
||||||
$bFoundClass = false;
|
|
||||||
foreach(self::ListAttributeDefs($sSomeClass) as $sAttCode => $oAttDef)
|
|
||||||
{
|
|
||||||
if (self::$m_aAttribOrigins[$sSomeClass][$sAttCode] != $sSomeClass)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($oAttDef->IsExternalKey())
|
|
||||||
{
|
|
||||||
$sRemoteClass = $oAttDef->GetTargetClass();
|
|
||||||
if (empty($sClass))
|
|
||||||
{
|
|
||||||
$aTargets[$sAttCode] = $sRemoteClass;
|
|
||||||
}
|
|
||||||
elseif ($sClass == $sRemoteClass)
|
|
||||||
{
|
|
||||||
$bFoundClass = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aTargets[$sAttCode] = $sRemoteClass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (empty($sClass) || $bFoundClass)
|
|
||||||
{
|
|
||||||
$aResult[$sSomeClass] = $aTargets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $aResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using GetLinkClasses is the recommended way to determine if a class is
|
* Using GetLinkClasses is the recommended way to determine if a class is
|
||||||
* actually an N-N relation because it is based on the decision made by the
|
* actually an N-N relation because it is based on the decision made by the
|
||||||
* designer the data model
|
* designer the data model
|
||||||
*
|
*
|
||||||
* This function has two siblings that will be soon deprecated:
|
|
||||||
* {@link MetaModel::EnumLinkingClasses} and {@link MetaModel::EnumLinkClasses}
|
|
||||||
*
|
|
||||||
* @return array (target class => (external key code => target class))
|
* @return array (target class => (external key code => target class))
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
@@ -7423,25 +7372,9 @@ abstract class MetaModel
|
|||||||
*/
|
*/
|
||||||
public static function EnumPlugins($sInterface, $sFilterInstanceOf = null)
|
public static function EnumPlugins($sInterface, $sFilterInstanceOf = null)
|
||||||
{
|
{
|
||||||
if (!array_key_exists($sInterface, self::$m_aExtensionClasses))
|
$pluginManager = new PluginManager(self::$m_aExtensionClassNames);
|
||||||
{
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($sFilterInstanceOf))
|
return $pluginManager->EnumPlugins($sInterface, $sFilterInstanceOf);
|
||||||
{
|
|
||||||
return self::$m_aExtensionClasses[$sInterface];
|
|
||||||
}
|
|
||||||
|
|
||||||
$fFilterCallback = function ($instance) use ($sFilterInstanceOf)
|
|
||||||
{
|
|
||||||
return $instance instanceof $sFilterInstanceOf;
|
|
||||||
};
|
|
||||||
|
|
||||||
return array_filter(
|
|
||||||
self::$m_aExtensionClasses[$sInterface],
|
|
||||||
$fFilterCallback
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7452,16 +7385,9 @@ abstract class MetaModel
|
|||||||
*/
|
*/
|
||||||
public static function GetPlugins($sInterface, $sClassName)
|
public static function GetPlugins($sInterface, $sClassName)
|
||||||
{
|
{
|
||||||
$oInstance = null;
|
$pluginManager = new PluginManager(self::$m_aExtensionClassNames);
|
||||||
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
|
|
||||||
{
|
|
||||||
if (array_key_exists($sClassName, self::$m_aExtensionClasses[$sInterface]))
|
|
||||||
{
|
|
||||||
return self::$m_aExtensionClasses[$sInterface][$sClassName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $oInstance;
|
return $pluginManager->GetPlugins($sInterface, $sClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ExpressionHelper {
|
|||||||
*
|
*
|
||||||
* @uses \DBSearch::AllowAllData()
|
* @uses \DBSearch::AllowAllData()
|
||||||
*
|
*
|
||||||
* @since 2.7.2 2.8.0 N°3324
|
* @since 2.7.2 3.0.0 N°3324
|
||||||
*/
|
*/
|
||||||
public static function ExpressionAllowAllDataCallback($oExpression, $bAllowAllData) {
|
public static function ExpressionAllowAllDataCallback($oExpression, $bAllowAllData) {
|
||||||
if (!($oExpression instanceof NestedQueryExpression)) {
|
if (!($oExpression instanceof NestedQueryExpression)) {
|
||||||
@@ -42,6 +42,9 @@ class ExpressionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NotYetEvaluatedExpression extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method Check($oModelReflection, array $aAliases, $sSourceQuery)
|
* @method Check($oModelReflection, array $aAliases, $sSourceQuery)
|
||||||
@@ -129,6 +132,47 @@ abstract class Expression {
|
|||||||
*/
|
*/
|
||||||
abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false);
|
abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect parameters, i.e. :parameter
|
||||||
|
*
|
||||||
|
* @param null $sParentFilter
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function GetParameters($sParentFilter = null)
|
||||||
|
{
|
||||||
|
$aParameters = array();
|
||||||
|
$unused = $this->RenderExpression(false, $aParameters, true);
|
||||||
|
|
||||||
|
if (!is_null($sParentFilter)) $sParentFilter .= '->';
|
||||||
|
|
||||||
|
$aRet = array();
|
||||||
|
foreach($aParameters as $sParameter => $unused)
|
||||||
|
{
|
||||||
|
if (is_null($sParentFilter))
|
||||||
|
{
|
||||||
|
$aRet[] = $sParameter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (substr($sParameter, 0, strlen($sParentFilter)) == $sParentFilter)
|
||||||
|
{
|
||||||
|
$aRet[] = substr($sParameter, strlen($sParentFilter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
*
|
||||||
|
* @param array $aArgs
|
||||||
|
*
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
abstract public function Evaluate(array $aArgs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively renders the expression as a structure (array) suitable for a JSON export
|
* Recursively renders the expression as a structure (array) suitable for a JSON export
|
||||||
*
|
*
|
||||||
@@ -345,6 +389,16 @@ class SQLExpression extends Expression
|
|||||||
return $this->m_sSQL;
|
return $this->m_sSQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
throw new Exception('a nested query cannot be evaluated');
|
||||||
|
}
|
||||||
|
|
||||||
// recursive rendering
|
// recursive rendering
|
||||||
public function toJSON(&$aArgs = null, $bRetrofitParams = false)
|
public function toJSON(&$aArgs = null, $bRetrofitParams = false)
|
||||||
{
|
{
|
||||||
@@ -492,6 +546,149 @@ class BinaryExpression extends Expression
|
|||||||
return "($sLeft $sOperator $sRight)";
|
return "($sLeft $sOperator $sRight)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
$mLeft = $this->GetLeftExpr()->Evaluate($aArgs);
|
||||||
|
$mRight = $this->GetRightExpr()->Evaluate($aArgs);
|
||||||
|
|
||||||
|
$sOperator = $this->GetOperator();
|
||||||
|
$sType = null;
|
||||||
|
switch($sOperator)
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
case '*':
|
||||||
|
case '/':
|
||||||
|
$sType = 'maths';
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
case '!=':
|
||||||
|
case '<>':
|
||||||
|
$sType = 'comp';
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
case '>=':
|
||||||
|
case '<':
|
||||||
|
case '<=':
|
||||||
|
$sType = 'numcomp';
|
||||||
|
break;
|
||||||
|
case 'OR':
|
||||||
|
case 'AND':
|
||||||
|
$sType = 'logical';
|
||||||
|
break;
|
||||||
|
case 'LIKE':
|
||||||
|
$sType = 'like';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Operator '$sOperator' not yet supported");
|
||||||
|
}
|
||||||
|
switch ($sType){
|
||||||
|
case 'logical':
|
||||||
|
$bLeft = static::CastToBool($mLeft);
|
||||||
|
$bRight = static::CastToBool($mRight);
|
||||||
|
switch ($sOperator)
|
||||||
|
{
|
||||||
|
case 'OR':
|
||||||
|
$result = (int)($bLeft || $bRight);
|
||||||
|
break;
|
||||||
|
case 'AND':
|
||||||
|
$result = (int)($bLeft && $bRight);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Logic: unknown operator '$sOperator'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'maths':
|
||||||
|
$iLeft = (int) $mLeft;
|
||||||
|
$iRight = (int) $mRight;
|
||||||
|
switch ($sOperator)
|
||||||
|
{
|
||||||
|
case '+' : $result = $iLeft + $iRight; break;
|
||||||
|
case '-' : $result = $iLeft - $iRight; break;
|
||||||
|
case '*' : $result = $iLeft * $iRight; break;
|
||||||
|
case '/' : $result = $iLeft / $iRight; break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Logic: unknown operator '$sOperator'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'comp':
|
||||||
|
$left = $mLeft;
|
||||||
|
$right = $mRight;
|
||||||
|
switch ($sOperator)
|
||||||
|
{
|
||||||
|
case '=' : $result = ($left == $right); break;
|
||||||
|
case '!=' : $result = ($left != $right); break;
|
||||||
|
case '<>' : $result = ($left != $right); break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Logic: unknown operator '$sOperator'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'numcomp':
|
||||||
|
$iLeft = static::ComparableValue($mLeft);
|
||||||
|
$iRight = static::ComparableValue($mRight);
|
||||||
|
switch ($sOperator)
|
||||||
|
{
|
||||||
|
case '=' : $result = ($iLeft == $iRight); break;
|
||||||
|
case '>' : $result = ($iLeft > $iRight); break;
|
||||||
|
case '<' : $result = ($iLeft < $iRight); break;
|
||||||
|
case '>=' : $result = ($iLeft >= $iRight); break;
|
||||||
|
case '<=' : $result = ($iLeft <= $iRight); break;
|
||||||
|
case '!=' : $result = ($iLeft != $iRight); break;
|
||||||
|
case '<>' : $result = ($iLeft != $iRight); break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Logic: unknown operator '$sOperator'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'like':
|
||||||
|
$sEscaped = preg_quote($mRight, '/');
|
||||||
|
$sEscaped = str_replace(array('%', '_', '\\\\.*', '\\\\.'), array('.*', '.', '%', '_'), $sEscaped);
|
||||||
|
$result = (int) preg_match("/$sEscaped/i", $mLeft);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected function CastToBool($mValue)
|
||||||
|
{
|
||||||
|
if (is_string($mValue))
|
||||||
|
{
|
||||||
|
if (is_numeric($mValue))
|
||||||
|
{
|
||||||
|
return abs($mValue) > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (bool)$mValue;
|
||||||
|
}
|
||||||
|
static protected function ComparableValue($mixed)
|
||||||
|
{
|
||||||
|
if (is_string($mixed))
|
||||||
|
{
|
||||||
|
$oDate = new \DateTime($mixed);
|
||||||
|
if (($oDate->format('Y-m-d') == $mixed) || ($oDate->format('Y-m-d H:i:s') == $mixed))
|
||||||
|
{
|
||||||
|
$iRet = $oDate->format('U');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$iRet = (int) $mixed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$iRet = $mixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $iRet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @throws \MissingQueryArgument
|
* @throws \MissingQueryArgument
|
||||||
@@ -894,6 +1091,16 @@ class MatchExpression extends BinaryExpression
|
|||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
throw new Exception('evaluation of MATCHES not implemented yet');
|
||||||
|
}
|
||||||
|
|
||||||
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
|
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
|
||||||
{
|
{
|
||||||
/** @var \FieldExpression $oLeft */
|
/** @var \FieldExpression $oLeft */
|
||||||
@@ -932,6 +1139,16 @@ class UnaryExpression extends Expression
|
|||||||
return CMDBSource::Quote($this->m_value);
|
return CMDBSource::Quote($this->m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
return $this->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @throws \MissingQueryArgument
|
* @throws \MissingQueryArgument
|
||||||
@@ -1078,6 +1295,16 @@ class ScalarExpression extends UnaryExpression
|
|||||||
return $sRet;
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
return $this->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -1386,6 +1613,21 @@ class FieldExpression extends UnaryExpression
|
|||||||
return "`{$this->m_sParent}`.`{$this->m_sName}`";
|
return "`{$this->m_sParent}`.`{$this->m_sName}`";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
$sKey = empty($this->m_sParent) ? $this->m_sName : "{$this->m_sParent}.{$this->m_sName}";
|
||||||
|
if (!array_key_exists($sKey, $aArgs))
|
||||||
|
{
|
||||||
|
throw new Exception("Missing field '$sKey' from context");
|
||||||
|
}
|
||||||
|
return $aArgs[$sKey];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -1441,7 +1683,8 @@ class FieldExpression extends UnaryExpression
|
|||||||
|
|
||||||
public function ListRequiredFields()
|
public function ListRequiredFields()
|
||||||
{
|
{
|
||||||
return array($this->m_sParent.'.'.$this->m_sName);
|
$sField = empty($this->m_sParent) ? $this->m_sName : "{$this->m_sParent}.{$this->m_sName}";
|
||||||
|
return array($sField);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function CollectUsedParents(&$aTable)
|
public function CollectUsedParents(&$aTable)
|
||||||
@@ -1822,6 +2065,16 @@ class VariableExpression extends UnaryExpression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
throw new Exception('not implemented yet');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -1962,6 +2215,16 @@ class ListExpression extends Expression
|
|||||||
return '('.implode(', ', $aRes).')';
|
return '('.implode(', ', $aRes).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
throw new Exception('list expression not yet supported');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -2177,6 +2440,16 @@ class NestedQueryExpression extends Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
throw new Exception('a nested query cannot be evaluated');
|
||||||
|
}
|
||||||
|
|
||||||
public function Browse(Closure $callback)
|
public function Browse(Closure $callback)
|
||||||
{
|
{
|
||||||
$callback($this);
|
$callback($this);
|
||||||
@@ -2279,6 +2552,252 @@ class FunctionExpression extends Expression
|
|||||||
return $this->m_sVerb.'('.implode(', ', $aRes).')';
|
return $this->m_sVerb.'('.implode(', ', $aRes).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
switch($this->m_sVerb)
|
||||||
|
{
|
||||||
|
case 'CONCAT':
|
||||||
|
$sRet = '';
|
||||||
|
foreach ($this->m_aArgs as $iPos => $oExpr)
|
||||||
|
{
|
||||||
|
$item = $oExpr->Evaluate($aArgs);
|
||||||
|
if (is_null($item)) return null;
|
||||||
|
$sRet .= $item;
|
||||||
|
}
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'CONCAT_WS':
|
||||||
|
if (count($this->m_aArgs) < 3)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires at least 3 arguments");
|
||||||
|
}
|
||||||
|
$sSeparator = $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
foreach ($this->m_aArgs as $iPos => $oExpr)
|
||||||
|
{
|
||||||
|
if ($iPos == 0) continue;
|
||||||
|
$item = $oExpr->Evaluate($aArgs);
|
||||||
|
if (is_null($item)) return null;
|
||||||
|
$aStrings[] = $item;
|
||||||
|
}
|
||||||
|
$sRet = implode($sSeparator, $aStrings);
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'SUBSTR':
|
||||||
|
if (count($this->m_aArgs) < 2)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires at least 2 arguments");
|
||||||
|
}
|
||||||
|
$sString = $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
$iRawPos = $this->m_aArgs[1]->Evaluate($aArgs);
|
||||||
|
$iPos = $iRawPos > 0 ?
|
||||||
|
$iRawPos - 1// 0-based in PHP (1-based in SQL)
|
||||||
|
: $iRawPos; // Negative
|
||||||
|
if (count($this->m_aArgs) == 2)
|
||||||
|
{
|
||||||
|
// Up to the end of the string
|
||||||
|
$sRet = substr($sString, $iPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Length specified
|
||||||
|
$iLen = $this->m_aArgs[2]->Evaluate($aArgs);
|
||||||
|
$sRet = substr($sString, $iPos, $iLen);
|
||||||
|
}
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'TRIM':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$sRet = trim($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'INET_ATON':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$sRet = ip2long($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'INET_NTOA':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$sRet = long2ip($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'ISNULL':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$sRet = is_null($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'COALESCE':
|
||||||
|
if (count($this->m_aArgs) < 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires at least 1 argument");
|
||||||
|
}
|
||||||
|
$ret = null;
|
||||||
|
foreach($this->m_aArgs as $iPos => $oExpr)
|
||||||
|
{
|
||||||
|
$ret = $oExpr->Evaluate($aArgs);
|
||||||
|
if (!is_null($ret)) break;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
case 'IF':
|
||||||
|
if (count($this->m_aArgs) != 3)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 3 arguments");
|
||||||
|
}
|
||||||
|
$bCond = $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
if ($bCond)
|
||||||
|
{
|
||||||
|
$ret = $this->m_aArgs[1]->Evaluate($aArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ret = $this->m_aArgs[2]->Evaluate($aArgs);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
case 'ELT':
|
||||||
|
if (count($this->m_aArgs) < 2)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires at least 2 arguments");
|
||||||
|
}
|
||||||
|
// First argument is the 1-based position
|
||||||
|
$iPosition = (int) $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
if (($iPosition == 0) || ($iPosition >= count($this->m_aArgs)))
|
||||||
|
{
|
||||||
|
// Out of range
|
||||||
|
$ret = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ret = $this->m_aArgs[$iPosition]->Evaluate($aArgs);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
case 'DATE':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$sRet = date('Y-m-d', strtotime($this->m_aArgs[0]->Evaluate($aArgs)));
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'YEAR':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$iRet = (int) date('Y', strtotime($this->m_aArgs[0]->Evaluate($aArgs)));
|
||||||
|
return $iRet;
|
||||||
|
|
||||||
|
case 'MONTH':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$iRet = (int) date('m', strtotime($this->m_aArgs[0]->Evaluate($aArgs)));
|
||||||
|
return $iRet;
|
||||||
|
|
||||||
|
case 'DAY':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$iRet = (int) date('d', strtotime($this->m_aArgs[0]->Evaluate($aArgs)));
|
||||||
|
return $iRet;
|
||||||
|
|
||||||
|
case 'DATE_FORMAT':
|
||||||
|
if (count($this->m_aArgs) != 2)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 2 arguments");
|
||||||
|
}
|
||||||
|
$oDate = new DateTime($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
$sFormat = $this->m_aArgs[1]->Evaluate($aArgs);
|
||||||
|
$sFormat = str_replace(
|
||||||
|
array('%y', '%x', '%w', '%W', '%v', '%T', '%S', '%r', '%p', '%M', '%l', '%k', '%I', '%h', '%b', '%a', '%D', '%c', '%e', '%Y', '%d', '%m', '%H', '%i', '%s'),
|
||||||
|
array('y', 'o', 'w', 'l', 'W', 'H:i:s', 's', 'h:i:s A', 'A', 'F', 'g', 'H', 'h', 'h','M', 'D', 'jS', 'n', 'j', 'Y', 'd', 'm', 'H', 'i', 's'),
|
||||||
|
$sFormat);
|
||||||
|
if (preg_match('/%j/', $sFormat))
|
||||||
|
{
|
||||||
|
$sFormat = str_replace('%j', date_format($oDate, 'z') + 1, $sFormat);
|
||||||
|
}
|
||||||
|
if (preg_match('/%[fUuVX]/', $sFormat))
|
||||||
|
{
|
||||||
|
throw new NotYetEvaluatedExpression("Expression ".$this->RenderExpression().' cannot be evaluated (known limitation)');
|
||||||
|
}
|
||||||
|
$sRet = date_format($oDate, $sFormat);
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'TO_DAYS':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$oDate = new DateTime($this->m_aArgs[0]->Evaluate($aArgs));
|
||||||
|
$oZero = new DateTime('1582-01-01');
|
||||||
|
$iRet = (int) $oDate->diff($oZero)->format('%a') + 577815;
|
||||||
|
return $iRet;
|
||||||
|
|
||||||
|
case 'FROM_DAYS':
|
||||||
|
if (count($this->m_aArgs) != 1)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 1 argument");
|
||||||
|
}
|
||||||
|
$iSince1582 = $this->m_aArgs[0]->Evaluate($aArgs) - 577814;
|
||||||
|
$oDate = new DateTime("1582-01-01 +$iSince1582 days");
|
||||||
|
$sRet = $oDate->format('Y-m-d');
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'NOW':
|
||||||
|
$sRet = date('Y-m-d H:i:s');
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'CURRENT_DATE':
|
||||||
|
$sRet = date('Y-m-d');
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'DATE_ADD':
|
||||||
|
if (count($this->m_aArgs) != 2)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 2 arguments");
|
||||||
|
}
|
||||||
|
$sStartDate = $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
$sInterval = $this->m_aArgs[1]->Evaluate($aArgs);
|
||||||
|
$oDate = new DateTime("$sStartDate +$sInterval");
|
||||||
|
$sRet = $oDate->format('Y-m-d H:i:s');
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
case 'DATE_SUB':
|
||||||
|
if (count($this->m_aArgs) != 2)
|
||||||
|
{
|
||||||
|
throw new \Exception("Function {$this->m_sVerb} requires 2 arguments");
|
||||||
|
}
|
||||||
|
$sStartDate = $this->m_aArgs[0]->Evaluate($aArgs);
|
||||||
|
$sInterval = $this->m_aArgs[1]->Evaluate($aArgs);
|
||||||
|
$oDate = new DateTime("$sStartDate -$sInterval");
|
||||||
|
$sRet = $oDate->format('Y-m-d H:i:s');
|
||||||
|
return $sRet;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception("Function {$this->m_sVerb} cannot be evaluated -unhandled yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -2605,6 +3124,17 @@ class IntervalExpression extends Expression
|
|||||||
return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit;
|
return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
$iValue = $this->m_oValue->Evaluate($aArgs);
|
||||||
|
return "$iValue {$this->m_sUnit}";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -2723,6 +3253,21 @@ class CharConcatExpression extends Expression
|
|||||||
return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)";
|
return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
$sRet = '';
|
||||||
|
foreach ($this->m_aExpressions as $oExpr)
|
||||||
|
{
|
||||||
|
$sRet .= $oExpr->Evaluate($aArgs);
|
||||||
|
}
|
||||||
|
return $sRet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see Expression::ToJSON()
|
* @see Expression::ToJSON()
|
||||||
@@ -2864,6 +3409,21 @@ class CharConcatWSExpression extends CharConcatExpression
|
|||||||
return "CAST(CONCAT_WS($sSep, ".implode(', ', $aRes).") AS CHAR)";
|
return "CAST(CONCAT_WS($sSep, ".implode(', ', $aRes).") AS CHAR)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the value of the expression
|
||||||
|
* @param array $aArgs
|
||||||
|
* @throws \Exception if terms cannot be evaluated as scalars
|
||||||
|
*/
|
||||||
|
public function Evaluate(array $aArgs)
|
||||||
|
{
|
||||||
|
$aRes = array();
|
||||||
|
foreach ($this->m_aExpressions as $oExpr)
|
||||||
|
{
|
||||||
|
$aRes .= $oExpr->Evaluate($aArgs);
|
||||||
|
}
|
||||||
|
return implode($this->m_separator, $aRes);
|
||||||
|
}
|
||||||
|
|
||||||
public function Browse(Closure $callback)
|
public function Browse(Closure $callback)
|
||||||
{
|
{
|
||||||
$callback($this);
|
$callback($this);
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ require_once('dbobjectiterator.php');
|
|||||||
|
|
||||||
class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||||
{
|
{
|
||||||
|
const LINK_ALIAS = 'Link';
|
||||||
|
const REMOTE_ALIAS = 'Remote';
|
||||||
|
|
||||||
protected $sHostClass; // subclass of DBObject
|
protected $sHostClass; // subclass of DBObject
|
||||||
protected $sAttCode; // xxxxxx_list
|
protected $sAttCode; // xxxxxx_list
|
||||||
protected $sClass; // class of the links
|
protected $sClass; // class of the links
|
||||||
@@ -786,11 +789,13 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
/**
|
/**
|
||||||
* @param bool $bShowObsolete
|
* @param bool $bShowObsolete
|
||||||
*
|
*
|
||||||
* @return \DBObjectSet
|
* @return \DBObjectSet indirect relations will get `SELECT L,R ...` (l = lnk class, R = remote)
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \CoreWarning
|
* @throws \CoreWarning
|
||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°2334 returns both lnk and remote classes for indirect relations
|
||||||
*/
|
*/
|
||||||
public function ToDBObjectSet($bShowObsolete = true)
|
public function ToDBObjectSet($bShowObsolete = true)
|
||||||
{
|
{
|
||||||
@@ -802,7 +807,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||||
/** @var \AttributeExternalKey $oLinkingAttDef */
|
/** @var \AttributeExternalKey $oLinkingAttDef */
|
||||||
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
|
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
|
||||||
|
|
||||||
|
// N°2334 add pointed class (SELECT L,R) to have all fields (lnk + remote) in display
|
||||||
|
// the pointed class is always present in the search, as generated by \AttributeLinkedSet::GetDefaultValue
|
||||||
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
||||||
|
$oRemoteClassSearch = new DBObjectSearch($sTargetClass);
|
||||||
|
|
||||||
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
|
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
|
||||||
{
|
{
|
||||||
$oNotObsolete = new BinaryExpression(
|
$oNotObsolete = new BinaryExpression(
|
||||||
@@ -810,10 +820,9 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
'=',
|
'=',
|
||||||
new ScalarExpression(0)
|
new ScalarExpression(0)
|
||||||
);
|
);
|
||||||
$oNotObsoleteRemote = new DBObjectSearch($sTargetClass);
|
$oRemoteClassSearch->AddConditionExpression($oNotObsolete);
|
||||||
$oNotObsoleteRemote->AddConditionExpression($oNotObsolete);
|
|
||||||
$oLinkSearch->AddCondition_PointingTo($oNotObsoleteRemote, $sExtKeyToRemote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass))
|
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass))
|
||||||
{
|
{
|
||||||
$oNotArchived = new BinaryExpression(
|
$oNotArchived = new BinaryExpression(
|
||||||
@@ -821,10 +830,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
'=',
|
'=',
|
||||||
new ScalarExpression(0)
|
new ScalarExpression(0)
|
||||||
);
|
);
|
||||||
$oNotArchivedRemote = new DBObjectSearch($sTargetClass);
|
|
||||||
$oNotArchivedRemote->AddConditionExpression($oNotArchived);
|
$oRemoteClassSearch->AddConditionExpression($oNotArchived);
|
||||||
$oLinkSearch->AddCondition_PointingTo($oNotArchivedRemote, $sExtKeyToRemote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$oLinkSearch->AddCondition_PointingTo($oRemoteClassSearch, $sExtKeyToRemote);
|
||||||
|
$oLinkSearch->RenameAlias($oLinkSearch->GetClassAlias(), self::LINK_ALIAS);
|
||||||
|
$oLinkSearch->RenameAlias($sTargetClass, self::REMOTE_ALIAS);
|
||||||
|
$oLinkSearch->SetSelectedClasses([self::LINK_ALIAS, self::REMOTE_ALIAS]);
|
||||||
}
|
}
|
||||||
$oLinkSet = new DBObjectSet($oLinkSearch);
|
$oLinkSet = new DBObjectSet($oLinkSearch);
|
||||||
$oLinkSet->SetShowObsoleteData($bShowObsolete);
|
$oLinkSet->SetShowObsoleteData($bShowObsolete);
|
||||||
|
|||||||
30
core/plugininstanciationmanager.class.inc.php
Normal file
30
core/plugininstanciationmanager.class.inc.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class PluginInstanciationManager
|
||||||
|
{
|
||||||
|
public function InstantiatePlugins($m_aExtensionClassNames, $sInterface)
|
||||||
|
{
|
||||||
|
$newPerInstanceClasses = array();
|
||||||
|
if (array_key_exists($sInterface, $m_aExtensionClassNames))
|
||||||
|
{
|
||||||
|
foreach ($m_aExtensionClassNames[$sInterface] as $sClassName)
|
||||||
|
{
|
||||||
|
if (class_exists($sClassName))
|
||||||
|
{
|
||||||
|
$class = new ReflectionClass($sClassName);
|
||||||
|
|
||||||
|
if ($class->isInstantiable())
|
||||||
|
{
|
||||||
|
$newPerInstanceClasses[$sClassName] = new $sClassName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $newPerInstanceClasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
105
core/pluginmanager.class.inc.php
Normal file
105
core/pluginmanager.class.inc.php
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class PluginManager
|
||||||
|
{
|
||||||
|
|
||||||
|
private $m_aExtensionClassNames;
|
||||||
|
private static $m_aExtensionClasses;
|
||||||
|
private $m_pluginInstantiationManager;
|
||||||
|
|
||||||
|
public function __construct($m_aExtensionClassNames, $m_pluginInstanciationManager = null)
|
||||||
|
{
|
||||||
|
if (is_null(self::$m_aExtensionClasses)) {
|
||||||
|
self::$m_aExtensionClasses = [];
|
||||||
|
}
|
||||||
|
$this->m_aExtensionClassNames = $m_aExtensionClassNames;
|
||||||
|
|
||||||
|
if ($m_pluginInstanciationManager == null)
|
||||||
|
{
|
||||||
|
$this->m_pluginInstantiationManager = new PluginInstanciationManager();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->m_pluginInstantiationManager = $m_pluginInstanciationManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sInterface
|
||||||
|
* @param bool $bCanInstantiatePlugins internal use, let this value to true
|
||||||
|
* @param string|null $sFilterInstanceOf [optional] if given, only instance of this string will be returned
|
||||||
|
*
|
||||||
|
* @return array classes=>instance implementing the given interface
|
||||||
|
*/
|
||||||
|
public function EnumPlugins($sInterface, $sFilterInstanceOf = null, $bCanInstantiatePlugins = true)
|
||||||
|
{
|
||||||
|
$aPlugins = array();
|
||||||
|
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
|
||||||
|
{
|
||||||
|
$aAllPlugins = array_values(self::$m_aExtensionClasses[$sInterface]);
|
||||||
|
|
||||||
|
if (is_null($sFilterInstanceOf))
|
||||||
|
{
|
||||||
|
return $aAllPlugins;
|
||||||
|
};
|
||||||
|
|
||||||
|
$aPlugins = array();
|
||||||
|
foreach ($aAllPlugins as $instance)
|
||||||
|
{
|
||||||
|
if ($instance instanceof $sFilterInstanceOf)
|
||||||
|
{
|
||||||
|
$aPlugins[] = $instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($bCanInstantiatePlugins && array_key_exists($sInterface, $this->m_aExtensionClassNames))
|
||||||
|
{
|
||||||
|
$this->InstantiatePlugins($sInterface);
|
||||||
|
|
||||||
|
return $this->EnumPlugins($sInterface, $sFilterInstanceOf, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function InstantiatePlugins($sInterface)
|
||||||
|
{
|
||||||
|
self::$m_aExtensionClasses[$sInterface] = $this->m_pluginInstantiationManager->InstantiatePlugins($this->m_aExtensionClassNames, $sInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sInterface
|
||||||
|
* @param string $sClassName
|
||||||
|
* @param bool $bCanInstantiatePlugins internal use, let this value to true
|
||||||
|
*
|
||||||
|
* @return mixed the instance of the specified plug-ins for the given interface
|
||||||
|
*/
|
||||||
|
public function GetPlugins($sInterface, $sClassName, $bCanInstantiatePlugins = true)
|
||||||
|
{
|
||||||
|
$oInstance = null;
|
||||||
|
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
|
||||||
|
{
|
||||||
|
if (array_key_exists($sClassName, self::$m_aExtensionClasses[$sInterface]))
|
||||||
|
{
|
||||||
|
return self::$m_aExtensionClasses[$sInterface][$sClassName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($bCanInstantiatePlugins && array_key_exists($sInterface, $this->m_aExtensionClassNames))
|
||||||
|
{
|
||||||
|
$this->InstantiatePlugins($sInterface);
|
||||||
|
return $this->GetPlugins($sInterface, $sClassName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -472,7 +472,7 @@ class RelationGraph extends SimpleGraph
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
|
|
||||||
$sObjectRef = RelationObjectNode::MakeId($oRelatedObj);
|
$sObjectRef = RelationObjectNode::MakeId($oRelatedObj);
|
||||||
$oRelatedNode = $this->GetNode($sObjectRef);
|
$oRelatedNode = $this->GetNode($sObjectRef);
|
||||||
@@ -501,7 +501,7 @@ class RelationGraph extends SimpleGraph
|
|||||||
while ($oRelatedObj = $oObjSet->Fetch());
|
while ($oRelatedObj = $oObjSet->Fetch());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,6 +467,18 @@ class CoreServices implements iRestServiceProvider
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!$bExtendedOutput && RestUtils::GetOptionalParam($aParams, 'output_fields', '*') != '*')
|
||||||
|
{
|
||||||
|
$aFields = $aShowFields[$sClass];
|
||||||
|
//Id is not a valid attribute to optimize
|
||||||
|
if (in_array('id', $aFields))
|
||||||
|
{
|
||||||
|
unset($aFields[array_search('id', $aFields)]);
|
||||||
|
}
|
||||||
|
$aAttToLoad = array($oObjectSet->GetClassAlias() => $aFields);
|
||||||
|
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
|
||||||
|
}
|
||||||
|
|
||||||
while ($oObject = $oObjectSet->Fetch())
|
while ($oObject = $oObjectSet->Fetch())
|
||||||
{
|
{
|
||||||
$oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput);
|
$oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput);
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ EOF
|
|||||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||||
while($aRow = $oSet->FetchAssoc())
|
while($aRow = $oSet->FetchAssoc())
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
|
|
||||||
$sData .= "<tr>";
|
$sData .= "<tr>";
|
||||||
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec)
|
||||||
@@ -362,7 +362,7 @@ EOF
|
|||||||
$sData .= "</tr>";
|
$sData .= "</tr>";
|
||||||
$iCount++;
|
$iCount++;
|
||||||
}
|
}
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||||
if ($this->aStatusInfo['total'] == 0)
|
if ($this->aStatusInfo['total'] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ abstract class Trigger extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_trigger",
|
"db_table" => "priv_trigger",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -168,7 +167,6 @@ abstract class TriggerOnObject extends Trigger
|
|||||||
"db_table" => "priv_trigger_onobject",
|
"db_table" => "priv_trigger_onobject",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -295,7 +293,6 @@ class TriggerOnPortalUpdate extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_onportalupdate",
|
"db_table" => "priv_trigger_onportalupdate",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -328,7 +325,6 @@ abstract class TriggerOnStateChange extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_onstatechange",
|
"db_table" => "priv_trigger_onstatechange",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -363,7 +359,6 @@ class TriggerOnStateEnter extends TriggerOnStateChange
|
|||||||
"db_table" => "priv_trigger_onstateenter",
|
"db_table" => "priv_trigger_onstateenter",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -397,7 +392,6 @@ class TriggerOnStateLeave extends TriggerOnStateChange
|
|||||||
"db_table" => "priv_trigger_onstateleave",
|
"db_table" => "priv_trigger_onstateleave",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -431,7 +425,6 @@ class TriggerOnObjectCreate extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_onobjcreate",
|
"db_table" => "priv_trigger_onobjcreate",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -465,7 +458,6 @@ class TriggerOnObjectDelete extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_onobjdelete",
|
"db_table" => "priv_trigger_onobjdelete",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -500,7 +492,6 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_onobjupdate",
|
"db_table" => "priv_trigger_onobjupdate",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
@@ -593,7 +584,6 @@ class lnkTriggerAction extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_link_action_trigger",
|
"db_table" => "priv_link_action_trigger",
|
||||||
"db_key_field" => "link_id",
|
"db_key_field" => "link_id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
"is_link" => true,
|
"is_link" => true,
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
@@ -633,7 +623,6 @@ class TriggerOnThresholdReached extends TriggerOnObject
|
|||||||
"db_table" => "priv_trigger_threshold",
|
"db_table" => "priv_trigger_threshold",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
|
|||||||
@@ -45,25 +45,85 @@ define('UR_ACTION_APPLICATION_DEFINED', 10000); // Application specific actions
|
|||||||
*/
|
*/
|
||||||
abstract class UserRightsAddOnAPI
|
abstract class UserRightsAddOnAPI
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string $sAdminUser
|
||||||
|
* @param string $sAdminPwd
|
||||||
|
* @param string $sLanguage
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
abstract public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US'); // could be used during initial installation
|
abstract public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US'); // could be used during initial installation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
abstract public function Init(); // loads data (possible optimizations)
|
abstract public function Init(); // loads data (possible optimizations)
|
||||||
|
|
||||||
// Used to build select queries showing only objects visible for the given user
|
/**
|
||||||
|
* Used to build select queries showing only objects visible for the given user
|
||||||
|
*
|
||||||
|
* @param string $sLogin
|
||||||
|
* @param string $sClass
|
||||||
|
* @param array $aSettings
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
abstract public function GetSelectFilter($sLogin, $sClass, $aSettings = array()); // returns a filter object
|
abstract public function GetSelectFilter($sLogin, $sClass, $aSettings = array()); // returns a filter object
|
||||||
|
|
||||||
abstract public function IsActionAllowed($oUser, $sClass, $iActionCode, /*dbObjectSet*/ $oInstanceSet = null);
|
/**
|
||||||
abstract public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, /*dbObjectSet*/ $oInstanceSet = null);
|
* @param \User $oUser
|
||||||
abstract public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, /*dbObjectSet*/ $oInstanceSet = null);
|
* @param string $sClass
|
||||||
abstract public function IsAdministrator($oUser);
|
* @param int $iActionCode
|
||||||
abstract public function IsPortalUser($oUser);
|
* @param null $oInstanceSet
|
||||||
abstract public function FlushPrivileges();
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $oUser
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sStimulusCode
|
||||||
|
* @param \DBObjectSet|null $oInstanceSet
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $oUser
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param int $iActionCode
|
||||||
|
* @param \DBObjectSet|null $oInstanceSet
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $oUser
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function IsAdministrator($oUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $oUser
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function IsPortalUser($oUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
abstract public function FlushPrivileges();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default behavior for addons that do not support profiles
|
* Default behavior for addons that do not support profiles
|
||||||
*
|
*
|
||||||
* @param $oUser User
|
* @param \User $oUser
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function ListProfiles($oUser)
|
public function ListProfiles($oUser)
|
||||||
@@ -72,7 +132,18 @@ abstract class UserRightsAddOnAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ...
|
* ...
|
||||||
|
*
|
||||||
|
* @param string$sClass
|
||||||
|
* @param array $aAllowedOrgs
|
||||||
|
* @param array $aSettings
|
||||||
|
* @param string|null $sAttCode
|
||||||
|
*
|
||||||
|
* @return \DBObjectSearch
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
*/
|
*/
|
||||||
public function MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings = array(), $sAttCode = null)
|
public function MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings = array(), $sAttCode = null)
|
||||||
{
|
{
|
||||||
@@ -156,6 +227,9 @@ abstract class UserRightsAddOnAPI
|
|||||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||||
abstract class User extends cmdbAbstractObject
|
abstract class User extends cmdbAbstractObject
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -168,7 +242,6 @@ abstract class User extends cmdbAbstractObject
|
|||||||
"db_table" => "priv_user",
|
"db_table" => "priv_user",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
"display_template" => "",
|
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
//MetaModel::Init_InheritAttributes();
|
||||||
@@ -202,7 +275,11 @@ abstract class User extends cmdbAbstractObject
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute a name in best effort mode
|
* Compute a name in best effort mode
|
||||||
*/
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public function GetFriendlyName()
|
public function GetFriendlyName()
|
||||||
{
|
{
|
||||||
if (!MetaModel::IsValidAttCode(get_class($this), 'contactid'))
|
if (!MetaModel::IsValidAttCode(get_class($this), 'contactid'))
|
||||||
@@ -230,6 +307,32 @@ abstract class User extends cmdbAbstractObject
|
|||||||
return $this->Get('login');
|
return $this->Get('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the initials in best effort mode
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function GetInitials()
|
||||||
|
{
|
||||||
|
$sInitials = '';
|
||||||
|
|
||||||
|
if (MetaModel::IsValidAttCode(get_class($this), 'contactid') && ($this->Get('contactid') != 0))
|
||||||
|
{
|
||||||
|
$sInitials .= mb_substr($this->Get('first_name'), 0, 1);
|
||||||
|
$sInitials .= mb_substr($this->Get('last_name'), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($sInitials))
|
||||||
|
{
|
||||||
|
$sInitials = mb_substr($this->Get('login'), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sInitials;
|
||||||
|
}
|
||||||
|
|
||||||
protected $oContactObject;
|
protected $oContactObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -409,25 +512,23 @@ abstract class User extends cmdbAbstractObject
|
|||||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||||
{
|
{
|
||||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||||
if (!$bEditMode)
|
|
||||||
{
|
|
||||||
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
|
||||||
$this->DoShowGrantSumary($oPage, 'bizmodel,grant_by_profile');
|
|
||||||
|
|
||||||
// debug
|
$oPage->SetCurrentTab('UI:UserManagement:GrantMatrix');
|
||||||
if (false)
|
$this->DoShowGrantSumary($oPage, 'bizmodel,grant_by_profile');
|
||||||
{
|
|
||||||
$oPage->SetCurrentTab('More on user rigths (dev only)');
|
// debug
|
||||||
$oPage->add("<h3>User rights</h3>\n");
|
if (false)
|
||||||
$this->DoShowGrantSumary($oPage, 'addon/userrights');
|
{
|
||||||
$oPage->add("<h3>Change log</h3>\n");
|
$oPage->SetCurrentTab('More on user rigths (dev only)');
|
||||||
$this->DoShowGrantSumary($oPage, 'core/cmdb');
|
$oPage->add("<h3>User rights</h3>\n");
|
||||||
$oPage->add("<h3>Application</h3>\n");
|
$this->DoShowGrantSumary($oPage, 'addon/userrights');
|
||||||
$this->DoShowGrantSumary($oPage, 'application');
|
$oPage->add("<h3>Change log</h3>\n");
|
||||||
$oPage->add("<h3>GUI</h3>\n");
|
$this->DoShowGrantSumary($oPage, 'core/cmdb');
|
||||||
$this->DoShowGrantSumary($oPage, 'gui');
|
$oPage->add("<h3>Application</h3>\n");
|
||||||
|
$this->DoShowGrantSumary($oPage, 'application');
|
||||||
}
|
$oPage->add("<h3>GUI</h3>\n");
|
||||||
|
$this->DoShowGrantSumary($oPage, 'gui');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,25 +671,38 @@ interface iSelfRegister
|
|||||||
*/
|
*/
|
||||||
class UserRights
|
class UserRights
|
||||||
{
|
{
|
||||||
|
const DEFAULT_USER_CONTACT_ID_ATTCODE = 'contactid';
|
||||||
|
const DEFAULT_CONTACT_ORG_ID_ATTCODE = 'org_id';
|
||||||
|
const DEFAULT_CONTACT_ORG_ID_FRIENDLYNAME_ATTCODE = self::DEFAULT_CONTACT_ORG_ID_ATTCODE.'_friendlyname';
|
||||||
|
const DEFAULT_CONTACT_FIRSTNAME_ATTCODE = 'first_name';
|
||||||
|
const DEFAULT_CONTACT_PICTURE_ATTCODE = 'picture';
|
||||||
|
|
||||||
|
public static $m_aCacheUsers;
|
||||||
/** @var UserRightsAddOnAPI $m_oAddOn */
|
/** @var UserRightsAddOnAPI $m_oAddOn */
|
||||||
protected static $m_oAddOn;
|
protected static $m_oAddOn;
|
||||||
protected static $m_oUser;
|
protected static $m_oUser;
|
||||||
protected static $m_oRealUser;
|
protected static $m_oRealUser;
|
||||||
protected static $m_sSelfRegisterAddOn = null;
|
protected static $m_sSelfRegisterAddOn = null;
|
||||||
|
protected static $m_aAdmins = array();
|
||||||
|
protected static $m_aPortalUsers = array();
|
||||||
/** @var array array('sName' => $sName, 'bSuccess' => $bSuccess); */
|
/** @var array array('sName' => $sName, 'bSuccess' => $bSuccess); */
|
||||||
private static $m_sLastLoginStatus = null;
|
private static $m_sLastLoginStatus = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sModuleName
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function SelectModule($sModuleName)
|
public static function SelectModule($sModuleName)
|
||||||
{
|
{
|
||||||
if (!class_exists($sModuleName))
|
if (!class_exists($sModuleName))
|
||||||
{
|
{
|
||||||
throw new CoreException("Could not select this module, '$sModuleName' in not a valid class name");
|
throw new CoreException("Could not select this module, '$sModuleName' in not a valid class name");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!is_subclass_of($sModuleName, 'UserRightsAddOnAPI'))
|
if (!is_subclass_of($sModuleName, 'UserRightsAddOnAPI'))
|
||||||
{
|
{
|
||||||
throw new CoreException("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI");
|
throw new CoreException("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
self::$m_oAddOn = new $sModuleName;
|
self::$m_oAddOn = new $sModuleName;
|
||||||
self::$m_oAddOn->Init();
|
self::$m_oAddOn->Init();
|
||||||
@@ -596,6 +710,12 @@ class UserRights
|
|||||||
self::$m_oRealUser = null;
|
self::$m_oRealUser = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sModuleName
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function SelectSelfRegister($sModuleName)
|
public static function SelectSelfRegister($sModuleName)
|
||||||
{
|
{
|
||||||
if (!class_exists($sModuleName))
|
if (!class_exists($sModuleName))
|
||||||
@@ -605,19 +725,33 @@ class UserRights
|
|||||||
self::$m_sSelfRegisterAddOn = $sModuleName;
|
self::$m_sSelfRegisterAddOn = $sModuleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \UserRightsAddOnAPI
|
||||||
|
*/
|
||||||
public static function GetModuleInstance()
|
public static function GetModuleInstance()
|
||||||
{
|
{
|
||||||
return self::$m_oAddOn;
|
return self::$m_oAddOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Installation: create the very first user
|
/**
|
||||||
|
* Installation: create the very first user
|
||||||
|
*
|
||||||
|
* @param string $sAdminUser
|
||||||
|
* @param string $sAdminPwd
|
||||||
|
* @param string $sLanguage
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
public static function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||||
{
|
{
|
||||||
$bRes = self::$m_oAddOn->CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage);
|
$bRes = self::$m_oAddOn->CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage);
|
||||||
self::FlushPrivileges(true /* reset admin cache */);
|
self::FlushPrivileges(true /* reset admin cache */);
|
||||||
return $bRes;
|
return $bRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsLoggedIn()
|
public static function IsLoggedIn()
|
||||||
{
|
{
|
||||||
if (self::$m_oUser == null)
|
if (self::$m_oUser == null)
|
||||||
@@ -630,9 +764,17 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function Login($sName, $sAuthentication = 'any')
|
/**
|
||||||
|
* @param string $sLogin Login of the concerned user
|
||||||
|
* @param string $sAuthentication
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \DictExceptionUnknownLanguage
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function Login($sLogin, $sAuthentication = 'any')
|
||||||
{
|
{
|
||||||
$oUser = self::FindUser($sName, $sAuthentication);
|
$oUser = self::FindUser($sLogin, $sAuthentication);
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -649,38 +791,55 @@ class UserRights
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function CheckCredentials($sName, $sPassword, $sLoginMode = 'form', $sAuthentication = 'any')
|
/**
|
||||||
|
* @param string $sLogin Login of the user to check the credentials for
|
||||||
|
* @param string $sPassword
|
||||||
|
* @param string $sLoginMode
|
||||||
|
* @param string $sAuthentication
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function CheckCredentials($sLogin, $sPassword, $sLoginMode = 'form', $sAuthentication = 'any')
|
||||||
{
|
{
|
||||||
$oUser = self::FindUser($sName, $sAuthentication);
|
$oUser = self::FindUser($sLogin, $sAuthentication);
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
// Check if the user does not exist at all or if it is just disabled
|
// Check if the user does not exist at all or if it is just disabled
|
||||||
if (self::FindUser($sName, $sAuthentication, true) == null)
|
if (self::FindUser($sLogin, $sAuthentication, true) == null)
|
||||||
{
|
{
|
||||||
// User does not exist at all
|
// User does not exist at all
|
||||||
$bCheckCredentialsAndCreateUser = self::CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication);
|
$bCheckCredentialsAndCreateUser = self::CheckCredentialsAndCreateUser($sLogin, $sPassword, $sLoginMode, $sAuthentication);
|
||||||
self::$m_sLastLoginStatus = array('sName' => $sName, 'bSuccess' => $bCheckCredentialsAndCreateUser);
|
self::$m_sLastLoginStatus = array('sName' => $sLogin, 'bSuccess' => $bCheckCredentialsAndCreateUser);
|
||||||
return $bCheckCredentialsAndCreateUser;
|
return $bCheckCredentialsAndCreateUser;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// User is actually disabled
|
// User is actually disabled
|
||||||
self::$m_sLastLoginStatus = array('sName' => $sName, 'bSuccess' => false);
|
self::$m_sLastLoginStatus = array('sName' => $sLogin, 'bSuccess' => false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$oUser->CheckCredentials($sPassword))
|
if (!$oUser->CheckCredentials($sPassword))
|
||||||
{
|
{
|
||||||
self::$m_sLastLoginStatus = array('sName' => $sName, 'bSuccess' => false);
|
self::$m_sLastLoginStatus = array('sName' => $sLogin, 'bSuccess' => false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
self::UpdateUser($oUser, $sLoginMode, $sAuthentication);
|
self::UpdateUser($oUser, $sLoginMode, $sAuthentication);
|
||||||
self::$m_sLastLoginStatus = array('sName' => $sName, 'bSuccess' => true);
|
self::$m_sLastLoginStatus = array('sName' => $sLogin, 'bSuccess' => true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sName
|
||||||
|
* @param string $sPassword
|
||||||
|
* @param string $sLoginMode
|
||||||
|
* @param string $sAuthentication
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public static function CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication)
|
public static function CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication)
|
||||||
{
|
{
|
||||||
if (self::$m_sSelfRegisterAddOn != null)
|
if (self::$m_sSelfRegisterAddOn != null)
|
||||||
@@ -689,6 +848,11 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $oUser
|
||||||
|
* @param string $sLoginMode
|
||||||
|
* @param string $sAuthentication
|
||||||
|
*/
|
||||||
public static function UpdateUser($oUser, $sLoginMode, $sAuthentication)
|
public static function UpdateUser($oUser, $sLoginMode, $sAuthentication)
|
||||||
{
|
{
|
||||||
if (self::$m_sSelfRegisterAddOn != null)
|
if (self::$m_sSelfRegisterAddOn != null)
|
||||||
@@ -696,7 +860,10 @@ class UserRights
|
|||||||
call_user_func(array(self::$m_sSelfRegisterAddOn, 'UpdateUser'), $oUser, $sLoginMode, $sAuthentication);
|
call_user_func(array(self::$m_sSelfRegisterAddOn, 'UpdateUser'), $oUser, $sLoginMode, $sAuthentication);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function TrustWebServerContext()
|
public static function TrustWebServerContext()
|
||||||
{
|
{
|
||||||
if (!is_null(self::$m_oUser))
|
if (!is_null(self::$m_oUser))
|
||||||
@@ -711,9 +878,11 @@ class UserRights
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether or not the archive mode is allowed to the current user
|
* Tells whether or not the archive mode is allowed to the current user
|
||||||
* @return boolean
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
static function CanBrowseArchive()
|
public static function CanBrowseArchive()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
{
|
{
|
||||||
@@ -732,6 +901,9 @@ class UserRights
|
|||||||
return $bRet;
|
return $bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function CanChangePassword()
|
public static function CanChangePassword()
|
||||||
{
|
{
|
||||||
if (MetaModel::DBIsReadOnly())
|
if (MetaModel::DBIsReadOnly())
|
||||||
@@ -749,16 +921,24 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ChangePassword($sOldPassword, $sNewPassword, $sName = '')
|
/**
|
||||||
|
* @param string $sOldPassword
|
||||||
|
* @param string $sNewPassword
|
||||||
|
* @param string $sLogin Login of the concerned user
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function ChangePassword($sOldPassword, $sNewPassword, $sLogin = '')
|
||||||
{
|
{
|
||||||
if (empty($sName))
|
if (empty($sLogin))
|
||||||
{
|
{
|
||||||
$oUser = self::$m_oUser;
|
$oUser = self::$m_oUser;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// find the id out of the login string
|
// find the id out of the login string
|
||||||
$oUser = self::FindUser($sName);
|
$oUser = self::FindUser($sLogin);
|
||||||
}
|
}
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
@@ -772,15 +952,18 @@ class UserRights
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sName Login identifier of the user to impersonate
|
* @param string $sLogin Login identifier of the user to impersonate
|
||||||
|
*
|
||||||
* @return bool True if an impersonation occurred
|
* @return bool True if an impersonation occurred
|
||||||
|
* @throws \DictExceptionUnknownLanguage
|
||||||
|
* @throws \OQLException
|
||||||
*/
|
*/
|
||||||
public static function Impersonate($sName)
|
public static function Impersonate($sLogin)
|
||||||
{
|
{
|
||||||
if (!self::CheckLogin()) return false;
|
if (!self::CheckLogin()) return false;
|
||||||
|
|
||||||
$bRet = false;
|
$bRet = false;
|
||||||
$oUser = self::FindUser($sName);
|
$oUser = self::FindUser($sLogin);
|
||||||
if ($oUser)
|
if ($oUser)
|
||||||
{
|
{
|
||||||
$bRet = true;
|
$bRet = true;
|
||||||
@@ -799,13 +982,16 @@ class UserRights
|
|||||||
// Do impersonate!
|
// Do impersonate!
|
||||||
self::$m_oUser = $oUser;
|
self::$m_oUser = $oUser;
|
||||||
Dict::SetUserLanguage(self::GetUserLanguage());
|
Dict::SetUserLanguage(self::GetUserLanguage());
|
||||||
$_SESSION['impersonate_user'] = $sName;
|
$_SESSION['impersonate_user'] = $sLogin;
|
||||||
self::_ResetSessionCache();
|
self::_ResetSessionCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $bRet;
|
return $bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \DictExceptionUnknownLanguage
|
||||||
|
*/
|
||||||
public static function Deimpersonate()
|
public static function Deimpersonate()
|
||||||
{
|
{
|
||||||
if (!is_null(self::$m_oRealUser))
|
if (!is_null(self::$m_oRealUser))
|
||||||
@@ -817,6 +1003,11 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current user login or an empty string if nobody connected.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GetUser()
|
public static function GetUser()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
@@ -829,7 +1020,9 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** User */
|
/**
|
||||||
|
* @return \User|null
|
||||||
|
*/
|
||||||
public static function GetUserObject()
|
public static function GetUserObject()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
@@ -841,7 +1034,10 @@ class UserRights
|
|||||||
return self::$m_oUser;
|
return self::$m_oUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GetUserLanguage()
|
public static function GetUserLanguage()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
@@ -855,9 +1051,15 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetUserId($sName = '')
|
/**
|
||||||
|
* @param string $sLogin
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function GetUserId($sLogin = '')
|
||||||
{
|
{
|
||||||
if (empty($sName))
|
if (empty($sLogin))
|
||||||
{
|
{
|
||||||
// return current user id
|
// return current user id
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
@@ -869,7 +1071,7 @@ class UserRights
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// find the id out of the login string
|
// find the id out of the login string
|
||||||
$oUser = self::$m_oAddOn->FindUser($sName);
|
$oUser = self::FindUser($sLogin);
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -878,27 +1080,163 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetContactId($sName = '')
|
/**
|
||||||
|
* @param string $sLogin Login of the user from which we return the contact ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function GetContactId($sLogin = '')
|
||||||
{
|
{
|
||||||
if (empty($sName))
|
if (empty($sLogin))
|
||||||
{
|
{
|
||||||
$oUser = self::$m_oUser;
|
$oUser = self::$m_oUser;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oUser = FindUser($sName);
|
$oUser = self::FindUser($sLogin);
|
||||||
}
|
}
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (!MetaModel::IsValidAttCode(get_class($oUser), 'contactid'))
|
if (!MetaModel::IsValidAttCode(get_class($oUser), static::DEFAULT_USER_CONTACT_ID_ATTCODE))
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return $oUser->Get('contactid');
|
return $oUser->Get(static::DEFAULT_USER_CONTACT_ID_ATTCODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the absolute URL of the contact picture
|
||||||
|
*
|
||||||
|
* @param string $sLogin Login of the user from which we return the picture URL
|
||||||
|
* @param bool $bAllowDefaultPicture Set to false if you want it to return null instead of the default picture URL when the contact has no picture defined. This can be useful when we want to display something else than the default picture (eg. initials)
|
||||||
|
*
|
||||||
|
* @return null|string
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetContactPictureAbsUrl($sLogin = '', $bAllowDefaultPicture = true)
|
||||||
|
{
|
||||||
|
// First, the default picture
|
||||||
|
if($bAllowDefaultPicture === true)
|
||||||
|
{
|
||||||
|
$sPictureUrl = utils::GetAbsoluteUrlAppRoot().'images/user-pictures/' . 'user-profile-default-256px.png';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sPictureUrl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then check if the user has a contact attached and if it has an picture defined
|
||||||
|
$sContactId = UserRights::GetContactId($sLogin);
|
||||||
|
if(!empty($sContactId))
|
||||||
|
{
|
||||||
|
$oContact = MetaModel::GetObject('Contact', $sContactId, false, true);
|
||||||
|
$sContactClass = get_class($oContact);
|
||||||
|
|
||||||
|
// Check that Contact object still exists and that Contact class has a picture attribute
|
||||||
|
if(!is_null($oContact) && MetaModel::IsValidAttCode($sContactClass, static::DEFAULT_CONTACT_PICTURE_ATTCODE))
|
||||||
|
{
|
||||||
|
/** @var \ormDocument $oPicture */
|
||||||
|
$oPicture = $oContact->Get(static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||||
|
if($oPicture->IsEmpty())
|
||||||
|
{
|
||||||
|
if($bAllowDefaultPicture === true)
|
||||||
|
{
|
||||||
|
/** @var \AttributeImage $oAttDef */
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef($sContactClass, static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||||
|
$sPictureUrl = $oAttDef->Get('default_image');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sPictureUrl = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ContextTag::Check(ContextTag::TAG_PORTAL)) {
|
||||||
|
$sPictureUrl = utils::GetAbsoluteUrlAppRoot().'pages/exec.php/object/document/display/'.$sContactClass.'/'.$oContact->GetKey().'/'.static::DEFAULT_CONTACT_PICTURE_ATTCODE.'?exec_module=itop-portal-base&exec_page=index.php&portal_id='.PORTAL_ID;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sPictureUrl = $oPicture->GetDisplayURL($sContactClass, $oContact->GetKey(), static::DEFAULT_CONTACT_PICTURE_ATTCODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the organization name of the current user's contact.
|
||||||
|
* If the user has no contact linked, null is returned.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetContactOrganizationFriendlyname()
|
||||||
|
{
|
||||||
|
$sOrgFriendlyname = null;
|
||||||
|
|
||||||
|
$oContact = static::GetContactObject();
|
||||||
|
if(!is_null($oContact) && MetaModel::IsValidAttCode(get_class($oContact), static::DEFAULT_CONTACT_ORG_ID_FRIENDLYNAME_ATTCODE))
|
||||||
|
{
|
||||||
|
$sOrgFriendlyname = $oContact->Get(static::DEFAULT_CONTACT_ORG_ID_FRIENDLYNAME_ATTCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sOrgFriendlyname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the first name of the current user's contact.
|
||||||
|
* If the user has no contact, null is returned.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetContactFirstname()
|
||||||
|
{
|
||||||
|
$sFirstname = null;
|
||||||
|
|
||||||
|
$oContact = static::GetContactObject();
|
||||||
|
if(!is_null($oContact) && MetaModel::IsValidAttCode(get_class($oContact), static::DEFAULT_CONTACT_FIRSTNAME_ATTCODE))
|
||||||
|
{
|
||||||
|
$sFirstname = $oContact->Get(static::DEFAULT_CONTACT_FIRSTNAME_ATTCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sFirstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the friendlyname of the current user's contact.
|
||||||
|
* If the user has no contact, null is returned.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetContactFriendlyname()
|
||||||
|
{
|
||||||
|
$sFriendlyname = null;
|
||||||
|
|
||||||
|
$oContact = static::GetContactObject();
|
||||||
|
if(!is_null($oContact))
|
||||||
|
{
|
||||||
|
$sFriendlyname = $oContact->GetRawName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sFriendlyname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DBObject|null
|
||||||
|
*/
|
||||||
public static function GetContactObject()
|
public static function GetContactObject()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oUser))
|
if (is_null(self::$m_oUser))
|
||||||
@@ -911,16 +1249,23 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the user name in best effort mode
|
/**
|
||||||
public static function GetUserFriendlyName($sName = '')
|
* Render the user name in best effort mode
|
||||||
|
*
|
||||||
|
* @param string $sLogin Login of the user we want to retrieve the friendlyname
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
public static function GetUserFriendlyName($sLogin = '')
|
||||||
{
|
{
|
||||||
if (empty($sName))
|
if (empty($sLogin))
|
||||||
{
|
{
|
||||||
$oUser = self::$m_oUser;
|
$oUser = self::$m_oUser;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oUser = FindUser($sName);
|
$oUser = self::FindUser($sLogin);
|
||||||
}
|
}
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
@@ -929,6 +1274,48 @@ class UserRights
|
|||||||
return $oUser->GetFriendlyName();
|
return $oUser->GetFriendlyName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the user initials in best effort mode
|
||||||
|
*
|
||||||
|
* @param string $sLogin Login of the user from which we want to retrieve the initials
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \OQLException
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetUserInitials($sLogin = '')
|
||||||
|
{
|
||||||
|
if (empty($sLogin))
|
||||||
|
{
|
||||||
|
$oUser = self::$m_oUser;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oUser = self::FindUser($sLogin);
|
||||||
|
}
|
||||||
|
if (is_null($oUser))
|
||||||
|
{
|
||||||
|
$sInitials = '';
|
||||||
|
$aLoginParts = explode(' ', $sLogin);
|
||||||
|
foreach($aLoginParts as $sLoginPart)
|
||||||
|
{
|
||||||
|
// Keep only upper case first letters
|
||||||
|
// eg. "My first name My last name" => "MM"
|
||||||
|
// eg. "Carrie Anne Moss" => "CAM"
|
||||||
|
if(preg_match('/^\p{Lu}/u', $sLoginPart) > 0)
|
||||||
|
{
|
||||||
|
$sInitials .= mb_substr($sLoginPart, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sInitials;
|
||||||
|
}
|
||||||
|
return $oUser->GetInitials();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsImpersonated()
|
public static function IsImpersonated()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oRealUser))
|
if (is_null(self::$m_oRealUser))
|
||||||
@@ -938,6 +1325,9 @@ class UserRights
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GetRealUser()
|
public static function GetRealUser()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oRealUser))
|
if (is_null(self::$m_oRealUser))
|
||||||
@@ -947,11 +1337,17 @@ class UserRights
|
|||||||
return self::$m_oRealUser->Get('login');
|
return self::$m_oRealUser->Get('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \User|null
|
||||||
|
*/
|
||||||
public static function GetRealUserObject()
|
public static function GetRealUserObject()
|
||||||
{
|
{
|
||||||
return self::$m_oRealUser;
|
return self::$m_oRealUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GetRealUserId()
|
public static function GetRealUserId()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oRealUser))
|
if (is_null(self::$m_oRealUser))
|
||||||
@@ -961,6 +1357,9 @@ class UserRights
|
|||||||
return self::$m_oRealUser->GetKey();
|
return self::$m_oRealUser->GetKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GetRealUserFriendlyName()
|
public static function GetRealUserFriendlyName()
|
||||||
{
|
{
|
||||||
if (is_null(self::$m_oRealUser))
|
if (is_null(self::$m_oRealUser))
|
||||||
@@ -970,6 +1369,9 @@ class UserRights
|
|||||||
return self::$m_oRealUser->GetFriendlyName();
|
return self::$m_oRealUser->GetFriendlyName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function CheckLogin()
|
protected static function CheckLogin()
|
||||||
{
|
{
|
||||||
if (!self::IsLoggedIn())
|
if (!self::IsLoggedIn())
|
||||||
@@ -983,7 +1385,7 @@ class UserRights
|
|||||||
/**
|
/**
|
||||||
* Add additional filter for organization silos to all the requests.
|
* Add additional filter for organization silos to all the requests.
|
||||||
*
|
*
|
||||||
* @param $sClass
|
* @param string $sClass
|
||||||
* @param array $aSettings
|
* @param array $aSettings
|
||||||
*
|
*
|
||||||
* @return bool|\Expression
|
* @return bool|\Expression
|
||||||
@@ -1015,11 +1417,13 @@ class UserRights
|
|||||||
/**
|
/**
|
||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param int $iActionCode
|
* @param int $iActionCode
|
||||||
* @param DBObjectSet $oInstanceSet
|
* @param \DBObjectSet $oInstanceSet
|
||||||
* @param User $oUser
|
* @param \User $oUser
|
||||||
|
*
|
||||||
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO|UR_ALLOWED_DEPENDS)
|
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO|UR_ALLOWED_DEPENDS)
|
||||||
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
public static function IsActionAllowed($sClass, $iActionCode, /*dbObjectSet*/$oInstanceSet = null, $oUser = null)
|
public static function IsActionAllowed($sClass, $iActionCode, $oInstanceSet = null, $oUser = null)
|
||||||
{
|
{
|
||||||
// When initializing, we need to let everything pass trough
|
// When initializing, we need to let everything pass trough
|
||||||
if (!self::CheckLogin()) return UR_ALLOWED_YES;
|
if (!self::CheckLogin()) return UR_ALLOWED_YES;
|
||||||
@@ -1071,6 +1475,15 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sStimulusCode
|
||||||
|
* @param \DBObjectSet|null $oInstanceSet
|
||||||
|
* @param \User|null $oUser
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
public static function IsStimulusAllowed($sClass, $sStimulusCode, /*dbObjectSet*/ $oInstanceSet = null, $oUser = null)
|
public static function IsStimulusAllowed($sClass, $sStimulusCode, /*dbObjectSet*/ $oInstanceSet = null, $oUser = null)
|
||||||
{
|
{
|
||||||
// When initializing, we need to let everything pass trough
|
// When initializing, we need to let everything pass trough
|
||||||
@@ -1102,9 +1515,11 @@ class UserRights
|
|||||||
* @param string $sClass
|
* @param string $sClass
|
||||||
* @param string $sAttCode
|
* @param string $sAttCode
|
||||||
* @param int $iActionCode
|
* @param int $iActionCode
|
||||||
* @param DBObjectSet $oInstanceSet
|
* @param \DBObjectSet $oInstanceSet
|
||||||
* @param User $oUser
|
* @param \User $oUser
|
||||||
|
*
|
||||||
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO)
|
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO)
|
||||||
|
* @throws \CoreException
|
||||||
*/
|
*/
|
||||||
public static function IsActionAllowedOnAttribute($sClass, $sAttCode, $iActionCode, /*dbObjectSet*/$oInstanceSet = null, $oUser = null)
|
public static function IsActionAllowedOnAttribute($sClass, $sAttCode, $iActionCode, /*dbObjectSet*/$oInstanceSet = null, $oUser = null)
|
||||||
{
|
{
|
||||||
@@ -1139,7 +1554,11 @@ class UserRights
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static $m_aAdmins = array();
|
/**
|
||||||
|
* @param \User|null $oUser
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsAdministrator($oUser = null)
|
public static function IsAdministrator($oUser = null)
|
||||||
{
|
{
|
||||||
if (!self::CheckLogin()) return false;
|
if (!self::CheckLogin()) return false;
|
||||||
@@ -1156,7 +1575,11 @@ class UserRights
|
|||||||
return self::$m_aAdmins[$iUser];
|
return self::$m_aAdmins[$iUser];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static $m_aPortalUsers = array();
|
/**
|
||||||
|
* @param \User|null $oUser
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsPortalUser($oUser = null)
|
public static function IsPortalUser($oUser = null)
|
||||||
{
|
{
|
||||||
if (!self::CheckLogin()) return false;
|
if (!self::CheckLogin()) return false;
|
||||||
@@ -1173,6 +1596,9 @@ class UserRights
|
|||||||
return self::$m_aPortalUsers[$iUser];
|
return self::$m_aPortalUsers[$iUser];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function GetAllowedPortals()
|
public static function GetAllowedPortals()
|
||||||
{
|
{
|
||||||
$aAllowedPortals = array();
|
$aAllowedPortals = array();
|
||||||
@@ -1198,6 +1624,50 @@ class UserRights
|
|||||||
return $aAllowedPortals;
|
return $aAllowedPortals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see UR_ACTION_READ, UR_ACTION_MODIFY, ...
|
||||||
|
*
|
||||||
|
* @param int $iActionCode
|
||||||
|
* @param array $aCategories
|
||||||
|
* @param bool $bWithLabels
|
||||||
|
* @param \User|null $oUser
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws \DictExceptionMissingString
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public static function GetAllowedClasses($iActionCode, $aCategories = array('bizmodel'), $bWithLabels = false, $oUser = null)
|
||||||
|
{
|
||||||
|
$aAllowedClasses = [];
|
||||||
|
foreach(MetaModel::GetClasses(implode(',', $aCategories)) as $sClass)
|
||||||
|
{
|
||||||
|
if(static::IsActionAllowed($sClass, $iActionCode, null, $oUser) === UR_ALLOWED_YES)
|
||||||
|
{
|
||||||
|
if($bWithLabels)
|
||||||
|
{
|
||||||
|
$aAllowedClasses[$sClass] = MetaModel::GetName($sClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aAllowedClasses[] = $sClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by label
|
||||||
|
if($bWithLabels)
|
||||||
|
{
|
||||||
|
asort($aAllowedClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aAllowedClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User|null $oUser
|
||||||
|
*
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
public static function ListProfiles($oUser = null)
|
public static function ListProfiles($oUser = null)
|
||||||
{
|
{
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
@@ -1261,8 +1731,6 @@ class UserRights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static $m_aCacheUsers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a user based on its login and its type of authentication
|
* Find a user based on its login and its type of authentication
|
||||||
*
|
*
|
||||||
@@ -1320,6 +1788,18 @@ class UserRights
|
|||||||
return $oUser;
|
return $oUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string$sClass
|
||||||
|
* @param array $aAllowedOrgs
|
||||||
|
* @param array $aSettings
|
||||||
|
* @param string|null $sAttCode
|
||||||
|
*
|
||||||
|
* @return \DBObjectSearch
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
*/
|
||||||
public static function MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings = array(), $sAttCode = null)
|
public static function MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings = array(), $sAttCode = null)
|
||||||
{
|
{
|
||||||
return self::$m_oAddOn->MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings, $sAttCode);
|
return self::$m_oAddOn->MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings, $sAttCode);
|
||||||
|
|||||||
@@ -141,7 +141,10 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
$this->m_oExtraCondition = $oFilter;
|
$this->m_oExtraCondition = $oFilter;
|
||||||
$this->m_bIsLoaded = false;
|
$this->m_bIsLoaded = false;
|
||||||
}
|
}
|
||||||
|
public function SetOrderBy(array $aOrderBy)
|
||||||
|
{
|
||||||
|
$this->m_aOrderBy = $aOrderBy;
|
||||||
|
}
|
||||||
public function ToObjectSet($aArgs = array(), $sContains = '', $iAdditionalValue = null)
|
public function ToObjectSet($aArgs = array(), $sContains = '', $iAdditionalValue = null)
|
||||||
{
|
{
|
||||||
if ($this->m_bAllowAllData)
|
if ($this->m_bAllowAllData)
|
||||||
@@ -217,7 +220,7 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
$this->m_sOperation = $sOperation;
|
$this->m_sOperation = $sOperation;
|
||||||
|
|
||||||
$this->m_aValues = array();
|
$this->m_aValues = array();
|
||||||
|
|
||||||
if ($this->m_bAllowAllData)
|
if ($this->m_bAllowAllData)
|
||||||
{
|
{
|
||||||
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||||
@@ -243,7 +246,7 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
||||||
$aFields = $oExpression->ListRequiredFields();
|
$aFields = $oExpression->ListRequiredFields();
|
||||||
$sClass = $oFilter->GetClass();
|
$sClass = $oFilter->GetClass();
|
||||||
foreach($aFields as $sField)
|
/*foreach($aFields as $sField)
|
||||||
{
|
{
|
||||||
$aFieldItems = explode('.', $sField);
|
$aFieldItems = explode('.', $sField);
|
||||||
if ($aFieldItems[0] != $sClass)
|
if ($aFieldItems[0] != $sClass)
|
||||||
@@ -251,7 +254,7 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
$sOperation = 'contains';
|
$sOperation = 'contains';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
switch ($sOperation)
|
switch ($sOperation)
|
||||||
{
|
{
|
||||||
@@ -345,6 +348,160 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
{
|
{
|
||||||
$this->m_bSort = $bSort;
|
$this->m_bSort = $bSort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
|
||||||
|
{
|
||||||
|
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation))
|
||||||
|
{
|
||||||
|
$this->LoadValuesForAutocomplete($aArgs, $sContains, $sOperation);
|
||||||
|
$this->m_bIsLoaded = true;
|
||||||
|
}
|
||||||
|
// The results are already filtered and sorted (on friendly name)
|
||||||
|
$aRet = $this->m_aValues;
|
||||||
|
return $aRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $aArgs
|
||||||
|
* @param string $sContains
|
||||||
|
* @param string $sOperation 'contains' or 'equals_start_with'
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \OQLException
|
||||||
|
*/
|
||||||
|
protected function LoadValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
|
||||||
|
{
|
||||||
|
$this->m_sContains = $sContains;
|
||||||
|
$this->m_sOperation = $sOperation;
|
||||||
|
|
||||||
|
$this->m_aValues = array();
|
||||||
|
|
||||||
|
if ($this->m_bAllowAllData)
|
||||||
|
{
|
||||||
|
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
|
||||||
|
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$oFilter) return false;
|
||||||
|
if (!is_null($this->m_oExtraCondition))
|
||||||
|
{
|
||||||
|
$oFilter = $oFilter->Intersect($this->m_oExtraCondition);
|
||||||
|
}
|
||||||
|
foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
|
||||||
|
{
|
||||||
|
foreach ($aProperties as $sProperty => $value)
|
||||||
|
{
|
||||||
|
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
||||||
|
$sClass = $oFilter->GetClass();
|
||||||
|
|
||||||
|
switch ($sOperation)
|
||||||
|
{
|
||||||
|
case 'equals':
|
||||||
|
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||||
|
$sClassAlias = $oFilter->GetClassAlias();
|
||||||
|
$aFilters = array();
|
||||||
|
$oValueExpr = new ScalarExpression($sContains);
|
||||||
|
foreach($aAttributes as $sAttribute)
|
||||||
|
{
|
||||||
|
$oNewFilter = $oFilter->DeepClone();
|
||||||
|
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||||
|
$oCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr);
|
||||||
|
$oNewFilter->AddConditionExpression($oCondition);
|
||||||
|
$aFilters[] = $oNewFilter;
|
||||||
|
}
|
||||||
|
// Unions are much faster than OR conditions
|
||||||
|
$oFilter = new DBUnionSearch($aFilters);
|
||||||
|
break;
|
||||||
|
case 'start_with':
|
||||||
|
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
|
||||||
|
$sClassAlias = $oFilter->GetClassAlias();
|
||||||
|
$aFilters = array();
|
||||||
|
$oValueExpr = new ScalarExpression($sContains.'%');
|
||||||
|
foreach($aAttributes as $sAttribute)
|
||||||
|
{
|
||||||
|
$oNewFilter = $oFilter->DeepClone();
|
||||||
|
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||||
|
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||||
|
$oNewFilter->AddConditionExpression($oCondition);
|
||||||
|
$aFilters[] = $oNewFilter;
|
||||||
|
}
|
||||||
|
// Unions are much faster than OR conditions
|
||||||
|
$oFilter = new DBUnionSearch($aFilters);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
||||||
|
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
||||||
|
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||||
|
$oFilter->AddConditionExpression($oNewCondition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
|
||||||
|
if (empty($this->m_sValueAttCode))
|
||||||
|
{
|
||||||
|
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($sClass);
|
||||||
|
$sFormatAdditionalField = $aComplementAttributeSpec[0];
|
||||||
|
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||||
|
|
||||||
|
if (count($aAdditionalField)>0)
|
||||||
|
{
|
||||||
|
$aAttToLoad = array_merge ($aAttToLoad, [$oFilter->GetClassAlias() => $aAdditionalField]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oObjects->OptimizeColumnLoad($aAttToLoad);
|
||||||
|
while ($oObject = $oObjects->Fetch())
|
||||||
|
{
|
||||||
|
$aData=[];
|
||||||
|
if (empty($this->m_sValueAttCode))
|
||||||
|
{
|
||||||
|
$aData['label'] = $oObject->GetName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aData['label'] = $oObject->Get($this->m_sValueAttCode);
|
||||||
|
}
|
||||||
|
if($oObject->IsObsolete())
|
||||||
|
{
|
||||||
|
$aData['obsolescence_flag']='1';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aData['obsolescence_flag']='0';
|
||||||
|
}
|
||||||
|
if (count($aAdditionalField)>0)
|
||||||
|
{
|
||||||
|
$aArguments = [];
|
||||||
|
foreach ($aAdditionalField as $sAdditionalField)
|
||||||
|
{
|
||||||
|
array_push ($aArguments,$oObject->Get($sAdditionalField));
|
||||||
|
}
|
||||||
|
$aData['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aData['additional_field']='';
|
||||||
|
}
|
||||||
|
$this->m_aValues[$oObject->GetKey()] = $aData;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ class XMLBulkExport extends BulkExport
|
|||||||
|
|
||||||
while ($aObjects = $oSet->FetchAssoc())
|
while ($aObjects = $oSet->FetchAssoc())
|
||||||
{
|
{
|
||||||
set_time_limit($iLoopTimeLimit);
|
set_time_limit(intval($iLoopTimeLimit));
|
||||||
if (count($aAuthorizedClasses) > 1)
|
if (count($aAuthorizedClasses) > 1)
|
||||||
{
|
{
|
||||||
$sData .= "<Row>\n";
|
$sData .= "<Row>\n";
|
||||||
@@ -182,7 +182,7 @@ class XMLBulkExport extends BulkExport
|
|||||||
$iCount++;
|
$iCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_time_limit($iPreviousTimeLimit);
|
set_time_limit(intval($iPreviousTimeLimit));
|
||||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||||
if ($this->aStatusInfo['total'] == 0)
|
if ($this->aStatusInfo['total'] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
5
css/README.md
Normal file
5
css/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
In order to better separate our developments from the embedded third-party libs, files should be moved in either the /backoffice, /lib or something new folders.
|
||||||
|
|
||||||
|
IMPORTANT: Before moving a file, we should first consider if:
|
||||||
|
- The file is used in an iTop extension that should be compatible with the iTop version currently under developments
|
||||||
|
- The file is still used in iTop itself (or if we can consider removing it for clean up)
|
||||||
71
css/backoffice/README.md
Normal file
71
css/backoffice/README.md
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
## Description
|
||||||
|
This is a brief description of the SASS 7-1 system and how to use it.
|
||||||
|
- [File structure](#file-structure)
|
||||||
|
- [Usage](#usage)
|
||||||
|
|
||||||
|
## File structure
|
||||||
|
SCSS files are structured following the [7-1 pattern](https://sass-guidelin.es/#the-7-1-pattern). \
|
||||||
|
@rveitch made a great summary with the following, which can also be found [here](https://gist.github.com/rveitch/84cea9650092119527bc).
|
||||||
|
|
||||||
|
```
|
||||||
|
css/backoffice/
|
||||||
|
|
|
||||||
|
|– utils/
|
||||||
|
| |– _variables.scss # Sass Variables
|
||||||
|
| |– _functions.scss # Sass Functions
|
||||||
|
| |– _mixins.scss # Sass Mixins
|
||||||
|
| |– _helpers.scss # Class & placeholders helpers
|
||||||
|
|
|
||||||
|
|– vendors/
|
||||||
|
| |– _bootstrap.scss # Bootstrap
|
||||||
|
| |– _jquery-ui.scss # jQuery UI
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|– base/
|
||||||
|
| |– _reset.scss # Reset/normalize
|
||||||
|
| |– _typography.scss # Typography rules
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|– components/
|
||||||
|
| |– _buttons.scss # Buttons
|
||||||
|
| |– _carousel.scss # Carousel
|
||||||
|
| |– _cover.scss # Cover
|
||||||
|
| |– _dropdown.scss # Dropdown
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|– layout/
|
||||||
|
| |– _navigation.scss # Navigation
|
||||||
|
| |– _grid.scss # Grid system
|
||||||
|
| |– _header.scss # Header
|
||||||
|
| |– _footer.scss # Footer
|
||||||
|
| |– _sidebar.scss # Sidebar
|
||||||
|
| |– _forms.scss # Forms
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|– pages/
|
||||||
|
| |– _home.scss # Home specific styles
|
||||||
|
| |– _contact.scss # Contact specific styles
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|– themes/
|
||||||
|
| |– _theme.scss # Default theme
|
||||||
|
| |– _admin.scss # Admin theme
|
||||||
|
| ... # Etc…
|
||||||
|
|
|
||||||
|
|
|
||||||
|
`– main.scss # Main Sass file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
To avoid common errors, files should be imported in the final file in the following order. Again those are just following the SASS guidelines:
|
||||||
|
- Utils
|
||||||
|
- Variables
|
||||||
|
- Functions
|
||||||
|
- Mixins
|
||||||
|
- Helpers
|
||||||
|
- Vendors
|
||||||
|
- Base
|
||||||
|
- Components
|
||||||
|
- Layout
|
||||||
|
- Pages
|
||||||
|
- Themes
|
||||||
20
css/backoffice/base/_all.scss
Normal file
20
css/backoffice/base/_all.scss
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import "base";
|
||||||
|
@import "typography";
|
||||||
67
css/backoffice/base/_base.scss
Normal file
67
css/backoffice/base/_base.scss
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
$ibo-hyperlink-color: $ibo-color-primary-500 !default;
|
||||||
|
$ibo-hyperlink-color--on-hover: $ibo-color-primary-600 !default;
|
||||||
|
$ibo-hyperlink-color--on-active: $ibo-color-primary-700 !default;
|
||||||
|
|
||||||
|
$ibo-svg-illustration--fill: $ibo-color-primary-500 !default;
|
||||||
|
|
||||||
|
$ibo-content-block--background-color: $ibo-color-white-100 !default;
|
||||||
|
$ibo-content-block--border: 1px solid $ibo-color-grey-400 !default;
|
||||||
|
|
||||||
|
/* CSS variables */
|
||||||
|
:root{
|
||||||
|
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
|
||||||
|
--ibo-hyperlink-color--on-hover: #{$ibo-hyperlink-color--on-hover};
|
||||||
|
--ibo-hyperlink-color--on-active: #{$ibo-hyperlink-color--on-active};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Box sizing reset */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after{
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base font size (used by all typographies) */
|
||||||
|
html{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hyperlinks reset, ensure that they are of the right color and without decoration everywhere (of course this can be overloaded in some components) */
|
||||||
|
a{
|
||||||
|
color: var(--ibo-hyperlink-color);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:visited{
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
color: var(--ibo-hyperlink-color--on-hover);
|
||||||
|
}
|
||||||
|
&:active{
|
||||||
|
color: var(--ibo-hyperlink-color--on-active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ibo-svg-illustration--container>svg *[fill="#6c63ff"]{
|
||||||
|
fill: $ibo-svg-illustration--fill;
|
||||||
|
}
|
||||||
163
css/backoffice/base/_typography.scss
Normal file
163
css/backoffice/base/_typography.scss
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is an overload of the default lib. stylesheet to use local fonts instead of the CDN */
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 100;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 Thin'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Thin.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Thin.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 100;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 Thin'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-ThinItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-ThinItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 200;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 ExtraLight'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-ExtraLight.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-ExtraLight.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 200;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 ExtraLight'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-ExtraLightItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-ExtraLightItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 Light'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Light.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Light.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 Light'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-LightItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-LightItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Regular.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Regular.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Italic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Italic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 Medium'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Medium.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Medium.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 Medium'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-MediumItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-MediumItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 SemiBold'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-SemiBold.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-SemiBold.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 SemiBold'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-SemiBoldItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-SemiBoldItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Bold.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Bold.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-BoldItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-BoldItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 800;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 ExtraBold'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-ExtraBold.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-ExtraBold.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 800;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 ExtraBold'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-ExtraBoldItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-ExtraBoldItalic.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 900;
|
||||||
|
font-style: normal;
|
||||||
|
src: local('Raleway-v4020 Black'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-Black.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-Black.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: Monorale;
|
||||||
|
font-weight: 900;
|
||||||
|
font-style: italic;
|
||||||
|
src: local('Raleway-v4020 Black'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/otf/Monorale-BlackItalic.otf') format('otf'),
|
||||||
|
url('../../lib/samvk/monorale-raleway-sober/woff/Monorale-BlackItalic.woff') format('woff');
|
||||||
|
}
|
||||||
98
css/backoffice/components/_alert.scss
Normal file
98
css/backoffice/components/_alert.scss
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* SCSS variables */
|
||||||
|
$ibo-alert--spacing-top--with-same-block: 6px !default;
|
||||||
|
$ibo-alert--spacing-top--with-other-blocks: 16px !default;
|
||||||
|
$ibo-alert--padding-y: 18px !default;
|
||||||
|
$ibo-alert--padding-x: 20px !default;
|
||||||
|
$ibo-alert--border-radius: $ibo-border-radius-300 !default;
|
||||||
|
|
||||||
|
$ibo-alert--title--padding-bottom: 4px !default;
|
||||||
|
|
||||||
|
$ibo-alert--title--highlight--width: 4px !default;
|
||||||
|
$ibo-alert--title--highlight--height: 100% !default;
|
||||||
|
|
||||||
|
$ibo-alert-colors: (
|
||||||
|
'primary': ($ibo-color-primary-200, $ibo-color-primary-700, $ibo-color-primary-900),
|
||||||
|
'secondary': ($ibo-color-secondary-200, $ibo-color-secondary-700, $ibo-color-secondary-900),
|
||||||
|
'neutral': ($ibo-color-secondary-200, $ibo-color-secondary-700, $ibo-color-secondary-900),
|
||||||
|
'information': ($ibo-color-information-200, $ibo-color-information-700, $ibo-color-information-900),
|
||||||
|
'success': ($ibo-color-success-100, $ibo-color-success-700, $ibo-color-success-900),
|
||||||
|
'failure': ($ibo-color-danger-200, $ibo-color-danger-700, $ibo-color-danger-900),
|
||||||
|
'warning': ($ibo-color-warning-200, $ibo-color-warning-700, $ibo-color-warning-900),
|
||||||
|
'danger': ($ibo-color-danger-200, $ibo-color-danger-700, $ibo-color-danger-900),
|
||||||
|
'grey' : ($ibo-color-grey-200, $ibo-color-grey-700, $ibo-color-grey-900),
|
||||||
|
'blue-grey': ($ibo-color-blue-grey-200, $ibo-color-blue-grey-700, $ibo-color-blue-grey-900),
|
||||||
|
'blue': ($ibo-color-blue-200, $ibo-color-blue-700, $ibo-color-blue-900),
|
||||||
|
'cyan': ($ibo-color-cyan-100, $ibo-color-blue-700, $ibo-color-cyan-900),
|
||||||
|
'green': ($ibo-color-green-100, $ibo-color-green-700, $ibo-color-green-900),
|
||||||
|
'orange' : ($ibo-color-orange-200, $ibo-color-orange-700, $ibo-color-orange-900),
|
||||||
|
'red': ($ibo-color-red-200, $ibo-color-red-700, $ibo-color-red-900),
|
||||||
|
'pink': ($ibo-color-pink-200, $ibo-color-pink-700, $ibo-color-pink-900),
|
||||||
|
) !default;
|
||||||
|
|
||||||
|
@each $sColor, $aColorValues in $ibo-alert-colors {
|
||||||
|
$bg-color: nth($aColorValues, 1);
|
||||||
|
$highlight-color: nth($aColorValues, 2);
|
||||||
|
$text-color: nth($aColorValues, 3);
|
||||||
|
.ibo-alert.ibo-is-#{$sColor} {
|
||||||
|
background-color: $bg-color;
|
||||||
|
color: $text-color;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background-color: $highlight-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rules */
|
||||||
|
.ibo-alert {
|
||||||
|
position: relative;
|
||||||
|
padding: $ibo-alert--padding-y $ibo-alert--padding-x;
|
||||||
|
border-radius: $ibo-alert--border-radius;
|
||||||
|
overflow: hidden; /* To force highlight color to be cropped by the border radius */
|
||||||
|
|
||||||
|
@extend %ibo-font-ral-med-150;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
content: '';
|
||||||
|
|
||||||
|
width: $ibo-alert--title--highlight--width;
|
||||||
|
height: $ibo-alert--title--highlight--height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ibo-alert--title {
|
||||||
|
padding-bottom: $ibo-alert--title--padding-bottom;
|
||||||
|
|
||||||
|
@extend %ibo-font-ral-bol-150;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spacing between alert blocks */
|
||||||
|
.ibo-alert + .ibo-alert {
|
||||||
|
margin-top: $ibo-alert--spacing-top--with-same-block;
|
||||||
|
}
|
||||||
|
/* Spacing between an alert block and something else */
|
||||||
|
.ibo-alert + :not(.ibo-alert) {
|
||||||
|
margin-top: $ibo-alert--spacing-top--with-other-blocks;
|
||||||
|
}
|
||||||
29
css/backoffice/components/_all.scss
Normal file
29
css/backoffice/components/_all.scss
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* copyright Copyright (C) 2010-2020 Combodo SARL
|
||||||
|
* license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import "alert";
|
||||||
|
@import "badge";
|
||||||
|
@import "button";
|
||||||
|
@import "breadcrumbs";
|
||||||
|
@import "quick-create";
|
||||||
|
@import "global-search";
|
||||||
|
@import "popover-menu/popover-menu";
|
||||||
|
@import "popover-menu/popover-menu-item";
|
||||||
|
@import "newsroom-menu";
|
||||||
|
@import "panel";
|
||||||
|
@import "modal";
|
||||||
|
@import "dashlet/all";
|
||||||
|
@import "input/all";
|
||||||
|
|
||||||
|
@import "title";
|
||||||
|
@import "datatable";
|
||||||
|
@import "form";
|
||||||
|
@import "fieldset";
|
||||||
|
@import "field";
|
||||||
|
@import "toolbar";
|
||||||
|
@import "richtext";
|
||||||
|
@import "formtable";
|
||||||
|
@import "formtablerow";
|
||||||
|
@import "search-form";
|
||||||
99
css/backoffice/components/_badge.scss
Normal file
99
css/backoffice/components/_badge.scss
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* SCSS variables */
|
||||||
|
$ibo-badge--margin: 4px 8px !default;
|
||||||
|
$ibo-badge--padding: 6px 10px !default;
|
||||||
|
$ibo-badge--border-radius: $ibo-border-radius-300 !default;
|
||||||
|
|
||||||
|
$ibo-badge-new-state-primary-color: $ibo-color-blue-100 !default;
|
||||||
|
$ibo-badge-new-state-secondary-color: $ibo-color-blue-900 !default;
|
||||||
|
|
||||||
|
$ibo-badge-neutral-state-primary-color: $ibo-color-blue-100 !default;
|
||||||
|
$ibo-badge-neutral-state-secondary-color: $ibo-color-blue-900 !default;
|
||||||
|
|
||||||
|
$ibo-badge-waiting-state-primary-color: $ibo-color-orange-100 !default;
|
||||||
|
$ibo-badge-waiting-state-secondary-color: $ibo-color-orange-800 !default;
|
||||||
|
|
||||||
|
$ibo-badge-success-state-primary-color: $ibo-color-green-100 !default;
|
||||||
|
$ibo-badge-success-state-secondary-color: $ibo-color-green-900 !default;
|
||||||
|
|
||||||
|
$ibo-badge-failure-state-primary-color: $ibo-color-red-100 !default;
|
||||||
|
$ibo-badge-failure-state-secondary-color: $ibo-color-red-800 !default;
|
||||||
|
|
||||||
|
$ibo-badge-frozen-state-primary-color: $ibo-color-grey-100 !default;
|
||||||
|
$ibo-badge-frozen-state-secondary-color: $ibo-color-grey-700 !default;
|
||||||
|
|
||||||
|
/* - For basic badge */
|
||||||
|
$ibo-badge-active-state-primary-color: $ibo-color-green-100 !default;
|
||||||
|
$ibo-badge-active-state-secondary-color: $ibo-color-green-900 !default;
|
||||||
|
|
||||||
|
$ibo-badge-inactive-state-primary-color: $ibo-color-orange-100 !default;
|
||||||
|
$ibo-badge-inactive-state-secondary-color: $ibo-color-orange-800 !default;
|
||||||
|
|
||||||
|
$ibo-badge-states-colors: (
|
||||||
|
'new': (
|
||||||
|
'primary-color': $ibo-badge-new-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-new-state-secondary-color,
|
||||||
|
),
|
||||||
|
'neutral': (
|
||||||
|
'primary-color': $ibo-badge-neutral-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-neutral-state-secondary-color,
|
||||||
|
),
|
||||||
|
'waiting': (
|
||||||
|
'primary-color': $ibo-badge-waiting-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-waiting-state-secondary-color,
|
||||||
|
),
|
||||||
|
'success': (
|
||||||
|
'primary-color': $ibo-badge-success-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-success-state-secondary-color,
|
||||||
|
),
|
||||||
|
'failure': (
|
||||||
|
'primary-color': $ibo-badge-failure-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-failure-state-secondary-color,
|
||||||
|
),
|
||||||
|
'frozen': (
|
||||||
|
'primary-color': $ibo-badge-frozen-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-frozen-state-secondary-color,
|
||||||
|
),
|
||||||
|
'active': (
|
||||||
|
'primary-color': $ibo-badge-active-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-active-state-secondary-color,
|
||||||
|
),
|
||||||
|
'inactive': (
|
||||||
|
'primary-color': $ibo-badge-inactive-state-primary-color,
|
||||||
|
'secondary-color': $ibo-badge-inactive-state-secondary-color,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $sType, $aColors in $ibo-badge-states-colors {
|
||||||
|
.ibo-badge-is-#{$sType} {
|
||||||
|
color: map-get($aColors, 'secondary-color');
|
||||||
|
background-color: map-get($aColors, 'primary-color');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rules */
|
||||||
|
.ibo-badge {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin: $ibo-badge--margin;
|
||||||
|
padding: $ibo-badge--padding;
|
||||||
|
border-radius: $ibo-badge--border-radius;
|
||||||
|
}
|
||||||
80
css/backoffice/components/_breadcrumbs.scss
Normal file
80
css/backoffice/components/_breadcrumbs.scss
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
$ibo-breadcrumbs--item--text-color: $ibo-color-grey-800 !default;
|
||||||
|
|
||||||
|
$ibo-breadcrumbs--item-icon--margin-x: 8px !default;
|
||||||
|
$ibo-breadcrumbs--item-icon--max-width: 16px !default;
|
||||||
|
$ibo-breadcrumbs--item-icon--text-color: $ibo-color-grey-600 !default;
|
||||||
|
|
||||||
|
$ibo-breadcrumbs--item-label--max-width: 100px !default;
|
||||||
|
|
||||||
|
$ibo-breadcrumbs--item-separator--margin-x: 12px !default;
|
||||||
|
$ibo-breadcrumbs--item-separator--text-color: $ibo-color-grey-500 !default;
|
||||||
|
|
||||||
|
.ibo-breadcrumbs{
|
||||||
|
@extend %ibo-full-height-content;
|
||||||
|
|
||||||
|
* {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ibo-breadcrumbs--item{
|
||||||
|
color: $ibo-breadcrumbs--item--text-color;
|
||||||
|
@extend %ibo-font-ral-nor-100;
|
||||||
|
|
||||||
|
&:not(:last-child){
|
||||||
|
&::after{
|
||||||
|
content: '\f054';
|
||||||
|
margin: 0 $ibo-breadcrumbs--item-separator--margin-x;
|
||||||
|
color: $ibo-breadcrumbs--item-separator--text-color;
|
||||||
|
@extend %fa-solid-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
.ibo-breadcrumbs--item-icon{
|
||||||
|
> *{
|
||||||
|
opacity: 1;
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ibo-breadcrumbs--item-icon{
|
||||||
|
margin-right: $ibo-breadcrumbs--item-icon--margin-x;
|
||||||
|
@extend %ibo-font-ral-nor-150;
|
||||||
|
transition: all 0.1s linear;
|
||||||
|
|
||||||
|
> span{
|
||||||
|
color: $ibo-breadcrumbs--item-icon--text-color;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
> img{
|
||||||
|
height: auto;
|
||||||
|
max-width: $ibo-breadcrumbs--item-icon--max-width;
|
||||||
|
opacity: 0.3;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ibo-breadcrumbs--item-label{
|
||||||
|
display: inline; /* Otherwise the "truncate" doesn't work with th default display: flex */
|
||||||
|
max-width: $ibo-breadcrumbs--item-label--max-width;
|
||||||
|
@extend %ibo-text-truncated-with-ellipsis;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user