mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
Compare commits
1497 Commits
3.0.0-alph
...
3.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa9ab1ace5 | ||
|
|
bfe22b4ec0 | ||
|
|
f84bc9fbbc | ||
|
|
0dc03de7b2 | ||
|
|
af338de17f | ||
|
|
0cffd567c2 | ||
|
|
9d006c279b | ||
|
|
f410bff309 | ||
|
|
0e9ff71c0a | ||
|
|
a599a5c5b7 | ||
|
|
84dae0fb37 | ||
|
|
65e3ef32ed | ||
|
|
0396914068 | ||
|
|
0e55a30e5a | ||
|
|
c0fbf0c735 | ||
|
|
e59d472cec | ||
|
|
27e6840442 | ||
|
|
a6aa183e26 | ||
|
|
b5074c4cee | ||
|
|
fbb54c6d6d | ||
|
|
95066fbc49 | ||
|
|
e2958bd43f | ||
|
|
382135fde8 | ||
|
|
4d80235d89 | ||
|
|
8b9589744b | ||
|
|
250d95c3eb | ||
|
|
0997189969 | ||
|
|
410948fb4e | ||
|
|
9f75fae33f | ||
|
|
b1aebc6c7a | ||
|
|
85526b1983 | ||
|
|
2a1e0b7429 | ||
|
|
3a73bd3b24 | ||
|
|
d7ba0aac82 | ||
|
|
8259a79cd2 | ||
|
|
de71d490c1 | ||
|
|
60b015919d | ||
|
|
2ca11aa2b7 | ||
|
|
275daf3b0d | ||
|
|
671d112452 | ||
|
|
a23ea9a01f | ||
|
|
949b213f9d | ||
|
|
a940adc4ba | ||
|
|
5d994edd62 | ||
|
|
2a9ce75db0 | ||
|
|
f8fcfc4d7d | ||
|
|
663a9ab224 | ||
|
|
f604821bdf | ||
|
|
ac83c0334c | ||
|
|
457165b2fc | ||
|
|
b1ca1f2630 | ||
|
|
bce1bd8192 | ||
|
|
4d123e1450 | ||
|
|
58e315d7f6 | ||
|
|
1281d475e4 | ||
|
|
32ac999ff5 | ||
|
|
1059befa39 | ||
|
|
5db8bd06ba | ||
|
|
0f5130611d | ||
|
|
a1271da74a | ||
|
|
0d40235791 | ||
|
|
d1e594e225 | ||
|
|
bcc2d7140e | ||
|
|
ee5847ec82 | ||
|
|
108bc2fa1d | ||
|
|
efb7f84ec4 | ||
|
|
224031e0d6 | ||
|
|
e905838733 | ||
|
|
dd63f2b817 | ||
|
|
8f84c3b84b | ||
|
|
bc4f384948 | ||
|
|
00c58bb245 | ||
|
|
11f6c88ac7 | ||
|
|
77cf879f4f | ||
|
|
13f6f6ebe6 | ||
|
|
c413ac989e | ||
|
|
7a770b32ee | ||
|
|
9d8adae5c7 | ||
|
|
b0531597f0 | ||
|
|
0bdf43b085 | ||
|
|
27da8470b7 | ||
|
|
c0be48ceee | ||
|
|
6c561029e9 | ||
|
|
c417a454d6 | ||
|
|
d8e2a1cc7c | ||
|
|
51e24a4e35 | ||
|
|
a82f172ca4 | ||
|
|
8ef43452f8 | ||
|
|
18a4867b4d | ||
|
|
ff05a1d35e | ||
|
|
5a4c9393a4 | ||
|
|
4b03b42494 | ||
|
|
215dcfb465 | ||
|
|
b965138d57 | ||
|
|
485262ec0a | ||
|
|
dd8a51ea1b | ||
|
|
d85729803d | ||
|
|
3132d665e0 | ||
|
|
be03f3c6de | ||
|
|
3a876d5c75 | ||
|
|
147916062b | ||
|
|
bcfdf76b71 | ||
|
|
679542eaaa | ||
|
|
4d5ff22b60 | ||
|
|
d54c5b5f55 | ||
|
|
0de6f98add | ||
|
|
5bf6035bcf | ||
|
|
a076792e77 | ||
|
|
73132f981e | ||
|
|
80e4a46a20 | ||
|
|
95d9b845b6 | ||
|
|
609d9c7a60 | ||
|
|
3d338aff33 | ||
|
|
8a46900df9 | ||
|
|
8efbfd13d0 | ||
|
|
19264a7d64 | ||
|
|
742e3a2a20 | ||
|
|
117bf3046d | ||
|
|
b072e1bb3d | ||
|
|
d405fc0675 | ||
|
|
77527987ee | ||
|
|
2e6b773ba4 | ||
|
|
dd6a9fe16a | ||
|
|
d9ccc620c9 | ||
|
|
b245275c7d | ||
|
|
bf22c8b67a | ||
|
|
1b58d9b801 | ||
|
|
2d2a6857de | ||
|
|
373641e01d | ||
|
|
d11eceac62 | ||
|
|
3965806fa0 | ||
|
|
74eabafe31 | ||
|
|
2625d2da80 | ||
|
|
1b9eb2a6ad | ||
|
|
94c37b2e14 | ||
|
|
71d2d61c4e | ||
|
|
020dc8b819 | ||
|
|
c11ad30134 | ||
|
|
02d32a556d | ||
|
|
71fcc6f026 | ||
|
|
dd614f5931 | ||
|
|
499d429a0e | ||
|
|
7168860a0b | ||
|
|
a395c1760a | ||
|
|
4033773849 | ||
|
|
9fd6ba414d | ||
|
|
2aee978790 | ||
|
|
39efe1237e | ||
|
|
684c88e0b8 | ||
|
|
e7c7ca76ac | ||
|
|
a6e5969201 | ||
|
|
1e99ad436f | ||
|
|
8580eb6d2b | ||
|
|
c6b8526dc0 | ||
|
|
03c7d63588 | ||
|
|
32e714f4a6 | ||
|
|
b8ef4885e5 | ||
|
|
e669cfcea1 | ||
|
|
82f0cd5f3d | ||
|
|
b6661fde86 | ||
|
|
e46480032e | ||
|
|
aed1e7dfdc | ||
|
|
b32fd7e018 | ||
|
|
3ae8575c1d | ||
|
|
cc4b307bc9 | ||
|
|
6d004f83dd | ||
|
|
8f68ca3f67 | ||
|
|
84741c19f0 | ||
|
|
96126d235f | ||
|
|
4de40e289f | ||
|
|
86f649affc | ||
|
|
4f5c987d8b | ||
|
|
9ccd26a541 | ||
|
|
e7b5953feb | ||
|
|
e441e5e78a | ||
|
|
6d57945bd1 | ||
|
|
0cb0f52b12 | ||
|
|
6be9a87c15 | ||
|
|
43daa2ef08 | ||
|
|
8f9a69fa60 | ||
|
|
1d94e12da8 | ||
|
|
0a04fe5917 | ||
|
|
b03389068e | ||
|
|
c9171ef30e | ||
|
|
3853d38d69 | ||
|
|
caa2a05bf4 | ||
|
|
fc39d8aca9 | ||
|
|
022887258f | ||
|
|
cf12578289 | ||
|
|
3105a7ef77 | ||
|
|
f5ee19370c | ||
|
|
923134d67d | ||
|
|
3c2c2d7a51 | ||
|
|
3ee4a14c56 | ||
|
|
dd284a6c1d | ||
|
|
c240a8991d | ||
|
|
0948c46dc7 | ||
|
|
d9755fe59d | ||
|
|
7f82e9262b | ||
|
|
44952d1ea0 | ||
|
|
7f15eed9a8 | ||
|
|
14930fbab2 | ||
|
|
2cbca93d77 | ||
|
|
c2f5cafaf3 | ||
|
|
81822efa0f | ||
|
|
104cf9479c | ||
|
|
a36632def6 | ||
|
|
6a1b1d7740 | ||
|
|
f544d53c36 | ||
|
|
3188204d05 | ||
|
|
a7294d48a6 | ||
|
|
42be0c20cb | ||
|
|
1c6ffab0e3 | ||
|
|
095d61b6f9 | ||
|
|
923a025f1c | ||
|
|
a4b6f4e37c | ||
|
|
78b2824c13 | ||
|
|
f0c73451a2 | ||
|
|
62f5eb5ae9 | ||
|
|
7d9416cc81 | ||
|
|
a82a2df6aa | ||
|
|
f1e4120364 | ||
|
|
3471d9d693 | ||
|
|
6d7bcb8a7c | ||
|
|
db6e813cba | ||
|
|
d74e3e6b42 | ||
|
|
e9648ad75e | ||
|
|
e53da47647 | ||
|
|
1128490d47 | ||
|
|
186ef1689e | ||
|
|
0487cb8701 | ||
|
|
27b930c31c | ||
|
|
a8ef1c7899 | ||
|
|
644f0bc94c | ||
|
|
f3b0f79a59 | ||
|
|
eaae79a5f0 | ||
|
|
bc10baed3e | ||
|
|
b740cb2afd | ||
|
|
c0ec7e02f8 | ||
|
|
5977c5dd9e | ||
|
|
1c2dcc7b9a | ||
|
|
6ad3c40c42 | ||
|
|
f49c8ce188 | ||
|
|
acf828b72e | ||
|
|
cb61d85572 | ||
|
|
626316e8d1 | ||
|
|
ab30bae46a | ||
|
|
bd2c0d1121 | ||
|
|
64764228a9 | ||
|
|
463593d6cf | ||
|
|
85aac7bf52 | ||
|
|
dc36b4648d | ||
|
|
25145a68af | ||
|
|
dab522caca | ||
|
|
88634bcd92 | ||
|
|
6ab6930986 | ||
|
|
1f3b467083 | ||
|
|
34647cc402 | ||
|
|
2a9e16bd2c | ||
|
|
ed1fdfa830 | ||
|
|
1124a584cd | ||
|
|
d2c014f718 | ||
|
|
e488ec8c38 | ||
|
|
18b2e54581 | ||
|
|
3c89313795 | ||
|
|
11278d7ba5 | ||
|
|
a6eeb3a50a | ||
|
|
1f1028bbc0 | ||
|
|
08f973f8c0 | ||
|
|
ad22113881 | ||
|
|
e5498e3292 | ||
|
|
16c9599739 | ||
|
|
a7040a911d | ||
|
|
8227796c87 | ||
|
|
bac92716f3 | ||
|
|
993dbed7e7 | ||
|
|
390dc1c945 | ||
|
|
09b12bd06e | ||
|
|
3a06f2eaa9 | ||
|
|
a8e1db8b3c | ||
|
|
2cc4448a15 | ||
|
|
d0d254ad59 | ||
|
|
8f62b63309 | ||
|
|
227c90b47f | ||
|
|
6fc3033100 | ||
|
|
cfab20519e | ||
|
|
cbc5bb70d0 | ||
|
|
d5d3a7af47 | ||
|
|
03fcc94b1f | ||
|
|
4a28aa316f | ||
|
|
88a615528f | ||
|
|
b3e1b7124a | ||
|
|
48d0fc6ddb | ||
|
|
8bf9987174 | ||
|
|
0f4c325aab | ||
|
|
93a1f027cb | ||
|
|
3e0971597b | ||
|
|
fce3934977 | ||
|
|
d8feda89a5 | ||
|
|
7aecdd0dc7 | ||
|
|
a478294211 | ||
|
|
9de1f1800d | ||
|
|
94c8dbac18 | ||
|
|
efc745f574 | ||
|
|
3e45dcdbb1 | ||
|
|
07257cc2d2 | ||
|
|
ae6e08d430 | ||
|
|
473a49ab6b | ||
|
|
0c58d67f41 | ||
|
|
d2c4a6e2e9 | ||
|
|
d1ccd5c8eb | ||
|
|
370a07f596 | ||
|
|
9ae056e663 | ||
|
|
ce596877a4 | ||
|
|
3d9540e895 | ||
|
|
27d8869665 | ||
|
|
3b3fa7b1f8 | ||
|
|
135b5e8adb | ||
|
|
52dbf23245 | ||
|
|
6b899d3f77 | ||
|
|
87ba67225a | ||
|
|
2ad3b3c27e | ||
|
|
46dc7709ab | ||
|
|
92a640e41a | ||
|
|
842df7646b | ||
|
|
01b38d2ed6 | ||
|
|
ddb5ffc11a | ||
|
|
2a62e28c66 | ||
|
|
973133ce0b | ||
|
|
be0a728f42 | ||
|
|
1bb7d9947c | ||
|
|
65d94bd914 | ||
|
|
d951d0def0 | ||
|
|
beadd9cd03 | ||
|
|
fac97324a3 | ||
|
|
f33919c312 | ||
|
|
74d8eda713 | ||
|
|
6790fdb9e8 | ||
|
|
d545123ca7 | ||
|
|
59678ef8c6 | ||
|
|
a6d20ab648 | ||
|
|
e5559a1899 | ||
|
|
f8757c6d5d | ||
|
|
7f4ef12c04 | ||
|
|
2a90557782 | ||
|
|
7b3595357a | ||
|
|
f6d9d0f08b | ||
|
|
f3cf154969 | ||
|
|
923a4048d3 | ||
|
|
0816d27456 | ||
|
|
d07199db7c | ||
|
|
903afff687 | ||
|
|
c0f5906dce | ||
|
|
fa3140cc13 | ||
|
|
22aaba3c65 | ||
|
|
5878b18b02 | ||
|
|
530ec111ef | ||
|
|
430049d7c4 | ||
|
|
e45fd92022 | ||
|
|
605165fc5a | ||
|
|
644944c6fd | ||
|
|
8313d61521 | ||
|
|
81d30ca9f4 | ||
|
|
6078ccc144 | ||
|
|
7b9d89e485 | ||
|
|
48bc8b2341 | ||
|
|
8f03ac4aa3 | ||
|
|
97f5f0b50d | ||
|
|
05594ccdd6 | ||
|
|
e2f301827a | ||
|
|
067cbe2afa | ||
|
|
a99f4c0666 | ||
|
|
d594f28ed9 | ||
|
|
deed948f54 | ||
|
|
25e88b889d | ||
|
|
d6695d3ad8 | ||
|
|
0bc9aed3fe | ||
|
|
98ec4bba53 | ||
|
|
e527324468 | ||
|
|
8ccada40d1 | ||
|
|
80d974f2b4 | ||
|
|
521c493fd1 | ||
|
|
b68ee1136e | ||
|
|
0f43b0a6de | ||
|
|
58d1a1d311 | ||
|
|
5b3ab2965f | ||
|
|
f97f55bcca | ||
|
|
3262ad7029 | ||
|
|
a5bb6a0c55 | ||
|
|
f0d6b41cee | ||
|
|
5c01d222c9 | ||
|
|
7e65541d3c | ||
|
|
83b8fbb6b5 | ||
|
|
5b9e5f8de9 | ||
|
|
ddceeafc52 | ||
|
|
56087d9686 | ||
|
|
5aef6f209b | ||
|
|
1b6d69037e | ||
|
|
3941f323c0 | ||
|
|
b19f9d4875 | ||
|
|
057bb1a296 | ||
|
|
192cb2df73 | ||
|
|
47c797daba | ||
|
|
33dcb35344 | ||
|
|
68ab84716b | ||
|
|
b60fb4fb99 | ||
|
|
8fb5a9acd0 | ||
|
|
4c289edac7 | ||
|
|
f6be3736fd | ||
|
|
f8f9c2d7bb | ||
|
|
94fdc79be5 | ||
|
|
5fa2caac29 | ||
|
|
8b25679df8 | ||
|
|
a67bff3959 | ||
|
|
24eec4aa21 | ||
|
|
978e64d66c | ||
|
|
3dad90dbcf | ||
|
|
17c4a18c94 | ||
|
|
c8f709a4e6 | ||
|
|
90cc08b920 | ||
|
|
54b718e7cd | ||
|
|
0bc2f2c818 | ||
|
|
c0b1581f0c | ||
|
|
bf793fd989 | ||
|
|
711fe5607b | ||
|
|
4fa259af14 | ||
|
|
49fe8d0a0f | ||
|
|
e492d713c4 | ||
|
|
77962d73eb | ||
|
|
e53cab0d1d | ||
|
|
5816b22639 | ||
|
|
5f8eb26bff | ||
|
|
8b894bf96b | ||
|
|
96021274cc | ||
|
|
5f3fda95fc | ||
|
|
3afa783ba8 | ||
|
|
a997e528ec | ||
|
|
9177982592 | ||
|
|
d32bfa3ef4 | ||
|
|
78d82528fc | ||
|
|
216489ab2d | ||
|
|
d3d2820b4e | ||
|
|
f75c660a45 | ||
|
|
cb91d6f3c4 | ||
|
|
6744147bf9 | ||
|
|
fcb84423ea | ||
|
|
fa92c12b5a | ||
|
|
d3a857d9d3 | ||
|
|
c843e13c58 | ||
|
|
131ecd5e3b | ||
|
|
7a95ea407b | ||
|
|
efeedcad30 | ||
|
|
5be3496c8f | ||
|
|
d465bf10fd | ||
|
|
2265d1641e | ||
|
|
6f9b5b7c64 | ||
|
|
7d92ff65a2 | ||
|
|
1260a09c05 | ||
|
|
95f328d2af | ||
|
|
0c87bd9aad | ||
|
|
99f09127ea | ||
|
|
87987e1c2f | ||
|
|
9d98a494cb | ||
|
|
4d74371e8e | ||
|
|
20e41f21d9 | ||
|
|
5940578e3a | ||
|
|
94b52f8d9f | ||
|
|
8674ebb137 | ||
|
|
71e64cd1dc | ||
|
|
d0ea5e9e1c | ||
|
|
d9ed2e6de9 | ||
|
|
8a4372762e | ||
|
|
82e67f27f7 | ||
|
|
8124bea16f | ||
|
|
62165a2a0d | ||
|
|
31f6558710 | ||
|
|
afd9ddf46d | ||
|
|
d62825c99b | ||
|
|
a7e7e62245 | ||
|
|
c11fd4f0ab | ||
|
|
a29dac2c60 | ||
|
|
8846a42bf4 | ||
|
|
72805e5da9 | ||
|
|
8bbcf542b6 | ||
|
|
f01109bd18 | ||
|
|
6f659a3431 | ||
|
|
2e8c0346d3 | ||
|
|
fbd46609ff | ||
|
|
70620b96bc | ||
|
|
daebfdd54b | ||
|
|
6b5cbfb64e | ||
|
|
8fa9147dc1 | ||
|
|
30542f6b27 | ||
|
|
c2c0b6a1b0 | ||
|
|
c2ffe58070 | ||
|
|
daa039cb85 | ||
|
|
6028a3e419 | ||
|
|
082592fc22 | ||
|
|
5baa157d42 | ||
|
|
adafcabbb8 | ||
|
|
9312fdb573 | ||
|
|
ba33cf98e3 | ||
|
|
649bd2a170 | ||
|
|
8f8e86a4eb | ||
|
|
532672b5d1 | ||
|
|
34c61f812a | ||
|
|
b782f2f9b2 | ||
|
|
58d2b1d3f4 | ||
|
|
7d1f5c91a7 | ||
|
|
f53abf9a45 | ||
|
|
407a651e44 | ||
|
|
992541ed99 | ||
|
|
3a9228d8d3 | ||
|
|
aa9632a41b | ||
|
|
ba994c91fc | ||
|
|
5d3a829f65 | ||
|
|
d4d1b8f513 | ||
|
|
67141eaeac | ||
|
|
43671629f0 | ||
|
|
66f7406148 | ||
|
|
dc0006bd76 | ||
|
|
0ab2f03064 | ||
|
|
89205a66ad | ||
|
|
50af948c9f | ||
|
|
5da5f5ac42 | ||
|
|
0e062f51e9 | ||
|
|
e0a655e102 | ||
|
|
a5a771b242 | ||
|
|
11f330cff6 | ||
|
|
e0b744183a | ||
|
|
f6db3d5700 | ||
|
|
94601efed2 | ||
|
|
573a6d82fe | ||
|
|
318d8ce3c9 | ||
|
|
85d3cc92c4 | ||
|
|
7aa0694eac | ||
|
|
20af4921f8 | ||
|
|
8204dbb6ae | ||
|
|
e759124bd8 | ||
|
|
41fc8de9c5 | ||
|
|
b54a63a5f7 | ||
|
|
a27eb8c63b | ||
|
|
572fce041b | ||
|
|
456f7f7c7d | ||
|
|
5d6194e679 | ||
|
|
1d0da38d40 | ||
|
|
b63f720e5d | ||
|
|
64d5f52eae | ||
|
|
c1af4de1d4 | ||
|
|
7f72088736 | ||
|
|
38956503e1 | ||
|
|
47ff93cb5d | ||
|
|
212e34feac | ||
|
|
f5ff1ce80b | ||
|
|
db4eefb759 | ||
|
|
58018687dd | ||
|
|
ec1fb06106 | ||
|
|
b6b6d11abc | ||
|
|
094a86cbbf | ||
|
|
fdf01b770a | ||
|
|
262a815457 | ||
|
|
699944711b | ||
|
|
c7425558e7 | ||
|
|
4124e44a8d | ||
|
|
41e8ce1c74 | ||
|
|
238036ef48 | ||
|
|
da0ca3d440 | ||
|
|
0fd3cb01cf | ||
|
|
ab7cf49de0 | ||
|
|
cf5dffcd80 | ||
|
|
9af4846372 | ||
|
|
2834c2f86c | ||
|
|
7bf1ef355f | ||
|
|
34c12b61cc | ||
|
|
fc0bac6726 | ||
|
|
4534944b08 | ||
|
|
1d6ad94694 | ||
|
|
367197357c | ||
|
|
ae416f2769 | ||
|
|
a19df34b79 | ||
|
|
7127c70ed6 | ||
|
|
80cc850112 | ||
|
|
dfbb362330 | ||
|
|
ab5e5a7f4a | ||
|
|
a123f764e6 | ||
|
|
65ed5b3fce | ||
|
|
e8656e8504 | ||
|
|
86c614d56d | ||
|
|
093194f326 | ||
|
|
d3eaf6030d | ||
|
|
574d089c20 | ||
|
|
3a141def49 | ||
|
|
8dac0a56c9 | ||
|
|
8fade400b7 | ||
|
|
8334b68285 | ||
|
|
482bf2e523 | ||
|
|
10bdb57391 | ||
|
|
8717d6d75e | ||
|
|
c2339dcb5c | ||
|
|
de7ac4ba31 | ||
|
|
f1d05ae9b5 | ||
|
|
2f73256c94 | ||
|
|
a353b1fdc1 | ||
|
|
7d3992eeaf | ||
|
|
7b8e551662 | ||
|
|
075470dabb | ||
|
|
f567f581c3 | ||
|
|
b3e3a27555 | ||
|
|
28dcfcffd0 | ||
|
|
c214d09e84 | ||
|
|
46680d3854 | ||
|
|
9a0ea60cd7 | ||
|
|
3d14aedcd8 | ||
|
|
a28c9c896d | ||
|
|
912f6bb376 | ||
|
|
e23b60c203 | ||
|
|
547038aae8 | ||
|
|
8137bc0ca9 | ||
|
|
7a67218ad1 | ||
|
|
8471bdeffe | ||
|
|
82a5ab5aef | ||
|
|
3959ed505b | ||
|
|
5320f3f5fd | ||
|
|
72b2feb697 | ||
|
|
ac91bc8898 | ||
|
|
ca2c66733c | ||
|
|
8ce2e43780 | ||
|
|
118d6ff837 | ||
|
|
5869591167 | ||
|
|
de5efe19b2 | ||
|
|
33d8bf07b1 | ||
|
|
818690dba8 | ||
|
|
e35076f682 | ||
|
|
de8761ea61 | ||
|
|
0ad65691d3 | ||
|
|
cd170be44e | ||
|
|
ecc9733623 | ||
|
|
bab2febb24 | ||
|
|
610ff6494a | ||
|
|
be4012ea5d | ||
|
|
7fec31e775 | ||
|
|
52a939578c | ||
|
|
8fce088e6f | ||
|
|
5452286d8d | ||
|
|
50fc7f753e | ||
|
|
8c2d54e6d3 | ||
|
|
a8ede8b857 | ||
|
|
8dd8f98b61 | ||
|
|
fac6d1741e | ||
|
|
6b6db02567 | ||
|
|
2a1b58e2c1 | ||
|
|
19d61300bb | ||
|
|
599c838fd9 | ||
|
|
b97e2839c5 | ||
|
|
190ac1a65a | ||
|
|
6bc2d241fd | ||
|
|
a15903b5ef | ||
|
|
91fc2d2e2b | ||
|
|
2432ff77a3 | ||
|
|
0da945ee29 | ||
|
|
d2f6ac5015 | ||
|
|
0d7302d530 | ||
|
|
f02c8e94d7 | ||
|
|
1aeee8b671 | ||
|
|
4bcf03c6a1 | ||
|
|
7c8349f4f5 | ||
|
|
d229e08f02 | ||
|
|
168d3c5b75 | ||
|
|
0d020bb706 | ||
|
|
5e5277f38e | ||
|
|
11fb507df3 | ||
|
|
b5adb2e82b | ||
|
|
d68e208325 | ||
|
|
3afc4e8185 | ||
|
|
85935eb5fd | ||
|
|
fcbb691c0a | ||
|
|
20c6b72a0c | ||
|
|
9abd8eb223 | ||
|
|
eacdfa4088 | ||
|
|
a15cc8718e | ||
|
|
21321c0599 | ||
|
|
386c90c601 | ||
|
|
fccc57458c | ||
|
|
8b47536835 | ||
|
|
5d0c61178b | ||
|
|
3bcae734e5 | ||
|
|
8dd96ea636 | ||
|
|
04d7980789 | ||
|
|
370c08cd68 | ||
|
|
e143fa5e33 | ||
|
|
614ba55819 | ||
|
|
f1613c62a4 | ||
|
|
ca7a9bdbe2 | ||
|
|
1caa9a3e15 | ||
|
|
c3140c2db3 | ||
|
|
ebada5e866 | ||
|
|
0902f2c32b | ||
|
|
dfa85df39c | ||
|
|
d175bca3cc | ||
|
|
1aa61fe29b | ||
|
|
c1eee655dd | ||
|
|
6b8acc4b2f | ||
|
|
4ab6ace9fd | ||
|
|
ed04836a8d | ||
|
|
3e92e6675d | ||
|
|
2710f945d8 | ||
|
|
bdc8fe9db3 | ||
|
|
33d72890fa | ||
|
|
59b5092e3b | ||
|
|
9daaf4a9f7 | ||
|
|
40d002d9e8 | ||
|
|
3380b8896a | ||
|
|
c1564fdcc6 | ||
|
|
d7bab12542 | ||
|
|
21a6be1bda | ||
|
|
e49b0db58d | ||
|
|
4932a2cfbd | ||
|
|
e376f13263 | ||
|
|
fe5d5f3869 | ||
|
|
710e6e49a8 | ||
|
|
ba1cc00d03 | ||
|
|
bd7837b14c | ||
|
|
3ef307fada | ||
|
|
979e73e376 | ||
|
|
fe70db9af6 | ||
|
|
842e8f9e01 | ||
|
|
3501d39877 | ||
|
|
233efa43c7 | ||
|
|
725e635016 | ||
|
|
a948c3c54e | ||
|
|
a763ecbfc5 | ||
|
|
fab1c0bcf8 | ||
|
|
377120aead | ||
|
|
577ae34b50 | ||
|
|
fa7d316dbf | ||
|
|
52cd4f7c5e | ||
|
|
570b012000 | ||
|
|
9f06e82171 | ||
|
|
995619af9b | ||
|
|
c842162fe2 | ||
|
|
0f3df3a436 | ||
|
|
c5021721c6 | ||
|
|
1a3e8c59c7 | ||
|
|
210051c12d | ||
|
|
998c3208f6 | ||
|
|
9c8b2328db | ||
|
|
b300b76783 | ||
|
|
ef871fba7f | ||
|
|
1f90ccdb1f | ||
|
|
83f99642e0 | ||
|
|
5f217d75bb | ||
|
|
ae6a264d6d | ||
|
|
a4d8fb0b4c | ||
|
|
fe0f57c00d | ||
|
|
57bd868580 | ||
|
|
e1b50c1dcd | ||
|
|
256c01dff4 | ||
|
|
085855cdc5 | ||
|
|
bbbc5e966b | ||
|
|
18d4685007 | ||
|
|
7f1b1ca662 | ||
|
|
b54918bb5e | ||
|
|
56b27897cf | ||
|
|
1beae731bf | ||
|
|
30b691243b | ||
|
|
4cb9cc7d68 | ||
|
|
fc98bc781b | ||
|
|
a1b6f09115 | ||
|
|
642bb8b131 | ||
|
|
1eae57a401 | ||
|
|
5a18bfbd6f | ||
|
|
bedc997c3f | ||
|
|
fd991c951e | ||
|
|
a06bf6ea7c | ||
|
|
45beda3f26 | ||
|
|
7b4b9fb68c | ||
|
|
71db321570 | ||
|
|
29bf4561e5 | ||
|
|
377eb36509 | ||
|
|
2afbae9c89 | ||
|
|
1e64e0c741 | ||
|
|
3bc130c802 | ||
|
|
99295634a6 | ||
|
|
1d7bc7c8f7 | ||
|
|
4e22906180 | ||
|
|
9bdccb0fb3 | ||
|
|
cf956099ac | ||
|
|
101a100c1f | ||
|
|
824fc19323 | ||
|
|
6c20f74b90 | ||
|
|
b4ce1b7ae6 | ||
|
|
e397cee40d | ||
|
|
e3b7914759 | ||
|
|
8efc688ff8 | ||
|
|
622b486d1f | ||
|
|
226c301d92 | ||
|
|
61a7822db3 | ||
|
|
9b15750b02 | ||
|
|
64754f982c | ||
|
|
675dcda86d | ||
|
|
5748ea3a74 | ||
|
|
5ccd229092 | ||
|
|
88e502ad7a | ||
|
|
72f6305320 | ||
|
|
45981c1941 | ||
|
|
4d660cc3c8 | ||
|
|
f231fa47a0 | ||
|
|
40ceccda46 | ||
|
|
866d6e829b | ||
|
|
6d7d6e9531 | ||
|
|
ad0fdfe921 | ||
|
|
bb8d4a92cb | ||
|
|
1429792690 | ||
|
|
1f26b59d90 | ||
|
|
c2c69d9f43 | ||
|
|
133e5003cd | ||
|
|
f97eb794ba | ||
|
|
7a8a3cbce8 | ||
|
|
2fb8f21b58 | ||
|
|
7b093a6bba | ||
|
|
c631f28e53 | ||
|
|
66909ce19a | ||
|
|
eca3782bda | ||
|
|
a5c2e20a02 | ||
|
|
05fff3b8aa | ||
|
|
175aebaa14 | ||
|
|
cf4e023695 | ||
|
|
1d58e7d6f8 | ||
|
|
282842fa2c | ||
|
|
748a22c728 | ||
|
|
bd47ca34df | ||
|
|
e27b6b2dde | ||
|
|
9a7074bcba | ||
|
|
bedd6b5fcc | ||
|
|
0638f79c2b | ||
|
|
abcf73f233 | ||
|
|
52113233b8 | ||
|
|
9cbaced1f3 | ||
|
|
77d4613bd8 | ||
|
|
225c176f71 | ||
|
|
a850d3b67c | ||
|
|
74a434ab04 | ||
|
|
f8e0a28134 | ||
|
|
d7d156303f | ||
|
|
c30b1dd379 | ||
|
|
2daa1d93e9 | ||
|
|
556388f2f4 | ||
|
|
752508b724 | ||
|
|
cf72c2ef8f | ||
|
|
3b40728701 | ||
|
|
e3015a284b | ||
|
|
1cdedec33d | ||
|
|
d4607ee815 | ||
|
|
291e1d0c30 | ||
|
|
c2dc2c6100 | ||
|
|
65dbaf427c | ||
|
|
0e146bf341 | ||
|
|
fbb4455250 | ||
|
|
b2050a8895 | ||
|
|
d601e9608c | ||
|
|
5c0e92d51a | ||
|
|
c679318d16 | ||
|
|
cd4b3fdaab | ||
|
|
0030d5c2b8 | ||
|
|
95a0efedcf | ||
|
|
7a8a78d348 | ||
|
|
cebbc215d7 | ||
|
|
1060c0ca94 | ||
|
|
fb321fa034 | ||
|
|
925e45782c | ||
|
|
6a5c47887a | ||
|
|
13a1d32f56 | ||
|
|
267f3ec7ca | ||
|
|
9907e4af58 | ||
|
|
a505902ed5 | ||
|
|
25c840e036 | ||
|
|
35155e4b7a | ||
|
|
da4cf8b661 | ||
|
|
77710f1613 | ||
|
|
a7fde78105 | ||
|
|
39f30a059b | ||
|
|
a6f4b30004 | ||
|
|
2763b99142 | ||
|
|
4ce3631e4b | ||
|
|
7ed906f1c3 | ||
|
|
1a43d5afd7 | ||
|
|
db0c796218 | ||
|
|
1c7f72d1f8 | ||
|
|
5770000e65 | ||
|
|
ad7b78b871 | ||
|
|
4d78f4b535 | ||
|
|
30cddeae2d | ||
|
|
db13c105ad | ||
|
|
c8911f1fa9 | ||
|
|
8295920c3c | ||
|
|
2276539f24 | ||
|
|
9b7cd20d47 | ||
|
|
a284087460 | ||
|
|
c5a6f441aa | ||
|
|
9dc0a052bf | ||
|
|
61b5a3924e | ||
|
|
99cb5ffb37 | ||
|
|
e0ae2706de | ||
|
|
8dfdc4761e | ||
|
|
9723a346b6 | ||
|
|
1667a0a6df | ||
|
|
cdfdfc75ab | ||
|
|
e1d644c33b | ||
|
|
c601082a5e | ||
|
|
a33b1303d2 | ||
|
|
5836be7131 | ||
|
|
6f40bb4c35 | ||
|
|
56a1a82ec8 | ||
|
|
22ffb4ecee | ||
|
|
ad93d6dd41 | ||
|
|
affb869116 | ||
|
|
fa39846cc8 | ||
|
|
3d4e63416f | ||
|
|
9586bd7dea | ||
|
|
0f3eb53554 | ||
|
|
c757b5051e | ||
|
|
fbe173444e | ||
|
|
770d96cdec | ||
|
|
b0a1371122 | ||
|
|
defa1e40e1 | ||
|
|
c3cb4fbe75 | ||
|
|
88f45a69b1 | ||
|
|
1a44406d70 | ||
|
|
837d1824b1 | ||
|
|
2bf23f0618 | ||
|
|
26bbdc1a57 | ||
|
|
933bddebe3 | ||
|
|
9c0966ff42 | ||
|
|
0b60079c07 | ||
|
|
083f50a5d4 | ||
|
|
c8ede0e8da | ||
|
|
2b69ca2f04 | ||
|
|
9bbec47976 | ||
|
|
5bde218076 | ||
|
|
a4a88cd63a | ||
|
|
da77439e1e | ||
|
|
241bd1cdeb | ||
|
|
f61ec3179a | ||
|
|
147e240035 | ||
|
|
cc747ebef7 | ||
|
|
5e86183d40 | ||
|
|
f04a5dbfef | ||
|
|
1c0177f711 | ||
|
|
a1893a115f | ||
|
|
4a227c7ed2 | ||
|
|
5e21ec03cd | ||
|
|
ea502e9c81 | ||
|
|
e5d8c885bc | ||
|
|
7327025aac | ||
|
|
952280ecc6 | ||
|
|
4d8930832e | ||
|
|
c59301ebc6 | ||
|
|
cb338e1ce5 | ||
|
|
146089e021 | ||
|
|
6634f3981e | ||
|
|
38c6f8c76f | ||
|
|
00008528a6 | ||
|
|
cc4727ad95 | ||
|
|
e650297ded | ||
|
|
71c5f47cd8 | ||
|
|
74246a8278 | ||
|
|
c450c9426c | ||
|
|
46f9fe743c | ||
|
|
be38bca83d | ||
|
|
c31df5fff3 | ||
|
|
8a13cdbcff | ||
|
|
27ee6fec70 | ||
|
|
4e0c21a2ac | ||
|
|
6e0af1a3b7 | ||
|
|
e9e18513be | ||
|
|
1e18a5ce07 | ||
|
|
10d5ca50fc | ||
|
|
4770123be5 | ||
|
|
a6daa577e8 | ||
|
|
b7c7b05243 | ||
|
|
acf721befa | ||
|
|
f297cdb8b2 | ||
|
|
b39b09c33c | ||
|
|
bdec220d7e | ||
|
|
666d0d418f | ||
|
|
9d2fc883b8 | ||
|
|
ea04a6e1c9 | ||
|
|
913ea0cef2 | ||
|
|
82ba7f25b0 | ||
|
|
bb877a244b | ||
|
|
5e56a08768 | ||
|
|
a12959d60e | ||
|
|
83434b5506 | ||
|
|
dcd4abe72b | ||
|
|
571520815a | ||
|
|
e9cff0920b | ||
|
|
905ee19519 | ||
|
|
6879cd762c | ||
|
|
8f0e665c68 | ||
|
|
0b95220d1b | ||
|
|
aa326a1276 | ||
|
|
e0127d330a | ||
|
|
32469b3421 | ||
|
|
4cafd41944 | ||
|
|
4f7760ed86 | ||
|
|
e1b2a767f5 | ||
|
|
c039d0f81d | ||
|
|
4870893fc2 | ||
|
|
e2940150c3 | ||
|
|
3058b2eb00 | ||
|
|
dbe747ea23 | ||
|
|
4c23f1f32b | ||
|
|
c1c8fad97e | ||
|
|
bcdb6bdac8 | ||
|
|
36991a3d5b | ||
|
|
003d9107a4 | ||
|
|
e8f26bdf18 | ||
|
|
a53485d08f | ||
|
|
7e46054f8b | ||
|
|
789ee8e2d1 | ||
|
|
eea8ceda63 | ||
|
|
44587663bb | ||
|
|
c36d650d61 | ||
|
|
f716e42672 | ||
|
|
3b288ce5d6 | ||
|
|
e485853b08 | ||
|
|
38bc2d9d58 | ||
|
|
244de6915d | ||
|
|
874f2f63a8 | ||
|
|
71a65606a1 | ||
|
|
a8c834b1e9 | ||
|
|
c8dd19c22f | ||
|
|
9ad204244a | ||
|
|
c8e8778d7b | ||
|
|
a5052ef42b | ||
|
|
68f7880d42 | ||
|
|
f4241142c5 | ||
|
|
1cc48c8d8e | ||
|
|
ebb80a9b05 | ||
|
|
8d8f6f7ed5 | ||
|
|
e6c0333915 | ||
|
|
3be360dfb9 | ||
|
|
d08adc43c1 | ||
|
|
3361c9de29 | ||
|
|
0eff37844b | ||
|
|
5f3d5a593c | ||
|
|
e74ee179af | ||
|
|
d8006b160c | ||
|
|
f328e58c02 | ||
|
|
656fa3208a | ||
|
|
f647ce61c2 | ||
|
|
19270a9dde | ||
|
|
91fd69e0bd | ||
|
|
3b220b6050 | ||
|
|
4ceccb3c41 | ||
|
|
47fdc47d33 | ||
|
|
ed4cf4ff05 | ||
|
|
d332787deb | ||
|
|
55a6f85252 | ||
|
|
aacf3700f4 | ||
|
|
9ed2127530 | ||
|
|
eac9d7adfb | ||
|
|
3c60e4f765 | ||
|
|
e11252a2d6 | ||
|
|
99564d75b7 | ||
|
|
26e54b8796 | ||
|
|
eaa507bc70 | ||
|
|
91752b4068 | ||
|
|
82b7854d46 | ||
|
|
08ea82cf05 | ||
|
|
6e99701c47 | ||
|
|
aa0fb2b8f7 | ||
|
|
6710ffa334 | ||
|
|
0664a42f99 | ||
|
|
73f6c697b9 | ||
|
|
15c5a22d11 | ||
|
|
40c112d47a | ||
|
|
4a2cbc9be3 | ||
|
|
a91b6dbca3 | ||
|
|
5c85af10c5 | ||
|
|
8026965915 | ||
|
|
5f00362805 | ||
|
|
648a3cc430 | ||
|
|
977d1d0246 | ||
|
|
222fab27d1 | ||
|
|
a48d850721 | ||
|
|
599c4ebad8 | ||
|
|
4f9d133670 | ||
|
|
9a4f956153 | ||
|
|
927fd980f6 | ||
|
|
446512793b | ||
|
|
7f55fd4bf6 | ||
|
|
0c7925cdfb | ||
|
|
96faad7539 | ||
|
|
69189ab41a | ||
|
|
6b76e5a853 | ||
|
|
dbb6e43751 | ||
|
|
f07f0ba1c7 | ||
|
|
2ddeebdc78 | ||
|
|
d312bf74b9 | ||
|
|
f83f606d92 | ||
|
|
857ae5fd95 | ||
|
|
265b5dd969 | ||
|
|
d7c7ef8332 | ||
|
|
54f8ef924f | ||
|
|
2e2b7f96f2 | ||
|
|
a5894c1a4c | ||
|
|
e06996a2e4 | ||
|
|
34d9eb2d96 | ||
|
|
f5d89de177 | ||
|
|
53c4c14522 | ||
|
|
ff44fcdfe0 | ||
|
|
2f0e7c6d29 | ||
|
|
7115a6ae7d | ||
|
|
2eae1e81d1 | ||
|
|
ecd282faf1 | ||
|
|
765560d1f5 | ||
|
|
bc024d9ed0 | ||
|
|
f1d047becf | ||
|
|
50af5d9af1 | ||
|
|
494789c02e | ||
|
|
63929566d9 | ||
|
|
ed3df37176 | ||
|
|
c736615de1 | ||
|
|
5121ed7c39 | ||
|
|
4f4ea5c6fa | ||
|
|
29a1539379 | ||
|
|
2a15fbae4d | ||
|
|
7b5b1c58d3 | ||
|
|
82bf2dab2c | ||
|
|
694899980c | ||
|
|
749ab51651 | ||
|
|
fa973c5467 | ||
|
|
2f68be14f8 | ||
|
|
37a4a3eb47 | ||
|
|
664dd12241 | ||
|
|
03190b95cf | ||
|
|
da632c3f0f | ||
|
|
43290c0ff5 | ||
|
|
590b094ad5 | ||
|
|
b3e3fe2dc2 | ||
|
|
d863881591 | ||
|
|
3e5d0f53d2 | ||
|
|
29df7fda7e | ||
|
|
9ebf0ce1e5 | ||
|
|
2bb1583995 | ||
|
|
b98ffc4b8b | ||
|
|
818b3632ac | ||
|
|
7d1a2668a1 | ||
|
|
7677bd7cfe | ||
|
|
c98881671b | ||
|
|
ef1b7ca82c | ||
|
|
d39d634aba | ||
|
|
c65a760de7 | ||
|
|
8fba402016 | ||
|
|
0922baee7b | ||
|
|
2a68f13ade | ||
|
|
2ba01bb408 | ||
|
|
8c19bc66e4 | ||
|
|
87ee0b8893 | ||
|
|
92c8af1b19 | ||
|
|
b85b4d0067 | ||
|
|
5762ac38a7 | ||
|
|
dc804a90d4 | ||
|
|
968720f774 | ||
|
|
7b5244b52d | ||
|
|
30d4835fbb | ||
|
|
dd921e49b6 | ||
|
|
33a8372409 | ||
|
|
5125a86f8b | ||
|
|
54e9bd5c8e | ||
|
|
066a6d8b36 | ||
|
|
b241f03e76 | ||
|
|
306452679e | ||
|
|
880b88a4ef | ||
|
|
16dc6b36ba | ||
|
|
7e67661d5f | ||
|
|
397cd9b946 | ||
|
|
3d29a1e894 | ||
|
|
2d93879e7a | ||
|
|
4217fa8736 | ||
|
|
ff69f9af89 | ||
|
|
1b2087e52e | ||
|
|
3b31a36473 | ||
|
|
43fdcab528 | ||
|
|
49c2d0c10e | ||
|
|
9db246eb42 | ||
|
|
f1cad5993b | ||
|
|
76fc4e3ee2 | ||
|
|
86dbd8d7a6 | ||
|
|
36457da4f2 | ||
|
|
e646dc8a69 | ||
|
|
1bb6d62c17 | ||
|
|
2ed785fb06 | ||
|
|
01006e55c0 | ||
|
|
46b4990252 | ||
|
|
b3f1b0e610 | ||
|
|
14d8646734 | ||
|
|
5dcddf2317 | ||
|
|
b8aeef1d71 | ||
|
|
fa0ea7ed77 | ||
|
|
63c1a1d2d3 | ||
|
|
154156f4a1 | ||
|
|
8f1d9fba57 | ||
|
|
26d25706f2 | ||
|
|
574bd53c37 | ||
|
|
1514cd83ab | ||
|
|
7c8019319a | ||
|
|
882fd761a6 | ||
|
|
3df48f69c6 | ||
|
|
f723862def | ||
|
|
26f800d488 | ||
|
|
1fb15a421a | ||
|
|
4816d1e943 | ||
|
|
e440667d69 | ||
|
|
cebc51e045 | ||
|
|
16ca856996 | ||
|
|
cb955ee84f | ||
|
|
de45557635 | ||
|
|
6ac1cc4831 | ||
|
|
959cecf891 | ||
|
|
d54e156ec2 | ||
|
|
54c5c8c016 | ||
|
|
9b67f7beba | ||
|
|
b4caa97e69 | ||
|
|
de7cd679ba | ||
|
|
392cdf6058 | ||
|
|
8ddbadacec | ||
|
|
6dd1807fca | ||
|
|
01c4dff035 | ||
|
|
cb6a8fccb9 | ||
|
|
c15a60170d | ||
|
|
82f4f47cf3 | ||
|
|
aa2651ca71 | ||
|
|
cb28ca7941 | ||
|
|
527154f0be | ||
|
|
f4b9b0b313 | ||
|
|
daba1d3bba | ||
|
|
d57e368b03 | ||
|
|
9f962eb40f | ||
|
|
79d0b9543a | ||
|
|
7d9f73f650 | ||
|
|
ace0657b7d | ||
|
|
4afb374f6a | ||
|
|
648cfd9af4 | ||
|
|
5fe8ca178e | ||
|
|
63eb0f1530 | ||
|
|
21740123f4 | ||
|
|
2aae6cd744 | ||
|
|
d8316a090a | ||
|
|
e51fd028fa | ||
|
|
bffb7b5eab | ||
|
|
77808ecd41 | ||
|
|
2b798baffc | ||
|
|
07347663d6 | ||
|
|
9ab1a0d437 | ||
|
|
04b4749510 | ||
|
|
ad6646afaf | ||
|
|
7e3d414e9e | ||
|
|
c117f8a5ab | ||
|
|
b8d6918f71 | ||
|
|
2f10f24317 | ||
|
|
ec8a1af2a5 | ||
|
|
cd39d6a817 | ||
|
|
ad08376f6e | ||
|
|
71d3713950 | ||
|
|
137b4e55c4 | ||
|
|
b51d7409c1 | ||
|
|
442e9598f8 | ||
|
|
a41229b223 | ||
|
|
f1b972dde8 | ||
|
|
9a5e86caea | ||
|
|
8df2f96dfe | ||
|
|
0f72a35f48 | ||
|
|
a4d52aa255 | ||
|
|
09e531f11c | ||
|
|
958566da61 | ||
|
|
ace6215d20 | ||
|
|
97792ab0b1 | ||
|
|
574b6609ba | ||
|
|
0a4db9bd50 | ||
|
|
9fccb6dd3f | ||
|
|
9221899525 | ||
|
|
6a33fbc7b3 | ||
|
|
790a675d90 | ||
|
|
09da54ee56 | ||
|
|
028a3ccec8 | ||
|
|
503817e572 | ||
|
|
e0fe657f27 | ||
|
|
3a83d2ad89 | ||
|
|
ccb6bb943c | ||
|
|
f0307afe2b | ||
|
|
05b75cf98a | ||
|
|
24a6d6b6fd | ||
|
|
cdaf431d24 | ||
|
|
cf1f49ebc9 | ||
|
|
06ecfb5814 | ||
|
|
354fc1949b | ||
|
|
fc2b220197 | ||
|
|
acea2110ac | ||
|
|
176111794e | ||
|
|
3e051e38c3 | ||
|
|
d4aeb4b157 | ||
|
|
fca123e127 | ||
|
|
dc2f8fe9bb | ||
|
|
f10d3893f4 | ||
|
|
05cf1bc83a | ||
|
|
3791306be7 | ||
|
|
1353917994 | ||
|
|
5ef75772f0 | ||
|
|
82e98ced85 | ||
|
|
2dea5447b4 | ||
|
|
9aa379981e | ||
|
|
050c00c791 | ||
|
|
551689d445 | ||
|
|
dd4d40ce81 | ||
|
|
d77f374918 | ||
|
|
640b6a7288 | ||
|
|
5128833a62 | ||
|
|
f1ad55c86c | ||
|
|
e20f6d7564 | ||
|
|
ec26a8d343 | ||
|
|
542be44740 | ||
|
|
cdbb783ebc | ||
|
|
e602a93829 | ||
|
|
b7bcd4fe7b | ||
|
|
f01bec4003 | ||
|
|
9be3ff3cca | ||
|
|
2c0d001721 | ||
|
|
d3efd3ea0e | ||
|
|
e18df16387 | ||
|
|
4ddfbf6559 | ||
|
|
1d02ada8dc | ||
|
|
608c868b53 | ||
|
|
65639517ff | ||
|
|
1f64e4eda4 | ||
|
|
7a446941e0 | ||
|
|
0a87ccaa77 | ||
|
|
06a829ce35 | ||
|
|
fc3f096823 | ||
|
|
874bf38316 | ||
|
|
27eb3a8509 | ||
|
|
c14476ec73 | ||
|
|
c3b8abee47 | ||
|
|
ece8803259 | ||
|
|
4541aa4446 | ||
|
|
679b25f3fb | ||
|
|
337aebfed9 | ||
|
|
5e22c442ce | ||
|
|
4ebe3d2b2f | ||
|
|
4123c6213d | ||
|
|
4089e853f8 | ||
|
|
c1fc502916 | ||
|
|
a1030e3f81 | ||
|
|
ffc0bd0a9c | ||
|
|
8dddf90838 | ||
|
|
2608c071d0 | ||
|
|
1f4d1d1959 | ||
|
|
3876fb9d62 | ||
|
|
c8dbf88c03 | ||
|
|
f8b8dd0bc6 | ||
|
|
efe61c7b14 | ||
|
|
d664c26fb7 | ||
|
|
47cebb8671 | ||
|
|
f525e161a8 | ||
|
|
a00c573866 | ||
|
|
745ffc7cd2 | ||
|
|
dbece17235 | ||
|
|
ceb48c2ead | ||
|
|
9580a20f3f | ||
|
|
85e9073228 | ||
|
|
2b0691daa6 | ||
|
|
c1e25b121e | ||
|
|
31f3bf9368 | ||
|
|
42354ba794 | ||
|
|
1b115624a2 | ||
|
|
d2bc651fc6 | ||
|
|
a20fd2278f | ||
|
|
cb4fb15b0a | ||
|
|
102123441d | ||
|
|
4bb59548d0 | ||
|
|
3d27e59269 | ||
|
|
ebe30a88a1 | ||
|
|
a5d26b93e9 | ||
|
|
afca91089a | ||
|
|
893787d7f9 | ||
|
|
a9bab22720 | ||
|
|
13018c9df7 | ||
|
|
c451293370 | ||
|
|
64fca3306f | ||
|
|
3cce93be95 | ||
|
|
916f9b367e | ||
|
|
c6816318a9 | ||
|
|
9df80b9f79 | ||
|
|
59e9cdbfe6 | ||
|
|
7f0e8abc09 | ||
|
|
c106caf924 | ||
|
|
c06e176d57 | ||
|
|
62bb0b9b78 | ||
|
|
70beeb726a | ||
|
|
c173f0b5d6 | ||
|
|
43a2b5cda6 | ||
|
|
17cecde604 | ||
|
|
728c09d97d | ||
|
|
eb89c52bae | ||
|
|
e3895f284b | ||
|
|
50342b6dfe | ||
|
|
8265b9b034 | ||
|
|
96e7f57a34 | ||
|
|
abf6d5422e | ||
|
|
2bef89137e | ||
|
|
a0ac1c70a9 | ||
|
|
1ccabe645b | ||
|
|
b03c5232b0 | ||
|
|
97c77b612e | ||
|
|
e96400c43b | ||
|
|
c22f019ea1 | ||
|
|
bc3c46b566 | ||
|
|
a8431c5810 | ||
|
|
68332896ad | ||
|
|
dbda9512e5 | ||
|
|
c4756e8cec | ||
|
|
b8a42843e0 | ||
|
|
10c3f9f633 | ||
|
|
05e802b74a | ||
|
|
0c8d78d753 | ||
|
|
5ccb12453a | ||
|
|
37351d6b3e | ||
|
|
57a085eec1 | ||
|
|
0808a76226 | ||
|
|
0019595923 | ||
|
|
4d61c14f80 | ||
|
|
cf1b613923 | ||
|
|
815b2e1670 | ||
|
|
c46b046254 | ||
|
|
70efa37109 | ||
|
|
13d2699011 | ||
|
|
1304e2eb2d | ||
|
|
3cf16627c1 | ||
|
|
4aaa237bf9 | ||
|
|
cece15d10c | ||
|
|
cc6e9492fd | ||
|
|
7f97df02ce | ||
|
|
f28fc15a8d | ||
|
|
59f9cd3694 | ||
|
|
aa15e009cb | ||
|
|
b9ca2ac13d | ||
|
|
80e1e0e61a | ||
|
|
ecebe4ecd5 | ||
|
|
8bfcb14d0c | ||
|
|
1cf1473d6b | ||
|
|
aa43425df3 | ||
|
|
35d77ff642 | ||
|
|
2575fd6f4d | ||
|
|
15aa9e508c | ||
|
|
d1b12ee04b | ||
|
|
1252d760ab | ||
|
|
81b96b2430 | ||
|
|
5dd6477cfc | ||
|
|
5f30729127 | ||
|
|
abb192eb0f | ||
|
|
c701b518b8 | ||
|
|
14ac58b999 | ||
|
|
ae094f9bc6 | ||
|
|
e9d800794e | ||
|
|
7de427dc38 | ||
|
|
c117a23e0d | ||
|
|
77b72a6eb1 | ||
|
|
9f48de7774 | ||
|
|
539fa43503 | ||
|
|
5378361faa | ||
|
|
d2d5a90637 | ||
|
|
631a73e07d | ||
|
|
c944cd29b1 | ||
|
|
5d5a3183c0 | ||
|
|
eb537f45f4 | ||
|
|
cdb97baa80 | ||
|
|
398b5f446c | ||
|
|
4099a8ef5a | ||
|
|
fd5958b764 | ||
|
|
a2a4cd4e7a | ||
|
|
35215cf62f | ||
|
|
8dda0f02f2 | ||
|
|
efbd249e7f | ||
|
|
cf4e8c65d2 | ||
|
|
9a595e3178 | ||
|
|
14f8a5aa36 | ||
|
|
a759380999 | ||
|
|
05ed58d741 | ||
|
|
6b2eeeccf5 | ||
|
|
340b9134c0 | ||
|
|
ba01ac715f | ||
|
|
8f151b84c9 | ||
|
|
c5942a3ddd | ||
|
|
08449b7af5 | ||
|
|
a4ccd835bc | ||
|
|
97aa758123 |
@@ -77,24 +77,20 @@ Then, **for a method** of an eligible class:
|
|||||||
|
|
||||||
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
|
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```
|
```
|
||||||
cd .doc
|
cd .doc
|
||||||
composer require phpdocumentor/phpdocumentor:~2 --dev
|
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generation
|
## Generation
|
||||||
`./bin/build-doc-object-manipulation` and `./bin/build-doc-extensions` contains examples of doc. generation, beware: they have to be called from the .doc directory:
|
|
||||||
```shell
|
|
||||||
cd /path/to/itop/.doc
|
|
||||||
./bin/build-doc-object-manipulation
|
|
||||||
```
|
|
||||||
|
|
||||||
the resulting documentation is written into `data/phpdocumentor/output`
|
|
||||||
|
|
||||||
|
1. Switch to this directory : `cd /path/to/itop/.doc`
|
||||||
|
2. `composer install`
|
||||||
|
3. `./bin/build-doc-object-manipulation`
|
||||||
|
3. `./bin/build-doc-extensions`
|
||||||
|
4. Get the generated files from `/path/to/itop/data/phpdocumentor/output`
|
||||||
|
|
||||||
## Dokuwiki requirements
|
## Dokuwiki requirements
|
||||||
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
|
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh -x
|
#!/bin/sh -x
|
||||||
|
|
||||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && .doc/vendor/bin/phpdoc -c .doc/phpdoc-extensions.dist.xml -vvv
|
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf data/phpdocumentor/output/extensions/ && rm -rf data/phpdocumentor/temp/extensions/ && ./vendor/bin/phpdoc -c ./phpdoc-extensions.dist.xml -vvv
|
||||||
|
|
||||||
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||||
cd data/phpdocumentor/output/extensions/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
cd ../data/phpdocumentor/output/extensions/ && for i in $(ls | grep [A-Z]); do mv -i $i $(echo $i | tr 'A-Z' 'a-z'); done
|
||||||
|
|||||||
@@ -6,19 +6,20 @@ end_of_line = lf
|
|||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = false
|
insert_final_newline = false
|
||||||
max_line_length = 140
|
max_line_length = 300
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
ij_continuation_indent_size = 8
|
ij_continuation_indent_size = 8
|
||||||
ij_formatter_off_tag = @formatter:off
|
ij_formatter_off_tag = @formatter:off
|
||||||
ij_formatter_on_tag = @formatter:on
|
ij_formatter_on_tag = @formatter:on
|
||||||
ij_formatter_tags_enabled = false
|
ij_formatter_tags_enabled = false
|
||||||
ij_smart_tabs = false
|
ij_smart_tabs = false
|
||||||
ij_visual_guides = 80,120
|
ij_visual_guides = 300
|
||||||
ij_wrap_on_typing = true
|
ij_wrap_on_typing = true
|
||||||
|
|
||||||
[*.css]
|
[*.css]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
ij_smart_tabs = true
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
ij_css_align_closing_brace_with_properties = false
|
ij_css_align_closing_brace_with_properties = false
|
||||||
ij_css_blank_lines_around_nested_selector = 1
|
ij_css_blank_lines_around_nested_selector = 1
|
||||||
ij_css_blank_lines_between_blocks = 1
|
ij_css_blank_lines_between_blocks = 1
|
||||||
@@ -38,7 +39,9 @@ ij_css_use_double_quotes = true
|
|||||||
ij_css_value_alignment = do_not_align
|
ij_css_value_alignment = do_not_align
|
||||||
|
|
||||||
[*.scss]
|
[*.scss]
|
||||||
indent_style = tab
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_visual_guides = none
|
||||||
ij_scss_align_closing_brace_with_properties = false
|
ij_scss_align_closing_brace_with_properties = false
|
||||||
ij_scss_blank_lines_around_nested_selector = 1
|
ij_scss_blank_lines_around_nested_selector = 1
|
||||||
ij_scss_blank_lines_between_blocks = 1
|
ij_scss_blank_lines_between_blocks = 1
|
||||||
@@ -58,8 +61,8 @@ ij_scss_use_double_quotes = true
|
|||||||
ij_scss_value_alignment = 0
|
ij_scss_value_alignment = 0
|
||||||
|
|
||||||
[*.twig]
|
[*.twig]
|
||||||
indent_style = tab
|
|
||||||
ij_smart_tabs = true
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
ij_wrap_on_typing = false
|
ij_wrap_on_typing = false
|
||||||
ij_twig_keep_indents_on_empty_lines = false
|
ij_twig_keep_indents_on_empty_lines = false
|
||||||
ij_twig_spaces_inside_comments_delimiters = true
|
ij_twig_spaces_inside_comments_delimiters = true
|
||||||
@@ -67,6 +70,7 @@ ij_twig_spaces_inside_delimiters = true
|
|||||||
ij_twig_spaces_inside_variable_delimiters = true
|
ij_twig_spaces_inside_variable_delimiters = true
|
||||||
|
|
||||||
[.editorconfig]
|
[.editorconfig]
|
||||||
|
ij_visual_guides = none
|
||||||
ij_editorconfig_align_group_field_declarations = false
|
ij_editorconfig_align_group_field_declarations = false
|
||||||
ij_editorconfig_space_after_colon = false
|
ij_editorconfig_space_after_colon = false
|
||||||
ij_editorconfig_space_after_comma = true
|
ij_editorconfig_space_after_comma = true
|
||||||
@@ -74,17 +78,19 @@ ij_editorconfig_space_before_colon = false
|
|||||||
ij_editorconfig_space_before_comma = false
|
ij_editorconfig_space_before_comma = false
|
||||||
ij_editorconfig_spaces_around_assignment_operators = true
|
ij_editorconfig_spaces_around_assignment_operators = true
|
||||||
|
|
||||||
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul, phpunit.xml.dist}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
tab_width = 2
|
tab_width = 2
|
||||||
ij_smart_tabs = true
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_wrap_on_typing = false
|
||||||
ij_xml_align_attributes = true
|
ij_xml_align_attributes = true
|
||||||
ij_xml_align_text = false
|
ij_xml_align_text = false
|
||||||
ij_xml_attribute_wrap = normal
|
ij_xml_attribute_wrap = normal
|
||||||
ij_xml_block_comment_at_first_column = true
|
ij_xml_block_comment_at_first_column = true
|
||||||
ij_xml_keep_blank_lines = 2
|
ij_xml_keep_blank_lines = 2
|
||||||
ij_xml_keep_indents_on_empty_lines = false
|
ij_xml_keep_indents_on_empty_lines = false
|
||||||
ij_xml_keep_line_breaks = false
|
ij_xml_keep_line_breaks = true
|
||||||
ij_xml_keep_line_breaks_in_text = true
|
ij_xml_keep_line_breaks_in_text = true
|
||||||
ij_xml_keep_whitespaces = false
|
ij_xml_keep_whitespaces = false
|
||||||
ij_xml_keep_whitespaces_around_cdata = preserve
|
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||||
@@ -93,21 +99,24 @@ ij_xml_line_comment_at_first_column = true
|
|||||||
ij_xml_space_after_tag_name = false
|
ij_xml_space_after_tag_name = false
|
||||||
ij_xml_space_around_equals_in_attribute = false
|
ij_xml_space_around_equals_in_attribute = false
|
||||||
ij_xml_space_inside_empty_tag = false
|
ij_xml_space_inside_empty_tag = false
|
||||||
ij_xml_text_wrap = normal
|
ij_xml_text_wrap = off
|
||||||
|
|
||||||
[{*.bash,*.sh,*.zsh}]
|
[{*.bash,*.sh,*.zsh}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
tab_width = 2
|
tab_width = 2
|
||||||
|
ij_visual_guides = none
|
||||||
ij_shell_binary_ops_start_line = false
|
ij_shell_binary_ops_start_line = false
|
||||||
ij_shell_keep_column_alignment_padding = false
|
ij_shell_keep_column_alignment_padding = false
|
||||||
ij_shell_minify_program = false
|
ij_shell_minify_program = false
|
||||||
ij_shell_redirect_followed_by_space = false
|
ij_shell_redirect_followed_by_space = false
|
||||||
ij_shell_switch_cases_indented = false
|
ij_shell_switch_cases_indented = false
|
||||||
|
ij_shell_use_unix_line_separator = true
|
||||||
|
|
||||||
[{*.cjs,*.js}]
|
[{*.cjs,*.js}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
ij_continuation_indent_size = 4
|
ij_continuation_indent_size = 4
|
||||||
ij_smart_tabs = true
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
ij_javascript_align_imports = false
|
ij_javascript_align_imports = false
|
||||||
ij_javascript_align_multiline_array_initializer_expression = false
|
ij_javascript_align_multiline_array_initializer_expression = false
|
||||||
ij_javascript_align_multiline_binary_operation = false
|
ij_javascript_align_multiline_binary_operation = false
|
||||||
@@ -297,6 +306,7 @@ ij_php_array_initializer_new_line_after_left_brace = true
|
|||||||
ij_php_array_initializer_right_brace_on_new_line = true
|
ij_php_array_initializer_right_brace_on_new_line = true
|
||||||
ij_php_array_initializer_wrap = on_every_item
|
ij_php_array_initializer_wrap = on_every_item
|
||||||
ij_php_assignment_wrap = off
|
ij_php_assignment_wrap = off
|
||||||
|
ij_php_attributes_wrap = off
|
||||||
ij_php_author_weight = 8
|
ij_php_author_weight = 8
|
||||||
ij_php_binary_operation_sign_on_next_line = false
|
ij_php_binary_operation_sign_on_next_line = false
|
||||||
ij_php_binary_operation_wrap = off
|
ij_php_binary_operation_wrap = off
|
||||||
@@ -385,6 +395,7 @@ ij_php_new_line_after_php_opening_tag = false
|
|||||||
ij_php_null_type_position = in_the_end
|
ij_php_null_type_position = in_the_end
|
||||||
ij_php_package_weight = 28
|
ij_php_package_weight = 28
|
||||||
ij_php_param_weight = 5
|
ij_php_param_weight = 5
|
||||||
|
ij_php_parameters_attributes_wrap = off
|
||||||
ij_php_parentheses_expression_new_line_after_left_paren = false
|
ij_php_parentheses_expression_new_line_after_left_paren = false
|
||||||
ij_php_parentheses_expression_right_paren_on_new_line = false
|
ij_php_parentheses_expression_right_paren_on_new_line = false
|
||||||
ij_php_phpdoc_blank_line_before_tags = true
|
ij_php_phpdoc_blank_line_before_tags = true
|
||||||
@@ -406,6 +417,7 @@ ij_php_see_weight = 3
|
|||||||
ij_php_since_weight = 28
|
ij_php_since_weight = 28
|
||||||
ij_php_sort_phpdoc_elements = true
|
ij_php_sort_phpdoc_elements = true
|
||||||
ij_php_space_after_colon = true
|
ij_php_space_after_colon = true
|
||||||
|
ij_php_space_after_colon_in_named_argument = true
|
||||||
ij_php_space_after_colon_in_return_type = true
|
ij_php_space_after_colon_in_return_type = true
|
||||||
ij_php_space_after_comma = true
|
ij_php_space_after_comma = true
|
||||||
ij_php_space_after_for_semicolon = true
|
ij_php_space_after_for_semicolon = true
|
||||||
@@ -419,6 +431,7 @@ ij_php_space_before_catch_parentheses = true
|
|||||||
ij_php_space_before_class_left_brace = true
|
ij_php_space_before_class_left_brace = true
|
||||||
ij_php_space_before_closure_left_parenthesis = true
|
ij_php_space_before_closure_left_parenthesis = true
|
||||||
ij_php_space_before_colon = true
|
ij_php_space_before_colon = true
|
||||||
|
ij_php_space_before_colon_in_named_argument = false
|
||||||
ij_php_space_before_colon_in_return_type = false
|
ij_php_space_before_colon_in_return_type = false
|
||||||
ij_php_space_before_comma = false
|
ij_php_space_before_comma = false
|
||||||
ij_php_space_before_do_left_brace = true
|
ij_php_space_before_do_left_brace = true
|
||||||
@@ -486,6 +499,7 @@ ij_php_while_on_new_line = false
|
|||||||
|
|
||||||
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
|
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
ij_visual_guides = none
|
||||||
ij_json_keep_blank_lines_in_code = 0
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
ij_json_keep_indents_on_empty_lines = false
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
ij_json_keep_line_breaks = true
|
ij_json_keep_line_breaks = true
|
||||||
@@ -500,6 +514,7 @@ ij_json_wrap_long_lines = false
|
|||||||
[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
|
[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
ij_smart_tabs = true
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||||
ij_html_align_attributes = true
|
ij_html_align_attributes = true
|
||||||
ij_html_align_text = false
|
ij_html_align_text = false
|
||||||
@@ -527,10 +542,30 @@ ij_html_space_inside_empty_tag = false
|
|||||||
ij_html_text_wrap = normal
|
ij_html_text_wrap = normal
|
||||||
ij_html_uniform_ident = false
|
ij_html_uniform_ident = false
|
||||||
|
|
||||||
|
[{*.markdown,*.md}]
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
|
||||||
[{*.yaml,*.yml}]
|
[{*.yaml,*.yml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_yaml_align_values_properties = do_not_align
|
||||||
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
ij_yaml_indent_sequence_value = true
|
||||||
ij_yaml_keep_indents_on_empty_lines = false
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
ij_yaml_keep_line_breaks = true
|
ij_yaml_keep_line_breaks = true
|
||||||
ij_yaml_space_before_colon = true
|
ij_yaml_sequence_on_new_line = false
|
||||||
|
ij_yaml_space_before_colon = false
|
||||||
ij_yaml_spaces_within_braces = true
|
ij_yaml_spaces_within_braces = true
|
||||||
ij_yaml_spaces_within_brackets = true
|
ij_yaml_spaces_within_brackets = true
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -32,6 +32,8 @@ test/vendor/*
|
|||||||
!/data/.htaccess
|
!/data/.htaccess
|
||||||
!/data/index.php
|
!/data/index.php
|
||||||
!/data/web.config
|
!/data/web.config
|
||||||
|
!/data/exclude.txt
|
||||||
|
!/data/.compilation-symlinks
|
||||||
|
|
||||||
# iTop extensions
|
# iTop extensions
|
||||||
/extensions/**
|
/extensions/**
|
||||||
@@ -140,5 +142,3 @@ local.properties
|
|||||||
.cache-main
|
.cache-main
|
||||||
.scala_dependencies
|
.scala_dependencies
|
||||||
.worksheet
|
.worksheet
|
||||||
|
|
||||||
/css/setup.css
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2010-2020 Combodo SARL
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2010-2020 Combodo SARL
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2010-2020 Combodo SARL
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* script used to sort license file (usefull for autogeneration)
|
* script used to sort license file (useful for autogeneration)
|
||||||
* Example: php
|
*
|
||||||
|
* Requirements :
|
||||||
|
* * bash (on Windows, use Git Bash)
|
||||||
|
* * composer (if you use the phar version, mind to create a `Composer` alias !)
|
||||||
|
* * JQ command
|
||||||
|
* to install on Windows :
|
||||||
|
* `curl -L -o /usr/bin/jq.exe https://github.com/stedolan/jq/releases/latest/download/jq-win64.exe`
|
||||||
|
* this is a Windows port : https://stedolan.github.io/jq/
|
||||||
|
*
|
||||||
|
* Known bug on Windows :
|
||||||
|
* Licenses added from Composer contains a path in the product node (N°3870)
|
||||||
|
* `<product scope="lib">C:\Dev\wamp64\www\itop-dev\.make\license/../..//lib/symfony/console</product>`
|
||||||
|
*
|
||||||
|
* Licenses sources :
|
||||||
|
* * `composer licenses --format json` (see https://getcomposer.org/doc/03-cli.md#licenses)
|
||||||
|
* * keep every existing nodes with `/licenses/license[11]/product/@scope` not in ['lib', 'datamodels']
|
||||||
|
* ⚠ If licenses were added manually, they might be removed by this tool ! Be very careful to check for the result before pushing !
|
||||||
|
*
|
||||||
|
* To launch, check requirements and run `php updateLicenses.php`
|
||||||
|
* The target license file path is in `$xmlFilePath`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$iTopFolder = __DIR__ . "/../../" ;
|
$iTopFolder = __DIR__ . "/../../" ;
|
||||||
|
|||||||
77
.make/release/changelog.php
Normal file
77
.make/release/changelog.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Usage :
|
||||||
|
* `php changelog.php 2.7.4`
|
||||||
|
*
|
||||||
|
* As argument is passed the git ref (tag name or sha1) we want to use as reference
|
||||||
|
*
|
||||||
|
* Outputs :
|
||||||
|
*
|
||||||
|
* 1. List of bugs as CSV :
|
||||||
|
* bug ref;link
|
||||||
|
* Example :
|
||||||
|
* <code>
|
||||||
|
* Bug_ref;Bug_URL;sha1
|
||||||
|
* 1234;https://support.combodo.com/pages/UI.php?operation=details&class=Bug&id=1234;949b213f9|b1ca1f263|a1271da74
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* 2. List of commits sha1/message without bug ref
|
||||||
|
* Example :
|
||||||
|
* <code>
|
||||||
|
* sha1;subject
|
||||||
|
* a6aa183e2;:bookmark: Prepare 2.7.5
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
if (count($argv) === 1) {
|
||||||
|
echo '⚠ You must pass the base tag/sha1 as parameter';
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$sBaseReference = $argv[1];
|
||||||
|
|
||||||
|
|
||||||
|
//--- Get log
|
||||||
|
$sGitLogCommand = 'git log --decorate --pretty="%h;%s" --date-order --no-merges '.$sBaseReference.'..HEAD';
|
||||||
|
$sGitLogRaw = shell_exec($sGitLogCommand);
|
||||||
|
|
||||||
|
|
||||||
|
//--- Analyze log
|
||||||
|
$aGitLogLines = preg_split('/\n/', trim($sGitLogRaw));;
|
||||||
|
$aLogLinesWithBugRef = [];
|
||||||
|
$aLogLineNoBug = [];
|
||||||
|
foreach ($aGitLogLines as $sLogLine) {
|
||||||
|
$sBugRef = preg_match('/[nN]°(\d{3,4})/', $sLogLine, $aLineBugRef);
|
||||||
|
if (($sBugRef === false) || empty($aLineBugRef)) {
|
||||||
|
$aLogLineNoBug[] = $sLogLine;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iBugId = $aLineBugRef[1];
|
||||||
|
$sSha = substr($sLogLine, 0, 9);
|
||||||
|
|
||||||
|
if (array_key_exists($iBugId, $aLogLinesWithBugRef)) {
|
||||||
|
$aBugShaRefs = $aLogLinesWithBugRef[$iBugId];
|
||||||
|
$aBugShaRefs[] = $sSha;
|
||||||
|
$aLogLinesWithBugRef[$iBugId] = $aBugShaRefs;
|
||||||
|
} else {
|
||||||
|
$aLogLinesWithBugRef[$iBugId] = [$sSha];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aBugsList = array_keys($aLogLinesWithBugRef);
|
||||||
|
sort($aBugsList, SORT_NUMERIC);
|
||||||
|
|
||||||
|
|
||||||
|
//-- Output results
|
||||||
|
echo "# Bugs included\n";
|
||||||
|
echo "Bug_ref;Bug_URL;sha1\n";
|
||||||
|
foreach ($aBugsList as $sBugRef) {
|
||||||
|
$sShaRefs = implode('|', $aLogLinesWithBugRef[$sBugRef]);
|
||||||
|
echo "{$sBugRef};https://support.combodo.com/pages/UI.php?operation=details&class=Bug&id={$sBugRef};$sShaRefs\n";
|
||||||
|
}
|
||||||
|
echo "\n";
|
||||||
|
echo "# Logs line without bug referenced\n";
|
||||||
|
echo "sha1;subject\n";
|
||||||
|
foreach ($aLogLineNoBug as $sLogLine) {
|
||||||
|
echo "$sLogLine\n";
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ If you want to use another license, you may [create an extension][wiki new ext].
|
|||||||
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
|
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
|
||||||
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
|
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
|
||||||
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
|
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
|
||||||
we don't have anymore a `master` branch.
|
we don't have a `master` branch anymore.
|
||||||
|
|
||||||
Here are the branches we use and their meaning :
|
Here are the branches we use and their meaning :
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ In this example, when 3.0.0-beta is shipped that will become:
|
|||||||
And when 3.0.0 final will be out:
|
And when 3.0.0 final will be out:
|
||||||
|
|
||||||
- `develop`: future 3.1.0 version
|
- `develop`: future 3.1.0 version
|
||||||
- `support/2.8`: 2.8.x maintenance version (will host developments for 3.0.1)
|
- `support/3.0`: 3.0.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
|
||||||
@@ -125,8 +125,7 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
|||||||
* ⬆️ `:arrow_up:` when upgrading dependencies
|
* ⬆️ `:arrow_up:` when upgrading dependencies
|
||||||
* ⬇️ `:arrow_down:` when downgrading dependencies
|
* ⬇️ `:arrow_down:` when downgrading dependencies
|
||||||
* ♻️ `:recycle:` code refactoring
|
* ♻️ `:recycle:` code refactoring
|
||||||
* 💄 `:lipstick:` Updating the UI and style files.
|
* 💄 `:lipstick:` Updating the UI and style files.
|
||||||
|
|
||||||
|
|
||||||
## 👥 Pull request
|
## 👥 Pull request
|
||||||
|
|
||||||
@@ -137,3 +136,21 @@ When your code is working, please:
|
|||||||
* create a pull request.
|
* create a pull request.
|
||||||
|
|
||||||
Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
||||||
|
|
||||||
|
You might check the ["Allow edits from maintainers" PR checkbox][allow_edits_checkbox] to ease review.
|
||||||
|
|
||||||
|
[allow_edits_checkbox]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork#enabling-repository-maintainer-permissions-on-existing-pull-requests
|
||||||
|
|
||||||
|
### 🙏 We are thankful
|
||||||
|
|
||||||
|
We are thankful for all your contributions to the iTop universe! As a thank you gift, we will send stickers to every iTop (& extensions) contributors!
|
||||||
|
|
||||||
|
Stickers' design might change from one year to another. For the first year we wanted to try a "craft beer label" look, see examples below:
|
||||||
|
|
||||||
|
* Bug hunter: Fix a bug
|
||||||
|
* Translator: Add/update translations
|
||||||
|
* White hat: Find and/or fix a vulnerability
|
||||||
|
* Contributor: Contribute by finding a bug, making an extension or any other way
|
||||||
|
* Partner: For Combodo's official partners
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
86
README.md
86
README.md
@@ -72,51 +72,55 @@ iTop development is sponsored, led and supported by [Combodo][0].
|
|||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
We would like to give a special thank you to the people from the community who contributed to this project, including:
|
We would like to give a special thank you 🤗 to the people from the community who contributed to this project, including:
|
||||||
|
|
||||||
### Names
|
### Names
|
||||||
- Alves, David
|
|
||||||
- Beck, Pedro
|
- Alves, David
|
||||||
- Bilger, Jean-François
|
- Beck, Pedro
|
||||||
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
- Bilger, Jean-François
|
||||||
- Cardoso, Anderson
|
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
||||||
- Cassaro, Bruno
|
- Cardoso, Anderson
|
||||||
- Casteleyn, Thomas (a.k.a @Hipska)
|
- Cassaro, Bruno
|
||||||
- Castro, Randall Badilla
|
- Casteleyn, Thomas (a.k.a @Hipska)
|
||||||
- Colantoni, Maria Laura
|
- Castro, Randall Badilla
|
||||||
- Couronné, Guy
|
- Colantoni, Maria Laura
|
||||||
- Dvořák, Lukáš
|
- Couronné, Guy
|
||||||
- Goethals, Stefan
|
- Dvořák, Lukáš
|
||||||
- Gumble, David
|
- Goethals, Stefan
|
||||||
- Hippler, Lars
|
- Gumble, David
|
||||||
- Khamit, Shamil
|
- Kaltefleiter, Lars (a.k.a @larhip)
|
||||||
- Kincel, Martin
|
- Khamit, Shamil
|
||||||
- Konečný, Kamil
|
- Kincel, Martin
|
||||||
- Kunin, Vladimir
|
- Konečný, Kamil
|
||||||
- Lassiter, Dennis
|
- Kunin, Vladimir
|
||||||
- Lazcano, Federico
|
- Lassiter, Dennis
|
||||||
- Lucas, Jonathan
|
- Lazcano, Federico
|
||||||
- Malik, Remie
|
- Lucas, Jonathan
|
||||||
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
- Malik, Remie
|
||||||
- Rosenke, Stephan
|
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||||
- Seki, Shoji
|
- Rosenke, Stephan
|
||||||
- Shilov, Vladimir
|
- Seki, Shoji
|
||||||
- Tulio, Marco
|
- Shilov, Vladimir
|
||||||
- Turrubiates, Miguel
|
- Tulio, Marco
|
||||||
|
- Turrubiates, Miguel
|
||||||
|
|
||||||
### Aliases
|
### Aliases
|
||||||
- chifu1234
|
|
||||||
- cprobst
|
- chifu1234
|
||||||
- Karkoff1212
|
- cprobst
|
||||||
- larhip
|
- DudekArtur
|
||||||
- Laura
|
- Karkoff1212
|
||||||
- Purple Grape
|
- Laura
|
||||||
- Schlobinux
|
- Purple Grape
|
||||||
- theBigOne
|
- Schlobinux
|
||||||
- ulmerspatz
|
- theBigOne
|
||||||
|
- ulmerspatz
|
||||||
|
|
||||||
### Companies
|
### Companies
|
||||||
- Hardis
|
|
||||||
- ITOMIG
|
- [Hardis](https://www.hardis-group.com/)
|
||||||
- Pimkie
|
- [ITOMIG](https://www.itomig.de/)
|
||||||
|
- [Pimkie](https://www.pimkie.com/)
|
||||||
|
- [Super-Visions](https://www.super-visions.com/)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
/**
|
/**
|
||||||
* UserRightsMatrix (User management Module)
|
* UserRightsMatrix (User management Module)
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* UserRightsNull
|
* UserRightsNull
|
||||||
* User management Module - say Yeah! to everything
|
* User management Module - say Yeah! to everything
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
|
||||||
*
|
|
||||||
* iTop is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* iTop is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('ADMIN_PROFILE_NAME', 'Administrator');
|
define('ADMIN_PROFILE_NAME', 'Administrator');
|
||||||
@@ -234,7 +221,7 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
(
|
(
|
||||||
"category" => "addon/userrights,grant_by_profile",
|
"category" => "addon/userrights,grant_by_profile",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "userid",
|
"name_attcode" => array("userlogin", "profile"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
@@ -259,24 +246,56 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetName()
|
|
||||||
{
|
|
||||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CheckToDelete(&$oDeletionPlan)
|
public function CheckToDelete(&$oDeletionPlan)
|
||||||
{
|
{
|
||||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||||
{
|
|
||||||
// Users deletion is NOT allowed in demo mode
|
// Users deletion is NOT allowed in demo mode
|
||||||
$oDeletionPlan->AddToDelete($this, null);
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||||
$oDeletionPlan->ComputeResults();
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||||
|
}
|
||||||
|
catch (SecurityException $e) {
|
||||||
|
// Users deletion is NOT allowed
|
||||||
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
|
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||||
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return parent::CheckToDelete($oDeletionPlan);
|
return parent::CheckToDelete($oDeletionPlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function DoCheckToDelete(&$oDeletionPlan)
|
||||||
|
{
|
||||||
|
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||||
|
// Users deletion is NOT allowed in demo mode
|
||||||
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
|
$oDeletionPlan->SetDeletionIssues($this, array('deletion not allowed in demo mode.'), true);
|
||||||
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
||||||
|
}
|
||||||
|
catch (SecurityException $e) {
|
||||||
|
// Users deletion is NOT allowed
|
||||||
|
$oDeletionPlan->AddToDelete($this, null);
|
||||||
|
$oDeletionPlan->SetDeletionIssues($this, [$e->getMessage()], true);
|
||||||
|
$oDeletionPlan->ComputeResults();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::DoCheckToDelete($oDeletionPlan);
|
||||||
|
}
|
||||||
|
|
||||||
protected function OnInsert()
|
protected function OnInsert()
|
||||||
{
|
{
|
||||||
$this->CheckIfProfileIsAllowed(UR_ACTION_CREATE);
|
$this->CheckIfProfileIsAllowed(UR_ACTION_CREATE);
|
||||||
@@ -289,7 +308,6 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
|
|
||||||
protected function OnDelete()
|
protected function OnDelete()
|
||||||
{
|
{
|
||||||
$this->CheckIfProfileIsAllowed(UR_ACTION_DELETE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -339,7 +357,7 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
(
|
(
|
||||||
"category" => "addon/userrights,grant_by_profile",
|
"category" => "addon/userrights,grant_by_profile",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "userid",
|
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userorg",
|
"db_table" => "priv_urp_userorg",
|
||||||
@@ -364,12 +382,6 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetName()
|
|
||||||
{
|
|
||||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Org', $this->Get('userlogin'), $this->Get('allowed_org_name'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected function OnInsert()
|
protected function OnInsert()
|
||||||
{
|
{
|
||||||
$this->CheckIfOrgIsAllowed();
|
$this->CheckIfOrgIsAllowed();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -327,7 +327,7 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
(
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "userid",
|
"name_attcode" => array("userlogin", "profile"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
@@ -351,11 +351,6 @@ class URP_UserProfile extends UserRightsBaseClassGUI
|
|||||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetName()
|
|
||||||
{
|
|
||||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class URP_UserOrg extends UserRightsBaseClassGUI
|
class URP_UserOrg extends UserRightsBaseClassGUI
|
||||||
@@ -366,7 +361,7 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
(
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "userid",
|
"name_attcode" => array("userlogin", "allowed_org_name"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userorg",
|
"db_table" => "priv_urp_userorg",
|
||||||
@@ -390,11 +385,6 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
|||||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetName()
|
|
||||||
{
|
|
||||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Org', $this->Get('userlogin'), $this->Get('allowed_org_name'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -270,7 +270,7 @@ class URP_UserProfile extends UserRightsBaseClass
|
|||||||
(
|
(
|
||||||
"category" => "addon/userrights",
|
"category" => "addon/userrights",
|
||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "userid",
|
"name_attcode" => array("userlogin", "profile"),
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array(),
|
||||||
"db_table" => "priv_urp_userprofile",
|
"db_table" => "priv_urp_userprofile",
|
||||||
@@ -294,11 +294,6 @@ class URP_UserProfile extends UserRightsBaseClass
|
|||||||
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetName()
|
|
||||||
{
|
|
||||||
return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
60
application/DBSearchHelper.php
Normal file
60
application/DBSearchHelper.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DBSearchHelper
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
class DBSearchHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add context filter to DBUnionSearch
|
||||||
|
*
|
||||||
|
* @param \DBSearch|null $oSearch
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function AddContextFilter(?DBSearch $oSearch): void
|
||||||
|
{
|
||||||
|
$oAppContext = new ApplicationContext();
|
||||||
|
$sClass = $oSearch->GetClass();
|
||||||
|
foreach ($oAppContext->GetNames() as $key) {
|
||||||
|
// Find the value of the object corresponding to each 'context' parameter
|
||||||
|
$aCallSpec = [$sClass, 'MapContextParam'];
|
||||||
|
$sAttCode = '';
|
||||||
|
if (is_callable($aCallSpec)) {
|
||||||
|
$sAttCode = call_user_func($aCallSpec, $key); // Returns null when there is no mapping for this parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
||||||
|
// Add Hierarchical condition if hierarchical key
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
|
if (isset($oAttDef) && ($oAttDef->IsExternalKey())) {
|
||||||
|
$iDefaultValue = intval($oAppContext->GetCurrentValue($key));
|
||||||
|
if ($iDefaultValue != 0) {
|
||||||
|
try {
|
||||||
|
/** @var AttributeExternalKey $oAttDef */
|
||||||
|
$sTargetClass = $oAttDef->GetTargetClass();
|
||||||
|
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass);
|
||||||
|
if ($sHierarchicalKeyCode !== false) {
|
||||||
|
$oFilter = new DBObjectSearch($sTargetClass);
|
||||||
|
$oFilter->AddCondition('id', $iDefaultValue);
|
||||||
|
$oHKFilter = new DBObjectSearch($sTargetClass);
|
||||||
|
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
|
||||||
|
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
// If filtering fails just ignore it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||||
|
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ajax_page
|
* Class ajax_page
|
||||||
|
*
|
||||||
* @deprecated will be removed in 3.1.0 - moved to AjaxPage
|
* @deprecated will be removed in 3.1.0 - moved to AjaxPage
|
||||||
*/
|
*/
|
||||||
class ajax_page extends AjaxPage
|
class ajax_page extends AjaxPage
|
||||||
|
|||||||
@@ -1,27 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
/*
|
||||||
//
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
// This file is part of iTop.
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
//
|
*/
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// iTop is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Includes all the classes to have the application up and running
|
* Includes all the classes to have the application up and running
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
||||||
@@ -31,9 +15,4 @@ require_once(APPROOT.'/application/audit.category.class.inc.php');
|
|||||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||||
require_once(APPROOT.'/application/query.class.inc.php');
|
require_once(APPROOT.'/application/query.class.inc.php');
|
||||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||||
//require_once(APPROOT.'/application/menunode.class.inc.php');
|
|
||||||
require_once(APPROOT.'/application/utils.inc.php');
|
require_once(APPROOT.'/application/utils.inc.php');
|
||||||
|
|
||||||
class ApplicationException extends CoreException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2018 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,13 +20,13 @@
|
|||||||
/**
|
/**
|
||||||
* Class ApplicationContext
|
* Class ApplicationContext
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2018 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @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\Base\Component\Input\InputUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||||
use Combodo\iTop\Application\UI\UIBlock;
|
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||||
|
|
||||||
require_once(APPROOT."/application/utils.inc.php");
|
require_once(APPROOT."/application/utils.inc.php");
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ class ApplicationContext
|
|||||||
{
|
{
|
||||||
$oContext = new UIContentBlock();
|
$oContext = new UIContentBlock();
|
||||||
foreach ($this->aValues as $sName => $sValue) {
|
foreach ($this->aValues as $sName => $sValue) {
|
||||||
$oContext->AddSubBlock(InputFactory::MakeForHidden('c[$sName]', utils::HtmlEntities($sValue)));
|
$oContext->AddSubBlock(InputUIBlockFactory::MakeForHidden('c[$sName]', utils::HtmlEntities($sValue)));
|
||||||
}
|
}
|
||||||
return $oContext;
|
return $oContext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||||
use Symfony\Component\DependencyInjection\Container;
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
|
|
||||||
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
||||||
@@ -29,7 +30,7 @@ require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
|||||||
* You may implement such interfaces in a module file (e.g. main.mymodule.php)
|
* You may implement such interfaces in a module file (e.g. main.mymodule.php)
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @package Extensibility
|
* @package Extensibility
|
||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
@@ -72,15 +73,14 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public abstract function ListSupportedLoginModes();
|
abstract public function ListSupportedLoginModes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function LoginAction($sLoginState, &$iErrorCode)
|
public function LoginAction($sLoginState, &$iErrorCode)
|
||||||
{
|
{
|
||||||
switch ($sLoginState)
|
switch ($sLoginState) {
|
||||||
{
|
|
||||||
case LoginWebPage::LOGIN_STATE_START:
|
case LoginWebPage::LOGIN_STATE_START:
|
||||||
return $this->OnStart($iErrorCode);
|
return $this->OnStart($iErrorCode);
|
||||||
|
|
||||||
@@ -430,7 +430,7 @@ interface iApplicationUIExtension
|
|||||||
*
|
*
|
||||||
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
|
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
|
||||||
*
|
*
|
||||||
* @return string[string]
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function EnumAllowedActions(DBObjectSet $oSet);
|
public function EnumAllowedActions(DBObjectSet $oSet);
|
||||||
}
|
}
|
||||||
@@ -776,6 +776,10 @@ abstract class ApplicationPopupMenuItem
|
|||||||
/** @ignore */
|
/** @ignore */
|
||||||
protected $sLabel;
|
protected $sLabel;
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
|
protected $sTooltip;
|
||||||
|
/** @ignore */
|
||||||
|
protected $sIconClass;
|
||||||
|
/** @ignore */
|
||||||
protected $aCssClasses;
|
protected $aCssClasses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -790,6 +794,8 @@ abstract class ApplicationPopupMenuItem
|
|||||||
{
|
{
|
||||||
$this->sUID = $sUID;
|
$this->sUID = $sUID;
|
||||||
$this->sLabel = $sLabel;
|
$this->sLabel = $sLabel;
|
||||||
|
$this->sTooltip = '';
|
||||||
|
$this->sIconClass = '';
|
||||||
$this->aCssClasses = array();
|
$this->aCssClasses = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,6 +850,47 @@ abstract class ApplicationPopupMenuItem
|
|||||||
$this->aCssClasses[] = $sCssClass;
|
$this->aCssClasses[] = $sCssClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $sTooltip
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function SetTooltip($sTooltip)
|
||||||
|
{
|
||||||
|
$this->sTooltip = $sTooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function GetTooltip()
|
||||||
|
{
|
||||||
|
return $this->sTooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $sIconClass
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function SetIconClass($sIconClass)
|
||||||
|
{
|
||||||
|
$this->sIconClass = $sIconClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function GetIconClass()
|
||||||
|
{
|
||||||
|
return $this->sIconClass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the components to create a popup menu item in HTML
|
* Returns the components to create a popup menu item in HTML
|
||||||
*
|
*
|
||||||
@@ -891,7 +938,13 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
/** @ignore */
|
/** @ignore */
|
||||||
public function GetMenuItem()
|
public function GetMenuItem()
|
||||||
{
|
{
|
||||||
return array('label' => $this->GetLabel(), 'url' => $this->GetUrl(), 'target' => $this-> GetTarget(), 'css_classes' => $this->aCssClasses);
|
return array('label' => $this->GetLabel(),
|
||||||
|
'url' => $this->GetUrl(),
|
||||||
|
'target' => $this-> GetTarget(),
|
||||||
|
'css_classes' => $this->aCssClasses,
|
||||||
|
'icon_class' => $this->sIconClass,
|
||||||
|
'tooltip' => $this->sTooltip
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
@@ -951,6 +1004,8 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
|||||||
'onclick' => $this->GetJsCode().'; return false;',
|
'onclick' => $this->GetJsCode().'; return false;',
|
||||||
'url' => $this->GetUrl(),
|
'url' => $this->GetUrl(),
|
||||||
'css_classes' => $this->GetCssClasses(),
|
'css_classes' => $this->GetCssClasses(),
|
||||||
|
'icon_class' => $this->sIconClass,
|
||||||
|
'tooltip' => $this->sTooltip
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1042,6 +1097,7 @@ class JSButtonItem extends JSPopupMenuItem
|
|||||||
* @api
|
* @api
|
||||||
* @package Extensibility
|
* @package Extensibility
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
* @deprecated since 3.0.0 use iPageUIBlockExtension instead
|
||||||
*/
|
*/
|
||||||
interface iPageUIExtension
|
interface iPageUIExtension
|
||||||
{
|
{
|
||||||
@@ -1073,12 +1129,56 @@ interface iPageUIExtension
|
|||||||
public function GetBannerHtml(iTopWebPage $oPage);
|
public function GetBannerHtml(iTopWebPage $oPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this interface to add content to any iTopWebPage
|
||||||
|
*
|
||||||
|
* There are 3 places where content can be added:
|
||||||
|
*
|
||||||
|
* * The north pane: (normaly empty/hidden) at the top of the page, spanning the whole
|
||||||
|
* width of the page
|
||||||
|
* * The south pane: (normaly empty/hidden) at the bottom of the page, spanning the whole
|
||||||
|
* width of the page
|
||||||
|
* * The admin banner (two tones gray background) at the left of the global search.
|
||||||
|
* Limited space, use it for short messages
|
||||||
|
*
|
||||||
|
* Each of the methods of this interface is supposed to return the HTML to be inserted at
|
||||||
|
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @package Extensibility
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
interface iPageUIBlockExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add content to the "admin banner"
|
||||||
|
*
|
||||||
|
* @return iUIBlock|null The Block to add into the page
|
||||||
|
*/
|
||||||
|
public function GetBannerBlock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add content to the header of the page
|
||||||
|
*
|
||||||
|
* @return iUIBlock|null The Block to add into the page
|
||||||
|
*/
|
||||||
|
public function GetHeaderBlock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add content to the footer of the page
|
||||||
|
*
|
||||||
|
* @return iUIBlock|null The Block to add into the page
|
||||||
|
*/
|
||||||
|
public function GetFooterBlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this class instead of iPageUIExtension if you don't need to overload all methods
|
* Extend this class instead of iPageUIExtension if you don't need to overload all methods
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @package Extensibility
|
* @package Extensibility
|
||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
|
* @deprecated since 3.0.0 use AbstractPageUIBlockExtension instead
|
||||||
*/
|
*/
|
||||||
abstract class AbstractPageUIExtension implements iPageUIExtension
|
abstract class AbstractPageUIExtension implements iPageUIExtension
|
||||||
{
|
{
|
||||||
@@ -1087,6 +1187,8 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
|||||||
*/
|
*/
|
||||||
public function GetNorthPaneHtml(iTopWebPage $oPage)
|
public function GetNorthPaneHtml(iTopWebPage $oPage)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1095,6 +1197,8 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
|||||||
*/
|
*/
|
||||||
public function GetSouthPaneHtml(iTopWebPage $oPage)
|
public function GetSouthPaneHtml(iTopWebPage $oPage)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,11 +1207,47 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
|
|||||||
*/
|
*/
|
||||||
public function GetBannerHtml(iTopWebPage $oPage)
|
public function GetBannerHtml(iTopWebPage $oPage)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use iPageUIBlockExtension instead');
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend this class instead of iPageUIExtension if you don't need to overload all methods
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @package Extensibility
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
abstract class AbstractPageUIBlockExtension implements iPageUIBlockExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function GetBannerBlock()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function GetHeaderBlock()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function GetFooterBlock()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this interface to add content to any enhanced portal page
|
* Implement this interface to add content to any enhanced portal page
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* to check and is linked to a set of rules that determine the valid or invalid objects
|
* to check and is linked to a set of rules that determine the valid or invalid objects
|
||||||
* inside the set
|
* inside the set
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
* or the "bad" ones. The core audit engines computes the complement to the definition
|
* or the "bad" ones. The core audit engines computes the complement to the definition
|
||||||
* set when needed to obtain either the valid objects, or the ones with an error
|
* set when needed to obtain either the valid objects, or the ones with an error
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||||
File diff suppressed because it is too large
Load Diff
38
application/compilecssservice.class.inc.php
Normal file
38
application/compilecssservice.class.inc.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
|
*
|
||||||
|
* This file is part of iTop.
|
||||||
|
*
|
||||||
|
* iTop is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* iTop is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CompileCSSService : used to ease testing ThemeHander class via mocks
|
||||||
|
*
|
||||||
|
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
|
*/
|
||||||
|
class CompileCSSService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* CompileCSSService constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
||||||
|
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||||
@@ -1,26 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2013-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
|
||||||
*
|
|
||||||
* iTop is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* iTop is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Component\Toolbar\Toolbar;
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
||||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||||
|
|
||||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||||
require_once(APPROOT.'application/dashlet.class.inc.php');
|
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||||
@@ -443,22 +431,19 @@ abstract class Dashboard
|
|||||||
public function RenderProperties($oPage, $aExtraParams = array())
|
public function RenderProperties($oPage, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
// menu to pick a layout and edit other properties of the dashboard
|
// menu to pick a layout and edit other properties of the dashboard
|
||||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
|
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashboard-editor--properties"><div class="ui-widget-header ui-corner-all ibo-dashboard-editor--properties-title">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
|
||||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||||
|
|
||||||
$oPage->add('<div style="text-align:center">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
|
$oPage->add('<div class="ibo-dashboard-editor--properties-subtitle" data-role="ibo-dashboard-editor--properties-subtitle">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
|
||||||
$oPage->add('<div id="select_layout" style="text-align:center">');
|
$oPage->add('<div id="select_layout" class="ibo-dashboard-editor--layout-list" data-role="ibo-dashboard-editor--layout-list">');
|
||||||
foreach( get_declared_classes() as $sLayoutClass)
|
foreach (get_declared_classes() as $sLayoutClass) {
|
||||||
{
|
if (is_subclass_of($sLayoutClass, 'DashboardLayout')) {
|
||||||
if (is_subclass_of($sLayoutClass, 'DashboardLayout'))
|
|
||||||
{
|
|
||||||
$oReflection = new ReflectionClass($sLayoutClass);
|
$oReflection = new ReflectionClass($sLayoutClass);
|
||||||
if (!$oReflection->isAbstract())
|
if (!$oReflection->isAbstract()) {
|
||||||
{
|
|
||||||
$aCallSpec = array($sLayoutClass, 'GetInfo');
|
$aCallSpec = array($sLayoutClass, 'GetInfo');
|
||||||
$aInfo = call_user_func($aCallSpec);
|
$aInfo = call_user_func($aCallSpec);
|
||||||
$sChecked = ($this->sLayoutClass == $sLayoutClass) ? 'checked' : '';
|
$sChecked = ($this->sLayoutClass == $sLayoutClass) ? 'checked' : '';
|
||||||
$oPage->add('<input type="radio" name="layout_class" '.$sChecked.' value="'.$sLayoutClass.'" id="layout_'.$sLayoutClass.'"><label for="layout_'.$sLayoutClass.'"><img src="'.$sUrl.$aInfo['icon'].'" /></label>'); // title="" on either the img or the label does nothing !
|
$oPage->add('<input type="radio" name="layout_class" '.$sChecked.' value="'.$sLayoutClass.'" id="layout_'.$sLayoutClass.'"><label for="layout_'.$sLayoutClass.'"><img src="'.$sUrl.$aInfo['icon'].'" class="ibo-dashboard--properties--icon" data-role="ibo-dashboard--properties--icon"/></label>'); // title="" on either the img or the label does nothing !
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -489,7 +474,8 @@ abstract class Dashboard
|
|||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
// Note: the title gets deleted by the validation mechanism
|
// Note: the title gets deleted by the validation mechanism
|
||||||
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
|
$("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
|
||||||
|
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
|
||||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||||
|
|
||||||
$('#attr_auto_reload').change( function(ev) {
|
$('#attr_auto_reload').change( function(ev) {
|
||||||
@@ -506,7 +492,7 @@ abstract class Dashboard
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#event_bus').bind('dashlet-selected', function(event, data){
|
$('#event_bus').on('dashlet-selected', function(event, data){
|
||||||
var sDashletId = data.dashlet_id;
|
var sDashletId = data.dashlet_id;
|
||||||
var sPropId = 'dashlet_properties_'+sDashletId;
|
var sPropId = 'dashlet_properties_'+sDashletId;
|
||||||
$('.dashlet_properties').each(function() {
|
$('.dashlet_properties').each(function() {
|
||||||
@@ -531,6 +517,8 @@ EOF
|
|||||||
* @param bool $bEditMode
|
* @param bool $bEditMode
|
||||||
* @param array $aExtraParams
|
* @param array $aExtraParams
|
||||||
* @param bool $bCanEdit
|
* @param bool $bCanEdit
|
||||||
|
*
|
||||||
|
* @return \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout
|
||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
||||||
{
|
{
|
||||||
@@ -538,21 +526,6 @@ EOF
|
|||||||
$aExtraParams['dashboard_div_id'] = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
$aExtraParams['dashboard_div_id'] = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||||
}
|
}
|
||||||
|
|
||||||
$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();
|
||||||
|
|
||||||
@@ -563,11 +536,36 @@ JS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
$oDashboard = $oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||||
|
$oPage->AddUiBlock($oDashboard);
|
||||||
|
|
||||||
|
$bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
||||||
|
|
||||||
|
if ($bFromDasboardPage) {
|
||||||
|
$sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
|
||||||
|
$sHtml = "<div class=\"ibo-top-bar--toolbar-dashboard-title\">{$sTitleForHTML}</div>";
|
||||||
|
if ($oPage instanceof iTopWebPage) {
|
||||||
|
$oTopBar = $oPage->GetTopBarLayout();
|
||||||
|
$oToolbar = ToolbarUIBlockFactory::MakeStandard();
|
||||||
|
$oTopBar->SetToolbar($oToolbar);
|
||||||
|
|
||||||
|
$oToolbar->AddHtml($sHtml);
|
||||||
|
} else {
|
||||||
|
$oPage->add_script(<<<JS
|
||||||
|
$(".ibo-top-bar--toolbar-dashboard-title").html("$sTitleForHTML");
|
||||||
|
JS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$oDashboard->SetTitle(Dict::S($this->sTitle));
|
||||||
|
}
|
||||||
|
|
||||||
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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $oDashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -579,19 +577,18 @@ JS
|
|||||||
public function RenderDashletsSelection(WebPage $oPage)
|
public function RenderDashletsSelection(WebPage $oPage)
|
||||||
{
|
{
|
||||||
// Toolbox/palette to drag and drop dashlets
|
// Toolbox/palette to drag and drop dashlets
|
||||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
|
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashboard--available-dashlets"><div class="ui-widget-header ui-corner-all ibo-dashboard--available-dashlet--title">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
|
||||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||||
|
|
||||||
$oPage->add('<div id="select_dashlet" style="text-align:center; max-height:120px; overflow-y:auto;">');
|
$oPage->add('<div id="select_dashlet" class="ibo-dashboard--available-dashlets--list" data-role="ibo-dashboard--available-dashlets--list">');
|
||||||
$aAvailableDashlets = $this->GetAvailableDashlets();
|
$aAvailableDashlets = $this->GetAvailableDashlets();
|
||||||
foreach($aAvailableDashlets as $sDashletClass => $aInfo)
|
foreach ($aAvailableDashlets as $sDashletClass => $aInfo) {
|
||||||
{
|
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="ibo-dashboard-editor--available-dashlet-icon dashlet_icon ui-widget-content ui-corner-all" data-role="ibo-dashboard-editor--available-dashlet-icon" id="dashlet_'.$sDashletClass.'" title="'.$aInfo['label'].'"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
|
||||||
$oPage->add('<span dashlet_class="'.$sDashletClass.'" class="dashlet_icon ui-widget-content ui-corner-all" id="dashlet_'.$sDashletClass.'" title="'.$aInfo['label'].'" style="width:34px; height:34px; display:inline-block; margin:2px;"><img src="'.$sUrl.$aInfo['icon'].'" /></span>');
|
|
||||||
}
|
}
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
|
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
$oPage->add_ready_script("$('.dashlet_icon').draggable({helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
|
$oPage->add_ready_script("$('.dashlet_icon').draggable({cursor: 'move', helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -601,12 +598,12 @@ JS
|
|||||||
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
|
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
// Toolbox/palette to edit the properties of each dashlet
|
// Toolbox/palette to edit the properties of each dashlet
|
||||||
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
|
$oPage->add('<div class="ui-widget-content ui-corner-all ibo-dashlet--properties"><div class="ui-widget-header ui-corner-all ibo-dashlet--properties--title">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
|
||||||
|
|
||||||
/** @var \DashboardLayoutMultiCol $oLayout */
|
/** @var \DashboardLayoutMultiCol $oLayout */
|
||||||
$oLayout = new $this->sLayoutClass();
|
$oLayout = new $this->sLayoutClass();
|
||||||
|
|
||||||
$oPage->add('<div id="dashlet_properties" style="text-align:center">');
|
$oPage->add('<div id="dashlet_properties">');
|
||||||
foreach($this->aCells as $iCellIdx => $aCell)
|
foreach($this->aCells as $iCellIdx => $aCell)
|
||||||
{
|
{
|
||||||
/** @var \Dashlet $oDashlet */
|
/** @var \Dashlet $oDashlet */
|
||||||
@@ -639,16 +636,13 @@ JS
|
|||||||
|
|
||||||
foreach( get_declared_classes() as $sDashletClass)
|
foreach( get_declared_classes() as $sDashletClass)
|
||||||
{
|
{
|
||||||
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instanciated.
|
// DashletUnknown is not among the selection as it is just a fallback for dashlets that can't instantiated.
|
||||||
if ( is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, array('DashletUnknown', 'DashletProxy')) )
|
if (is_subclass_of($sDashletClass, 'Dashlet') && !in_array($sDashletClass, array('DashletUnknown', 'DashletProxy'))) {
|
||||||
{
|
|
||||||
$oReflection = new ReflectionClass($sDashletClass);
|
$oReflection = new ReflectionClass($sDashletClass);
|
||||||
if (!$oReflection->isAbstract())
|
if (!$oReflection->isAbstract()) {
|
||||||
{
|
|
||||||
$aCallSpec = array($sDashletClass, 'IsVisible');
|
$aCallSpec = array($sDashletClass, 'IsVisible');
|
||||||
$bVisible = call_user_func($aCallSpec);
|
$bVisible = call_user_func($aCallSpec);
|
||||||
if ($bVisible)
|
if ($bVisible) {
|
||||||
{
|
|
||||||
$aCallSpec = array($sDashletClass, 'GetInfo');
|
$aCallSpec = array($sDashletClass, 'GetInfo');
|
||||||
$aInfo = call_user_func($aCallSpec);
|
$aInfo = call_user_func($aCallSpec);
|
||||||
$aDashlets[$sDashletClass] = $aInfo;
|
$aDashlets[$sDashletClass] = $aInfo;
|
||||||
@@ -896,11 +890,53 @@ class RuntimeDashboard extends Dashboard
|
|||||||
$oDashboard->FromXml($sDashboardDefinition);
|
$oDashboard->FromXml($sDashboardDefinition);
|
||||||
$oDashboard->SetCustomFlag($bCustomized);
|
$oDashboard->SetCustomFlag($bCustomized);
|
||||||
$oDashboard->SetDefinitionFile($sDashboardFile);
|
$oDashboard->SetDefinitionFile($sDashboardFile);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$oDashboard = null;
|
$oDashboard = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $oDashboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sDashboardFile file name relative to the current module folder
|
||||||
|
* @param string $sDashBoardId code of the dashboard either menu_id or <class>__<attcode>
|
||||||
|
*
|
||||||
|
* @return null|RuntimeDashboard
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function GetDashboardToEdit($sDashboardFile, $sDashBoardId)
|
||||||
|
{
|
||||||
|
$bCustomized = false;
|
||||||
|
|
||||||
|
// Search for an eventual user defined dashboard
|
||||||
|
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||||
|
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||||
|
$oUDSearch->AddCondition('menu_code', $sDashBoardId, '=');
|
||||||
|
$oUDSet = new DBObjectSet($oUDSearch);
|
||||||
|
if ($oUDSet->Count() > 0) {
|
||||||
|
// Assuming there is at most one couple {user, menu}!
|
||||||
|
$oUserDashboard = $oUDSet->Fetch();
|
||||||
|
$sDashboardDefinition = $oUserDashboard->Get('contents');
|
||||||
|
$bCustomized = true;
|
||||||
|
} else {
|
||||||
|
$sDashboardDefinition = @file_get_contents($sDashboardFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($sDashboardDefinition !== false) {
|
||||||
|
$oDashboard = new RuntimeDashboard($sDashBoardId);
|
||||||
|
$oDashboard->FromXml($sDashboardDefinition);
|
||||||
|
$oDashboard->SetCustomFlag($bCustomized);
|
||||||
|
$oDashboard->SetDefinitionFile($sDashboardFile);
|
||||||
|
} else {
|
||||||
|
$oDashboard = null;
|
||||||
|
}
|
||||||
|
|
||||||
return $oDashboard;
|
return $oDashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -910,43 +946,33 @@ class RuntimeDashboard extends Dashboard
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
||||||
{
|
{
|
||||||
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class']))
|
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class'])) {
|
||||||
{
|
|
||||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||||
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aRenderParams = $aExtraParams;
|
$aRenderParams = $aExtraParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::Render($oPage, $bEditMode, $aRenderParams);
|
$oDashboard = parent::Render($oPage, $bEditMode, $aRenderParams);
|
||||||
|
|
||||||
if (isset($aExtraParams['query_params']['this->object()']))
|
if (isset($aExtraParams['query_params']['this->object()'])) {
|
||||||
{
|
|
||||||
/** @var \DBObject $oObj */
|
/** @var \DBObject $oObj */
|
||||||
$oObj = $aExtraParams['query_params']['this->object()'];
|
$oObj = $aExtraParams['query_params']['this->object()'];
|
||||||
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
|
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
|
||||||
}
|
if (isset($aExtraParams['from_dashboard_page'])) {
|
||||||
else
|
$aAjaxParams['from_dashboard_page'] = $aExtraParams['from_dashboard_page'];
|
||||||
{
|
}
|
||||||
|
} else {
|
||||||
$aAjaxParams = $aExtraParams;
|
$aAjaxParams = $aExtraParams;
|
||||||
}
|
}
|
||||||
if (!$bEditMode && !$oPage->IsPrintableVersion())
|
if (!$bEditMode && !$oPage->IsPrintableVersion()) {
|
||||||
{
|
|
||||||
$sId = $this->GetId();
|
$sId = $this->GetId();
|
||||||
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
$sDivId = utils::Sanitize($sId, '', 'element_identifier');
|
||||||
if ($this->GetAutoReload())
|
if ($this->GetAutoReload()) {
|
||||||
{
|
|
||||||
$sFile = addslashes($this->GetDefinitionFile());
|
|
||||||
$sExtraParams = json_encode($aAjaxParams);
|
|
||||||
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
|
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
|
||||||
$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
|
<<<JS
|
||||||
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
||||||
{
|
{
|
||||||
clearInterval(AutoReloadDashboardId$sDivId);
|
clearInterval(AutoReloadDashboardId$sDivId);
|
||||||
@@ -960,23 +986,16 @@ class RuntimeDashboard extends Dashboard
|
|||||||
// Do not reload when a dialog box is active
|
// Do not reload when a dialog box is active
|
||||||
if (!($('.ui-dialog:visible').length > 0) && $('.ibo-dashboard#$sDivId').is(':visible'))
|
if (!($('.ui-dialog:visible').length > 0) && $('.ibo-dashboard#$sDivId').is(':visible'))
|
||||||
{
|
{
|
||||||
$('.ibo-dashboard#$sDivId').block();
|
updateDashboard$sDivId();
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
|
||||||
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, c: $sContext, reload_url: '$sReloadURL'},
|
|
||||||
function(data){
|
|
||||||
$('.ibo-dashboard#$sDivId').html(data);
|
|
||||||
$('.ibo-dashboard#$sDivId').unblock();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
|
||||||
{
|
{
|
||||||
clearInterval(AutoReloadDashboardId$sDivId);
|
clearInterval(AutoReloadDashboardId$sDivId);
|
||||||
@@ -986,67 +1005,76 @@ EOF
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bCanEdit)
|
if ($bCanEdit) {
|
||||||
{
|
$this->RenderSelector($oPage, $oDashboard, $aAjaxParams);
|
||||||
$this->RenderSelector($oPage, $aAjaxParams);
|
$this->RenderEditionTools($oPage, $oDashboard, $aAjaxParams);
|
||||||
$this->RenderEditionTools($oPage, $aAjaxParams);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param WebPage $oPage
|
||||||
|
* @param \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout $oDashboard
|
||||||
|
* @param bool $bFromDashboardPage
|
||||||
* @param array $aAjaxParams
|
* @param array $aAjaxParams
|
||||||
*
|
*
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \CoreUnexpectedValue
|
* @throws \CoreUnexpectedValue
|
||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
*/
|
*/
|
||||||
protected function RenderSelector(WebPage $oPage, $aAjaxParams = array())
|
protected function RenderSelector(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aAjaxParams = array())
|
||||||
{
|
{
|
||||||
|
if (!$this->HasCustomDashboard()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$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="ibo-top-bar--toolbar-dashboard-selector">';
|
$sSwitchToStandard = Dict::S('UI:Toggle:SwitchToStandardDashboard');
|
||||||
if ($this->HasCustomDashboard()) {
|
$sSwitchToCustom = Dict::S('UI:Toggle:SwitchToCustomDashboard');
|
||||||
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
|
||||||
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
|
|
||||||
$sSelectorHtml .= '<div class="selector-label">'.$sStandard.'</div>';
|
$sSelectorHtml = '<div id="ibo-dashboard-selector'.$sDivId.'" class="ibo-dashboard--selector" data-tooltip-content="'.($bStandardSelected ? $sSwitchToCustom : $sSwitchToStandard).'">';
|
||||||
$sSelectorHtml .= '<label class="switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="slider round"></span></label></input></label>';
|
$sSelectorHtml .= '<label class="ibo-dashboard--switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="ibo-dashboard--slider"></span></label></input></label>';
|
||||||
$sCustom = Dict::S('UI:Toggle:CustomDashboard');
|
|
||||||
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
|
|
||||||
}
|
|
||||||
$sSelectorHtml .= '</div>';
|
$sSelectorHtml .= '</div>';
|
||||||
|
|
||||||
$sFile = addslashes($this->GetDefinitionFile());
|
$sFile = addslashes($this->GetDefinitionFile());
|
||||||
$sReloadURL = $this->GetReloadURL();
|
$sReloadURL = $this->GetReloadURL();
|
||||||
|
|
||||||
if ($oPage instanceof iTopWebPage) {
|
$bFromDashboardPage = isset($aAjaxParams['from_dashboard_page']) ? isset($aAjaxParams['from_dashboard_page']) : false;
|
||||||
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
if ($bFromDashboardPage) {
|
||||||
|
if ($oPage instanceof iTopWebPage) {
|
||||||
|
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||||
|
$oToolbar->AddHtml($sSelectorHtml);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$oToolbar = $oDashboard->GetToolbar();
|
||||||
$oToolbar->AddHtml($sSelectorHtml);
|
$oToolbar->AddHtml($sSelectorHtml);
|
||||||
|
}
|
||||||
|
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
<<<EOF
|
<<<JS
|
||||||
function ToggleDashboardSelector$sDivId()
|
function ToggleDashboardSelector$sDivId()
|
||||||
{
|
{
|
||||||
$('.ibo-dashboard#$sDivId').block();
|
var dashboard = $('.ibo-dashboard#$sDivId')
|
||||||
|
dashboard.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) {
|
||||||
$('.ibo-dashboard#$sDivId').html(data);
|
dashboard.html(data);
|
||||||
$('.ibo-dashboard#$sDivId').unblock();
|
dashboard.unblock();
|
||||||
|
if ($('#ibo-dashboard-selector$sDivId input').prop("checked")) {
|
||||||
|
$('#ibo-dashboard-selector$sDivId').data('tooltip-content', '$sSwitchToStandard');
|
||||||
|
} else {
|
||||||
|
$('#ibo-dashboard-selector$sDivId').data('tooltip-content', '$sSwitchToCustom');
|
||||||
|
}
|
||||||
|
CombodoTooltip.InitAllNonInstantiatedTooltips($('#ibo-dashboard-selector$sDivId').parent());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
EOF
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$sSelectorHtml = addslashes($sSelectorHtml);
|
|
||||||
$oPage->add_script(<<<JS
|
|
||||||
$(".ibo-top-bar--toolbar-dashboard-selector").replaceWith("$sSelectorHtml");
|
|
||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1076,12 +1104,8 @@ JS
|
|||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
|
protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $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');
|
||||||
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||||
@@ -1089,52 +1113,46 @@ JS
|
|||||||
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
||||||
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
|
||||||
$sName = 'UI:Dashboard:Actions';
|
$sName = 'UI:Dashboard:Actions';
|
||||||
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
|
||||||
$oActionButton = ButtonFactory::MakeLinkNeutral('', '', 'fas fa-ellipsis-v', $sName, '', $sMenuTogglerId);
|
$bFromDashboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
|
||||||
$oActionButton->AddCSSClasses("ibo-top-bar--toolbar-dashboard-menu-toggler");
|
if ($bFromDashboardPage) {
|
||||||
|
if (!($oPage instanceof iTopWebPage)) {
|
||||||
|
// TODO 3.0 change the menu
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$oToolbar = $oPage->GetTopBarLayout()->GetToolbar();
|
||||||
|
} else {
|
||||||
|
$oToolbar = $oDashboard->GetToolbar();
|
||||||
|
}
|
||||||
|
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S($sName), $sName, '', false, $sMenuTogglerId)
|
||||||
|
->AddCSSClass('ibo-top-bar--toolbar-dashboard-menu-toggler')
|
||||||
|
->AddCSSClass('ibo-action-button');
|
||||||
|
|
||||||
$oToolbar->AddSubBlock($oActionButton);
|
$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;
|
|
||||||
if ($this->HasCustomDashboard()) {
|
if ($this->HasCustomDashboard()) {
|
||||||
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
|
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||||
}
|
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||||
if ($bCanEdit) {
|
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:DeleteCustom'),
|
||||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
||||||
|
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
||||||
|
} else {
|
||||||
|
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
|
||||||
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->bCustomized) {
|
|
||||||
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
|
|
||||||
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
|
|
||||||
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
|
||||||
|
|
||||||
$oToolbar->AddSubBlock($oPage->GetPopoverMenu($sPopoverMenuId, $aActions));
|
$oActionsMenu = $oPage->GetPopoverMenu($sPopoverMenuId, $aActions)
|
||||||
$oActionButton->AddCSSClasses('ibo-action-button')
|
->SetTogglerJSSelector("#$sMenuTogglerId")
|
||||||
->SetJsCode(<<<JS
|
->SetContainer(PopoverMenu::ENUM_CONTAINER_BODY);
|
||||||
$("#{$sPopoverMenuId}").popover_menu({toggler: "#{$sMenuTogglerId}"});
|
|
||||||
$('#{$sMenuTogglerId}').on('click', function(oEvent) {
|
$oToolbar->AddSubBlock($oActionButton)
|
||||||
var oEventTarget = $('#{$sMenuTogglerId}');
|
->AddSubBlock($oActionsMenu);
|
||||||
var aEventTargetPos = oEventTarget.position();
|
|
||||||
var popover = $("#{$sPopoverMenuId}");
|
|
||||||
|
|
||||||
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();
|
$sReloadURL = $this->GetReloadURL();
|
||||||
$oPage->add_script(
|
$oPage->add_script(
|
||||||
@@ -1172,7 +1190,7 @@ EOF
|
|||||||
|
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#select_layout input').click( function() {
|
$('#select_layout input').on('click', function() {
|
||||||
var sLayoutClass = $(this).val();
|
var sLayoutClass = $(this).val();
|
||||||
$('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass});
|
$('.itop-dashboard').runtimedashboard('option', {layout_class: sLayoutClass});
|
||||||
} );
|
} );
|
||||||
@@ -1211,30 +1229,27 @@ EOF
|
|||||||
*/
|
*/
|
||||||
public function RenderEditor($oPage, $aExtraParams = array())
|
public function RenderEditor($oPage, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
if (isset($aExtraParams['this->class']))
|
if (isset($aExtraParams['this->class'])) {
|
||||||
{
|
|
||||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||||
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aRenderParams = $aExtraParams;
|
$aRenderParams = $aExtraParams;
|
||||||
}
|
}
|
||||||
$aRenderParams['dashboard_div_id'] = $aExtraParams['dashboard_div_id'];
|
$aRenderParams['dashboard_div_id'] = $aExtraParams['dashboard_div_id'];
|
||||||
$sJSExtraParams = json_encode($aExtraParams);
|
$sJSExtraParams = json_encode($aExtraParams);
|
||||||
$oPage->add('<div id="dashboard_editor">');
|
$oPage->add('<div id="dashboard_editor" class="ibo-dashboard-editor" data-role="ibo-dashboard-editor">');
|
||||||
$oPage->add('<div class="ui-layout-center">');
|
$oPage->add('<div class="ui-layout-center">');
|
||||||
$this->SetCustomFlag(true);
|
$this->SetCustomFlag(true);
|
||||||
$this->Render($oPage, true, $aRenderParams);
|
$this->Render($oPage, true, $aRenderParams);
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
$oPage->add('<div class="ui-layout-east">');
|
$oPage->add('<div class="ui-layout-east ibo-dashboard-editor--pane" data-role="ibo-dashboard-editor--pane">');
|
||||||
$this->RenderProperties($oPage, $aExtraParams);
|
$this->RenderProperties($oPage, $aExtraParams);
|
||||||
$this->RenderDashletsSelection($oPage);
|
$this->RenderDashletsSelection($oPage);
|
||||||
$this->RenderDashletsProperties($oPage, $aExtraParams);
|
$this->RenderDashletsProperties($oPage, $aExtraParams);
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
|
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
|
|
||||||
$sDialogTitle = Dict::S('UI:DashboardEdit:Title');
|
$sDialogTitle = Dict::S('UI:DashboardEdit:Title');
|
||||||
$sOkButtonLabel = Dict::S('UI:Button:Save');
|
$sOkButtonLabel = Dict::S('UI:Button:Save');
|
||||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||||
@@ -1262,7 +1277,24 @@ $('#dashboard_editor').dialog({
|
|||||||
modal: true,
|
modal: true,
|
||||||
title: '$sDialogTitle',
|
title: '$sDialogTitle',
|
||||||
buttons: [
|
buttons: [
|
||||||
{ text: "$sOkButtonLabel", click: function() {
|
{ text: "$sCancelButtonLabel",
|
||||||
|
class: "ibo-is-alternative",
|
||||||
|
click: function() {
|
||||||
|
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
||||||
|
if (oDashboard.is_modified())
|
||||||
|
{
|
||||||
|
if (!confirm('$sCancelConfirmationMessage'))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.bLeavingOnUserAction = true;
|
||||||
|
$(this).dialog( "close" );
|
||||||
|
$(this).remove();
|
||||||
|
} },
|
||||||
|
{ text: "$sOkButtonLabel",
|
||||||
|
class: "ibo-is-primary",
|
||||||
|
click: function() {
|
||||||
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
||||||
if (oDashboard.is_dirty())
|
if (oDashboard.is_dirty())
|
||||||
{
|
{
|
||||||
@@ -1278,19 +1310,6 @@ $('#dashboard_editor').dialog({
|
|||||||
window.bLeavingOnUserAction = true;
|
window.bLeavingOnUserAction = true;
|
||||||
oDashboard.save($(this));
|
oDashboard.save($(this));
|
||||||
} },
|
} },
|
||||||
{ text: "$sCancelButtonLabel", click: function() {
|
|
||||||
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
|
|
||||||
if (oDashboard.is_modified())
|
|
||||||
{
|
|
||||||
if (!confirm('$sCancelConfirmationMessage'))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.bLeavingOnUserAction = true;
|
|
||||||
$(this).dialog( "close" );
|
|
||||||
$(this).remove();
|
|
||||||
} },
|
|
||||||
],
|
],
|
||||||
close: function() { $(this).remove(); }
|
close: function() { $(this).remove(); }
|
||||||
});
|
});
|
||||||
@@ -1308,20 +1327,16 @@ $('#dashboard_editor .ui-layout-center').runtimedashboard({
|
|||||||
new_dashlet_parameters: {operation: 'new_dashlet'}
|
new_dashlet_parameters: {operation: 'new_dashlet'}
|
||||||
});
|
});
|
||||||
|
|
||||||
dashboard_prop_size = GetUserPreference('dashboard_prop_size', 350);
|
var dashboard_prop_size = GetUserPreference('dashboard_prop_size', 400);
|
||||||
$('#dashboard_editor').layout({
|
$('#dashboard_editor > .itop-dashboard').width($('#dashboard_editor').width() - dashboard_prop_size);
|
||||||
east: {
|
|
||||||
minSize: 200,
|
// We check when we finish click on the pane with the resize slider
|
||||||
size: dashboard_prop_size,
|
// if the pane size changed (% 5px), if it's the case we save the value in userpref
|
||||||
togglerLength_open: 0,
|
$('#dashboard_editor > .itop-dashboard').on('mouseup',function (){
|
||||||
togglerLength_closed: 0,
|
var iWidthDiff = $(this).width() - ($('#dashboard_editor').width() - dashboard_prop_size);
|
||||||
onresize_end: function(name, elt, state, options, layout)
|
if( Math.abs(iWidthDiff) > 5){
|
||||||
{
|
dashboard_prop_size = iWidthDiff;
|
||||||
if (state.isSliding == false)
|
SetUserPreference('dashboard_prop_size', $('#dashboard_editor').width() - $(this).width(), true);
|
||||||
{
|
|
||||||
SetUserPreference('dashboard_prop_size', state.size, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1483,32 +1498,37 @@ JS
|
|||||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||||
|
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<JS
|
<<<JS
|
||||||
$('#dashlet_creation_dlg').dialog({
|
$('#dashlet_creation_dlg').dialog({
|
||||||
width: 600,
|
width: 600,
|
||||||
modal: true,
|
modal: true,
|
||||||
title: '$sDialogTitle',
|
title: '$sDialogTitle',
|
||||||
buttons: [
|
buttons: [
|
||||||
{ text: "$sOkButtonLabel", click: function() {
|
{ text: "$sCancelButtonLabel",
|
||||||
var oForm = $(this).find('form');
|
click: function() {
|
||||||
var sFormId = oForm.attr('id');
|
|
||||||
var oParams = null;
|
|
||||||
var aErrors = ValidateForm(sFormId, false);
|
|
||||||
if (aErrors.length == 0)
|
|
||||||
{
|
|
||||||
oParams = ReadFormParams(sFormId);
|
|
||||||
}
|
|
||||||
oParams.operation = 'add_dashlet';
|
|
||||||
var me = $(this);
|
|
||||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
|
|
||||||
me.dialog( "close" );
|
|
||||||
me.remove();
|
|
||||||
$('body').append(data);
|
|
||||||
});
|
|
||||||
} },
|
|
||||||
{ text: "$sCancelButtonLabel", click: function() {
|
|
||||||
$(this).dialog( "close" ); $(this).remove();
|
$(this).dialog( "close" ); $(this).remove();
|
||||||
} },
|
} ,
|
||||||
|
'class': 'ibo-button ibo-is-alternative ibo-is-neutral action cancel'
|
||||||
|
},
|
||||||
|
{ text: "$sOkButtonLabel",
|
||||||
|
click: function() {
|
||||||
|
var oForm = $(this).find('form');
|
||||||
|
var sFormId = oForm.attr('id');
|
||||||
|
var oParams = null;
|
||||||
|
var aErrors = ValidateForm(sFormId, false);
|
||||||
|
if (aErrors.length == 0)
|
||||||
|
{
|
||||||
|
oParams = ReadFormParams(sFormId);
|
||||||
|
}
|
||||||
|
oParams.operation = 'add_dashlet';
|
||||||
|
var me = $(this);
|
||||||
|
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
|
||||||
|
me.dialog( "close" );
|
||||||
|
me.remove();
|
||||||
|
$('body').append(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
'class': 'ibo-button ibo-is-regular ibo-is-primary action' }
|
||||||
],
|
],
|
||||||
close: function() { $(this).remove(); }
|
close: function() { $(this).remove(); }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -15,15 +15,15 @@
|
|||||||
//
|
//
|
||||||
// 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\Base\Component\Html\Html;
|
||||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardColumn;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn;
|
||||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardLayout as UIDashboardLayout;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
|
||||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardRow;
|
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard presentation
|
* Dashboard presentation
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
abstract class DashboardLayout
|
abstract class DashboardLayout
|
||||||
@@ -116,12 +116,15 @@ 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);
|
||||||
|
|
||||||
$oDashboardLayout = new UIDashboardLayout();
|
$oDashboardLayout = new DashboardLayoutUIBlock();
|
||||||
$oPage->AddUiBlock($oDashboardLayout);
|
//$oPage->AddUiBlock($oDashboardLayout);
|
||||||
|
|
||||||
$iCellIdx = 0;
|
$iCellIdx = 0;
|
||||||
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||||
|
|
||||||
|
//Js given by each dashlet to reload
|
||||||
|
$sJSReload = "";
|
||||||
|
|
||||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||||
$oDashboardRow = new DashboardRow();
|
$oDashboardRow = new DashboardRow();
|
||||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||||
@@ -148,8 +151,11 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
}
|
}
|
||||||
$iCellIdx++;
|
$iCellIdx++;
|
||||||
}
|
}
|
||||||
|
$sJSReload .= $oDashboardRow->GetJSRefreshCallback()." ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}");
|
||||||
|
|
||||||
if ($bEditMode) // Add one row for extensibility
|
if ($bEditMode) // Add one row for extensibility
|
||||||
{
|
{
|
||||||
$oDashboardRow = new DashboardRow();
|
$oDashboardRow = new DashboardRow();
|
||||||
@@ -161,7 +167,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
|||||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
return $oDashboardLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2012-2018 Combodo SARL
|
// Copyright (C) 2012-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -16,19 +16,19 @@
|
|||||||
// 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\Base\Component\Dashlet\DashletContainer;
|
||||||
use Combodo\iTop\Application\UI\Component\Dashlet\DashletFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Dashlet\DashletFactory;
|
||||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||||
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\iUIBlock;
|
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||||
use Combodo\iTop\Application\UI\UIBlock;
|
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||||
|
|
||||||
require_once(APPROOT.'application/forms.class.inc.php');
|
require_once(APPROOT.'application/forms.class.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all 'dashlets' (i.e. widgets to be inserted into a dashboard)
|
* Base class for all 'dashlets' (i.e. widgets to be inserted into a dashboard)
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
abstract class Dashlet
|
abstract class Dashlet
|
||||||
@@ -212,20 +212,16 @@ abstract class Dashlet
|
|||||||
{
|
{
|
||||||
$sId = $this->GetID();
|
$sId = $this->GetID();
|
||||||
|
|
||||||
$sCSSClasses = implode(' ', $this->aCSSClasses);
|
|
||||||
if ($bEnclosingDiv) {
|
if ($bEnclosingDiv) {
|
||||||
if ($bEditMode) {
|
if ($bEditMode) {
|
||||||
$oDashletContainer = new DashletContainer("dashlet_{$sId}");
|
$oDashletContainer = new DashletContainer("dashlet_{$sId}");
|
||||||
} else {
|
} else {
|
||||||
$oDashletContainer = new DashletContainer();
|
$oDashletContainer = new DashletContainer();
|
||||||
}
|
}
|
||||||
$oDashletContainer->AddCSSClasses($sCSSClasses);
|
$oDashletContainer->AddCSSClasses($this->aCSSClasses);
|
||||||
} else {
|
} else {
|
||||||
$oDashletContainer = new DashletContainer();
|
$oDashletContainer = new DashletContainer();
|
||||||
|
$oDashletContainer->AddCSSClasses($this->aCSSClasses);
|
||||||
foreach ($this->aCSSClasses as $sCSSClass) {
|
|
||||||
$oPage->add_ready_script("$('#dashlet_".$sId."').addClass('$sCSSClass');");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -239,14 +235,14 @@ abstract class Dashlet
|
|||||||
// 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");
|
$oDashletContainer->AddCSSClass("dashlet-content");
|
||||||
$oDashletContainer->AddHtml('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
$oDashletContainer->AddHtml('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
||||||
}
|
}
|
||||||
} catch (OqlException $e) {
|
} catch (OqlException $e) {
|
||||||
$oDashletContainer->AddCSSClasses("dashlet-content");
|
$oDashletContainer->AddCSSClass("dashlet-content");
|
||||||
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
|
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$oDashletContainer->AddCSSClasses("dashlet-content");
|
$oDashletContainer->AddCSSClass("dashlet-content");
|
||||||
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
|
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,17 +438,21 @@ EOF
|
|||||||
$sAttType = $aTargetAttCodes[$sTargetAttCode];
|
$sAttType = $aTargetAttCodes[$sTargetAttCode];
|
||||||
$sExtFieldAttCode = $sTargetAttCode;
|
$sExtFieldAttCode = $sTargetAttCode;
|
||||||
}
|
}
|
||||||
if (is_a($sAttType, 'AttributeLinkedSet', true))
|
|
||||||
{
|
$aForbidenAttType = [
|
||||||
continue;
|
'AttributeLinkedSet',
|
||||||
}
|
'AttributeFriendlyName',
|
||||||
if (is_a($sAttType, 'AttributeFriendlyName', true))
|
|
||||||
{
|
'iAttributeNoGroupBy', //we cannot only use iAttributeNoGroupBy since this method is also used by the designer who do not have access to the classes' PHP reflection API. So the known classes has to be listed altogether
|
||||||
continue;
|
'AttributeOneWayPassword',
|
||||||
}
|
'AttributeEncryptedString',
|
||||||
if (is_a($sAttType, 'AttributeOneWayPassword', true))
|
'AttributePassword',
|
||||||
{
|
];
|
||||||
continue;
|
foreach ($aForbidenAttType as $sForbidenAttType) {
|
||||||
|
if (is_a($sAttType, $sForbidenAttType, true))
|
||||||
|
{
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
|
$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
|
||||||
@@ -602,7 +602,7 @@ 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');
|
||||||
|
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||||
@@ -622,7 +622,7 @@ 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());
|
||||||
|
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||||
@@ -746,7 +746,7 @@ 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.
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
$oDashletContainer->AddHtml('<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>');
|
||||||
return $oDashletContainer;
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
@@ -763,7 +763,7 @@ 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());
|
||||||
|
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$sHtml = '';
|
$sHtml = '';
|
||||||
$sHtml .= '<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>';
|
$sHtml .= '<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>';
|
||||||
@@ -848,12 +848,13 @@ class DashletPlainText extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$sText = utils::HtmlEntities($this->aProperties['text']);
|
$sText = $this->aProperties['text'];
|
||||||
|
$sText = utils::EscapeHtml($sText);
|
||||||
$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;
|
||||||
|
|
||||||
return DashletFactory::MakeForDashletText($sId, $sText);
|
return DashletFactory::MakeForDashletPlainText($sText, $sId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -873,7 +874,7 @@ class DashletPlainText extends Dashlet
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletPlainText:Label'),
|
'label' => Dict::S('UI:DashletPlainText:Label'),
|
||||||
'icon' => 'images/dashlet-text.png',
|
'icon' => 'images/dashlets/icons8-text-box-48.png',
|
||||||
'description' => Dict::S('UI:DashletPlainText:Description'),
|
'description' => Dict::S('UI:DashletPlainText:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -903,14 +904,17 @@ class DashletObjectList extends Dashlet
|
|||||||
{
|
{
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
$sShowMenu = $this->aProperties['menu'] ? '1' : '0';
|
$sShowMenu = $this->aProperties['menu'] ? '1' : '0';
|
||||||
|
|
||||||
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
|
||||||
|
|
||||||
$oFilter = $this->GetDBSearch($aExtraParams);
|
$oFilter = $this->GetDBSearch($aExtraParams);
|
||||||
|
$sClass = $oFilter->GetClass();
|
||||||
|
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, Dict::S($sTitle))
|
||||||
|
->AddCSSClass('ibo-datatable-panel');
|
||||||
|
|
||||||
$oBlock = new DisplayBlock($oFilter, 'list');
|
$oBlock = new DisplayBlock($oFilter, 'list');
|
||||||
$aParams = array(
|
$aParams = array(
|
||||||
'menu' => $sShowMenu,
|
'menu' => $sShowMenu,
|
||||||
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
|
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
|
||||||
|
'surround_with_panel' => false,
|
||||||
|
'max_height' => '500px',
|
||||||
);
|
);
|
||||||
$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->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||||
@@ -923,24 +927,36 @@ class DashletObjectList extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
|
$oDashletContainer = new DashletContainer($this->sId, ['dashlet-content']);
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
$sQuery = $this->aProperties['query'];
|
$sQuery = $this->aProperties['query'];
|
||||||
$bShowMenu = $this->aProperties['menu'];
|
$bShowMenu = $this->aProperties['menu'];
|
||||||
|
$sHtmlTitle = utils::HtmlEntities($this->oModelReflection->DictString($sTitle));
|
||||||
$oPage->add('<div class="dashlet-content">');
|
|
||||||
$sHtmlTitle = utils::HtmlEntities($this->oModelReflection->DictString($sTitle)); // done in the itop block
|
|
||||||
if ($sHtmlTitle != '') {
|
if ($sHtmlTitle != '') {
|
||||||
$oPage->add('<h1>'.$sHtmlTitle.'</h1>');
|
$sHtmlTitle = '<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">');
|
$sId = $this->sId;
|
||||||
$oPage->p(Dict::S('UI:NoObjectToDisplay'));
|
$sMessage = Dict::S('UI:NoObjectToDisplay');
|
||||||
|
$sMenu = '';
|
||||||
if ($bShowMenu) {
|
if ($bShowMenu) {
|
||||||
$oPage->p('<a>'.Dict::Format('UI:ClickToCreateNew', $this->oModelReflection->GetName($sClass)).'</a>');
|
$sMenu = '<p><a>'.Dict::Format('UI:ClickToCreateNew', $this->oModelReflection->GetName($sClass)).'</a></p>';
|
||||||
}
|
}
|
||||||
$oPage->add('</div>');
|
|
||||||
$oPage->add('</div>');
|
$sHtml = <<<HTML
|
||||||
|
<div class="dashlet-content">
|
||||||
|
<h1>$sHtmlTitle</h1>
|
||||||
|
<div id="block_fake_$sId" class="display_block">
|
||||||
|
<p>$sMessage</p>
|
||||||
|
$sMenu
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
|
|
||||||
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
|
||||||
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetDBSearch($aExtraParams = array())
|
public function GetDBSearch($aExtraParams = array())
|
||||||
@@ -981,7 +997,7 @@ class DashletObjectList extends Dashlet
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletObjectList:Label'),
|
'label' => Dict::S('UI:DashletObjectList:Label'),
|
||||||
'icon' => 'images/dashlet-list.png',
|
'icon' => 'images/dashlets/icons8-list-48.png',
|
||||||
'description' => Dict::S('UI:DashletObjectList:Description'),
|
'description' => Dict::S('UI:DashletObjectList:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1240,7 +1256,7 @@ abstract class DashletGroupBy extends Dashlet
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, Dict::S($sTitle));
|
||||||
|
|
||||||
|
|
||||||
$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)
|
||||||
@@ -1332,7 +1348,7 @@ abstract class DashletGroupBy extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
$oDashletContainer->AddHtml('error!');
|
$oDashletContainer->AddHtml('error!');
|
||||||
return $oDashletContainer;
|
return $oDashletContainer;
|
||||||
}
|
}
|
||||||
@@ -1581,7 +1597,7 @@ abstract class DashletGroupBy extends Dashlet
|
|||||||
// Note: no need to translate, should never be visible to the end-user!
|
// Note: no need to translate, should never be visible to the end-user!
|
||||||
return array(
|
return array(
|
||||||
'label' => 'Objects grouped by...',
|
'label' => 'Objects grouped by...',
|
||||||
'icon' => 'images/dashlet-object-grouped.png',
|
'icon' => 'images/dashlets/icons8-transaction-list-48.png',
|
||||||
'description' => 'Grouped objects dashlet (abstract)',
|
'description' => 'Grouped objects dashlet (abstract)',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1645,7 +1661,7 @@ class DashletGroupByPie extends DashletGroupBy
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletGroupByPie:Label'),
|
'label' => Dict::S('UI:DashletGroupByPie:Label'),
|
||||||
'icon' => 'images/dashlet-pie-chart.png',
|
'icon' => 'images/dashlets/icons8-pie-chart-48.png',
|
||||||
'description' => Dict::S('UI:DashletGroupByPie:Description'),
|
'description' => Dict::S('UI:DashletGroupByPie:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1655,7 +1671,7 @@ 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');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
|
|
||||||
@@ -1720,7 +1736,7 @@ class DashletGroupByBars extends DashletGroupBy
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletGroupByBars:Label'),
|
'label' => Dict::S('UI:DashletGroupByBars:Label'),
|
||||||
'icon' => 'images/dashlet-bar-chart.png',
|
'icon' => 'images/dashlets/icons8-bar-chart-48.png',
|
||||||
'description' => Dict::S('UI:DashletGroupByBars:Description'),
|
'description' => Dict::S('UI:DashletGroupByBars:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1730,7 +1746,7 @@ 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');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$sTitle = $this->aProperties['title'];
|
$sTitle = $this->aProperties['title'];
|
||||||
|
|
||||||
@@ -1821,7 +1837,7 @@ class DashletGroupByTable extends DashletGroupBy
|
|||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletGroupByTable:Label'),
|
'label' => Dict::S('UI:DashletGroupByTable:Label'),
|
||||||
'description' => Dict::S('UI:DashletGroupByTable:Description'),
|
'description' => Dict::S('UI:DashletGroupByTable:Description'),
|
||||||
'icon' => 'images/dashlet-groupby-table.png',
|
'icon' => 'images/dashlets/icons8-transaction-list-48.png',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1890,7 +1906,7 @@ class DashletHeaderStatic extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$sTitle = utils::HtmlEntities($this->aProperties['title']);
|
$sTitle = $this->aProperties['title'];
|
||||||
$sIcon = $this->aProperties['icon'];
|
$sIcon = $this->aProperties['icon'];
|
||||||
|
|
||||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||||
@@ -1950,7 +1966,7 @@ class DashletHeaderStatic extends Dashlet
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletHeaderStatic:Label'),
|
'label' => Dict::S('UI:DashletHeaderStatic:Label'),
|
||||||
'icon' => 'images/dashlet-header.png',
|
'icon' => 'images/dashlets/icons8-header-48.png',
|
||||||
'description' => Dict::S('UI:DashletHeaderStatic:Description'),
|
'description' => Dict::S('UI:DashletHeaderStatic:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2020,7 +2036,7 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$sGroupBy = $this->aProperties['group_by'];
|
$sGroupBy = $this->aProperties['group_by'];
|
||||||
|
|
||||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
$sIconPath = $oIconSelect->MakeFileUrl($sIcon);
|
||||||
|
|
||||||
$aValues = $this->GetValues();
|
$aValues = $this->GetValues();
|
||||||
if (count($aValues) > 0) {
|
if (count($aValues) > 0) {
|
||||||
@@ -2042,8 +2058,6 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPanel = PanelFactory::MakeEnhancedNeutral(Dict::S(str_replace('_', ':', $sTitle)), $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'])) {
|
||||||
@@ -2053,11 +2067,17 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$aQueryParams = array();
|
$aQueryParams = array();
|
||||||
}
|
}
|
||||||
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||||
|
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
|
$sClass = $oFilter->GetClass();
|
||||||
|
|
||||||
|
$oPanel = PanelUIBlockFactory::MakeNeutral(Dict::S(str_replace('_', ':', $sTitle)))
|
||||||
|
->SetIcon($sIconPath)
|
||||||
|
->SetColorFromClass($sClass);
|
||||||
$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->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||||
|
|
||||||
$oSubTitle = $oPanel->GetSubTitle();
|
$oSubTitle = $oPanel->GetSubTitleBlock();
|
||||||
$oSet = new DBObjectSet($oFilter);
|
$oSet = new DBObjectSet($oFilter);
|
||||||
$iCount = $oSet->Count();
|
$iCount = $oSet->Count();
|
||||||
$oAppContext = new ApplicationContext();
|
$oAppContext = new ApplicationContext();
|
||||||
@@ -2078,13 +2098,25 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$sQuery = $this->aProperties['query'];
|
$sQuery = $this->aProperties['query'];
|
||||||
$sGroupBy = $this->aProperties['group_by'];
|
$sGroupBy = $this->aProperties['group_by'];
|
||||||
|
|
||||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
$aValueLabels = [];
|
||||||
$sClass = $oQuery->GetClass();
|
$aValues = [];
|
||||||
|
try {
|
||||||
|
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||||
|
$sClass = $oQuery->GetClass();
|
||||||
|
$aValues = $this->GetValues();
|
||||||
|
foreach ($aValues as $sValue) {
|
||||||
|
$aValueLabels[] = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnknownClassOqlException $e) {
|
||||||
|
$aValueLabels[] = $e->GetUserFriendlyDescription();
|
||||||
|
$aValues[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||||
|
|
||||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
|
||||||
|
|
||||||
$sHtml = '';
|
$sHtml = '';
|
||||||
$sHtml .= '<img src="'.$sIconPath.'">';
|
$sHtml .= '<img src="'.$sIconPath.'">';
|
||||||
@@ -2092,20 +2124,18 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$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();
|
|
||||||
|
|
||||||
$sHtml .= '<div class="display_block" id="'.$sBlockId.'">';
|
$sHtml .= '<div class="display_block" id="'.$sBlockId.'">';
|
||||||
$sHtml .= '<div class="summary-details">';
|
$sHtml .= '<div class="summary-details">';
|
||||||
$sHtml .= '<table><tbody>';
|
$sHtml .= '<table><tbody>';
|
||||||
$sHtml .= '<tr>';
|
$sHtml .= '<tr>';
|
||||||
foreach ($aValues as $sValue) {
|
foreach ($aValueLabels as $sValueLabel) {
|
||||||
$sValueLabel = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
|
|
||||||
$sHtml .= ' <th>'.$sValueLabel.'</th>';
|
$sHtml .= ' <th>'.$sValueLabel.'</th>';
|
||||||
}
|
}
|
||||||
$sHtml .= '</tr>';
|
$sHtml .= '</tr>';
|
||||||
$sHtml .= '<tr>';
|
$sHtml .= '<tr>';
|
||||||
foreach ($aValues as $sValue) {
|
foreach ($aValues as $sValue) {
|
||||||
$iCount = (int)rand(2, 100);
|
$iCount = rand(2, 100);
|
||||||
$iTotal += $iCount;
|
$iTotal += $iCount;
|
||||||
$sHtml .= ' <td>'.$iCount.'</td>';
|
$sHtml .= ' <td>'.$iCount.'</td>';
|
||||||
}
|
}
|
||||||
@@ -2120,7 +2150,6 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
$sHtml .= '<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>';
|
$sHtml .= '<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>';
|
||||||
$sHtml .= '</div>';
|
$sHtml .= '</div>';
|
||||||
|
|
||||||
$sHtml .= '</div>';
|
|
||||||
|
|
||||||
$oDashletContainer->AddHtml($sHtml);
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
|
||||||
@@ -2254,7 +2283,7 @@ class DashletHeaderDynamic extends Dashlet
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletHeaderDynamic:Label'),
|
'label' => Dict::S('UI:DashletHeaderDynamic:Label'),
|
||||||
'icon' => 'images/dashlet-header-stats.png',
|
'icon' => 'images/dashlets/icons8-header-altered-48.png',
|
||||||
'description' => Dict::S('UI:DashletHeaderDynamic:Description'),
|
'description' => Dict::S('UI:DashletHeaderDynamic:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2281,12 +2310,13 @@ 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');
|
$oDashletContainer = new DashletContainer($this->sId, ['dashlet-content']);
|
||||||
|
|
||||||
$sClass = $this->aProperties['class'];
|
$sClass = $this->aProperties['class'];
|
||||||
$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;
|
||||||
|
$aExtraParams['withJSRefreshCallBack'] = true;
|
||||||
$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->DisplayIntoContentBlock($oDashletContainer, $oPage, $sBlockId, $aExtraParams);
|
$oBlock->DisplayIntoContentBlock($oDashletContainer, $oPage, $sBlockId, $aExtraParams);
|
||||||
|
|
||||||
@@ -2298,21 +2328,22 @@ class DashletBadge extends Dashlet
|
|||||||
*/
|
*/
|
||||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$oDashletContainer = new DashletContainer($this->sId, 'dashlet-content');
|
$oDashletContainer = new DashletContainer($this->sId, ['dashlet-content']);
|
||||||
|
|
||||||
$sClass = $this->aProperties['class'];
|
$sClass = $this->aProperties['class'];
|
||||||
$sIconUrl = $this->oModelReflection->GetClassIcon($sClass, false);
|
$sIconUrl = utils::HtmlEntities($this->oModelReflection->GetClassIcon($sClass, false));
|
||||||
$sClassLabel = $this->oModelReflection->GetName($sClass);
|
$sClassLabel = $this->oModelReflection->GetName($sClass);
|
||||||
|
$sId = $this->sId;
|
||||||
|
$sClassCreate = Dict::Format('UI:ClickToCreateNew', $sClassLabel);
|
||||||
|
|
||||||
$sHtml = '';
|
$sHtml = <<<HTML
|
||||||
$sHtml .= '<div id="block_fake_'.$this->sId.'" class="display_block">';
|
<div id="block_fake_$sId" class="display_block">
|
||||||
$sHtml .= '<p>';
|
<div class="ibo-dashlet-badge--body" data-role="ibo-dashlet-badge--body" title="$sClassLabel">
|
||||||
$sHtml .= ' <a class="actions"><img src="'.utils::HtmlEntities($sIconUrl).'" style="vertical-align:middle;float;left;margin-right:10px;border:0;">'.$sClassLabel.': 947</a>';
|
<div class="ibo-dashlet-badge--icon-container"><img class="ibo-dashlet-badge--icon" src="$sIconUrl"></div>
|
||||||
$sHtml .= '</p>';
|
<div class="ibo-dashlet-badge--actions"><a class="ibo-dashlet-badge--action-list" href="#" data-role="ibo-dashlet-badge--action-list"><span class="ibo-dashlet-badge--action-list-count">4</span><span class="ibo-dashlet-badge--action-list-label">$sClassLabel</span></a><a class="ibo-dashlet-badge--action-create" href="#"><span class="ibo-dashlet-badge--action-create-icon fas fa-plus"></span><span class="ibo-dashlet-badge--action-create-label"> $sClassCreate </span></a></div>
|
||||||
$sHtml .= '<p>';
|
</div>
|
||||||
$sHtml .= ' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>';
|
</div>
|
||||||
$sHtml .= '</p>';
|
HTML;
|
||||||
$sHtml .= '</div>';
|
|
||||||
|
|
||||||
$oDashletContainer->AddHtml($sHtml);
|
$oDashletContainer->AddHtml($sHtml);
|
||||||
|
|
||||||
@@ -2366,7 +2397,7 @@ class DashletBadge extends Dashlet
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'label' => Dict::S('UI:DashletBadge:Label'),
|
'label' => Dict::S('UI:DashletBadge:Label'),
|
||||||
'icon' => 'images/dashlet-badge.png',
|
'icon' => 'images/dashlets/icons8-badge-48.png',
|
||||||
'description' => Dict::S('UI:DashletBadge:Description'),
|
'description' => Dict::S('UI:DashletBadge:Description'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<parent>WelcomeMenu</parent>
|
<parent>WelcomeMenu</parent>
|
||||||
<definition>
|
<definition>
|
||||||
<layout>DashboardLayoutOneCol</layout>
|
<layout>DashboardLayoutOneCol</layout>
|
||||||
<title/>
|
<title>Menu:WelcomeMenuPage</title>
|
||||||
<cells>
|
<cells>
|
||||||
<cell id="0">
|
<cell id="0">
|
||||||
<rank>0</rank>
|
<rank>0</rank>
|
||||||
@@ -237,6 +237,27 @@
|
|||||||
</argument>
|
</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</method>
|
</method>
|
||||||
|
<method id="AddValue">
|
||||||
|
<arguments>
|
||||||
|
<argument id="1">
|
||||||
|
<type>attcode</type>
|
||||||
|
<mandatory>true</mandatory>
|
||||||
|
<type_restrictions>
|
||||||
|
<operation>allow</operation>
|
||||||
|
<types>
|
||||||
|
<type id="AttributeInteger"/>
|
||||||
|
<type id="AttributeDecimal"/>
|
||||||
|
<type id="AttributePercentage"/>
|
||||||
|
<type id="AttributeDuration"/>
|
||||||
|
</types>
|
||||||
|
</type_restrictions>
|
||||||
|
</argument>
|
||||||
|
<argument id="2">
|
||||||
|
<type>string</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
</argument>
|
||||||
|
</arguments>
|
||||||
|
</method>
|
||||||
<method id="SetCurrentDate">
|
<method id="SetCurrentDate">
|
||||||
<arguments>
|
<arguments>
|
||||||
<argument id="1">
|
<argument id="1">
|
||||||
@@ -253,6 +274,22 @@
|
|||||||
</argument>
|
</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</method>
|
</method>
|
||||||
|
<method id="SetCurrentDateIfNull">
|
||||||
|
<arguments>
|
||||||
|
<argument id="1">
|
||||||
|
<type>attcode</type>
|
||||||
|
<mandatory>true</mandatory>
|
||||||
|
<type_restrictions>
|
||||||
|
<operation>allow</operation>
|
||||||
|
<types>
|
||||||
|
<type id="AttributeDate"/>
|
||||||
|
<type id="AttributeDateTime"/>
|
||||||
|
<type id="AttributeString"/>
|
||||||
|
</types>
|
||||||
|
</type_restrictions>
|
||||||
|
</argument>
|
||||||
|
</arguments>
|
||||||
|
</method>
|
||||||
<method id="SetCurrentUser">
|
<method id="SetCurrentUser">
|
||||||
<arguments>
|
<arguments>
|
||||||
<argument id="1">
|
<argument id="1">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Combodo\iTop\Renderer\BlockRenderer;
|
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,8 @@ use Combodo\iTop\Renderer\BlockRenderer;
|
|||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
*
|
||||||
|
* @deprecated since 3.0.0 use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DataTable
|
class DataTable
|
||||||
@@ -46,6 +48,7 @@ class DataTable
|
|||||||
*/
|
*/
|
||||||
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
|
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use Combodo\iTop\Application\UI\Base\Component\DataTable\Datatable');
|
||||||
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
|
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
|
||||||
$this->sDatatableContainerId = 'datatable_'.utils::GetSafeId($iListId);
|
$this->sDatatableContainerId = 'datatable_'.utils::GetSafeId($iListId);
|
||||||
$this->oSet = $oSet;
|
$this->oSet = $oSet;
|
||||||
@@ -113,8 +116,7 @@ class DataTable
|
|||||||
// See if this column is a must to load
|
// See if this column is a must to load
|
||||||
$sClass = $this->aClassAliases[$sAlias];
|
$sClass = $this->aClassAliases[$sAlias];
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
if ($oAttDef->alwaysLoadInTables())
|
if ($oAttDef->AlwaysLoadInTables()) {
|
||||||
{
|
|
||||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,26 +352,26 @@ EOF;
|
|||||||
* @param $aExtraParams
|
* @param $aExtraParams
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @throws \ApplicationException
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
* @throws \DictExceptionMissingString
|
* @throws \DictExceptionMissingString
|
||||||
* @throws \MissingQueryArgument
|
* @throws \MissingQueryArgument
|
||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
* @throws \OQLException
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws \Twig\Error\LoaderError
|
||||||
|
* @throws \Twig\Error\RuntimeError
|
||||||
|
* @throws \Twig\Error\SyntaxError
|
||||||
*/
|
*/
|
||||||
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
||||||
|
|
||||||
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
||||||
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 ConsoleBlockRenderer::RenderBlockTemplateInPage($oPage, $oBlock);
|
||||||
return BlockRenderer::RenderBlockTemplates($oBlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||||
9
application/exceptions/ApplicationException.php
Normal file
9
application/exceptions/ApplicationException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ApplicationException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
14
application/exceptions/ArchivedObjectException.php
Normal file
14
application/exceptions/ArchivedObjectException.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when querying on an object that exists in the database but is archived
|
||||||
|
*
|
||||||
|
* @since 2.5.1 N°1108
|
||||||
|
*/
|
||||||
|
class ArchivedObjectException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/BulkChangeException.php
Normal file
9
application/exceptions/BulkChangeException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BulkChangeException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/CSVParserException.php
Normal file
9
application/exceptions/CSVParserException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CSVParserException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/ConfigException.php
Normal file
9
application/exceptions/ConfigException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ConfigException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
77
application/exceptions/CoreCannotSaveObjectException.php
Normal file
77
application/exceptions/CoreCannotSaveObjectException.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CoreCannotSaveObjectException
|
||||||
|
*
|
||||||
|
* Specialized exception to raise if {@link DBObject::CheckToWrite()} fails, which allow easy data retrieval
|
||||||
|
*
|
||||||
|
* @see \DBObject::DBInsertNoReload()
|
||||||
|
* @see \DBObject::DBUpdate()
|
||||||
|
*
|
||||||
|
* @since 2.6.0 N°659 uniqueness constraint
|
||||||
|
*/
|
||||||
|
class CoreCannotSaveObjectException extends CoreException
|
||||||
|
{
|
||||||
|
/** @var string[] */
|
||||||
|
private $aIssues;
|
||||||
|
/** @var int */
|
||||||
|
private $iObjectId;
|
||||||
|
/** @var string */
|
||||||
|
private $sObjectClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CoreCannotSaveObjectException constructor.
|
||||||
|
*
|
||||||
|
* @param array $aContextData containing at least those keys : issues, id, class
|
||||||
|
*/
|
||||||
|
public function __construct($aContextData, $oPrevious = null)
|
||||||
|
{
|
||||||
|
$this->aIssues = $aContextData['issues'];
|
||||||
|
$this->iObjectId = $aContextData['id'];
|
||||||
|
$this->sObjectClass = $aContextData['class'];
|
||||||
|
|
||||||
|
$sIssues = implode(', ', $this->aIssues);
|
||||||
|
parent::__construct($sIssues, $aContextData, '', $oPrevious);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHtmlMessage()
|
||||||
|
{
|
||||||
|
$sTitle = Dict::S('UI:Error:SaveFailed');
|
||||||
|
$sContent = "<span><strong>{$sTitle}</strong></span>";
|
||||||
|
|
||||||
|
if (count($this->aIssues) == 1) {
|
||||||
|
$sIssue = reset($this->aIssues);
|
||||||
|
$sContent .= " <span>{$sIssue}</span>";
|
||||||
|
} else {
|
||||||
|
$sContent .= '<ul>';
|
||||||
|
foreach ($this->aIssues as $sError) {
|
||||||
|
$sContent .= "<li>$sError</li>";
|
||||||
|
}
|
||||||
|
$sContent .= '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIssues()
|
||||||
|
{
|
||||||
|
return $this->aIssues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObjectId()
|
||||||
|
{
|
||||||
|
return $this->iObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObjectClass()
|
||||||
|
{
|
||||||
|
return $this->sObjectClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
108
application/exceptions/CoreException.php
Normal file
108
application/exceptions/CoreException.php
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CoreException extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* CoreException constructor.
|
||||||
|
*
|
||||||
|
* @param string $sIssue error message
|
||||||
|
* @param array|null $aContextData key/value array, value MUST implements _toString
|
||||||
|
* @param string $sImpact
|
||||||
|
* @param Exception|null $oPrevious
|
||||||
|
*/
|
||||||
|
public function __construct($sIssue, $aContextData = null, $sImpact = '', $oPrevious = null)
|
||||||
|
{
|
||||||
|
$this->m_sIssue = $sIssue;
|
||||||
|
$this->m_sImpact = $sImpact;
|
||||||
|
|
||||||
|
if (is_array($aContextData)) {
|
||||||
|
$this->m_aContextData = $aContextData;
|
||||||
|
} else {
|
||||||
|
$this->m_aContextData = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$sMessage = $sIssue;
|
||||||
|
if (!empty($sImpact)) {
|
||||||
|
$sMessage .= "($sImpact)";
|
||||||
|
}
|
||||||
|
if (count($this->m_aContextData) > 0) {
|
||||||
|
$sMessage .= ": ";
|
||||||
|
$aContextItems = array();
|
||||||
|
foreach ($this->m_aContextData as $sKey => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$aPairs = array();
|
||||||
|
foreach ($value as $key => $val) {
|
||||||
|
if (is_array($val)) {
|
||||||
|
$aPairs[] = $key.'=>('.implode(', ', $val).')';
|
||||||
|
} else {
|
||||||
|
$aPairs[] = $key.'=>'.$val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sValue = '{'.implode('; ', $aPairs).'}';
|
||||||
|
} else {
|
||||||
|
$sValue = $value;
|
||||||
|
}
|
||||||
|
$aContextItems[] = "$sKey = $sValue";
|
||||||
|
}
|
||||||
|
$sMessage .= implode(', ', $aContextItems);
|
||||||
|
}
|
||||||
|
parent::__construct($sMessage, 0, $oPrevious);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string code and message for log purposes
|
||||||
|
*/
|
||||||
|
public function getInfoLog()
|
||||||
|
{
|
||||||
|
return 'error_code='.$this->getCode().', message="'.$this->getMessage().'"';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
|
||||||
|
{
|
||||||
|
return $this->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTraceAsString() cannot be overrided and it is limited as only current exception stack is returned.
|
||||||
|
* we need stack of all previous exceptions
|
||||||
|
*
|
||||||
|
* @uses __tostring() already does the work.
|
||||||
|
* @since 2.7.2/ 3.0.0
|
||||||
|
*/
|
||||||
|
public function getFullStackTraceAsString()
|
||||||
|
{
|
||||||
|
return "".$this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTraceAsHtml()
|
||||||
|
{
|
||||||
|
$aBackTrace = $this->getTrace();
|
||||||
|
|
||||||
|
return MyHelpers::get_callstack_html(0, $this->getTrace());
|
||||||
|
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addInfo($sKey, $value)
|
||||||
|
{
|
||||||
|
$this->m_aContextData[$sKey] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIssue()
|
||||||
|
{
|
||||||
|
return $this->m_sIssue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImpact()
|
||||||
|
{
|
||||||
|
return $this->m_sImpact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContextData()
|
||||||
|
{
|
||||||
|
return $this->m_aContextData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0 N°2555
|
||||||
|
*/
|
||||||
|
class CorePortalInvalidActionRuleException extends CoreException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
17
application/exceptions/CoreTemplateException.php
Normal file
17
application/exceptions/CoreTemplateException.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0 N°3522
|
||||||
|
*/
|
||||||
|
class CoreTemplateException extends CoreException
|
||||||
|
{
|
||||||
|
public function __construct(Exception $oTwigException, string $sTemplatePath)
|
||||||
|
{
|
||||||
|
$sMessage = "Twig Exception when rendering '$sTemplatePath' : ".$oTwigException->getMessage();
|
||||||
|
parent::__construct($sMessage, null, '', $oTwigException);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
application/exceptions/CoreUnexpectedValue.php
Normal file
9
application/exceptions/CoreUnexpectedValue.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CoreUnexpectedValue extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/CoreWarning.php
Normal file
9
application/exceptions/CoreWarning.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CoreWarning extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/DeleteException.php
Normal file
9
application/exceptions/DeleteException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DeleteException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
14
application/exceptions/InvalidConfigParamException.php
Normal file
14
application/exceptions/InvalidConfigParamException.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter stored in the {@link Config} is invalid
|
||||||
|
*
|
||||||
|
* @since 2.7.0
|
||||||
|
*/
|
||||||
|
class InvalidConfigParamException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when the password is not valid
|
||||||
|
*
|
||||||
|
* @since 2.7.0
|
||||||
|
*/
|
||||||
|
class InvalidPasswordAttributeOneWayPassword extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
13
application/exceptions/PageNotFoundException.php
Normal file
13
application/exceptions/PageNotFoundException.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Combodo\iTop\Application\TwigBase\Controller;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class PageNotFoundException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/SecurityException.php
Normal file
9
application/exceptions/SecurityException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SecurityException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/SynchroExceptionNotStarted.php
Normal file
9
application/exceptions/SynchroExceptionNotStarted.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SynchroExceptionNotStarted extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/UserRightException.php
Normal file
9
application/exceptions/UserRightException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class UserRightException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
9
application/exceptions/dict/DictException.php
Normal file
9
application/exceptions/dict/DictException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DictException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
16
application/exceptions/dict/DictExceptionMissingString.php
Normal file
16
application/exceptions/dict/DictExceptionMissingString.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DictExceptionMissingString extends DictException
|
||||||
|
{
|
||||||
|
public function __construct($sLanguageCode, $sStringCode)
|
||||||
|
{
|
||||||
|
$aContext = array();
|
||||||
|
$aContext['language_code'] = $sLanguageCode;
|
||||||
|
$aContext['string_code'] = $sStringCode;
|
||||||
|
parent::__construct('Missing localized string', $aContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
application/exceptions/dict/DictExceptionUnknownLanguage.php
Normal file
15
application/exceptions/dict/DictExceptionUnknownLanguage.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DictExceptionUnknownLanguage extends DictException
|
||||||
|
{
|
||||||
|
public function __construct($sLanguageCode)
|
||||||
|
{
|
||||||
|
$aContext = array();
|
||||||
|
$aContext['language_code'] = $sLanguageCode;
|
||||||
|
parent::__construct('Unknown localization language', $aContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
application/exceptions/mysql/MySQLException.php
Normal file
39
application/exceptions/mysql/MySQLException.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MySQLException extends CoreException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* MySQLException constructor.
|
||||||
|
*
|
||||||
|
* @param string $sIssue
|
||||||
|
* @param array $aContext
|
||||||
|
* @param \Exception $oException
|
||||||
|
* @param \mysqli $oMysqli to use when working with a custom mysqli instance
|
||||||
|
*/
|
||||||
|
public function __construct($sIssue, $aContext, $oException = null, $oMysqli = null)
|
||||||
|
{
|
||||||
|
if ($oException != null) {
|
||||||
|
$aContext['mysql_errno'] = $oException->getCode();
|
||||||
|
$this->code = $oException->getCode();
|
||||||
|
$aContext['mysql_error'] = $oException->getMessage();
|
||||||
|
} else if ($oMysqli != null) {
|
||||||
|
$aContext['mysql_errno'] = $oMysqli->errno;
|
||||||
|
$this->code = $oMysqli->errno;
|
||||||
|
$aContext['mysql_error'] = $oMysqli->error;
|
||||||
|
} else {
|
||||||
|
$aContext['mysql_errno'] = CMDBSource::GetErrNo();
|
||||||
|
$this->code = CMDBSource::GetErrNo();
|
||||||
|
$aContext['mysql_error'] = CMDBSource::GetError();
|
||||||
|
}
|
||||||
|
parent::__construct($sIssue, $aContext);
|
||||||
|
//if is connection error, don't log the default message with password in
|
||||||
|
if (mysqli_connect_errno()) {
|
||||||
|
error_log($this->message);
|
||||||
|
error_reporting(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
application/exceptions/mysql/MySQLHasGoneAwayException.php
Normal file
32
application/exceptions/mysql/MySQLHasGoneAwayException.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MySQLHasGoneAwayException
|
||||||
|
*
|
||||||
|
* @see https://dev.mysql.com/doc/refman/5.7/en/gone-away.html
|
||||||
|
* @since 2.5.0 N°1195
|
||||||
|
*/
|
||||||
|
class MySQLHasGoneAwayException extends MySQLException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* can not be a constant before PHP 5.6 (http://php.net/manual/fr/language.oop5.constants.php)
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
public static function getErrorCodes()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
2006,
|
||||||
|
2013,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct($sIssue, $aContext)
|
||||||
|
{
|
||||||
|
parent::__construct($sIssue, $aContext, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
application/exceptions/mysql/MySQLNoTransactionException.php
Normal file
13
application/exceptions/mysql/MySQLNoTransactionException.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0 N°679
|
||||||
|
*/
|
||||||
|
class MySQLNoTransactionException extends MySQLException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MySQLQueryHasNoResultException
|
||||||
|
*
|
||||||
|
* @since 2.5.0
|
||||||
|
*/
|
||||||
|
class MySQLQueryHasNoResultException extends MySQLException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
application/exceptions/oql/CoreOqlException.php
Normal file
13
application/exceptions/oql/CoreOqlException.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0 N°2555
|
||||||
|
*/
|
||||||
|
class CoreOqlException extends CoreException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0 N°2555
|
||||||
|
*/
|
||||||
|
class CoreOqlMultipleResultsForbiddenException extends CoreOqlException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
15
application/exceptions/process/ProcessException.php
Normal file
15
application/exceptions/process/ProcessException.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception for {@link iProcess} implementations.<br>
|
||||||
|
* An error happened during the processing but we can go on with the next implementations.
|
||||||
|
*
|
||||||
|
* @since 2.5.0 N°1195
|
||||||
|
*/
|
||||||
|
class ProcessException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
16
application/exceptions/process/ProcessFatalException.php
Normal file
16
application/exceptions/process/ProcessFatalException.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ProcessFatalException
|
||||||
|
* Exception for iProcess implementations.<br>
|
||||||
|
* A big error occurred, we have to stop the iProcess processing.
|
||||||
|
*
|
||||||
|
* @since 2.5.0 N°1195
|
||||||
|
*/
|
||||||
|
class ProcessFatalException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0 PR #89
|
||||||
|
*/
|
||||||
|
class ProcessInvalidConfigException extends ProcessException
|
||||||
|
{
|
||||||
|
}
|
||||||
114
application/findstylesheetobject.class.inc.php
Normal file
114
application/findstylesheetobject.class.inc.php
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
|
*
|
||||||
|
* This file is part of iTop.
|
||||||
|
*
|
||||||
|
* iTop is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* iTop is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FindStylesheetObject: dedicated class to store computations made in method ThemeHandler::FindStylesheetFile.
|
||||||
|
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||||
|
* @since 3.0.0 N°3588
|
||||||
|
*/
|
||||||
|
class FindStylesheetObject{
|
||||||
|
|
||||||
|
//file URIs
|
||||||
|
private $aStylesheetFileURIs;
|
||||||
|
|
||||||
|
//fill paths
|
||||||
|
private $aStylesheetImportPaths;
|
||||||
|
private $aAllStylesheetFilePaths;
|
||||||
|
private $sLastStyleSheetPath;
|
||||||
|
|
||||||
|
private $iLastModified;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FindStylesheetObject constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->aStylesheetFileURIs = [];
|
||||||
|
$this->aStylesheetImportPaths = [];
|
||||||
|
$this->aAllStylesheetFilePaths = [];
|
||||||
|
$this->sLastStyleSheetPath = "";
|
||||||
|
$this->iLastModified = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetLastStylesheetFile(): string
|
||||||
|
{
|
||||||
|
return $this->sLastStyleSheetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetImportPaths(): array
|
||||||
|
{
|
||||||
|
return $this->aStylesheetImportPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array : main stylesheets URIs
|
||||||
|
*/
|
||||||
|
public function GetStylesheetFileURIs(): array
|
||||||
|
{
|
||||||
|
return $this->aStylesheetFileURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetLastModified() : int
|
||||||
|
{
|
||||||
|
return $this->iLastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array : main stylesheets paths + included files paths
|
||||||
|
*/
|
||||||
|
public function GetAllStylesheetPaths(): array
|
||||||
|
{
|
||||||
|
return $this->aAllStylesheetFilePaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string : last found stylesheet URI
|
||||||
|
*/
|
||||||
|
public function GetLastStyleSheetPath(): string
|
||||||
|
{
|
||||||
|
return $this->sLastStyleSheetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AddStylesheet(string $sStylesheetFileURI, string $sStylesheetFilePath): void
|
||||||
|
{
|
||||||
|
$this->aStylesheetFileURIs[] = $sStylesheetFileURI;
|
||||||
|
$this->aAllStylesheetFilePaths[] = $sStylesheetFilePath;
|
||||||
|
$this->sLastStyleSheetPath = $sStylesheetFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AlreadyFetched(string $sStylesheetFilePath) : bool {
|
||||||
|
return in_array($sStylesheetFilePath, $this->aAllStylesheetFilePaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AddImport(string $sStylesheetFileURI, string $sStylesheetFilePath): void
|
||||||
|
{
|
||||||
|
$this->aStylesheetImportPaths[$sStylesheetFileURI] = $sStylesheetFilePath;
|
||||||
|
$this->aAllStylesheetFilePaths[] = $sStylesheetFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function UpdateLastModified(string $sStylesheetFile): void
|
||||||
|
{
|
||||||
|
$this->iLastModified = max($this->iLastModified, @filemtime($sStylesheetFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ResetLastStyleSheet(): void
|
||||||
|
{
|
||||||
|
$this->sLastStyleSheetPath = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* Helper class to build interactive forms to be used either in stand-alone
|
* Helper class to build interactive forms to be used either in stand-alone
|
||||||
* modal dialog or in "property-sheet" panes.
|
* modal dialog or in "property-sheet" panes.
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
class DesignerForm
|
class DesignerForm
|
||||||
@@ -102,23 +102,19 @@ class DesignerForm
|
|||||||
$sReturn .= '<fieldset>';
|
$sReturn .= '<fieldset>';
|
||||||
$sReturn .= '<legend>'.$sLabel.'</legend>';
|
$sReturn .= '<legend>'.$sLabel.'</legend>';
|
||||||
}
|
}
|
||||||
foreach($aFields as $oField)
|
foreach($aFields as $oField) {
|
||||||
{
|
|
||||||
$aRow = $oField->Render($oP, $sFormId);
|
$aRow = $oField->Render($oP, $sFormId);
|
||||||
if ($oField->IsVisible())
|
if ($oField->IsVisible()) {
|
||||||
{
|
$sValidation = '<span class="prop_apply ibo-prop--apply">'.$this->GetValidationArea($oField->GetFieldId()).'</span>';
|
||||||
$sValidation = ' <span class="prop_apply">'.$this->GetValidationArea($oField->GetFieldId()).'</span>';
|
|
||||||
$sField = $aRow['value'].$sValidation;
|
$sField = $aRow['value'].$sValidation;
|
||||||
$aDetails[] = array('label' => $aRow['label'], 'value' => $sField);
|
$aDetails[] = array('label' => $aRow['label'], 'value' => $sField);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sHiddenFields .= $aRow['value'];
|
$sHiddenFields .= $aRow['value'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sReturn .= $oP->GetDetails($aDetails);
|
$sReturn .= $oP->GetDetails($aDetails);
|
||||||
if ($sLabel != '')
|
|
||||||
{
|
if ($sLabel != '') {
|
||||||
$sReturn .= '</fieldset>';
|
$sReturn .= '</fieldset>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,18 +226,18 @@ class DesignerForm
|
|||||||
if ($oField->IsVisible())
|
if ($oField->IsVisible())
|
||||||
{
|
{
|
||||||
$sFieldId = $this->GetFieldId($oField->GetCode());
|
$sFieldId = $this->GetFieldId($oField->GetCode());
|
||||||
$sValidation = $this->GetValidationArea($sFieldId, '<span title="Apply" class="ui-icon ui-icon-circle-check"/>');
|
$sValidation = $this->GetValidationArea($sFieldId, '<span data-tooltip-content="Apply"><i class="fas fa-check"></i></span>');
|
||||||
$sValidationFields = '</td><td class="prop_icon prop_apply">'.$sValidation.'</td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td>'.$this->EndRow();
|
$sValidationFields = '</td><td class="prop_icon prop_apply ibo-prop--apply">'.$sValidation.'</td><td class="prop_icon prop_cancel ibo-prop--cancel"><span data-tooltip-content="Revert"><i class="fas fa-times"></i></span></td>'.$this->EndRow();
|
||||||
|
|
||||||
$sPath = $this->GetHierarchyPath().'/'.$oField->GetCode();
|
$sPath = $this->GetHierarchyPath().'/'.$oField->GetCode();
|
||||||
|
|
||||||
if (is_null($aRow['label']))
|
if (is_null($aRow['label']))
|
||||||
{
|
{
|
||||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_value" colspan="2">'.$aRow['value'];
|
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_value ibo-field--value" colspan="2">'.$aRow['value'];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_label">'.$aRow['label'].'</td><td class="prop_value">'.$aRow['value'];
|
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_label ibo-field--label">'.$aRow['label'].'</td><td class="prop_value ibo-field--value">'.$aRow['value'];
|
||||||
}
|
}
|
||||||
if (!($oField instanceof DesignerFormSelectorField) && !($oField instanceof DesignerMultipleSubFormField))
|
if (!($oField instanceof DesignerFormSelectorField) && !($oField instanceof DesignerMultipleSubFormField))
|
||||||
{
|
{
|
||||||
@@ -266,6 +262,7 @@ class DesignerForm
|
|||||||
$this->AddReadyScript(
|
$this->AddReadyScript(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#row_$sFieldId').$sWidgetClass({parent_selector: $sNotifyParentSelectorJS, field_id: '$sFieldId', equals: $sHandlerEquals, get_field_value: $sHandlerGetValue, auto_apply: $sAutoApply, value: '', submit_to: '$sActionUrl', submit_parameters: $sJSSubmitParams $sJSExtraParams });
|
$('#row_$sFieldId').$sWidgetClass({parent_selector: $sNotifyParentSelectorJS, field_id: '$sFieldId', equals: $sHandlerEquals, get_field_value: $sHandlerGetValue, auto_apply: $sAutoApply, value: '', submit_to: '$sActionUrl', submit_parameters: $sJSSubmitParams $sJSExtraParams });
|
||||||
|
CombodoTooltip.InitTooltipFromMarkup($('#$sFormId [data-tooltip-content]'));
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -291,7 +288,6 @@ EOF
|
|||||||
}
|
}
|
||||||
$this->AddReadyScript(
|
$this->AddReadyScript(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('.prop_table').tableHover();
|
|
||||||
var idx = 0;
|
var idx = 0;
|
||||||
$('.prop_table tbody tr').each(function() {
|
$('.prop_table tbody tr').each(function() {
|
||||||
if ((idx % 2) == 0)
|
if ((idx % 2) == 0)
|
||||||
@@ -548,7 +544,7 @@ EOF
|
|||||||
|
|
||||||
public function GetValidationArea($sId, $sContent = '')
|
public function GetValidationArea($sId, $sContent = '')
|
||||||
{
|
{
|
||||||
return "<span style=\"display:inline-block;width:20px;\" id=\"v_{$sId}\"><span class=\"ui-icon ui-icon-alert\"></span>$sContent</span>";
|
return "<span id=\"v_{$sId}\">$sContent</span>";
|
||||||
}
|
}
|
||||||
public function GetAsyncActionClass()
|
public function GetAsyncActionClass()
|
||||||
{
|
{
|
||||||
@@ -716,7 +712,7 @@ class DesignerFormField
|
|||||||
$this->bMandatory = false;
|
$this->bMandatory = false;
|
||||||
$this->bReadOnly = false;
|
$this->bReadOnly = false;
|
||||||
$this->bAutoApply = false;
|
$this->bAutoApply = false;
|
||||||
$this->aCSSClasses = array();
|
$this->aCSSClasses = array('ibo-input');
|
||||||
$this->bDisplayed = true;
|
$this->bDisplayed = true;
|
||||||
$this->aWidgetExtraParams = array();
|
$this->aWidgetExtraParams = array();
|
||||||
}
|
}
|
||||||
@@ -1020,10 +1016,10 @@ class DesignerTextField extends DesignerFormField
|
|||||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
$('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||||
{
|
{
|
||||||
var myTimer = null;
|
var myTimer = null;
|
||||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -1055,6 +1051,12 @@ EOF
|
|||||||
|
|
||||||
class DesignerLongTextField extends DesignerTextField
|
class DesignerLongTextField extends DesignerTextField
|
||||||
{
|
{
|
||||||
|
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||||
|
{
|
||||||
|
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||||
|
$this->aCSSClasses[] = 'ibo-input-text';
|
||||||
|
}
|
||||||
|
|
||||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||||
{
|
{
|
||||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||||
@@ -1078,10 +1080,10 @@ class DesignerLongTextField extends DesignerTextField
|
|||||||
{
|
{
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
$('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
||||||
{
|
{
|
||||||
var myTimer = null;
|
var myTimer = null;
|
||||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -1129,10 +1131,10 @@ class DesignerIntegerField extends DesignerFormField
|
|||||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change keyup validate', function() { ValidateInteger('$sId', $sMandatory, $(this).closest('form').attr('id'), $sMin, $sMax); } );
|
$('#$sId').on('change keyup validate', function() { ValidateInteger('$sId', $sMandatory, $(this).closest('form').attr('id'), $sMin, $sMax); } );
|
||||||
{
|
{
|
||||||
var myTimer = null;
|
var myTimer = null;
|
||||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
$('#$sId').on('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -1178,6 +1180,7 @@ class DesignerComboField extends DesignerFormField
|
|||||||
$this->bMultipleSelection = false;
|
$this->bMultipleSelection = false;
|
||||||
$this->bOtherChoices = false;
|
$this->bOtherChoices = false;
|
||||||
$this->sNullLabel = Dict::S('UI:SelectOne');
|
$this->sNullLabel = Dict::S('UI:SelectOne');
|
||||||
|
$this->aCSSClasses[] = 'ibo-input-select';
|
||||||
|
|
||||||
$this->bAutoApply = true;
|
$this->bAutoApply = true;
|
||||||
$this->bSorted = true; // Sorted by default
|
$this->bSorted = true; // Sorted by default
|
||||||
@@ -1292,11 +1295,12 @@ class DesignerComboField extends DesignerFormField
|
|||||||
}
|
}
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change validate', function() { ValidateWithPattern('$sId', $sMandatory, '', $(this).closest('form').attr('id'), null, null); } );
|
$('#$sId').on('change validate', function() { ValidateWithPattern('$sId', $sMandatory, '', $(this).closest('form').attr('id'), null, null); } );
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return array('label' => $this->sLabel, 'value' => $sHtml);
|
return array('label' => $this->sLabel, 'value' => $sHtml);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ReadParam(&$aValues)
|
public function ReadParam(&$aValues)
|
||||||
@@ -1315,6 +1319,7 @@ class DesignerBooleanField extends DesignerFormField
|
|||||||
{
|
{
|
||||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||||
$this->bAutoApply = true;
|
$this->bAutoApply = true;
|
||||||
|
$this->aCSSClasses[] = 'ibo-input-checkbox';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||||
@@ -1597,6 +1602,7 @@ class DesignerFormSelectorField extends DesignerFormField
|
|||||||
$this->defaultRealValue = $defaultValue;
|
$this->defaultRealValue = $defaultValue;
|
||||||
$this->aSubForms = array();
|
$this->aSubForms = array();
|
||||||
$this->bSorted = true;
|
$this->bSorted = true;
|
||||||
|
$this->aCSSClasses[] = 'ibo-input-select';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsSorted()
|
public function IsSorted()
|
||||||
@@ -1730,7 +1736,7 @@ class DesignerFormSelectorField extends DesignerFormField
|
|||||||
{
|
{
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change reverted', function() { $('.subform_{$sId}').hide(); $('.{$sId}_'+this.value).show(); } );
|
$('#$sId').on('change reverted', function() { $('.subform_{$sId}').hide(); $('.{$sId}_'+this.value).show(); } );
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
/**
|
/**
|
||||||
* Persistent class InputOutputTask
|
* Persistent class InputOutputTask
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWebPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||||
|
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader');
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
/**
|
/**
|
||||||
* Class LoginBasic
|
* Class LoginBasic
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Class LoginExternal
|
* Class LoginExternal
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Class LoginURL
|
* Class LoginURL
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
/**
|
/**
|
||||||
* Class LoginWebPage
|
* Class LoginWebPage
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -84,10 +84,8 @@ class LoginWebPage extends NiceWebPage
|
|||||||
|
|
||||||
parent::__construct($sTitle);
|
parent::__construct($sTitle);
|
||||||
$this->SetStyleSheet();
|
$this->SetStyleSheet();
|
||||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
$this->no_cache();
|
||||||
$this->add_header('Pragma: no-cache');
|
$this->add_xframe_options();
|
||||||
$this->add_header('Expires: 0');
|
|
||||||
$this->add_header('X-Frame-Options: deny');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetStyleSheet()
|
public function SetStyleSheet()
|
||||||
@@ -724,7 +722,7 @@ class LoginWebPage extends NiceWebPage
|
|||||||
|
|
||||||
public static function HTTPReload()
|
public static function HTTPReload()
|
||||||
{
|
{
|
||||||
$sOriginURL = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
$sOriginURL = utils::GetCurrentAbsoluteUrl();
|
||||||
if (!utils::StartsWith($sOriginURL, utils::GetAbsoluteUrlAppRoot()))
|
if (!utils::StartsWith($sOriginURL, utils::GetAbsoluteUrlAppRoot()))
|
||||||
{
|
{
|
||||||
// If the found URL does not start with the configured AppRoot URL
|
// If the found URL does not start with the configured AppRoot URL
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2019 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,23 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2013-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* This file is part of iTop.
|
|
||||||
*
|
|
||||||
* iTop is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* iTop is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\UI\Component\Title\TitleFactory;
|
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||||
|
|
||||||
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');
|
||||||
@@ -342,15 +329,17 @@ class ApplicationMenu
|
|||||||
*/
|
*/
|
||||||
public static function DisplayMenu($oPage, $aExtraParams)
|
public static function DisplayMenu($oPage, $aExtraParams)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetMenuGroups() instead');
|
||||||
self::LoadAdditionalMenus();
|
self::LoadAdditionalMenus();
|
||||||
// Sort the root menu based on the rank
|
// Sort the root menu based on the rank
|
||||||
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
|
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
|
||||||
$iAccordion = 0;
|
$iAccordion = 0;
|
||||||
$iActiveAccordion = $iAccordion;
|
$iActiveAccordion = $iAccordion;
|
||||||
$iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
|
$iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
|
||||||
foreach(self::$aRootMenus as $aMenu)
|
foreach (self::$aRootMenus as $aMenu) {
|
||||||
{
|
if (!self::CanDisplayMenu($aMenu)) {
|
||||||
if (!self::CanDisplayMenu($aMenu)) { continue; }
|
continue;
|
||||||
|
}
|
||||||
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
||||||
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$oMenuNode->GetMenuID()).'" class="navigation-menu-group" data-menu-id="'.$oMenuNode->GetMenuId().'">'.$oMenuNode->GetTitle().'</h3>');
|
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$oMenuNode->GetMenuID()).'" class="navigation-menu-group" data-menu-id="'.$oMenuNode->GetMenuId().'">'.$oMenuNode->GetTitle().'</h3>');
|
||||||
$oPage->AddToMenu('<div>');
|
$oPage->AddToMenu('<div>');
|
||||||
@@ -418,13 +407,12 @@ EOF
|
|||||||
*/
|
*/
|
||||||
protected static function DisplaySubMenu($oPage, $aMenus, $aExtraParams, $iActiveMenu = -1)
|
protected static function DisplaySubMenu($oPage, $aMenus, $aExtraParams, $iActiveMenu = -1)
|
||||||
{
|
{
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('use static::GetSubMenuNodes() instead');
|
||||||
// Sort the menu based on the rank
|
// Sort the menu based on the rank
|
||||||
$bActive = false;
|
$bActive = false;
|
||||||
usort($aMenus, array('ApplicationMenu', 'CompareOnRank'));
|
usort($aMenus, array('ApplicationMenu', 'CompareOnRank'));
|
||||||
foreach($aMenus as $aMenu)
|
foreach ($aMenus as $aMenu) {
|
||||||
{
|
if (!self::CanDisplayMenu($aMenu)) {
|
||||||
if (!self::CanDisplayMenu($aMenu))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$index = $aMenu['index'];
|
$index = $aMenu['index'];
|
||||||
@@ -723,6 +711,22 @@ abstract class MenuNode
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function GetEntriesCountFromOQL(string $sOQL)
|
||||||
|
{
|
||||||
|
// Count the entries up to 99
|
||||||
|
$oSearch = DBSearch::FromOQL($sOQL);
|
||||||
|
|
||||||
|
DBSearchHelper::AddContextFilter($oSearch);
|
||||||
|
|
||||||
|
$oSet = new DBObjectSet($oSearch);
|
||||||
|
$iCount = $oSet->CountWithLimit(99);
|
||||||
|
if ($iCount > 99) {
|
||||||
|
$iCount = "99+";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $iCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of entries of the page corresponding to this menu item.
|
* Get the number of entries of the page corresponding to this menu item.
|
||||||
*
|
*
|
||||||
@@ -1130,8 +1134,8 @@ class OQLMenuNode extends MenuNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
//$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'>");
|
$oPage->add("<div class='sf_results_area' data-target='search_results'>");
|
||||||
$oTitle = TitleFactory::MakeForPage($sTitle);
|
$oTitle = TitleUIBlockFactory::MakeForPage($sTitle);
|
||||||
$oPage->AddUiBlock($oTitle);
|
$oPage->AddUiBlock($oTitle);
|
||||||
|
|
||||||
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
|
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
|
||||||
@@ -1139,7 +1143,7 @@ class OQLMenuNode extends MenuNode
|
|||||||
$oBlock->Display($oPage, $sUsageId);
|
$oBlock->Display($oPage, $sUsageId);
|
||||||
|
|
||||||
$oPage->add("</div>");
|
$oPage->add("</div>");
|
||||||
|
|
||||||
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage)) {
|
if ($bEnableBreadcrumb && ($oPage instanceof iTopWebPage)) {
|
||||||
// Breadcrumb
|
// Breadcrumb
|
||||||
//$iCount = $oBlock->GetDisplayedCount();
|
//$iCount = $oBlock->GetDisplayedCount();
|
||||||
@@ -1156,15 +1160,7 @@ class OQLMenuNode extends MenuNode
|
|||||||
|
|
||||||
public function GetEntriesCount()
|
public function GetEntriesCount()
|
||||||
{
|
{
|
||||||
// Count the entries up to 99
|
return $this->GetEntriesCountFromOQL($this->sOQL);
|
||||||
|
|
||||||
$oSet = new DBObjectSet(DBSearch::FromOQL($this->sOQL));
|
|
||||||
$iCount = $oSet->CountWithLimit(99);
|
|
||||||
if ($iCount > 99) {
|
|
||||||
$iCount = "99+";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $iCount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1420,37 +1416,29 @@ 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="ibo-dashboard" id="'.$sDivId.'">');
|
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
|
||||||
$aExtraParams['dashboard_div_id'] = $sDivId;
|
$aExtraParams['dashboard_div_id'] = $sDivId;
|
||||||
|
$aExtraParams['from_dashboard_page'] = true;
|
||||||
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
|
||||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
|
|
||||||
$bEdit = utils::ReadParam('edit', false);
|
$bEdit = utils::ReadParam('edit', false);
|
||||||
if ($bEdit)
|
if ($bEdit) {
|
||||||
{
|
|
||||||
$sId = addslashes($this->sMenuId);
|
$sId = addslashes($this->sMenuId);
|
||||||
$oPage->add_ready_script("EditDashboard('$sId');");
|
$oPage->add_ready_script("EditDashboard('$sId');");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
$oParentMenu = ApplicationMenu::GetMenuNode($this->iParentIndex);
|
||||||
$sParentTitle = $oParentMenu->GetTitle();
|
$sParentTitle = $oParentMenu->GetTitle();
|
||||||
$sThisTitle = $this->GetTitle();
|
$sThisTitle = $this->GetTitle();
|
||||||
if ($sParentTitle != $sThisTitle)
|
if ($sParentTitle != $sThisTitle) {
|
||||||
{
|
|
||||||
$sDescription = $sParentTitle.' / '.$sThisTitle;
|
$sDescription = $sParentTitle.' / '.$sThisTitle;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sDescription = $sThisTitle;
|
$sDescription = $sThisTitle;
|
||||||
}
|
}
|
||||||
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId())
|
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId()) {
|
||||||
{
|
|
||||||
$sIcon = 'fas fa-home';
|
$sIcon = 'fas fa-home';
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sIcon = 'fas fa-chart-pie';
|
$sIcon = 'fas fa-chart-pie';
|
||||||
}
|
}
|
||||||
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||||
@@ -1622,5 +1610,23 @@ class ShortcutMenuNode extends MenuNode
|
|||||||
{
|
{
|
||||||
return $this->oShortcut->Get('name');
|
return $this->oShortcut->Get('name');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the page corresponding to this menu node is countable
|
||||||
|
*
|
||||||
|
* @return bool true if corresponding page is countable
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public function HasCount()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function GetEntriesCount()
|
||||||
|
{
|
||||||
|
return $this->GetEntriesCountFromOQL($this->oShortcut->Get('oql'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2015 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader');
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader');
|
||||||
@@ -1,33 +1,34 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2015 Combodo SARL
|
/*
|
||||||
//
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
// This file is part of iTop.
|
|
||||||
//
|
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// iTop is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent class Event and derived
|
|
||||||
* Application internal events
|
|
||||||
* There is also a file log
|
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
* This file is part of iTop.
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
*
|
||||||
|
* iTop is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* iTop is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\Field\Field;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||||
|
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
|
||||||
|
|
||||||
abstract class Query extends cmdbAbstractObject
|
abstract class Query extends cmdbAbstractObject
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @throws \CoreException
|
||||||
|
* @since 3.0.0 N°3227 add is_template field for predefined queries
|
||||||
|
*/
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
$aParams = array
|
$aParams = array
|
||||||
@@ -42,17 +43,39 @@ abstract class Query extends cmdbAbstractObject
|
|||||||
"db_finalclass_field" => "realclass",
|
"db_finalclass_field" => "realclass",
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
//MetaModel::Init_InheritAttributes();
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
|
||||||
|
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeString("name", array(
|
||||||
|
"allowed_values" => null,
|
||||||
|
"sql" => "name",
|
||||||
|
"default_value" => null,
|
||||||
|
"is_null_allowed" => false,
|
||||||
|
"depends_on" => array(),
|
||||||
|
)));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeText("description", array(
|
||||||
|
"allowed_values" => null,
|
||||||
|
"sql" => "description",
|
||||||
|
"default_value" => null,
|
||||||
|
"is_null_allowed" => false,
|
||||||
|
"depends_on" => array(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeEnum("is_template", array(
|
||||||
|
'allowed_values' => new ValueSetEnum('yes,no'),
|
||||||
|
'sql' => 'is_template',
|
||||||
|
'default_value' => 'no',
|
||||||
|
'is_null_allowed' => false,
|
||||||
|
'depends_on' => [],
|
||||||
|
'display_style' => 'radio_horizontal',
|
||||||
|
)));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', array('name', 'description')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details',
|
||||||
|
array('name', 'is_template', 'description')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', array('name', 'description')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'is_template')); // Criteria of the std search form
|
||||||
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
|
MetaModel::Init_SetZListItems('default_search',
|
||||||
|
array('name', 'description', 'is_template')); // Criteria of the default search form
|
||||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,58 +90,73 @@ class QueryOQL extends Query
|
|||||||
"key_type" => "autoincrement",
|
"key_type" => "autoincrement",
|
||||||
"name_attcode" => "name",
|
"name_attcode" => "name",
|
||||||
"state_attcode" => "",
|
"state_attcode" => "",
|
||||||
"reconc_keys" => array(),
|
"reconc_keys" => array('oql', 'is_template'),
|
||||||
"db_table" => "priv_query_oql",
|
"db_table" => "priv_query_oql",
|
||||||
"db_key_field" => "id",
|
"db_key_field" => "id",
|
||||||
"db_finalclass_field" => "",
|
"db_finalclass_field" => "",
|
||||||
);
|
);
|
||||||
MetaModel::Init_Params($aParams);
|
MetaModel::Init_Params($aParams);
|
||||||
MetaModel::Init_InheritAttributes();
|
MetaModel::Init_InheritAttributes();
|
||||||
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array(
|
||||||
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
"allowed_values" => null,
|
||||||
|
"sql" => "oql",
|
||||||
|
"default_value" => null,
|
||||||
|
"is_null_allowed" => false,
|
||||||
|
"depends_on" => array(),
|
||||||
|
)));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeText("fields", array(
|
||||||
|
"allowed_values" => null,
|
||||||
|
"sql" => "fields",
|
||||||
|
"default_value" => null,
|
||||||
|
"is_null_allowed" => true,
|
||||||
|
"depends_on" => array(),
|
||||||
|
)));
|
||||||
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
|
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
|
||||||
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
|
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
|
||||||
|
|
||||||
// Display lists
|
// Display lists
|
||||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
|
MetaModel::Init_SetZListItems('details',
|
||||||
|
array('name', 'is_template', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
|
||||||
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'fields', 'oql')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search',
|
||||||
|
array('name', 'description', 'is_template', 'fields', 'oql')); // Criteria of the std search form
|
||||||
}
|
}
|
||||||
|
|
||||||
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
|
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
|
||||||
{
|
{
|
||||||
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
|
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
|
||||||
|
$oPage->add_script("$('[name=\"attr_oql\"]').addClass('ibo-queryoql'); $('[data-attribute-code=\"oql\"]').addClass('ibo-queryoql');");
|
||||||
if (!$bEditMode)
|
|
||||||
{
|
if (!$bEditMode) {
|
||||||
$sFields = trim($this->Get('fields'));
|
$sFields = trim($this->Get('fields'));
|
||||||
$bExportV1Recommended = ($sFields == '');
|
$bExportV1Recommended = ($sFields == '');
|
||||||
if ($bExportV1Recommended)
|
if ($bExportV1Recommended) {
|
||||||
{
|
|
||||||
$oFieldAttDef = MetaModel::GetAttributeDef('QueryOQL', 'fields');
|
$oFieldAttDef = MetaModel::GetAttributeDef('QueryOQL', 'fields');
|
||||||
$oPage->add('<div class="message message_error" style="padding-left: 30px;"><div style="padding: 10px;">'.Dict::Format('UI:Query:UrlV1', $oFieldAttDef->GetLabel()).'</div></div>');
|
$oAlert = AlertUIBlockFactory::MakeForFailure()
|
||||||
|
->SetIsClosable(false)
|
||||||
|
->SetIsCollapsible(false);
|
||||||
|
$oAlert->AddCSSClass('mb-5');
|
||||||
|
$oAlert->AddSubBlock(new Html(Dict::Format('UI:Query:UrlV1', '')));
|
||||||
|
$oPage->AddSubBlock($oAlert);
|
||||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
|
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
|
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
|
||||||
}
|
}
|
||||||
$sOql = $this->Get('oql');
|
$sOql = $this->Get('oql');
|
||||||
$sMessage = null;
|
$sMessage = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||||
$aParameters = $oSearch->GetQueryParams();
|
$aParameters = $oSearch->GetQueryParams();
|
||||||
foreach($aParameters as $sParam => $val)
|
foreach ($aParameters as $sParam => $val) {
|
||||||
{
|
|
||||||
$sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]';
|
$sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]';
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPage->p(Dict::S('UI:Query:UrlForExcel').':<br/><textarea cols="80" rows="3" READONLY>'.$sUrl.'</textarea>');
|
$oTextArea = new TextArea("", $sUrl, null, 80, 3);
|
||||||
|
$oFieldUrl = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:Query:UrlForExcel'), $oTextArea, Field::ENUM_FIELD_LAYOUT_LARGE);
|
||||||
|
$oPage->AddSubBlock($oFieldUrl);
|
||||||
|
|
||||||
if (count($aParameters) == 0)
|
if (count($aParameters) == 0) {
|
||||||
{
|
|
||||||
$oBlock = new DisplayBlock($oSearch, 'list');
|
$oBlock = new DisplayBlock($oSearch, 'list');
|
||||||
$aExtraParams = array(
|
$aExtraParams = array(
|
||||||
//'menu' => $sShowMenu,
|
//'menu' => $sShowMenu,
|
||||||
@@ -128,10 +166,13 @@ class QueryOQL extends Query
|
|||||||
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
|
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OQLException $e)
|
catch
|
||||||
{
|
(OQLException $e) {
|
||||||
$sMessage = '<div class="message message_error" style="padding-left: 30px;"><div style="padding: 10px;">'.Dict::Format('UI:RunQuery:Error', $e->getHtmlDesc()).'</div></div>';
|
$oAlert = AlertUIBlockFactory::MakeForFailure(Dict::Format('UI:RunQuery:Error'), $e->getHtmlDesc())
|
||||||
$oPage->p($sMessage);
|
->SetIsClosable(false)
|
||||||
|
->SetIsCollapsible(false);
|
||||||
|
$oAlert->AddCSSClass('mb-5');
|
||||||
|
$oPage->AddSubBlock($oAlert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $aFieldsMap;
|
return $aFieldsMap;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2016 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -15,14 +15,14 @@
|
|||||||
//
|
//
|
||||||
// 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;
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent class Shortcut and derived
|
* Persistent class Shortcut and derived
|
||||||
* Shortcuts of any kind
|
* Shortcuts of any kind
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ function ShortcutRenameOK()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#shortcut_rename_dlg form').bind('submit', function() { return false; });
|
$('#shortcut_rename_dlg form').on('submit', function() { return false; });
|
||||||
|
|
||||||
$('#shortcut_rename_dlg').dialog({
|
$('#shortcut_rename_dlg').dialog({
|
||||||
width: 400,
|
width: 400,
|
||||||
@@ -286,8 +286,7 @@ class ShortcutOQL extends Shortcut
|
|||||||
$sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval')));
|
$sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval')));
|
||||||
|
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<JS
|
||||||
|
|
||||||
// Note: the title gets deleted by the validation mechanism
|
// Note: the title gets deleted by the validation mechanism
|
||||||
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
|
$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
|
||||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||||
@@ -315,23 +314,30 @@ function ShortcutCreationOK()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#shortcut_creation_dlg form').bind('submit', function() { ShortcutCreationOK(); return false; });
|
$('#shortcut_creation_dlg form').on('submit', function() { ShortcutCreationOK(); return false; });
|
||||||
|
|
||||||
$('#shortcut_creation_dlg').dialog({
|
$('#shortcut_creation_dlg').dialog({
|
||||||
width: 400,
|
width: 400,
|
||||||
modal: true,
|
modal: true,
|
||||||
title: '$sDialogTitle',
|
title: '$sDialogTitle',
|
||||||
buttons: [
|
buttons: [
|
||||||
{ text: "$sOkButtonLabel", click: ShortcutCreationOK },
|
{
|
||||||
{ text: "$sCancelButtonLabel", click: function() {
|
text: "$sCancelButtonLabel",
|
||||||
$(this).dialog( "close" ); $(this).remove();
|
class: "ibo-is-alternative",
|
||||||
} },
|
click: function() {
|
||||||
|
$(this).dialog( "close" );
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "$sOkButtonLabel",
|
||||||
|
class: "ibo-is-primary",
|
||||||
|
click: ShortcutCreationOK
|
||||||
|
},
|
||||||
],
|
],
|
||||||
close: function() { $(this).remove(); }
|
close: function() { $(this).remove(); }
|
||||||
});
|
});
|
||||||
EOF
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2016 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -23,7 +23,7 @@ require_once(APPROOT.'/core/contexttag.class.inc.php');
|
|||||||
/**
|
/**
|
||||||
* File to include to initialize the datamodel in memory
|
* File to include to initialize the datamodel in memory
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ register_shutdown_function(function()
|
|||||||
$sMessage = substr($sMessage, 0, $iStackTracePos);
|
$sMessage = substr($sMessage, 0, $iStackTracePos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IssueLog::error($sMessage);
|
IssueLog::error($sMessage, null, $err);
|
||||||
if (strpos($err['message'], 'Allowed memory size of') !== false)
|
if (strpos($err['message'], 'Allowed memory size of') !== false)
|
||||||
{
|
{
|
||||||
$sLimit = ini_get('memory_limit');
|
$sLimit = ini_get('memory_limit');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -21,7 +21,7 @@ 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
|
* @deprecated 3.0.0
|
||||||
*/
|
*/
|
||||||
class DisplayTemplate
|
class DisplayTemplate
|
||||||
{
|
{
|
||||||
@@ -31,14 +31,15 @@ class DisplayTemplate
|
|||||||
|
|
||||||
public function __construct($sTemplate)
|
public function __construct($sTemplate)
|
||||||
{
|
{
|
||||||
$this->m_aTags = array (
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||||
|
$this->m_aTags = array(
|
||||||
'itopblock',
|
'itopblock',
|
||||||
'itopcheck',
|
'itopcheck',
|
||||||
'itoptabs',
|
'itoptabs',
|
||||||
'itoptab',
|
'itoptab',
|
||||||
'itoptoggle',
|
'itoptoggle',
|
||||||
'itopstring',
|
'itopstring',
|
||||||
'sqlblock'
|
'sqlblock',
|
||||||
);
|
);
|
||||||
$this->m_sTemplate = $sTemplate;
|
$this->m_sTemplate = $sTemplate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* Copyright (C) 2013-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -43,16 +43,13 @@ class ThemeHandler
|
|||||||
public static function GetDefaultThemeInformation()
|
public static function GetDefaultThemeInformation()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'light-grey',
|
'name' => 'fullmoon',
|
||||||
'parameters' => [
|
'parameters' => [
|
||||||
'variables' => [],
|
'variables' => [],
|
||||||
'imports' => [
|
'imports' => [],
|
||||||
'css-variables' => '../css/css-variables.scss',
|
|
||||||
],
|
|
||||||
'stylesheets' => [
|
'stylesheets' => [
|
||||||
'jqueryui' => '../css/ui-lightness/jqueryui.scss',
|
'main' => '../css/backoffice/main.scss',
|
||||||
'main' => '../css/light-grey.scss',
|
]
|
||||||
],
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -60,22 +57,27 @@ class ThemeHandler
|
|||||||
/**
|
/**
|
||||||
* Return the ID of the theme currently defined in the config. file
|
* Return the ID of the theme currently defined in the config. file
|
||||||
*
|
*
|
||||||
|
* @deprecated 3.0.0, will be removed in 3.1, see N°3898
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function GetCurrentThemeId()
|
public static function GetCurrentThemeId()
|
||||||
{
|
{
|
||||||
try
|
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||||
{
|
static::GetCurrentUserThemeId();
|
||||||
if (is_null(MetaModel::GetConfig()))
|
}
|
||||||
{
|
|
||||||
throw new CoreException('no config');
|
/**
|
||||||
}
|
* @return string ID of the theme currently defined in the config. file, which applies to all users by default. If non defined, fallback on the default one.
|
||||||
$sThemeId = MetaModel::GetConfig()->Get('backoffice_default_theme');
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetApplicationThemeId(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$sThemeId = utils::GetConfig()->Get('backoffice_default_theme');
|
||||||
}
|
}
|
||||||
catch(CoreException $oCompileException)
|
catch (CoreException $oCompileException) {
|
||||||
{
|
|
||||||
// Fallback on our default theme in case the config. is not available yet
|
// Fallback on our default theme in case the config. is not available yet
|
||||||
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
|
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
|
||||||
$sThemeId = $aDefaultTheme['name'];
|
$sThemeId = $aDefaultTheme['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,49 +85,173 @@ class ThemeHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the absolute path of the compiled theme folder.
|
* @return string ID of the theme to use for the current user as per they preferences. If non defined, fallback on the app. theme ID.
|
||||||
*
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetCurrentUserThemeId(): string
|
||||||
|
{
|
||||||
|
$sThemeId = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (true === utils::GetConfig()->Get('user_preferences.allow_backoffice_theme_override')) {
|
||||||
|
$sThemeId = appUserPreferences::GetPref('backoffice_theme', null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $oException) {
|
||||||
|
// Do nothing, already handled by $sThemeId null by default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback on the app. theme
|
||||||
|
if (is_null($sThemeId)) {
|
||||||
|
$sThemeId = static::GetApplicationThemeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sThemeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* @param string $sThemeId
|
* @param string $sThemeId
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string Label of the theme which is either a dict entry ('theme:<THEME_ID>') or the ID if no localized dict. entry found.
|
||||||
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static function GetCompiledThemeFolderAbsolutePath($sThemeId)
|
public static function GetThemeLabel(string $sThemeId): string
|
||||||
{
|
{
|
||||||
return APPROOT.'env-'.utils::GetCurrentEnvironment().'/branding/themes/'.$sThemeId.'/';
|
$sDictEntryCode = 'theme:'.$sThemeId;
|
||||||
|
$sDictEntryValue = Dict::S('theme:'.$sThemeId);
|
||||||
|
|
||||||
|
return ($sDictEntryCode === $sDictEntryValue) ? $sThemeId : $sDictEntryValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array Associative array of <THEME_ID> => <THEME_LABEL>, ordered by labels
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetAvailableThemes(): array
|
||||||
|
{
|
||||||
|
$aThemes = [];
|
||||||
|
|
||||||
|
foreach (glob(static::GetCompiledThemesFolderAbsolutePath().'/*') as $sPath) {
|
||||||
|
if (is_dir($sPath)) {
|
||||||
|
$sThemeId = basename($sPath);
|
||||||
|
$sThemeLabel = static::GetThemeLabel($sThemeId);
|
||||||
|
|
||||||
|
$aThemes[$sThemeId] = $sThemeLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asort($aThemes);
|
||||||
|
|
||||||
|
return $aThemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sThemeId
|
||||||
|
*
|
||||||
|
* @return bool True if $sThemeId is a valid theme that can be used.
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function IsValidTheme(string $sThemeId): bool
|
||||||
|
{
|
||||||
|
return array_key_exists($sThemeId, static::GetAvailableThemes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string Absolute path to the folder containing all the compiled themes
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetCompiledThemesFolderAbsolutePath(): string
|
||||||
|
{
|
||||||
|
return APPROOT.'env-'.utils::GetCurrentEnvironment().'/branding/themes/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sThemeId
|
||||||
|
*
|
||||||
|
* @return string Absolute path to the folder containing the $sThemeId theme
|
||||||
|
*/
|
||||||
|
public static function GetCompiledThemeFolderAbsolutePath(string $sThemeId): string
|
||||||
|
{
|
||||||
|
return static::GetCompiledThemesFolderAbsolutePath().$sThemeId.'/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sThemeId
|
||||||
|
*
|
||||||
|
* @return string Absolute path of the compiled file for the $sThemeId theme (Note: It doesn't mean that the theme is actually compiled)
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetCompiledThemeFileAbsolutePath(string $sThemeId): string
|
||||||
|
{
|
||||||
|
return static::GetCompiledThemeFolderAbsolutePath($sThemeId).'main.css';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sThemeId
|
||||||
|
*
|
||||||
|
* @return string Absolute URL of the compiled file for the $sThemeId theme (Note: It doesn't mean that the theme is actually compiled)
|
||||||
|
* @throws \Exception
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static function GetCompiledThemeFileAbsoluteUrl(string $sThemeId): string
|
||||||
|
{
|
||||||
|
return utils::GetAbsoluteUrlModulesRoot().'branding/themes/'.$sThemeId.'/main.css';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the absolute URL for the current theme CSS file
|
* Return the absolute URL for the current theme CSS file
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function GetCurrentThemeUrl()
|
public static function GetCurrentThemeUrl(): string
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// Try to compile theme defined in the configuration
|
// Try to compile theme defined in the configuration
|
||||||
$sThemeId = static::GetCurrentThemeId();
|
// Note: In maintenance mode we should stick to the app theme (also we don't have access to many PHP classes, including the user preferences)
|
||||||
static::CompileTheme($sThemeId);
|
$sThemeId = SetupUtils::IsInMaintenanceMode() ? static::GetApplicationThemeId() : static::GetCurrentUserThemeId();
|
||||||
|
if (static::ShouldThemeSignatureCheckBeForced($sThemeId)) {
|
||||||
|
static::CompileTheme($sThemeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(CoreException $oCompileException)
|
catch (CoreException $oCompileException) {
|
||||||
{
|
|
||||||
// Fallback on our default theme (should always be compilable) in case the previous theme doesn't exists
|
// Fallback on our default theme (should always be compilable) in case the previous theme doesn't exists
|
||||||
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
|
$aDefaultTheme = ThemeHandler::GetDefaultThemeInformation();
|
||||||
$sThemeId = $aDefaultTheme['name'];
|
$sThemeId = $aDefaultTheme['name'];
|
||||||
$sDefaultThemeDirPath = static::GetCompiledThemeFolderAbsolutePath($sThemeId);
|
$sDefaultThemeDirPath = static::GetCompiledThemeFolderAbsolutePath($sThemeId);
|
||||||
|
|
||||||
// Create our theme dir if it doesn't exist (XML theme node removed, renamed etc..)
|
// Create our theme dir if it doesn't exist (XML theme node removed, renamed etc..)
|
||||||
if(!is_dir($sDefaultThemeDirPath))
|
if (!is_dir($sDefaultThemeDirPath)) {
|
||||||
{
|
|
||||||
SetupUtils::builddir($sDefaultThemeDirPath);
|
SetupUtils::builddir($sDefaultThemeDirPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static::CompileTheme($sThemeId, false, "", $aDefaultTheme['parameters']);
|
if (static::ShouldThemeSignatureCheckBeForced($sThemeId)) {
|
||||||
|
static::CompileTheme($sThemeId, false, "", $aDefaultTheme['parameters']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return absolute url to theme compiled css
|
return static::GetCompiledThemeFileAbsoluteUrl($sThemeId);
|
||||||
return utils::GetAbsoluteUrlModulesRoot().'branding/themes/'.$sThemeId.'/main.css';
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sThemeId
|
||||||
|
*
|
||||||
|
* @return bool True if the $sThemeId signature check -and possibly the compilation- should be forced (dev. environment, missing compiled file, ...)
|
||||||
|
*/
|
||||||
|
protected static function ShouldThemeSignatureCheckBeForced(string $sThemeId): bool
|
||||||
|
{
|
||||||
|
if (utils::IsDevelopmentEnvironment()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === file_exists(static::GetCompiledThemeFileAbsolutePath($sThemeId))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === utils::GetConfig()->Get('theme.force_signature_check_at_runtime')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,33 +263,30 @@ class ThemeHandler
|
|||||||
* @param boolean $bSetup
|
* @param boolean $bSetup
|
||||||
* @param string $sSetupCompilationTimestamp : setup compilation timestamp in micro secunds
|
* @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 Folder 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
|
* @return boolean: indicate whether theme compilation occured
|
||||||
*/
|
*/
|
||||||
public static function CompileTheme($sThemeId, $bSetup=false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
|
public static function CompileTheme($sThemeId, $bSetup=false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null) {
|
||||||
{
|
if ($sSetupCompilationTimestamp === "") {
|
||||||
if ($sSetupCompilationTimestamp==="")
|
|
||||||
{
|
|
||||||
$sSetupCompilationTimestamp = microtime(true);
|
$sSetupCompilationTimestamp = microtime(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !==false) ? explode('.', $sSetupCompilationTimestamp)[0] : $sSetupCompilationTimestamp;
|
$sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !== false) ? explode('.',
|
||||||
|
$sSetupCompilationTimestamp)[0] : $sSetupCompilationTimestamp;
|
||||||
|
|
||||||
$sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
|
$sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
|
||||||
|
|
||||||
// Default working path
|
// Default working path
|
||||||
if($sWorkingPath === null)
|
if ($sWorkingPath === null) {
|
||||||
{
|
|
||||||
$sWorkingPath = $sEnv;
|
$sWorkingPath = $sEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default import paths (env-*)
|
// Default import paths (env-*)
|
||||||
if($aImportsPaths === null)
|
if ($aImportsPaths === null) {
|
||||||
{
|
$aImportsPaths = [$sEnv];
|
||||||
$aImportsPaths = [ $sEnv];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We do NOT check that the folder exists!
|
// Note: We do NOT check that the folder exists!
|
||||||
@@ -171,53 +294,52 @@ class ThemeHandler
|
|||||||
$sThemeCssPath = $sThemeFolderPath.'main.css';
|
$sThemeCssPath = $sThemeFolderPath.'main.css';
|
||||||
|
|
||||||
// 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)) {
|
||||||
if (!is_dir($sThemeFolderPath))
|
|
||||||
{
|
|
||||||
mkdir($sWorkingPath.'/branding/');
|
mkdir($sWorkingPath.'/branding/');
|
||||||
mkdir($sWorkingPath.'/branding/themes/');
|
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)
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aThemeParameters = json_decode(@file_get_contents($sThemeFolderPath.'theme-parameters.json'), true);
|
$aThemeParameters = json_decode(@file_get_contents($sThemeFolderPath.'theme-parameters.json'), true);
|
||||||
if ($aThemeParameters === null)
|
if ($aThemeParameters === null) {
|
||||||
{
|
|
||||||
throw new CoreException('Could not load "'.$sThemeId.'" theme parameters from file, check that it has been compiled correctly');
|
throw new CoreException('Could not load "'.$sThemeId.'" theme parameters from file, check that it has been compiled correctly');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aThemeParametersWithVersion = self::CloneThemeParameterAndIncludeVersion($aThemeParameters, $sSetupCompilationTimestampInSecunds);
|
$aThemeParametersWithVersion = self::CloneThemeParameterAndIncludeVersion($aThemeParameters, $sSetupCompilationTimestampInSecunds, $aImportsPaths);
|
||||||
|
|
||||||
$sTmpThemeScssContent = '';
|
|
||||||
$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
|
||||||
|
$sTmpThemeScssContent = '';
|
||||||
$aStylesheetFiles = [];
|
$oFindStylesheetObject = new FindStylesheetObject();
|
||||||
foreach ($aThemeParameters['imports'] as $sImport)
|
if (isset($aThemeParameters['variable_imports'])) {
|
||||||
{
|
foreach ($aThemeParameters['variable_imports'] as $sImport) {
|
||||||
$sTmpThemeScssContent .= '@import "'.$sImport.'";'."\n";
|
static::FindStylesheetFile($sImport, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
}
|
||||||
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
|
|
||||||
$iImportLastModified = @filemtime($sFile);
|
|
||||||
$aStylesheetFiles[] = $sFile;
|
|
||||||
$iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified;
|
|
||||||
}
|
}
|
||||||
foreach ($aThemeParameters['stylesheets'] as $sStylesheet)
|
|
||||||
{
|
if (isset($aThemeParameters['utility_imports'])) {
|
||||||
|
foreach ($aThemeParameters['utility_imports'] as $sImport) {
|
||||||
|
static::FindStylesheetFile($sImport, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aThemeParameters['stylesheets'])) {
|
||||||
|
foreach ($aThemeParameters['stylesheets'] as $sStylesheet) {
|
||||||
|
static::FindStylesheetFile($sStylesheet, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($oFindStylesheetObject->GetStylesheetFileURIs() as $sStylesheet){
|
||||||
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
|
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
|
||||||
|
|
||||||
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
|
|
||||||
$iStylesheetLastModified = @filemtime($sFile);
|
|
||||||
$aStylesheetFiles[] = $sFile;
|
|
||||||
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $aStylesheetFiles, $sThemeId);
|
$iStyleLastModified = $oFindStylesheetObject->GetLastModified();
|
||||||
|
|
||||||
|
$aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $oFindStylesheetObject->GetAllStylesheetPaths(), $sThemeId);
|
||||||
foreach ($aIncludedImages as $sImage)
|
foreach ($aIncludedImages as $sImage)
|
||||||
{
|
{
|
||||||
if (is_file($sImage))
|
if (is_file($sImage))
|
||||||
@@ -274,11 +396,12 @@ CSS;
|
|||||||
static::$oCompileCSSService = new CompileCSSService();
|
static::$oCompileCSSService = new CompileCSSService();
|
||||||
}
|
}
|
||||||
//store it again to change $version with latest compiled time
|
//store it again to change $version with latest compiled time
|
||||||
|
SetupLog::Info("Compiling theme $sThemeId...");
|
||||||
$sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths,
|
$sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths,
|
||||||
$aThemeParametersWithVersion);
|
$aThemeParametersWithVersion);
|
||||||
|
SetupLog::Info("$sThemeId theme compilation done.");
|
||||||
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
||||||
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
|
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
|
||||||
SetupLog::Info("Theme $sThemeId file compiled.");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,6 +409,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Compute the signature of a theme defined by its theme parameters. The signature is a JSON structure of
|
* 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)
|
* 1) one MD5 of all the variables/values (JSON encoded)
|
||||||
* 2) the MD5 of each stylesheet file
|
* 2) the MD5 of each stylesheet file
|
||||||
@@ -299,25 +423,54 @@ CSS;
|
|||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages)
|
public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages) {
|
||||||
{
|
|
||||||
$aSignature = [
|
$aSignature = [
|
||||||
'variables' => md5(json_encode($aThemeParameters['variables'])),
|
'variables' => md5(json_encode($aThemeParameters['variables'])),
|
||||||
'stylesheets' => [],
|
'stylesheets' => [],
|
||||||
'imports' => [],
|
'variable_imports' => [],
|
||||||
'images' => []
|
'images' => [],
|
||||||
|
'utility_imports' => []
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($aThemeParameters['imports'] as $key => $sImport)
|
$oFindStylesheetObject = new FindStylesheetObject();
|
||||||
{
|
|
||||||
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
|
if (isset($aThemeParameters['variable_imports'])) {
|
||||||
$aSignature['stylesheets'][$key] = md5_file($sFile);
|
foreach ($aThemeParameters['variable_imports'] as $key => $sImport) {
|
||||||
|
static::FindStylesheetFile($sImport, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
$sFile = $oFindStylesheetObject->GetLastStylesheetFile();
|
||||||
|
if (!empty($sFile)) {
|
||||||
|
$aSignature['variable_imports'][$key] = md5_file($sFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach ($aThemeParameters['stylesheets'] as $key => $sStylesheet)
|
|
||||||
{
|
if (isset($aThemeParameters['utility_imports'])) {
|
||||||
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
|
foreach ($aThemeParameters['utility_imports'] as $key => $sImport) {
|
||||||
$aSignature['stylesheets'][$key] = md5_file($sFile);
|
static::FindStylesheetFile($sImport, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
$sFile = $oFindStylesheetObject->GetLastStylesheetFile();
|
||||||
|
if (!empty($sFile)) {
|
||||||
|
$aSignature['utility_imports'][$key] = md5_file($sFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (isset($aThemeParameters['stylesheets'])) {
|
||||||
|
foreach ($aThemeParameters['stylesheets'] as $key => $sStylesheet) {
|
||||||
|
static::FindStylesheetFile($sStylesheet, $aImportsPaths, $oFindStylesheetObject);
|
||||||
|
$sFile = $oFindStylesheetObject->GetLastStylesheetFile();
|
||||||
|
|
||||||
|
if (!empty($sFile)) {
|
||||||
|
$aSignature['stylesheets'][$key] = md5_file($sFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aFiles = $oFindStylesheetObject->GetImportPaths();
|
||||||
|
if (count($aFiles) !== 0) {
|
||||||
|
foreach ($aFiles as $sFileURI => $sFilePath) {
|
||||||
|
$aSignature['utility_imports'][$sFileURI] = md5_file($sFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($aIncludedImages as $sImage)
|
foreach ($aIncludedImages as $sImage)
|
||||||
{
|
{
|
||||||
if (is_file($sImage)) {
|
if (is_file($sImage)) {
|
||||||
@@ -337,7 +490,7 @@ CSS;
|
|||||||
* @param string $sThemeId : used only for logging purpose
|
* @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
|
* @return array complete path of the images, but with slashes as dir separator instead of DIRECTORY_SEPARATOR
|
||||||
* @since 3.0.0
|
* @since 3.0.0 N°2982
|
||||||
*/
|
*/
|
||||||
public static function GetIncludedImages($aThemeParametersVariables, $aStylesheetFiles, $sThemeId)
|
public static function GetIncludedImages($aThemeParametersVariables, $aStylesheetFiles, $sThemeId)
|
||||||
{
|
{
|
||||||
@@ -432,6 +585,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Complete url using provided variables. Example with $var=1: XX + $var => XX1
|
* Complete url using provided variables. Example with $var=1: XX + $var => XX1
|
||||||
* @param $aMap
|
* @param $aMap
|
||||||
* @param $aThemeParametersVariables
|
* @param $aThemeParametersVariables
|
||||||
@@ -464,6 +618,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Find missing variable values from SCSS content based on their name.
|
* Find missing variable values from SCSS content based on their name.
|
||||||
*
|
*
|
||||||
* @param $aThemeParametersVariables
|
* @param $aThemeParametersVariables
|
||||||
@@ -522,6 +677,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* @param $aFoundVariables
|
* @param $aFoundVariables
|
||||||
* @param array $aToCompleteUrls
|
* @param array $aToCompleteUrls
|
||||||
* @param array $aCompleteUrls
|
* @param array $aCompleteUrls
|
||||||
@@ -566,6 +722,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Find all referenced URLs from a SCSS file.
|
* Find all referenced URLs from a SCSS file.
|
||||||
* @param $aThemeParametersVariables
|
* @param $aThemeParametersVariables
|
||||||
* @param $sStylesheetFile
|
* @param $sStylesheetFile
|
||||||
@@ -586,6 +743,10 @@ CSS;
|
|||||||
{
|
{
|
||||||
foreach ($aMatches[1] as $path)
|
foreach ($aMatches[1] as $path)
|
||||||
{
|
{
|
||||||
|
$iRemainingClosingParenthesisPos = strpos($path, ')');
|
||||||
|
if ($iRemainingClosingParenthesisPos !== false){
|
||||||
|
$path = substr($path, 0, $iRemainingClosingParenthesisPos);
|
||||||
|
}
|
||||||
if (!array_key_exists($path, $aCompleteUrls)
|
if (!array_key_exists($path, $aCompleteUrls)
|
||||||
&& !array_key_exists($path, $aToCompleteUrls))
|
&& !array_key_exists($path, $aToCompleteUrls))
|
||||||
{
|
{
|
||||||
@@ -624,6 +785,7 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Calculate url based on its template + variables.
|
* Calculate url based on its template + variables.
|
||||||
* @param $sUrlTemplate
|
* @param $sUrlTemplate
|
||||||
* @param $aFoundVariables
|
* @param $aFoundVariables
|
||||||
@@ -674,8 +836,10 @@ CSS;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the signature for a generated CSS file. The signature MUST be alone one line immediately
|
* @since 3.0.0 N°2982
|
||||||
* followed (on the next line) by the === SIGNATURE END === pattern
|
* 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
|
||||||
|
* The signature MUST be in the first 100th lines of the file.
|
||||||
*
|
*
|
||||||
* Note the signature can be place anywhere in the CSS file (obviously inside a CSS comment !) but the
|
* 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)
|
* function will be faster if the signature is at the beginning of the file (since the file is scanned from the start)
|
||||||
@@ -686,6 +850,7 @@ CSS;
|
|||||||
*/
|
*/
|
||||||
public static function GetSignature($sFilepath)
|
public static function GetSignature($sFilepath)
|
||||||
{
|
{
|
||||||
|
$iCount = 0;
|
||||||
$sPreviousLine = '';
|
$sPreviousLine = '';
|
||||||
$hFile = @fopen($sFilepath, "r");
|
$hFile = @fopen($sFilepath, "r");
|
||||||
if ($hFile !== false)
|
if ($hFile !== false)
|
||||||
@@ -693,15 +858,22 @@ CSS;
|
|||||||
$sLine = '';
|
$sLine = '';
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
$iCount++;
|
||||||
$sPreviousLine = $sLine;
|
$sPreviousLine = $sLine;
|
||||||
$sLine = rtrim(fgets($hFile)); // Remove the trailing \n
|
$sLine = rtrim(fgets($hFile)); // Remove the trailing \n
|
||||||
}
|
}
|
||||||
while (($sLine !== false) && ($sLine != '=== SIGNATURE END ==='));
|
while (($sLine !== false) && ($sLine != '=== SIGNATURE END ===') && ($iCount <= 100));
|
||||||
fclose($hFile);
|
fclose($hFile);
|
||||||
}
|
}
|
||||||
return $sPreviousLine;
|
return $sPreviousLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
|
* @param $JsonSignature
|
||||||
|
*
|
||||||
|
* @return false|mixed
|
||||||
|
*/
|
||||||
public static function GetVarSignature($JsonSignature)
|
public static function GetVarSignature($JsonSignature)
|
||||||
{
|
{
|
||||||
$aJsonArray = json_decode($JsonSignature, true);
|
$aJsonArray = json_decode($JsonSignature, true);
|
||||||
@@ -713,38 +885,110 @@ CSS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the given file in the list of ImportsPaths directory
|
* @param string $sFileURI
|
||||||
* @param string $sFile
|
|
||||||
* @param string[] $aImportsPaths
|
* @param string[] $aImportsPaths
|
||||||
* @throws Exception
|
* @param FindStylesheetObject $oFindStylesheetObject
|
||||||
* @return string
|
* @param bool $bImports
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*@since 3.0.0 N°2982
|
||||||
|
* Find the given file in the list '$aImportsPaths' of directory and all included stylesheets as well
|
||||||
|
* Compute latest timestamp found among all found stylesheets
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public static function FindStylesheetFile($sFile, $aImportsPaths)
|
public static function FindStylesheetFile(string $sFileURI, array $aImportsPaths, $oFindStylesheetObject, $bImports = false)
|
||||||
{
|
{
|
||||||
|
if (! $bImports) {
|
||||||
|
$oFindStylesheetObject->ResetLastStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
foreach($aImportsPaths as $sPath)
|
foreach($aImportsPaths as $sPath)
|
||||||
{
|
{
|
||||||
$sImportedFile = realpath($sPath.'/'.$sFile);
|
$sFilePath = $sPath.'/'.$sFileURI;
|
||||||
if (file_exists($sImportedFile))
|
$sImportedFile = realpath($sFilePath);
|
||||||
|
if ($sImportedFile === false){
|
||||||
|
// Handle shortcut syntax : @import "typo" ;
|
||||||
|
// file matched: typo.scss
|
||||||
|
$sFilePath2 = "$sFilePath.scss";
|
||||||
|
$sImportedFile = realpath($sFilePath2);
|
||||||
|
if ($sImportedFile){
|
||||||
|
self::FindStylesheetFile("$sFileURI.scss", [ $sPath ], $oFindStylesheetObject, $bImports);
|
||||||
|
$sImportedFile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sImportedFile === false){
|
||||||
|
// Handle shortcut syntax : @import "typo" ;
|
||||||
|
// file matched: _typo.scss
|
||||||
|
$sShortCut = substr($sFilePath, strrpos($sFilePath, '/') + 1);
|
||||||
|
$sFilePath = static::ReplaceLastOccurrence($sShortCut, "_$sShortCut.scss", $sFilePath);
|
||||||
|
$sFileURI = static::ReplaceLastOccurrence($sShortCut, "_$sShortCut.scss", $sFileURI);
|
||||||
|
$sImportedFile = realpath($sFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file_exists($sImportedFile))
|
||||||
|
&& (!$oFindStylesheetObject->AlreadyFetched($sImportedFile)))
|
||||||
{
|
{
|
||||||
return $sImportedFile;
|
if ($bImports){
|
||||||
|
$oFindStylesheetObject->AddImport($sFileURI, $sImportedFile);
|
||||||
|
}else{
|
||||||
|
$oFindStylesheetObject->AddStylesheet($sFileURI, $sImportedFile);
|
||||||
|
}
|
||||||
|
$oFindStylesheetObject->UpdateLastModified($sImportedFile);
|
||||||
|
|
||||||
|
//Regexp matching on all included scss files : @import 'XXX.scss';
|
||||||
|
$sDirUri = dirname($sFileURI);
|
||||||
|
preg_match_all('/@import \s*[\"\']([^\"\']*)\s*[\"\']\s*;/', file_get_contents($sImportedFile), $aMatches);
|
||||||
|
if ( (is_array($aMatches)) && (count($aMatches)!==0) ){
|
||||||
|
foreach ($aMatches[1] as $sImportedFile){
|
||||||
|
self::FindStylesheetFile("$sDirUri/$sImportedFile", [ $sPath ], $oFindStylesheetObject, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ''; // Not found, fail silently, maybe the SCSS compiler knowns better...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $search
|
||||||
|
* @param $replace
|
||||||
|
* @param $subject
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
|
* Replaces last occurrence of the string
|
||||||
|
* @return string|string[]
|
||||||
|
*/
|
||||||
|
public static function ReplaceLastOccurrence($sSearch, $sReplace, $sSubject)
|
||||||
|
{
|
||||||
|
$iPos = strrpos($sSubject, $sSearch);
|
||||||
|
|
||||||
|
if($iPos !== false)
|
||||||
|
{
|
||||||
|
$sSubject = substr_replace($sSubject, $sReplace, $iPos, strlen($sSearch));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
|
* Used for testing purpose
|
||||||
|
* @param $oCompileCSSServiceMock
|
||||||
|
*/
|
||||||
public static function MockCompileCSSService($oCompileCSSServiceMock)
|
public static function MockCompileCSSService($oCompileCSSServiceMock)
|
||||||
{
|
{
|
||||||
static::$oCompileCSSService = $oCompileCSSServiceMock;
|
static::$oCompileCSSService = $oCompileCSSServiceMock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
* Clone variable array and include $version with bSetupCompilationTimestamp value
|
* Clone variable array and include $version with bSetupCompilationTimestamp value
|
||||||
* @param $aThemeParameters
|
* @param $aThemeParameters
|
||||||
* @param $bSetupCompilationTimestamp
|
* @param $bSetupCompilationTimestamp
|
||||||
|
* @param $aImportsPaths
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp)
|
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp, $aImportsPaths)
|
||||||
{
|
{
|
||||||
$aThemeParametersVariable = [];
|
$aThemeParametersVariable = [];
|
||||||
if (array_key_exists('variables', $aThemeParameters))
|
if (array_key_exists('variables', $aThemeParameters))
|
||||||
@@ -755,22 +999,47 @@ CSS;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('variable_imports', $aThemeParameters))
|
||||||
|
{
|
||||||
|
if (is_array($aThemeParameters['variable_imports']))
|
||||||
|
{
|
||||||
|
$aThemeParametersVariable = array_merge($aThemeParametersVariable, static::GetVariablesFromFile($aThemeParameters['variable_imports'], $aImportsPaths));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
|
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
|
||||||
return $aThemeParametersVariable;
|
return $aThemeParametersVariable;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class CompileCSSService
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* CompileCSSService constructor.
|
* @param $aVariableFiles
|
||||||
|
* @param $aImportsPaths
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @since 3.0.0 N°3593
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public static function GetVariablesFromFile($aVariableFiles, $aImportsPaths){
|
||||||
{
|
$aVariablesResults = [];
|
||||||
}
|
foreach ($aVariableFiles as $sVariableFile)
|
||||||
|
{
|
||||||
|
foreach($aImportsPaths as $sPath) {
|
||||||
|
$sFilePath = $sPath.'/'.$sVariableFile;
|
||||||
|
$sImportedFile = realpath($sFilePath);
|
||||||
|
if ($sImportedFile !== false) {
|
||||||
|
$sFileContent = file_get_contents($sImportedFile);
|
||||||
|
$aVariableMatches = [];
|
||||||
|
|
||||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
|
preg_match_all('/\s*\$(.*?)\s*:\s*[\"\']{0,1}(.*?)[\"\']{0,1}\s*[;!]/', $sFileContent, $aVariableMatches);
|
||||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
$aVariableMatches = array_combine($aVariableMatches[1], array_map(function ($sVariableValue) {
|
||||||
|
return $sVariableValue;
|
||||||
|
}, $aVariableMatches[2]));
|
||||||
|
$aVariablesResults = array_merge($aVariablesResults, $aVariableMatches);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_map( function($sVariableValue) { return ltrim($sVariableValue); }, $aVariablesResults );
|
||||||
|
return $aVariablesResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
35
application/themehandlerservice.class.inc.php
Normal file
35
application/themehandlerservice.class.inc.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2013-2020 Combodo SARL
|
||||||
|
*
|
||||||
|
* This file is part of iTop.
|
||||||
|
*
|
||||||
|
* iTop is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* iTop is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ThemeHandlerService : used to ease testing MFCompiler::CompileThemes class via mocks
|
||||||
|
*
|
||||||
|
* @author Olivier DAIN <olivier.dain@combodo.com>
|
||||||
|
* @since 3.0.0 N°2982
|
||||||
|
*/
|
||||||
|
class ThemeHandlerService
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CompileTheme($sThemeId, $bSetup = false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null){
|
||||||
|
return ThemeHandler::CompileTheme($sThemeId, $bSetup, $sSetupCompilationTimestamp="", $aThemeParameters, $aImportsPaths, $sWorkingPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2015 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
* which choice is configured via the parameter 'transaction_storage'
|
* which choice is configured via the parameter 'transaction_storage'
|
||||||
*
|
*
|
||||||
* @package iTop
|
* @package iTop
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -297,11 +297,19 @@ class privUITransactionFile
|
|||||||
* Cleanup old transactions which have been pending since more than 24 hours
|
* Cleanup old transactions which have been pending since more than 24 hours
|
||||||
* Use filemtime instead of filectime since filectime may be affected by operations on the directory (like changing the access rights)
|
* Use filemtime instead of filectime since filectime may be affected by operations on the directory (like changing the access rights)
|
||||||
*/
|
*/
|
||||||
protected static function CleanupOldTransactions()
|
protected static function CleanupOldTransactions($sTransactionDir = null)
|
||||||
{
|
{
|
||||||
$iLimit = time() - 24*3600;
|
$iThreshold = (int) MetaModel::GetConfig()->Get('transactions_gc_threshold');
|
||||||
|
$iThreshold = min(100, $iThreshold);
|
||||||
|
$iThreshold = max(1, $iThreshold);
|
||||||
|
if ((100 != $iThreshold) && (rand(1, 100) > $iThreshold)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
$aTransactions = glob(APPROOT.'data/transactions/*-*');
|
$iLimit = time() - 24*3600;
|
||||||
|
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : APPROOT.'data/transactions/*';
|
||||||
|
$aTransactions = glob($sPattern);
|
||||||
foreach($aTransactions as $sFileName)
|
foreach($aTransactions as $sFileName)
|
||||||
{
|
{
|
||||||
if (filemtime($sFileName) < $iLimit)
|
if (filemtime($sFileName) < $iLimit)
|
||||||
|
|||||||
@@ -1,20 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2013-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||||
@@ -66,67 +53,103 @@ class UIExtKeyWidget
|
|||||||
|
|
||||||
protected $iId;
|
protected $iId;
|
||||||
protected $sTargetClass;
|
protected $sTargetClass;
|
||||||
|
protected $sFilter;
|
||||||
protected $sAttCode;
|
protected $sAttCode;
|
||||||
//@deprecated
|
|
||||||
protected $bSearchMode;
|
protected $bSearchMode;
|
||||||
|
|
||||||
//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
|
/**
|
||||||
static public function DisplayFromAttCode($oPage, $sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName = '', $sFormPrefix = '', $aArgs, $bSearchMode = false)
|
* @param \WebPage $oPage
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sTitle
|
||||||
|
* @param object $oAllowedValues
|
||||||
|
* @param mixed $value
|
||||||
|
* @param int $iInputId
|
||||||
|
* @param boolean $bMandatory
|
||||||
|
* @param string $sFieldName
|
||||||
|
* @param string $sFormPrefix
|
||||||
|
* @param array $aArgs
|
||||||
|
* @param boolean $bSearchMode
|
||||||
|
* @param string $sInputType type of field rendering, contains one of the \cmdbAbstractObject::ENUM_INPUT_TYPE_* constants
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°3750 new $sInputType parameter
|
||||||
|
*/
|
||||||
|
public static function DisplayFromAttCode(
|
||||||
|
$oPage, $sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName = '', $sFormPrefix = '',
|
||||||
|
$aArgs = [], $bSearchMode = false, &$sInputType = ''
|
||||||
|
)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
$sTargetClass = $oAttDef->GetTargetClass();
|
$sTargetClass = $oAttDef->GetTargetClass();
|
||||||
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
|
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
|
||||||
$bAllowTargetCreation = $oAttDef->AllowTargetCreation();
|
$bAllowTargetCreation = $oAttDef->AllowTargetCreation();
|
||||||
if (!$bSearchMode)
|
if (!$bSearchMode) {
|
||||||
{
|
|
||||||
$sDisplayStyle = $oAttDef->GetDisplayStyle();
|
$sDisplayStyle = $oAttDef->GetDisplayStyle();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$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);
|
||||||
if(!$bSearchMode)
|
if (!$bSearchMode) {
|
||||||
{
|
switch ($sDisplayStyle)
|
||||||
switch($sDisplayStyle)
|
|
||||||
{
|
{
|
||||||
case 'radio':
|
case 'radio':
|
||||||
case 'radio_horizontal':
|
case 'radio_horizontal':
|
||||||
case 'radio_vertical':
|
case 'radio_vertical':
|
||||||
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_RADIO;
|
||||||
|
|
||||||
return $oWidget->DisplayRadio($oPage, $iMaxComboLength, $bAllowTargetCreation, $oAllowedValues, $value, $sFieldName, $sDisplayStyle);
|
return $oWidget->DisplayRadio($oPage, $iMaxComboLength, $bAllowTargetCreation, $oAllowedValues, $value, $sFieldName, $sDisplayStyle);
|
||||||
break;
|
|
||||||
|
|
||||||
case 'select':
|
case 'select':
|
||||||
case 'list':
|
case 'list':
|
||||||
default:
|
default:
|
||||||
return $oWidget->DisplaySelect($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value,
|
return $oWidget->DisplaySelect($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value,
|
||||||
$bMandatory, $sFieldName, $sFormPrefix, $aArgs);
|
$bMandatory, $sFieldName, $sFormPrefix, $aArgs, $sInputType);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId,
|
||||||
|
$bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle, true, $sInputType);
|
||||||
}
|
}
|
||||||
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, $sFilter = null)
|
||||||
{
|
{
|
||||||
$this->sTargetClass = $sTargetClass;
|
$this->sTargetClass = $sTargetClass;
|
||||||
|
$this->sFilter = $sFilter;
|
||||||
$this->iId = $iInputId;
|
$this->iId = $iInputId;
|
||||||
$this->sAttCode = $sAttCode;
|
$this->sAttCode = $sAttCode;
|
||||||
$this->bSearchMode = $bSearchMode;
|
$this->bSearchMode = $bSearchMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete
|
* @param \WebPage $oPage
|
||||||
* Get the HTML fragment corresponding to the ext key editing widget
|
* @param int $iMaxComboLength
|
||||||
* @param WebPage $oP The web page used for all the output
|
* @param bool $bAllowTargetCreation
|
||||||
|
* @param string $sTitle
|
||||||
|
* @param \DBObjectset $oAllowedValues
|
||||||
|
* @param mixed $value
|
||||||
|
* @param bool $bMandatory
|
||||||
|
* @param string $sFieldName
|
||||||
|
* @param string $sFormPrefix
|
||||||
* @param array $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
* @return string The HTML fragment to be inserted into the page
|
* @param string $sInputType type of field rendering, contains one of the \cmdbAbstractObject::ENUM_INPUT_TYPE_* constants
|
||||||
|
*
|
||||||
|
* @return string the HTML fragment corresponding to the ext key editing widget
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \ConfigException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \DictExceptionMissingString
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°2508 - Include Obsolescence icon within list and autocomplete
|
||||||
|
* @since 3.0.0 N°3750 new $sInputType parameter
|
||||||
*/
|
*/
|
||||||
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array())
|
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '')
|
||||||
{
|
{
|
||||||
$sTitle = addslashes($sTitle);
|
$sTitle = addslashes($sTitle);
|
||||||
$oPage->add_linked_script('../js/extkeywidget.js');
|
$oPage->add_linked_script('../js/extkeywidget.js');
|
||||||
@@ -137,29 +160,23 @@ class UIExtKeyWidget
|
|||||||
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
|
$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());
|
$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
|
||||||
if($this->bSearchMode)
|
if ($this->bSearchMode) {
|
||||||
{
|
|
||||||
$sWizHelper = 'null';
|
$sWizHelper = 'null';
|
||||||
$sWizHelperJSON = "''";
|
$sWizHelperJSON = "''";
|
||||||
$sJSSearchMode = 'true';
|
$sJSSearchMode = 'true';
|
||||||
}
|
} else {
|
||||||
else
|
if (isset($aArgs['wizHelper'])) {
|
||||||
{
|
|
||||||
if (isset($aArgs['wizHelper']))
|
|
||||||
{
|
|
||||||
$sWizHelper = $aArgs['wizHelper'];
|
$sWizHelper = $aArgs['wizHelper'];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
}
|
}
|
||||||
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
|
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
|
||||||
$sJSSearchMode = 'false';
|
$sJSSearchMode = 'false';
|
||||||
}
|
}
|
||||||
if (is_null($oAllowedValues))
|
if (is_null($oAllowedValues)) {
|
||||||
{
|
|
||||||
throw new Exception('Implementation: null value for allowed values definition');
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
}
|
}
|
||||||
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
@@ -167,9 +184,12 @@ class UIExtKeyWidget
|
|||||||
$bDoSearch = !utils::IsHighCardinality($this->sTargetClass);
|
$bDoSearch = !utils::IsHighCardinality($this->sTargetClass);
|
||||||
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
|
|
||||||
|
$bIsAutocomplete = $oAllowedValues->CountExceeds($iMaxComboLength);
|
||||||
|
$sWrapperCssClass = $bIsAutocomplete ? 'ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper';
|
||||||
|
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey ibo-input-wrapper ibo-input-select-wrapper--with-buttons $sWrapperCssClass\" data-attcode=\"".$this->sAttCode."\" data-validation=\"untouched\">";
|
||||||
|
|
||||||
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||||
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
|
if (!$bIsAutocomplete) {
|
||||||
{
|
|
||||||
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||||
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
|
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
|
||||||
//$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
//$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
||||||
@@ -204,47 +224,40 @@ class UIExtKeyWidget
|
|||||||
$sDisplayValue=$oObj->GetName();
|
$sDisplayValue=$oObj->GetName();
|
||||||
if($value != $oObj->GetKey())
|
if($value != $oObj->GetKey())
|
||||||
{
|
{
|
||||||
$oPage->add_ready_script(
|
$value=$oObj->GetKey();
|
||||||
<<<EOF
|
|
||||||
$('#$this->iId').attr('data-validate','dependencies');
|
|
||||||
EOF
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
if ((is_array($value) && in_array($oObj->GetKey(), $value)) || ($value == $oObj->GetKey())) {
|
||||||
if ((is_array($value) && in_array($oObj->GetKey(), $value)) || ($value == $oObj->GetKey()))
|
$sDisplayValue = $oObj->GetName();
|
||||||
{
|
|
||||||
$sDisplayValue=$oObj->GetKey();
|
|
||||||
// $sHTMLValue.="<div class='item' data-value='".$oObj->GetKey)."'>".$oObj->GetName()."</div>";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($oObj->IsObsolete()){
|
if ($oObj->IsObsolete()) {
|
||||||
$aOption['obsolescence_flag'] ="1";
|
$aOption['obsolescence_flag'] = "1";
|
||||||
}
|
}
|
||||||
if ($bAddingValue)
|
if ($bAddingValue) {
|
||||||
{
|
|
||||||
$aArguments = [];
|
$aArguments = [];
|
||||||
foreach ($aAdditionalField as $sAdditionalField)
|
foreach ($aAdditionalField as $sAdditionalField) {
|
||||||
{
|
array_push($aArguments, $oObj->Get($sAdditionalField));
|
||||||
array_push($aArguments,$oObj->Get($sAdditionalField));
|
|
||||||
}
|
}
|
||||||
$aOption['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
$aOption['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
|
||||||
}
|
}
|
||||||
array_push($aOptions,$aOption);
|
array_push($aOptions, $aOption);
|
||||||
}
|
}
|
||||||
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\"></select>";
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_DECORATED;
|
||||||
$sJsonOptions=json_encode($aOptions);
|
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\" tabindex=\"0\"></select>";
|
||||||
|
$sJsonOptions = json_encode($aOptions);
|
||||||
$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>";
|
||||||
oACWidget_{$this->iId}.AddSelectize('$sJsonOptions','$sDisplayValue');
|
oACWidget_{$this->iId}.AddSelectize('$sJsonOptions','$value');
|
||||||
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
$('#$this->iId').on('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||||
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
|
$('#$this->iId').on('change', function() { $(this).trigger('extkeychange') } );
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -261,16 +274,14 @@ EOF
|
|||||||
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
|
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
|
||||||
{
|
{
|
||||||
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
|
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sDisplayValue = $this->GetObjectName($value);
|
$sDisplayValue = $this->GetObjectName($value);
|
||||||
}
|
}
|
||||||
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $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 ibo-input ibo-input-select ibo-input-select-autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_AUTOCOMPLETE;
|
||||||
$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>";
|
$sHTMLValue .= "<input class=\"field_autocomplete ibo-input ibo-input-select ibo-input-select-autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\" placeholder='...'/>";
|
||||||
|
|
||||||
// another hidden input to store & pass the object's Id
|
// 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";
|
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||||
@@ -288,24 +299,13 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||||
|
$sHTMLValue .= " <div class=\"ibo-input-select--action-button ibo-input-select--action-button--clear ibo-is-hidden\" id=\"mini_clear_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Clear();\" data-tooltip-content='".Dict::S('UI:Button:Clear')."'><i class=\"fas fa-times\"></i></div>";
|
||||||
}
|
}
|
||||||
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
if ($bCreate && $bExtensions) {
|
||||||
{
|
|
||||||
$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';
|
$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>";
|
$sHTMLValue .= "<div class=\"ibo-input-select--action-button ibo-input-select--action-button--create\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\" data-tooltip-content='".Dict::S('UI:Button:Create')."'><i class=\"fas fa-plus\"></i></div>";
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<JS
|
<<<JS
|
||||||
if ($('#ajax_{$this->iId}').length == 0)
|
if ($('#ajax_{$this->iId}').length == 0)
|
||||||
@@ -315,6 +315,21 @@ JS
|
|||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
|
||||||
|
$sHTMLValue .= "<div class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\" data-tooltip-content='".Dict::S('UI:Button:SearchInHierarchy')."'><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 ($oAllowedValues->CountExceeds($iMaxComboLength)) {
|
||||||
|
$sHTMLValue .= " <div class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\" data-tooltip-content='".Dict::S('UI:Button:Search')."'><i class=\"fas fa-search\"></i></div>";
|
||||||
|
}
|
||||||
|
$sHTMLValue .= "</div>";
|
||||||
$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>";
|
$sHTMLValue .= "<span class=\"form_validation ibo-field-validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
||||||
|
|
||||||
@@ -403,17 +418,39 @@ JS
|
|||||||
|
|
||||||
return $sHTMLValue;
|
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 $oPage
|
||||||
|
* @param int $iMaxComboLength
|
||||||
|
* @param boolean $bAllowTargetCreation
|
||||||
|
* @param string $sTitle
|
||||||
|
* @param \DBObjectset $oAllowedValues
|
||||||
|
* @param mixed $value
|
||||||
|
* @param int $iInputId
|
||||||
|
* @param boolean $bMandatory
|
||||||
|
* @param strin $sFieldName
|
||||||
|
* @param string $sFormPrefix
|
||||||
* @param array $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
|
* @param null $bSearchMode
|
||||||
|
* @param string $sDisplayStyle
|
||||||
|
* @param boolean $bSearchMultiple
|
||||||
|
* @param string $sInputType type of field rendering, contains one of the \cmdbAbstractObject::ENUM_INPUT_TYPE_* constants
|
||||||
|
*
|
||||||
* @return string The HTML fragment to be inserted into the page
|
* @return string The HTML fragment to be inserted into the page
|
||||||
|
* @throws \ConfigException
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \MySQLHasGoneAwayException
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°3750 new $sInputType parameter
|
||||||
*/
|
*/
|
||||||
public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true)
|
public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true, &$sInputType = '')
|
||||||
{
|
{
|
||||||
if (!is_null($bSearchMode))
|
if (!is_null($bSearchMode)) {
|
||||||
{
|
|
||||||
$this->bSearchMode = $bSearchMode;
|
$this->bSearchMode = $bSearchMode;
|
||||||
}
|
}
|
||||||
$sTitle = addslashes($sTitle);
|
$sTitle = addslashes($sTitle);
|
||||||
@@ -427,27 +464,20 @@ JS
|
|||||||
|
|
||||||
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
|
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
|
||||||
$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
|
$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
|
||||||
if($this->bSearchMode)
|
if ($this->bSearchMode) {
|
||||||
{
|
|
||||||
$sWizHelper = 'null';
|
$sWizHelper = 'null';
|
||||||
$sWizHelperJSON = "''";
|
$sWizHelperJSON = "''";
|
||||||
$sJSSearchMode = 'true';
|
$sJSSearchMode = 'true';
|
||||||
}
|
} else {
|
||||||
else
|
if (isset($aArgs['wizHelper'])) {
|
||||||
{
|
|
||||||
if (isset($aArgs['wizHelper']))
|
|
||||||
{
|
|
||||||
$sWizHelper = $aArgs['wizHelper'];
|
$sWizHelper = $aArgs['wizHelper'];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
}
|
}
|
||||||
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
|
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
|
||||||
$sJSSearchMode = 'false';
|
$sJSSearchMode = 'false';
|
||||||
}
|
}
|
||||||
if (is_null($oAllowedValues))
|
if (is_null($oAllowedValues)) {
|
||||||
{
|
|
||||||
throw new Exception('Implementation: null value for allowed values definition');
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
}
|
}
|
||||||
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
@@ -456,84 +486,71 @@ JS
|
|||||||
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
|
|
||||||
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||||
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
|
if (!$oAllowedValues->CountExceeds($iMaxComboLength)) {
|
||||||
{
|
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||||
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
switch ($sDisplayStyle) {
|
||||||
switch($sDisplayStyle)
|
|
||||||
{
|
|
||||||
case 'radio':
|
case 'radio':
|
||||||
case 'radio_horizontal':
|
case 'radio_horizontal':
|
||||||
case 'radio_vertical':
|
case 'radio_vertical':
|
||||||
$sValidationField = null;
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_RADIO;
|
||||||
|
$sValidationField = null;
|
||||||
|
|
||||||
$bVertical = ($sDisplayStyle != 'radio_horizontal');
|
$bVertical = ($sDisplayStyle != 'radio_horizontal');
|
||||||
$bExtensions = false;
|
$bExtensions = false;
|
||||||
$oAllowedValues->Rewind();
|
$oAllowedValues->Rewind();
|
||||||
$aAllowedValues = array();
|
$aAllowedValues = array();
|
||||||
while($oObj = $oAllowedValues->Fetch())
|
while ($oObj = $oAllowedValues->Fetch()) {
|
||||||
{
|
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
|
||||||
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
|
}
|
||||||
}
|
$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField);
|
||||||
$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField);
|
$aEventsList[] = 'change';
|
||||||
$aEventsList[] ='change';
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 'select':
|
case 'select':
|
||||||
case 'list':
|
case 'list':
|
||||||
default:
|
default:
|
||||||
|
$sHelpText = '';
|
||||||
|
$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
||||||
|
|
||||||
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
|
if ($this->bSearchMode) {
|
||||||
$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
|
if ($bSearchMultiple) {
|
||||||
|
$sHTMLValue .= "<select class=\"multiselect\" multiple title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"$this->iId\">\n";
|
||||||
if ($this->bSearchMode)
|
} else {
|
||||||
{
|
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
|
||||||
if ($bSearchMultiple)
|
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
|
||||||
{
|
$sHTMLValue .= "<option value=\"\">$sDisplayValue</option>\n";
|
||||||
$sHTMLValue .= "<select class=\"multiselect\" multiple title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"$this->iId\">\n";
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
|
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
|
||||||
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
|
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
|
||||||
$sHTMLValue .= "<option value=\"\">$sDisplayValue</option>\n";
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
|
|
||||||
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$oAllowedValues->Rewind();
|
$oAllowedValues->Rewind();
|
||||||
while($oObj = $oAllowedValues->Fetch())
|
while ($oObj = $oAllowedValues->Fetch()) {
|
||||||
{
|
$key = $oObj->GetKey();
|
||||||
$key = $oObj->GetKey();
|
$display_value = $oObj->GetName();
|
||||||
$display_value = $oObj->GetName();
|
|
||||||
|
|
||||||
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
|
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true')) {
|
||||||
{
|
// When there is only once choice, select it by default
|
||||||
// When there is only once choice, select it by default
|
$sSelected = 'selected';
|
||||||
$sSelected = 'selected';
|
if ($value != $key) {
|
||||||
if($value != $key)
|
$oPage->add_ready_script(
|
||||||
{
|
<<<EOF
|
||||||
$oPage->add_ready_script(
|
|
||||||
<<<EOF
|
|
||||||
$('#$this->iId').attr('data-validate','dependencies');
|
$('#$this->iId').attr('data-validate','dependencies');
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$sSelected = (is_array($value) && in_array($key, $value)) || ($value == $key) ? 'selected' : '';
|
||||||
}
|
}
|
||||||
|
$sHTMLValue .= "<option value=\"$key\" $sSelected>$display_value</option>\n";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$sSelected = (is_array($value) && in_array($key, $value)) || ($value == $key) ? 'selected' : '';
|
|
||||||
}
|
|
||||||
$sHTMLValue .= "<option value=\"$key\" $sSelected>$display_value</option>\n";
|
|
||||||
}
|
|
||||||
$sHTMLValue .= "</select>\n";
|
$sHTMLValue .= "</select>\n";
|
||||||
$sHTMLValue .= "</div>\n";
|
$sHTMLValue .= "</div>\n";
|
||||||
|
|
||||||
if (($this->bSearchMode) && $bSearchMultiple)
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_RAW;
|
||||||
{
|
if (($this->bSearchMode) && $bSearchMultiple) {
|
||||||
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_DROPDOWN_MULTIPLE_CHOICES;
|
||||||
$aOptions = array(
|
$aOptions = array(
|
||||||
'header' => true,
|
'header' => true,
|
||||||
'checkAllText' => Dict::S('UI:SearchValue:CheckAll'),
|
'checkAllText' => Dict::S('UI:SearchValue:CheckAll'),
|
||||||
@@ -544,36 +561,32 @@ EOF
|
|||||||
);
|
);
|
||||||
$sJSOptions = json_encode($aOptions);
|
$sJSOptions = json_encode($aOptions);
|
||||||
$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').on('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||||
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
|
$('#$this->iId').on('change', function() { $(this).trigger('extkeychange') } );
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
} // Switch
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Too many choices, use an autocomplete
|
// Too many choices, use an autocomplete
|
||||||
|
$sInputType = CmdbAbstractObject::ENUM_INPUT_TYPE_AUTOCOMPLETE;
|
||||||
// Check that the given value is allowed
|
// Check that the given value is allowed
|
||||||
$oSearch = $oAllowedValues->GetFilter();
|
$oSearch = $oAllowedValues->GetFilter();
|
||||||
$oSearch->AddCondition('id', $value);
|
$oSearch->AddCondition('id', $value);
|
||||||
$oSet = new DBObjectSet($oSearch);
|
$oSet = new DBObjectSet($oSearch);
|
||||||
if ($oSet->Count() == 0)
|
if ($oSet->Count() == 0) {
|
||||||
{
|
|
||||||
$value = null;
|
$value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
|
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
|
||||||
{
|
{
|
||||||
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
|
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sDisplayValue = $this->GetObjectName($value);
|
$sDisplayValue = $this->GetObjectName($value);
|
||||||
}
|
}
|
||||||
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
|
||||||
@@ -599,33 +612,31 @@ EOF
|
|||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
|
||||||
{
|
|
||||||
$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>";
|
$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(
|
||||||
<<<JS
|
<<<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>');
|
||||||
}
|
}
|
||||||
JS
|
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=\"ibo-input-select--action-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(
|
||||||
<<<JS
|
<<<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>');
|
||||||
}
|
}
|
||||||
JS
|
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>";
|
$sHTMLValue .= "<span class=\"form_validation ibo-field-validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
|
||||||
|
|
||||||
return $sHTMLValue;
|
return $sHTMLValue;
|
||||||
@@ -642,6 +653,9 @@ JS
|
|||||||
$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 if (!empty($this->sFilter)) {
|
||||||
|
$aParams = array();
|
||||||
|
$oFilter = DBObjectSearch::FromOQL($this->sFilter);
|
||||||
} else {
|
} else {
|
||||||
$aParams = array();
|
$aParams = array();
|
||||||
$oFilter = new DBObjectSearch($this->sTargetClass);
|
$oFilter = new DBObjectSearch($this->sTargetClass);
|
||||||
@@ -656,7 +670,7 @@ JS
|
|||||||
'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.'_results',
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
$sCancel = Dict::S('UI:Button:Cancel');
|
$sCancel = Dict::S('UI:Button:Cancel');
|
||||||
@@ -664,11 +678,9 @@ JS
|
|||||||
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||||
$oPage->add(<<<HTML
|
$oPage->add(<<<HTML
|
||||||
<form id="fr_{$this->iId}" OnSubmit="return oACWidget_{$this->iId}.DoOk();">
|
<form id="fr_{$this->iId}" OnSubmit="return oACWidget_{$this->iId}.DoOk();">
|
||||||
<div id="dr_{$this->iId}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
<div id="dr_{$this->iId}">
|
||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
<div><p>{$sEmptyList}</p></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">
|
<input type="hidden" id="count_{$this->iId}_results" value="0">
|
||||||
</form>
|
</form>
|
||||||
</div></div>
|
</div></div>
|
||||||
@@ -677,8 +689,28 @@ HTML
|
|||||||
|
|
||||||
$sDialogTitle = addslashes($sTitle);
|
$sDialogTitle = addslashes($sTitle);
|
||||||
$oPage->add_ready_script(<<<JS
|
$oPage->add_ready_script(<<<JS
|
||||||
$('#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({
|
||||||
$('#fs_{$this->iId}').bind('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
|
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,
|
||||||
|
buttons: [
|
||||||
|
{ text: "$sCancel",
|
||||||
|
class: "ibo-is-alternative ibo-is-neutral",
|
||||||
|
click: function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
} },
|
||||||
|
{ text: "$sOK",
|
||||||
|
class: "ibo-is-regular ibo-is-primary",
|
||||||
|
click: function() {
|
||||||
|
oACWidget_{$this->iId}.DoOk();
|
||||||
|
} },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
$('#fs_{$this->iId}').on('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
|
||||||
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
|
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
|
||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
@@ -712,33 +744,34 @@ JS
|
|||||||
$iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode);
|
$iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode);
|
||||||
|
|
||||||
$oBlock = new DisplayBlock($oFilter, 'list_search', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
|
$oBlock = new DisplayBlock($oFilter, 'list_search', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
|
||||||
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId, 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results
|
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId.'_results', 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for objects to be selected
|
* Search for objects to be selected
|
||||||
*
|
*
|
||||||
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
||||||
* @param string $sFilter The OQL expression used to define/limit limit the scope of possible values
|
* @param string $sFilter The OQL expression used to define/limit limit the scope of possible values
|
||||||
* @param DBObject $oObj The current object for the OQL context
|
* @param DBObject $oObj The current object for the OQL context
|
||||||
* @param string $sContains The text of the autocomplete to filter the results
|
* @param string $sContains The text of the autocomplete to filter the results
|
||||||
* @param string $sOutputFormat
|
* @param string $sOutputFormat
|
||||||
* @param null $sOperation for the values @see ValueSetObjects->LoadValues()
|
* @param null $sOperation for the values @see ValueSetObjects->LoadValues()
|
||||||
*
|
*
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
* @throws OQLException
|
* @throws OQLException
|
||||||
*/
|
*/
|
||||||
public function AutoComplete(WebPage $oP, $sFilter, $oObj = null, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null)
|
public function AutoComplete(
|
||||||
|
WebPage $oP, $sFilter, $oObj = null, $sContains = '', $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (is_null($sFilter))
|
if (is_null($sFilter)) {
|
||||||
{
|
|
||||||
throw new Exception('Implementation: null value for allowed values definition');
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 = MetaModel::GetConfig()->Get('max_autocomplete_results');
|
||||||
$oValuesSet->SetLimit($iMax);
|
$oValuesSet->SetLimit($iMax);
|
||||||
$oValuesSet->SetSort(false);
|
$oValuesSet->SetSort(false);
|
||||||
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
||||||
@@ -746,9 +779,8 @@ JS
|
|||||||
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
|
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
|
||||||
asort($aValuesContains);
|
asort($aValuesContains);
|
||||||
$aValues = $aValuesContains;
|
$aValues = $aValuesContains;
|
||||||
if (sizeof($aValues) < $iMax)
|
if (sizeof($aValues) < $iMax) {
|
||||||
{
|
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
|
||||||
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
|
|
||||||
asort($aValuesContains);
|
asort($aValuesContains);
|
||||||
$iSize = sizeof($aValuesContains);
|
$iSize = sizeof($aValuesContains);
|
||||||
foreach ($aValuesContains as $sKey => $sFriendlyName)
|
foreach ($aValuesContains as $sKey => $sFriendlyName)
|
||||||
@@ -803,17 +835,27 @@ JS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the display name of the selected object, to fill back the autocomplete
|
* @param int $iObjId object ID
|
||||||
|
* @param string $sFormAttCode attcode if we need a value that isn't the display name
|
||||||
|
*
|
||||||
|
* @return string Either the display name of the selected object or the specified attribute value
|
||||||
|
*
|
||||||
|
* @uses \DBObject::GetName() to get display name
|
||||||
|
*
|
||||||
|
* @since 3.0.0 N°3227 add the $sAttCode parameter and method PHPDoc
|
||||||
*/
|
*/
|
||||||
public function GetObjectName($iObjId)
|
public function GetObjectName($iObjId, $sFormAttCode = null)
|
||||||
{
|
{
|
||||||
$aModifierProps = array();
|
$aModifierProps = array();
|
||||||
$aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode;
|
$aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode;
|
||||||
|
|
||||||
$oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps);
|
$oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps);
|
||||||
if ($oObj)
|
if ($oObj) {
|
||||||
{
|
if (is_null($sFormAttCode)) {
|
||||||
return $oObj->GetName();
|
return $oObj->GetName();
|
||||||
|
} else {
|
||||||
|
return $oObj->Get($sFormAttCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -863,7 +905,7 @@ JS
|
|||||||
$oPage->add('</div></div></div>');
|
$oPage->add('</div></div></div>');
|
||||||
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
|
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
|
||||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
|
$oPage->add_ready_script("$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoSelectObjectClass);");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -888,8 +930,7 @@ JS
|
|||||||
$sClassAlias = $oSet->GetFilter()->GetClassAlias();
|
$sClassAlias = $oSet->GetFilter()->GetClassAlias();
|
||||||
if (isset($aConsts[$sClassAlias]))
|
if (isset($aConsts[$sClassAlias]))
|
||||||
{
|
{
|
||||||
foreach($aConsts[$sClassAlias] as $sAttCode => $value)
|
foreach($aConsts[$sClassAlias] as $sAttCode => $value) {
|
||||||
{
|
|
||||||
$oNewObj->Set($sAttCode, $value);
|
$oNewObj->Set($sAttCode, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -898,44 +939,35 @@ JS
|
|||||||
// 3rd - set values from the page argument 'default'
|
// 3rd - set values from the page argument 'default'
|
||||||
$oNewObj->UpdateObjectFromArg('default');
|
$oNewObj->UpdateObjectFromArg('default');
|
||||||
|
|
||||||
$sDialogTitle = '';
|
|
||||||
$sClassLabel = MetaModel::GetName($this->sTargetClass);
|
$sClassLabel = MetaModel::GetName($this->sTargetClass);
|
||||||
$sClassIcon = MetaModel::GetClassIcon($this->sTargetClass);
|
$sHeaderTitleEscaped = utils::EscapeHtml(Dict::Format('UI:CreationTitle_Class', $sClassLabel));
|
||||||
$sObjClass = get_class($oNewObj);
|
|
||||||
$sObjKey = $oNewObj->GetKey();
|
|
||||||
$sHeaderTitle = Dict::Format('UI:CreationTitle_Class', $sClassLabel);
|
|
||||||
$oPage->add(<<<HTML
|
$oPage->add(<<<HTML
|
||||||
<div id="ac_create_{$this->iId}">
|
<div id="ac_create_{$this->iId}" title="{$sHeaderTitleEscaped}">
|
||||||
<!-- Beginning of object-details -->
|
<div id="dcr_{$this->iId}">
|
||||||
<div class="object-details" data-object-class="$sObjClass" data-object-id="$sObjKey" data-object-mode="create">
|
|
||||||
<!-- Beginning of wizContainer -->
|
|
||||||
<div class="wizContainer" style="vertical-align:top;">
|
|
||||||
<div id="dcr_{$this->iId}">
|
|
||||||
<h1>$sClassIcon $sHeaderTitle</h1>
|
|
||||||
HTML
|
HTML
|
||||||
);
|
);
|
||||||
$aFieldsFlags = array();
|
$aFieldsFlags = array();
|
||||||
$aFieldsComments = array();
|
$aFieldsComments = array();
|
||||||
foreach(MetaModel::ListAttributeDefs($this->sTargetClass) as $sAttCode => $oAttDef)
|
foreach (MetaModel::ListAttributeDefs($this->sTargetClass) as $sAttCode => $oAttDef) {
|
||||||
{
|
if (($oAttDef instanceof AttributeBlob) || (false)) {
|
||||||
if (($oAttDef instanceof AttributeBlob) || (false))
|
|
||||||
{
|
|
||||||
$aFieldsFlags[$sAttCode] = OPT_ATT_READONLY;
|
$aFieldsFlags[$sAttCode] = OPT_ATT_READONLY;
|
||||||
$aFieldsComments[$sAttCode] = ' <img src="../images/transp-lock.png" style="vertical-align:middle" title="'.htmlentities(Dict::S('UI:UploadNotSupportedInThisMode')).'"/>';
|
$aFieldsComments[$sAttCode] = ' <img src="../images/transp-lock.png" style="vertical-align:middle" title="'.htmlentities(Dict::S('UI:UploadNotSupportedInThisMode')).'"/>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), array('formPrefix' => $this->iId, 'noRelations' => true, 'fieldsFlags' => $aFieldsFlags, 'fieldsComments' => $aFieldsComments));
|
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), array('formPrefix' => $this->iId, 'noRelations' => true, 'fieldsFlags' => $aFieldsFlags, 'fieldsComments' => $aFieldsComments));
|
||||||
$oPage->add(<<<HTML
|
$oPage->add(<<<HTML
|
||||||
</div>
|
</div>
|
||||||
</div><!-- End of wizContainer -->
|
|
||||||
</div><!-- End of object-details -->
|
|
||||||
</div>
|
</div>
|
||||||
HTML
|
HTML
|
||||||
);
|
);
|
||||||
// $oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: 'auto', autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
|
||||||
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
$oPage->add_ready_script(<<<JS
|
||||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
|
$('#ac_create_{$this->iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
|
||||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);");
|
$('#dcr_{$this->iId} form').removeAttr('onsubmit');
|
||||||
|
$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);
|
||||||
|
JS
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -968,8 +1000,8 @@ HTML
|
|||||||
$oPage->add('<div class="treecontrol" id="treecontrolid"><a href="?#">'.Dict::S("UI:Treeview:CollapseAll").'</a> | <a href="?#">'.Dict::S("UI:Treeview:ExpandAll").'</a></div>');
|
$oPage->add('<div class="treecontrol" id="treecontrolid"><a href="?#">'.Dict::S("UI:Treeview:CollapseAll").'</a> | <a href="?#">'.Dict::S("UI:Treeview:ExpandAll").'</a></div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPage->add("<input type=\"button\" id=\"btn_cancel_{$this->iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#dlg_tree_{$this->iId}').dialog('close');\"> ");
|
$oPage->add("<input type=\"button\" class=\"ibo-button ibo-is-regular ibo-is-neutral\" id=\"btn_cancel_{$this->iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#dlg_tree_{$this->iId}').dialog('close');\"> ");
|
||||||
$oPage->add("<input type=\"button\" id=\"btn_ok_{$this->iId}\" value=\"".Dict::S('UI:Button:Ok')."\" onClick=\"oACWidget_{$this->iId}.DoHKOk();\">");
|
$oPage->add("<input type=\"button\" class=\"ibo-button ibo-is-regular ibo-is-primary\" id=\"btn_ok_{$this->iId}\" value=\"".Dict::S('UI:Button:Ok')."\" onClick=\"oACWidget_{$this->iId}.DoHKOk();\">");
|
||||||
|
|
||||||
$oPage->add('</div></div>');
|
$oPage->add('</div></div>');
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2016 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
* UI wdiget for displaying and editing one-way encrypted passwords
|
* UI wdiget for displaying and editing one-way encrypted passwords
|
||||||
*
|
*
|
||||||
* @author Romain Quetiez
|
* @author Romain Quetiez
|
||||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -70,11 +70,7 @@ class UIHTMLEditorWidget
|
|||||||
// To change the default settings of the editor,
|
// To change the default settings of the editor,
|
||||||
// a) edit the file /js/ckeditor/config.js
|
// a) edit the file /js/ckeditor/config.js
|
||||||
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
||||||
$aConfig = array();
|
$aConfig = utils::GetCkeditorPref();
|
||||||
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
|
|
||||||
$aConfig['language'] = $sLanguage;
|
|
||||||
$aConfig['contentsLanguage'] = $sLanguage;
|
|
||||||
$aConfig['extraPlugins'] = 'disabler,codesnippet';
|
|
||||||
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
|
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
|
||||||
if ($sWidthSpec != '')
|
if ($sWidthSpec != '')
|
||||||
{
|
{
|
||||||
@@ -97,10 +93,10 @@ class UIHTMLEditorWidget
|
|||||||
// The most relevant solution would be to implement a plugin to CKEdit, and handle the internal events like: setData, insertHtml, insertElement, loadSnapshot, key, afterUndo, afterRedo
|
// The most relevant solution would be to implement a plugin to CKEdit, and handle the internal events like: setData, insertHtml, insertElement, loadSnapshot, key, afterUndo, afterRedo
|
||||||
|
|
||||||
// Could also be bound to 'instanceReady.ckeditor'
|
// Could also be bound to 'instanceReady.ckeditor'
|
||||||
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
|
$oPage->add_ready_script("$('#$iId').on('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$iId').bind('update', function(evt){
|
$('#$iId').on('update', function(evt){
|
||||||
BlockField('cke_$iId', $('#$iId').prop('disabled'));
|
BlockField('cke_$iId', $('#$iId').prop('disabled'));
|
||||||
//Delayed execution - ckeditor must be properly initialized before setting readonly
|
//Delayed execution - ckeditor must be properly initialized before setting readonly
|
||||||
var retryCount = 0;
|
var retryCount = 0;
|
||||||
|
|||||||
@@ -1,28 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
/*
|
||||||
//
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
// This file is part of iTop.
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
//
|
*/
|
||||||
// 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
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||||
// (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 UILinksWidgetDirect
|
* Class UILinksWidgetDirect
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class UILinksWidgetDirect
|
class UILinksWidgetDirect
|
||||||
{
|
{
|
||||||
protected $sClass;
|
protected $sClass;
|
||||||
@@ -243,23 +233,21 @@ class UILinksWidgetDirect
|
|||||||
protected function DisplayEditInPlace(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
|
protected function DisplayEditInPlace(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
|
||||||
{
|
{
|
||||||
$aAttribs = $this->GetTableConfig();
|
$aAttribs = $this->GetTableConfig();
|
||||||
|
|
||||||
$oValue->Rewind();
|
$oValue->Rewind();
|
||||||
$oPage->add('<table class="listContainer" id="'.$this->sInputid.'"><tr><td>');
|
|
||||||
|
|
||||||
$aData = array();
|
$aData = array();
|
||||||
while($oLinkObj = $oValue->Fetch())
|
while ($oLinkObj = $oValue->Fetch()) {
|
||||||
{
|
|
||||||
$aRow = array();
|
$aRow = array();
|
||||||
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.$oLinkObj->GetKey().'"/>';
|
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.$oLinkObj->GetKey().'"/>';
|
||||||
foreach($this->aZlist as $sLinkedAttCode)
|
foreach ($this->aZlist as $sLinkedAttCode) {
|
||||||
{
|
|
||||||
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
|
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
|
||||||
}
|
}
|
||||||
$aData[] = $aRow;
|
$aData[] = $aRow;
|
||||||
}
|
}
|
||||||
$oPage->table($aAttribs, $aData);
|
$oDiv = UIContentBlockUIBlockFactory::MakeStandard($this->sInputid, ['listContainer']);
|
||||||
$oPage->add('</td></tr></table>'); //listcontainer
|
$oPage->AddSubBlock($oDiv);
|
||||||
|
$oDatatable = DataTableUIBlockFactory::MakeForForm($this->sInputid, $aAttribs, $aData);
|
||||||
|
$oDatatable->SetOptions(['select_mode' => 'custom']);
|
||||||
|
$oDiv->AddSubBlock($oDatatable);
|
||||||
$sInputName = $sFormPrefix.'attr_'.$this->sAttCode;
|
$sInputName = $sFormPrefix.'attr_'.$this->sAttCode;
|
||||||
$aLabels = array(
|
$aLabels = array(
|
||||||
'delete' => Dict::S('UI:Button:Delete'),
|
'delete' => Dict::S('UI:Button:Delete'),
|
||||||
@@ -349,11 +337,10 @@ class UILinksWidgetDirect
|
|||||||
|
|
||||||
$oPage->add(<<<HTML
|
$oPage->add(<<<HTML
|
||||||
<form id="ObjectsAddForm_{$this->sInputid}">
|
<form id="ObjectsAddForm_{$this->sInputid}">
|
||||||
<div id="SearchResultsToAdd_{$this->sInputid}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
<div id="SearchResultsToAdd_{$this->sInputid}">
|
||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
<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>
|
</form>
|
||||||
HTML
|
HTML
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,32 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
/*
|
||||||
//
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
// This file is part of iTop.
|
|
||||||
//
|
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// iTop is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UILinksWidget
|
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory;
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||||
use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\FormTableRow\FormTableRow;
|
use Combodo\iTop\Application\UI\Base\Component\DataTable\StaticTable\FormTableRow\FormTableRow;
|
||||||
use Combodo\iTop\Renderer\BlockRenderer;
|
use Combodo\iTop\Application\UI\Links\Indirect\BlockIndirectLinksEdit\BlockIndirectLinksEdit;
|
||||||
|
use Combodo\iTop\Application\UI\Links\Indirect\BlockObjectPickerDialog\BlockObjectPickerDialog;
|
||||||
|
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||||
|
|
||||||
require_once(APPROOT.'application/displayblock.class.inc.php');
|
require_once(APPROOT.'application/displayblock.class.inc.php');
|
||||||
|
|
||||||
@@ -100,8 +82,7 @@ class UILinksWidget
|
|||||||
$this->m_aEditableFields[] = $this->m_sExtKeyToRemote;
|
$this->m_aEditableFields[] = $this->m_sExtKeyToRemote;
|
||||||
|
|
||||||
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
|
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
|
||||||
foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef)
|
foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef) {
|
||||||
{
|
|
||||||
$sRemoteAttCode = $oRemoteAttDef->GetCode();
|
$sRemoteAttCode = $oRemoteAttDef->GetCode();
|
||||||
$this->m_aTableConfig['static::'.$sRemoteAttCode] = array(
|
$this->m_aTableConfig['static::'.$sRemoteAttCode] = array(
|
||||||
'label' => $oRemoteAttDef->GetLabel(),
|
'label' => $oRemoteAttDef->GetLabel(),
|
||||||
@@ -342,29 +323,14 @@ 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 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 \Combodo\iTop\Application\UI\Base\Component\DataTable\StaticTable\FormTable\FormTable
|
||||||
* @throws \ReflectionException
|
|
||||||
* @throws \Twig\Error\LoaderError
|
|
||||||
* @throws \Twig\Error\RuntimeError
|
|
||||||
* @throws \Twig\Error\SyntaxError
|
|
||||||
*/
|
*/
|
||||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
protected function GetFormTableBlock($aConfig, $aData)
|
||||||
{
|
{
|
||||||
$oTable = DataTableFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig);
|
return DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aData);
|
||||||
|
|
||||||
foreach ($aData as $iRowId => $aRow)
|
|
||||||
{
|
|
||||||
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aRow, $iRowId);
|
|
||||||
$oTable->AddRow($oRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sHtml = BlockRenderer::RenderBlockTemplates($oTable);
|
|
||||||
|
|
||||||
return $sHtml;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -379,65 +345,65 @@ JS
|
|||||||
*
|
*
|
||||||
* @return string The HTML fragment to be inserted into the page
|
* @return string The HTML fragment to be inserted into the page
|
||||||
* @throws \ArchivedObjectException
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \ConfigException
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \DictExceptionMissingString
|
* @throws \CoreUnexpectedValue
|
||||||
|
* @throws \MySQLException
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws \Twig\Error\LoaderError
|
||||||
|
* @throws \Twig\Error\RuntimeError
|
||||||
|
* @throws \Twig\Error\SyntaxError
|
||||||
*/
|
*/
|
||||||
public function Display(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj)
|
public function Display(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj): string
|
||||||
{
|
{
|
||||||
$sHtmlValue = '';
|
$sLinkedSetId = "{$this->m_sAttCode}{$this->m_sNameSuffix}";
|
||||||
$sHtmlValue .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
|
|
||||||
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
|
$oBlock = new BlockIndirectLinksEdit("linkedset_{$sLinkedSetId}", ["ibo-block-indirect-links--edit"]);
|
||||||
|
|
||||||
|
$oBlock->sLinkedSetId = $sLinkedSetId;
|
||||||
|
$oBlock->sClass = $this->m_sClass;
|
||||||
|
$oBlock->sAttCode = $this->m_sAttCode;
|
||||||
|
$oBlock->iInputId = $this->m_iInputId;
|
||||||
|
$oBlock->sNameSuffix = $this->m_sNameSuffix;
|
||||||
|
$oBlock->bDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
||||||
|
$oBlock->oWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
|
$oBlock->sExtKeyToRemote = $this->m_sExtKeyToRemote;
|
||||||
|
// Don't automatically launch the search if the table is huge
|
||||||
|
$oBlock->bJSDoSearch = utils::IsHighCardinality($this->m_sRemoteClass) ? 'false' : 'true';
|
||||||
|
$oBlock->sFormPrefix = $sFormPrefix;
|
||||||
|
$oBlock->sRemoteClass = $this->m_sRemoteClass;
|
||||||
|
|
||||||
$oValue->Rewind();
|
$oValue->Rewind();
|
||||||
$aForm = array();
|
$aForm = array();
|
||||||
$iAddedId = -1; // Unique id for new links
|
$iAddedId = -1; // Unique id for new links
|
||||||
|
|
||||||
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
|
||||||
// Don't automatically launch the search if the table is huge
|
|
||||||
$bDoSearch = !utils::IsHighCardinality($this->m_sRemoteClass);
|
|
||||||
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
|
||||||
$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}.Init();
|
|
||||||
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),
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote),
|
||||||
false /* Must not be found */);
|
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
|
$bReadOnly = true;
|
||||||
{
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */, true);
|
||||||
$bReadOnly = true;
|
}
|
||||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($oCurrentLink->IsNew())
|
if ($oCurrentLink->IsNew()) {
|
||||||
{
|
$key = $iAddedId--;
|
||||||
$key = $iAddedId--;
|
} else {
|
||||||
}
|
$key = $oCurrentLink->GetKey();
|
||||||
else
|
}
|
||||||
{
|
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||||
$key = $oCurrentLink->GetKey();
|
|
||||||
}
|
|
||||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
|
||||||
}
|
}
|
||||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
$oDataTable = DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aForm);
|
||||||
// To prevent adding forms inside the main form
|
$oDataTable->SetOptions(['select_mode' => 'custom']);
|
||||||
|
$oBlock->AddSubBlock($oDataTable);
|
||||||
|
|
||||||
$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();\" >";
|
$oBlock->AddControls();
|
||||||
$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 .= "<span style=\"clear:both;\"><p> </p></span>\n";
|
return ConsoleBlockRenderer::RenderBlockTemplateInPage($oPage, $oBlock);
|
||||||
$sHtmlValue .= "</div>\n";
|
|
||||||
$oPage->add_at_the_end("<div id=\"dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}\"></div>"); // To prevent adding forms inside the main form
|
|
||||||
return $sHtmlValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -481,8 +447,6 @@ JS
|
|||||||
*/
|
*/
|
||||||
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array())
|
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array())
|
||||||
{
|
{
|
||||||
//$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');
|
||||||
@@ -500,38 +464,32 @@ JS
|
|||||||
$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);
|
|
||||||
$oPage->AddUiBlock($oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
$sLinkedSetId = "{$this->m_sAttCode}{$this->m_sNameSuffix}";
|
||||||
|
|
||||||
|
$oBlock = new BlockObjectPickerDialog();
|
||||||
|
$oPage->AddUiBlock($oBlock);
|
||||||
|
|
||||||
|
$oBlock->sLinkedSetId = $sLinkedSetId;
|
||||||
|
$oBlock->iInputId = $this->m_iInputId;
|
||||||
|
$oBlock->sLinkedClassName = MetaModel::GetName($this->m_sLinkedClass);
|
||||||
|
$oBlock->sClassName = MetaModel::GetName($this->m_sClass);
|
||||||
|
|
||||||
|
$oDisplayBlock = new DisplayBlock($oFilter, 'search', false);
|
||||||
|
$oBlock->AddSubBlock($oDisplayBlock->GetDisplay($oPage, "SearchFormToAdd_{$sLinkedSetId}",
|
||||||
array(
|
array(
|
||||||
'menu' => false,
|
'menu' => false,
|
||||||
'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
'result_list_outer_selector' => "SearchResultsToAdd_{$sLinkedSetId}",
|
||||||
'table_id' => "add_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
'table_id' => "add_{$sLinkedSetId}",
|
||||||
'table_inner_id' => "ResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}",
|
'table_inner_id' => "ResultsToAdd_{$sLinkedSetId}",
|
||||||
'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,
|
||||||
)));
|
)));
|
||||||
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
|
||||||
$sCancel = Dict::S('UI:Button:Cancel');
|
|
||||||
$sAdd = Dict::S('UI:Button:Add');
|
|
||||||
|
|
||||||
$oPage->add(<<<HTML
|
$oBlock->AddForm();
|
||||||
<form id="ObjectsAddForm_{$this->m_sAttCode}{$this->m_sNameSuffix}">
|
|
||||||
<div id="SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}" style="vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;">
|
|
||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
|
||||||
</div>
|
|
||||||
<input type="hidden" id="count_{$this->m_sAttCode}{$this->m_sNameSuffix}" value="0"/>
|
|
||||||
<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}').resize(oWidget{$this->m_iInputId}.UpdateSizes);");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -581,18 +539,44 @@ HTML
|
|||||||
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||||
|
|
||||||
$iAdditionId = $iMaxAddedId + 1;
|
$iAdditionId = $iMaxAddedId + 1;
|
||||||
foreach($aLinkedObjectIds as $iObjectId)
|
foreach ($aLinkedObjectIds as $iObjectId) {
|
||||||
{
|
|
||||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
|
||||||
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
|
||||||
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId);
|
$oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId);
|
||||||
$oP->AddUiBlock($oRow);
|
$oP->AddUiBlock($oRow);
|
||||||
$iAdditionId++;
|
$iAdditionId++;
|
||||||
|
} else {
|
||||||
|
$oP->p(Dict::Format('UI:Error:Object_Class_Id_NotFound', $this->m_sLinkedClass, $iObjectId));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oP
|
||||||
|
* @param int $iMaxAddedId
|
||||||
|
* @param $oFullSetFilter
|
||||||
|
* @param DBObject $oCurrentObj
|
||||||
|
*
|
||||||
|
* @throws \ArchivedObjectException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public function DoAddIndirectLinks(JsonPage $oP, $iMaxAddedId, $oFullSetFilter, $oCurrentObj)
|
||||||
|
{
|
||||||
|
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||||
|
|
||||||
|
$iAdditionId = $iMaxAddedId + 1;
|
||||||
|
foreach ($aLinkedObjectIds as $iObjectId) {
|
||||||
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId, false);
|
||||||
|
if (is_object($oLinkedObj)) {
|
||||||
|
$aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids
|
||||||
|
$aData = [];
|
||||||
|
foreach ($aRow as $item) {
|
||||||
|
$aData[] = $item;
|
||||||
|
}
|
||||||
|
$oP->AddData($aData);
|
||||||
|
$iAdditionId++;
|
||||||
|
} else {
|
||||||
$oP->p(Dict::Format('UI:Error:Object_Class_Id_NotFound', $this->m_sLinkedClass, $iObjectId));
|
$oP->p(Dict::Format('UI:Error:Object_Class_Id_NotFound', $this->m_sLinkedClass, $iObjectId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* Class UIPasswordWidget
|
* Class UIPasswordWidget
|
||||||
* UI wdiget for displaying and editing one-way encrypted passwords
|
* UI wdiget for displaying and editing one-way encrypted passwords
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -67,10 +67,10 @@ class UIPasswordWidget
|
|||||||
|
|
||||||
$sHtmlValue .= '<span class="form_validation ibo-field-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').on('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').on('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
||||||
$oPage->add_ready_script("$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
$oPage->add_ready_script("$('#{$this->iId}_confirm').on('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
||||||
$oPage->add_ready_script("$('#{$this->iId}').bind('update', function(evt, sFormId)
|
$oPage->add_ready_script("$('#{$this->iId}').on('update', function(evt, sFormId)
|
||||||
{
|
{
|
||||||
if ($(this).prop('disabled'))
|
if ($(this).prop('disabled'))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2018 Combodo SARL
|
* Copyright (C) 2010-2021 Combodo SARL
|
||||||
*
|
*
|
||||||
* This file is part of iTop.
|
* This file is part of iTop.
|
||||||
*
|
*
|
||||||
@@ -64,16 +64,42 @@ class UISearchFormForeignKeys
|
|||||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
<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>
|
</form>
|
||||||
HTML
|
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(
|
||||||
$oPage->add_ready_script("$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});");
|
<<<JS
|
||||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_iInputId} form').bind('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
$('#dlg_{$this->m_iInputId}').dialog({
|
||||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_iInputId}').resize(oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);");
|
width: $(window).width()*0.8,
|
||||||
|
height: $(window).height()*0.8,
|
||||||
|
autoOpen: false,
|
||||||
|
modal: true,
|
||||||
|
resizeStop: oForeignKeysWidget{$this->m_iInputId}.UpdateSizes,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: Dict.S('UI:Button:Cancel'),
|
||||||
|
class: "cancel ibo-is-alternative ibo-is-neutral",
|
||||||
|
click: function() {
|
||||||
|
$('#dlg_{$this->m_iInputId}').dialog('close');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: Dict.S('UI:Button:Add'),
|
||||||
|
id: 'btn_ok_{$this->m_iInputId}',
|
||||||
|
class: "ok ibo-is-regular ibo-is-primary",
|
||||||
|
click: function() {
|
||||||
|
oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
});
|
||||||
|
$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
|
||||||
|
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
|
||||||
|
$('#SearchFormToAdd_{$this->m_iInputId}').resize(oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
|
||||||
|
JS
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
|
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
/**
|
/**
|
||||||
* Class UIWizard
|
* Class UIWizard
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -270,23 +270,20 @@ $sJSHandlerCode
|
|||||||
$aFields = array(); // reset
|
$aFields = array(); // reset
|
||||||
foreach(MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode=>$oAttDef)
|
foreach(MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode=>$oAttDef)
|
||||||
{
|
{
|
||||||
$iOptions = (isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode])) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
|
$iOptions = (isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode])) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
|
||||||
if ( ($sStateAttCode != $sAttCode) &&
|
if (($sStateAttCode != $sAttCode) &&
|
||||||
(!$oAttDef->IsExternalField()) &&
|
(!$oAttDef->IsExternalField()) &&
|
||||||
(($iOptions & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) == 0) &&
|
($oAttDef->IsWritable()) &&
|
||||||
(!isset($aFieldsDone[$sAttCode])) )
|
(($iOptions & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) == 0) &&
|
||||||
|
(!isset($aFieldsDone[$sAttCode]))) {
|
||||||
{
|
// 'State', external fields, read-only (both because of the flags or the attribute type) and hidden fields
|
||||||
// 'State', external fields, read-only and hidden fields
|
|
||||||
// and fields that are already listed in the wizard
|
// and fields that are already listed in the wizard
|
||||||
// are removed from the 'optional' part of the wizard
|
// are removed from the 'optional' part of the wizard
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||||
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
|
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
|
||||||
$aFields[$sAttCode] = array();
|
$aFields[$sAttCode] = array();
|
||||||
foreach($aPrerequisites as $sCode)
|
foreach ($aPrerequisites as $sCode) {
|
||||||
{
|
if (!isset($aFieldsDone[$sCode])) {
|
||||||
if (!isset($aFieldsDone[$sCode]))
|
|
||||||
{
|
|
||||||
// retain only the dependencies that were not covered
|
// retain only the dependencies that were not covered
|
||||||
// in the 'mandatory' part of the wizard
|
// in the 'mandatory' part of the wizard
|
||||||
$aFields[$sAttCode][$sCode] = '';
|
$aFields[$sAttCode][$sCode] = '';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
/**
|
/**
|
||||||
* Store and retrieve user custom dashboards
|
* Store and retrieve user custom dashboards
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
require_once(APPROOT.'/core/dbobject.class.php');
|
require_once(APPROOT.'/core/dbobject.class.php');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
// Copyright (C) 2010-2021 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
/**
|
/**
|
||||||
* Store and retrieve user's preferences (i.e persistent per user settings)
|
* Store and retrieve user's preferences (i.e persistent per user settings)
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
require_once(APPROOT.'/core/dbobject.class.php');
|
require_once(APPROOT.'/core/dbobject.class.php');
|
||||||
@@ -34,7 +34,8 @@ require_once(APPROOT.'/core/userrights.class.inc.php');
|
|||||||
*/
|
*/
|
||||||
class appUserPreferences extends DBObject
|
class appUserPreferences extends DBObject
|
||||||
{
|
{
|
||||||
private static $oUserPrefs = null; // Local cache
|
/** @var array Associative array of the prefs. of users: <USER_ID> => <PREFS> */
|
||||||
|
private static $aUsersPrefs = []; // Local cache
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of the given property/preference
|
* Get the value of the given property/preference
|
||||||
@@ -42,31 +43,35 @@ class appUserPreferences extends DBObject
|
|||||||
*
|
*
|
||||||
* @param string $sCode Code/Name of the property to set
|
* @param string $sCode Code/Name of the property to set
|
||||||
* @param mixed $defaultValue The default value
|
* @param mixed $defaultValue The default value
|
||||||
|
* @param string|null $sUserId Added in 3.0.0. ID of the user we want the pref. from, default is the current user
|
||||||
*
|
*
|
||||||
* @return mixed The value of the property for the current user
|
* @return mixed The value of the property for the current user
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \CoreUnexpectedValue
|
* @throws \CoreUnexpectedValue
|
||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
|
* @throws \OQLException
|
||||||
|
* @since 3.0.0 Added the $sUserId parameter
|
||||||
*/
|
*/
|
||||||
public static function GetPref($sCode, $defaultValue)
|
public static function GetPref($sCode, $defaultValue, ?string $sUserId = null)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
if (null === $sUserId) {
|
||||||
{
|
$sUserId = UserRights::GetUserId();
|
||||||
self::Load();
|
|
||||||
}
|
}
|
||||||
$aPrefs = self::$oUserPrefs->Get('preferences');
|
|
||||||
if (array_key_exists($sCode, $aPrefs))
|
if (false === array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
{
|
self::Load($sUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aPrefs = self::$aUsersPrefs[$sUserId]->Get('preferences');
|
||||||
|
if (array_key_exists($sCode, $aPrefs)) {
|
||||||
return $aPrefs[$sCode];
|
return $aPrefs[$sCode];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return $defaultValue;
|
return $defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value for a given preference, and stores it into the database
|
* Set the value for a given preference for the current user, 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 mixed $value Value to set
|
* @param mixed $value Value to set
|
||||||
@@ -78,25 +83,23 @@ class appUserPreferences extends DBObject
|
|||||||
*/
|
*/
|
||||||
public static function SetPref($sCode, $value)
|
public static function SetPref($sCode, $value)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
$sUserId = UserRights::GetUserId();
|
||||||
{
|
if (false === array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
self::Load();
|
self::Load($sUserId);
|
||||||
}
|
}
|
||||||
$aPrefs = self::$oUserPrefs->Get('preferences');
|
|
||||||
if (array_key_exists($sCode, $aPrefs) && ($aPrefs[$sCode] === $value))
|
$aPrefs = self::$aUsersPrefs[$sUserId]->Get('preferences');
|
||||||
{
|
if (array_key_exists($sCode, $aPrefs) && ($aPrefs[$sCode] === $value)) {
|
||||||
// Do not write it again
|
// Do not write it again
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aPrefs[$sCode] = $value;
|
$aPrefs[$sCode] = $value;
|
||||||
self::$oUserPrefs->Set('preferences', $aPrefs);
|
self::$aUsersPrefs[$sUserId]->Set('preferences', $aPrefs);
|
||||||
self::Save();
|
self::Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) for the current user, 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
|
||||||
@@ -108,37 +111,33 @@ class appUserPreferences extends DBObject
|
|||||||
*/
|
*/
|
||||||
public static function UnsetPref($sCodeOrPattern, $bPattern = false)
|
public static function UnsetPref($sCodeOrPattern, $bPattern = false)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
$sUserId = UserRights::GetUserId();
|
||||||
{
|
if (false === array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
self::Load();
|
self::Load($sUserId);
|
||||||
}
|
}
|
||||||
$aPrefs = self::$oUserPrefs->Get('preferences');
|
|
||||||
if ($bPattern)
|
$aPrefs = self::$aUsersPrefs[$sUserId]->Get('preferences');
|
||||||
{
|
if ($bPattern) {
|
||||||
// the supplied code is a pattern, clear all preferences that match
|
// the supplied code is a pattern, clear all preferences that match
|
||||||
foreach($aPrefs as $sKey => $void)
|
foreach ($aPrefs as $sKey => $void) {
|
||||||
{
|
if (preg_match($sCodeOrPattern, $sKey)) {
|
||||||
if (preg_match($sCodeOrPattern, $sKey))
|
|
||||||
{
|
|
||||||
unset($aPrefs[$sKey]);
|
unset($aPrefs[$sKey]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self::$oUserPrefs->Set('preferences', $aPrefs);
|
self::$aUsersPrefs[$sUserId]->Set('preferences', $aPrefs);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
unset($aPrefs[$sCodeOrPattern]);
|
unset($aPrefs[$sCodeOrPattern]);
|
||||||
self::$oUserPrefs->Set('preferences', $aPrefs);
|
self::$aUsersPrefs[$sUserId]->Set('preferences', $aPrefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save only if needed
|
// Save only if needed
|
||||||
if (self::$oUserPrefs->IsModified())
|
if (self::$aUsersPrefs[$sUserId]->IsModified()) {
|
||||||
{
|
|
||||||
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 current user, packed as a JSON object
|
||||||
*
|
*
|
||||||
* @return string JSON representation of the preferences
|
* @return string JSON representation of the preferences
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
@@ -147,11 +146,13 @@ class appUserPreferences extends DBObject
|
|||||||
*/
|
*/
|
||||||
public static function GetAsJSON()
|
public static function GetAsJSON()
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs == null)
|
$sUserId = UserRights::GetUserId();
|
||||||
{
|
if (false === array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
self::Load();
|
self::Load($sUserId);
|
||||||
}
|
}
|
||||||
$aPrefs = self::$oUserPrefs->Get('preferences');
|
|
||||||
|
$aPrefs = self::$aUsersPrefs[$sUserId]->Get('preferences');
|
||||||
|
|
||||||
return json_encode($aPrefs);
|
return json_encode($aPrefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,32 +163,33 @@ class appUserPreferences extends DBObject
|
|||||||
*/
|
*/
|
||||||
public static function ResetPreferences()
|
public static function ResetPreferences()
|
||||||
{
|
{
|
||||||
self::$oUserPrefs = null;
|
self::$aUsersPrefs = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function to ERASE all the preferences from the current user
|
* Call this function to ERASE all the preferences from the current user (only in memory, not in DB)
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function ClearPreferences()
|
public static function ClearPreferences()
|
||||||
{
|
{
|
||||||
self::$oUserPrefs = null;
|
$sUserId = UserRights::GetUserId();
|
||||||
|
unset(self::$aUsersPrefs[$sUserId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save preferences in the DB
|
* Save preferences of the current user in the DB, for now we don't allow interfering with an other users preferences
|
||||||
*
|
*
|
||||||
* @return void;
|
* @return void;
|
||||||
*/
|
*/
|
||||||
protected static function Save()
|
protected static function Save()
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs != null)
|
$sUserId = UserRights::GetUserId();
|
||||||
{
|
|
||||||
if (self::$oUserPrefs->IsModified())
|
if (array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
{
|
if (self::$aUsersPrefs[$sUserId]->IsModified()) {
|
||||||
utils::PushArchiveMode(false);
|
utils::PushArchiveMode(false);
|
||||||
self::$oUserPrefs->DBUpdate();
|
self::$aUsersPrefs[$sUserId]->DBUpdate();
|
||||||
utils::PopArchiveMode();
|
utils::PopArchiveMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,36 +199,45 @@ 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
|
||||||
*
|
*
|
||||||
|
* @param string|null $sUserId Added in 3.0.0. ID of the user to load the prefs for, if null then current user will be used.
|
||||||
|
*
|
||||||
* @return void;
|
* @return void;
|
||||||
* @throws \CoreException
|
* @throws \CoreException
|
||||||
* @throws \CoreUnexpectedValue
|
* @throws \CoreUnexpectedValue
|
||||||
* @throws \MySQLException
|
* @throws \MySQLException
|
||||||
|
* @throws \OQLException
|
||||||
|
* @since 3.0.0 Added $sUserId parameter
|
||||||
*/
|
*/
|
||||||
protected static function Load()
|
protected static function Load(?string $sUserId = null)
|
||||||
{
|
{
|
||||||
if (self::$oUserPrefs != null) return;
|
// Already in cache
|
||||||
|
if (array_key_exists($sUserId, self::$aUsersPrefs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $sUserId) {
|
||||||
|
$sUserId = UserRights::GetUserId();
|
||||||
|
}
|
||||||
|
|
||||||
$oSearch = new DBObjectSearch('appUserPreferences');
|
$oSearch = new DBObjectSearch('appUserPreferences');
|
||||||
$oSearch->AddCondition('userid', UserRights::GetUserId(), '=');
|
$oSearch->AddCondition('userid', $sUserId, '=');
|
||||||
$oSet = new DBObjectSet($oSearch);
|
$oSet = new DBObjectSet($oSearch);
|
||||||
$oObj = $oSet->Fetch();
|
$oObj = $oSet->Fetch();
|
||||||
if ($oObj == null)
|
if ($oObj == null) {
|
||||||
{
|
|
||||||
// No prefs (yet) for this user, create the object
|
// No prefs (yet) for this user, create the object
|
||||||
$oObj = new appUserPreferences();
|
$oObj = new appUserPreferences();
|
||||||
$oObj->Set('userid', UserRights::GetUserId());
|
$oObj->Set('userid', $sUserId);
|
||||||
$oObj->Set('preferences', array()); // Default preferences: an empty array
|
$oObj->Set('preferences', array()); // Default preferences: an empty array
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
utils::PushArchiveMode(false);
|
utils::PushArchiveMode(false);
|
||||||
$oObj->DBInsert();
|
$oObj->DBInsert();
|
||||||
utils::PopArchiveMode();
|
utils::PopArchiveMode();
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch (Exception $e) {
|
||||||
{
|
|
||||||
// Ignore errors
|
// Ignore errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self::$oUserPrefs = $oObj;
|
self::$aUsersPrefs[$sUserId] = $oObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/WebPage.php
|
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/WebPage.php, now loadable using autoloader
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/WebPage.php, now loadable using autoloader');
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user