mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-14 07:54:10 +01:00
Compare commits
919 Commits
N2011
...
2.7.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a108be8517 | ||
|
|
3e57c3b1e9 | ||
|
|
f18e27a183 | ||
|
|
358efb0f2f | ||
|
|
723fc917f1 | ||
|
|
01f34eea29 | ||
|
|
705d941979 | ||
|
|
691acb45e6 | ||
|
|
97e4ff30ff | ||
|
|
34c76c735a | ||
|
|
47d8e35639 | ||
|
|
d4dc739b30 | ||
|
|
b84859b07e | ||
|
|
3f154fa765 | ||
|
|
f31e32d7a9 | ||
|
|
1589535a45 | ||
|
|
53353ec9e1 | ||
|
|
a601b1c59a | ||
|
|
e093abcb2b | ||
|
|
01cb88a661 | ||
|
|
5ef32b6b31 | ||
|
|
ba1c719568 | ||
|
|
0507e4f4a8 | ||
|
|
60eb312e68 | ||
|
|
044a8926b3 | ||
|
|
acf8c9d49e | ||
|
|
d99e79eb3f | ||
|
|
843c8ccd38 | ||
|
|
d45326606d | ||
|
|
5886d038e3 | ||
|
|
8fed7c7005 | ||
|
|
604522aa61 | ||
|
|
7af35c2d09 | ||
|
|
87497eb491 | ||
|
|
434ed0dd4e | ||
|
|
473a55bde6 | ||
|
|
0b65b36e74 | ||
|
|
4aeb78ccac | ||
|
|
21d5de1756 | ||
|
|
797893d317 | ||
|
|
dd5ac38dd4 | ||
|
|
2741a446ea | ||
|
|
da3d886bd7 | ||
|
|
ad40e02fee | ||
|
|
7cc63e21dd | ||
|
|
611e828d1a | ||
|
|
3abcd59b03 | ||
|
|
48f4cd8943 | ||
|
|
abd5e27c2e | ||
|
|
ccb3a21c68 | ||
|
|
aa060746d7 | ||
|
|
6ec441e501 | ||
|
|
52d3d8cfe7 | ||
|
|
081ba68af4 | ||
|
|
38d5889979 | ||
|
|
5b4808c378 | ||
|
|
2af22d3387 | ||
|
|
7c1a8c90da | ||
|
|
e7726a17db | ||
|
|
57da9a848d | ||
|
|
464ee46631 | ||
|
|
46358b6e36 | ||
|
|
46d6779562 | ||
|
|
ea708e1e05 | ||
|
|
374946505a | ||
|
|
18db31f138 | ||
|
|
332c6eb33c | ||
|
|
e5c49e3bd4 | ||
|
|
60769dc4b7 | ||
|
|
9e652ef214 | ||
|
|
d2825c1b24 | ||
|
|
8482be7068 | ||
|
|
9dc56b727e | ||
|
|
c6759220b9 | ||
|
|
470af54acb | ||
|
|
344f74f444 | ||
|
|
0d1ca1bc0e | ||
|
|
d9e3684d3d | ||
|
|
e59db3f3d9 | ||
|
|
c883d618c3 | ||
|
|
8911a9a3ed | ||
|
|
366d2754ef | ||
|
|
4db114f64d | ||
|
|
d36340a3cd | ||
|
|
7e6de5d8dd | ||
|
|
490eda4f4a | ||
|
|
b5b4d70c2d | ||
|
|
a74cff6902 | ||
|
|
1010274c48 | ||
|
|
c39ff13217 | ||
|
|
58da108e85 | ||
|
|
8b4fdb54ea | ||
|
|
1877cb5e93 | ||
|
|
1530b3f2ca | ||
|
|
4c3c5228aa | ||
|
|
3ae4ca89f4 | ||
|
|
b415b1eeae | ||
|
|
c0ae983faa | ||
|
|
7845cbcc55 | ||
|
|
a33977251e | ||
|
|
b0d668b124 | ||
|
|
b0856c1abf | ||
|
|
2bffa3cf17 | ||
|
|
5ab05c6a6a | ||
|
|
72af2b7cd6 | ||
|
|
143c0a5b07 | ||
|
|
daf79f2324 | ||
|
|
15d11c6c86 | ||
|
|
b298a1fa82 | ||
|
|
007b8147c7 | ||
|
|
4013b76c9e | ||
|
|
ed81391aff | ||
|
|
28818010d6 | ||
|
|
928c19f923 | ||
|
|
34aa240840 | ||
|
|
6872dbd180 | ||
|
|
c5bea30c64 | ||
|
|
071a254611 | ||
|
|
d2d203df34 | ||
|
|
e1ffdea172 | ||
|
|
9abcf40df7 | ||
|
|
b67dc888fe | ||
|
|
c7b101d169 | ||
|
|
df5a7440a4 | ||
|
|
a59a8c0ec5 | ||
|
|
bf9f43da8b | ||
|
|
928b82a9c8 | ||
|
|
b9008d2459 | ||
|
|
50dddaaa9b | ||
|
|
1b168501af | ||
|
|
35a49bad60 | ||
|
|
97c1ff55e9 | ||
|
|
ffead92d5a | ||
|
|
81ea2b1fe4 | ||
|
|
9cdfe0ecb4 | ||
|
|
0473269132 | ||
|
|
4798bf2f79 | ||
|
|
c3c5c56dd8 | ||
|
|
4fb9bbb831 | ||
|
|
267cdd2aee | ||
|
|
fe0bd1a4b8 | ||
|
|
9fa510d2a8 | ||
|
|
fd29986354 | ||
|
|
8ec6bb4758 | ||
|
|
f3306f5fb4 | ||
|
|
20683fdf50 | ||
|
|
603ae8c0e1 | ||
|
|
f1d0418e48 | ||
|
|
9c8c306df3 | ||
|
|
d2543e9c67 | ||
|
|
55a0d910fa | ||
|
|
bd8144a67c | ||
|
|
004d1a7245 | ||
|
|
09fb99ed58 | ||
|
|
ae8071f707 | ||
|
|
c1cf084e43 | ||
|
|
87c794b22e | ||
|
|
a382d6ad35 | ||
|
|
2d86599a19 | ||
|
|
914971b30d | ||
|
|
443763de48 | ||
|
|
ff3c7ebe54 | ||
|
|
c0f82f25a3 | ||
|
|
f90381d412 | ||
|
|
d367d2e864 | ||
|
|
9d20eba2ad | ||
|
|
863746852f | ||
|
|
f416f994c9 | ||
|
|
70dfbbc15e | ||
|
|
85932eab98 | ||
|
|
0ee77d8c88 | ||
|
|
2f2d9547b7 | ||
|
|
32b065708b | ||
|
|
18285df154 | ||
|
|
b1b6c9f426 | ||
|
|
ff884533f9 | ||
|
|
417e80fe8d | ||
|
|
c203e6c7be | ||
|
|
730a0d1c98 | ||
|
|
d9b374f723 | ||
|
|
b9cb692504 | ||
|
|
23fc4bb4f7 | ||
|
|
4ae035dd51 | ||
|
|
3a791162c5 | ||
|
|
06791b06c4 | ||
|
|
5ebc290b94 | ||
|
|
675221a15e | ||
|
|
2f431a0d14 | ||
|
|
fd4e41950c | ||
|
|
41d5ae704a | ||
|
|
83fc069bf4 | ||
|
|
32c5cd245b | ||
|
|
a259be9033 | ||
|
|
fbbdee242a | ||
|
|
4a12635ea5 | ||
|
|
db7278e9c1 | ||
|
|
10056aa4ca | ||
|
|
bb566df432 | ||
|
|
4042a12d39 | ||
|
|
5ae4f9ade8 | ||
|
|
1636f9839c | ||
|
|
c76cccd2e7 | ||
|
|
532eb466a1 | ||
|
|
e8879a0455 | ||
|
|
ef5b4e212c | ||
|
|
24eb82d140 | ||
|
|
cdc8edb56b | ||
|
|
7235c63445 | ||
|
|
fd3b33b04b | ||
|
|
e8815e5653 | ||
|
|
551b9a3b76 | ||
|
|
1c6b639992 | ||
|
|
6fb7587d95 | ||
|
|
3953e74cb4 | ||
|
|
a8f616bba7 | ||
|
|
560eb5e071 | ||
|
|
c665bb4761 | ||
|
|
36584092e5 | ||
|
|
30430bb7dc | ||
|
|
fdf5cff12a | ||
|
|
4816b2b0fe | ||
|
|
9c808bf2ed | ||
|
|
7a12c2c615 | ||
|
|
149bc9f4ef | ||
|
|
b91183e9ec | ||
|
|
b67639f9ec | ||
|
|
cdbcc9ce8c | ||
|
|
6c7d094921 | ||
|
|
23466f6e00 | ||
|
|
08c1f4f072 | ||
|
|
1194c5c7fe | ||
|
|
f63fb16233 | ||
|
|
a4143df36a | ||
|
|
3e78568755 | ||
|
|
9b14cd7633 | ||
|
|
2b2488f376 | ||
|
|
fd77554cb7 | ||
|
|
2ee3d27ba8 | ||
|
|
af24f46803 | ||
|
|
da1684a8b9 | ||
|
|
5e7ae930c5 | ||
|
|
541226356c | ||
|
|
a30345c96c | ||
|
|
d035130d00 | ||
|
|
7d8181c44f | ||
|
|
45536cf957 | ||
|
|
da5ccaaa85 | ||
|
|
7c773991e7 | ||
|
|
bf976e5b8f | ||
|
|
d9ad3f5e98 | ||
|
|
9054dcb9ff | ||
|
|
57116ef054 | ||
|
|
c6f5b8b1f9 | ||
|
|
9e015ba59a | ||
|
|
6144cfad3d | ||
|
|
3844a18b86 | ||
|
|
e88c6e9583 | ||
|
|
6793fb2a35 | ||
|
|
4834c326aa | ||
|
|
e6167adefd | ||
|
|
a8c3756ba7 | ||
|
|
34b47f0239 | ||
|
|
0d13d9eabe | ||
|
|
358adb2109 | ||
|
|
92285b55b6 | ||
|
|
dda91be6d1 | ||
|
|
bec4dbafd2 | ||
|
|
dcb46990c2 | ||
|
|
fe03342b6f | ||
|
|
ee037acd34 | ||
|
|
d4a696cb6b | ||
|
|
5c483efd15 | ||
|
|
9aeba1df9b | ||
|
|
e98683ae1c | ||
|
|
c552e73d20 | ||
|
|
1851163cee | ||
|
|
3667f95b7c | ||
|
|
b6796d2742 | ||
|
|
047983cb91 | ||
|
|
8455abdfe9 | ||
|
|
b7c3fbb176 | ||
|
|
5642552f9a | ||
|
|
6f6b654dba | ||
|
|
c8b791efd3 | ||
|
|
52fd58cd93 | ||
|
|
66d638e224 | ||
|
|
16c4f18a81 | ||
|
|
cd6104ddb3 | ||
|
|
4fe7cd5adc | ||
|
|
3f59141407 | ||
|
|
8b37f503c7 | ||
|
|
7c9353d299 | ||
|
|
dfc901ffa4 | ||
|
|
611bf3035f | ||
|
|
35bb2da6bd | ||
|
|
53e034ce4f | ||
|
|
cd4db1db06 | ||
|
|
b1dbddffb9 | ||
|
|
221c10aa9b | ||
|
|
15ecd7bccf | ||
|
|
0d8dd0dc17 | ||
|
|
ec986e0fbc | ||
|
|
f0e0c73e9b | ||
|
|
d9a24d2e14 | ||
|
|
93618f974d | ||
|
|
4dfc217992 | ||
|
|
5a1a6cf6f0 | ||
|
|
36b325f71d | ||
|
|
74a3712116 | ||
|
|
1fe7eb6cf4 | ||
|
|
0d0f8e9ffc | ||
|
|
0a2063ce69 | ||
|
|
ce207e5c56 | ||
|
|
f22eaae457 | ||
|
|
fbc5280add | ||
|
|
65512ca984 | ||
|
|
385b4f8d4a | ||
|
|
f65f22f333 | ||
|
|
607d355c61 | ||
|
|
29c30c1f89 | ||
|
|
2ff771c16a | ||
|
|
5e641f2273 | ||
|
|
d52254bbf0 | ||
|
|
a97c8be31a | ||
|
|
9c067e5645 | ||
|
|
24d6857069 | ||
|
|
ed9259df9e | ||
|
|
75794fb4d9 | ||
|
|
4c386da7d2 | ||
|
|
abbd2e64c9 | ||
|
|
300a723fca | ||
|
|
ddf42d0358 | ||
|
|
88be0d7638 | ||
|
|
e26428a0eb | ||
|
|
7b36852d7a | ||
|
|
d1eb674314 | ||
|
|
4afed39b0e | ||
|
|
c1460cfdc7 | ||
|
|
85a94ee1e7 | ||
|
|
68895551b2 | ||
|
|
eece09e5ed | ||
|
|
0dd1f26b39 | ||
|
|
1b958a3c4d | ||
|
|
a1d23cddc5 | ||
|
|
14c25e3d9b | ||
|
|
c3915ee48e | ||
|
|
21ff03e28f | ||
|
|
2c8887398d | ||
|
|
f51cd65b1f | ||
|
|
dbb5a5191b | ||
|
|
e9844aed45 | ||
|
|
aaf6289953 | ||
|
|
b0d0223821 | ||
|
|
f271606e5e | ||
|
|
23a9bae391 | ||
|
|
b7c795c313 | ||
|
|
46c553fbad | ||
|
|
fc5bbfbed2 | ||
|
|
afe760a8bc | ||
|
|
7e78c35d23 | ||
|
|
56f0e95a22 | ||
|
|
7f9024465f | ||
|
|
75dc11b882 | ||
|
|
db0a5bd071 | ||
|
|
64434f8065 | ||
|
|
044623309c | ||
|
|
a54695b2e0 | ||
|
|
7acb53a22f | ||
|
|
a2d05e8119 | ||
|
|
dfcebfcbea | ||
|
|
3f165c9803 | ||
|
|
85971ea9f3 | ||
|
|
ff3ec219ef | ||
|
|
e0374dd186 | ||
|
|
51ee3b31cb | ||
|
|
496ea830c5 | ||
|
|
1e911b5094 | ||
|
|
6073be25de | ||
|
|
93a736e42a | ||
|
|
128afc8a56 | ||
|
|
a8d5630030 | ||
|
|
d83a256b9d | ||
|
|
5af33ffe0a | ||
|
|
ffd37d7802 | ||
|
|
31a34c247c | ||
|
|
4ccd842bdf | ||
|
|
f186c9e242 | ||
|
|
4e66c9fc23 | ||
|
|
99e21652a0 | ||
|
|
24a0cc2f64 | ||
|
|
e9dee86b7c | ||
|
|
42d7901828 | ||
|
|
7f156e961d | ||
|
|
d71b3b1893 | ||
|
|
cb1488c17f | ||
|
|
e13bcba89a | ||
|
|
7d8e8df0c5 | ||
|
|
0e5c0ff46d | ||
|
|
67bff3e19d | ||
|
|
19d9c69fb8 | ||
|
|
cb772a9527 | ||
|
|
ee621c1b92 | ||
|
|
20aa1bfdd6 | ||
|
|
9c52f6b949 | ||
|
|
0f890ad228 | ||
|
|
aac6ab0fc6 | ||
|
|
3fde778c0c | ||
|
|
348bdbdc0d | ||
|
|
3e9223a0bc | ||
|
|
a905a8a3c1 | ||
|
|
b2ab07aa69 | ||
|
|
9bd1da95e0 | ||
|
|
83c0df2157 | ||
|
|
8d7c64be66 | ||
|
|
0625a01a4f | ||
|
|
208a8723ff | ||
|
|
f4c2a9ca7d | ||
|
|
c97fd63e6d | ||
|
|
58402cdda8 | ||
|
|
59fa3e10a3 | ||
|
|
0831a427cc | ||
|
|
08517f0c7e | ||
|
|
97e58c2d79 | ||
|
|
6693ec48a0 | ||
|
|
9a13d4ce04 | ||
|
|
51bbe1f79d | ||
|
|
5dd92ab506 | ||
|
|
7120201469 | ||
|
|
046eeb03f2 | ||
|
|
ce22dc9309 | ||
|
|
953c9e588e | ||
|
|
2ceb4068ad | ||
|
|
11f62063a6 | ||
|
|
7885d712a6 | ||
|
|
a6ca282ff4 | ||
|
|
8ef67dee3b | ||
|
|
fb1b730bd5 | ||
|
|
af9c45849e | ||
|
|
a711a67f4c | ||
|
|
b743b7e2fb | ||
|
|
3db92359e5 | ||
|
|
088f08b315 | ||
|
|
71cd61dfe4 | ||
|
|
947e26d864 | ||
|
|
e3995a130f | ||
|
|
384641e274 | ||
|
|
0985415e11 | ||
|
|
3e13c9e825 | ||
|
|
ec09589646 | ||
|
|
83e3321a48 | ||
|
|
bb4c8ea52d | ||
|
|
5960dc6245 | ||
|
|
ca92316e7d | ||
|
|
b096472ccf | ||
|
|
261498d225 | ||
|
|
320a6b8a16 | ||
|
|
b3cadaf314 | ||
|
|
660852115e | ||
|
|
543e57ed7d | ||
|
|
4d78b7ca13 | ||
|
|
a32bdf3f2f | ||
|
|
5382d2006c | ||
|
|
ae1d60d11e | ||
|
|
e8c0bcfbb2 | ||
|
|
b8a04cb842 | ||
|
|
b4ffa8c045 | ||
|
|
7e540f16f9 | ||
|
|
e69275c6c5 | ||
|
|
16c123df49 | ||
|
|
446eee79fc | ||
|
|
cbc96d8a58 | ||
|
|
d2015b7d7b | ||
|
|
305b236f41 | ||
|
|
e172bd13df | ||
|
|
94cb4a2bb4 | ||
|
|
7abbbf6b7b | ||
|
|
66287757b3 | ||
|
|
661ecc57c5 | ||
|
|
15f9f79a24 | ||
|
|
286374fe7c | ||
|
|
ea288c2194 | ||
|
|
927cd60ad2 | ||
|
|
fb6e47e42a | ||
|
|
34d4f6b1f9 | ||
|
|
f7170953fb | ||
|
|
e80d52cc0f | ||
|
|
75da1ce7a7 | ||
|
|
7894c872dc | ||
|
|
14b2d2ed4c | ||
|
|
a7b5077e0c | ||
|
|
de2b88b707 | ||
|
|
130734bec7 | ||
|
|
d7fad4b646 | ||
|
|
db4c241cba | ||
|
|
be09909976 | ||
|
|
f4d538ef6c | ||
|
|
a6b1da393b | ||
|
|
501c20a34d | ||
|
|
b858ba3786 | ||
|
|
60863c5fcf | ||
|
|
1ee3f4a984 | ||
|
|
aadb605dec | ||
|
|
f63f2bd445 | ||
|
|
0205f150a3 | ||
|
|
cdbdf580c8 | ||
|
|
e4ba2b0828 | ||
|
|
28d00cc7c9 | ||
|
|
b897da8f6f | ||
|
|
dc868b16ab | ||
|
|
ee2e109769 | ||
|
|
2b955ddd53 | ||
|
|
33cb4fd42b | ||
|
|
a03af7e9ef | ||
|
|
90dbc35d41 | ||
|
|
66e9fc2068 | ||
|
|
0a9b376684 | ||
|
|
83ba909c08 | ||
|
|
9ed33f16dd | ||
|
|
e9fdb61bb5 | ||
|
|
073b1cd303 | ||
|
|
e712791f43 | ||
|
|
fefd9aae95 | ||
|
|
a4743901a3 | ||
|
|
ced9489643 | ||
|
|
0c45a0ca49 | ||
|
|
f3572e82ec | ||
|
|
dd620022a8 | ||
|
|
2237ec581c | ||
|
|
a0cd70ae71 | ||
|
|
80fce579a0 | ||
|
|
1313484ebe | ||
|
|
95aa541293 | ||
|
|
c4702f6a87 | ||
|
|
5c0fc0bec5 | ||
|
|
d8de7b19cb | ||
|
|
38640b01a8 | ||
|
|
a11e783867 | ||
|
|
8ca2fffa78 | ||
|
|
3f3cbd17ed | ||
|
|
5a18769336 | ||
|
|
cd6fe171cd | ||
|
|
ee45e546a8 | ||
|
|
c8be217a1d | ||
|
|
618df6de1d | ||
|
|
e6e79df8db | ||
|
|
509ca47b36 | ||
|
|
066353e1e7 | ||
|
|
a6737afb2f | ||
|
|
d5b3a62df5 | ||
|
|
7f82faefe1 | ||
|
|
08731857e5 | ||
|
|
90062acc35 | ||
|
|
030d912820 | ||
|
|
9e9187b169 | ||
|
|
c1258d0527 | ||
|
|
b7039c81ba | ||
|
|
7088b96c16 | ||
|
|
d31273dff5 | ||
|
|
85460ef6e2 | ||
|
|
5ab059c404 | ||
|
|
322ea1870d | ||
|
|
878b87b68c | ||
|
|
ab3024d98a | ||
|
|
d447c96385 | ||
|
|
e3ac4d1039 | ||
|
|
8fc4aa7240 | ||
|
|
aff9d8cbca | ||
|
|
260c15c6b6 | ||
|
|
dab48146bf | ||
|
|
14ae9f0809 | ||
|
|
b3369c8b0e | ||
|
|
1115cdd2ec | ||
|
|
44673b9fd2 | ||
|
|
faf9b32176 | ||
|
|
a93c1092fc | ||
|
|
6c81163d20 | ||
|
|
f71edbf45b | ||
|
|
0d3e48475e | ||
|
|
ae8451e837 | ||
|
|
33903f570b | ||
|
|
123e734046 | ||
|
|
008261e918 | ||
|
|
d388086baa | ||
|
|
f7af705bb5 | ||
|
|
a827cb7546 | ||
|
|
c7fe6f388a | ||
|
|
a04080a93e | ||
|
|
04158f5589 | ||
|
|
127809a836 | ||
|
|
6c948873ff | ||
|
|
a93be39aeb | ||
|
|
6de6c38834 | ||
|
|
a5745ba72d | ||
|
|
7c93d116ec | ||
|
|
0867d8a3c4 | ||
|
|
71f5d29cba | ||
|
|
f948d6e026 | ||
|
|
a222ead43c | ||
|
|
d6bfbbcd30 | ||
|
|
17df9d0f9d | ||
|
|
93099ea3c7 | ||
|
|
2f9e050e2b | ||
|
|
e68340273b | ||
|
|
5c341138e1 | ||
|
|
56b9eb6cf3 | ||
|
|
db20244212 | ||
|
|
6f9f74e72f | ||
|
|
8070d5b9b7 | ||
|
|
6197ecbaf4 | ||
|
|
ca585d3f42 | ||
|
|
02c78d4044 | ||
|
|
9e5d668c02 | ||
|
|
051656f295 | ||
|
|
9a51a44549 | ||
|
|
5102b113ed | ||
|
|
f1e4d94499 | ||
|
|
d04102bab3 | ||
|
|
c723d19e01 | ||
|
|
b0414748cb | ||
|
|
dac77e0606 | ||
|
|
02b98543d9 | ||
|
|
519aaadd9a | ||
|
|
fe27fef530 | ||
|
|
72dbb6f937 | ||
|
|
ccb29d10ae | ||
|
|
e479775833 | ||
|
|
86a7192f5a | ||
|
|
4a1be13904 | ||
|
|
0f3347f64d | ||
|
|
6564d84a2f | ||
|
|
f4747c5cef | ||
|
|
1e92c2f28a | ||
|
|
e4b097b196 | ||
|
|
85653c9ffc | ||
|
|
b1761e04b2 | ||
|
|
da5d8b20fa | ||
|
|
9a5a5f858f | ||
|
|
d6b194b0aa | ||
|
|
50ed52bacc | ||
|
|
daa906a697 | ||
|
|
a0cd281c42 | ||
|
|
ecd8f40c0f | ||
|
|
616c1b9b73 | ||
|
|
6bb5606c00 | ||
|
|
a6ceb88fca | ||
|
|
7bb7a94fbc | ||
|
|
e4324cedb4 | ||
|
|
07781c7c9d | ||
|
|
ea58a807fc | ||
|
|
fb6806a1c1 | ||
|
|
d24870e0ae | ||
|
|
166451c4e9 | ||
|
|
7c1290f684 | ||
|
|
179c774ba8 | ||
|
|
b57c224052 | ||
|
|
e886d80de6 | ||
|
|
3791b2dd24 | ||
|
|
12c916f4e5 | ||
|
|
ba7e00e130 | ||
|
|
895abde39c | ||
|
|
bada955725 | ||
|
|
b6418d95e7 | ||
|
|
f9e18675f3 | ||
|
|
22416cc0be | ||
|
|
ec086ad94a | ||
|
|
17d4b570e8 | ||
|
|
2dfad12553 | ||
|
|
b7dc55604e | ||
|
|
991bc359cb | ||
|
|
26dcaa0ded | ||
|
|
b5d3ddb7e3 | ||
|
|
8b178914b3 | ||
|
|
ce6fd4d775 | ||
|
|
bc55bfbee1 | ||
|
|
9c75cb4537 | ||
|
|
633fa343a5 | ||
|
|
a1d01e252b | ||
|
|
e9119e95ac | ||
|
|
af332a34d6 | ||
|
|
2d6251e5df | ||
|
|
b157fad0b6 | ||
|
|
70d2bb163c | ||
|
|
d9bf3339d2 | ||
|
|
b4ee5cd59c | ||
|
|
fae6c89e9a | ||
|
|
89d310258b | ||
|
|
a58529f46c | ||
|
|
12a2035791 | ||
|
|
b1ff7f0e9b | ||
|
|
23cf2b91f4 | ||
|
|
3c4fe338b6 | ||
|
|
6159ab33b7 | ||
|
|
91f410a85c | ||
|
|
58ffd37f9e | ||
|
|
0a48696cd8 | ||
|
|
2f71570390 | ||
|
|
5c9d98d12c | ||
|
|
15362df69a | ||
|
|
77f757995e | ||
|
|
2858d13fd5 | ||
|
|
ab0c97621a | ||
|
|
78b6c03af7 | ||
|
|
22342cdc05 | ||
|
|
99f398a87e | ||
|
|
dccdd84c25 | ||
|
|
d4d16f43ac | ||
|
|
dcf4963e0c | ||
|
|
a773a4957a | ||
|
|
87ee731dbe | ||
|
|
9ec36a76f6 | ||
|
|
5dc8283229 | ||
|
|
09b470e6c7 | ||
|
|
40151c7a43 | ||
|
|
34c030b501 | ||
|
|
e9a2528b13 | ||
|
|
e9d72bd022 | ||
|
|
b166686a15 | ||
|
|
c59d3cc624 | ||
|
|
ca95060b05 | ||
|
|
f2380ae354 | ||
|
|
2d039af278 | ||
|
|
831879fe37 | ||
|
|
0451ae07c8 | ||
|
|
ea1dfd8933 | ||
|
|
24519c69a4 | ||
|
|
3e55693bfa | ||
|
|
f5d0947b27 | ||
|
|
b5c4801beb | ||
|
|
3eff8f62b1 | ||
|
|
16c8466841 | ||
|
|
2da181a399 | ||
|
|
6e8bcf7b69 | ||
|
|
b83e5e2b72 | ||
|
|
da6791d75f | ||
|
|
764b0f8e31 | ||
|
|
2a0928b4be | ||
|
|
cac0da4e3d | ||
|
|
7e064365eb | ||
|
|
7c7382f372 | ||
|
|
4918b9c83a | ||
|
|
9bb365e60d | ||
|
|
b3c80e6ecf | ||
|
|
e5c77f64aa | ||
|
|
ed95f4e05f | ||
|
|
9f0e8dc49b | ||
|
|
693fdfdc5b | ||
|
|
b8d5c01382 | ||
|
|
01108ca83d | ||
|
|
3d5b7197f6 | ||
|
|
d3db77c675 | ||
|
|
c313ed2efc | ||
|
|
54c027823b | ||
|
|
f63aceeabe | ||
|
|
533e65fcd1 | ||
|
|
3fb0c768e6 | ||
|
|
243aab1030 | ||
|
|
22dba9ae07 | ||
|
|
d8f75495fe | ||
|
|
2240743100 | ||
|
|
a6a2410c50 | ||
|
|
02857a86fd | ||
|
|
d663d01798 | ||
|
|
3602163b38 | ||
|
|
34751a52a8 | ||
|
|
cb7c382b99 | ||
|
|
3322074ce7 | ||
|
|
83bb3b6d72 | ||
|
|
229f800266 | ||
|
|
75737b4ffe | ||
|
|
a5340917a7 | ||
|
|
914d19e7e4 | ||
|
|
eb49dbbdc8 | ||
|
|
912bab5a43 | ||
|
|
76c3f640db | ||
|
|
94092f445f | ||
|
|
f5b56d9855 | ||
|
|
b25a8b4c9f | ||
|
|
7ad9b9dd08 | ||
|
|
856c037bb0 | ||
|
|
388896b963 | ||
|
|
1d8addf675 | ||
|
|
c8c3d32b18 | ||
|
|
75a0979eee | ||
|
|
d6a0a279a5 | ||
|
|
44f5d71e1b | ||
|
|
bc841dd239 | ||
|
|
9c71d32964 | ||
|
|
d199d84b27 | ||
|
|
065895aa73 | ||
|
|
24aca83de4 | ||
|
|
3de7aa1ada | ||
|
|
5a0edb5c39 | ||
|
|
d4fec14123 | ||
|
|
38951fab1a | ||
|
|
e2c8237beb | ||
|
|
1224570fa5 | ||
|
|
afb99c0f4b | ||
|
|
733c908e34 | ||
|
|
06592d7d37 | ||
|
|
377b4b038c | ||
|
|
49e31ddb3d | ||
|
|
fd55bdf9a8 | ||
|
|
3f7fd6f9f9 | ||
|
|
1cb36621a1 | ||
|
|
ddd9188eb7 | ||
|
|
02254eac67 | ||
|
|
ebe026b2e9 | ||
|
|
efc7c5b0f4 | ||
|
|
6eb3a243df | ||
|
|
f68a77450d | ||
|
|
c5943c6c28 | ||
|
|
bc3b50ad23 | ||
|
|
b52e972a39 | ||
|
|
2d344e0209 | ||
|
|
519252efd4 | ||
|
|
e59e62fb1b | ||
|
|
1f7923beae | ||
|
|
2f15bbdaf3 | ||
|
|
a35690d13c | ||
|
|
4857569813 | ||
|
|
a2d34d1779 | ||
|
|
cdba1e0d36 | ||
|
|
48f15d7781 | ||
|
|
d0a766d424 | ||
|
|
a89bca4626 | ||
|
|
23ec21e494 | ||
|
|
63a36fd0f6 | ||
|
|
02617e8976 | ||
|
|
7cf7e55454 | ||
|
|
5067c867b8 | ||
|
|
6b5cc7ca4b | ||
|
|
acf80b4b92 | ||
|
|
7bb49893ee | ||
|
|
bf62b63173 | ||
|
|
b8fb1fa78a | ||
|
|
818b4d08da | ||
|
|
f438fbd06f | ||
|
|
297a45d477 | ||
|
|
17fe9dfd5f | ||
|
|
084d12bb45 | ||
|
|
9d0cbca497 | ||
|
|
1587218c6d | ||
|
|
a613b4b101 | ||
|
|
c989e2eda5 | ||
|
|
12d3e36887 | ||
|
|
c6fd381b01 | ||
|
|
a784661025 | ||
|
|
1f9a638bc1 | ||
|
|
545504c0de | ||
|
|
32f1e97bcd | ||
|
|
456b51d7f8 | ||
|
|
43b0747b83 | ||
|
|
9637e75f97 | ||
|
|
6f0effcc66 | ||
|
|
84767692b0 | ||
|
|
d484614c0f | ||
|
|
3dd8f214bf | ||
|
|
d3700ac9f8 | ||
|
|
7aa5d84ff4 | ||
|
|
46e99bfb40 | ||
|
|
fb5f59e72e | ||
|
|
8af1a53721 | ||
|
|
7034ffea39 | ||
|
|
94ed0354c2 | ||
|
|
2cf3408023 | ||
|
|
3b16d33775 | ||
|
|
3ff6374ace | ||
|
|
0ea2fed481 | ||
|
|
6bbc543ac1 | ||
|
|
1ca4f993b0 | ||
|
|
44f448fec4 | ||
|
|
abf7e65816 | ||
|
|
55bce63cea | ||
|
|
710e5afe08 | ||
|
|
cbf37677cb | ||
|
|
efb98c6414 | ||
|
|
01fbcb7044 | ||
|
|
53d2f6320b | ||
|
|
9d02da9d9c | ||
|
|
a0841d76db | ||
|
|
e3c4d611c3 | ||
|
|
79e8c48824 | ||
|
|
9ef298608e | ||
|
|
3ee8d5125b | ||
|
|
59c490fcea | ||
|
|
b8b468195c | ||
|
|
d873a5e68b | ||
|
|
6ad27b43ab | ||
|
|
1df19f65c4 | ||
|
|
c22a20c1ef | ||
|
|
c140ab970e | ||
|
|
5723e9a77e | ||
|
|
bdedd83368 | ||
|
|
2f5f92ddca | ||
|
|
87a98fe382 | ||
|
|
8894ff0fda | ||
|
|
488d2ed886 | ||
|
|
48f190447c | ||
|
|
63184d0bf5 | ||
|
|
a9bd5a8bb0 | ||
|
|
6c9850b8f6 | ||
|
|
e89b4e070c | ||
|
|
911d84d513 | ||
|
|
1a3f836a5a | ||
|
|
bb0e797cee | ||
|
|
05d866f0f7 | ||
|
|
e7fbb2273d | ||
|
|
91f159841b | ||
|
|
905dba67c3 | ||
|
|
676b83519a | ||
|
|
0e2c8ff220 | ||
|
|
e39a6b96bd | ||
|
|
da1268fc05 | ||
|
|
fb07d19a64 | ||
|
|
487e0c8769 | ||
|
|
5ee125c593 | ||
|
|
4876ae7c22 | ||
|
|
e9b04b923e | ||
|
|
5d8b9fd4db |
103
.doc/README.md
Normal file
103
.doc/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Phpdoc dokuwiki template
|
||||
This directory contains a template for rendering iTop phpdoc as dokuwiki pages.
|
||||
|
||||
|
||||
Conventional tags that you should use:
|
||||
* `@internal` : exclude from the documentation.
|
||||
* `@api` : it means that a method is an api, thus it may be interacted with.
|
||||
* `@see` : it points to another documented method
|
||||
* `@link` : external url
|
||||
* if you point to another page of the wiki, please use relative links.
|
||||
* `@example` : let you provide example of code
|
||||
* `@param`, `@return`, `@throws`, ...
|
||||
|
||||
|
||||
## Special instructions
|
||||
|
||||
Some iTop specific tags were added :
|
||||
* `@api-advanced`: it means that a method is an `@api` but mark it also as "complex" to use
|
||||
* `@overwritable-hook`: used to mark a method as "designed to be extended"
|
||||
* `@extension-hook`: not used for now
|
||||
* `@phpdoc-tuning-exclude-inherited`: once this tag is present on a class, it's inherited methods won't be showed.
|
||||
|
||||
|
||||
### known limitations:
|
||||
#### `@see` tags must be very specific:
|
||||
* always prefix class members with `ClassName::`
|
||||
* for methods always suffix them with `()`,
|
||||
* do not reference variables since they are not documented. If you have to, always prefix them with `$`
|
||||
|
||||
examples:
|
||||
```
|
||||
/**
|
||||
* @see DBObject
|
||||
* @see DBObject::Get()
|
||||
* @see DBObject::$foo
|
||||
*/
|
||||
```
|
||||
|
||||
#### Do not use inline tags, they do not work properly, example:
|
||||
```
|
||||
/**
|
||||
* This is a texts with an inline tag {@see [FQSEN] [<description>]} it must never be used
|
||||
*/
|
||||
```
|
||||
|
||||
#### The `@example` tag must respect this very precise syntax
|
||||
* the sentence in the first line (next to the tag) is the title, it must be enclosed by double quotes
|
||||
* the following lines are the sample code.
|
||||
* 💔 since we simply hack the official tag, this syntax must be respected carefully 💔
|
||||
example:
|
||||
```
|
||||
/**
|
||||
* @example "This is the title of the multiline example"
|
||||
* $foo = DBObject::Get('foo');
|
||||
* DBObject::Set('foo', ++$foo);
|
||||
*/
|
||||
```
|
||||
|
||||
## How content is included into the documentation
|
||||
|
||||
**For a class** those requirements have to be respected:
|
||||
- the file containing the class must be listed in `/phpdoc/files/file[]` of `.doc/phpdoc-objects-manipulation.dist.xml`
|
||||
- the class **must not** have the tag `@internal`
|
||||
- the class **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||
|
||||
Then, **for a method** of an eligible class:
|
||||
- **public** methods **must** have at least one of: `@api`, `@api-advanced`, `@overwritable-hook`, `@extension-hook`
|
||||
- **protected** methods **must** have at least one of: `@overwritable-hook`, `@extension-hook`
|
||||
- **private** methods are **always excluded**
|
||||
|
||||
**Class properties** and **constants** are never documented (this is subject to change).
|
||||
|
||||
|
||||
|
||||
|
||||
## A note about the rendering engine
|
||||
|
||||
:notebook: as spaces are used to mark code, the templates (`.doc/phpdoc-templates/combodo-wiki/*`) have very few indentation, thus they are awful to read (sorry).
|
||||
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
```
|
||||
cd .doc
|
||||
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||
```
|
||||
|
||||
## Generation
|
||||
`./bin/build-doc-object-manipulation` and `./bin/build-doc-extensions` contains examples of doc. generation, beware: they have to be called from the .doc directory:
|
||||
```shell
|
||||
cd /path/to/itop/.doc
|
||||
./bin/build-doc-object-manipulation
|
||||
```
|
||||
|
||||
the resulting documentation is written into `data/phpdocumentor/output`
|
||||
|
||||
|
||||
## Dokuwiki requirements
|
||||
* the template uses the [wrap plugin](https://www.dokuwiki.org/plugin:wrap).
|
||||
* the generated files have to be placed under an arbitrary directory of `[/path/to/dokuwiki]/data/pages`.
|
||||
* the html has to be activated [config:htmlok](https://www.dokuwiki.org/config:htmlok)
|
||||
* the generated files have to be in lowercase
|
||||
6
.doc/bin/build-doc-extensions
Executable file
6
.doc/bin/build-doc-extensions
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/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
|
||||
|
||||
# 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
|
||||
7
.doc/bin/build-doc-object-manipulation
Executable file
7
.doc/bin/build-doc-object-manipulation
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
rm -rf /tmp/phpdoc-twig-cache/ && rm -rf ../data/phpdocumentor/output/objects-manipulation/ && rm -rf ../data/phpdocumentor/temp/objects-manipulation/ && ./vendor/bin/phpdoc -c ./phpdoc-objects-manipulation.dist.xml -vvv
|
||||
|
||||
|
||||
# now wee need to lowercase every generated file because dokuwiki can't handle uppercase
|
||||
cd ../data/phpdocumentor/output/objects-manipulation/ && for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
|
||||
6
.doc/composer.json
Normal file
6
.doc/composer.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"require-dev": {
|
||||
"phpdocumentor/phpdocumentor": "~2",
|
||||
"jms/serializer": "1.7.*"
|
||||
}
|
||||
}
|
||||
20
.doc/phpdoc-extensions.dist.xml
Executable file
20
.doc/phpdoc-extensions.dist.xml
Executable file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
<title><![CDATA[iTop extensions]]></title>
|
||||
|
||||
<parser>
|
||||
<target>../data/phpdocumentor/temp/extensions</target>
|
||||
</parser>
|
||||
|
||||
<transformer>
|
||||
<target>../data/phpdocumentor/output/extensions</target>
|
||||
</transformer>
|
||||
|
||||
<transformations>
|
||||
<template name="phpdoc-templates/combodo-wiki"/>
|
||||
</transformations>
|
||||
|
||||
<files>
|
||||
<file>../application/applicationextension.inc.php</file>
|
||||
</files>
|
||||
</phpdoc>
|
||||
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
58
.doc/phpdoc-objects-manipulation.dist.xml
Executable file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
|
||||
<!--
|
||||
/**
|
||||
The documentation of this file can be found here : https://docs.phpdoc.org/references/configuration.html
|
||||
it has to be completed by the CLI parameters documentation which is more comprehensive: https://docs.phpdoc.org/references/commands/project_run.html#usage
|
||||
|
||||
usage:
|
||||
vendor/bin/phpdoc -c phpdoc-objects-manipulation.dist.xml
|
||||
|
||||
*/
|
||||
-->
|
||||
|
||||
<title><![CDATA[iTop's objects manipulation API]]></title>
|
||||
|
||||
<parser>
|
||||
<default-package-name>iTopORM</default-package-name>
|
||||
<target>../data/phpdocumentor/temp/objects-manipulation</target>
|
||||
<visibility>public,protected</visibility>
|
||||
<markers>
|
||||
<!--<item>TODO</item>-->
|
||||
<!--<item>FIXME</item>-->
|
||||
</markers>
|
||||
<extensions>
|
||||
<extension>php</extension>
|
||||
</extensions>
|
||||
</parser>
|
||||
|
||||
<transformer>
|
||||
<target>../data/phpdocumentor/output/objects-manipulation</target>
|
||||
</transformer>
|
||||
|
||||
<transformations>
|
||||
<template name="phpdoc-templates/combodo-wiki"/>
|
||||
</transformations>
|
||||
|
||||
<!--<logging>-->
|
||||
<!--<level>warn</level>-->
|
||||
<!--<paths>-->
|
||||
<!--<!–<default>data/phpdocumentor/log/objects-manipulation/{DATE}.log</default>–>-->
|
||||
<!--<!–<errors>data/phpdocumentor/log/objects-manipulation/{DATE}.errors.log</errors>–>-->
|
||||
|
||||
<!--<default>{APP_ROOT}/data/log/{DATE}.log</default>-->
|
||||
<!--<errors>{APP_ROOT}/data/log/{DATE}.errors.log</errors>-->
|
||||
<!--</paths>-->
|
||||
<!--</logging>-->
|
||||
|
||||
<files>
|
||||
<file>../core/dbobject.class.php</file>
|
||||
<file>../core/dbobjectsearch.class.php</file>
|
||||
<file>../core/metamodel.class.php</file>
|
||||
<file>../core/dbobjectset.class.php</file>
|
||||
<file>../core/dbsearch.class.php</file>
|
||||
<file>../core/dbunionsearch.class.php</file>
|
||||
</files>
|
||||
|
||||
</phpdoc>
|
||||
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
136
.doc/phpdoc-templates/combodo-wiki/class.txt.twig
Normal file
@@ -0,0 +1,136 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
|
||||
{% if node.tags['internal'] is defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This class is "internal", and thus is not documented!</WRAP>
|
||||
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This class is neither "api", "api-advanced", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||
{% else %}
|
||||
|
||||
====== {{ node.name }} ======
|
||||
|
||||
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
|
||||
|
||||
{% if node.deprecated %}
|
||||
=== **<del>Deprecated</del>**===
|
||||
//{{ node.tags.deprecated[0].description }}//
|
||||
{% endif %}
|
||||
|
||||
|
||||
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||
|
||||
|
||||
{% set class = node.parent %}
|
||||
{% block hierarchy_element %}
|
||||
|
||||
{% if class and class.name is defined and class.name|trim != '' %}
|
||||
==== parent ====
|
||||
{% set child = class %}
|
||||
{% set class = class.parent %}
|
||||
{{ block('hierarchy_element') }}
|
||||
[[{{ child.name }}|{{ child.name }}]]
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% for interface in node.interfaces|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Implements ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for trait in node.usedTraits|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Uses traits ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||
|
||||
{% set methods = node.inheritedMethods.merge(node.methods.merge(node.magicMethods)) %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '=====', sub_title_level: '=='} %}
|
||||
|
||||
<WRAP clear />
|
||||
|
||||
{% for method in methods|sort_asc
|
||||
if method.visibility == 'public'
|
||||
and (
|
||||
method.tags['api'] is defined
|
||||
or method.tags['api-advanced'] is defined
|
||||
or method.tags['overwritable-hook'] is defined
|
||||
or method.tags['extension-hook'] is defined
|
||||
)
|
||||
and (
|
||||
node.tags['phpdoc-tuning-exclude-inherited'] is not defined
|
||||
or method.parent.name == node.name
|
||||
)
|
||||
%}
|
||||
{%- if loop.first %}
|
||||
===== Public methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% for method in methods|sort_asc if method.visibility == 'protected' and (method.tags['overwritable-hook'] is defined or method.tags['extension-hook'] is defined) %}
|
||||
{%- if loop.first %}
|
||||
===== Protected methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||
{% if constants|length > 0 %}
|
||||
===== Constants =====
|
||||
{% for constant in constants|sort_asc %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#{% set properties = node.inheritedProperties.merge(node.properties.merge(node.magicProperties)) %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Public properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Protected properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
{% block constant %}
|
||||
|
||||
<WRAP group box >
|
||||
<WRAP twothirds column >
|
||||
==== {{ constant.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if constant.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and constant.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
== {{ constant.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ constant.description|markdown|raw }}</html>
|
||||
|
||||
{% if constant.deprecated %}
|
||||
=== Deprecated ===
|
||||
{{ constant.tags.deprecated[0].description|raw }}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:constant} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:constant, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:constant, title_level: '==', blacklist: ['link', 'see', 'var', 'deprecated', 'uses', 'package', 'subpackage', 'todo', 'code-example']} %}
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endblock %}
|
||||
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
95
.doc/phpdoc-templates/combodo-wiki/elements/method.txt.twig
Normal file
@@ -0,0 +1,95 @@
|
||||
{% block method %}
|
||||
|
||||
|
||||
<WRAP group box >
|
||||
<WRAP twothirds column >
|
||||
==== {{ method.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
<WRAP third column >
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:method, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
{% if method.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and method.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
{% if method.abstract %}<wrap warning>abstract</wrap> {% endif %}
|
||||
{% if method.final %}<wrap notice>final</wrap> {% endif %}
|
||||
<wrap notice>{{ method.visibility }}</wrap>
|
||||
{% if method.static %}<wrap warning>static</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
== {{ method.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ method.description|markdown|raw }}</html>
|
||||
|
||||
<code php>{% if method.abstract %}abstract {% endif %}{% if method.final %}final {% endif %}{{ method.visibility }} {% if method.static %}static {% endif %}{{ method.name }}({% for argument in method.arguments %}{{ argument.isVariadic ? '...' }}{{ argument.name }}{{ argument.default ? (' = '~argument.default)|raw }}{% if not loop.last %}, {% endif %}{% endfor %})</code>
|
||||
|
||||
<WRAP twothirds column >
|
||||
|
||||
|
||||
=== Parameters ===
|
||||
{% if method.arguments|length > 0 -%}
|
||||
^ types ^ name ^ default ^ description ^
|
||||
{% for argument in method.arguments -%}
|
||||
| **<nowiki>{{ argument.types|join('|')|raw }}</nowiki>** | {{ argument.name }} {{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }} | <nowiki>{{ argument.default|raw }}</nowiki> | {{ argument.description|trim|replace("\n", ' ')|raw }} |{{ "\r\n" }}
|
||||
{%- endfor %}
|
||||
{% else %}
|
||||
//none//
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#=== Parameters ===#}
|
||||
{#{% if method.arguments|length > 0 -%}#}
|
||||
{#{% for argument in method.arguments -%}#}
|
||||
{#== {{ argument.name }} ==#}
|
||||
|
||||
|
||||
{#{% set varDesc %}#}
|
||||
{#<span style="margin:0 10px; 0 20px; font-weight: bold;">{{ argument.types|join('|') }}</span>#}
|
||||
{#{{ argument.isVariadic ? '<small style="color: gray">variadic</small>' }}#}
|
||||
{#{{ argument.description|raw }}#}
|
||||
{#{% endset %}#}
|
||||
{#<html>{{ varDesc|markdown|raw }}</html>#}
|
||||
{#{%- endfor %}#}
|
||||
{#{% else %}#}
|
||||
{#<wrap tip>This method has no parameter</wrap>#}
|
||||
{#{% endif %}#}
|
||||
|
||||
|
||||
{% if method.response and method.response.types|join() != 'void' %}
|
||||
=== Returns ===
|
||||
<html>{{ ('**' ~ method.response.types|join('|')|trim ~ '** ' ~ method.response.description)|markdown|raw }}</html>
|
||||
{% endif %}
|
||||
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column >
|
||||
|
||||
{% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %}
|
||||
=== Throws ===
|
||||
{% for exception in method.tags.throws -%}
|
||||
{% if loop.length > 1 %} * {% endif %}''{{ exception.types|join('|')|raw }}'' <nowiki>{{ exception.description|raw }}</nowiki>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:method} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/used-by.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags-with-description.txt.twig' with {structure:method, title_level: '===', WRAP: 'info', tagsWithDescription: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:method, title_level: '===', blacklist: ['todo', 'link', 'see', 'abstract', 'example', 'param', 'return', 'access', 'deprecated', 'throws', 'throw', 'uses', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'used-by', 'inheritdoc', 'code-example']} %}
|
||||
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:method, title_level: '==='} %}
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
{% block property %}
|
||||
|
||||
<WRAP group box>
|
||||
<WRAP twothirds column >
|
||||
==== ${{ property.name }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if property.deprecated %}<wrap danger>deprecated</wrap> {% endif %}
|
||||
{% if (node.parent is not null and property.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
|
||||
|
||||
== {{ property.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ property.description|markdown|raw }}</html>
|
||||
{% if property.var.0.description %}<html>{{ property.var.0.description|markdown|raw }}</html>{% endif %}
|
||||
|
||||
|
||||
|
||||
{#{% if property.types %}#}
|
||||
{#== Type ==#}
|
||||
{#{% for type in property.types %}#}
|
||||
{#{% if loop.length > 1 %} * {% endif %}{{ type|raw }} : {{ type.description|raw }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{{ property.types|join('|')|raw }}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
|
||||
{% if property.deprecated %}
|
||||
== Deprecated ==
|
||||
{{ property.tags.deprecated[0].description }}
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/inherited-from.txt.twig' with {structure:property} %}
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:property, title_level: '=='} %}
|
||||
|
||||
{% include 'includes/uses.txt.twig' with {structure:property, title_level: ''} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:property, title_level: '==', blacklist: ['link', 'see', 'access', 'var', 'deprecated', 'uses', 'todo', 'code-example']} %}
|
||||
|
||||
|
||||
<code php>{{ property.visibility }} ${{ property.name }}{% if property.types %} : {{ property.types|join('|')|raw }}{% endif %}</code>
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endblock %}
|
||||
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
1
.doc/phpdoc-templates/combodo-wiki/file.source.txt.twig
Normal file
@@ -0,0 +1 @@
|
||||
{{ node.source|raw }}
|
||||
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
122
.doc/phpdoc-templates/combodo-wiki/file.txt.twig
Normal file
@@ -0,0 +1,122 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block javascripts %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{#<section class="row-fluid">#}
|
||||
{#<div class="span2 sidebar">#}
|
||||
{#{% set namespace = project.namespace %}#}
|
||||
{#{{ block('sidebarNamespaces') }}#}
|
||||
{#</div>#}
|
||||
{#</section>#}
|
||||
{#<section class="row-fluid">#}
|
||||
====== {{ node.path|split('/')|slice(0,-1)|join('/') }}{{ node.name }} ======
|
||||
{{ node.summary }}
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
{% if node.traits|length > 0 %}
|
||||
|
||||
===== Traits =====
|
||||
{% for trait in node.traits %}
|
||||
<tr>
|
||||
<td>{{ trait|raw }}</td>
|
||||
<td><em>{{ trait.summary }}</em></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if node.interfaces|length > 0 %}
|
||||
===== Interfaces =====
|
||||
{% for interface in node.interfaces %}
|
||||
<tr>
|
||||
<td>{{ interface|raw }}</td>
|
||||
<td><em>{{ interface.summary }}</em></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.classes|length > 0 %}
|
||||
===== Classes =====
|
||||
{% for class in node.classes %}
|
||||
{{ class|raw }}
|
||||
<em>{{ class.summary }}</em>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.package is not empty and node.package != '\\' %}
|
||||
===== Package =====
|
||||
{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}
|
||||
{% endif %}
|
||||
|
||||
{% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
|
||||
{% if loop.first %}
|
||||
===== See also =====
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
<dd><a href="{{ tag.reference ?: tag.link }}"><div class="namespace-wrapper">{{ tag.description ?: tag.reference }}</div></a></dd>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<h2>Tags</h2>
|
||||
<table class="table table-condensed">
|
||||
{% for tagName,tags in node.tags if tagName not in ['link', 'see', 'package', 'subpackage'] %}
|
||||
<tr>
|
||||
<th>
|
||||
{{ tagName }}
|
||||
</th>
|
||||
<td>
|
||||
{% for tag in tags %}
|
||||
{{ tag.description|markdown|raw }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="2"><em>None found</em></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
{% if node.constants|length > 0 %}
|
||||
<div class="row-fluid">
|
||||
<section class="span8 content file">
|
||||
<h2>Constants</h2>
|
||||
</section>
|
||||
<aside class="span4 detailsbar"></aside>
|
||||
</div>
|
||||
|
||||
{% for constant in node.constants %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if node.functions|length > 0 %}
|
||||
<div class="row-fluid">
|
||||
<section class="span8 content file">
|
||||
<h2>Functions</h2>
|
||||
</section>
|
||||
<aside class="span4 detailsbar"></aside>
|
||||
</div>
|
||||
|
||||
{% for method in node.functions %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="source-view-label">{{ node.file.name }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre data-src="{{ path('files/' ~ node.path ~ '.txt')|raw }}" class="language-php line-numbers"></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
42
.doc/phpdoc-templates/combodo-wiki/graphs/class.html.twig
Normal file
@@ -0,0 +1,42 @@
|
||||
{% extends 'layout.html.twig' %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link href="{{ path('css/jquery.iviewer.css') }}" rel="stylesheet" media="all"/>
|
||||
<style>
|
||||
#viewer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="{{ path('js/jquery.mousewheel.js') }}" type="text/javascript"></script>
|
||||
<script src="{{ path('js/jquery.iviewer.js') }}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).resize(function(){
|
||||
$("#viewer").height($(window).height() - 100);
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
|
||||
$('#viewer img').bind('dragstart', function(event){
|
||||
event.preventDefault();
|
||||
});
|
||||
$(window).resize();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div class="wrapper">
|
||||
<div id="viewer" class="viewer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
5
.doc/phpdoc-templates/combodo-wiki/htaccess.dist
Normal file
@@ -0,0 +1,5 @@
|
||||
# Fixes a vulnerability in CentOS: http://stackoverflow.com/questions/20533279/prevent-php-from-parsing-non-php-files-such-as-somefile-php-txt
|
||||
<FilesMatch \.php\.txt$>
|
||||
RemoveHandler .php
|
||||
ForceType text/plain
|
||||
</FilesMatch>
|
||||
@@ -0,0 +1,34 @@
|
||||
{% if title_level is not defined %}
|
||||
{%- set title_level = '==' -%}
|
||||
{% endif %}
|
||||
|
||||
{% if sub_title_level is not defined %}
|
||||
{%- set sub_title_level = title_level|slice(1) -%}
|
||||
{% endif %}
|
||||
{% if sub_title_level == '=' %}
|
||||
{%- set sub_title_level = '' -%}
|
||||
{% endif %}
|
||||
|
||||
{#{% for tagName,tags in structure.tags if tagName in ['code-example'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#{{title_level}} Examples {{title_level}}#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#{%- set descToken = tag.description|split("\n", 2) -%}#}
|
||||
{#{%- set title = descToken[0] -%}#}
|
||||
{#{%- set code = descToken[1] -%}#}
|
||||
{#{{sub_title_level}} {{ title }} {{sub_title_level}}#}
|
||||
{#<code php>{{ code|raw }}</code>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{% for tagName,tags in structure.tags if tagName in ['example'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Examples {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{{ sub_title_level }} {{ tag.filePath|escape }}{{ sub_title_level }}
|
||||
<code php>{{ tag.description|raw }}</code>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
|
||||
{% if (node.parent is null) %}
|
||||
{{title_level}} File {{ structure.path }} {{title_level}}
|
||||
{% endif %}
|
||||
|
||||
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
|
||||
{{title_level}} Inherited from {{title_level}}
|
||||
[[{{structure.parent}}|{{structure.parent}}]]
|
||||
{% endif %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% for structure in structures|sort_asc if structure.tags['internal'] is not defined and (structure.tags['api'] is defined or structure.tags['api-advanced'] is defined or structure.tags['overwritable-hook'] is defined or structure.tags['extension-hook'] is defined ) %}
|
||||
{#{{ structure|raw }}#}
|
||||
|
||||
{% set structureName = structure|trim('\\', 'left') %}
|
||||
|
||||
<WRAP group box>
|
||||
<WRAP twothirds column >
|
||||
==== {{ structureName }} ====
|
||||
</WRAP>{# twothirds column#}
|
||||
|
||||
<WRAP third column>
|
||||
{% if structure.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if structure.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if structure.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% if (node.parent is not null and structure.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}<wrap notice>inherited</wrap> {% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:structure, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
|
||||
{{ structure.summary|raw }}
|
||||
[[{{structureName}}|More information]]
|
||||
|
||||
</WRAP>{# group #}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{% if title_level is not defined %}
|
||||
{%- set title_level='==' -%}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['link', 'see'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} See also {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{%- set linkTag = tag.reference|trim('\\', 'left') -%}
|
||||
{% if not('()' in linkTag or '$' in linkTag or node.name in linkTag or '::' in linkTag ) %}
|
||||
{%- set linkTag = linkTag|lower -%}
|
||||
{% elseif node.name~'::' in linkTag %}
|
||||
{%- set linkTag = linkTag|replace({(node.name~'::'): '#'})|lower -%}
|
||||
{% elseif '::' in linkTag -%}
|
||||
{%- set linkTag = linkTag|replace({'::': '#'})|lower -%}
|
||||
{% else %}
|
||||
{%- set linkTag = '#' ~ linkTag|lower -%}
|
||||
{%- endif %}
|
||||
|
||||
{% if loop.length > 1 %} * {% endif %}{% if tag.reference is not empty -%}
|
||||
[[{{linkTag}}|{{ (tag.reference)|trim('\\', 'left') }}]] {% if tag.description|trim is not empty %}: {{ tag.description|trim('\\', 'left') }} {% endif %}
|
||||
{%- else -%}
|
||||
{#{{ tag.description|trim('\\', 'left') }}#}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,56 @@
|
||||
{% if tag is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set tag = "api" -%}
|
||||
{%- endif %}
|
||||
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
|
||||
|
||||
{% for method in methods|sort_asc
|
||||
if (method.visibility == 'public')
|
||||
and (
|
||||
method.tags[tag] is defined
|
||||
and (
|
||||
hidden_by[tag] is not defined or method.tags[hidden_by[tag]] is not defined
|
||||
)
|
||||
)
|
||||
%}
|
||||
{%- if loop.first %}
|
||||
{% if tag == 'api' %}
|
||||
===== API synthesis =====
|
||||
<WRAP>
|
||||
List of the public API methods.
|
||||
When manipulating {{ node.name }}, You can call those methods:
|
||||
</WRAP>
|
||||
{% elseif tag == 'api-advanced' %}
|
||||
===== Advanced API synthesis =====
|
||||
<WRAP>
|
||||
List of advanced API methods
|
||||
Beware they usage is recommended to advanced users only.
|
||||
</WRAP>
|
||||
{% elseif tag == 'overwritable-hook' %}
|
||||
===== overwritable-hook synthesis =====
|
||||
<WRAP >When inheriting from {{ node.name }},
|
||||
you can overwrite those methods in order to add custom logic:
|
||||
</WRAP>
|
||||
{% elseif tag == 'extension-hook' %}
|
||||
===== extension-hook synthesis =====
|
||||
<WRAP >
|
||||
When inheriting from {{ node.name }},
|
||||
you can extend the behaviour of iTop by implementing:
|
||||
</WRAP>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set sanitizedMethod = method|trim('\\', 'left')|replace({(node.name~'::'): ''}) %}
|
||||
{% if '::' in sanitizedMethod -%}
|
||||
{%- if node.tags['phpdoc-tuning-exclude-inherited'] is not defined %}
|
||||
* [[{{sanitizedMethod|replace({'::': '#'})|lower}}|↪{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||
{% endif %}
|
||||
{%- else %}
|
||||
* [[#{{sanitizedMethod}}|{{sanitizedMethod}}]] — {{ method.summary|replace({"\n":""})|raw }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,20 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level = '==' %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{%- for tagName,tags in structure.tags if tagName in tagsWithDescription -%}
|
||||
{%- for tag in tags -%}
|
||||
{%- if tag.description is not empty -%}
|
||||
{%- if WRAP is defined -%}
|
||||
<WRAP {{WRAP}}>
|
||||
{%- endif -%}
|
||||
{{title_level}} {{ tagName }} {{title_level}}
|
||||
{{ tag.description|escape }}
|
||||
{%- if WRAP is defined -%}
|
||||
</WRAP>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
|
||||
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
22
.doc/phpdoc-templates/combodo-wiki/includes/tags.txt.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='=====' %}
|
||||
{% endif %}
|
||||
|
||||
{% if blacklist is not defined %}
|
||||
{% set blacklist =['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'api', 'api-advanced', 'todo', 'code-example'] %}
|
||||
{% endif %}
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
{#^ {% for tagName,tags in structure.tags if tagName not in blacklist -%}#}
|
||||
{#{{ tagName }} ^#}
|
||||
{#{%- endfor %}#}
|
||||
|
||||
{% for tagName,tags in structure.tags if tagName not in blacklist and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||
{%- if loop.first %}
|
||||
{{title_level}} Tags {{title_level}}
|
||||
{% endif %}
|
||||
^ {{ tagName }} | {% for tag in tags %}{{ tag.version ? tag.version ~ ' ' : '' }}{{ tag.description}}{% endfor %} |
|
||||
{% endfor %}
|
||||
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/used-by.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['used-by'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Used by {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#<dt>Uses</dt>#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
24
.doc/phpdoc-templates/combodo-wiki/includes/uses.txt.twig
Normal file
@@ -0,0 +1,24 @@
|
||||
{% if title_level is not defined %}
|
||||
{% set title_level='' %}
|
||||
{% endif %}
|
||||
{% for tagName,tags in structure.tags if tagName in ['uses'] %}
|
||||
{% if loop.first %}
|
||||
{{title_level}} Uses {{title_level}}
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ tag.reference ?: tag.link }} : {{ tag.description ?: tag.reference }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{#{% for tagName,tags in method.tags if tagName in ['uses'] %}#}
|
||||
{#{% if loop.first %}#}
|
||||
{#<dt>Uses</dt>#}
|
||||
{#{% endif %}#}
|
||||
{#{% for tag in tags %}#}
|
||||
{#<dd>{{ tag.reference|raw }}</dd>#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endfor %}#}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% if wrap is not defined -%}
|
||||
{% set wrap = 'notice' %}
|
||||
{%- endif -%}
|
||||
{% if hidden_by is not defined -%}
|
||||
{# Do not display @api if @api-advanced is also present #}
|
||||
{%- set hidden_by = {"api" : "api-advanced"} -%}
|
||||
{%- endif %}
|
||||
|
||||
{%- for tagName,tags in structure.tags if tagName in wrapTags and (hidden_by[tagName] is not defined or structure.tags[hidden_by[tagName]] is not defined) %}
|
||||
<wrap {{wrap}}>{{tagName}}</wrap>
|
||||
{% endfor %}
|
||||
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
121
.doc/phpdoc-templates/combodo-wiki/interface.txt.twig
Normal file
@@ -0,0 +1,121 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
|
||||
{% if node.tags['internal'] is defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This interface is "internal", and thus is not documented!</WRAP>
|
||||
{% elseif node.tags['api'] is not defined and node.tags['api-advanced'] is not defined and node.tags['overwritable-hook'] is not defined and node.tags['extension-hook'] is not defined %}
|
||||
====== {{ node.name }} ======
|
||||
<WRAP alert>This interface is neither "api", "overwritable-hook" or "extension-hook", and thus is not documented!</WRAP>
|
||||
{% else %}
|
||||
|
||||
====== {{ node.name }} ======
|
||||
|
||||
{% if node.deprecated %}<wrap danger>deprecated</wrap>{% endif %}
|
||||
{% if node.abstract %}<wrap warning>abstract</wrap>{% endif %}
|
||||
{% if node.final %}<wrap notice>final</wrap>{% endif %}
|
||||
{% include 'includes/wrap-tags.txt.twig' with {structure:node, wrap: 'safety', wrapTags: ['api', 'api-advanced', 'overwritable-hook', 'extension-hook']} %}
|
||||
|
||||
|
||||
|
||||
{% if node.deprecated %}
|
||||
=== **<del>Deprecated</del>**===
|
||||
//{{ node.tags.deprecated[0].description }}//
|
||||
{% endif %}
|
||||
|
||||
|
||||
== {{ node.summary|replace({"\n":""})|raw }} ==
|
||||
<html>{{ node.description|markdown|raw }}</html>
|
||||
|
||||
|
||||
{% include 'includes/code-examples.txt.twig' with {structure:node, title_level: '====='} %}
|
||||
|
||||
|
||||
{% set class = node.parent %}
|
||||
{% block hierarchy_element %}
|
||||
|
||||
{% if class and class.name is defined and class.name|trim != '' %}
|
||||
==== parent ====
|
||||
{% set child = class %}
|
||||
{% set class = class.parent %}
|
||||
{{ block('hierarchy_element') }}
|
||||
[[{{ child.name }}|{{ child.name }}]]
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% for interface in node.interfaces|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Implements ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ interface.fullyQualifiedStructuralElementName ?: interface }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for trait in node.usedTraits|sort_asc %}
|
||||
{% if loop.first %}
|
||||
==== Uses traits ====
|
||||
{% endif %}
|
||||
{% if loop.length > 1 %} * {% endif %}{{ trait.fullyQualifiedStructuralElementName ?: trait }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% include 'includes/see-also.txt.twig' with {structure:node, title_level: '==='} %}
|
||||
|
||||
{% include 'includes/tags.txt.twig' with {structure:node, title_level: '=====', blacklist: ['link', 'see', 'abstract', 'example', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage', 'phpdoc-tuning-exclude-inherited', 'api', 'api-advanced', 'overwritable-hook', 'extension-hook', 'copyright', 'license', 'code-example']} %}
|
||||
|
||||
|
||||
{% set methods = node.inheritedMethods.merge(node.methods) %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'api-advanced'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'overwritable-hook'} %}
|
||||
{% include 'includes/tag-synthesys.txt.twig' with {methods:methods, tag:'extension-hook'} %}
|
||||
|
||||
<WRAP clear />
|
||||
|
||||
|
||||
{% for method in methods|sort_asc if method.visibility == 'public' %}
|
||||
{%- if loop.first %}
|
||||
===== Public methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
{% for method in methods|sort_asc if method.visibility == 'protected' %}
|
||||
{%- if loop.first %}
|
||||
===== Protected methods =====
|
||||
{% endif %}
|
||||
{{ block('method') }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
{% set constants = node.inheritedConstants.merge(node.constants) %}
|
||||
{% if constants|length > 0 %}
|
||||
===== Constants =====
|
||||
{% for constant in constants|sort_asc %}
|
||||
{{ block('constant') }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{#{% set properties = node.inheritedProperties.merge(node.properties) %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'public' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Public properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% for property in properties|sort_asc if property.visibility == 'protected' %}#}
|
||||
{#{%- if loop.first %}#}
|
||||
{#===== Protected properties =====#}
|
||||
{#{% endif %}#}
|
||||
{#{{ block('property') }}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
|
||||
{%- endif %} {#{% elseif node.tags['xxx'] is not defined and ... #}
|
||||
|
||||
<wrap button>[[start|🔙 Back]]</wrap>
|
||||
{% endblock %}
|
||||
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
5
.doc/phpdoc-templates/combodo-wiki/layout.txt.twig
Normal file
@@ -0,0 +1,5 @@
|
||||
{% use 'elements/constant.txt.twig' %}
|
||||
{% use 'elements/property.txt.twig' %}
|
||||
{% use 'elements/method.txt.twig' %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
51
.doc/phpdoc-templates/combodo-wiki/namespace.txt.twig
Normal file
@@ -0,0 +1,51 @@
|
||||
{% extends 'layout.txt.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% set namespace = project.namespace %}
|
||||
{{ block('sidebarNamespaces') }}
|
||||
|
||||
{#{{ node.parent|raw }}#}
|
||||
{#====== {{ node.parent.fullyQualifiedStructuralElementName }}{{ node.name }} ======#}
|
||||
|
||||
{% if node.children|length > 0 %}
|
||||
=====Namespaces=====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.children} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
{% if node.traits|length > 0 %}
|
||||
===== Traits =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.traits} %}
|
||||
----
|
||||
{%- endif %}
|
||||
|
||||
{% if node.interfaces|length > 0 %}
|
||||
===== Interfaces =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.interfaces} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
{% if node.classes|length > 0 %}
|
||||
===== Classes =====
|
||||
{% include 'includes/namespace-structure-toc.html.twig' with {structures: node.classes} %}
|
||||
----
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{#{% if node.constants|length > 0 %}#}
|
||||
{#===== Constants =====#}
|
||||
{#{% for constant in node.constants|sort_asc %}#}
|
||||
{# {{ block('constant') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
{#{% if node.functions|length > 0 %}#}
|
||||
{#===== Functions =====#}
|
||||
|
||||
{#{% for method in node.functions|sort_asc %}#}
|
||||
{# {{ block('method') }}#}
|
||||
{#{% endfor %}#}
|
||||
{#{% endif %}#}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
====== Deprecated elements ======
|
||||
|
||||
{#{% for element in project.indexes.elements if element.deprecated %}#}
|
||||
{#{% if element.file.path != previousPath %}#}
|
||||
{#<li><a href="#{{ element.file.path }}"><i class="icon-file"></i> {{ element.file.path }}</a></li>#}
|
||||
{#{% endif %}#}
|
||||
{#{% set previousPath = element.file.path %}#}
|
||||
{#{% endfor %}#}
|
||||
|
||||
{% for element in project.indexes.elements if element.deprecated %}
|
||||
{% if element.file.path != previousPath %}
|
||||
{% if previousPath %}
|
||||
</WRAP>{# group #}
|
||||
{% endif %}
|
||||
{#<a name="{{ element.file.path }}" id="{{ element.file.path }}"></a>#}
|
||||
===== {{ element.file.path }} ({{ element.tags.deprecated.count }} found)=====
|
||||
|
||||
<WRAP group >
|
||||
<WRAP third column >
|
||||
Element
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
Line
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
Description
|
||||
</WRAP>{# third column#}
|
||||
|
||||
{% endif %}
|
||||
{% for tag in element.tags.deprecated %}
|
||||
<WRAP group >
|
||||
<WRAP third column >
|
||||
{{ element.fullyQualifiedStructuralElementName }}
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
{{ element.line }}
|
||||
</WRAP>{# third column#}
|
||||
<WRAP third column >
|
||||
{{ tag.description }}
|
||||
</WRAP>{# third column#}
|
||||
|
||||
{% endfor %}
|
||||
</WRAP>{# group #}
|
||||
{% set previousPath = element.file.path %}
|
||||
{% else %}
|
||||
<WRAP info>No deprecated elements have been found in this project.</WRAP>
|
||||
{% endfor %}
|
||||
|
||||
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
27
.doc/phpdoc-templates/combodo-wiki/template.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<template>
|
||||
<author>Bruno DA SILVA</author>
|
||||
<email>contact [at] combodo.com</email>
|
||||
<version>1.0.0</version>
|
||||
<copyright>Combodo 2018</copyright>
|
||||
<description><![CDATA[
|
||||
|
||||
Forked from the clean theme of https://github.com/phpDocumentor/phpDocumentor2 provided under the MIT licence.
|
||||
The original work is copyright "Mike van Riel".
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
To improve performance you can add the following to your .htaccess:
|
||||
|
||||
<ifModule mod_deflate.c>
|
||||
<filesMatch "\.(js|css|html)$">
|
||||
SetOutputFilter DEFLATE
|
||||
</filesMatch>
|
||||
</ifModule>
|
||||
]]></description>
|
||||
<transformations>
|
||||
<transformation writer="twig" query="namespace" source="templates/combodo-wiki/namespace.txt.twig" artifact="start.txt"/>
|
||||
<transformation writer="twig" query="indexes.classes" source="templates/combodo-wiki/class.txt.twig" artifact="{{name}}.txt"/>
|
||||
<transformation writer="twig" query="indexes.interfaces" source="templates/combodo-wiki/interface.txt.twig" artifact="{{name}}.txt" />
|
||||
</transformations>
|
||||
</template>
|
||||
711
.editorconfig
Normal file
711
.editorconfig
Normal file
@@ -0,0 +1,711 @@
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
max_line_length = 140
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = 80, 120, 140
|
||||
ij_wrap_on_typing = true
|
||||
|
||||
[*.css]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_css_align_closing_brace_with_properties = false
|
||||
ij_css_blank_lines_around_nested_selector = 1
|
||||
ij_css_blank_lines_between_blocks = 1
|
||||
ij_css_brace_placement = 0
|
||||
ij_css_hex_color_long_format = false
|
||||
ij_css_hex_color_lower_case = false
|
||||
ij_css_hex_color_short_format = false
|
||||
ij_css_hex_color_upper_case = false
|
||||
ij_css_keep_blank_lines_in_code = 2
|
||||
ij_css_keep_indents_on_empty_lines = false
|
||||
ij_css_keep_single_line_blocks = false
|
||||
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_css_space_after_colon = true
|
||||
ij_css_space_before_opening_brace = true
|
||||
ij_css_value_alignment = 0
|
||||
|
||||
[*.csv]
|
||||
max_line_length = 2147483647
|
||||
ij_wrap_on_typing = false
|
||||
ij_csv_wrap_long_lines = false
|
||||
|
||||
[*.feature]
|
||||
indent_size = 2
|
||||
ij_gherkin_keep_indents_on_empty_lines = false
|
||||
|
||||
[*.less]
|
||||
indent_size = 2
|
||||
ij_less_align_closing_brace_with_properties = false
|
||||
ij_less_blank_lines_around_nested_selector = 1
|
||||
ij_less_blank_lines_between_blocks = 1
|
||||
ij_less_brace_placement = 0
|
||||
ij_less_hex_color_long_format = false
|
||||
ij_less_hex_color_lower_case = false
|
||||
ij_less_hex_color_short_format = false
|
||||
ij_less_hex_color_upper_case = false
|
||||
ij_less_keep_blank_lines_in_code = 2
|
||||
ij_less_keep_indents_on_empty_lines = false
|
||||
ij_less_keep_single_line_blocks = false
|
||||
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_less_space_after_colon = true
|
||||
ij_less_space_before_opening_brace = true
|
||||
ij_less_value_alignment = 0
|
||||
|
||||
[*.sass]
|
||||
indent_size = 2
|
||||
ij_sass_align_closing_brace_with_properties = false
|
||||
ij_sass_blank_lines_around_nested_selector = 1
|
||||
ij_sass_blank_lines_between_blocks = 1
|
||||
ij_sass_brace_placement = 0
|
||||
ij_sass_hex_color_long_format = false
|
||||
ij_sass_hex_color_lower_case = false
|
||||
ij_sass_hex_color_short_format = false
|
||||
ij_sass_hex_color_upper_case = false
|
||||
ij_sass_keep_blank_lines_in_code = 2
|
||||
ij_sass_keep_indents_on_empty_lines = false
|
||||
ij_sass_keep_single_line_blocks = false
|
||||
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_sass_space_after_colon = true
|
||||
ij_sass_space_before_opening_brace = true
|
||||
ij_sass_value_alignment = 0
|
||||
|
||||
[*.scss]
|
||||
indent_style = tab
|
||||
ij_scss_align_closing_brace_with_properties = false
|
||||
ij_scss_blank_lines_around_nested_selector = 1
|
||||
ij_scss_blank_lines_between_blocks = 1
|
||||
ij_scss_brace_placement = 0
|
||||
ij_scss_hex_color_long_format = false
|
||||
ij_scss_hex_color_lower_case = false
|
||||
ij_scss_hex_color_short_format = false
|
||||
ij_scss_hex_color_upper_case = false
|
||||
ij_scss_keep_blank_lines_in_code = 2
|
||||
ij_scss_keep_indents_on_empty_lines = false
|
||||
ij_scss_keep_single_line_blocks = false
|
||||
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_scss_space_after_colon = true
|
||||
ij_scss_space_before_opening_brace = true
|
||||
ij_scss_value_alignment = 0
|
||||
|
||||
[*.twig]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_twig_keep_indents_on_empty_lines = false
|
||||
ij_twig_spaces_inside_delimiters = true
|
||||
ij_twig_spaces_inside_variable_delimiters = true
|
||||
|
||||
[.editorconfig]
|
||||
ij_editorconfig_align_group_field_declarations = false
|
||||
ij_editorconfig_space_after_colon = false
|
||||
ij_editorconfig_space_after_comma = true
|
||||
ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
ij_editorconfig_spaces_around_assignment_operators = true
|
||||
|
||||
[{*.cjs,*.js}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
ij_javascript_align_imports = false
|
||||
ij_javascript_align_multiline_array_initializer_expression = false
|
||||
ij_javascript_align_multiline_binary_operation = false
|
||||
ij_javascript_align_multiline_chained_methods = false
|
||||
ij_javascript_align_multiline_extends_list = false
|
||||
ij_javascript_align_multiline_for = true
|
||||
ij_javascript_align_multiline_parameters = true
|
||||
ij_javascript_align_multiline_parameters_in_calls = false
|
||||
ij_javascript_align_multiline_ternary_operation = false
|
||||
ij_javascript_align_object_properties = 0
|
||||
ij_javascript_align_union_types = false
|
||||
ij_javascript_align_var_statements = 0
|
||||
ij_javascript_array_initializer_new_line_after_left_brace = false
|
||||
ij_javascript_array_initializer_right_brace_on_new_line = false
|
||||
ij_javascript_array_initializer_wrap = off
|
||||
ij_javascript_assignment_wrap = off
|
||||
ij_javascript_binary_operation_sign_on_next_line = false
|
||||
ij_javascript_binary_operation_wrap = off
|
||||
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*
|
||||
ij_javascript_blank_lines_after_imports = 1
|
||||
ij_javascript_blank_lines_around_class = 1
|
||||
ij_javascript_blank_lines_around_field = 0
|
||||
ij_javascript_blank_lines_around_function = 1
|
||||
ij_javascript_blank_lines_around_method = 1
|
||||
ij_javascript_block_brace_style = next_line
|
||||
ij_javascript_call_parameters_new_line_after_left_paren = false
|
||||
ij_javascript_call_parameters_right_paren_on_new_line = false
|
||||
ij_javascript_call_parameters_wrap = off
|
||||
ij_javascript_catch_on_new_line = false
|
||||
ij_javascript_chained_call_dot_on_new_line = true
|
||||
ij_javascript_class_brace_style = end_of_line
|
||||
ij_javascript_comma_on_new_line = false
|
||||
ij_javascript_do_while_brace_force = never
|
||||
ij_javascript_else_on_new_line = true
|
||||
ij_javascript_enforce_trailing_comma = keep
|
||||
ij_javascript_extends_keyword_wrap = off
|
||||
ij_javascript_extends_list_wrap = off
|
||||
ij_javascript_field_prefix = _
|
||||
ij_javascript_file_name_style = relaxed
|
||||
ij_javascript_finally_on_new_line = false
|
||||
ij_javascript_for_brace_force = never
|
||||
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||
ij_javascript_for_statement_wrap = off
|
||||
ij_javascript_force_quote_style = false
|
||||
ij_javascript_force_semicolon_style = false
|
||||
ij_javascript_function_expression_brace_style = end_of_line
|
||||
ij_javascript_if_brace_force = always
|
||||
ij_javascript_import_merge_members = global
|
||||
ij_javascript_import_prefer_absolute_path = global
|
||||
ij_javascript_import_sort_members = true
|
||||
ij_javascript_import_sort_module_name = false
|
||||
ij_javascript_import_use_node_resolution = true
|
||||
ij_javascript_imports_wrap = on_every_item
|
||||
ij_javascript_indent_case_from_switch = true
|
||||
ij_javascript_indent_chained_calls = true
|
||||
ij_javascript_indent_package_children = 0
|
||||
ij_javascript_jsx_attribute_value = braces
|
||||
ij_javascript_keep_blank_lines_in_code = 2
|
||||
ij_javascript_keep_first_column_comment = true
|
||||
ij_javascript_keep_indents_on_empty_lines = false
|
||||
ij_javascript_keep_line_breaks = true
|
||||
ij_javascript_keep_simple_blocks_in_one_line = false
|
||||
ij_javascript_keep_simple_methods_in_one_line = false
|
||||
ij_javascript_line_comment_add_space = true
|
||||
ij_javascript_line_comment_at_first_column = false
|
||||
ij_javascript_method_brace_style = end_of_line
|
||||
ij_javascript_method_call_chain_wrap = off
|
||||
ij_javascript_method_parameters_new_line_after_left_paren = false
|
||||
ij_javascript_method_parameters_right_paren_on_new_line = false
|
||||
ij_javascript_method_parameters_wrap = off
|
||||
ij_javascript_object_literal_wrap = on_every_item
|
||||
ij_javascript_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_javascript_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_javascript_place_assignment_sign_on_next_line = false
|
||||
ij_javascript_prefer_as_type_cast = false
|
||||
ij_javascript_prefer_parameters_wrap = false
|
||||
ij_javascript_reformat_c_style_comments = false
|
||||
ij_javascript_space_after_colon = true
|
||||
ij_javascript_space_after_comma = true
|
||||
ij_javascript_space_after_dots_in_rest_parameter = false
|
||||
ij_javascript_space_after_generator_mult = true
|
||||
ij_javascript_space_after_property_colon = true
|
||||
ij_javascript_space_after_quest = true
|
||||
ij_javascript_space_after_type_colon = true
|
||||
ij_javascript_space_after_unary_not = false
|
||||
ij_javascript_space_before_async_arrow_lparen = true
|
||||
ij_javascript_space_before_catch_keyword = true
|
||||
ij_javascript_space_before_catch_left_brace = true
|
||||
ij_javascript_space_before_catch_parentheses = true
|
||||
ij_javascript_space_before_class_lbrace = true
|
||||
ij_javascript_space_before_class_left_brace = true
|
||||
ij_javascript_space_before_colon = true
|
||||
ij_javascript_space_before_comma = false
|
||||
ij_javascript_space_before_do_left_brace = true
|
||||
ij_javascript_space_before_else_keyword = true
|
||||
ij_javascript_space_before_else_left_brace = true
|
||||
ij_javascript_space_before_finally_keyword = true
|
||||
ij_javascript_space_before_finally_left_brace = true
|
||||
ij_javascript_space_before_for_left_brace = true
|
||||
ij_javascript_space_before_for_parentheses = true
|
||||
ij_javascript_space_before_for_semicolon = false
|
||||
ij_javascript_space_before_function_left_parenth = true
|
||||
ij_javascript_space_before_generator_mult = false
|
||||
ij_javascript_space_before_if_left_brace = true
|
||||
ij_javascript_space_before_if_parentheses = true
|
||||
ij_javascript_space_before_method_call_parentheses = false
|
||||
ij_javascript_space_before_method_left_brace = true
|
||||
ij_javascript_space_before_method_parentheses = false
|
||||
ij_javascript_space_before_property_colon = false
|
||||
ij_javascript_space_before_quest = true
|
||||
ij_javascript_space_before_switch_left_brace = true
|
||||
ij_javascript_space_before_switch_parentheses = true
|
||||
ij_javascript_space_before_try_left_brace = true
|
||||
ij_javascript_space_before_type_colon = false
|
||||
ij_javascript_space_before_unary_not = false
|
||||
ij_javascript_space_before_while_keyword = true
|
||||
ij_javascript_space_before_while_left_brace = true
|
||||
ij_javascript_space_before_while_parentheses = true
|
||||
ij_javascript_spaces_around_additive_operators = false
|
||||
ij_javascript_spaces_around_arrow_function_operator = true
|
||||
ij_javascript_spaces_around_assignment_operators = true
|
||||
ij_javascript_spaces_around_bitwise_operators = true
|
||||
ij_javascript_spaces_around_equality_operators = true
|
||||
ij_javascript_spaces_around_logical_operators = true
|
||||
ij_javascript_spaces_around_multiplicative_operators = true
|
||||
ij_javascript_spaces_around_relational_operators = true
|
||||
ij_javascript_spaces_around_shift_operators = true
|
||||
ij_javascript_spaces_around_unary_operator = false
|
||||
ij_javascript_spaces_within_array_initializer_brackets = false
|
||||
ij_javascript_spaces_within_brackets = false
|
||||
ij_javascript_spaces_within_catch_parentheses = false
|
||||
ij_javascript_spaces_within_for_parentheses = false
|
||||
ij_javascript_spaces_within_if_parentheses = false
|
||||
ij_javascript_spaces_within_imports = false
|
||||
ij_javascript_spaces_within_interpolation_expressions = false
|
||||
ij_javascript_spaces_within_method_call_parentheses = false
|
||||
ij_javascript_spaces_within_method_parentheses = false
|
||||
ij_javascript_spaces_within_object_literal_braces = false
|
||||
ij_javascript_spaces_within_object_type_braces = true
|
||||
ij_javascript_spaces_within_parentheses = false
|
||||
ij_javascript_spaces_within_switch_parentheses = false
|
||||
ij_javascript_spaces_within_type_assertion = false
|
||||
ij_javascript_spaces_within_union_types = true
|
||||
ij_javascript_spaces_within_while_parentheses = false
|
||||
ij_javascript_special_else_if_treatment = true
|
||||
ij_javascript_ternary_operation_signs_on_next_line = false
|
||||
ij_javascript_ternary_operation_wrap = off
|
||||
ij_javascript_union_types_wrap = on_every_item
|
||||
ij_javascript_use_chained_calls_group_indents = true
|
||||
ij_javascript_use_double_quotes = true
|
||||
ij_javascript_use_explicit_js_extension = global
|
||||
ij_javascript_use_path_mapping = always
|
||||
ij_javascript_use_public_modifier = false
|
||||
ij_javascript_use_semicolon_after_statement = true
|
||||
ij_javascript_var_declaration_wrap = normal
|
||||
ij_javascript_while_brace_force = never
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.module,*.hphp,*.phtml,*.php5,*.php4,*.php,*.ctp,*.inc}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_group_field_declarations = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_key_value_pairs = false
|
||||
ij_php_align_multiline_array_initializer_expression = false
|
||||
ij_php_align_multiline_binary_operation = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
ij_php_align_multiline_extends_list = false
|
||||
ij_php_align_multiline_for = true
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_parameters_in_calls = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_align_phpdoc_param_names = false
|
||||
ij_php_api_weight = 1
|
||||
ij_php_array_initializer_new_line_after_left_brace = true
|
||||
ij_php_array_initializer_right_brace_on_new_line = true
|
||||
ij_php_array_initializer_wrap = on_every_item
|
||||
ij_php_assignment_wrap = off
|
||||
ij_php_author_weight = 7
|
||||
ij_php_binary_operation_sign_on_next_line = false
|
||||
ij_php_binary_operation_wrap = off
|
||||
ij_php_blank_lines_after_class_header = 0
|
||||
ij_php_blank_lines_after_function = 1
|
||||
ij_php_blank_lines_after_imports = 1
|
||||
ij_php_blank_lines_after_opening_tag = 0
|
||||
ij_php_blank_lines_after_package = 1
|
||||
ij_php_blank_lines_around_class = 1
|
||||
ij_php_blank_lines_around_constants = 0
|
||||
ij_php_blank_lines_around_field = 0
|
||||
ij_php_blank_lines_around_method = 1
|
||||
ij_php_blank_lines_before_class_end = 0
|
||||
ij_php_blank_lines_before_imports = 1
|
||||
ij_php_blank_lines_before_method_body = 0
|
||||
ij_php_blank_lines_before_package = 1
|
||||
ij_php_blank_lines_before_return_statement = 1
|
||||
ij_php_block_brace_style = next_line
|
||||
ij_php_call_parameters_new_line_after_left_paren = false
|
||||
ij_php_call_parameters_right_paren_on_new_line = false
|
||||
ij_php_call_parameters_wrap = normal
|
||||
ij_php_catch_on_new_line = true
|
||||
ij_php_category_weight = 28
|
||||
ij_php_class_brace_style = next_line
|
||||
ij_php_comma_after_last_array_element = true
|
||||
ij_php_concat_spaces = false
|
||||
ij_php_copyright_weight = 28
|
||||
ij_php_deprecated_weight = 28
|
||||
ij_php_do_while_brace_force = always
|
||||
ij_php_else_if_style = as_is
|
||||
ij_php_else_on_new_line = true
|
||||
ij_php_example_weight = 3
|
||||
ij_php_extends_keyword_wrap = off
|
||||
ij_php_extends_list_wrap = off
|
||||
ij_php_fields_default_visibility = private
|
||||
ij_php_filesource_weight = 28
|
||||
ij_php_finally_on_new_line = true
|
||||
ij_php_for_brace_force = always
|
||||
ij_php_for_statement_new_line_after_left_paren = false
|
||||
ij_php_for_statement_right_paren_on_new_line = false
|
||||
ij_php_for_statement_wrap = off
|
||||
ij_php_force_short_declaration_array_style = false
|
||||
ij_php_global_weight = 28
|
||||
ij_php_group_use_wrap = on_every_item
|
||||
ij_php_if_brace_force = always
|
||||
ij_php_if_lparen_on_next_line = false
|
||||
ij_php_if_rparen_on_next_line = false
|
||||
ij_php_ignore_weight = 28
|
||||
ij_php_import_sorting = alphabetic
|
||||
ij_php_indent_break_from_case = true
|
||||
ij_php_indent_case_from_switch = true
|
||||
ij_php_indent_code_in_php_tags = false
|
||||
ij_php_internal_weight = 0
|
||||
ij_php_keep_blank_lines_after_lbrace = 2
|
||||
ij_php_keep_blank_lines_before_right_brace = 2
|
||||
ij_php_keep_blank_lines_in_code = 2
|
||||
ij_php_keep_blank_lines_in_declarations = 2
|
||||
ij_php_keep_control_statement_in_one_line = true
|
||||
ij_php_keep_first_column_comment = true
|
||||
ij_php_keep_indents_on_empty_lines = false
|
||||
ij_php_keep_line_breaks = true
|
||||
ij_php_keep_rparen_and_lbrace_on_one_line = true
|
||||
ij_php_keep_simple_methods_in_one_line = false
|
||||
ij_php_lambda_brace_style = end_of_line
|
||||
ij_php_license_weight = 28
|
||||
ij_php_line_comment_add_space = false
|
||||
ij_php_line_comment_at_first_column = true
|
||||
ij_php_link_weight = 28
|
||||
ij_php_lower_case_boolean_const = true
|
||||
ij_php_lower_case_null_const = true
|
||||
ij_php_method_brace_style = next_line
|
||||
ij_php_method_call_chain_wrap = off
|
||||
ij_php_method_parameters_new_line_after_left_paren = true
|
||||
ij_php_method_parameters_right_paren_on_new_line = true
|
||||
ij_php_method_parameters_wrap = normal
|
||||
ij_php_method_weight = 28
|
||||
ij_php_modifier_list_wrap = false
|
||||
ij_php_multiline_chained_calls_semicolon_on_new_line = false
|
||||
ij_php_namespace_brace_style = 1
|
||||
ij_php_null_type_position = in_the_end
|
||||
ij_php_package_weight = 28
|
||||
ij_php_param_weight = 4
|
||||
ij_php_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_php_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_php_phpdoc_blank_line_before_tags = true
|
||||
ij_php_phpdoc_blank_lines_around_parameters = true
|
||||
ij_php_phpdoc_keep_blank_lines = true
|
||||
ij_php_phpdoc_param_spaces_between_name_and_description = 1
|
||||
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
|
||||
ij_php_phpdoc_param_spaces_between_type_and_name = 1
|
||||
ij_php_phpdoc_use_fqcn = true
|
||||
ij_php_phpdoc_wrap_long_lines = true
|
||||
ij_php_place_assignment_sign_on_next_line = false
|
||||
ij_php_place_parens_for_constructor = 0
|
||||
ij_php_property_read_weight = 28
|
||||
ij_php_property_weight = 28
|
||||
ij_php_property_write_weight = 28
|
||||
ij_php_return_type_on_new_line = false
|
||||
ij_php_return_weight = 5
|
||||
ij_php_see_weight = 2
|
||||
ij_php_since_weight = 28
|
||||
ij_php_sort_phpdoc_elements = true
|
||||
ij_php_space_after_colon = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_after_comma = true
|
||||
ij_php_space_after_for_semicolon = true
|
||||
ij_php_space_after_quest = true
|
||||
ij_php_space_after_type_cast = false
|
||||
ij_php_space_after_unary_not = false
|
||||
ij_php_space_before_array_initializer_left_brace = false
|
||||
ij_php_space_before_catch_keyword = true
|
||||
ij_php_space_before_catch_left_brace = true
|
||||
ij_php_space_before_catch_parentheses = true
|
||||
ij_php_space_before_class_left_brace = true
|
||||
ij_php_space_before_closure_left_parenthesis = true
|
||||
ij_php_space_before_colon = true
|
||||
ij_php_space_before_colon_in_return_type = false
|
||||
ij_php_space_before_comma = false
|
||||
ij_php_space_before_do_left_brace = true
|
||||
ij_php_space_before_else_keyword = true
|
||||
ij_php_space_before_else_left_brace = true
|
||||
ij_php_space_before_finally_keyword = true
|
||||
ij_php_space_before_finally_left_brace = true
|
||||
ij_php_space_before_for_left_brace = true
|
||||
ij_php_space_before_for_parentheses = true
|
||||
ij_php_space_before_for_semicolon = false
|
||||
ij_php_space_before_if_left_brace = true
|
||||
ij_php_space_before_if_parentheses = true
|
||||
ij_php_space_before_method_call_parentheses = false
|
||||
ij_php_space_before_method_left_brace = true
|
||||
ij_php_space_before_method_parentheses = false
|
||||
ij_php_space_before_quest = true
|
||||
ij_php_space_before_switch_left_brace = true
|
||||
ij_php_space_before_switch_parentheses = true
|
||||
ij_php_space_before_try_left_brace = true
|
||||
ij_php_space_before_unary_not = false
|
||||
ij_php_space_before_while_keyword = true
|
||||
ij_php_space_before_while_left_brace = true
|
||||
ij_php_space_before_while_parentheses = true
|
||||
ij_php_space_between_ternary_quest_and_colon = false
|
||||
ij_php_spaces_around_additive_operators = true
|
||||
ij_php_spaces_around_arrow = false
|
||||
ij_php_spaces_around_assignment_in_declare = false
|
||||
ij_php_spaces_around_assignment_operators = true
|
||||
ij_php_spaces_around_bitwise_operators = true
|
||||
ij_php_spaces_around_equality_operators = true
|
||||
ij_php_spaces_around_logical_operators = true
|
||||
ij_php_spaces_around_multiplicative_operators = true
|
||||
ij_php_spaces_around_null_coalesce_operator = true
|
||||
ij_php_spaces_around_relational_operators = true
|
||||
ij_php_spaces_around_shift_operators = true
|
||||
ij_php_spaces_around_unary_operator = false
|
||||
ij_php_spaces_around_var_within_brackets = false
|
||||
ij_php_spaces_within_array_initializer_braces = false
|
||||
ij_php_spaces_within_brackets = false
|
||||
ij_php_spaces_within_catch_parentheses = false
|
||||
ij_php_spaces_within_for_parentheses = false
|
||||
ij_php_spaces_within_if_parentheses = false
|
||||
ij_php_spaces_within_method_call_parentheses = false
|
||||
ij_php_spaces_within_method_parentheses = false
|
||||
ij_php_spaces_within_parentheses = false
|
||||
ij_php_spaces_within_short_echo_tags = true
|
||||
ij_php_spaces_within_switch_parentheses = false
|
||||
ij_php_spaces_within_while_parentheses = false
|
||||
ij_php_special_else_if_treatment = false
|
||||
ij_php_subpackage_weight = 28
|
||||
ij_php_ternary_operation_signs_on_next_line = false
|
||||
ij_php_ternary_operation_wrap = off
|
||||
ij_php_throws_weight = 6
|
||||
ij_php_todo_weight = 28
|
||||
ij_php_unknown_tag_weight = 28
|
||||
ij_php_upper_case_boolean_const = false
|
||||
ij_php_upper_case_null_const = false
|
||||
ij_php_uses_weight = 28
|
||||
ij_php_var_weight = 28
|
||||
ij_php_variable_naming_style = mixed
|
||||
ij_php_version_weight = 28
|
||||
ij_php_while_brace_force = always
|
||||
ij_php_while_on_new_line = false
|
||||
|
||||
[{*.sht,*.htm,*.html,*.shtm,*.shtml}]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||
ij_html_align_attributes = true
|
||||
ij_html_align_text = false
|
||||
ij_html_attribute_wrap = normal
|
||||
ij_html_block_comment_at_first_column = true
|
||||
ij_html_do_not_align_children_of_min_lines = 0
|
||||
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
|
||||
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot,style,script,head
|
||||
ij_html_enforce_quotes = false
|
||||
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
|
||||
ij_html_keep_blank_lines = 2
|
||||
ij_html_keep_indents_on_empty_lines = false
|
||||
ij_html_keep_line_breaks = true
|
||||
ij_html_keep_line_breaks_in_text = true
|
||||
ij_html_keep_whitespaces = false
|
||||
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||
ij_html_line_comment_at_first_column = true
|
||||
ij_html_new_line_after_last_attribute = never
|
||||
ij_html_new_line_before_first_attribute = never
|
||||
ij_html_quote_style = double
|
||||
ij_html_remove_new_line_before_tags = br
|
||||
ij_html_space_after_tag_name = false
|
||||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
|
||||
[{*.ts,*.ats}]
|
||||
ij_continuation_indent_size = 4
|
||||
ij_typescript_align_imports = false
|
||||
ij_typescript_align_multiline_array_initializer_expression = false
|
||||
ij_typescript_align_multiline_binary_operation = false
|
||||
ij_typescript_align_multiline_chained_methods = false
|
||||
ij_typescript_align_multiline_extends_list = false
|
||||
ij_typescript_align_multiline_for = true
|
||||
ij_typescript_align_multiline_parameters = true
|
||||
ij_typescript_align_multiline_parameters_in_calls = false
|
||||
ij_typescript_align_multiline_ternary_operation = false
|
||||
ij_typescript_align_object_properties = 0
|
||||
ij_typescript_align_union_types = false
|
||||
ij_typescript_align_var_statements = 0
|
||||
ij_typescript_array_initializer_new_line_after_left_brace = false
|
||||
ij_typescript_array_initializer_right_brace_on_new_line = false
|
||||
ij_typescript_array_initializer_wrap = off
|
||||
ij_typescript_assignment_wrap = off
|
||||
ij_typescript_binary_operation_sign_on_next_line = false
|
||||
ij_typescript_binary_operation_wrap = off
|
||||
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**/*
|
||||
ij_typescript_blank_lines_after_imports = 1
|
||||
ij_typescript_blank_lines_around_class = 1
|
||||
ij_typescript_blank_lines_around_field = 0
|
||||
ij_typescript_blank_lines_around_field_in_interface = 0
|
||||
ij_typescript_blank_lines_around_function = 1
|
||||
ij_typescript_blank_lines_around_method = 1
|
||||
ij_typescript_blank_lines_around_method_in_interface = 1
|
||||
ij_typescript_block_brace_style = end_of_line
|
||||
ij_typescript_call_parameters_new_line_after_left_paren = false
|
||||
ij_typescript_call_parameters_right_paren_on_new_line = false
|
||||
ij_typescript_call_parameters_wrap = off
|
||||
ij_typescript_catch_on_new_line = false
|
||||
ij_typescript_chained_call_dot_on_new_line = true
|
||||
ij_typescript_class_brace_style = end_of_line
|
||||
ij_typescript_comma_on_new_line = false
|
||||
ij_typescript_do_while_brace_force = never
|
||||
ij_typescript_else_on_new_line = false
|
||||
ij_typescript_enforce_trailing_comma = keep
|
||||
ij_typescript_extends_keyword_wrap = off
|
||||
ij_typescript_extends_list_wrap = off
|
||||
ij_typescript_field_prefix = _
|
||||
ij_typescript_file_name_style = relaxed
|
||||
ij_typescript_finally_on_new_line = false
|
||||
ij_typescript_for_brace_force = never
|
||||
ij_typescript_for_statement_new_line_after_left_paren = false
|
||||
ij_typescript_for_statement_right_paren_on_new_line = false
|
||||
ij_typescript_for_statement_wrap = off
|
||||
ij_typescript_force_quote_style = false
|
||||
ij_typescript_force_semicolon_style = false
|
||||
ij_typescript_function_expression_brace_style = end_of_line
|
||||
ij_typescript_if_brace_force = never
|
||||
ij_typescript_import_merge_members = global
|
||||
ij_typescript_import_prefer_absolute_path = global
|
||||
ij_typescript_import_sort_members = true
|
||||
ij_typescript_import_sort_module_name = false
|
||||
ij_typescript_import_use_node_resolution = true
|
||||
ij_typescript_imports_wrap = on_every_item
|
||||
ij_typescript_indent_case_from_switch = true
|
||||
ij_typescript_indent_chained_calls = true
|
||||
ij_typescript_indent_package_children = 0
|
||||
ij_typescript_jsdoc_include_types = false
|
||||
ij_typescript_jsx_attribute_value = braces
|
||||
ij_typescript_keep_blank_lines_in_code = 2
|
||||
ij_typescript_keep_first_column_comment = true
|
||||
ij_typescript_keep_indents_on_empty_lines = false
|
||||
ij_typescript_keep_line_breaks = true
|
||||
ij_typescript_keep_simple_blocks_in_one_line = false
|
||||
ij_typescript_keep_simple_methods_in_one_line = false
|
||||
ij_typescript_line_comment_add_space = true
|
||||
ij_typescript_line_comment_at_first_column = false
|
||||
ij_typescript_method_brace_style = end_of_line
|
||||
ij_typescript_method_call_chain_wrap = off
|
||||
ij_typescript_method_parameters_new_line_after_left_paren = false
|
||||
ij_typescript_method_parameters_right_paren_on_new_line = false
|
||||
ij_typescript_method_parameters_wrap = off
|
||||
ij_typescript_object_literal_wrap = on_every_item
|
||||
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_typescript_place_assignment_sign_on_next_line = false
|
||||
ij_typescript_prefer_as_type_cast = false
|
||||
ij_typescript_prefer_parameters_wrap = false
|
||||
ij_typescript_reformat_c_style_comments = false
|
||||
ij_typescript_space_after_colon = true
|
||||
ij_typescript_space_after_comma = true
|
||||
ij_typescript_space_after_dots_in_rest_parameter = false
|
||||
ij_typescript_space_after_generator_mult = true
|
||||
ij_typescript_space_after_property_colon = true
|
||||
ij_typescript_space_after_quest = true
|
||||
ij_typescript_space_after_type_colon = true
|
||||
ij_typescript_space_after_unary_not = false
|
||||
ij_typescript_space_before_async_arrow_lparen = true
|
||||
ij_typescript_space_before_catch_keyword = true
|
||||
ij_typescript_space_before_catch_left_brace = true
|
||||
ij_typescript_space_before_catch_parentheses = true
|
||||
ij_typescript_space_before_class_lbrace = true
|
||||
ij_typescript_space_before_class_left_brace = true
|
||||
ij_typescript_space_before_colon = true
|
||||
ij_typescript_space_before_comma = false
|
||||
ij_typescript_space_before_do_left_brace = true
|
||||
ij_typescript_space_before_else_keyword = true
|
||||
ij_typescript_space_before_else_left_brace = true
|
||||
ij_typescript_space_before_finally_keyword = true
|
||||
ij_typescript_space_before_finally_left_brace = true
|
||||
ij_typescript_space_before_for_left_brace = true
|
||||
ij_typescript_space_before_for_parentheses = true
|
||||
ij_typescript_space_before_for_semicolon = false
|
||||
ij_typescript_space_before_function_left_parenth = true
|
||||
ij_typescript_space_before_generator_mult = false
|
||||
ij_typescript_space_before_if_left_brace = true
|
||||
ij_typescript_space_before_if_parentheses = true
|
||||
ij_typescript_space_before_method_call_parentheses = false
|
||||
ij_typescript_space_before_method_left_brace = true
|
||||
ij_typescript_space_before_method_parentheses = false
|
||||
ij_typescript_space_before_property_colon = false
|
||||
ij_typescript_space_before_quest = true
|
||||
ij_typescript_space_before_switch_left_brace = true
|
||||
ij_typescript_space_before_switch_parentheses = true
|
||||
ij_typescript_space_before_try_left_brace = true
|
||||
ij_typescript_space_before_type_colon = false
|
||||
ij_typescript_space_before_unary_not = false
|
||||
ij_typescript_space_before_while_keyword = true
|
||||
ij_typescript_space_before_while_left_brace = true
|
||||
ij_typescript_space_before_while_parentheses = true
|
||||
ij_typescript_spaces_around_additive_operators = true
|
||||
ij_typescript_spaces_around_arrow_function_operator = true
|
||||
ij_typescript_spaces_around_assignment_operators = true
|
||||
ij_typescript_spaces_around_bitwise_operators = true
|
||||
ij_typescript_spaces_around_equality_operators = true
|
||||
ij_typescript_spaces_around_logical_operators = true
|
||||
ij_typescript_spaces_around_multiplicative_operators = true
|
||||
ij_typescript_spaces_around_relational_operators = true
|
||||
ij_typescript_spaces_around_shift_operators = true
|
||||
ij_typescript_spaces_around_unary_operator = false
|
||||
ij_typescript_spaces_within_array_initializer_brackets = false
|
||||
ij_typescript_spaces_within_brackets = false
|
||||
ij_typescript_spaces_within_catch_parentheses = false
|
||||
ij_typescript_spaces_within_for_parentheses = false
|
||||
ij_typescript_spaces_within_if_parentheses = false
|
||||
ij_typescript_spaces_within_imports = false
|
||||
ij_typescript_spaces_within_interpolation_expressions = false
|
||||
ij_typescript_spaces_within_method_call_parentheses = false
|
||||
ij_typescript_spaces_within_method_parentheses = false
|
||||
ij_typescript_spaces_within_object_literal_braces = false
|
||||
ij_typescript_spaces_within_object_type_braces = true
|
||||
ij_typescript_spaces_within_parentheses = false
|
||||
ij_typescript_spaces_within_switch_parentheses = false
|
||||
ij_typescript_spaces_within_type_assertion = false
|
||||
ij_typescript_spaces_within_union_types = true
|
||||
ij_typescript_spaces_within_while_parentheses = false
|
||||
ij_typescript_special_else_if_treatment = true
|
||||
ij_typescript_ternary_operation_signs_on_next_line = false
|
||||
ij_typescript_ternary_operation_wrap = off
|
||||
ij_typescript_union_types_wrap = on_every_item
|
||||
ij_typescript_use_chained_calls_group_indents = false
|
||||
ij_typescript_use_double_quotes = true
|
||||
ij_typescript_use_explicit_js_extension = global
|
||||
ij_typescript_use_path_mapping = always
|
||||
ij_typescript_use_public_modifier = false
|
||||
ij_typescript_use_semicolon_after_statement = true
|
||||
ij_typescript_var_declaration_wrap = normal
|
||||
ij_typescript_while_brace_force = never
|
||||
ij_typescript_while_on_new_line = false
|
||||
ij_typescript_wrap_comments = false
|
||||
|
||||
[{*.yml,*.yaml}]
|
||||
indent_size = 2
|
||||
ij_continuation_indent_size = 2
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
||||
|
||||
[{*.zsh,*.bash,*.sh}]
|
||||
ij_shell_binary_ops_start_line = false
|
||||
ij_shell_keep_column_alignment_padding = false
|
||||
ij_shell_minify_program = false
|
||||
ij_shell_redirect_followed_by_space = false
|
||||
ij_shell_switch_cases_indented = false
|
||||
|
||||
[{.stylelintrc,.eslintrc,.babelrc,jest.config,*.bowerrc,*.jsb3,*.jsb2,*.json}]
|
||||
indent_size = 2
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = true
|
||||
ij_json_space_before_comma = false
|
||||
ij_json_spaces_within_braces = false
|
||||
ij_json_spaces_within_brackets = false
|
||||
ij_json_wrap_long_lines = false
|
||||
|
||||
[{phpunit.xml.dist,*.jhm,*.rng,*.wsdl,*.fxml,*.xslt,*.jrxml,*.ant,*.xul,*.xsl,*.xsd,*.tld,*.jnlp,*.xml}]
|
||||
indent_size = 2
|
||||
indent_style = tab
|
||||
tab_width = 2
|
||||
ij_smart_tabs = true
|
||||
ij_xml_block_comment_at_first_column = true
|
||||
ij_xml_keep_indents_on_empty_lines = false
|
||||
ij_xml_line_comment_at_first_column = true
|
||||
48
.gitignore
vendored
48
.gitignore
vendored
@@ -1,38 +1,48 @@
|
||||
|
||||
# no slash at the end to handle also symlinks
|
||||
/toolkit
|
||||
/conf/*
|
||||
/env-*/*
|
||||
/env-*
|
||||
|
||||
# maintenance mode (N°2240)
|
||||
/.maintenance
|
||||
|
||||
# listing prevention in conf directory
|
||||
/conf/**
|
||||
!/conf/.htaccess
|
||||
!/conf/index.php
|
||||
!/conf/web.config
|
||||
|
||||
# composer reserver directory, from sources, populate/update using "composer install"
|
||||
vendor/*
|
||||
test/vendor/*
|
||||
|
||||
# all datas but listing prevention
|
||||
data/*
|
||||
!data/.htaccess
|
||||
!data/index.php
|
||||
!data/web.config
|
||||
/data/**
|
||||
!/data/.htaccess
|
||||
!/data/index.php
|
||||
!/data/web.config
|
||||
|
||||
# iTop extensions
|
||||
extensions/*
|
||||
!extensions/readme.txt
|
||||
/extensions/**
|
||||
!/extensions/readme.txt
|
||||
|
||||
# all logs but listing prevention
|
||||
log/*
|
||||
!log/.htaccess
|
||||
!log/index.php
|
||||
!log/web.config
|
||||
/log/**
|
||||
!/log/.htaccess
|
||||
!/log/index.php
|
||||
!/log/web.config
|
||||
|
||||
|
||||
# Jetbrains
|
||||
.idea/**
|
||||
!.idea/encodings.xml
|
||||
!.idea/codeStyles
|
||||
!.idea/codeStyles/*
|
||||
!.idea/inspectionProfiles
|
||||
!.idea/inspectionProfiles/*
|
||||
|
||||
/.idea/**
|
||||
!/.idea/encodings.xml
|
||||
!/.idea/codeStyles
|
||||
!/.idea/codeStyles/*
|
||||
!/.idea/inspectionProfiles
|
||||
!/.idea/inspectionProfiles/*
|
||||
|
||||
#phpdocumentor temp file
|
||||
ast.dump
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
33
.idea/codeStyles/Project.xml
generated
33
.idea/codeStyles/Project.xml
generated
@@ -1,37 +1,56 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<option name="RIGHT_MARGIN" value="320" />
|
||||
<option name="RIGHT_MARGIN" value="140" />
|
||||
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
|
||||
<option name="SOFT_MARGINS" value="140" />
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="html,body,thead,tbody,tfoot,script,style" />
|
||||
<option name="HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES" value="4" />
|
||||
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="html,body,thead,tbody,tfoot,style,script,head" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="USE_CHAINED_CALLS_GROUP_INDENTS" value="true" />
|
||||
</JSCodeStyleSettings>
|
||||
<PHPCodeStyleSettings>
|
||||
<option name="CONCAT_SPACES" value="false" />
|
||||
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
|
||||
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
|
||||
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="true" />
|
||||
<option name="PHPDOC_WRAP_LONG_LINES" value="true" />
|
||||
<option name="THROWS_WEIGHT" value="6" />
|
||||
<option name="PARAM_WEIGHT" value="4" />
|
||||
<option name="RETURN_WEIGHT" value="5" />
|
||||
<option name="AUTHOR_WEIGHT" value="7" />
|
||||
<option name="INTERNAL_WEIGHT" value="0" />
|
||||
<option name="API_WEIGHT" value="1" />
|
||||
<option name="EXAMPLE_WEIGHT" value="3" />
|
||||
<option name="SEE_WEIGHT" value="2" />
|
||||
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
|
||||
<option name="LOWER_CASE_NULL_CONST" value="true" />
|
||||
<option name="BLANK_LINES_BEFORE_RETURN_STATEMENT" value="1" />
|
||||
<option name="KEEP_RPAREN_AND_LBRACE_ON_ONE_LINE" value="true" />
|
||||
<option name="PHPDOC_USE_FQCN" value="true" />
|
||||
</PHPCodeStyleSettings>
|
||||
<XML>
|
||||
<option name="XML_TEXT_WRAP" value="0" />
|
||||
<option name="XML_KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="XML_KEEP_WHITE_SPACES_INSIDE_CDATA" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="BRACE_STYLE" value="2" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="SPACE_AROUND_ADDITIVE_OPERATORS" value="false" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<indentOptions>
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="PHP">
|
||||
<option name="RIGHT_MARGIN" value="320" />
|
||||
<option name="BLANK_LINES_AFTER_PACKAGE" value="1" />
|
||||
<option name="BRACE_STYLE" value="2" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
@@ -49,9 +68,7 @@
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
<option name="WRAP_ON_TYPING" value="1" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
126
.idea/inspectionProfiles/Combodo.xml
generated
126
.idea/inspectionProfiles/Combodo.xml
generated
@@ -1,10 +1,81 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Combodo" />
|
||||
<inspection_tool class="CascadeStringReplacementInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ForgottenDebugOutputInspection" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="configuration">
|
||||
<list>
|
||||
<option value="\Codeception\Util\Debug::debug" />
|
||||
<option value="\Codeception\Util\Debug::pause" />
|
||||
<option value="\Doctrine\Common\Util\Debug::dump" />
|
||||
<option value="\Doctrine\Common\Util\Debug::export" />
|
||||
<option value="\Illuminate\Support\Debug\Dumper::dump" />
|
||||
<option value="\Symfony\Component\Debug\Debug::enable" />
|
||||
<option value="\Symfony\Component\Debug\DebugClassLoader::enable" />
|
||||
<option value="\Symfony\Component\Debug\ErrorHandler::register" />
|
||||
<option value="\Symfony\Component\Debug\ExceptionHandler::register" />
|
||||
<option value="\TYPO3\CMS\Core\Utility\DebugUtility::debug" />
|
||||
<option value="\Zend\Debug\Debug::dump" />
|
||||
<option value="\Zend\Di\Display\Console::export" />
|
||||
<option value="dd" />
|
||||
<option value="debug_print_backtrace" />
|
||||
<option value="debug_zval_dump" />
|
||||
<option value="dpm" />
|
||||
<option value="dpq" />
|
||||
<option value="dsm" />
|
||||
<option value="dump" />
|
||||
<option value="dvm" />
|
||||
<option value="error_log" />
|
||||
<option value="kpr" />
|
||||
<option value="phpinfo" />
|
||||
<option value="print_r" />
|
||||
<option value="var_dump" />
|
||||
<option value="var_export" />
|
||||
<option value="xdebug_break" />
|
||||
<option value="xdebug_call_class" />
|
||||
<option value="xdebug_call_file" />
|
||||
<option value="xdebug_call_function" />
|
||||
<option value="xdebug_call_line" />
|
||||
<option value="xdebug_code_coverage_started" />
|
||||
<option value="xdebug_debug_zval" />
|
||||
<option value="xdebug_debug_zval_stdout" />
|
||||
<option value="xdebug_dump_superglobals" />
|
||||
<option value="xdebug_enable" />
|
||||
<option value="xdebug_get_code_coverage" />
|
||||
<option value="xdebug_get_collected_errors" />
|
||||
<option value="xdebug_get_declared_vars" />
|
||||
<option value="xdebug_get_function_stack" />
|
||||
<option value="xdebug_get_headers" />
|
||||
<option value="xdebug_get_monitored_functions" />
|
||||
<option value="xdebug_get_profiler_filename" />
|
||||
<option value="xdebug_get_stack_depth" />
|
||||
<option value="xdebug_get_tracefile_name" />
|
||||
<option value="xdebug_is_enabled" />
|
||||
<option value="xdebug_memory_usage" />
|
||||
<option value="xdebug_peak_memory_usage" />
|
||||
<option value="xdebug_print_function_stack" />
|
||||
<option value="xdebug_start_code_coverage" />
|
||||
<option value="xdebug_start_error_collection" />
|
||||
<option value="xdebug_start_function_monitor" />
|
||||
<option value="xdebug_start_trace" />
|
||||
<option value="xdebug_stop_code_coverage" />
|
||||
<option value="xdebug_stop_error_collection" />
|
||||
<option value="xdebug_stop_function_monitor" />
|
||||
<option value="xdebug_stop_trace" />
|
||||
<option value="xdebug_time_index" />
|
||||
<option value="xdebug_var_dump" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="migratedIntoUserSpace" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="HtmlRequiredAltAttribute" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="HtmlRequiredLangAttribute" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PhpComposerExtensionStubsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpShortOpenTagInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpTooManyParametersInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="limit" value="7" />
|
||||
</inspection_tool>
|
||||
@@ -19,6 +90,61 @@
|
||||
<inspection_tool class="PhpUnusedParameterInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="DONT_REPORT_ABSTRACT_CLASS" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SecurityAdvisoriesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="optionConfiguration">
|
||||
<list>
|
||||
<option value="barryvdh/laravel-debugbar" />
|
||||
<option value="behat/behat" />
|
||||
<option value="brianium/paratest" />
|
||||
<option value="codeception/codeception" />
|
||||
<option value="codedungeon/phpunit-result-printer" />
|
||||
<option value="composer/composer" />
|
||||
<option value="doctrine/coding-standard" />
|
||||
<option value="filp/whoops" />
|
||||
<option value="friendsofphp/php-cs-fixer" />
|
||||
<option value="humbug/humbug" />
|
||||
<option value="infection/infection" />
|
||||
<option value="jakub-onderka/php-parallel-lint" />
|
||||
<option value="johnkary/phpunit-speedtrap" />
|
||||
<option value="kalessil/production-dependencies-guard" />
|
||||
<option value="mikey179/vfsStream" />
|
||||
<option value="mockery/mockery" />
|
||||
<option value="mybuilder/phpunit-accelerator" />
|
||||
<option value="orchestra/testbench" />
|
||||
<option value="pdepend/pdepend" />
|
||||
<option value="phan/phan" />
|
||||
<option value="phing/phing" />
|
||||
<option value="phpcompatibility/php-compatibility" />
|
||||
<option value="phpmd/phpmd" />
|
||||
<option value="phpro/grumphp" />
|
||||
<option value="phpspec/phpspec" />
|
||||
<option value="phpspec/prophecy" />
|
||||
<option value="phpstan/phpstan" />
|
||||
<option value="phpunit/phpunit" />
|
||||
<option value="povils/phpmnd" />
|
||||
<option value="roave/security-advisories" />
|
||||
<option value="satooshi/php-coveralls" />
|
||||
<option value="sebastian/phpcpd" />
|
||||
<option value="slevomat/coding-standard" />
|
||||
<option value="spatie/phpunit-watcher" />
|
||||
<option value="squizlabs/php_codesniffer" />
|
||||
<option value="sstalle/php7cc" />
|
||||
<option value="symfony/debug" />
|
||||
<option value="symfony/maker-bundle" />
|
||||
<option value="symfony/phpunit-bridge" />
|
||||
<option value="symfony/var-dumper" />
|
||||
<option value="vimeo/psalm" />
|
||||
<option value="wimg/php-compatibility" />
|
||||
<option value="wp-coding-standards/wpcs" />
|
||||
<option value="yiisoft/yii2-coding-standards" />
|
||||
<option value="yiisoft/yii2-debug" />
|
||||
<option value="yiisoft/yii2-gii" />
|
||||
<option value="zendframework/zend-coding-standard" />
|
||||
<option value="zendframework/zend-debug" />
|
||||
<option value="zendframework/zend-test" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
|
||||
1
.idea/inspectionProfiles/profiles_settings.xml
generated
1
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +1,5 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="projectProfile" value="Combodo" />
|
||||
<option name="PROJECT_PROFILE" value="Combodo" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
|
||||
@@ -10,5 +10,7 @@ mkdir -p toolkit
|
||||
rm -rf toolkit/*
|
||||
|
||||
# fill target dirs
|
||||
curl http://www.combodo.com/documentation/iTopDataModelToolkit-2.3.zip | tar xvz --directory toolkit
|
||||
curl https://www.combodo.com/documentation/iTopDataModelToolkit-2.3.zip > toolkit.zip
|
||||
unzip toolkit.zip
|
||||
rm toolkit.zip
|
||||
cp -r .jenkins/configuration/default-environment/unattended_install/* toolkit
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set -x
|
||||
|
||||
# on the root dir
|
||||
composer install
|
||||
# composer install -a # => Not needed anymore (libs were added to git with N°2435)
|
||||
|
||||
|
||||
# under the test dir
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
set -x
|
||||
|
||||
|
||||
|
||||
whoami
|
||||
pwd
|
||||
ls
|
||||
|
||||
@@ -3,6 +3,20 @@ set -x
|
||||
|
||||
cd test
|
||||
|
||||
export DEBUG_UNIT_TEST="0"
|
||||
export DEBUG_UNIT_TEST=0
|
||||
RUN_NONREG_TESTS=0
|
||||
|
||||
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
|
||||
if [ $# -ge 1 -a "x$1" == "xtrue" ]
|
||||
then
|
||||
export DEBUG_UNIT_TEST=1
|
||||
else
|
||||
export DEBUG_UNIT_TEST=0
|
||||
fi
|
||||
|
||||
if [ $# -ge 2 -a "x$2" == "xtrue" ]
|
||||
then
|
||||
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
|
||||
else
|
||||
#echo php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
|
||||
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --exclude-group OQL --teamcity
|
||||
fi
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
|
||||
set -x
|
||||
|
||||
chmod 666 conf/production/config-itop.php
|
||||
|
||||
cd toolkit
|
||||
php unattended_install.php default-params.xml
|
||||
php unattended_install.php --response_file=default-params.xml --clean=true
|
||||
|
||||
@@ -80,7 +80,7 @@ $MySettings = array(
|
||||
|
||||
'db_host' => '',
|
||||
|
||||
'db_name' => 'itop_ci_main',
|
||||
'db_name' => 'itop_ci',
|
||||
|
||||
'db_pwd' => 'IKnowYouSeeMeInJenkinsConf',
|
||||
|
||||
@@ -94,10 +94,6 @@ $MySettings = array(
|
||||
|
||||
'default_language' => 'EN US',
|
||||
|
||||
// disable_attachments_download_legacy_portal: Disable attachments download from legacy portal
|
||||
// default: true
|
||||
'disable_attachments_download_legacy_portal' => true,
|
||||
|
||||
// draft_attachments_lifetime: Lifetime (in seconds) of drafts' attachments and inline images: after this duration, the garbage collector will delete them.
|
||||
// default: 3600
|
||||
'draft_attachments_lifetime' => 3600,
|
||||
@@ -251,6 +247,9 @@ $MySettings = array(
|
||||
*
|
||||
*/
|
||||
$MyModuleSettings = array(
|
||||
'authent-local' => array (
|
||||
'password_validation.pattern' => '',
|
||||
),
|
||||
'itop-attachments' => array (
|
||||
'allowed_classes' => array (
|
||||
0 => 'Ticket',
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</preinstall>
|
||||
<source_dir>datamodels/2.x/</source_dir>
|
||||
<datamodel_version>2.5.0</datamodel_version>
|
||||
<previous_configuration_file>/var/lib/jenkins/workspace/iTop-CI/unattended_install/default-config-itop.php</previous_configuration_file>
|
||||
<previous_configuration_file>default-config-itop.php</previous_configuration_file>
|
||||
<extensions_dir>extensions</extensions_dir>
|
||||
<target_env>production</target_env>
|
||||
<workspace_dir></workspace_dir>
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
//this scrit will be run under the ./toolkit directory, relatively to the document root
|
||||
|
||||
require_once('../approot.inc.php');
|
||||
|
||||
@@ -11,12 +11,22 @@ Here are some guidelines that will help us integrate your work!
|
||||
You are welcome to create pull requests on any of those subjects:
|
||||
|
||||
* 🐛 `:bug:` bug fix
|
||||
* 🔒 `:lock:` security
|
||||
* 🌐 `:globe_with_meridians:` translation / i18n / l10n
|
||||
|
||||
If you want to implement a **new feature**, please [create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) for review.
|
||||
If you ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the ticket.
|
||||
|
||||
For all **security related subjects**, please see our [security policy](SECURITY.md).
|
||||
|
||||
All **datamodel modification** should be done in an extension. Beware that such change would
|
||||
impact all existing customers, and could prevent them from
|
||||
upgrading!
|
||||
Combodo has a long experience of datamodel changes: they are very disruptive!
|
||||
This is why we avoid them in iTop core, especially the changes on existing objects/fields.
|
||||
If you have an idea you're sure would benefit to all of iTop users, you may
|
||||
[create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) to submit it, but be warned that there are lots of good
|
||||
reasons to refuse such changes.
|
||||
|
||||
### License
|
||||
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file),
|
||||
your code must comply with this license.
|
||||
@@ -31,7 +41,7 @@ If you want to use another license, you may [create an extension][wiki new ext].
|
||||
|
||||
TL;DR:
|
||||
> **create a fork from iTop main repository,
|
||||
> create a branch based on either release branch if present, or develop otherwise**
|
||||
> create a branch based on the develop branch**
|
||||
|
||||
We are using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. That means we have in our repo those
|
||||
main branches:
|
||||
@@ -39,23 +49,33 @@ main branches:
|
||||
- develop: ongoing development version
|
||||
- release/\*: if present, that means we are working on a beta version
|
||||
- master: previous stable version
|
||||
- support/\*: maintenance branches for older versions
|
||||
|
||||
For example, if no beta version is currently ongoing we could have:
|
||||
|
||||
- develop containing future 2.8.0 version
|
||||
- master containing 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
|
||||
In this example, when 2.8.0-beta is shipped that will become:
|
||||
|
||||
- develop: future 2.9.0 version
|
||||
- release/2.8: 2.8.0-beta
|
||||
- master: 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
|
||||
And when 2.8.0 final will be out:
|
||||
|
||||
- develop: future 2.9.0 version
|
||||
- master: 2.8.x maintenance version
|
||||
- support/2.7 : 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
|
||||
Most of the time you should based your developments on the develop branch.
|
||||
That may be different if you want to fix a bug, please use develop anyway and ask in your PR if rebase is possible.
|
||||
|
||||
|
||||
## Coding
|
||||
@@ -80,7 +100,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)). For example :
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
|
||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||
Emoji examples :
|
||||
* 🌐 `:globe_with_meridians:` for translations
|
||||
* 🎨 `:art:` when improving the format/structure of the code
|
||||
* ⚡️ `:zap:` when improving performance
|
||||
@@ -92,7 +114,8 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* ⬆️ `:arrow_up:` when upgrading dependencies
|
||||
* ⬇️ `:arrow_down:` when downgrading dependencies
|
||||
* ♻️ `:recycle:` code refactoring
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
* 💄 `:lipstick:` Updating the UI and style files.
|
||||
|
||||
|
||||
## Pull request
|
||||
|
||||
|
||||
6
Jenkinsfile
vendored
6
Jenkinsfile
vendored
@@ -1,5 +1,9 @@
|
||||
pipeline {
|
||||
agent any
|
||||
parameters {
|
||||
booleanParam(name: 'debugMode', defaultValue: 'false', description: 'Debug mode?')
|
||||
booleanParam(name: 'runNonRegOQLTests', defaultValue: 'false', description: 'Do You want to run legacy OQL regression tests?')
|
||||
}
|
||||
stages {
|
||||
|
||||
stage('init') {
|
||||
@@ -36,7 +40,7 @@ pipeline {
|
||||
parallel {
|
||||
stage('phpunit') {
|
||||
steps {
|
||||
sh './.jenkins/bin/tests/phpunit.sh'
|
||||
sh './.jenkins/bin/tests/phpunit.sh ${debugMode} ${runNonRegOQLTests}'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
108
README.md
108
README.md
@@ -23,43 +23,86 @@ iTop also offers mass import tools and web services to integrate with your IT
|
||||
|
||||
## Resources
|
||||
|
||||
- [iTop Forums][1]: for support request
|
||||
- [iTop Forums][1]: community support
|
||||
- [iTop Tickets][2]: for feature requests and bug reports
|
||||
- [Releases download][3]
|
||||
- [iTop documentation][4] for iTop and official extensions
|
||||
- [iTop extensions][5] for discovering and installing extensions
|
||||
- [Documentation][4] covering both iTop and its official extensions
|
||||
- [iTop Hub][5] : discover and install extensions !
|
||||
|
||||
|
||||
## Releases
|
||||
### Version 2.6
|
||||
|
||||
|
||||
[1]: https://sourceforge.net/p/itop/discussion/
|
||||
[2]: https://sourceforge.net/p/itop/tickets/
|
||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||
[4]: https://www.itophub.io/wiki
|
||||
[5]: https://store.itophub.io/en_US/
|
||||
|
||||
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
|
||||
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
|
||||
[12]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#service_management
|
||||
[13]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#change_management
|
||||
[14]: https://www.itophub.io/wiki/page?id=latest%3Aimplementation%3Astart#service_level_agreements_and_targets
|
||||
[15]: https://www.itophub.io/wiki/page?id=latest%3Auser%3Aactions#relations
|
||||
[16]: https://www.itophub.io/wiki/page?id=latest%3Auser%3Abulk_modify#uploading_data
|
||||
[17]: https://www.itophub.io/wiki/page?id=latest%3Aadmin%3Aaudit
|
||||
[18]: https://www.itophub.io/wiki/page?id=latest%3Aadvancedtopics%3Adata_synchro_overview
|
||||
|
||||
|
||||
|
||||
## Last releases
|
||||
|
||||
### Versions 2.6.*
|
||||
- 2.6.0 published on January 9, 2019
|
||||
- [Changes since the previous version][58]
|
||||
- [New features][59]
|
||||
- [Migration notes][60]
|
||||
- [Download iTop 2.6.0][61]
|
||||
- [Download iTop 2.6.1][61]
|
||||
|
||||
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
|
||||
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
|
||||
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
|
||||
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.1
|
||||
|
||||
|
||||
### Version 2.5
|
||||
### Versions 2.5.*
|
||||
- 2.5.0 published on July 11, 2018
|
||||
- [Changes since the previous version][54]
|
||||
- [New features][55]
|
||||
- [Migration notes][56]
|
||||
- [Download iTop 2.5.1][57]
|
||||
|
||||
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
|
||||
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
|
||||
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
|
||||
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
|
||||
|
||||
|
||||
### Version 2.4
|
||||
### Versions 2.4.*
|
||||
- 2.4.0 published on November 16, 2017
|
||||
- [Changes since the previous version][50]
|
||||
- [New features][51]
|
||||
- [Migration notes][52]
|
||||
- [Download iTop 2.4.1][53]
|
||||
|
||||
[50]: https://www.itophub.io/wiki/page?id=2_4_0:release:change_log
|
||||
[51]: https://www.itophub.io/wiki/page?id=2_4_0:release:2_4_whats_new
|
||||
[52]: https://www.itophub.io/wiki/page?id=2_4_0:install:230_to_240_migration_notes
|
||||
[53]: https://sourceforge.net/projects/itop/files/itop/2.4.1
|
||||
|
||||
# About Us
|
||||
|
||||
|
||||
## About Us
|
||||
|
||||
iTop development is sponsored, led and supported by [Combodo][0].
|
||||
|
||||
[0]: https://www.combodo.com
|
||||
|
||||
# Contributors
|
||||
|
||||
## Contributors
|
||||
|
||||
We would like to give a special thank you to the people from the community who contributed to this project, including:
|
||||
|
||||
### Names
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Bilger, Jean-François
|
||||
@@ -74,6 +117,7 @@ We would like to give a special thank you to the people from the community who c
|
||||
- Gumble, David
|
||||
- Hippler, Lars
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
@@ -85,7 +129,7 @@ We would like to give a special thank you to the people from the community who c
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
|
||||
#### Aliases
|
||||
### Aliases
|
||||
- chifu1234
|
||||
- cprobst
|
||||
- Karkoff1212
|
||||
@@ -96,45 +140,7 @@ We would like to give a special thank you to the people from the community who c
|
||||
- theBigOne
|
||||
- ulmerspatz
|
||||
|
||||
#### Companies
|
||||
### Companies
|
||||
- Hardis
|
||||
- ITOMIG
|
||||
|
||||
|
||||
|
||||
[0]: https://www.combodo.com
|
||||
|
||||
[1]: https://sourceforge.net/p/itop/discussion/
|
||||
[2]: https://sourceforge.net/p/itop/tickets/
|
||||
[3]: https://sourceforge.net/projects/itop/files/itop/
|
||||
[4]: https://www.itophub.io/wiki
|
||||
[5]: https://store.itophub.io/en_US/
|
||||
|
||||
|
||||
|
||||
[10]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#configuration_management_cmdb
|
||||
[11]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#ticketing
|
||||
[12]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#service_management
|
||||
[13]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#change_management
|
||||
[14]: https://www.itophub.io/wiki/page?id=2_5_0%3Aimplementation%3Astart#service_level_agreements_and_targets
|
||||
[15]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Aactions#relations
|
||||
[16]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Abulk_modify#uploading_data
|
||||
[17]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Aaudit
|
||||
[18]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadvancedtopics%3Adata_synchro_overview
|
||||
|
||||
|
||||
|
||||
[50]: https://www.itophub.io/wiki/page?id=2_4_0:release:change_log
|
||||
[51]: https://www.itophub.io/wiki/page?id=2_4_0:release:2_4_whats_new
|
||||
[52]: https://www.itophub.io/wiki/page?id=2_4_0:install:230_to_240_migration_notes
|
||||
[53]: https://sourceforge.net/projects/itop/files/itop/2.4.1
|
||||
|
||||
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
|
||||
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
|
||||
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
|
||||
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
|
||||
|
||||
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
|
||||
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
|
||||
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
|
||||
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.0
|
||||
|
||||
36
SECURITY.md
Normal file
36
SECURITY.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# 🔒 Reporting vulnerabilities
|
||||
|
||||
We take all security bugs seriously. Thank you for improving the security of iTop! We appreciate your efforts and
|
||||
responsible disclosure and will make every effort to acknowledge your contributions.
|
||||
|
||||
|
||||
## ✉️ How to report
|
||||
|
||||
### iTop vulnerabilities
|
||||
Please send a procedure to reproduce iTop vulnerabilities to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
||||
|
||||
You can send us a standard "given / then / when" report, including iTop version, impacts, and maybe installed modules or data if they are
|
||||
needed to reproduce.
|
||||
|
||||
### Dependencies vulnerabilities
|
||||
Report security bugs in third-party modules to the person or team maintaining the module, and notify us of this report by sending an email
|
||||
to [itop-security@combodo.com](mailto:itop-security@combodo.com).
|
||||
|
||||
|
||||
|
||||
## 📆 Disclosure Policy
|
||||
|
||||
Report sent to us will be acknowledged within the week.
|
||||
|
||||
Then, a Combodo developer will be assigned to the reported issue and will:
|
||||
|
||||
* confirm the problem and determine the affected iTop versions
|
||||
* audit the code to search any potential similar problems
|
||||
* try to find a workaround if any
|
||||
* create fixes for all releases still under maintenance
|
||||
* send you the commit(s) for review
|
||||
* send you the next version(s) that will contain the fix, and the estimated release dates
|
||||
|
||||
Security issues always take precedence over bug fixes and feature work.
|
||||
|
||||
The assignee will keep you informed of the resolution progress, and may ask you for additional information or guidance.
|
||||
@@ -121,20 +121,15 @@ class UserRightsMatrix extends UserRightsAddOnAPI
|
||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||
{
|
||||
// Maybe we should check that no other user with userid == 0 exists
|
||||
CMDBObject::SetTrackInfo('Initialization');
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', $sAdminUser);
|
||||
$oUser->Set('password', $sAdminPwd);
|
||||
$oUser->Set('contactid', 1); // one is for root !
|
||||
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
||||
|
||||
// Create a change to record the history of the User object
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$oChange->Set("userinfo", "Initialization");
|
||||
$iChangeId = $oChange->DBInsert();
|
||||
|
||||
// Now record the admin user object
|
||||
$iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
$this->SetupUser($iUserId, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -437,8 +437,6 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
CMDBObject::SetTrackInfo('Initialization');
|
||||
|
||||
$oChange = CMDBObject::GetCurrentChange();
|
||||
|
||||
$iContactId = 0;
|
||||
// Support drastic data model changes: no organization class (or not writable)!
|
||||
if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization'))
|
||||
@@ -446,7 +444,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oOrg = new Organization();
|
||||
$oOrg->Set('name', 'My Company/Department');
|
||||
$oOrg->Set('code', 'SOMECODE');
|
||||
$iOrgId = $oOrg->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$iOrgId = $oOrg->DBInsertNoReload();
|
||||
|
||||
// Support drastic data model changes: no Person class (or not writable)!
|
||||
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person'))
|
||||
@@ -463,7 +461,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oContact->Set('phone', '+00 000 000 000');
|
||||
}
|
||||
$oContact->Set('email', 'my.email@foo.org');
|
||||
$iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$iContactId = $oContact->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,14 +480,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
if (is_object($oAdminProfile))
|
||||
{
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
//$oUserProfile->Set('userid', $iUserId);
|
||||
$oUserProfile->Set('profileid', $oAdminProfile->GetKey());
|
||||
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
||||
//$oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oSet = DBObjectSet::FromObject($oUserProfile);
|
||||
$oUser->Set('profile_list', $oSet);
|
||||
}
|
||||
$iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -533,10 +533,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
|
||||
{
|
||||
// Create a change to record the history of the User object
|
||||
/** @var \CMDBChange $oChange */
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$oChange->Set("userinfo", "Initialization");
|
||||
$iChangeId = $oChange->DBInsert();
|
||||
|
||||
$iContactId = 0;
|
||||
// Support drastic data model changes: no organization class (or not writable)!
|
||||
@@ -545,7 +545,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oOrg = new Organization();
|
||||
$oOrg->Set('name', 'My Company/Department');
|
||||
$oOrg->Set('code', 'SOMECODE');
|
||||
$iOrgId = $oOrg->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oOrg::SetCurrentChange($oChange);
|
||||
$iOrgId = $oOrg->DBInsertNoReload();
|
||||
|
||||
// Support drastic data model changes: no Person class (or not writable)!
|
||||
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person'))
|
||||
@@ -562,7 +563,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oContact->Set('phone', '+00 000 000 000');
|
||||
}
|
||||
$oContact->Set('email', 'my.email@foo.org');
|
||||
$iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oContact::SetCurrentChange($oChange);
|
||||
$iContactId = $oContact->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,14 +583,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
if (is_object($oAdminProfile))
|
||||
{
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
//$oUserProfile->Set('userid', $iUserId);
|
||||
$oUserProfile->Set('profileid', $oAdminProfile->GetKey());
|
||||
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
||||
//$oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oSet = DBObjectSet::FromObject($oUserProfile);
|
||||
$oUser->Set('profile_list', $oSet);
|
||||
}
|
||||
$iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oUser::SetCurrentChange($oChange);
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -593,25 +593,12 @@ class UserRightsProjection extends UserRightsAddOnAPI
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$oChange->Set("userinfo", "Initialization");
|
||||
$iChangeId = $oChange->DBInsert();
|
||||
|
||||
$oOrg = new Organization();
|
||||
$oOrg->Set('name', 'My Company/Department');
|
||||
$oOrg->Set('code', 'SOMECODE');
|
||||
// $oOrg->Set('status', 'implementation');
|
||||
//$oOrg->Set('parent_id', xxx);
|
||||
$iOrgId = $oOrg->DBInsertTrackedNoReload($oChange, true /* skip strong security */);
|
||||
|
||||
// Location : optional
|
||||
//$oLocation = new bizLocation();
|
||||
//$oLocation->Set('name', 'MyOffice');
|
||||
//$oLocation->Set('status', 'implementation');
|
||||
//$oLocation->Set('org_id', $iOrgId);
|
||||
//$oLocation->Set('severity', 'high');
|
||||
//$oLocation->Set('address', 'my building in my city');
|
||||
//$oLocation->Set('country', 'my country');
|
||||
//$oLocation->Set('parent_location_id', xxx);
|
||||
//$iLocationId = $oLocation->DBInsertNoReload();
|
||||
$oOrg::SetCurrentChange($oChange);
|
||||
$iOrgId = $oOrg->DBInsertNoReload();
|
||||
|
||||
$oContact = new Person();
|
||||
$oContact->Set('name', 'My last name');
|
||||
@@ -619,24 +606,24 @@ class UserRightsProjection extends UserRightsAddOnAPI
|
||||
//$oContact->Set('status', 'available');
|
||||
$oContact->Set('org_id', $iOrgId);
|
||||
$oContact->Set('email', 'my.email@foo.org');
|
||||
//$oContact->Set('phone', '');
|
||||
//$oContact->Set('location_id', $iLocationId);
|
||||
//$oContact->Set('employee_number', '');
|
||||
$iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oContact::SetCurrentChange($oChange);
|
||||
$iContactId = $oContact->DBInsertNoReload();
|
||||
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', $sAdminUser);
|
||||
$oUser->Set('password', $sAdminPwd);
|
||||
$oUser->Set('contactid', $iContactId);
|
||||
$oUser->Set('language', $sLanguage); // Language was chosen during the installation
|
||||
$iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oUser::SetCurrentChange($oChange);
|
||||
$iUserId = $oUser->DBInsertNoReload();
|
||||
|
||||
// Add this user to the very specific 'admin' profile
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oUserProfile->Set('userid', $iUserId);
|
||||
$oUserProfile->Set('profileid', ADMIN_PROFILE_ID);
|
||||
$oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
|
||||
$oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||
$oUserProfile::SetCurrentChange($oChange);
|
||||
$oUserProfile->DBInsertNoReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class ajax_page extends WebPage implements iTabbedPage
|
||||
{
|
||||
/**
|
||||
* Jquery style ready script
|
||||
* @var Hash
|
||||
* @var array
|
||||
*/
|
||||
protected $m_sReadyScript;
|
||||
protected $m_oTabs;
|
||||
@@ -214,8 +214,11 @@ PrepareWidgets();
|
||||
EOF
|
||||
);
|
||||
}
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
$this->outputCollapsibleSectionInit();
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
{
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
echo self::FilterXSS($this->s_content);
|
||||
@@ -285,10 +288,16 @@ EOF
|
||||
echo self::FilterXSS($s_captured_output);
|
||||
}
|
||||
|
||||
$oKPI->ComputeAndReport('Echoing');
|
||||
|
||||
if (class_exists('DBSearch'))
|
||||
{
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI'))
|
||||
{
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ class CSVPage extends WebPage
|
||||
function __construct($s_title)
|
||||
{
|
||||
parent::__construct($s_title);
|
||||
$this->add_header("Content-type: text/plain; charset=utf-8");
|
||||
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header("Cache-control: no-cache");
|
||||
//$this->add_header("Content-Transfer-Encoding: binary");
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2017 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/>
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||
@@ -24,21 +25,33 @@ require_once(APPROOT.'core/modelreflection.class.inc.php');
|
||||
*
|
||||
* A user editable dashboard page
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
abstract class Dashboard
|
||||
{
|
||||
/** @var string $sTitle*/
|
||||
protected $sTitle;
|
||||
/** @var bool $bAutoReload */
|
||||
protected $bAutoReload;
|
||||
/** @var float|int $iAutoReloadSec */
|
||||
protected $iAutoReloadSec;
|
||||
/** @var string $sLayoutClass */
|
||||
protected $sLayoutClass;
|
||||
/** @var array $aWidgetsData */
|
||||
protected $aWidgetsData;
|
||||
/** @var \DOMNode|null $oDOMNode */
|
||||
protected $oDOMNode;
|
||||
/** @var string $sId */
|
||||
protected $sId;
|
||||
/** @var array $aCells */
|
||||
protected $aCells;
|
||||
/** @var \ModelReflection $oMetaModel */
|
||||
protected $oMetaModel;
|
||||
|
||||
|
||||
/**
|
||||
* Dashboard constructor.
|
||||
*
|
||||
* @param string $sId
|
||||
*/
|
||||
public function __construct($sId)
|
||||
{
|
||||
$this->sTitle = '';
|
||||
@@ -51,7 +64,7 @@ abstract class Dashboard
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sXml
|
||||
* @param string $sXml
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -64,7 +77,10 @@ abstract class Dashboard
|
||||
restore_error_handler();
|
||||
$this->FromDOMDocument($oDoc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \DOMDocument $oDoc
|
||||
*/
|
||||
public function FromDOMDocument(DOMDocument $oDoc)
|
||||
{
|
||||
$this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
|
||||
@@ -160,9 +176,16 @@ abstract class Dashboard
|
||||
protected function InitDashletFromDOMNode($oDomNode)
|
||||
{
|
||||
$sId = $oDomNode->getAttribute('id');
|
||||
// To avoid collision with other dashlets with the same ID we suffix it. Collisions typically happen with extensions.
|
||||
// Note: The check is done so we don't append it at each save of the dashboard.
|
||||
if(strpos($sId, 'uniqid_') === false)
|
||||
{
|
||||
$sId .= '_uniqid_' . uniqid();
|
||||
}
|
||||
|
||||
$sDashletType = $oDomNode->getAttribute('xsi:type');
|
||||
|
||||
// Test if dashlet can be instanciated, otherwise (uninstalled, broken, ...) we display a placeholder
|
||||
// Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
|
||||
$sClass = static::GetDashletClassFromType($sDashletType);
|
||||
/** @var \Dashlet $oNewDashlet */
|
||||
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
|
||||
@@ -172,7 +195,13 @@ abstract class Dashboard
|
||||
return $oNewDashlet;
|
||||
}
|
||||
|
||||
static function SortOnRank($aItem1, $aItem2)
|
||||
/**
|
||||
* @param array $aItem1
|
||||
* @param array $aItem2
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function SortOnRank($aItem1, $aItem2)
|
||||
{
|
||||
return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
|
||||
}
|
||||
@@ -200,6 +229,10 @@ abstract class Dashboard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function ToXml()
|
||||
{
|
||||
$oDoc = new DOMDocument();
|
||||
@@ -268,7 +301,9 @@ abstract class Dashboard
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $aParams
|
||||
*/
|
||||
public function FromParams($aParams)
|
||||
{
|
||||
$this->sLayoutClass = $aParams['layout_class'];
|
||||
@@ -305,42 +340,66 @@ abstract class Dashboard
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetLayout()
|
||||
{
|
||||
return $this->sLayoutClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $sLayoutClass
|
||||
*/
|
||||
public function SetLayout($sLayoutClass)
|
||||
{
|
||||
$this->sLayoutClass = $sLayoutClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetTitle()
|
||||
{
|
||||
return $this->sTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTitle
|
||||
*/
|
||||
public function SetTitle($sTitle)
|
||||
{
|
||||
$this->sTitle = $sTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function GetAutoReload()
|
||||
{
|
||||
return $this->bAutoReload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAutoReload
|
||||
*/
|
||||
public function SetAutoReload($bAutoReload)
|
||||
{
|
||||
$this->bAutoReload = $bAutoReload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public function GetAutoReloadInterval()
|
||||
{
|
||||
return $this->iAutoReloadSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $iAutoReloadSec
|
||||
*/
|
||||
public function SetAutoReloadInterval($iAutoReloadSec)
|
||||
{
|
||||
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec);
|
||||
@@ -356,12 +415,13 @@ abstract class Dashboard
|
||||
$this->aCells[] = array($oDashlet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage *
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
/**
|
||||
* @param \WebPage $oPage *
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function RenderProperties($oPage, $aExtraParams = array())
|
||||
{
|
||||
// menu to pick a layout and edit other properties of the dashboard
|
||||
@@ -449,7 +509,7 @@ EOF
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param \WebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams
|
||||
* @param bool $bCanEdit
|
||||
@@ -468,6 +528,12 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function RenderDashletsSelection(WebPage $oPage)
|
||||
{
|
||||
// Toolbox/palette to drag and drop dashlets
|
||||
@@ -485,7 +551,11 @@ EOF
|
||||
$oPage->add('</div>');
|
||||
$oPage->add_ready_script("$('.dashlet_icon').draggable({helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param array $aExtraParams
|
||||
*/
|
||||
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
// Toolbox/palette to edit the properties of each dashlet
|
||||
@@ -545,7 +615,10 @@ EOF
|
||||
|
||||
return $aDashlets;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int|mixed
|
||||
*/
|
||||
protected function GetNewDashletId()
|
||||
{
|
||||
$iNewId = 0;
|
||||
@@ -561,13 +634,19 @@ EOF
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oForm
|
||||
* @param \DesignerForm $oForm
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function SetFormParams($oForm, $aExtraParams = array());
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
* @param \ModelFactory|null $oFactory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function GetDashletClassFromType($sType, $oFactory = null)
|
||||
{
|
||||
if (is_subclass_of($sType, 'Dashlet'))
|
||||
@@ -586,37 +665,49 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class RuntimeDashboard
|
||||
*/
|
||||
class RuntimeDashboard extends Dashboard
|
||||
{
|
||||
/** @var bool $bCustomized */
|
||||
protected $bCustomized;
|
||||
/** @var string $sDefinitionFile */
|
||||
private $sDefinitionFile = '';
|
||||
/** @var null $sReloadURL */
|
||||
private $sReloadURL = null;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct($sId)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
$this->bCustomized = false;
|
||||
$this->oMetaModel = new ModelReflectionRuntime();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $bCustomized
|
||||
*/
|
||||
public function SetCustomFlag($bCustomized)
|
||||
{
|
||||
$this->bCustomized = $bCustomized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DesignerForm $oForm
|
||||
*
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function SetFormParams($oForm, $aExtraParams = array())
|
||||
{
|
||||
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property', 'extra_params' => $aExtraParams));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Save()
|
||||
{
|
||||
$sXml = $this->ToXml();
|
||||
@@ -632,7 +723,7 @@ class RuntimeDashboard extends Dashboard
|
||||
}
|
||||
else
|
||||
{
|
||||
// No such customized dasboard for the current user, let's create a new record
|
||||
// No such customized dashboard for the current user, let's create a new record
|
||||
$oUserDashboard = new UserDashboard();
|
||||
$oUserDashboard->Set('user_id', UserRights::GetUserId());
|
||||
$oUserDashboard->Set('menu_code', $this->sId);
|
||||
@@ -642,7 +733,18 @@ class RuntimeDashboard extends Dashboard
|
||||
$oUserDashboard->DBWrite();
|
||||
utils::PopArchiveMode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DeleteException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function Revert()
|
||||
{
|
||||
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||
@@ -669,6 +771,7 @@ class RuntimeDashboard extends Dashboard
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function GetDashboard($sDashboardFile, $sDashBoardId)
|
||||
{
|
||||
@@ -713,10 +816,7 @@ class RuntimeDashboard extends Dashboard
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams (class and id of the current object
|
||||
*
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
|
||||
@@ -851,6 +951,9 @@ EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function HasCustomDashboard()
|
||||
{
|
||||
try
|
||||
@@ -879,7 +982,7 @@ EOF
|
||||
{
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
||||
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
|
||||
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><i class=\"top-right-icon icon-additional-arrow fas fa-pencil-alt\"></i><ul>";
|
||||
|
||||
$aActions = array();
|
||||
$sFile = addslashes($this->sDefinitionFile);
|
||||
@@ -939,9 +1042,7 @@ EOF
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function RenderProperties($oPage, $aExtraParams = array())
|
||||
{
|
||||
@@ -977,7 +1078,7 @@ EOF
|
||||
|
||||
|
||||
/**
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
@@ -1117,7 +1218,14 @@ EOF
|
||||
);
|
||||
$oPage->add_ready_script("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string|null $sOQL
|
||||
*
|
||||
* @return \DesignerForm
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function GetDashletCreationForm($sOQL = null)
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
@@ -1228,6 +1336,9 @@ EOF
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $sOQL
|
||||
*
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function GetDashletCreationDlgFromOQL($oPage, $sOQL)
|
||||
{
|
||||
@@ -1292,13 +1403,19 @@ EOF
|
||||
$this->sDefinitionFile = $sDefinitionFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function GetReloadURL()
|
||||
{
|
||||
return $this->sReloadURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sReloadURL
|
||||
*/
|
||||
public function SetReloadURL($sReloadURL)
|
||||
{
|
||||
$this->sReloadURL = $sReloadURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +444,18 @@ EOF
|
||||
$sClass = $oQuery->GetClass();
|
||||
foreach($this->oModelReflection->ListAttributes($sClass) as $sAttCode => $sAttType)
|
||||
{
|
||||
// For external fields, find the real type of the target
|
||||
$sExtFieldAttCode = $sAttCode;
|
||||
$sTargetClass = $sClass;
|
||||
while (is_a($sAttType, 'AttributeExternalField', true))
|
||||
{
|
||||
$sExtKeyAttCode = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtFieldAttCode, 'extkey_attcode');
|
||||
$sTargetAttCode = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtFieldAttCode, 'target_attcode');
|
||||
$sTargetClass = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtKeyAttCode, 'targetclass');
|
||||
$aTargetAttCodes = $this->oModelReflection->ListAttributes($sTargetClass);
|
||||
$sAttType = $aTargetAttCodes[$sTargetAttCode];
|
||||
$sExtFieldAttCode = $sTargetAttCode;
|
||||
}
|
||||
if (is_a($sAttType, 'AttributeLinkedSet', true))
|
||||
{
|
||||
continue;
|
||||
@@ -456,15 +468,6 @@ EOF
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// For external fields, find the real type of the target
|
||||
while (is_a($sAttType, 'AttributeExternalField', true))
|
||||
{
|
||||
$sExtKeyAttCode = $this->oModelReflection->GetAttributeProperty($sClass, $sAttCode, 'extkey_attcode');
|
||||
$sTargetClass = $this->oModelReflection->GetAttributeProperty($sClass, $sExtKeyAttCode, 'targetclass');
|
||||
$sTargetAttCode = $this->oModelReflection->GetAttributeProperty($sClass, $sAttCode, 'target_attcode');
|
||||
$aTargetAttCodes = $this->oModelReflection->ListAttributes($sTargetClass);
|
||||
$sAttType = $aTargetAttCodes[$sTargetAttCode];
|
||||
}
|
||||
|
||||
$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
|
||||
if (!in_array($sLabel, $aGroupBy))
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
|
||||
<portals>
|
||||
<portal id="legacy_portal" _delta="define">
|
||||
<url>portal/index.php</url>
|
||||
<rank>1.0</rank>
|
||||
<handler/>
|
||||
<allow>
|
||||
</allow>
|
||||
<deny/>
|
||||
</portal>
|
||||
<portal id="backoffice" _delta="define">
|
||||
<url>pages/UI.php</url>
|
||||
<rank>2.0</rank>
|
||||
@@ -23,5 +15,10 @@
|
||||
<menu id="AdminTools" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>80</rank>
|
||||
</menu>
|
||||
<menu id="System" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>100</rank>
|
||||
<enable_class>ResourceSystemMenu</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2017 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/>
|
||||
/**
|
||||
* Data Table to display a set of objects in a tabular manner in HTML
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2017 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
|
||||
*/
|
||||
|
||||
class DataTable
|
||||
@@ -36,8 +31,13 @@ class DataTable
|
||||
/**
|
||||
* @param $iListId mixed Unique ID for this div/table in the page
|
||||
* @param $oSet DBObjectSet The set of data to display
|
||||
* @param $aClassAliases Hash The list of classes/aliases to be displayed in this set $sAlias => $sClassName
|
||||
* @param $aClassAliases array The list of classes/aliases to be displayed in this set $sAlias => $sClassName
|
||||
* @param $sTableId mixed A string (or null) identifying this table in order to persist its settings
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
|
||||
{
|
||||
@@ -50,7 +50,19 @@ class DataTable
|
||||
$this->oDefaultSettings = null;
|
||||
$this->bShowObsoleteData = $oSet->GetShowObsoleteData();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param \DataTableSettings $oSettings
|
||||
* @param $bActionsMenu
|
||||
* @param $sSelectMode
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function Display(WebPage $oPage, DataTableSettings $oSettings, $bActionsMenu, $sSelectMode, $bViewLink, $aExtraParams)
|
||||
{
|
||||
$this->oDefaultSettings = $oSettings;
|
||||
@@ -119,7 +131,23 @@ class DataTable
|
||||
|
||||
return $this->GetAsHTML($oPage, $oCustomSettings->iDefaultPageSize, $oCustomSettings->iDefaultPageSize, 0, $oCustomSettings->aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $iPageSize
|
||||
* @param $iDefaultPageSize
|
||||
* @param $iPageIndex
|
||||
* @param $aColumns
|
||||
* @param $bActionsMenu
|
||||
* @param $bToolkitMenu
|
||||
* @param $sSelectMode
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetAsHTML(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex, $aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams)
|
||||
{
|
||||
$sObjectsCount = $this->GetObjectCount($oPage, $sSelectMode);
|
||||
@@ -184,6 +212,10 @@ class DataTable
|
||||
*/
|
||||
public function GetAsHTMLTableRows(WebPage $oPage, $iPageSize, $aColumns, $sSelectMode, $bViewLink, $aExtraParams)
|
||||
{
|
||||
if ($iPageSize < 1)
|
||||
{
|
||||
$iPageSize = -1; // convention: no pagination
|
||||
}
|
||||
$aAttribs = $this->GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink);
|
||||
$aValues = $this->GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||
|
||||
@@ -194,7 +226,13 @@ class DataTable
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $sSelectMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetObjectCount(WebPage $oPage, $sSelectMode)
|
||||
{
|
||||
if (($sSelectMode == 'single') || ($sSelectMode == 'multiple'))
|
||||
@@ -207,6 +245,15 @@ class DataTable
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $iPageSize
|
||||
* @param $iDefaultPageSize
|
||||
* @param $iPageIndex
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetPager(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex)
|
||||
{
|
||||
$sHtml = '';
|
||||
@@ -222,14 +269,21 @@ class DataTable
|
||||
}
|
||||
|
||||
$sCombo = '<select class="pagesize">';
|
||||
for($iPage = 1; $iPage < 5; $iPage++)
|
||||
if($iPageSize < 1)
|
||||
{
|
||||
$iNbItems = $iPage * $iDefaultPageSize;
|
||||
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
|
||||
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
|
||||
$sCombo .= "<option selected=\"selected\" value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
|
||||
}
|
||||
$sSelected = ($iPageSize < 1) ? 'selected="selected"' : '';
|
||||
$sCombo .= "<option $sSelected value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
|
||||
else
|
||||
{
|
||||
for($iPage = 1; $iPage < 5; $iPage++)
|
||||
{
|
||||
$iNbItems = $iPage * $iDefaultPageSize;
|
||||
$sSelected = ($iNbItems == $iPageSize) ? 'selected="selected"' : '';
|
||||
$sCombo .= "<option $sSelected value=\"$iNbItems\">$iNbItems</option>";
|
||||
}
|
||||
$sCombo .= "<option value=\"-1\">".Dict::S('UI:Pagination:All')."</option>";
|
||||
}
|
||||
|
||||
$sCombo .= '</select>';
|
||||
|
||||
$sPages = Dict::S('UI:Pagination:PagesLabel');
|
||||
@@ -284,7 +338,17 @@ class DataTable
|
||||
EOF;
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
protected function GetActionsMenu(WebPage $oPage, $aExtraParams)
|
||||
{
|
||||
$oMenuBlock = new MenuBlock($this->oSet->GetFilter(), 'list');
|
||||
@@ -292,13 +356,20 @@ EOF;
|
||||
$sHtml = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $this->iListId);
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GetToolkitMenu(WebPage $oPage, $aExtraParams)
|
||||
{
|
||||
if (!$oPage->IsPrintableVersion())
|
||||
{
|
||||
$sMenuTitle = Dict::S('UI:ConfigureThisList');
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li><img src="../images/toolkit_menu.png?t='.utils::GetCacheBusterTimestamp().'"><ul>';
|
||||
$sHtml = '<div class="itop_popup toolkit_menu" id="tk_'.$this->iListId.'"><ul><li><i class="fas fa-tools"></i><i class="fas fa-caret-down"></i><ul>';
|
||||
|
||||
$oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');");
|
||||
$aActions = array(
|
||||
@@ -315,7 +386,15 @@ EOF;
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $aColumns
|
||||
* @param $bViewLink
|
||||
* @param $iDefaultPageSize
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetTableConfigDlg(WebPage $oPage, $aColumns, $bViewLink, $iDefaultPageSize)
|
||||
{
|
||||
$sHtml = "<div id=\"datatable_dlg_{$this->iListId}\" style=\"display: none;\">";
|
||||
@@ -351,13 +430,27 @@ EOF;
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $oSetting
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetAsHash($oSetting)
|
||||
{
|
||||
$aSettings = array('iDefaultPageSize' => $oSetting->iDefaultPageSize, 'oColumns' => $oSetting->aColumns);
|
||||
return $aSettings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
* @param $bViewLink
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
|
||||
{
|
||||
$aAttribs = array();
|
||||
@@ -390,7 +483,21 @@ EOF;
|
||||
}
|
||||
return $aAttribs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
* @param $iPageSize
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||
{
|
||||
$bLocalize = true;
|
||||
@@ -431,7 +538,7 @@ EOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRow['form::select'] = "<input type=\"checkBox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
||||
$aRow['form::select'] = "<input type=\"checkbox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
|
||||
}
|
||||
}
|
||||
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||
@@ -473,7 +580,24 @@ EOF;
|
||||
}
|
||||
return $aValues;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
* @param $iPageSize
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||
{
|
||||
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
||||
@@ -565,7 +689,7 @@ EOF;
|
||||
<<<EOF
|
||||
var oTable = $('#{$this->iListId} table.listResults');
|
||||
oTable.tableHover();
|
||||
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
|
||||
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, table_id: '{$this->iListId}', columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
|
||||
EOF
|
||||
);
|
||||
if ($sFakeSortList != '')
|
||||
@@ -574,11 +698,16 @@ EOF
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $iDefaultPageSize
|
||||
* @param $iStart
|
||||
*/
|
||||
public function UpdatePager(WebPage $oPage, $iDefaultPageSize, $iStart)
|
||||
{
|
||||
$iPageSize = ($iDefaultPageSize < 1) ? 1 : $iDefaultPageSize;
|
||||
$iPageIndex = 1 + floor($iStart / $iPageSize);
|
||||
$iPageSize = $iDefaultPageSize;
|
||||
$iPageIndex = 0;
|
||||
$sHtml = $this->GetPager($oPage, $iPageSize, $iDefaultPageSize, $iPageIndex);
|
||||
$oPage->add_ready_script("$('#pager{$this->iListId}').html('".json_encode($sHtml)."');");
|
||||
if ($iDefaultPageSize < 1)
|
||||
@@ -598,11 +727,48 @@ EOF
|
||||
*/
|
||||
class PrintableDataTable extends DataTable
|
||||
{
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $iPageSize
|
||||
* @param $iDefaultPageSize
|
||||
* @param $iPageIndex
|
||||
* @param $aColumns
|
||||
* @param $bActionsMenu
|
||||
* @param $bToolkitMenu
|
||||
* @param $sSelectMode
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function GetAsHTML(WebPage $oPage, $iPageSize, $iDefaultPageSize, $iPageIndex, $aColumns, $bActionsMenu, $bToolkitMenu, $sSelectMode, $bViewLink, $aExtraParams)
|
||||
{
|
||||
return $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, -1, $bViewLink, $aExtraParams);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
* @param $iPageSize
|
||||
* @param $bViewLink
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function GetHTMLTable(WebPage $oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
|
||||
{
|
||||
$iNbPages = ($iPageSize < 1) ? 1 : ceil($this->iNbObjects / $iPageSize);
|
||||
@@ -627,7 +793,13 @@ class DataTableSettings implements Serializable
|
||||
public $iDefaultPageSize;
|
||||
public $aColumns;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DataTableSettings constructor.
|
||||
*
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
*/
|
||||
public function __construct($aClassAliases, $sTableId = null)
|
||||
{
|
||||
$this->aClassAliases = $aClassAliases;
|
||||
@@ -635,14 +807,22 @@ class DataTableSettings implements Serializable
|
||||
$this->iDefaultPageSize = 10;
|
||||
$this->aColumns = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $iDefaultPageSize
|
||||
* @param $aSortOrder
|
||||
* @param $aColumns
|
||||
*/
|
||||
protected function Init($iDefaultPageSize, $aSortOrder, $aColumns)
|
||||
{
|
||||
$this->iDefaultPageSize = $iDefaultPageSize;
|
||||
$this->aColumns = $aColumns;
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
// Save only the 'visible' columns
|
||||
@@ -668,7 +848,12 @@ class DataTableSettings implements Serializable
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $sData
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unserialize($sData)
|
||||
{
|
||||
$aData = unserialize($sData);
|
||||
@@ -701,7 +886,16 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param $bViewLink
|
||||
* @param $aDefaultLists
|
||||
*
|
||||
* @return \DataTableSettings
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
static public function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
|
||||
{
|
||||
$oSettings = new DataTableSettings($aClassAliases);
|
||||
@@ -751,7 +945,10 @@ class DataTableSettings implements Serializable
|
||||
$oSettings->Init($iDefaultPageSize, $aSortOrder, $aColumns);
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function FixVisibleColumns()
|
||||
{
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
@@ -788,7 +985,15 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
* @param bool $bOnlyOnTable
|
||||
*
|
||||
* @return \DataTableSettings|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
static public function GetTableSettings($aClassAliases, $sTableId = null, $bOnlyOnTable = false)
|
||||
{
|
||||
$pref = null;
|
||||
@@ -817,7 +1022,10 @@ class DataTableSettings implements Serializable
|
||||
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetSortOrder()
|
||||
{
|
||||
$aSortOrder = array();
|
||||
@@ -835,7 +1043,12 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
return $aSortOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param null $sTargetTableId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($sTargetTableId = null)
|
||||
{
|
||||
$sSaveId = is_null($sTargetTableId) ? $this->sTableId : $sTargetTableId;
|
||||
@@ -846,6 +1059,9 @@ class DataTableSettings implements Serializable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAsDefault()
|
||||
{
|
||||
$sSettings = $this->serialize();
|
||||
@@ -875,7 +1091,12 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param null $sTableId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetPrefsKey($sTableId = null)
|
||||
{
|
||||
if ($sTableId == null) $sTableId = '*';
|
||||
@@ -886,7 +1107,18 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
return implode('/', $aKeys).'|'.$sTableId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sAlias
|
||||
* @param $sAttCode
|
||||
* @param $oAttDef
|
||||
* @param $bChecked
|
||||
* @param $sSort
|
||||
*
|
||||
* @return array|bool
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
protected function GetFieldData($sAlias, $sAttCode, $oAttDef, $bChecked, $sSort)
|
||||
{
|
||||
$ret = false;
|
||||
@@ -936,4 +1168,4 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2017 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/>
|
||||
|
||||
/**
|
||||
* DisplayBlock and derived class
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2017 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/webpage.class.inc.php');
|
||||
@@ -91,7 +85,7 @@ class DisplayBlock
|
||||
{
|
||||
$oDummyFilter = new DBObjectSearch($oSet->GetClass());
|
||||
$aKeys = array();
|
||||
$oSet->OptimizeColumnLoad(array('id')); // No need to load all the columns just to get the id
|
||||
$oSet->OptimizeColumnLoad(array($oSet->GetClassAlias() => array())); // No need to load all the columns just to get the id
|
||||
while($oObject = $oSet->Fetch())
|
||||
{
|
||||
$aKeys[] = $oObject->GetKey();
|
||||
@@ -249,7 +243,7 @@ class DisplayBlock
|
||||
$sHtml .= $this->GetRenderContent($oPage, $aExtraParams, $sId);
|
||||
} catch (Exception $e)
|
||||
{
|
||||
|
||||
IssueLog::Error('Exception during GetDisplay: ' . $e->getMessage());
|
||||
}
|
||||
$sHtml .= "</div>\n";
|
||||
}
|
||||
@@ -500,7 +494,10 @@ class DisplayBlock
|
||||
}
|
||||
$aAttribs =array(
|
||||
'group' => array('label' => $sGroupByLabel, 'description' => ''),
|
||||
'value' => array('label'=> Dict::S('UI:GroupBy:'.$sAggregationFunction), 'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr))
|
||||
'value' => array(
|
||||
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
|
||||
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
|
||||
),
|
||||
);
|
||||
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
|
||||
$sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount));
|
||||
@@ -699,7 +696,7 @@ class DisplayBlock
|
||||
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
|
||||
'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'),
|
||||
'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(),
|
||||
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png'
|
||||
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png',
|
||||
));
|
||||
|
||||
$oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])");
|
||||
@@ -1172,16 +1169,26 @@ EOF
|
||||
}
|
||||
if (($bAutoReload) && ($this->m_sStyle != 'search')) // Search form do NOT auto-reload
|
||||
{
|
||||
$sFilter = addslashes(str_replace('"', "'", $this->m_oFilter->serialize())); // Used either for asynchronous or auto_reload
|
||||
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
|
||||
// Used either for asynchronous or auto_reload
|
||||
// does a json_encode twice to get a string usable as function parameter
|
||||
$sFilterBefore = $this->m_oFilter->serialize();
|
||||
$sFilter = json_encode($sFilterBefore);
|
||||
$sExtraParams = json_encode(json_encode($aExtraParams));
|
||||
|
||||
$oPage->add_script('if (typeof window.oAutoReloadBlock == "undefined") {
|
||||
window.oAutoReloadBlock = {};
|
||||
}
|
||||
if (typeof window.oAutoReloadBlock[\''.$sId.'\'] != "undefined") {
|
||||
clearInterval(window.oAutoReloadBlock[\''.$sId.'\']);
|
||||
}
|
||||
window.oAutoReloadBlock[\''.$sId.'\'] = setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \"'.$sFilter.'\", \"'.$sExtraParams.'\")", '.$iReloadInterval.');');
|
||||
$oPage->add_script(
|
||||
<<<JS
|
||||
if (typeof window.oAutoReloadBlock == "undefined") {
|
||||
window.oAutoReloadBlock = {};
|
||||
}
|
||||
if (typeof window.oAutoReloadBlock['$sId'] != "undefined") {
|
||||
clearInterval(window.oAutoReloadBlock['$sId']);
|
||||
}
|
||||
|
||||
window.oAutoReloadBlock['$sId'] = setInterval(function() {
|
||||
ReloadBlock('$sId', '{$this->m_sStyle}', $sFilter, $sExtraParams);
|
||||
}, '$iReloadInterval');
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
return $sHtml;
|
||||
@@ -1719,6 +1726,7 @@ class MenuBlock extends DisplayBlock
|
||||
*/
|
||||
}
|
||||
$this->AddMenuSeparator($aActions);
|
||||
/** @var \iApplicationUIExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
|
||||
{
|
||||
$oSet->Rewind();
|
||||
@@ -1814,6 +1822,7 @@ class MenuBlock extends DisplayBlock
|
||||
}
|
||||
|
||||
$this->AddMenuSeparator($aActions);
|
||||
/** @var \iApplicationUIExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
|
||||
{
|
||||
$oSet->Rewind();
|
||||
@@ -1871,11 +1880,11 @@ class MenuBlock extends DisplayBlock
|
||||
{
|
||||
if (count($aFavoriteActions) > 0)
|
||||
{
|
||||
$sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>".Dict::S('UI:Menu:OtherActions')."\n<ul>\n";
|
||||
$sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>".Dict::S('UI:Menu:OtherActions')."<i class=\"fas fa-caret-down\"></i>"."\n<ul>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>".Dict::S('UI:Menu:Actions')."\n<ul>\n";
|
||||
$sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>".Dict::S('UI:Menu:Actions')."<i class=\"fas fa-caret-down\"></i>"."\n<ul>\n";
|
||||
}
|
||||
|
||||
$sHtml .= $oPage->RenderPopupMenuItems($aActions, $aFavoriteActions);
|
||||
@@ -1883,7 +1892,8 @@ class MenuBlock extends DisplayBlock
|
||||
if ($this->m_sStyle == 'details')
|
||||
{
|
||||
$sSearchAction = "window.location=\"{$sRootUrl}pages/UI.php?operation=search_form&do_search=0&class=$sClass{$sContext}\"";
|
||||
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::Format('UI:SearchFor_Class', MetaModel::GetName($sClass)), ENT_QUOTES, 'UTF-8')."\"><span class=\"search-button fa fa-search\" onclick='$sSearchAction'></span></div>";
|
||||
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::Format('UI:SearchFor_Class',
|
||||
MetaModel::GetName($sClass)), ENT_QUOTES, 'UTF-8')."\"><span class=\"search-button fas fa-search\" onclick='$sSearchAction'></span></div>";
|
||||
}
|
||||
|
||||
|
||||
@@ -1894,7 +1904,8 @@ class MenuBlock extends DisplayBlock
|
||||
}
|
||||
if (!$oPage->IsPrintableVersion() && ($sRefreshAction!=''))
|
||||
{
|
||||
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::S('UI:Button:Refresh'), ENT_QUOTES, 'UTF-8')."\"><span class=\"refresh-button fa fa-refresh\" onclick=\"$sRefreshAction\"></span></div>";
|
||||
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::S('UI:Button:Refresh'),
|
||||
ENT_QUOTES, 'UTF-8')."\"><span class=\"refresh-button fas fa-sync\" onclick=\"$sRefreshAction\"></span></div>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -395,6 +395,7 @@ EOF
|
||||
{
|
||||
foreach($aFields as $oField)
|
||||
{
|
||||
/** @var \DesignerFormField $oField */
|
||||
$oField->ReadParam($aValues);
|
||||
}
|
||||
}
|
||||
@@ -679,18 +680,34 @@ class DesignerTabularForm extends DesignerForm
|
||||
|
||||
class DesignerFormField
|
||||
{
|
||||
/** @var string $sLabel */
|
||||
protected $sLabel;
|
||||
/** @var string $sCode */
|
||||
protected $sCode;
|
||||
/** @var mixed $defaultValue */
|
||||
protected $defaultValue;
|
||||
/** @var \DesignerForm $oForm */
|
||||
protected $oForm;
|
||||
/** @var bool $bMandatory */
|
||||
protected $bMandatory;
|
||||
/** @var bool $bReadOnly */
|
||||
protected $bReadOnly;
|
||||
/** @var bool $bAutoApply */
|
||||
protected $bAutoApply;
|
||||
/** @var array $aCSSClasses */
|
||||
protected $aCSSClasses;
|
||||
/** @var bool $bDisplayed */
|
||||
protected $bDisplayed;
|
||||
/** @var array $aWidgetExtraParams */
|
||||
protected $aWidgetExtraParams;
|
||||
|
||||
|
||||
/**
|
||||
* DesignerFormField constructor.
|
||||
*
|
||||
* @param string $sCode
|
||||
* @param string $sLabel
|
||||
* @param mixed $defaultValue
|
||||
*/
|
||||
public function __construct($sCode, $sLabel, $defaultValue)
|
||||
{
|
||||
$this->sLabel = $sLabel;
|
||||
@@ -703,7 +720,10 @@ class DesignerFormField
|
||||
$this->bDisplayed = true;
|
||||
$this->aWidgetExtraParams = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCode()
|
||||
{
|
||||
return $this->sCode;
|
||||
@@ -712,69 +732,108 @@ class DesignerFormField
|
||||
/**
|
||||
* @param \DesignerForm $oForm
|
||||
*/
|
||||
public function SetForm(\DesignerForm $oForm)
|
||||
public function SetForm(DesignerForm $oForm)
|
||||
{
|
||||
$this->oForm = $oForm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $bMandatory
|
||||
*/
|
||||
public function SetMandatory($bMandatory = true)
|
||||
{
|
||||
$this->bMandatory = $bMandatory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bReadOnly
|
||||
*/
|
||||
public function SetReadOnly($bReadOnly = true)
|
||||
{
|
||||
$this->bReadOnly = $bReadOnly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsReadOnly()
|
||||
{
|
||||
return ($this->oForm->IsReadOnly() || $this->bReadOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAutoApply
|
||||
*/
|
||||
public function SetAutoApply($bAutoApply)
|
||||
{
|
||||
$this->bAutoApply = $bAutoApply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAutoApply()
|
||||
{
|
||||
return $this->bAutoApply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bDisplayed
|
||||
*/
|
||||
public function SetDisplayed($bDisplayed)
|
||||
{
|
||||
$this->bDisplayed = $bDisplayed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsDisplayed()
|
||||
{
|
||||
return $this->bDisplayed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetFieldId()
|
||||
{
|
||||
return $this->oForm->GetFieldId($this->sCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetWidgetClass()
|
||||
{
|
||||
return 'property_field';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetWidgetExtraParams()
|
||||
{
|
||||
return $this->aWidgetExtraParams;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \WebPage $oP
|
||||
* @param string $sFormId
|
||||
* @param string $sRenderMode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
return array('label' => $this->sLabel, 'value' => "<input type=\"text\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $aValues
|
||||
*/
|
||||
public function ReadParam(&$aValues)
|
||||
{
|
||||
if ($this->IsReadOnly())
|
||||
@@ -801,12 +860,18 @@ class DesignerFormField
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $sCSSClass
|
||||
*/
|
||||
public function AddCSSClass($sCSSClass)
|
||||
{
|
||||
$this->aCSSClasses[] = $sCSSClass;
|
||||
@@ -814,6 +879,8 @@ class DesignerFormField
|
||||
|
||||
/**
|
||||
* A way to set/change the default value after constructing the field
|
||||
*
|
||||
* @param array $aAllDefaultValue
|
||||
*/
|
||||
public function SetDefaultValueFrom($aAllDefaultValue)
|
||||
{
|
||||
@@ -822,7 +889,12 @@ class DesignerFormField
|
||||
$this->defaultValue = $aAllDefaultValue[$this->GetCode()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sFieldCode
|
||||
*
|
||||
* @return \DesignerFormField|false
|
||||
*/
|
||||
public function FindField($sFieldCode)
|
||||
{
|
||||
if ($this->sCode == $sFieldCode)
|
||||
@@ -832,11 +904,17 @@ class DesignerFormField
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetHandlerEquals()
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetHandlerGetValue()
|
||||
{
|
||||
return 'null';
|
||||
@@ -845,25 +923,43 @@ class DesignerFormField
|
||||
|
||||
class DesignerLabelField extends DesignerFormField
|
||||
{
|
||||
/** @var int $iCount A counter to automatically make the field code */
|
||||
protected static $iCount = 0;
|
||||
/** @var string $sDescription */
|
||||
protected $sDescription;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function __construct($sLabel, $sDescription)
|
||||
{
|
||||
parent::__construct('', $sLabel, '');
|
||||
// Increase counter
|
||||
static::$iCount++;
|
||||
|
||||
parent::__construct('label_number_' . static::$iCount, $sLabel, '');
|
||||
$this->sDescription = $sDescription;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
return array('label' => $this->sLabel, 'value' => $this->sDescription);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function ReadParam(&$aValues)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function IsVisible()
|
||||
{
|
||||
return true;
|
||||
@@ -1334,7 +1430,8 @@ class DesignerIconSelectionField extends DesignerFormField
|
||||
$sPostUploadTo = ($this->sUploadUrl == null) ? 'null' : "'{$this->sUploadUrl}'";
|
||||
if (!$this->IsReadOnly())
|
||||
{
|
||||
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$this->defaultValue}\"/>";
|
||||
$sDefaultValue = ($this->defaultValue !== '') ? $this->defaultValue : $this->aAllowedValues[$idx]['value'];
|
||||
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/>";
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').icon_select({current_idx: $idx, items: $sJSItems, post_upload_to: $sPostUploadTo});
|
||||
@@ -1396,6 +1493,7 @@ class RunTimeIconSelectionField extends DesignerIconSelectionField
|
||||
$sAvailableIcons .= ' static $sKey = '.var_export($sKey, true).';'.PHP_EOL;
|
||||
$sAvailableIcons .= ' static $aIconFiles = '.var_export($aFiles, true).';'.PHP_EOL;
|
||||
$sAvailableIcons .= '}'.PHP_EOL;
|
||||
SetupUtils::builddir(dirname($sCacheFile));
|
||||
file_put_contents($sCacheFile, $sAvailableIcons, LOCK_EX);
|
||||
}
|
||||
return $aFiles;
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2018 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 iTopWebPage
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2018 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/nicewebpage.class.inc.php");
|
||||
@@ -46,8 +39,14 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
protected $sBreadCrumbEntryIcon;
|
||||
protected $oCtx;
|
||||
|
||||
protected $bHasCollapsibleSection = false;
|
||||
|
||||
/**
|
||||
* iTopWebPage constructor.
|
||||
*
|
||||
* @param string $sTitle
|
||||
* @param bool $bPrintable
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($sTitle, $bPrintable = false)
|
||||
{
|
||||
parent::__construct($sTitle, $bPrintable);
|
||||
@@ -71,7 +70,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->m_sMenu = "";
|
||||
$this->m_aMessages = array();
|
||||
$this->SetRootUrl(utils::GetAbsoluteUrlAppRoot());
|
||||
$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header("Cache-control: no-cache");
|
||||
$this->add_linked_stylesheet("../css/jquery.treeview.css");
|
||||
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
|
||||
@@ -79,7 +78,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->add_linked_stylesheet("../css/jquery.multiselect.css");
|
||||
$this->add_linked_stylesheet("../css/magnific-popup.css");
|
||||
$this->add_linked_stylesheet("../css/c3.min.css");
|
||||
$this->add_linked_stylesheet("../css/font-awesome/css/font-awesome.min.css");
|
||||
$this->add_linked_stylesheet("../css/font-awesome/css/all.min.css");
|
||||
$this->add_linked_stylesheet("../css/font-awesome/css/v4-shims.min.css");
|
||||
|
||||
$this->add_linked_script('../js/jquery.layout.min.js');
|
||||
$this->add_linked_script('../js/jquery.ba-bbq.min.js');
|
||||
@@ -151,6 +151,9 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function IsMenuPaneVisible()
|
||||
{
|
||||
$bLeftPaneOpen = true;
|
||||
@@ -173,6 +176,9 @@ EOF
|
||||
return $bLeftPaneOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function PrepareLayout()
|
||||
{
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
@@ -221,7 +227,6 @@ EOF;
|
||||
);
|
||||
$sTimeFormat = AttributeDateTime::GetFormat()->ToTimeFormat();
|
||||
$oTimeFormat = new DateTimeFormat($sTimeFormat);
|
||||
$sJSLangShort = json_encode(strtolower(substr(Dict::GetUserLanguage(), 0, 2)));
|
||||
|
||||
// Date picker options
|
||||
$aPickerOptions = array(
|
||||
@@ -239,29 +244,38 @@ EOF;
|
||||
$sJSDatePickerOptions = json_encode($aPickerOptions);
|
||||
|
||||
// Time picker additional options
|
||||
$sUserLang = Dict::GetUserLanguage();
|
||||
$sUserLangShort = strtolower(
|
||||
substr($sUserLang, 0, 2)
|
||||
);
|
||||
// PR #40 : we are picking correct values for specific cases in dict files
|
||||
// some languages are using codes like zh-CN or pt-BR
|
||||
$sTimePickerLang = json_encode(
|
||||
Dict::S('INTERNAL:JQuery-DatePicker:LangCode', $sUserLangShort)
|
||||
);
|
||||
$aPickerOptions['showOn'] = '';
|
||||
$aPickerOptions['buttonImage'] = null;
|
||||
$aPickerOptions['timeFormat'] = $oTimeFormat->ToDatePicker();
|
||||
$aPickerOptions['controlType'] = 'select';
|
||||
$aPickerOptions['closeText'] = Dict::S('UI:Button:Ok');
|
||||
$sJSDateTimePickerOptions = json_encode($aPickerOptions);
|
||||
if ($sJSLangShort != '"en"')
|
||||
if ($sTimePickerLang != '"en"')
|
||||
{
|
||||
// More options that cannot be passed via json_encode since they must be evaluated client-side
|
||||
$aMoreJSOptions = ",
|
||||
'timeText': $.timepicker.regional[$sJSLangShort].timeText,
|
||||
'hourText': $.timepicker.regional[$sJSLangShort].hourText,
|
||||
'minuteText': $.timepicker.regional[$sJSLangShort].minuteText,
|
||||
'secondText': $.timepicker.regional[$sJSLangShort].secondText,
|
||||
'currentText': $.timepicker.regional[$sJSLangShort].currentText
|
||||
'timeText': $.timepicker.regional[$sTimePickerLang].timeText,
|
||||
'hourText': $.timepicker.regional[$sTimePickerLang].hourText,
|
||||
'minuteText': $.timepicker.regional[$sTimePickerLang].minuteText,
|
||||
'secondText': $.timepicker.regional[$sTimePickerLang].secondText,
|
||||
'currentText': $.timepicker.regional[$sTimePickerLang].currentText
|
||||
}";
|
||||
$sJSDateTimePickerOptions = substr($sJSDateTimePickerOptions, 0, -1).$aMoreJSOptions;
|
||||
}
|
||||
$this->add_script(
|
||||
<<< EOF
|
||||
<<< JS
|
||||
function GetUserLanguage()
|
||||
{
|
||||
return $sJSLangShort;
|
||||
return $sTimePickerLang;
|
||||
}
|
||||
function PrepareWidgets()
|
||||
{
|
||||
@@ -293,12 +307,12 @@ EOF;
|
||||
});
|
||||
});
|
||||
}
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
|
||||
// Attribute set tooltip on items
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
<<<JS
|
||||
$('.attribute-set-item').each(function(){
|
||||
// Encoding only title as the content is already sanitized by the HTML attribute.
|
||||
var sLabel = $('<div/>').text($(this).attr('data-label')).html();
|
||||
@@ -325,25 +339,24 @@ EOF
|
||||
position: { corner: { target: 'topMiddle', tooltip: 'bottomLeft' }}
|
||||
});
|
||||
});
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
|
||||
// Make image attributes zoomable
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
<<<JS
|
||||
$('.view-image img').each(function(){
|
||||
$(this).attr('href', $(this).attr('src'))
|
||||
})
|
||||
.magnificPopup({type: 'image', closeOnContentClick: true });
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
|
||||
|
||||
$this->add_init_script(
|
||||
<<< EOF
|
||||
<<< JS
|
||||
try
|
||||
{
|
||||
var myLayout; // a var is required because this page utilizes: myLayout.allowOverflow() method
|
||||
|
||||
|
||||
// Layout
|
||||
paneSize = GetUserPreference('menu_size', 300);
|
||||
if ($('body').length > 0)
|
||||
@@ -449,11 +462,11 @@ EOF
|
||||
// Do something with the error !
|
||||
alert(err);
|
||||
}
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
|
||||
$this->add_ready_script(
|
||||
<<< EOF
|
||||
<<< JS
|
||||
|
||||
// Adjust initial size
|
||||
$('.v-resizable').each( function()
|
||||
@@ -614,7 +627,7 @@ EOF
|
||||
});
|
||||
}
|
||||
});
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
$this->add_ready_script(InlineImage::FixImagesWidth());
|
||||
/*
|
||||
@@ -625,7 +638,7 @@ EOF
|
||||
|
||||
$sUserPrefs = appUserPreferences::GetAsJSON();
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
<<<JS
|
||||
// // for JQuery history
|
||||
// function history_callback(hash)
|
||||
// {
|
||||
@@ -695,7 +708,7 @@ EOF
|
||||
{
|
||||
$('.ui-layout-center, .ui-layout-north, .ui-layout-south').css({display: 'block'});
|
||||
}
|
||||
EOF
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -730,11 +743,22 @@ EOF
|
||||
$this->sBreadCrumbEntryIcon = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*/
|
||||
public function AddToMenu($sHtml)
|
||||
{
|
||||
$this->m_sMenu .= $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function GetSiloSelectionForm()
|
||||
{
|
||||
// List of visible Organizations
|
||||
@@ -761,15 +785,9 @@ EOF
|
||||
switch ($iCount)
|
||||
{
|
||||
case 0:
|
||||
// No such dimension/silo => nothing to select
|
||||
$sHtml = '<div id="SiloSelection"><!-- nothing to select --></div>';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Only one possible choice... no selection, but display the value
|
||||
$oOrg = $oSet->Fetch();
|
||||
$sHtml = '<div id="SiloSelection">'.$oOrg->GetName().'</div>';
|
||||
$sHtml .= '';
|
||||
// No such dimension/silo or only one possible choice => nothing to select
|
||||
$sHtml = '<div id="SiloSelection"><!-- nothing to select --></div>';
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -801,6 +819,9 @@ EOF
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public function DisplayMenu()
|
||||
{
|
||||
// Display the menu
|
||||
@@ -816,6 +837,8 @@ EOF
|
||||
protected function InitNewsroom()
|
||||
{
|
||||
$sNewsroomInitialImage = '';
|
||||
$aProviderParams = array();
|
||||
|
||||
if (MetaModel::GetConfig()->Get('newsroom_enabled') !== false)
|
||||
{
|
||||
$oUser = UserRights::GetUserObject();
|
||||
@@ -823,31 +846,32 @@ EOF
|
||||
* @var iNewsroomProvider[] $aProviders
|
||||
*/
|
||||
$aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
|
||||
$aProviderParams = array();
|
||||
foreach($aProviders as $oProvider)
|
||||
{
|
||||
$oProvider->SetConfig(MetaModel::GetConfig());
|
||||
$bProviderEnabled = appUserPreferences::GetPref('newsroom_provider_'.get_class($oProvider), true);
|
||||
if ($bProviderEnabled && $oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$aProviderParams[] = array(
|
||||
'label' => $oProvider->GetLabel(),
|
||||
'fetch_url' => $oProvider->GetFetchURL(),
|
||||
'view_all_url' => $oProvider->GetViewAllURL(),
|
||||
'mark_all_as_read_url' => $oProvider->GetMarkAllAsReadURL(),
|
||||
'placeholders' => $oProvider->GetPlaceholders(),
|
||||
'ttl' => $oProvider->GetTTL(),
|
||||
);
|
||||
$bProviderEnabled = appUserPreferences::GetPref('newsroom_provider_'.get_class($oProvider),true);
|
||||
if ($bProviderEnabled && $oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$aProviderParams[] = array(
|
||||
'label' => $oProvider->GetLabel(),
|
||||
'fetch_url' => $oProvider->GetFetchURL(),
|
||||
'view_all_url' => $oProvider->GetViewAllURL(),
|
||||
'mark_all_as_read_url' => $oProvider->GetMarkAllAsReadURL(),
|
||||
'placeholders' => $oProvider->GetPlaceholders(),
|
||||
'ttl' => $oProvider->GetTTL(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Show newsroom only if there are some providers
|
||||
if (count($aProviderParams) > 0)
|
||||
{
|
||||
$sImageUrl= '../images/newsroom_menu.png';
|
||||
$sPlaceholderImageUrl= '../images/newsroom-message.svg';
|
||||
$sImageUrl= 'fas fa-comment-dots';
|
||||
$sPlaceholderImageUrl= 'far fa-envelope';
|
||||
$aParams = array(
|
||||
'image_url' => $sImageUrl,
|
||||
'placeholder_image_url' => $sPlaceholderImageUrl,
|
||||
'cache_uuid' => 'itop-newsroom-'.md5(APPROOT),
|
||||
'image_icon' => $sImageUrl,
|
||||
'placeholder_image_icon' => $sPlaceholderImageUrl,
|
||||
'cache_uuid' => 'itop-newsroom-'.UserRights::GetUserId().'-'.md5(APPROOT),
|
||||
'providers' => $aProviderParams,
|
||||
'display_limit' => (int)appUserPreferences::GetPref('newsroom_display_size', 7),
|
||||
'labels' => array(
|
||||
@@ -862,20 +886,17 @@ EOF
|
||||
$('#top-left-newsroom-cell').newsroom_menu($sParams);
|
||||
EOF
|
||||
);
|
||||
$sNewsroomInitialImage = '<img style="opacity:0.4" src="../images/newsroom_menu.png">';
|
||||
$sNewsroomInitialImage = '<i style="opacity:0.4" class="top-right-icon fas fa-comment-dots"></i>';
|
||||
}
|
||||
else
|
||||
{
|
||||
// No newsroom menu at all
|
||||
}
|
||||
}
|
||||
// else no newsroom menu
|
||||
return $sNewsroomInitialImage;
|
||||
// else no newsroom menu
|
||||
return $sNewsroomInitialImage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
@@ -954,8 +975,8 @@ EOF
|
||||
$sNewEntry = json_encode(array(
|
||||
'id' => $this->sBreadCrumbEntryId,
|
||||
'url' => $this->sBreadCrumbEntryUrl,
|
||||
'label' => htmlentities($this->sBreadCrumbEntryLabel, ENT_QUOTES, 'UTF-8'),
|
||||
'description' => htmlentities($this->sBreadCrumbEntryDescription, ENT_QUOTES, 'UTF-8'),
|
||||
'label' => htmlentities($this->sBreadCrumbEntryLabel, ENT_QUOTES, self::PAGES_CHARSET),
|
||||
'description' => htmlentities($this->sBreadCrumbEntryDescription, ENT_QUOTES, self::PAGES_CHARSET),
|
||||
'icon' => $this->sBreadCrumbEntryIcon,
|
||||
));
|
||||
}
|
||||
@@ -988,8 +1009,9 @@ EOF
|
||||
$sHtml .= "<head>\n";
|
||||
// Make sure that Internet Explorer renders the page using its latest/highest/greatest standards !
|
||||
$sHtml .= "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n";
|
||||
$sHtml .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
|
||||
$sHtml .= "<title>".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</title>\n";
|
||||
$sPageCharset = self::PAGES_CHARSET;
|
||||
$sHtml .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$sPageCharset\" />\n";
|
||||
$sHtml .= "<title>".htmlentities($this->s_title, ENT_QUOTES, $sPageCharset)."</title>\n";
|
||||
$sHtml .= $this->get_base_tag();
|
||||
// Stylesheets MUST be loaded before any scripts otherwise
|
||||
// jQuery scripts may face some spurious problems (like failing on a 'reload')
|
||||
@@ -1108,16 +1130,18 @@ EOF
|
||||
{
|
||||
$sBodyClass = 'printable-version';
|
||||
}
|
||||
$sHtml .= "<body class=\"$sBodyClass\">\n";
|
||||
$sHtml .= "<body class=\"$sBodyClass\" data-gui-type=\"backoffice\">\n";
|
||||
if ($this->IsPrintableVersion())
|
||||
{
|
||||
$sHtml .= "<div class=\"explain-printable not-printable\">";
|
||||
$sHtml .= '<p>'.Dict::Format('UI:ExplainPrintable',
|
||||
'<img src="../images/eye-open-555.png" style="vertical-align:middle">').'</p>';
|
||||
$sHtml .= "<div id=\"hiddeable_chapters\"></div>";
|
||||
$sHtml .= '<button onclick="window.print()">'.htmlentities(Dict::S('UI:Button:GoPrint'), ENT_QUOTES, 'UTF-8').'</button>';
|
||||
$sHtml .= '<button onclick="window.print()">'.htmlentities(Dict::S('UI:Button:GoPrint'), ENT_QUOTES,
|
||||
self::PAGES_CHARSET).'</button>';
|
||||
$sHtml .= ' ';
|
||||
$sHtml .= '<button onclick="window.close()">'.htmlentities(Dict::S('UI:Button:Cancel'), ENT_QUOTES, 'UTF-8').'</button>';
|
||||
$sHtml .= '<button onclick="window.close()">'.htmlentities(Dict::S('UI:Button:Cancel'), ENT_QUOTES,
|
||||
self::PAGES_CHARSET).'</button>';
|
||||
$sHtml .= ' ';
|
||||
|
||||
$sDefaultResolution = '27.7cm';
|
||||
@@ -1155,7 +1179,7 @@ EOF;
|
||||
}
|
||||
|
||||
// Render the text of the global search form
|
||||
$sText = htmlentities(utils::ReadParam('text', '', false, 'raw_data'), ENT_QUOTES, 'UTF-8');
|
||||
$sText = htmlentities(utils::ReadParam('text', '', false, 'raw_data'), ENT_QUOTES, self::PAGES_CHARSET);
|
||||
$sOnClick = " onclick=\"if ($('#global-search-input').val() != '') { $('#global-search form').submit(); } \"";
|
||||
$sDefaultPlaceHolder = Dict::S("UI:YourSearch");
|
||||
|
||||
@@ -1179,7 +1203,7 @@ EOF;
|
||||
{
|
||||
$sLogonMessage = Dict::Format('UI:LoggedAsMessage', $sUserName);
|
||||
}
|
||||
$sLogOffMenu = "<span id=\"logOffBtn\"><ul><li><img src=\"../images/on-off-menu.png\"><ul>";
|
||||
$sLogOffMenu = "<span id=\"logOffBtn\"><ul><li><i class=\"top-right-icon icon-additional-arrow fas fa-power-off\"></i><ul>";
|
||||
$sLogOffMenu .= "<li><span>$sLogonMessage</span></li>\n";
|
||||
$aActions = array();
|
||||
|
||||
@@ -1210,7 +1234,7 @@ EOF;
|
||||
$oExitArchive = new JSPopupMenuItem('UI:ArchiveModeOff', Dict::S('UI:ArchiveModeOff'), 'return ArchiveMode(false);');
|
||||
$aActions[$oExitArchive->GetUID()] = $oExitArchive->GetMenuItem();
|
||||
|
||||
$sIcon = '<span class="fa fa-lock fa-1x"></span>';
|
||||
$sIcon = '<span class="fas fa-lock fa-1x"></span>';
|
||||
$this->AddApplicationMessage(Dict::S('UI:ArchiveMode:Banner'), $sIcon, Dict::S('UI:ArchiveMode:Banner+'));
|
||||
}
|
||||
elseif (UserRights::CanBrowseArchive())
|
||||
@@ -1256,8 +1280,8 @@ EOF;
|
||||
$sIcon =
|
||||
<<<EOF
|
||||
<span class="fa-stack fa-sm">
|
||||
<i class="fa fa-pencil fa-flip-horizontal fa-stack-1x"></i>
|
||||
<i class="fa fa-ban fa-stack-2x text-danger"></i>
|
||||
<i class="fas fa-pencil-alt fa-flip-horizontal fa-stack-1x"></i>
|
||||
<i class="fas fa-ban fa-stack-2x text-danger"></i>
|
||||
</span>
|
||||
EOF;
|
||||
|
||||
@@ -1274,7 +1298,7 @@ EOF;
|
||||
{
|
||||
$sHtmlIcon = $aMessage['icon'] ? $aMessage['icon'] : '';
|
||||
$sHtmlMessage = $aMessage['message'];
|
||||
$sTitleAttr = $aMessage['tip'] ? 'title="'.htmlentities($aMessage['tip'], ENT_QUOTES, 'UTF-8').'"' : '';
|
||||
$sTitleAttr = $aMessage['tip'] ? 'title="'.htmlentities($aMessage['tip'], ENT_QUOTES, self::PAGES_CHARSET).'"' : '';
|
||||
$sApplicationMessages .= '<div class="app-message" '.$sTitleAttr.'><span class="app-message-icon">'.$sHtmlIcon.'</span><span class="app-message-body">'.$sHtmlMessage.'</div></span>';
|
||||
}
|
||||
|
||||
@@ -1305,9 +1329,11 @@ EOF;
|
||||
$sHtml .= '<!-- Beginning of the left pane -->';
|
||||
$sHtml .= ' <div class="ui-layout-north">';
|
||||
$sHtml .= ' <div id="header-logo">';
|
||||
$sHtml .= ' <div id="top-left"></div><div id="logo"><a href="'.htmlentities($sIconUrl, ENT_QUOTES,
|
||||
'UTF-8').'"><img src="'.$sDisplayIcon.'" title="'.htmlentities($sVersionString, ENT_QUOTES,
|
||||
'UTF-8').'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
|
||||
$sHtml .= ' <div id="top-left"></div><div id="logo"><a href="'
|
||||
.htmlentities($sIconUrl, ENT_QUOTES, self::PAGES_CHARSET)
|
||||
.'"><img src="'.$sDisplayIcon.'" title="'
|
||||
.htmlentities($sVersionString, ENT_QUOTES, self::PAGES_CHARSET)
|
||||
.'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
|
||||
$sHtml .= ' </div>';
|
||||
$sHtml .= ' <div class="header-menu">';
|
||||
if (!MetaModel::GetConfig()->Get('demo_mode'))
|
||||
@@ -1339,10 +1365,10 @@ EOF;
|
||||
$sHtml .= ' <table id="top-bar-table">';
|
||||
$sHtml .= ' <tr>';
|
||||
$sHtml .= ' <td id="open-left-pane" class="menu-pane-exclusive" style="'.$GoHomeInitialStyle.'" onclick="$(\'body\').layout().open(\'west\');">';
|
||||
$sHtml .= ' <img src="../images/menu.png">';
|
||||
$sHtml .= ' <i class="fas fa-bars"></i>';
|
||||
$sHtml .= ' </td>';
|
||||
$sHtml .= ' <td id="go-home" class="menu-pane-exclusive" style="'.$GoHomeInitialStyle.'">';
|
||||
$sHtml .= ' <a href="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php"><img src="../images/home.png"></a>';
|
||||
$sHtml .= ' <a href="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php"><i class="fas fa-home"></i></a>';
|
||||
$sHtml .= ' </td>';
|
||||
$sHtml .= ' <td class="top-bar-spacer menu-pane-exclusive" style="'.$GoHomeInitialStyle.'">';
|
||||
$sHtml .= ' </td>';
|
||||
@@ -1352,8 +1378,8 @@ EOF;
|
||||
$sHtml .= ' <td id="top-bar-table-search">';
|
||||
$sHtml .= ' <div id="global-search"><form action="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php">';
|
||||
$sHtml .= ' <table id="top-left-buttons-area"><tr>';
|
||||
$sHtml .= ' <td id="top-left-global-search-cell"><div id="global-search-area"><input id="global-search-input" type="text" name="text" placeholder="'.$sDefaultPlaceHolder.'" value="'.$sText.'"></input><div '.$sOnClick.' id="global-search-image"><input type="hidden" name="operation" value="full_text"/></div></div></td>';
|
||||
$sHtml .= ' <td id="top-left-help-cell"><a id="help-link" href="'.$sOnlineHelpUrl.'" target="_blank"><img title="'.Dict::S('UI:Help').'" src="../images/help.png?t='.utils::GetCacheBusterTimestamp().'"/></td>';
|
||||
$sHtml .= ' <td id="top-left-global-search-cell"><div id="global-search-area"><input id="global-search-input" type="text" name="text" placeholder="'.$sDefaultPlaceHolder.'" value="'.$sText.'"></input><div '.$sOnClick.' id="global-search-image"><i class="top-right-icon fa-flip-horizontal fas fa-search"></i><input type="hidden" name="operation" value="full_text"/></div></div></td>';
|
||||
$sHtml .= ' <td id="top-left-help-cell"><a id="help-link" href="'.$sOnlineHelpUrl.'" target="_blank" title="'.Dict::S('UI:Help').'"><i class="top-right-icon fas fa-question-circle"></i></a></td>';
|
||||
$sHtml .= ' <td id="top-left-newsroom-cell">'.$sNewsRoomInitialImage.'</td>';
|
||||
$sHtml .= ' <td id="top-left-logoff-cell">'.self::FilterXSS($sLogOffMenu).'</td>';
|
||||
$sHtml .= ' </tr></table></form></div>';
|
||||
@@ -1408,9 +1434,12 @@ EOF;
|
||||
{
|
||||
if ($this->GetOutputFormat() == 'pdf' && $this->IsOutputFormatAvailable('pdf'))
|
||||
{
|
||||
// Note: Apparently this was a demand from ITOMIG a while back, so it's not "dead code" per say.
|
||||
// The last trace we got is in R-007989. Do not remove this without checking before with the concerned parties if it is still used!
|
||||
if (@is_readable(APPROOT.'lib/MPDF/mpdf.php'))
|
||||
{
|
||||
require_once(APPROOT.'lib/MPDF/mpdf.php');
|
||||
/** @noinspection PhpUndefinedClassInspection Check above comment */
|
||||
$oMPDF = new mPDF('c');
|
||||
$oMPDF->mirroMargins = false;
|
||||
if ($this->a_base['href'] != '')
|
||||
@@ -1438,52 +1467,45 @@ EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds init scripts for the collapsible sections
|
||||
* @param string $sTabContainer
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function outputCollapsibleSectionInit()
|
||||
{
|
||||
if (!$this->bHasCollapsibleSection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_script(<<<'EOD'
|
||||
function initCollapsibleSection(iSectionId, bOpenedByDefault, sSectionStateStorageKey)
|
||||
{
|
||||
var bStoredSectionState = JSON.parse(localStorage.getItem(sSectionStateStorageKey));
|
||||
var bIsSectionOpenedInitially = (bStoredSectionState == null) ? bOpenedByDefault : bStoredSectionState;
|
||||
|
||||
if (bIsSectionOpenedInitially) {
|
||||
$("#LnkCollapse_"+iSectionId).toggleClass("open");
|
||||
$("#Collapse_"+iSectionId).toggle();
|
||||
}
|
||||
|
||||
$("#LnkCollapse_"+iSectionId).click(function(e) {
|
||||
localStorage.setItem(sSectionStateStorageKey, !($("#Collapse_"+iSectionId).is(":visible")));
|
||||
$("#LnkCollapse_"+iSectionId).toggleClass("open");
|
||||
$("#Collapse_"+iSectionId).slideToggle("normal");
|
||||
e.preventDefault(); // we don't want to do anything more (see #1030 : a non wanted tab switching was triggered)
|
||||
});
|
||||
}
|
||||
EOD
|
||||
);
|
||||
}
|
||||
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '')
|
||||
{
|
||||
$this->add($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabLabel
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabLabel, $sHtml));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabLabel
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function SetCurrentTab($sTabLabel = '')
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTab($sTabLabel);
|
||||
@@ -1508,11 +1530,20 @@ EOD
|
||||
$this->add($this->m_oTabs->AddAjaxTab($sTabLabel, $sUrl, $bCache));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_oTabs->GetCurrentTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabLabel
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function RemoveTab($sTabLabel, $sTabContainer = null)
|
||||
{
|
||||
$this->m_oTabs->RemoveTab($sTabLabel, $sTabContainer);
|
||||
@@ -1521,6 +1552,9 @@ EOD
|
||||
/**
|
||||
* Finds the tab whose title matches a given pattern
|
||||
*
|
||||
* @param string $sPattern
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed The name of the tab as a string or false if not found
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null)
|
||||
@@ -1533,49 +1567,21 @@ EOD
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabLabel
|
||||
*/
|
||||
public function SelectTab($sTabContainer, $sTabLabel)
|
||||
{
|
||||
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabLabel));
|
||||
}
|
||||
|
||||
public function StartCollapsibleSection(
|
||||
$sSectionLabel, $bOpenedByDefault = false, $sSectionStateStorageBusinessKey = ''
|
||||
) {
|
||||
$this->add($this->GetStartCollapsibleSection($sSectionLabel, $bOpenedByDefault,
|
||||
$sSectionStateStorageBusinessKey));
|
||||
}
|
||||
|
||||
private function GetStartCollapsibleSection(
|
||||
$sSectionLabel, $bOpenedByDefault = false, $sSectionStateStorageBusinessKey = ''
|
||||
) {
|
||||
$this->bHasCollapsibleSection = true;
|
||||
$sHtml = '';
|
||||
static $iSectionId = 0;
|
||||
$sHtml .= '<a id="LnkCollapse_'.$iSectionId.'" class="CollapsibleLabel" href="#">'.$sSectionLabel.'</a></br>'."\n";
|
||||
$sHtml .= '<div id="Collapse_'.$iSectionId.'" style="display:none">'."\n";
|
||||
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$sSectionStateStorageKey = $oConfig->GetItopInstanceid().'/'.$sSectionStateStorageBusinessKey.'/collapsible-'.$iSectionId;
|
||||
$sSectionStateStorageKey = json_encode($sSectionStateStorageKey);
|
||||
$sOpenedByDefault = ($bOpenedByDefault) ? 'true' : 'false';
|
||||
$this->add_ready_script("initCollapsibleSection($iSectionId, $sOpenedByDefault, '$sSectionStateStorageKey');");
|
||||
|
||||
$iSectionId++;
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
public function EndCollapsibleSection()
|
||||
{
|
||||
$this->add($this->GetEndCollapsibleSection());
|
||||
}
|
||||
|
||||
public function GetEndCollapsibleSection()
|
||||
{
|
||||
return "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add($sHtml)
|
||||
{
|
||||
if (($this->m_oTabs->GetCurrentTabContainer() != '') && ($this->m_oTabs->GetCurrentTab() != ''))
|
||||
@@ -1641,15 +1647,21 @@ EOD
|
||||
|
||||
/**
|
||||
* Set the message to be displayed in the 'app-banner' section at the top of the page
|
||||
*
|
||||
* @param string $sHtmlMessage
|
||||
*/
|
||||
public function SetMessage($sHtmlMessage)
|
||||
{
|
||||
$sHtmlIcon = '<span class="fa fa-comment fa-1x"></span>';
|
||||
$sHtmlIcon = '<span class="fas fa-comment fa-1x"></span>';
|
||||
$this->AddApplicationMessage($sHtmlMessage, $sHtmlIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add message to be displayed in the 'app-banner' section at the top of the page
|
||||
*
|
||||
* @param string $sHtmlMessage
|
||||
* @param string|null $sHtmlIcon
|
||||
* @param string|null $sTip
|
||||
*/
|
||||
public function AddApplicationMessage($sHtmlMessage, $sHtmlIcon = null, $sTip = null)
|
||||
{
|
||||
@@ -1670,6 +1682,7 @@ EOD
|
||||
* @param string $sContent
|
||||
* @param string $sCssClasses CSS classes to add to the container
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 2.6
|
||||
*/
|
||||
public function AddHeaderMessage($sContent, $sCssClasses = 'message_info')
|
||||
@@ -1683,6 +1696,8 @@ EOF
|
||||
/**
|
||||
* Adds a script to be executed when the DOM is ready (typical JQuery use), right before add_ready_script
|
||||
*
|
||||
* @param string $sScript
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_init_script($sScript)
|
||||
|
||||
124
application/loginbasic.class.inc.php
Normal file
124
application/loginbasic.class.inc.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* Class LoginBasic
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class LoginBasic extends AbstractLoginFSMExtension
|
||||
{
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('basic');
|
||||
}
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
}
|
||||
elseif (isset($_SERVER['PHP_AUTH_USER']))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'basic';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
list($sAuthUser) = $this->GetAuthUserAndPassword();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
LoginWebPage::HTTP401Error();
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'basic')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
private function GetAuthUserAndPassword()
|
||||
{
|
||||
$sAuthUser = '';
|
||||
$sAuthPwd = null;
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
|
||||
{
|
||||
list($sAuthUser, $sAuthPwd) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($_SERVER['PHP_AUTH_USER']))
|
||||
{
|
||||
$sAuthUser = $_SERVER['PHP_AUTH_USER'];
|
||||
// Unfortunately, the RFC is not clear about the encoding...
|
||||
// IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8
|
||||
// So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base
|
||||
if (!LoginWebPage::LooksLikeUTF8($sAuthUser))
|
||||
{
|
||||
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
|
||||
// Supposed to be harmless in case of a plain ASCII string...
|
||||
$sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser);
|
||||
}
|
||||
$sAuthPwd = $_SERVER['PHP_AUTH_PW'];
|
||||
if (!LoginWebPage::LooksLikeUTF8($sAuthPwd))
|
||||
{
|
||||
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
|
||||
// Supposed to be harmless in case of a plain ASCII string...
|
||||
$sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return array($sAuthUser, $sAuthPwd);
|
||||
}
|
||||
}
|
||||
129
application/logindefault.class.inc.php
Normal file
129
application/logindefault.class.inc.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class LoginDefaultBefore
|
||||
*/
|
||||
class LoginDefaultBefore extends AbstractLoginFSMExtension
|
||||
{
|
||||
/**
|
||||
* Must be executed before the other login plugins
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('before');
|
||||
}
|
||||
|
||||
protected function OnStart(&$iErrorCode)
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_OK;
|
||||
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
|
||||
// Check if proposed login mode is present and allowed
|
||||
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
|
||||
$sProposedLoginMode = utils::ReadParam('login_mode', '');
|
||||
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
|
||||
if ($index !== false)
|
||||
{
|
||||
// Force login mode
|
||||
$_SESSION['login_mode'] = $sProposedLoginMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
// Check if proposed login mode is present and allowed
|
||||
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
|
||||
$sProposedLoginMode = utils::ReadParam('login_mode', '');
|
||||
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
|
||||
if ($index !== false)
|
||||
{
|
||||
// Force login mode
|
||||
LoginWebPage::SetLoginModeAndReload($sProposedLoginMode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class LoginDefaultAfter
|
||||
*/
|
||||
class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExtension
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Must be executed after the other login plugins
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('after');
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
self::ResetLoginSession();
|
||||
$iOnExit = LoginWebPage::getIOnExit();
|
||||
if ($iOnExit == LoginWebPage::EXIT_RETURN)
|
||||
{
|
||||
return LoginWebPage::LOGIN_FSM_RETURN; // Error, exit FSM
|
||||
}
|
||||
elseif ($iOnExit == LoginWebPage::EXIT_HTTP_401)
|
||||
{
|
||||
LoginWebPage::HTTP401Error(); // Error, exit
|
||||
}
|
||||
// LoginWebPage::EXIT_PROMPT
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOk(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
// If no plugin validated the user, exit
|
||||
self::ResetLoginSession();
|
||||
exit();
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all actions to log out properly
|
||||
*/
|
||||
public function LogoutAction()
|
||||
{
|
||||
self::ResetLoginSession();
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
unset($_SESSION['login_temp_auth_user']);
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
// Hard reset of the session
|
||||
private static function ResetLoginSession()
|
||||
{
|
||||
LoginWebPage::ResetSession();
|
||||
foreach (array_keys($_SESSION) as $sKey)
|
||||
{
|
||||
if (utils::StartsWith($sKey, 'login_'))
|
||||
{
|
||||
unset($_SESSION[$sKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
application/loginexternal.class.inc.php
Normal file
80
application/loginexternal.class.inc.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class LoginExternal
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class LoginExternal extends AbstractLoginFSMExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('external');
|
||||
}
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']))
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if ($sAuthUser && (strlen($sAuthUser) > 0))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'external';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$sAuthUser = $this->GetAuthUser();
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'external')
|
||||
{
|
||||
$_SESSION['can_logoff'] = false;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function GetAuthUser()
|
||||
{
|
||||
$sExtAuthVar = MetaModel::GetConfig()->GetExternalAuthenticationVariable(); // In which variable is the info passed ?
|
||||
eval('$sAuthUser = isset('.$sExtAuthVar.') ? '.$sExtAuthVar.' : false;'); // Retrieve the value
|
||||
/** @var string $sAuthUser */
|
||||
return $sAuthUser; // Retrieve the value
|
||||
}
|
||||
}
|
||||
138
application/loginform.class.inc.php
Normal file
138
application/loginform.class.inc.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class LoginForm
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
|
||||
{
|
||||
private $bForceFormOnError = false;
|
||||
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('form');
|
||||
}
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form'))
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
|
||||
{
|
||||
if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER))
|
||||
{
|
||||
// X-Combodo-Ajax is a special header automatically added to all ajax requests
|
||||
// Let's reply that we're currently logged-out
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
exit;
|
||||
}
|
||||
|
||||
// No credentials yet, display the form
|
||||
$oPage = LoginWebPage::NewLoginWebPage();
|
||||
$oPage->DisplayLoginForm($this->bForceFormOnError);
|
||||
$oPage->output();
|
||||
$this->bForceFormOnError = false;
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['login_temp_auth_user'] = $sAuthUser;
|
||||
$_SESSION['login_mode'] = 'form';
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
if (isset($_SESSION['auth_user']))
|
||||
{
|
||||
// If FSM reenter this state (example 2FA) then the auth_user is not resubmitted
|
||||
$sAuthUser = $_SESSION['auth_user'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
|
||||
}
|
||||
// Store 'auth_user' in session for further use
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
$this->bForceFormOnError = true;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'form')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoginTwigContext
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetTwigContext()
|
||||
{
|
||||
$oLoginContext = new LoginTwigContext();
|
||||
$oLoginContext->AddPostedVar('auth_user');
|
||||
$oLoginContext->AddPostedVar('auth_pwd');
|
||||
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data');
|
||||
|
||||
$aData = array(
|
||||
'sAuthUser' => $sAuthUser,
|
||||
'sAuthPwd' => $sAuthPwd,
|
||||
);
|
||||
$oLoginContext->AddBlockExtension('login_input', new LoginBlockExtension('extensionblock/loginforminput.html.twig', $aData));
|
||||
$oLoginContext->AddBlockExtension('login_submit', new LoginBlockExtension('extensionblock/loginformsubmit.html.twig'));
|
||||
$oLoginContext->AddBlockExtension('login_form_footer', new LoginBlockExtension('extensionblock/loginformfooter.html.twig'));
|
||||
|
||||
$bEnableResetPassword = empty(MetaModel::GetConfig()->Get('forgot_password')) ? true : MetaModel::GetConfig()->Get('forgot_password');
|
||||
$sResetPasswordUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?loginop=forgot_pwd';
|
||||
$aData = array(
|
||||
'bEnableResetPassword' => $bEnableResetPassword,
|
||||
'sResetPasswordUrl' => $sResetPasswordUrl,
|
||||
);
|
||||
$oLoginContext->AddBlockExtension('login_links', new LoginBlockExtension('extensionblock/loginformlinks.html.twig', $aData));
|
||||
|
||||
return $oLoginContext;
|
||||
}
|
||||
}
|
||||
321
application/logintwig.class.inc.php
Normal file
321
application/logintwig.class.inc.php
Normal file
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
use Combodo\iTop\TwigExtension;
|
||||
|
||||
/**
|
||||
* Twig context for modules extending the login screen
|
||||
* Class LoginTwigContext
|
||||
*/
|
||||
class LoginTwigContext
|
||||
{
|
||||
/** @var array */
|
||||
private $aBlockExtension;
|
||||
/** @var array */
|
||||
private $aPostedVars;
|
||||
/** @var string */
|
||||
private $sTwigLoaderPath;
|
||||
/** @var array */
|
||||
private $aCSSFiles;
|
||||
/** @var array */
|
||||
private $aJsFiles;
|
||||
private $sTwigNameSpace;
|
||||
|
||||
/**
|
||||
* Build a context to display the twig files used
|
||||
* to extend the login screens
|
||||
*
|
||||
* LoginTwigContext constructor.
|
||||
* @api
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->aBlockExtension = array();
|
||||
$this->aPostedVars = array();
|
||||
$this->sTwigLoaderPath = null;
|
||||
$this->aCSSFiles = array();
|
||||
$this->aJsFiles = array();
|
||||
$this->sTwigNameSpace = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the absolute path on disk of the folder containing the twig templates
|
||||
*
|
||||
* @param string $sPath absolute path of twig templates directory
|
||||
* @api
|
||||
*/
|
||||
public function SetLoaderPath($sPath)
|
||||
{
|
||||
$this->sTwigLoaderPath = $sPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Twig block extension
|
||||
*
|
||||
* @param string $sBlockName
|
||||
* @param LoginBlockExtension $oBlockExtension
|
||||
*/
|
||||
public function AddBlockExtension($sBlockName, $oBlockExtension)
|
||||
{
|
||||
$this->aBlockExtension[$sBlockName] = $oBlockExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a variable intended to be posted on URL (and managed) by the module.
|
||||
* Declaring the posted variables will prevent the core engine to manipulate these variables.
|
||||
*
|
||||
* @param string $sPostedVar Name of the posted variable
|
||||
* @api
|
||||
*/
|
||||
public function AddPostedVar($sPostedVar)
|
||||
{
|
||||
$this->aPostedVars[] = $sPostedVar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the URL of a CSS file to link to the login screen
|
||||
*
|
||||
* @param string $sFile URL of the CSS file to link
|
||||
* @api
|
||||
*/
|
||||
public function AddCSSFile($sFile)
|
||||
{
|
||||
$this->aCSSFiles[] = $sFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the URL of a javascript file to link to the login screen
|
||||
* @param string $sFile URL of the javascript file to link
|
||||
* @api
|
||||
*/
|
||||
public function AddJsFile($sFile)
|
||||
{
|
||||
$this->aJsFiles[] = $sFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sBlockName
|
||||
*
|
||||
* @return \LoginBlockExtension
|
||||
*/
|
||||
public function GetBlockExtension($sBlockName)
|
||||
{
|
||||
/** @var LoginBlockExtension $oBlockExtension */
|
||||
$oBlockExtension = isset($this->aBlockExtension[$sBlockName]) ? $this->aBlockExtension[$sBlockName] : null;
|
||||
return $oBlockExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetPostedVars()
|
||||
{
|
||||
return $this->aPostedVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetTwigLoaderPath()
|
||||
{
|
||||
return $this->sTwigLoaderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetCSSFiles()
|
||||
{
|
||||
return $this->aCSSFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetJsFiles()
|
||||
{
|
||||
return $this->aJsFiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig block description for login screen extension
|
||||
* The login screen can be extended by adding twig templates
|
||||
* to specific blocks of the login screens
|
||||
*
|
||||
* Class LoginBlockExtension
|
||||
*/
|
||||
class LoginBlockExtension
|
||||
{
|
||||
private $sTwig;
|
||||
private $aData;
|
||||
|
||||
/**
|
||||
* Create a new twig extension block
|
||||
* The given twig template can be HTML, CSS or JavaScript.
|
||||
* CSS goes to the block named 'css' and is inline in the page.
|
||||
* JavaScript goes to the blocks named 'script' or 'ready_script' and are inline in the page.
|
||||
* HTML goes to everywhere else
|
||||
*
|
||||
* LoginBlockExtension constructor.
|
||||
*
|
||||
* @param string $sTwig name of the twig file relative to the path given to the LoginTwigContext
|
||||
* @param array $aData Data given to the twig template (into the variable {{ aData }})
|
||||
* @api
|
||||
*/
|
||||
public function __construct($sTwig, $aData = array())
|
||||
{
|
||||
$this->sTwig = $sTwig;
|
||||
$this->aData = $aData;
|
||||
}
|
||||
|
||||
public function GetTwig()
|
||||
{
|
||||
return $this->sTwig;
|
||||
}
|
||||
|
||||
public function GetData()
|
||||
{
|
||||
return $this->aData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by LoginWebPage to display the login screen
|
||||
* Class LoginTwigRenderer
|
||||
*/
|
||||
class LoginTwigRenderer
|
||||
{
|
||||
private $aLoginPluginList;
|
||||
private $aPluginFormData;
|
||||
private $aPostedVars;
|
||||
private $oTwig;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->aLoginPluginList = LoginWebPage::GetLoginPluginList('iLoginUIExtension', false);
|
||||
$this->aPluginFormData = array();
|
||||
$aTwigLoaders = array();
|
||||
$this->aPostedVars = array();
|
||||
foreach ($this->aLoginPluginList as $oLoginPlugin)
|
||||
{
|
||||
/** @var \iLoginUIExtension $oLoginPlugin */
|
||||
$oLoginContext = $oLoginPlugin->GetTwigContext();
|
||||
if (is_null($oLoginContext))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$this->aPluginFormData[] = $oLoginContext;
|
||||
$sTwigLoaderPath = $oLoginContext->GetTwigLoaderPath();
|
||||
if ($sTwigLoaderPath != null)
|
||||
{
|
||||
$oExtensionLoader = new Twig_Loader_Filesystem();
|
||||
$oExtensionLoader->setPaths($sTwigLoaderPath);
|
||||
$aTwigLoaders[] = $oExtensionLoader;
|
||||
}
|
||||
$this->aPostedVars = array_merge($this->aPostedVars, $oLoginContext->GetPostedVars());
|
||||
}
|
||||
|
||||
$oCoreLoader = new Twig_Loader_Filesystem(array(), APPROOT.'templates');
|
||||
$aCoreTemplatesPaths = array('login', 'login/password');
|
||||
// Having this path declared after the plugins let the plugins replace the core templates
|
||||
$oCoreLoader->setPaths($aCoreTemplatesPaths);
|
||||
// Having the core templates accessible within a different namespace offer the possibility to extend them while replacing them
|
||||
$oCoreLoader->setPaths($aCoreTemplatesPaths, 'ItopCore');
|
||||
$aTwigLoaders[] = $oCoreLoader;
|
||||
|
||||
$oLoader = new Twig_Loader_Chain($aTwigLoaders);
|
||||
$this->oTwig = new Twig_Environment($oLoader);
|
||||
TwigExtension::RegisterTwigExtensions($this->oTwig);
|
||||
}
|
||||
|
||||
public function GetDefaultVars()
|
||||
{
|
||||
$sLogo = 'itop-logo-external.png';
|
||||
$sBrandingLogo = 'login-logo.png';
|
||||
|
||||
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
|
||||
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo))
|
||||
{
|
||||
$sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo.'?t='.utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
|
||||
$aVars = array(
|
||||
'sAppRootUrl' => utils::GetAbsoluteUrlAppRoot(),
|
||||
'aPluginFormData' => $this->GetPluginFormData(),
|
||||
'sItopVersion' => ITOP_VERSION,
|
||||
'sVersionShort' => $sVersionShort,
|
||||
'sIconUrl' => $sIconUrl,
|
||||
'sDisplayIcon' => $sDisplayIcon,
|
||||
);
|
||||
|
||||
return $aVars;
|
||||
}
|
||||
|
||||
public function Render(NiceWebPage $oPage, $sTwigFile, $aVars = array())
|
||||
{
|
||||
$oTemplate = $this->GetTwig()->load($sTwigFile);
|
||||
$oPage->add($oTemplate->renderBlock('body', $aVars));
|
||||
$oPage->add_script($oTemplate->renderBlock('script', $aVars));
|
||||
$oPage->add_ready_script($oTemplate->renderBlock('ready_script', $aVars));
|
||||
$oPage->add_style($oTemplate->renderBlock('css', $aVars));
|
||||
|
||||
// Render CSS links
|
||||
foreach ($this->aPluginFormData as $oFormData)
|
||||
{
|
||||
/** @var \LoginTwigContext $oFormData */
|
||||
$aCSSFiles = $oFormData->GetCSSFiles();
|
||||
foreach ($aCSSFiles as $sCSSFile)
|
||||
{
|
||||
$oPage->add_linked_stylesheet($sCSSFile);
|
||||
}
|
||||
$aJsFiles = $oFormData->GetJsFiles();
|
||||
foreach ($aJsFiles as $sJsFile)
|
||||
{
|
||||
$oPage->add_linked_script($sJsFile);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetLoginPluginList()
|
||||
{
|
||||
return $this->aLoginPluginList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetPluginFormData()
|
||||
{
|
||||
return $this->aPluginFormData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetPostedVars()
|
||||
{
|
||||
return $this->aPostedVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Twig_Environment
|
||||
*/
|
||||
public function GetTwig()
|
||||
{
|
||||
return $this->oTwig;
|
||||
}
|
||||
}
|
||||
93
application/loginurl.class.inc.php
Normal file
93
application/loginurl.class.inc.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class LoginURL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class LoginURL extends AbstractLoginFSMExtension
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bErrorOccurred = false;
|
||||
|
||||
/**
|
||||
* Return the list of supported login modes for this plugin
|
||||
*
|
||||
* @return array of supported login modes
|
||||
*/
|
||||
public function ListSupportedLoginModes()
|
||||
{
|
||||
return array('url');
|
||||
}
|
||||
|
||||
protected function OnModeDetection(&$iErrorCode)
|
||||
{
|
||||
if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred)
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (!empty($sAuthUser) && !empty($sAuthPwd))
|
||||
{
|
||||
$_SESSION['login_mode'] = 'url';
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnReadCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$_SESSION['login_temp_auth_user'] = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCheckCredentials(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
|
||||
{
|
||||
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
|
||||
return LoginWebPage::LOGIN_FSM_ERROR;
|
||||
}
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnCredentialsOK(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
|
||||
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnError(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$this->bErrorOccurred = true;
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
|
||||
protected function OnConnected(&$iErrorCode)
|
||||
{
|
||||
if ($_SESSION['login_mode'] == 'url')
|
||||
{
|
||||
$_SESSION['can_logoff'] = true;
|
||||
return LoginWebPage::CheckLoggedUser($iErrorCode);
|
||||
}
|
||||
return LoginWebPage::LOGIN_FSM_CONTINUE;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
93
application/maintenancemsg.php
Normal file
93
application/maintenancemsg.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Maintenance message display functions
|
||||
// Only included by approot.inc.php
|
||||
//
|
||||
|
||||
/**
|
||||
* Use a setup page to display the maintenance message
|
||||
* @param $sTitle
|
||||
* @param $sMessage
|
||||
*/
|
||||
function _MaintenanceSetupPageMessage($sTitle, $sMessage)
|
||||
{
|
||||
// Web Page
|
||||
@include_once(APPROOT.'setup/setuppage.class.inc.php');
|
||||
if (class_exists('SetupPage'))
|
||||
{
|
||||
$oP = new SetupPage($sTitle);
|
||||
$oP->p("<h2 class=\"center\">$sMessage</h2>");
|
||||
$oP->add_ready_script(
|
||||
<<<JS
|
||||
// Reload in 30s to check if maintenance is over
|
||||
setTimeout(function(){ window.location.reload(); }, 30000);
|
||||
JS
|
||||
|
||||
);
|
||||
$oP->output();
|
||||
}
|
||||
else
|
||||
{
|
||||
_MaintenanceTextMessage($sMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use simple text to display the maintenance message
|
||||
* @param $sMessage
|
||||
*/
|
||||
function _MaintenanceTextMessage($sMessage)
|
||||
{
|
||||
echo $sMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a simple HTML to display the maintenance message
|
||||
* @param $sMessage
|
||||
*/
|
||||
function _MaintenanceHtmlMessage($sMessage)
|
||||
{
|
||||
echo '<html><body><div>'.$sMessage.'</div></body></html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a simple JSON to display the maintenance message
|
||||
*
|
||||
* @param $sTitle
|
||||
* @param $sMessage
|
||||
*/
|
||||
function _MaintenanceJsonMessage($sTitle, $sMessage)
|
||||
{
|
||||
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
|
||||
if (class_exists('ajax_page'))
|
||||
{
|
||||
$oP = new ajax_page($sTitle);
|
||||
$oP->add_header('Access-Control-Allow-Origin: *');
|
||||
$oP->SetContentType('application/json');
|
||||
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
|
||||
$oP->Output();
|
||||
}
|
||||
else
|
||||
{
|
||||
_MaintenanceTextMessage($sMessage);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,20 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Construction and display of the application's main menu
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2016 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/utils.inc.php');
|
||||
@@ -201,7 +194,7 @@ class ApplicationMenu
|
||||
|
||||
/**
|
||||
* Entry point to display the whole menu into the web page, used by iTopWebPage
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param \WebPage $oPage
|
||||
* @param $aExtraParams
|
||||
* @throws DictExceptionMissingString
|
||||
*/
|
||||
@@ -217,7 +210,7 @@ class ApplicationMenu
|
||||
{
|
||||
if (!self::CanDisplayMenu($aMenu)) { continue; }
|
||||
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
||||
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$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('<ul>');
|
||||
$aChildren = self::GetChildren($aMenu['index']);
|
||||
@@ -270,7 +263,7 @@ EOF
|
||||
|
||||
/**
|
||||
* Handles the display of the sub-menus (called recursively if necessary)
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param \WebPage $oPage
|
||||
* @param array $aMenus
|
||||
* @param array $aExtraParams
|
||||
* @param int $iActiveMenu
|
||||
@@ -284,21 +277,39 @@ EOF
|
||||
usort($aMenus, array('ApplicationMenu', 'CompareOnRank'));
|
||||
foreach($aMenus as $aMenu)
|
||||
{
|
||||
if (!self::CanDisplayMenu($aMenu))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$index = $aMenu['index'];
|
||||
$oMenu = self::GetMenuNode($index);
|
||||
if ($oMenu->IsEnabled())
|
||||
{
|
||||
$aChildren = self::GetChildren($index);
|
||||
$sCSSClass = (count($aChildren) > 0) ? ' class="submenu"' : '';
|
||||
$aCSSClasses = array('navigation-menu-item');
|
||||
if (count($aChildren) > 0)
|
||||
{
|
||||
$aCSSClasses[] = 'submenu';
|
||||
}
|
||||
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
|
||||
$sItemHtml = '<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" class="'.implode(' ', $aCSSClasses).'" data-menu-id="'.$oMenu->GetMenuID().'">';
|
||||
if ($sHyperlink != '')
|
||||
{
|
||||
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" '.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
|
||||
$sLinkTarget = '';
|
||||
if ($oMenu->IsHyperLinkInNewWindow())
|
||||
{
|
||||
$sLinkTarget .= ' target="_blank"';
|
||||
}
|
||||
$sURL = '"'.$oMenu->GetHyperlink($aExtraParams).'"'.$sLinkTarget;
|
||||
$sTitle = $oMenu->GetTitle();
|
||||
$sItemHtml .= "<a href={$sURL}>{$sTitle}</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'" '.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
|
||||
$sItemHtml .= $oMenu->GetTitle();
|
||||
}
|
||||
$sItemHtml .= '</li>';
|
||||
$oPage->AddToMenu($sItemHtml);
|
||||
if ($iActiveMenu == $index)
|
||||
{
|
||||
$bActive = true;
|
||||
@@ -599,13 +610,24 @@ abstract class MenuNode
|
||||
|
||||
/**
|
||||
* @param $aExtraParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetHyperlink($aExtraParams)
|
||||
{
|
||||
$aExtraParams['c[menu]'] = $this->GetMenuId();
|
||||
return $this->AddParams(utils::GetAbsoluteUrlAppRoot().'pages/UI.php', $aExtraParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool true if the link should be opened in a new window
|
||||
* @since 2.7.0 N°1283
|
||||
*/
|
||||
public function IsHyperLinkInNewWindow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a limiting display condition for the same menu node. The conditions will be combined with a AND
|
||||
@@ -966,7 +988,7 @@ class SearchMenuNode extends MenuNode
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
|
||||
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', utils::GetAbsoluteUrlAppRoot().'images/search.png');
|
||||
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png');
|
||||
|
||||
$oSearch = new DBObjectSearch($this->sClass);
|
||||
$aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
|
||||
@@ -989,8 +1011,12 @@ class WebPageMenuNode extends MenuNode
|
||||
*/
|
||||
protected $sHyperlink;
|
||||
|
||||
/** @var bool */
|
||||
protected $bIsLinkInNewWindow;
|
||||
|
||||
/**
|
||||
* Create a menu item that points to any web page (not only UI.php)
|
||||
*
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
* @param string $sHyperlink URL to the page to load. Use relative URL if you want to keep the application portable !
|
||||
* @param integer $iParentIndex ID of the parent menu
|
||||
@@ -999,12 +1025,17 @@ class WebPageMenuNode extends MenuNode
|
||||
* @param integer $iActionCode Either UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_DELETE, UR_ACTION_BULKREAD, UR_ACTION_BULKMODIFY or UR_ACTION_BULKDELETE
|
||||
* @param integer $iAllowedResults Expected "rights" for the action: either UR_ALLOWED_YES, UR_ALLOWED_NO, UR_ALLOWED_DEPENDS or a mix of them...
|
||||
* @param string $sEnableStimulus
|
||||
* @param bool $bIsLinkInNewWindow for the {@link WebPageMenuNode::IsHyperLinkInNewWindow} method
|
||||
*/
|
||||
public function __construct($sMenuId, $sHyperlink, $iParentIndex, $fRank = 0.0, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
|
||||
public function __construct(
|
||||
$sMenuId, $sHyperlink, $iParentIndex, $fRank = 0.0, $sEnableClass = null, $iActionCode = null,
|
||||
$iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null, $bIsLinkInNewWindow = false
|
||||
)
|
||||
{
|
||||
parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
|
||||
$this->sHyperlink = $sHyperlink;
|
||||
$this->aReflectionProperties['url'] = $sHyperlink;
|
||||
$this->bIsLinkInNewWindow = $bIsLinkInNewWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1017,6 +1048,11 @@ class WebPageMenuNode extends MenuNode
|
||||
return $this->AddParams( $this->sHyperlink, $aExtraParams);
|
||||
}
|
||||
|
||||
public function IsHyperLinkInNewWindow()
|
||||
{
|
||||
return $this->bIsLinkInNewWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebPage $oPage
|
||||
* @param array $aExtraParams
|
||||
|
||||
@@ -37,17 +37,16 @@ class NiceWebPage extends WebPage
|
||||
{
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
$this->m_aReadyScripts = array();
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-3.3.1.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.min.js');
|
||||
if(utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
|
||||
{
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.dev.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev.js');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.prod.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.prod.min.js');
|
||||
}
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/ui-lightness/jquery-ui-1.11.4.custom.css');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/hovertip.js');
|
||||
// table sorting
|
||||
@@ -75,6 +74,8 @@ class NiceWebPage extends WebPage
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_abstract.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_time.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/clipboard.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/clipboardwidget.js');
|
||||
|
||||
$this->add_dict_entries('UI:Combo');
|
||||
|
||||
@@ -122,7 +123,7 @@ class NiceWebPage extends WebPage
|
||||
$("table.listResults").tableHover(); // hover tables
|
||||
EOF
|
||||
);
|
||||
$this->add_saas("css/light-grey.scss");
|
||||
$this->LoadTheme();
|
||||
|
||||
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
|
||||
$sAbsURLAppRoot = addslashes($this->m_sRootUrl);
|
||||
@@ -232,7 +233,8 @@ EOF
|
||||
foreach($aChoices as $sKey => $sValue)
|
||||
{
|
||||
$sSelected = ($sKey == $sDefaultValue) ? " SELECTED" : "";
|
||||
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"".htmlspecialchars($sKey)."\"$sSelected>".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."</option>");
|
||||
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"".htmlspecialchars($sKey)."\"$sSelected>".htmlentities($sValue,
|
||||
ENT_QUOTES, self::PAGES_CHARSET)."</option>");
|
||||
}
|
||||
$this->add("</select>");
|
||||
}
|
||||
@@ -254,6 +256,10 @@ EOF
|
||||
}
|
||||
parent::output();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
protected function LoadTheme()
|
||||
{
|
||||
$sCssThemeUrl = ThemeHandler::GetTheme();
|
||||
$this->add_linked_stylesheet($sCssThemeUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,53 @@
|
||||
<?php
|
||||
require_once(APPROOT.'lib/tcpdf/tcpdf.php');
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
require_once(APPROOT.'application/utils.inc.php');
|
||||
|
||||
/**
|
||||
* Custom class derived from TCPDF for providing custom headers and footers
|
||||
*
|
||||
* @author denis
|
||||
*
|
||||
*/
|
||||
class iTopPDF extends TCPDF
|
||||
{
|
||||
protected $sDocumentTitle;
|
||||
|
||||
|
||||
/**
|
||||
* Shortcut for {@link TCPDF::SetFont}, to use the font configured
|
||||
*
|
||||
* @param string $style
|
||||
* @param int $size
|
||||
* @param string $fontfile
|
||||
* @param string $subset
|
||||
* @param bool $out
|
||||
*
|
||||
* @uses \TCPDF::SetFont()
|
||||
* @uses \iTopPDF::GetPdfFont()
|
||||
* @since 2.7
|
||||
*/
|
||||
public function SetFontParams($style, $size, $fontfile='', $subset='default', $out=true)
|
||||
{
|
||||
$siTopFont = self::GetPdfFont();
|
||||
$this->SetFont($siTopFont, $style, $size, $fontfile, $subset, $out);
|
||||
}
|
||||
|
||||
public function SetDocumentTitle($sDocumentTitle)
|
||||
{
|
||||
$this->sDocumentTitle = $sDocumentTitle;
|
||||
@@ -17,26 +55,29 @@ class iTopPDF extends TCPDF
|
||||
|
||||
/**
|
||||
* Builds the custom header. Called for each new page.
|
||||
*
|
||||
* @see TCPDF::Header()
|
||||
*/
|
||||
public function Header()
|
||||
{
|
||||
// Title
|
||||
// Set font
|
||||
$this->SetFont('dejavusans', 'B', 10);
|
||||
|
||||
$this->SetFontParams('B', 10);
|
||||
|
||||
$iPageNumberWidth = 25;
|
||||
$aMargins = $this->getMargins();
|
||||
|
||||
|
||||
// Display the title (centered)
|
||||
$this->SetXY($aMargins['left'] + $iPageNumberWidth, 0);
|
||||
$this->MultiCell($this->getPageWidth() - $aMargins['left'] - $aMargins['right'] - 2*$iPageNumberWidth, 15, $this->sDocumentTitle, 0, 'C', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
$this->SetFont('dejavusans', '', 10);
|
||||
|
||||
$this->MultiCell($this->getPageWidth() - $aMargins['left'] - $aMargins['right'] - 2 * $iPageNumberWidth, 15, $this->sDocumentTitle,
|
||||
0, 'C', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
$this->SetFontParams('', 10);
|
||||
|
||||
// Display the page number (right aligned)
|
||||
// Warning: the 'R'ight alignment does not work when using placeholders like $this->getAliasNumPage() or $this->getAliasNbPages()
|
||||
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber' ,$this->page), 0, 'R', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
|
||||
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber', $this->page), 0, 'R', false, 0 /* $ln */, '',
|
||||
'', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
|
||||
// Branding logo
|
||||
$sBrandingIcon = APPROOT.'images/itop-logo.png';
|
||||
if (file_exists(MODULESROOT.'branding/main-logo.png'))
|
||||
@@ -51,6 +92,18 @@ class iTopPDF extends TCPDF
|
||||
{
|
||||
// No footer
|
||||
}
|
||||
|
||||
/**
|
||||
* dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
* @return string font in the config file (export_pdf_font)
|
||||
*/
|
||||
public static function GetPdfFont()
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$sPdfFont = $oConfig->Get('export_pdf_font');
|
||||
|
||||
return $sPdfFont;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,49 +111,45 @@ class iTopPDF extends TCPDF
|
||||
*/
|
||||
class PDFPage extends WebPage
|
||||
{
|
||||
/**
|
||||
* Instance of the TCPDF object for creating the PDF
|
||||
* @var TCPDF
|
||||
*/
|
||||
/** @var \iTopPDF Instance of the TCPDF object for creating the PDF */
|
||||
protected $oPdf;
|
||||
|
||||
|
||||
public function __construct($s_title, $sPageFormat = 'A4', $sPageOrientation = 'L')
|
||||
{
|
||||
parent::__construct($s_title);
|
||||
define(K_PATH_FONTS, APPROOT.'lib/tcpdf/fonts');
|
||||
$this->oPdf = new iTopPDF($sPageOrientation, 'mm', $sPageFormat, true, 'UTF-8', false);
|
||||
|
||||
define(K_PATH_FONTS, APPROOT.'lib/combodo/tcpdf/fonts');
|
||||
$this->oPdf = new iTopPDF($sPageOrientation, 'mm', $sPageFormat, true, self::PAGES_CHARSET, false);
|
||||
|
||||
// set document information
|
||||
$this->oPdf->SetCreator(PDF_CREATOR);
|
||||
$this->oPdf->SetAuthor('iTop');
|
||||
$this->oPdf->SetTitle($s_title);
|
||||
$this->oPdf->SetDocumentTitle($s_title);
|
||||
|
||||
|
||||
$this->oPdf->setFontSubsetting(true);
|
||||
|
||||
// Set font
|
||||
|
||||
// dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
$this->oPdf->SetFont('dejavusans', '', 10, '', true);
|
||||
|
||||
$this->oPdf->SetFontParams('', 10, '', true);
|
||||
|
||||
// set auto page breaks
|
||||
$this->oPdf->SetAutoPageBreak(true, 15); // 15 mm break margin at the bottom
|
||||
$this->oPdf->SetTopMargin(15);
|
||||
|
||||
|
||||
// Add a page, we're ready to start
|
||||
$this->oPdf->AddPage();
|
||||
|
||||
|
||||
$this->SetContentDisposition('inline', $s_title.'.pdf');
|
||||
$this->SetDefaultStyle();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a default style (suitable for printing) to be included each time $this->oPdf->writeHTML() is called
|
||||
*/
|
||||
protected function SetDefaultStyle()
|
||||
{
|
||||
$this->add_style(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
table {
|
||||
padding: 2pt;
|
||||
}
|
||||
@@ -124,19 +173,21 @@ td.icon {
|
||||
width: 30px;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get access to the underlying TCPDF object
|
||||
* @return TCPDF
|
||||
*
|
||||
* @return \iTopPDF
|
||||
*/
|
||||
public function get_tcpdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes the currently buffered HTML content into the PDF. This can be useful:
|
||||
* - to sync the flow in case you want to access the underlying TCPDF object for some specific/graphic output
|
||||
@@ -156,39 +207,42 @@ EOF
|
||||
$this->s_content = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether or not the page is a PDF page
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_pdf()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the PDF document and returns the PDF content as a string
|
||||
*
|
||||
* @return string
|
||||
* @see WebPage::output()
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$this->add_header('Content-type: application/x-pdf');
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$this->flush();
|
||||
}
|
||||
foreach ($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$this->flush();
|
||||
echo $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
}
|
||||
|
||||
|
||||
public function get_pdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -15,12 +15,15 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
* File to include to initialize the datamodel in memory
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -32,10 +35,16 @@ register_shutdown_function(function()
|
||||
$sReservedMemory = null;
|
||||
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR))
|
||||
{
|
||||
IssueLog::error($err['message']);
|
||||
if (strpos($err['message'], 'Allowed memory size of') !== false)
|
||||
{
|
||||
$sLimit = ini_get('memory_limit');
|
||||
echo "<p>iTop: Allowed memory size of $sLimit exhausted, contact your administrator to increase memory_limit in php.ini</p>\n";
|
||||
echo "<p>iTop: Allowed memory size of $sLimit exhausted, contact your administrator to increase 'memory_limit' in php.ini</p>\n";
|
||||
}
|
||||
elseif (strpos($err['message'], 'Maximum execution time') !== false)
|
||||
{
|
||||
$sLimit = ini_get('max_execution_time');
|
||||
echo "<p>iTop: Maximum execution time of $sLimit exceeded, contact your administrator to increase 'max_execution_time' in php.ini</p>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -44,9 +53,6 @@ register_shutdown_function(function()
|
||||
}
|
||||
});
|
||||
|
||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||
session_name('itop-'.md5(APPROOT));
|
||||
session_start();
|
||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||
@@ -79,4 +85,4 @@ else
|
||||
$_SESSION['itop_env'] = ITOP_DEFAULT_ENV;
|
||||
}
|
||||
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||
|
||||
@@ -399,6 +399,7 @@ class ObjectDetailsTemplate extends DisplayTemplate
|
||||
$aPlugInProperties = $aMatches[1];
|
||||
foreach($aPlugInProperties as $sPlugInClass)
|
||||
{
|
||||
/** @var \iApplicationUIExtension $oInstance */
|
||||
$oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass);
|
||||
if ($oInstance != null) // Safety check...
|
||||
{
|
||||
|
||||
74
application/themehandler.class.inc.php
Normal file
74
application/themehandler.class.inc.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* * Copyright (C) 2013-2019 Combodo SARL
|
||||
* *
|
||||
* * This file is part of iTop.
|
||||
* *
|
||||
* * iTop is free software; you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU Affero General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * iTop is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU Affero General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
|
||||
class ThemeHandler{
|
||||
|
||||
public static function GetTheme()
|
||||
{
|
||||
$sThemeId = MetaModel::GetConfig()->Get('backoffice_default_theme');
|
||||
$sEnvPath = APPROOT.'env-' . utils::GetCurrentEnvironment() .'/';
|
||||
$sThemePath = $sEnvPath.'/branding/themes/'.$sThemeId.'/';
|
||||
$aThemeParameters = json_decode(file_get_contents($sThemePath.'theme-parameters.json'), true);
|
||||
$sThemeCssPath = $sThemePath.'main.css';
|
||||
|
||||
$sTheme = '';
|
||||
$iStyleLastModified = 0;
|
||||
clearstatcache();
|
||||
// Loading files to import and stylesheet to compile, also getting most recent modification time on overall files
|
||||
foreach ($aThemeParameters['imports'] as $sImport)
|
||||
{
|
||||
$sTheme.= '@import "' . $sImport . '";' . "\n";
|
||||
|
||||
$iImportLastModified = filemtime($sEnvPath.$sImport);
|
||||
$iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified;
|
||||
}
|
||||
foreach ($aThemeParameters['stylesheets'] as $sStylesheet)
|
||||
{
|
||||
$sTheme.= '@import "' . $sStylesheet . '";'."\n";
|
||||
|
||||
$iStylesheetLastModified = filemtime($sEnvPath.$sStylesheet);
|
||||
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
|
||||
}
|
||||
|
||||
// Checking if our compiled css is outdated
|
||||
if (!file_exists($sThemeCssPath) || (is_writable($sThemePath) && (filemtime($sThemeCssPath) < $iStyleLastModified)))
|
||||
{
|
||||
$oScss = new Compiler();
|
||||
$oScss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\Expanded');
|
||||
// Setting our xml variables
|
||||
$oScss->setVariables($aThemeParameters['variables']);
|
||||
// Setting our import path to env-*
|
||||
$oScss->setImportPaths($sEnvPath);
|
||||
// Temporary disabling max exec time while compiling
|
||||
$iCurrentMaxExecTime = (int) ini_get('max_execution_time');
|
||||
set_time_limit(0);
|
||||
// Compiling our theme
|
||||
$sThemeCss = $oScss->compile($sTheme);
|
||||
set_time_limit($iCurrentMaxExecTime);
|
||||
file_put_contents($sThemePath.'main.css', $sThemeCss);
|
||||
}
|
||||
// Return absolute url to theme compiled css
|
||||
return utils::GetAbsoluteUrlModulesRoot().'/branding/themes/'.$sThemeId.'/main.css';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,9 +195,8 @@ class privUITransactionSession
|
||||
class privUITransactionFile
|
||||
{
|
||||
/**
|
||||
* Create a new transaction id, store it in the session and return its id
|
||||
* @param void
|
||||
* @return int The identifier of the new transaction
|
||||
* @return int The new transaction identifier
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function GetNewTransactionId()
|
||||
{
|
||||
@@ -207,7 +206,9 @@ class privUITransactionFile
|
||||
{
|
||||
throw new Exception('The directory "'.APPROOT.'data" must be writable to the application.');
|
||||
}
|
||||
if (!@mkdir(APPROOT.'data/transactions'))
|
||||
// condition avoids race condition N°2345
|
||||
// See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition
|
||||
if (!mkdir($concurrentDirectory = APPROOT.'data/transactions') && !is_dir($concurrentDirectory))
|
||||
{
|
||||
throw new Exception('Failed to create the directory "'.APPROOT.'data/transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
|
||||
}
|
||||
|
||||
140
application/twigextension.class.inc.php
Normal file
140
application/twigextension.class.inc.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop;
|
||||
|
||||
use AttributeDateTime;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Twig_Environment;
|
||||
use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
use utils;
|
||||
|
||||
class TwigExtension
|
||||
{
|
||||
/**
|
||||
* Registers Twig extensions such as filters or functions.
|
||||
* It allows us to access some stuff directly in twig.
|
||||
*
|
||||
* @param \Twig_Environment $oTwigEnv
|
||||
*/
|
||||
public static function RegisterTwigExtensions(Twig_Environment &$oTwigEnv)
|
||||
{
|
||||
// Filter to translate a string via the Dict::S function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_s }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('dict_s',
|
||||
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
|
||||
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
|
||||
})
|
||||
);
|
||||
|
||||
// Filter to format a string via the Dict::Format function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('dict_format',
|
||||
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
|
||||
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
|
||||
})
|
||||
);
|
||||
|
||||
// Filter to format output
|
||||
// example a DateTime is converted to user format
|
||||
// Usage in twig: {{ 'String:ToFormat'|output_format }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('date_format',
|
||||
function ($sDate) {
|
||||
try
|
||||
{
|
||||
if (preg_match('@^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$@', trim($sDate)))
|
||||
{
|
||||
return AttributeDateTime::GetFormat()->Format($sDate);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
}
|
||||
return $sDate;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
// Filter to format output
|
||||
// example a DateTime is converted to user format
|
||||
// Usage in twig: {{ 'String:ToFormat'|output_format }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('size_format',
|
||||
function ($sSize) {
|
||||
return utils::BytesToFriendlyFormat($sSize);
|
||||
})
|
||||
);
|
||||
|
||||
// Filter to enable base64 encode/decode
|
||||
// Usage in twig: {{ 'String to encode'|base64_encode }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('base64_encode', 'base64_encode'));
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('base64_decode', 'base64_decode'));
|
||||
|
||||
// Filter to enable json decode (encode already exists)
|
||||
// Usage in twig: {{ aSomeArray|json_decode }}
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('json_decode', function ($sJsonString, $bAssoc = false) {
|
||||
return json_decode($sJsonString, $bAssoc);
|
||||
})
|
||||
);
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?itopversion=".ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&itopversion=".ITOP_VERSION;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
|
||||
// Filter to add a module's version to an url
|
||||
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
|
||||
// Function to check our current environment
|
||||
// Usage in twig: {% if is_development_environment() %}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('is_development_environment', function()
|
||||
{
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
}));
|
||||
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_config_parameter', function($sParamName)
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->Get($sParamName);
|
||||
}));
|
||||
|
||||
// Function to get the URL of a static page in a module
|
||||
// Usage in twig: {{ get_static_page_module_url('itop-my-module', 'path-to-my-page') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_static_page_module_url', function($sModuleName, $sPage)
|
||||
{
|
||||
return utils::GetAbsoluteUrlModulesRoot().$sModuleName.'/'.$sPage;
|
||||
}));
|
||||
|
||||
// Function to get the URL of a php page in a module
|
||||
// Usage in twig: {{ get_page_module_url('itop-my-module', 'path-to-my-my-page.php') }}
|
||||
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_page_module_url', function($sModuleName, $sPage)
|
||||
{
|
||||
return utils::GetAbsoluteUrlModulePage($sModuleName, $sPage);
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -208,6 +208,14 @@ class UIExtKeyWidget
|
||||
{
|
||||
// When there is only once choice, select it by default
|
||||
$sSelected = 'selected';
|
||||
if($value != $key)
|
||||
{
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$this->iId').attr('data-validate','dependencies');
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -266,7 +274,7 @@ EOF
|
||||
|
||||
// the input for the auto-complete
|
||||
$sHTMLValue .= "<input class=\"field_autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif?t=".utils::GetCacheBusterTimestamp()."\" onClick=\"oACWidget_{$this->iId}.Search();\"/></span>";
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
|
||||
|
||||
// another hidden input to store & pass the object's Id
|
||||
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
|
||||
@@ -290,7 +298,7 @@ EOF
|
||||
}
|
||||
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
|
||||
{
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_tree_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_tree.gif?t=".utils::GetCacheBusterTimestamp()."\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"/></span>";
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
if ($('#ac_tree_{$this->iId}').length == 0)
|
||||
@@ -304,7 +312,7 @@ EOF
|
||||
{
|
||||
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
|
||||
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_add_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_add.gif?t=".utils::GetCacheBusterTimestamp()."\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"/></span>";
|
||||
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
if ($('#ajax_{$this->iId}').length == 0)
|
||||
|
||||
@@ -74,7 +74,7 @@ class UIHTMLEditorWidget
|
||||
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
|
||||
$aConfig['language'] = $sLanguage;
|
||||
$aConfig['contentsLanguage'] = $sLanguage;
|
||||
$aConfig['extraPlugins'] = 'disabler';
|
||||
$aConfig['extraPlugins'] = 'disabler,codesnippet';
|
||||
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
|
||||
if ($sWidthSpec != '')
|
||||
{
|
||||
|
||||
@@ -286,11 +286,13 @@ class UILinksWidgetDirect
|
||||
* @param DBObject $oCurrentObj
|
||||
* @param $aAlreadyLinked
|
||||
*
|
||||
* @param array $aPrefillFormParam
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked)
|
||||
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array())
|
||||
{
|
||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
||||
|
||||
@@ -333,6 +335,8 @@ class UILinksWidgetDirect
|
||||
|
||||
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
|
||||
$oFilter->SetInternalParams($aArgs);
|
||||
$aPrefillFormParam['filter'] = $oFilter;
|
||||
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
||||
}
|
||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}",
|
||||
@@ -359,13 +363,17 @@ class UILinksWidgetDirect
|
||||
|
||||
/**
|
||||
* Search for objects to be linked to the current object (i.e "remote" objects)
|
||||
*
|
||||
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
||||
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of $this->sLinkedClass
|
||||
* @param array $aAlreadyLinked Array of indentifiers of objects which are already linke to the current object (or about to be linked)
|
||||
* @param DBObject $oCurrentObj The object currently being edited... if known...
|
||||
* @throws Exception
|
||||
* @param array $aPrefillFormParam
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null)
|
||||
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null, $aPrefillFormParam = array())
|
||||
{
|
||||
if ($sRemoteClass == '')
|
||||
{
|
||||
@@ -395,16 +403,19 @@ class UILinksWidgetDirect
|
||||
$oFilter->AddCondition('id', $oCurrentObj->GetKey(), '!=');
|
||||
}
|
||||
}
|
||||
if (count($aAlreadyLinked) > 0)
|
||||
{
|
||||
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
|
||||
}
|
||||
if ($oCurrentObj != null)
|
||||
{
|
||||
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
||||
|
||||
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
|
||||
$oFilter->SetInternalParams($aArgs);
|
||||
|
||||
$aPrefillFormParam['filter'] = $oFilter;
|
||||
$oCurrentObj->PrefillForm('search', $aPrefillFormParam);
|
||||
}
|
||||
if (count($aAlreadyLinked) > 0)
|
||||
{
|
||||
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
|
||||
}
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results
|
||||
|
||||
@@ -133,14 +133,15 @@ class UILinksWidget
|
||||
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
|
||||
$aRow = array();
|
||||
$aFieldsMap = array();
|
||||
$iKey = 0;
|
||||
if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
|
||||
{
|
||||
$key = $linkObjOrId->GetKey();
|
||||
$iKey = $linkObjOrId->GetKey();
|
||||
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
|
||||
$sPrefix .= "[$key][";
|
||||
$sPrefix .= "[$iKey][";
|
||||
$sNameSuffix = "]"; // To make a tabular form
|
||||
$aArgs['prefix'] = $sPrefix;
|
||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$key}";
|
||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
|
||||
$aArgs['this'] = $linkObjOrId;
|
||||
|
||||
if($bReadOnly)
|
||||
@@ -154,7 +155,7 @@ class UILinksWidget
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$key\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$key\">";
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
|
||||
foreach($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId->GetKey().']';
|
||||
@@ -195,7 +196,30 @@ class UILinksWidget
|
||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".($iUniqueId < 0 ? -$iUniqueId : $iUniqueId);
|
||||
$aArgs['this'] = $oNewLinkObj;
|
||||
$sInputValue = $iUniqueId > 0 ? "-$iUniqueId" : "$iUniqueId";
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$sInputValue\">";
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"0\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$sInputValue\">";
|
||||
|
||||
if ($iUniqueId > 0)
|
||||
{
|
||||
// Rows created with ajax call need OnLinkAdded call.
|
||||
//
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rows added before loading the form don't have to call OnLinkAdded.
|
||||
// Listeners are already present and DOM is not recreated
|
||||
$iPositiveUniqueId = -$iUniqueId;
|
||||
$oP->add_ready_script(<<<EOF
|
||||
oWidget{$this->m_iInputId}.AddLink($iPositiveUniqueId, $iRemoteObjKey);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
foreach($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.-$iUniqueId.']';
|
||||
@@ -207,20 +231,12 @@ class UILinksWidget
|
||||
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
|
||||
'</div></div></div>';
|
||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
||||
$oP->add_ready_script(<<<EOF
|
||||
oWidget{$this->m_iInputId}.OnValueChange($iKey, $iUniqueId, '$sFieldCode', '$sValue');
|
||||
EOF
|
||||
);
|
||||
}
|
||||
$sState = '';
|
||||
|
||||
// Rows created with ajax call need OnLinkAdded call.
|
||||
// Rows added before loading the form cannot call OnLinkAdded.
|
||||
if ($iUniqueId > 0)
|
||||
{
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$bReadOnly)
|
||||
@@ -330,15 +346,26 @@ EOF
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public function Display(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
||||
public function Display(WebPage $oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj)
|
||||
{
|
||||
$sHtmlValue = '';
|
||||
$sHtmlValue .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
|
||||
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
|
||||
$oValue->Rewind();
|
||||
$aForm = array();
|
||||
$iAddedId = 1; // Unique id for new links
|
||||
$aAddedLinks = array();
|
||||
$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(<<<EOF
|
||||
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();
|
||||
EOF
|
||||
);
|
||||
|
||||
while($oCurrentLink = $oValue->Fetch())
|
||||
{
|
||||
// We try to retrieve the remote object as usual
|
||||
@@ -357,9 +384,7 @@ EOF
|
||||
|
||||
if ($oCurrentLink->IsNew())
|
||||
{
|
||||
$key = -($iAddedId++);
|
||||
$iUniqueId = -$key;
|
||||
$aAddedLinks[] = array('iAddedId' => $iUniqueId, 'iRemote' => $oCurrentLink->Get($this->m_sExtKeyToRemote));
|
||||
$key = $iAddedId--;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -368,24 +393,6 @@ EOF
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||
}
|
||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
||||
$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(<<<EOF
|
||||
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();
|
||||
EOF
|
||||
);
|
||||
|
||||
foreach ($aAddedLinks as $aAddedLink)
|
||||
{
|
||||
$oPage->add_ready_script(<<<EOF
|
||||
oWidget{$this->m_iInputId}.AddLink({$aAddedLink['iAddedId']}, {$aAddedLink['iRemote']});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
$sHtmlValue .= "<span style=\"float:left;\"> <img src=\"../images/tv-item-last.gif\"> <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";
|
||||
$sHtmlValue .= " <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnAdd\" type=\"button\" value=\"".Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sRemoteClass))."\" onClick=\"oWidget{$this->m_iInputId}.AddObjects();\"><span id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\"></span></span>\n";
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,45 +1,80 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Class WebPage
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 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
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Generic interface common to CLI and Web pages
|
||||
*/
|
||||
Interface Page
|
||||
{
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function output();
|
||||
|
||||
/**
|
||||
* Add any text or HTML fragment to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function add($sText);
|
||||
|
||||
/**
|
||||
* Add a paragraph to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function p($sText);
|
||||
|
||||
/**
|
||||
* Add a pre-formatted text to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function pre($sText);
|
||||
|
||||
/**
|
||||
* Add a comment
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function add_comment($sText);
|
||||
|
||||
/**
|
||||
* Adds a tabular content to the web page
|
||||
*
|
||||
* @param string[] $aConfig Configuration of the table: hash array of 'column_id' => 'Column Label'
|
||||
* @param string[] $aData Hash array. Data to display in the table: each row is made of 'column_id' => Data. A
|
||||
* column 'pkey' is expected for each row
|
||||
* @param array $aParams Hash array. Extra parameters for the table.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function table($aConfig, $aData, $aParams = array());
|
||||
}
|
||||
|
||||
@@ -60,6 +95,10 @@ Interface Page
|
||||
*/
|
||||
class WebPage implements Page
|
||||
{
|
||||
/**
|
||||
* @since 2.7.0 N°2529
|
||||
*/
|
||||
const PAGES_CHARSET = 'utf-8';
|
||||
protected $s_title;
|
||||
protected $s_content;
|
||||
protected $s_deferred_content;
|
||||
@@ -80,7 +119,14 @@ class WebPage implements Page
|
||||
protected $s_sOutputFormat;
|
||||
protected $a_OutputOptions;
|
||||
protected $bPrintable;
|
||||
protected $bHasCollapsibleSection;
|
||||
|
||||
/**
|
||||
* WebPage constructor.
|
||||
*
|
||||
* @param string $s_title
|
||||
* @param bool $bPrintable
|
||||
*/
|
||||
public function __construct($s_title, $bPrintable = false)
|
||||
{
|
||||
$this->s_title = $s_title;
|
||||
@@ -102,12 +148,15 @@ class WebPage implements Page
|
||||
$this->bTrashUnexpectedOutput = false;
|
||||
$this->s_OutputFormat = utils::ReadParam('output_format', 'html');
|
||||
$this->a_OutputOptions = array();
|
||||
$this->bHasCollapsibleSection = false;
|
||||
$this->bPrintable = $bPrintable;
|
||||
ob_start(); // Start capturing the output
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the title of the page after its creation
|
||||
*
|
||||
* @param string $s_title
|
||||
*/
|
||||
public function set_title($s_title)
|
||||
{
|
||||
@@ -116,6 +165,9 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Specify a default URL and a default target for all links on a page
|
||||
*
|
||||
* @param string $s_href
|
||||
* @param string $s_target
|
||||
*/
|
||||
public function set_base($s_href = '', $s_target = '')
|
||||
{
|
||||
@@ -124,7 +176,7 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any text or HTML fragment to the body of the page
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add($s_html)
|
||||
{
|
||||
@@ -135,6 +187,9 @@ class WebPage implements Page
|
||||
* Add any text or HTML fragment (identified by an ID) at the end of the body of the page
|
||||
* This is useful to add hidden content, DIVs or FORMs that should not
|
||||
* be embedded into each other.
|
||||
*
|
||||
* @param string $s_html
|
||||
* @param string $sId
|
||||
*/
|
||||
public function add_at_the_end($s_html, $sId = '')
|
||||
{
|
||||
@@ -142,7 +197,7 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a paragraph to the body of the page
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function p($s_html)
|
||||
{
|
||||
@@ -150,7 +205,7 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pre-formatted text to the body of the page
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function pre($s_html)
|
||||
{
|
||||
@@ -158,7 +213,7 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a comment
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_comment($sText)
|
||||
{
|
||||
@@ -167,6 +222,10 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add a paragraph to the body of the page
|
||||
*
|
||||
* @param string $s_html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetP($s_html)
|
||||
{
|
||||
@@ -174,20 +233,22 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tabular content to the web page
|
||||
*
|
||||
* @param string[] $aConfig Configuration of the table: hash array of 'column_id' => 'Column Label'
|
||||
* @param string[] $aData Hash array. Data to display in the table: each row is made of 'column_id' => Data. A
|
||||
* column 'pkey' is expected for each row
|
||||
* @param array $aParams Hash array. Extra parameters for the table.
|
||||
*
|
||||
* @return void
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$this->add($this->GetTable($aConfig, $aData, $aParams));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aConfig
|
||||
* @param array $aData
|
||||
* @param array $aParams
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetTable($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
@@ -215,6 +276,12 @@ class WebPage implements Page
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aRow
|
||||
* @param array $aConfig
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetTableRow($aRow, $aConfig)
|
||||
{
|
||||
$sHtml = '';
|
||||
@@ -239,6 +306,8 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add some Javascript to the header of the page
|
||||
*
|
||||
* @param string $s_script
|
||||
*/
|
||||
public function add_script($s_script)
|
||||
{
|
||||
@@ -247,6 +316,8 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add some Javascript to the header of the page
|
||||
*
|
||||
* @param $s_script
|
||||
*/
|
||||
public function add_ready_script($s_script)
|
||||
{
|
||||
@@ -279,12 +350,18 @@ class WebPage implements Page
|
||||
$this->a_dict_entries_prefixes[] = $s_entriesPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function get_dict_signature()
|
||||
{
|
||||
return str_replace('_', '', Dict::GetUserLanguage()).'-'.md5(implode(',',
|
||||
$this->a_dict_entries).'|'.implode(',', $this->a_dict_entries_prefixes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function get_dict_file_content()
|
||||
{
|
||||
$aEntries = array();
|
||||
@@ -304,6 +381,8 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add some CSS definitions to the header of the page
|
||||
*
|
||||
* @param string $s_style
|
||||
*/
|
||||
public function add_style($s_style)
|
||||
{
|
||||
@@ -323,12 +402,20 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add a CSS stylesheet (as an include, i.e. link) to the header of the page
|
||||
*
|
||||
* @param string $s_linked_stylesheet
|
||||
* @param string $s_condition
|
||||
*/
|
||||
public function add_linked_stylesheet($s_linked_stylesheet, $s_condition = "")
|
||||
{
|
||||
$this->a_linked_stylesheets[] = array('link' => $s_linked_stylesheet, 'condition' => $s_condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSaasRelPath
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add_saas($sSaasRelPath)
|
||||
{
|
||||
$sCssRelPath = utils::GetCSSFromSASS($sSaasRelPath);
|
||||
@@ -344,6 +431,8 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Add some custom header to the page
|
||||
*
|
||||
* @param string $s_header
|
||||
*/
|
||||
public function add_header($s_header)
|
||||
{
|
||||
@@ -361,6 +450,8 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Build a special kind of TABLE useful for displaying the details of an object from a hash array of data
|
||||
*
|
||||
* @param array $aFields
|
||||
*/
|
||||
public function details($aFields)
|
||||
{
|
||||
@@ -406,15 +497,22 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Build a special kind of TABLE useful for displaying the details of an object from a hash array of data
|
||||
*
|
||||
* @param array $aFields
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDetails($aFields)
|
||||
{
|
||||
$sHtml = "<div class=\"details\" id='search-widget-results-outer'>\n";
|
||||
$sHtml = "<div class=\"details\">\n";
|
||||
foreach ($aFields as $aAttrib)
|
||||
{
|
||||
$sDataAttCode = isset($aAttrib['attcode']) ? "data-attcode=\"{$aAttrib['attcode']}\"" : '';
|
||||
$sLayout = isset($aAttrib['layout']) ? $aAttrib['layout'] : 'small';
|
||||
$sHtml .= "<div class=\"field_container field_{$sLayout}\" $sDataAttCode>\n";
|
||||
$sDataAttributeCode = isset($aAttrib['attcode']) ? 'data-attribute-code="'.$aAttrib['attcode'].'"' : '';
|
||||
$sDataAttributeType = isset($aAttrib['atttype']) ? 'data-attribute-type="'.$aAttrib['atttype'].'"' : '';
|
||||
$sDataValueRaw = isset($aAttrib['value_raw']) ? 'data-value-raw="'.$aAttrib['value_raw'].'"' : '';
|
||||
|
||||
$sHtml .= "<div class=\"field_container field_{$sLayout}\" $sDataAttributeCode $sDataAttributeType $sDataValueRaw>\n";
|
||||
$sHtml .= "<div class=\"field_label label\">{$aAttrib['label']}</div>\n";
|
||||
|
||||
$sHtml .= "<div class=\"field_data\">\n";
|
||||
@@ -450,7 +548,7 @@ class WebPage implements Page
|
||||
/**
|
||||
* Build a set of radio buttons suitable for editing a field/attribute of an object (including its validation)
|
||||
*
|
||||
* @param $aAllowedValues hash Array of value => display_value
|
||||
* @param $aAllowedValues array Array of value => display_value
|
||||
* @param $value mixed Current value for the field/attribute
|
||||
* @param $iId mixed Unique Id for the input control in the page
|
||||
* @param $sFieldName string The name of the field, attr_<$sFieldName> will hold the value for the field
|
||||
@@ -470,13 +568,13 @@ class WebPage implements Page
|
||||
if ((count($aAllowedValues) == 1) && ($bMandatory == 'true'))
|
||||
{
|
||||
// When there is only once choice, select it by default
|
||||
$sSelected = ' checked';
|
||||
$sSelected = 'checked';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSelected = ($value == $key) ? ' checked' : '';
|
||||
$sSelected = ($value == $key) ? 'checked' : '';
|
||||
}
|
||||
$sHTMLValue .= "<input type=\"radio\" id=\"{$iId}_{$key}\" name=\"radio_$sFieldName\" onChange=\"$('#{$iId}').val(this.value).trigger('change');\" value=\"$key\"$sSelected><label class=\"radio\" for=\"{$iId}_{$key}\"> $display_value</label> ";
|
||||
$sHTMLValue .= "<input type=\"radio\" id=\"{$iId}_{$key}\" name=\"radio_$sFieldName\" onChange=\"$('#{$iId}').val(this.value).trigger('change');\" value=\"$key\" $sSelected><label class=\"radio\" for=\"{$iId}_{$key}\"> $display_value</label> ";
|
||||
if ($bVertical)
|
||||
{
|
||||
if ($idx == 0)
|
||||
@@ -515,6 +613,8 @@ class WebPage implements Page
|
||||
* Possible improvement: I've noticed that several output buffers are stacked,
|
||||
* if they are not empty, the output will be corrupted. The solution would
|
||||
* consist in unstacking all of them (and concatenate the contents).
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function ob_get_clean_safe()
|
||||
{
|
||||
@@ -552,7 +652,8 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
@@ -570,31 +671,7 @@ class WebPage implements Page
|
||||
echo "<title>".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</title>\n";
|
||||
echo $this->get_base_tag();
|
||||
|
||||
$this->output_dict_entries();
|
||||
|
||||
foreach ($this->a_linked_scripts as $s_script)
|
||||
{
|
||||
// Make sure that the URL to the script contains the application's version number
|
||||
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
||||
if (strpos($s_script, '?') === false)
|
||||
{
|
||||
$s_script .= "?t=".utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_script .= "&t=".utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
||||
}
|
||||
if (count($this->a_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
foreach ($this->a_scripts as $s_script)
|
||||
{
|
||||
echo "$s_script\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
// First put stylesheets so they can be loaded before browser interprets JS files, otherwise visual glitch can occur.
|
||||
foreach ($this->a_linked_stylesheets as $a_stylesheet)
|
||||
{
|
||||
if (strpos($a_stylesheet['link'], '?') === false)
|
||||
@@ -616,6 +693,7 @@ class WebPage implements Page
|
||||
}
|
||||
}
|
||||
|
||||
// Then inline styles
|
||||
if (count($this->a_styles) > 0)
|
||||
{
|
||||
echo "<style>\n";
|
||||
@@ -625,10 +703,43 @@ class WebPage implements Page
|
||||
}
|
||||
echo "</style>\n";
|
||||
}
|
||||
|
||||
// Favicon
|
||||
if (class_exists('MetaModel') && MetaModel::GetConfig())
|
||||
{
|
||||
echo "<link rel=\"shortcut icon\" href=\"".utils::GetAbsoluteUrlAppRoot()."images/favicon.ico?t=".utils::GetCacheBusterTimestamp()."\" />\n";
|
||||
}
|
||||
|
||||
// Dict entries for JS
|
||||
$this->output_dict_entries();
|
||||
|
||||
// JS files
|
||||
foreach ($this->a_linked_scripts as $s_script)
|
||||
{
|
||||
// Make sure that the URL to the script contains the application's version number
|
||||
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
||||
if (strpos($s_script, '?') === false)
|
||||
{
|
||||
$s_script .= "?t=".utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_script .= "&t=".utils::GetCacheBusterTimestamp();
|
||||
}
|
||||
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
||||
}
|
||||
|
||||
// JS inline scripts
|
||||
if (count($this->a_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
foreach ($this->a_scripts as $s_script)
|
||||
{
|
||||
echo "$s_script\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
|
||||
echo "</head>\n";
|
||||
echo "<body>\n";
|
||||
echo self::FilterXSS($this->s_content);
|
||||
@@ -652,6 +763,9 @@ class WebPage implements Page
|
||||
|
||||
/**
|
||||
* Build a series of hidden field[s] from an array
|
||||
*
|
||||
* @param string $sLabel
|
||||
* @param array $aData
|
||||
*/
|
||||
public function add_input_hidden($sLabel, $aData)
|
||||
{
|
||||
@@ -830,43 +944,55 @@ class WebPage implements Page
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aActions
|
||||
* @param array $aFavoriteActions
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function RenderPopupMenuItems($aActions, $aFavoriteActions = array())
|
||||
{
|
||||
$sPrevUrl = '';
|
||||
$sHtml = '';
|
||||
if (!$this->IsPrintableVersion())
|
||||
{
|
||||
foreach ($aActions as $aAction)
|
||||
foreach ($aActions as $sActionId => $aAction)
|
||||
{
|
||||
$sClass = isset($aAction['css_classes']) ? ' class="'.implode(' ', $aAction['css_classes']).'"' : '';
|
||||
$sOnClick = isset($aAction['onclick']) ? ' onclick="'.htmlspecialchars($aAction['onclick'], ENT_QUOTES,
|
||||
$sDataActionId = 'data-action-id="'.$sActionId.'"';
|
||||
$sClass = isset($aAction['css_classes']) ? 'class="'.implode(' ', $aAction['css_classes']).'"' : '';
|
||||
$sOnClick = isset($aAction['onclick']) ? 'onclick="'.htmlspecialchars($aAction['onclick'], ENT_QUOTES,
|
||||
"UTF-8").'"' : '';
|
||||
$sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : "";
|
||||
$sTarget = isset($aAction['target']) ? "target=\"{$aAction['target']}\"" : "";
|
||||
if (empty($aAction['url']))
|
||||
{
|
||||
if ($sPrevUrl != '') // Don't output consecutively two separators...
|
||||
{
|
||||
$sHtml .= "<li>{$aAction['label']}</li>";
|
||||
$sHtml .= "<li $sDataActionId>{$aAction['label']}</li>";
|
||||
}
|
||||
$sPrevUrl = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml .= "<li><a $sTarget href=\"{$aAction['url']}\"$sClass $sOnClick>{$aAction['label']}</a></li>";
|
||||
$sHtml .= "<li $sDataActionId><a $sTarget href=\"{$aAction['url']}\" $sClass $sOnClick>{$aAction['label']}</a></li>";
|
||||
$sPrevUrl = $aAction['url'];
|
||||
}
|
||||
}
|
||||
$sHtml .= "</ul></li></ul></div>";
|
||||
foreach (array_reverse($aFavoriteActions) as $aAction)
|
||||
foreach (array_reverse($aFavoriteActions) as $sActionId => $aAction)
|
||||
{
|
||||
$sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : "";
|
||||
$sHtml .= "<div class=\"actions_button\"><a $sTarget href='{$aAction['url']}'>{$aAction['label']}</a></div>";
|
||||
$sHtml .= "<div class=\"actions_button\" data-action-id=\"$sActionId\"><a $sTarget href='{$aAction['url']}'>{$aAction['label']}</a></div>";
|
||||
}
|
||||
}
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bReturnOutput
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function output_dict_entries($bReturnOutput = false)
|
||||
{
|
||||
if ((count($this->a_dict_entries) > 0) || (count($this->a_dict_entries_prefixes) > 0))
|
||||
@@ -887,17 +1013,126 @@ class WebPage implements Page
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds init scripts for the collapsible sections
|
||||
*/
|
||||
protected function outputCollapsibleSectionInit()
|
||||
{
|
||||
if (!$this->bHasCollapsibleSection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_script(<<<'EOD'
|
||||
function initCollapsibleSection(iSectionId, bOpenedByDefault, sSectionStateStorageKey)
|
||||
{
|
||||
var bStoredSectionState = JSON.parse(localStorage.getItem(sSectionStateStorageKey));
|
||||
var bIsSectionOpenedInitially = (bStoredSectionState == null) ? bOpenedByDefault : bStoredSectionState;
|
||||
|
||||
if (bIsSectionOpenedInitially) {
|
||||
$("#LnkCollapse_"+iSectionId).toggleClass("open");
|
||||
$("#Collapse_"+iSectionId).toggle();
|
||||
}
|
||||
|
||||
$("#LnkCollapse_"+iSectionId).click(function(e) {
|
||||
localStorage.setItem(sSectionStateStorageKey, !($("#Collapse_"+iSectionId).is(":visible")));
|
||||
$("#LnkCollapse_"+iSectionId).toggleClass("open");
|
||||
$("#Collapse_"+iSectionId).slideToggle("normal");
|
||||
e.preventDefault(); // we don't want to do anything more (see #1030 : a non wanted tab switching was triggered)
|
||||
});
|
||||
}
|
||||
EOD
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSectionLabel
|
||||
* @param bool $bOpenedByDefault
|
||||
* @param string $sSectionStateStorageBusinessKey
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function StartCollapsibleSection($sSectionLabel, $bOpenedByDefault = false, $sSectionStateStorageBusinessKey = '')
|
||||
{
|
||||
$this->add($this->GetStartCollapsibleSection($sSectionLabel, $bOpenedByDefault, $sSectionStateStorageBusinessKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSectionLabel
|
||||
* @param bool $bOpenedByDefault
|
||||
* @param string $sSectionStateStorageBusinessKey
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetStartCollapsibleSection($sSectionLabel, $bOpenedByDefault = false, $sSectionStateStorageBusinessKey = '')
|
||||
{
|
||||
$this->bHasCollapsibleSection = true;
|
||||
$sHtml = '';
|
||||
static $iSectionId = 0;
|
||||
$sHtml .= '<a id="LnkCollapse_'.$iSectionId.'" class="CollapsibleLabel" href="#">'.$sSectionLabel.'</a></br>'."\n";
|
||||
$sHtml .= '<div id="Collapse_'.$iSectionId.'" style="display:none">'."\n";
|
||||
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$sSectionStateStorageKey = $oConfig->GetItopInstanceid().'/'.$sSectionStateStorageBusinessKey.'/collapsible-'.$iSectionId;
|
||||
$sSectionStateStorageKey = json_encode($sSectionStateStorageKey);
|
||||
$sOpenedByDefault = ($bOpenedByDefault) ? 'true' : 'false';
|
||||
$this->add_ready_script("initCollapsibleSection($iSectionId, $sOpenedByDefault, '$sSectionStateStorageKey');");
|
||||
|
||||
$iSectionId++;
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
public function EndCollapsibleSection()
|
||||
{
|
||||
$this->add($this->GetEndCollapsibleSection());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetEndCollapsibleSection()
|
||||
{
|
||||
return "</div>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
interface iTabbedPage
|
||||
{
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '');
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabLabel
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabLabel, $sHtml);
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '');
|
||||
|
||||
/**
|
||||
* @param string $sTabLabel
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function SetCurrentTab($sTabLabel = '');
|
||||
|
||||
/**
|
||||
@@ -918,11 +1153,20 @@ interface iTabbedPage
|
||||
|
||||
public function GetCurrentTab();
|
||||
|
||||
/**
|
||||
* @param string$sTabLabel
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RemoveTab($sTabLabel, $sTabContainer = null);
|
||||
|
||||
/**
|
||||
* Finds the tab whose title matches a given pattern
|
||||
*
|
||||
* @param string $sPattern
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed The name of the tab as a string or false if not found
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null);
|
||||
@@ -944,6 +1188,12 @@ class TabManager
|
||||
$this->m_sCurrentTab = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '')
|
||||
{
|
||||
$this->m_aTabs[$sTabContainer] = array('prefix' => $sPrefix, 'tabs' => array());
|
||||
@@ -951,12 +1201,20 @@ class TabManager
|
||||
return "\$Tabs:$sTabContainer\$";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToCurrentTab($sHtml)
|
||||
{
|
||||
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
|
||||
}
|
||||
|
||||
public function GetCurrentTabLength($sHtml)
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function GetCurrentTabLength()
|
||||
{
|
||||
$iLength = isset($this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html']) ? strlen($this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html']) : 0;
|
||||
|
||||
@@ -982,16 +1240,33 @@ class TabManager
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTab
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function TabExists($sTabContainer, $sTab)
|
||||
{
|
||||
return isset($this->m_aTabs[$sTabContainer]['tabs'][$sTab]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function TabsContainerCount()
|
||||
{
|
||||
return count($this->m_aTabs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabLabel
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
|
||||
{
|
||||
if (!isset($this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]))
|
||||
@@ -1015,6 +1290,11 @@ class TabManager
|
||||
return ''; // Nothing to add to the page for now
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
|
||||
@@ -1023,6 +1303,11 @@ class TabManager
|
||||
return $sPreviousTabContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabLabel
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function SetCurrentTab($sTabLabel = '')
|
||||
{
|
||||
$sPreviousTab = $this->m_sCurrentTab;
|
||||
@@ -1040,9 +1325,11 @@ class TabManager
|
||||
*
|
||||
* @param string $sTabLabel The (localised) label of the tab
|
||||
* @param string $sUrl The URL to load (on the same server)
|
||||
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause
|
||||
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. false will cause
|
||||
* the tab to be reloaded upon each activation.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public function AddAjaxTab($sTabLabel, $sUrl, $bCache = true)
|
||||
@@ -1057,17 +1344,26 @@ class TabManager
|
||||
return ''; // Nothing to add to the page for now
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCurrentTabContainer()
|
||||
{
|
||||
return $this->m_sCurrentTabContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_sCurrentTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabLabel
|
||||
* @param string|null $sTabContainer
|
||||
*/
|
||||
public function RemoveTab($sTabLabel, $sTabContainer = null)
|
||||
{
|
||||
if ($sTabContainer == null)
|
||||
@@ -1090,6 +1386,9 @@ class TabManager
|
||||
/**
|
||||
* Finds the tab whose title matches a given pattern
|
||||
*
|
||||
* @param string $sPattern
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed The actual name of the tab (as a string) or false if not found
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null)
|
||||
@@ -1116,6 +1415,11 @@ class TabManager
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabLabel
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function SelectTab($sTabContainer, $sTabLabel)
|
||||
{
|
||||
@@ -1142,6 +1446,12 @@ class TabManager
|
||||
return "window.setTimeout(\"$('$sSelector').tabs('select', $tab_index);\", 100);"; // Let the time to the tabs widget to initialize
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sContent
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RenderIntoContent($sContent, WebPage $oPage)
|
||||
{
|
||||
// Render the tabs in the page (if any)
|
||||
|
||||
@@ -42,7 +42,7 @@ class XMLPage extends WebPage
|
||||
parent::__construct($s_title);
|
||||
$this->m_bPassThrough = $bPassThrough;
|
||||
$this->m_bHeaderSent = false;
|
||||
$this->add_header("Content-type: text/xml; charset=utf-8");
|
||||
$this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header("Cache-control: no-cache");
|
||||
$this->add_header("Content-location: export.xml");
|
||||
}
|
||||
@@ -53,8 +53,9 @@ class XMLPage extends WebPage
|
||||
{
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
$this->s_content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n".trim($this->s_content);
|
||||
|
||||
$sCharset = self::PAGES_CHARSET;
|
||||
$this->s_content = "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n".trim($this->s_content);
|
||||
$this->add_header("Content-Length: ".strlen($this->s_content));
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
@@ -87,7 +88,8 @@ class XMLPage extends WebPage
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n";
|
||||
$sCharset = self::PAGES_CHARSET;
|
||||
echo "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n";
|
||||
echo trim($s_captured_output);
|
||||
echo trim($this->s_content);
|
||||
echo $sText;
|
||||
|
||||
@@ -2,14 +2,5 @@
|
||||
|
||||
define('APPROOT', dirname(__FILE__).'/');
|
||||
define('APPCONF', APPROOT.'conf/');
|
||||
define('ITOP_DEFAULT_ENV', 'production');
|
||||
|
||||
if (function_exists('microtime'))
|
||||
{
|
||||
$fItopStarted = microtime(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$fItopStarted = 1000 * time();
|
||||
}
|
||||
?>
|
||||
require_once APPROOT.'bootstrap.inc.php';
|
||||
|
||||
92
bootstrap.inc.php
Normal file
92
bootstrap.inc.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
define('ITOP_DEFAULT_ENV', 'production');
|
||||
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
|
||||
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
|
||||
|
||||
if (function_exists('microtime'))
|
||||
{
|
||||
$fItopStarted = microtime(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$fItopStarted = 1000 * time();
|
||||
}
|
||||
|
||||
if (! isset($GLOBALS['bBypassAutoload']) || $GLOBALS['bBypassAutoload'] == false)
|
||||
{
|
||||
require_once APPROOT.'/lib/autoload.php';
|
||||
}
|
||||
|
||||
//
|
||||
// Maintenance mode
|
||||
//
|
||||
|
||||
// Use 'maintenance' parameter to bypass maintenance mode
|
||||
if (!isset($bBypassMaintenance))
|
||||
{
|
||||
$bBypassMaintenance = isset($_REQUEST['maintenance']) ? boolval($_REQUEST['maintenance']) : false;
|
||||
}
|
||||
|
||||
if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
|
||||
{
|
||||
$sTitle = 'Maintenance';
|
||||
$sMessage = 'This application is currently under maintenance.';
|
||||
|
||||
http_response_code(503);
|
||||
// Display message depending on the request
|
||||
include(APPROOT.'application/maintenancemsg.php');
|
||||
$sSAPIName = strtoupper(trim(php_sapi_name()));
|
||||
|
||||
switch (true)
|
||||
{
|
||||
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/pages/ajax.searchform.php'):
|
||||
_MaintenanceHtmlMessage($sMessage);
|
||||
break;
|
||||
|
||||
case $sSAPIName == 'CLI':
|
||||
case array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER):
|
||||
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/webservices/soapserver.php'):
|
||||
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/webservices/rest.php'):
|
||||
_MaintenanceTextMessage($sMessage);
|
||||
break;
|
||||
|
||||
case isset($_SERVER['CONTENT_TYPE']) && ($_SERVER['CONTENT_TYPE'] == 'application/json'):
|
||||
_MaintenanceJsonMessage($sTitle, $sMessage);
|
||||
break;
|
||||
|
||||
default:
|
||||
_MaintenanceSetupPageMessage($sTitle, $sMessage);
|
||||
break;
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to test if a string ends with another
|
||||
* @param $haystack
|
||||
* @param $needle
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function EndsWith($haystack, $needle) {
|
||||
return substr_compare($haystack, $needle, -strlen($needle)) === 0;
|
||||
}
|
||||
@@ -1,21 +1,77 @@
|
||||
{
|
||||
"type": "project",
|
||||
"license": "AGPLv3",
|
||||
"require": {
|
||||
"php": ">=5.6.0",
|
||||
"ext-mysql": "*",
|
||||
"ext-ldap": "*",
|
||||
"ext-mcrypt": "*",
|
||||
"ext-cli": "*",
|
||||
"ext-soap": "*",
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"ext-mysqli": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-gd": "*"
|
||||
"ext-gd": "*",
|
||||
"ext-ctype": "*",
|
||||
|
||||
"scssphp/scssphp": "1.0.0",
|
||||
"swiftmailer/swiftmailer": "5.4.9",
|
||||
"pelago/emogrifier": "2.1.0",
|
||||
"combodo/tcpdf": "6.3.0",
|
||||
"pear/archive_tar": "1.4.7",
|
||||
|
||||
"symfony/console": "3.4.*",
|
||||
"symfony/dotenv": "3.4.*",
|
||||
"symfony/framework-bundle": "3.4.*",
|
||||
"symfony/twig-bundle": "3.4.*",
|
||||
"symfony/yaml": "3.4.*",
|
||||
"symfony/polyfill-php70": "1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/stopwatch": "3.4.*",
|
||||
"symfony/web-profiler-bundle": "3.4.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Required to use the AttributeEncryptedString.",
|
||||
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
|
||||
"ext-mcrypt": "Can be used as a polyfill if either libsodium and openssl are not installed (libsodium and openssl are more secure)",
|
||||
"ext-ldap": "Required to use LDAP as an identity provider",
|
||||
"ext-posix": "Not required by the core, but some extensions uses it.",
|
||||
"ext-imap": "Required by the extension \"Mail to ticket automation\""
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "5.6.0"
|
||||
},
|
||||
"vendor-dir": "lib",
|
||||
"preferred-install": {
|
||||
"*": "dist"
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"core",
|
||||
"application"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"core/dbobjectsearch.class.php",
|
||||
"core/legacy/dbobjectsearchlegacy.class.php",
|
||||
"core/querybuildercontext.class.inc.php",
|
||||
"core/legacy/querybuildercontextlegacy.class.inc.php",
|
||||
"core/querybuilderexpressions.class.inc.php",
|
||||
"core/legacy/querybuilderexpressionslegacy.class.inc.php",
|
||||
"application/loginform.class.inc.php",
|
||||
"application/loginbasic.class.inc.php",
|
||||
"application/logindefault.class.inc.php",
|
||||
"application/loginexternal.class.inc.php",
|
||||
"application/loginurl.class.inc.php"
|
||||
]
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "3.4.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
2536
composer.lock
generated
Normal file
2536
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
composer.readme
Normal file
2
composer.readme
Normal file
@@ -0,0 +1,2 @@
|
||||
To regenerate the autoload, run:
|
||||
composer dump-autoload -a
|
||||
13
conf/.htaccess
Normal file
13
conf/.htaccess
Normal file
@@ -0,0 +1,13 @@
|
||||
# Apache 2.4
|
||||
<ifModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</ifModule>
|
||||
|
||||
# Apache 2.2
|
||||
<ifModule !mod_authz_core.c>
|
||||
deny from all
|
||||
Satisfy All
|
||||
</ifModule>
|
||||
|
||||
# Apache 2.2 and 2.4
|
||||
IndexIgnore *
|
||||
2
conf/index.php
Normal file
2
conf/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo 'Access denied';
|
||||
8
conf/web.config
Normal file
8
conf/web.config
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<system.web>
|
||||
<authorization>
|
||||
<deny users="*" /> <!-- Denies all users -->
|
||||
</authorization>
|
||||
</system.web>
|
||||
</configuration>
|
||||
@@ -166,7 +166,14 @@ class apcFile
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@unlink($sCache))
|
||||
if (is_file($sCache))
|
||||
{
|
||||
if (!@unlink($sCache))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -209,8 +216,14 @@ class apcFile
|
||||
return false;
|
||||
}
|
||||
|
||||
@unlink(self::GetCacheFileName($sKey));
|
||||
@unlink(self::GetCacheFileName('-'.$sKey));
|
||||
if (is_file(self::GetCacheFileName($sKey)))
|
||||
{
|
||||
@unlink(self::GetCacheFileName($sKey));
|
||||
}
|
||||
if (is_file(self::GetCacheFileName('-'.$sKey)))
|
||||
{
|
||||
@unlink(self::GetCacheFileName('-'.$sKey));
|
||||
}
|
||||
if ($iTTL > 0)
|
||||
{
|
||||
// hint for ttl management
|
||||
@@ -312,6 +325,10 @@ class apcFile
|
||||
*/
|
||||
static protected function ReadCacheLocked($sFilename)
|
||||
{
|
||||
if (!is_file($sFilename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$file = @fopen($sFilename, 'r');
|
||||
if ($file === false)
|
||||
{
|
||||
|
||||
@@ -1,335 +0,0 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Utility to import/export the DB from/to a ZIP file
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* iTopArchive a class to manipulate (read/write) iTop archives with their catalog
|
||||
* Each iTop archive is a zip file that contains (at the root of the archive)
|
||||
* a file called catalog.xml holding the description of the archive
|
||||
*/
|
||||
class iTopArchive
|
||||
{
|
||||
const read = 0;
|
||||
const create = ZipArchive::CREATE;
|
||||
|
||||
protected $m_sZipPath;
|
||||
protected $m_oZip;
|
||||
protected $m_sVersion;
|
||||
protected $m_sTitle;
|
||||
protected $m_sDescription;
|
||||
protected $m_aPackages;
|
||||
protected $m_aErrorMessages;
|
||||
|
||||
/**
|
||||
* Construct an iTopArchive object
|
||||
* @param $sArchivePath string The full path the archive file
|
||||
* @param $iMode integrer Either iTopArchive::read for reading an existing archive or iTopArchive::create for creating a new one. Updating is not supported (yet)
|
||||
*/
|
||||
public function __construct($sArchivePath, $iMode = iTopArchive::read)
|
||||
{
|
||||
$this->m_sZipPath = $sArchivePath;
|
||||
$this->m_oZip = new ZipArchive();
|
||||
$this->m_oZip->open($this->m_sZipPath, $iMode);
|
||||
$this->m_aErrorMessages = array();
|
||||
$this->m_sVersion = '1.0';
|
||||
$this->m_sTitle = '';
|
||||
$this->m_sDescription = '';
|
||||
$this->m_aPackages = array();
|
||||
}
|
||||
|
||||
public function SetTitle($sTitle)
|
||||
{
|
||||
$this->m_sTitle = $sTitle;
|
||||
}
|
||||
|
||||
public function SetDescription($sDescription)
|
||||
{
|
||||
$this->m_sDescription = $sDescription;
|
||||
}
|
||||
|
||||
public function GetTitle()
|
||||
{
|
||||
return $this->m_sTitle;
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
{
|
||||
return $this->m_sDescription;
|
||||
}
|
||||
|
||||
public function GetPackages()
|
||||
{
|
||||
return $this->m_aPackages;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->m_oZip->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error message explaining the latest error encountered
|
||||
* @return array All the error messages encountered during the validation
|
||||
*/
|
||||
public function GetErrors()
|
||||
{
|
||||
return $this->m_aErrorMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the catalog from the archive (zip) file
|
||||
* @param sPath string Path the the zip file
|
||||
* @return boolean True in case of success, false otherwise
|
||||
*/
|
||||
public function ReadCatalog()
|
||||
{
|
||||
if ($this->IsValid())
|
||||
{
|
||||
$sXmlCatalog = $this->m_oZip->getFromName('catalog.xml');
|
||||
$oParser = xml_parser_create();
|
||||
xml_parse_into_struct($oParser, $sXmlCatalog, $aValues, $aIndexes);
|
||||
xml_parser_free($oParser);
|
||||
|
||||
$iIndex = $aIndexes['ARCHIVE'][0];
|
||||
$this->m_sVersion = $aValues[$iIndex]['attributes']['VERSION'];
|
||||
$iIndex = $aIndexes['TITLE'][0];
|
||||
$this->m_sTitle = $aValues[$iIndex]['value'];
|
||||
$iIndex = $aIndexes['DESCRIPTION'][0];
|
||||
if (array_key_exists('value', $aValues[$iIndex]))
|
||||
{
|
||||
// #@# implement a get_array_value(array, key, default) ?
|
||||
$this->m_sDescription = $aValues[$iIndex]['value'];
|
||||
}
|
||||
|
||||
foreach($aIndexes['PACKAGE'] as $iIndex)
|
||||
{
|
||||
$this->m_aPackages[$aValues[$iIndex]['attributes']['HREF']] = array( 'type' => $aValues[$iIndex]['attributes']['TYPE'], 'title'=> $aValues[$iIndex]['attributes']['TITLE'], 'description' => $aValues[$iIndex]['value']);
|
||||
}
|
||||
|
||||
//echo "Archive path: {$this->m_sZipPath}<br/>\n";
|
||||
//echo "Archive format version: {$this->m_sVersion}<br/>\n";
|
||||
//echo "Title: {$this->m_sTitle}<br/>\n";
|
||||
//echo "Description: {$this->m_sDescription}<br/>\n";
|
||||
//foreach($this->m_aPackages as $aFile)
|
||||
//{
|
||||
// echo "{$aFile['title']} ({$aFile['type']}): {$aFile['description']}<br/>\n";
|
||||
//}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function WriteCatalog()
|
||||
{
|
||||
$sXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n"; // split the XML closing tag that disturbs PSPad's syntax coloring
|
||||
$sXml .= "<archive version=\"1.0\">\n";
|
||||
$sXml .= "<title>{$this->m_sTitle}</title>\n";
|
||||
$sXml .= "<description>{$this->m_sDescription}</description>\n";
|
||||
foreach($this->m_aPackages as $sFileName => $aFile)
|
||||
{
|
||||
$sXml .= "<package title=\"{$aFile['title']}\" type=\"{$aFile['type']}\" href=\"$sFileName\">{$aFile['description']}</package>\n";
|
||||
}
|
||||
$sXml .= "</archive>";
|
||||
$this->m_oZip->addFromString('catalog.xml', $sXml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a package to the archive
|
||||
* @param string $sExternalFilePath The path to the file to be added to the archive as a package (directories are not yet implemented)
|
||||
* @param string $sFilePath The name of the file inside the archive
|
||||
* @param string $sTitle A short title for this package
|
||||
* @param string $sType Type of the package. SQL scripts must be of type 'text/sql'
|
||||
* @param string $sDescription A longer description of the purpose of this package
|
||||
* @return none
|
||||
*/
|
||||
public function AddPackage($sExternalFilePath, $sFilePath, $sTitle, $sType, $sDescription)
|
||||
{
|
||||
$this->m_aPackages[$sFilePath] = array('title' => $sTitle, 'type' => $sType, 'description' => $sDescription);
|
||||
$this->m_oZip->addFile($sExternalFilePath, $sFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given file from the archive
|
||||
* @param string $sFileName The path to the file inside the archive
|
||||
* @return string The content of the file read from the archive
|
||||
*/
|
||||
public function GetFileContents($sFileName)
|
||||
{
|
||||
return $this->m_oZip->getFromName($sFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the contents of the given file from the archive
|
||||
* @param string $sFileName The path to the file inside the archive
|
||||
* @param string $sDestinationFileName The path of the file to write
|
||||
* @return none
|
||||
*/
|
||||
public function ExtractToFile($sFileName, $sDestinationFileName)
|
||||
{
|
||||
$iBufferSize = 64 * 1024; // Read 64K at a time
|
||||
$oZipStream = $this->m_oZip->getStream($sFileName);
|
||||
$oDestinationStream = fopen($sDestinationFileName, 'wb');
|
||||
while (!feof($oZipStream)) {
|
||||
$sContents = fread($oZipStream, $iBufferSize);
|
||||
fwrite($oDestinationStream, $sContents);
|
||||
}
|
||||
fclose($oZipStream);
|
||||
fclose($oDestinationStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a SQL script taken from the archive. The package must be listed in the catalog and of type text/sql
|
||||
* @param string $sFileName The path to the SQL package inside the archive
|
||||
* @return boolean false in case of error, true otherwise
|
||||
*/
|
||||
public function ImportSql($sFileName, $sDatabase = 'itop')
|
||||
{
|
||||
if ( ($this->m_oZip->locateName($sFileName) == false) || (!isset($this->m_aPackages[$sFileName])) || ($this->m_aPackages[$sFileName]['type'] != 'text/sql'))
|
||||
{
|
||||
// invalid type or not listed in the catalog
|
||||
return false;
|
||||
}
|
||||
$sTempName = tempnam("../tmp/", "sql");
|
||||
//echo "Extracting to: '$sTempName'<br/>\n";
|
||||
$this->ExtractToFile($sFileName, $sTempName);
|
||||
// Note: the command line below works on Windows with the right path to mysql !!!
|
||||
$sCommandLine = 'type "'.$sTempName.'" | "/iTop/MySQL Server 5.0/bin/mysql.exe" -u root '.$sDatabase;
|
||||
//echo "Executing: '$sCommandLine'<br/>\n";
|
||||
exec($sCommandLine, $aOutput, $iRet);
|
||||
//echo "Return code: $iRet<br/>\n";
|
||||
//echo "Output:<br/><pre>\n";
|
||||
//print_r($aOutput);
|
||||
//echo "</pre><br/>\n";
|
||||
unlink($sTempName);
|
||||
return ($iRet == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps some part of the specified MySQL database into the archive as a text/sql package
|
||||
* @param $sTitle string A short title for this SQL script
|
||||
* @param $sDescription string A longer description of the purpose of this SQL script
|
||||
* @param $sFileName string The name of the package inside the archive
|
||||
* @param $sDatabase string name of the database
|
||||
* @param $aTables array array or table names. If empty, all tables are dumped
|
||||
* @param $bStructureOnly boolean Whether or not to dump the data or just the schema
|
||||
* @return boolean False in case of error, true otherwise
|
||||
*/
|
||||
public function AddDatabaseDump($sTitle, $sDescription, $sFileName, $sDatabase = 'itop', $aTables = array(), $bStructureOnly = true)
|
||||
{
|
||||
$sTempName = tempnam("../tmp/", "sql");
|
||||
$sNoData = $bStructureOnly ? "--no-data" : "";
|
||||
$sCommandLine = "\"/iTop/MySQL Server 5.0/bin/mysqldump.exe\" --user=root --opt $sNoData --result-file=$sTempName $sDatabase ".implode(" ", $aTables);
|
||||
//echo "Executing command: '$sCommandLine'<br/>\n";
|
||||
exec($sCommandLine, $aOutput, $iRet);
|
||||
//echo "Return code: $iRet<br/>\n";
|
||||
//echo "Output:<br/><pre>\n";
|
||||
//print_r($aOutput);
|
||||
//echo "</pre><br/>\n";
|
||||
if ($iRet == 0)
|
||||
{
|
||||
$this->AddPackage($sTempName, $sFileName, $sTitle, 'text/sql', $sDescription);
|
||||
}
|
||||
//unlink($sTempName);
|
||||
return ($iRet == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the consistency of the archive
|
||||
* @return boolean True if the archive file is consistent
|
||||
*/
|
||||
public function IsValid()
|
||||
{
|
||||
// TO DO: use a DTD to validate the XML instead of this hand-made validation
|
||||
$bResult = true;
|
||||
$aMandatoryTags = array('ARCHIVE' => array('VERSION'),
|
||||
'TITLE' => array(),
|
||||
'DESCRIPTION' => array(),
|
||||
'PACKAGE' => array('TYPE', 'HREF', 'TITLE'));
|
||||
|
||||
$sXmlCatalog = $this->m_oZip->getFromName('catalog.xml');
|
||||
$oParser = xml_parser_create();
|
||||
xml_parse_into_struct($oParser, $sXmlCatalog, $aValues, $aIndexes);
|
||||
xml_parser_free($oParser);
|
||||
|
||||
foreach($aMandatoryTags as $sTag => $aAttributes)
|
||||
{
|
||||
// Check that all the required tags are present
|
||||
if (!isset($aIndexes[$sTag]))
|
||||
{
|
||||
$this->m_aErrorMessages[] = "The XML catalog does not contain the mandatory tag $sTag.";
|
||||
$bResult = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($aIndexes[$sTag] as $iIndex)
|
||||
{
|
||||
switch($aValues[$iIndex]['type'])
|
||||
{
|
||||
case 'complete':
|
||||
case 'open':
|
||||
// Check that all the required attributes are present
|
||||
foreach($aAttributes as $sAttribute)
|
||||
{
|
||||
if (!isset($aValues[$iIndex]['attributes'][$sAttribute]))
|
||||
{
|
||||
$this->m_aErrorMessages[] = "The tag $sTag ($iIndex) does not contain the required attribute $sAttribute.";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// ignore other type of tags: close or cdata
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Unit test - reading an archive
|
||||
$sArchivePath = '../tmp/archive.zip';
|
||||
$oArchive = new iTopArchive($sArchivePath, iTopArchive::read);
|
||||
$oArchive->ReadCatalog();
|
||||
$oArchive->ImportSql('full_backup.sql');
|
||||
|
||||
// Writing an archive --
|
||||
|
||||
$sArchivePath = '../tmp/archive2.zip';
|
||||
$oArchive = new iTopArchive($sArchivePath, iTopArchive::create);
|
||||
$oArchive->SetTitle('First Archive !');
|
||||
$oArchive->SetDescription('This is just a test. Does not contain a lot of useful data.');
|
||||
$oArchive->AddPackage('../tmp/schema.sql', 'test.sql', 'this is just a test', 'text/sql', 'My first attempt at creating an archive from PHP...');
|
||||
$oArchive->WriteCatalog();
|
||||
|
||||
|
||||
$sArchivePath = '../tmp/archive2.zip';
|
||||
$oArchive = new iTopArchive($sArchivePath, iTopArchive::create);
|
||||
$oArchive->SetTitle('First Archive !');
|
||||
$oArchive->SetDescription('This is just a test. Does not contain a lot of useful data.');
|
||||
$oArchive->AddDatabaseDump('Test', 'This is my first automatic dump', 'schema.sql', 'itop', array('objects'));
|
||||
$oArchive->WriteCatalog();
|
||||
*/
|
||||
?>
|
||||
@@ -150,7 +150,7 @@ abstract class AsyncTask extends DBObject
|
||||
public function GetRetryDelay($iErrorCode = null)
|
||||
{
|
||||
$iRetryDelay = 600;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
|
||||
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($this)];
|
||||
@@ -162,12 +162,13 @@ abstract class AsyncTask extends DBObject
|
||||
public function GetMaxRetries($iErrorCode = null)
|
||||
{
|
||||
$iMaxRetries = 0;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
|
||||
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($this)];
|
||||
$iMaxRetries = $aConfig['max_retries'];
|
||||
}
|
||||
return $iMaxRetries;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,6 +381,6 @@ class AsyncSendEmail extends AsyncTask
|
||||
case EMAIL_SEND_ERROR:
|
||||
return "Failed: ".implode(', ', $aIssues);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2018 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/>
|
||||
|
||||
|
||||
/**
|
||||
* Typology for the attributes
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2018 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('MyHelpers.class.inc.php');
|
||||
require_once('ormdocument.class.inc.php');
|
||||
require_once('ormstopwatch.class.inc.php');
|
||||
@@ -73,7 +65,7 @@ define('EXTKEY_ABSOLUTE', 2);
|
||||
define('DEL_MANUAL', 1);
|
||||
|
||||
/**
|
||||
* Propagation of the deletion through an external key - ask the user to delete the referencing object
|
||||
* Propagation of the deletion through an external key - remove linked objects if ext key has is_null_allowed=false
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
@@ -512,7 +504,7 @@ abstract class AttributeDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sDefault
|
||||
* @param string|null $sDefault if null, will return the attribute code replacing "_" by " "
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
@@ -1030,6 +1022,14 @@ abstract class AttributeDefinition
|
||||
$oFormField->AddValidator(new \Combodo\iTop\Form\Validator\Validator($this->GetValidationPattern()));
|
||||
}
|
||||
|
||||
// Metadata
|
||||
$oFormField->AddMetadata('attribute-code', $this->GetCode());
|
||||
$oFormField->AddMetadata('attribute-type', get_class($this));
|
||||
if($this::IsScalar())
|
||||
{
|
||||
$oFormField->AddMetadata('value-raw', $oObject->Get($this->GetCode()));
|
||||
}
|
||||
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
@@ -1299,7 +1299,7 @@ class AttributeDashboard extends AttributeDefinition
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@@ -1374,6 +1374,11 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
*/
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
{
|
||||
if ($oHostObject === null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$sLinkClass = $this->GetLinkedClass();
|
||||
$sExtKeyToMe = $this->GetExtKeyToMe();
|
||||
|
||||
@@ -2764,7 +2769,7 @@ class AttributeDecimal extends AttributeDBField
|
||||
|
||||
if (!is_null($value) && ($value !== ''))
|
||||
{
|
||||
$value = sprintf("%01.".$this->Get('decimals')."f", $value);
|
||||
$value = sprintf("%01.".$this->Get('decimals')."F", $value);
|
||||
}
|
||||
return $value; // null or string
|
||||
}
|
||||
@@ -3264,10 +3269,13 @@ class AttributeClassState extends AttributeString
|
||||
$sClass = $oHostObj->Get($sTargetClass);
|
||||
|
||||
$aAllowedStates = array();
|
||||
$aValues = MetaModel::EnumStates($sClass);
|
||||
foreach(array_keys($aValues) as $sState)
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass)
|
||||
{
|
||||
$aAllowedStates[$sState] = $sState.' ('.MetaModel::GetStateLabel($sClass, $sState).')';
|
||||
$aValues = MetaModel::EnumStates($sChildClass);
|
||||
foreach (array_keys($aValues) as $sState)
|
||||
{
|
||||
$aAllowedStates[$sState] = $sState.' ('.MetaModel::GetStateLabel($sChildClass, $sState).')';
|
||||
}
|
||||
}
|
||||
return $aAllowedStates;
|
||||
}
|
||||
@@ -3286,9 +3294,15 @@ class AttributeClassState extends AttributeString
|
||||
{
|
||||
$sTargetClass = $this->Get('class_field');
|
||||
$sClass = $oHostObject->Get($sTargetClass);
|
||||
|
||||
$sHTML = '<span class="attribute-set-item" data-code="'.$sValue.'" data-label="'.$sValue.' ('.MetaModel::GetStateLabel($sClass, $sValue).')'.'" data-description="">'.$sValue.'</span>';
|
||||
return $sHTML;
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass)
|
||||
{
|
||||
$aValues = MetaModel::EnumStates($sChildClass);
|
||||
if (in_array($sValue, $aValues))
|
||||
{
|
||||
$sHTML = '<span class="attribute-set-item" data-code="'.$sValue.'" data-label="'.$sValue.' ('.MetaModel::GetStateLabel($sChildClass, $sValue).')'.'" data-description="">'.$sValue.'</span>';
|
||||
return $sHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sValue;
|
||||
@@ -3541,6 +3555,22 @@ class AttributeFinalClass extends AttributeString
|
||||
|
||||
return $aLocalizedValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \CoreException
|
||||
* @since 2.7
|
||||
*/
|
||||
public function CopyOnAllTables()
|
||||
{
|
||||
$sClass = self::GetHostClass();
|
||||
if (MetaModel::IsLeafClass($sClass))
|
||||
{
|
||||
// Leaf class, no finalclass
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6242,6 +6272,15 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
|
||||
{
|
||||
if (!is_null($oHostObject))
|
||||
{
|
||||
return $oHostObject->GetAsHTML($this->GetCode(), $oHostObject);
|
||||
}
|
||||
|
||||
return DBObject::MakeHyperLink($this->GetTargetClass(), $sValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6502,26 +6541,60 @@ class AttributeExternalField extends AttributeDefinition
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDefault
|
||||
*
|
||||
* @return string dict entry if defined, otherwise :
|
||||
* <ul>
|
||||
* <li>if field is a friendlyname then display the label of the ExternalKey
|
||||
* <li>the class hierarchy -> field name
|
||||
*
|
||||
* <p>For example, having this :
|
||||
*
|
||||
* <pre>
|
||||
* +---------------------+ +--------------------+ +--------------+
|
||||
* | Class A | | Class B | | Class C |
|
||||
* +---------------------+ +--------------------+ +--------------+
|
||||
* | foo <ExternalField>-------->c_id_friendly_name--------->friendlyname |
|
||||
* +---------------------+ +--------------------+ +--------------+
|
||||
* </pre>
|
||||
*
|
||||
* <p>The ExternalField foo points to a magical field that is brought by c_id ExternalKey in class B.
|
||||
*
|
||||
* <p>In the normal case the foo label would be : B -> C -> friendlyname<br>
|
||||
* But as foo is a friendlyname its label will be the same as the one on A.b_id field
|
||||
* This can be overrided with dict key Class:ClassA/Attribute:foo
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetLabel($sDefault = null)
|
||||
{
|
||||
$sLabelDefaultValue = '';
|
||||
$sLabel = parent::GetLabel($sLabelDefaultValue);
|
||||
if ($sLabelDefaultValue !== $sLabel)
|
||||
{
|
||||
return $sLabel;
|
||||
}
|
||||
|
||||
if ($this->IsFriendlyName())
|
||||
{
|
||||
// This will be used even if we are pointing to a friendlyname in a distance > 1
|
||||
// For example we can link to a magic friendlyname (like org_id_friendlyname)
|
||||
// If a specific label is needed, use a Dict key !
|
||||
// See N°2174
|
||||
$sKeyAttCode = $this->Get("extkey_attcode");
|
||||
$oExtKeyAttDef = MetaModel::GetAttributeDef($this->GetHostClass(), $sKeyAttCode);
|
||||
$sLabel = $oExtKeyAttDef->GetLabel($this->m_sCode);
|
||||
|
||||
return $sLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sLabel = parent::GetLabel('');
|
||||
if (strlen($sLabel) == 0)
|
||||
{
|
||||
$oRemoteAtt = $this->GetExtAttDef();
|
||||
$sLabel = $oRemoteAtt->GetLabel($this->m_sCode);
|
||||
$oKeyAtt = $this->GetKeyAttDef();
|
||||
$sKeyLabel = $oKeyAtt->GetLabel($this->GetKeyAttCode());
|
||||
$sLabel = "{$sKeyLabel}->{$sLabel}";
|
||||
}
|
||||
}
|
||||
|
||||
$oRemoteAtt = $this->GetExtAttDef();
|
||||
$sLabel = $oRemoteAtt->GetLabel($this->m_sCode);
|
||||
$oKeyAtt = $this->GetKeyAttDef();
|
||||
$sKeyLabel = $oKeyAtt->GetLabel($this->GetKeyAttCode());
|
||||
$sLabel = "{$sKeyLabel}->{$sLabel}";
|
||||
|
||||
return $sLabel;
|
||||
}
|
||||
@@ -6840,7 +6913,16 @@ class AttributeExternalField extends AttributeDefinition
|
||||
{
|
||||
$sFormFieldClass = $oRemoteAttDef::GetFormFieldClass();
|
||||
}
|
||||
/** @var \Combodo\iTop\Form\Field\Field $oFormField */
|
||||
$oFormField = new $sFormFieldClass($this->GetCode());
|
||||
switch ($sFormFieldClass)
|
||||
{
|
||||
case '\Combodo\iTop\Form\Field\SelectField':
|
||||
$oFormField->SetChoices($oRemoteAttDef->GetAllowedValues($oObject->ToArgsForQuery()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
parent::MakeFormField($oObject, $oFormField);
|
||||
|
||||
@@ -7239,6 +7321,7 @@ class AttributeBlob extends AttributeDefinition
|
||||
|
||||
public function MakeFormField(DBObject $oObject, $oFormField = null)
|
||||
{
|
||||
/** @var $oFormField \Combodo\iTop\Form\Field\BlobField */
|
||||
if ($oFormField === null)
|
||||
{
|
||||
$sFormFieldClass = static::GetFormFieldClass();
|
||||
@@ -7248,13 +7331,24 @@ class AttributeBlob extends AttributeDefinition
|
||||
// Note: As of today we want this field to always be read-only
|
||||
$oFormField->SetReadOnly(true);
|
||||
|
||||
// Generating urls
|
||||
$value = $oObject->Get($this->GetCode());
|
||||
$oFormField->SetDownloadUrl($value->GetDownloadURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
$oFormField->SetDisplayUrl($value->GetDisplayURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
|
||||
// Calling parent before so current value is set, then proceed
|
||||
parent::MakeFormField($oObject, $oFormField);
|
||||
|
||||
// Setting current value correctly as the default method returns an empty string when there is no file yet.
|
||||
/** @var \ormDocument $value */
|
||||
$value = $oObject->Get($this->GetCode());
|
||||
if(!is_object($value))
|
||||
{
|
||||
$oFormField->SetCurrentValue(new ormDocument());
|
||||
}
|
||||
|
||||
// Generating urls
|
||||
if(is_object($value) && !$value->IsEmpty())
|
||||
{
|
||||
$oFormField->SetDownloadUrl($value->GetDownloadURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
$oFormField->SetDisplayUrl($value->GetDisplayURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
}
|
||||
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
@@ -7334,7 +7428,17 @@ class AttributeImage extends AttributeBlob
|
||||
return '<div class="'.$sCssClasses.'" style="width: '.$iMaxWidthPx.'; height: '.$iMaxHeightPx.';"><span class="helper-middle"></span>'.$sRet.'</div>';
|
||||
}
|
||||
|
||||
private function GetHtmlForImageUrl($sUrl, $iMaxWidthPx, $iMaxHeightPx) {
|
||||
/**
|
||||
* @param string $sUrl
|
||||
* @param int $iMaxWidthPx
|
||||
* @param int $iMaxHeightPx
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.6.0 new private method
|
||||
* @since 2.7.0 change visibility to protected
|
||||
*/
|
||||
protected function GetHtmlForImageUrl($sUrl, $iMaxWidthPx, $iMaxHeightPx) {
|
||||
return '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'; max-height: '.$iMaxHeightPx.'">';
|
||||
}
|
||||
|
||||
@@ -7343,8 +7447,11 @@ class AttributeImage extends AttributeBlob
|
||||
* @param \DBObject $oHostObject
|
||||
*
|
||||
* @return null|string
|
||||
*
|
||||
* @since 2.6.0 new private method
|
||||
* @since 2.7.0 change visibility to protected
|
||||
*/
|
||||
private function GetAttributeImageFileUrl($value, $oHostObject) {
|
||||
protected function GetAttributeImageFileUrl($value, $oHostObject) {
|
||||
if (!is_object($value)) {
|
||||
return null;
|
||||
}
|
||||
@@ -7813,6 +7920,87 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
throw new CoreException("Unknown item code '$sItemCode' for attribute ".$this->GetHostClass().'::'.$this->GetCode());
|
||||
}
|
||||
|
||||
|
||||
public function GetSubItemSearchType($sItemCode)
|
||||
{
|
||||
switch ($sItemCode)
|
||||
{
|
||||
case 'timespent':
|
||||
return static::SEARCH_WIDGET_TYPE_NUMERIC; //seconds
|
||||
case 'started':
|
||||
case 'laststart':
|
||||
case 'stopped':
|
||||
return static::SEARCH_WIDGET_TYPE_DATE_TIME; //timestamp
|
||||
}
|
||||
|
||||
foreach($this->ListThresholds() as $iThreshold => $aFoo)
|
||||
{
|
||||
$sThPrefix = $iThreshold.'_';
|
||||
if (substr($sItemCode, 0, strlen($sThPrefix)) == $sThPrefix)
|
||||
{
|
||||
// The current threshold is concerned
|
||||
$sThresholdCode = substr($sItemCode, strlen($sThPrefix));
|
||||
switch ($sThresholdCode)
|
||||
{
|
||||
case 'deadline':
|
||||
return static::SEARCH_WIDGET_TYPE_DATE_TIME; //timestamp
|
||||
case 'passed':
|
||||
case 'triggered':
|
||||
return static::SEARCH_WIDGET_TYPE_ENUM; //booleans, used in conjuction with GetSubItemAllowedValues and IsSubItemNullAllowed
|
||||
case 'overrun':
|
||||
return static::SEARCH_WIDGET_TYPE_NUMERIC; //seconds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static::SEARCH_WIDGET_TYPE_RAW;
|
||||
}
|
||||
|
||||
public function GetSubItemAllowedValues($sItemCode, $aArgs = array(), $sContains = '')
|
||||
{
|
||||
foreach($this->ListThresholds() as $iThreshold => $aFoo)
|
||||
{
|
||||
$sThPrefix = $iThreshold.'_';
|
||||
if (substr($sItemCode, 0, strlen($sThPrefix)) == $sThPrefix)
|
||||
{
|
||||
// The current threshold is concerned
|
||||
$sThresholdCode = substr($sItemCode, strlen($sThPrefix));
|
||||
switch ($sThresholdCode)
|
||||
{
|
||||
case 'passed':
|
||||
case 'triggered':
|
||||
return array(
|
||||
0 => $this->GetBooleanLabel(0),
|
||||
1 => $this->GetBooleanLabel(1),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function IsSubItemNullAllowed($sItemCode, $bDefaultValue)
|
||||
{
|
||||
foreach($this->ListThresholds() as $iThreshold => $aFoo)
|
||||
{
|
||||
$sThPrefix = $iThreshold.'_';
|
||||
if (substr($sItemCode, 0, strlen($sThPrefix)) == $sThPrefix)
|
||||
{
|
||||
// The current threshold is concerned
|
||||
$sThresholdCode = substr($sItemCode, strlen($sThPrefix));
|
||||
switch ($sThresholdCode)
|
||||
{
|
||||
case 'passed':
|
||||
case 'triggered':
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bDefaultValue;
|
||||
}
|
||||
|
||||
protected function GetBooleanLabel($bValue)
|
||||
{
|
||||
$sDictKey = $bValue ? 'yes' : 'no';
|
||||
@@ -8162,9 +8350,39 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
*/
|
||||
class AttributeSubItem extends AttributeDefinition
|
||||
{
|
||||
const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW;
|
||||
/**
|
||||
* Return the search widget type corresponding to this attribute
|
||||
* the computation is made by AttributeStopWatch::GetSubItemSearchType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchType()
|
||||
{
|
||||
/** @var AttributeStopWatch $oParent */
|
||||
$oParent = $this->GetTargetAttDef();
|
||||
|
||||
static public function ListExpectedParams()
|
||||
return $oParent->GetSubItemSearchType($this->Get('item_code'));
|
||||
}
|
||||
|
||||
public function GetAllowedValues($aArgs = array(), $sContains = '')
|
||||
{
|
||||
/** @var AttributeStopWatch $oParent */
|
||||
$oParent = $this->GetTargetAttDef();
|
||||
|
||||
return $oParent->GetSubItemAllowedValues($this->Get('item_code'), $aArgs, $sContains);
|
||||
}
|
||||
|
||||
public function IsNullAllowed()
|
||||
{
|
||||
/** @var AttributeStopWatch $oParent */
|
||||
$oParent = $this->GetTargetAttDef();
|
||||
|
||||
$bDefaultValue = parent::IsNullAllowed();
|
||||
|
||||
return $oParent->IsSubItemNullAllowed($this->Get('item_code'), $bDefaultValue);
|
||||
}
|
||||
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array('target_attcode', 'item_code'));
|
||||
}
|
||||
@@ -9655,14 +9873,27 @@ class AttributeTagSet extends AttributeSet
|
||||
{
|
||||
$aJson['partial_values'] = array();
|
||||
$aJson['orig_value'] = array();
|
||||
$aJson['added'] = array();
|
||||
$aJson['removed'] = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJson['partial_values'] = $oValue->GetModified();
|
||||
$aJson['orig_value'] = array_merge($oValue->GetValues(), $oValue->GetModified());
|
||||
$aJson['added'] = $oValue->GetAdded();
|
||||
$aJson['removed'] = $oValue->GetRemoved();
|
||||
|
||||
if ($oValue->DisplayPartial())
|
||||
{
|
||||
// For bulk updates
|
||||
$aJson['partial_values'] = $oValue->GetModified();
|
||||
}
|
||||
else
|
||||
{
|
||||
// For simple updates
|
||||
$aJson['partial_values'] = array();
|
||||
}
|
||||
}
|
||||
$aJson['added'] = array();
|
||||
$aJson['removed'] = array();
|
||||
|
||||
|
||||
$iMaxTags = $this->GetMaxItems();
|
||||
$aJson['max_items_allowed'] = $iMaxTags;
|
||||
|
||||
@@ -33,6 +33,7 @@ MetaModel::IncludeModule('core/tagsetfield.class.inc.php');
|
||||
MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php');
|
||||
MetaModel::IncludeModule('core/backgroundtask.class.inc.php');
|
||||
MetaModel::IncludeModule('core/inlineimage.class.inc.php');
|
||||
MetaModel::IncludeModule('core/counter.class.inc.php');
|
||||
|
||||
MetaModel::IncludeModule('webservices/webservices.basic.php');
|
||||
|
||||
|
||||
@@ -56,8 +56,9 @@ interface iBackgroundProcess extends iProcess
|
||||
* interface iScheduledProcess
|
||||
* A variant of process that must be called at specific times
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
* @see \AbstractWeeklyScheduledProcess for a bootstrap implementation
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
*/
|
||||
interface iScheduledProcess extends iProcess
|
||||
{
|
||||
@@ -67,14 +68,189 @@ interface iScheduledProcess extends iProcess
|
||||
public function GetNextOccurrence();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class ProcessException
|
||||
* Exception for iProcess implementations.<br>
|
||||
* Implementation of {@link iScheduledProcess}, using config parameters for module
|
||||
*
|
||||
* Use these parameters :
|
||||
*
|
||||
* * enabled
|
||||
* * week_days
|
||||
* * time
|
||||
*
|
||||
* Param names and some of their default values are in constant that can be overriden.
|
||||
*
|
||||
* Other info (module name and time default value) should be provided using a method that needs to be implemented.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
|
||||
{
|
||||
// param have default names/values but can be overriden
|
||||
const MODULE_SETTING_ENABLED = 'enabled';
|
||||
const DEFAULT_MODULE_SETTING_ENABLED = true;
|
||||
const MODULE_SETTING_WEEKDAYS = 'week_days';
|
||||
const DEFAULT_MODULE_SETTING_WEEKDAYS = 'monday, tuesday, wednesday, thursday, friday, saturday, sunday';
|
||||
const MODULE_SETTING_TIME = 'time';
|
||||
|
||||
/**
|
||||
* Module must be declared in each implementation
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function GetModuleName();
|
||||
|
||||
/**
|
||||
* @return string default value for {@link MODULE_SETTING_TIME} config param.
|
||||
* example '23:30'
|
||||
*/
|
||||
abstract protected function GetDefaultModuleSettingTime();
|
||||
|
||||
/**
|
||||
* Interpret current setting for the week days
|
||||
*
|
||||
* @returns int[] (monday = 1)
|
||||
* @throws ProcessInvalidConfigException
|
||||
*/
|
||||
public function InterpretWeekDays()
|
||||
{
|
||||
static $aWEEKDAYTON = array(
|
||||
'monday' => 1,
|
||||
'tuesday' => 2,
|
||||
'wednesday' => 3,
|
||||
'thursday' => 4,
|
||||
'friday' => 5,
|
||||
'saturday' => 6,
|
||||
'sunday' => 7,
|
||||
);
|
||||
$aDays = array();
|
||||
$sWeekDays = MetaModel::GetConfig()->GetModuleSetting(
|
||||
$this->GetModuleName(),
|
||||
static::MODULE_SETTING_WEEKDAYS,
|
||||
static::DEFAULT_MODULE_SETTING_WEEKDAYS
|
||||
);
|
||||
|
||||
if ($sWeekDays !== '')
|
||||
{
|
||||
$aWeekDaysRaw = explode(',', $sWeekDays);
|
||||
foreach ($aWeekDaysRaw as $sWeekDay)
|
||||
{
|
||||
$sWeekDay = strtolower(trim($sWeekDay));
|
||||
if (array_key_exists($sWeekDay, $aWEEKDAYTON))
|
||||
{
|
||||
$aDays[] = $aWEEKDAYTON[$sWeekDay];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_WEEKDAYS."' (found '$sWeekDay')");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($aDays) === 0)
|
||||
{
|
||||
throw new ProcessInvalidConfigException($this->GetModuleName().': missing setting \''.static::MODULE_SETTING_WEEKDAYS.'\'');
|
||||
}
|
||||
$aDays = array_unique($aDays);
|
||||
sort($aDays);
|
||||
|
||||
return $aDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the exact time at which the process must be run next time
|
||||
*
|
||||
* @return DateTime
|
||||
* @throws Exception
|
||||
*/
|
||||
public function GetNextOccurrence()
|
||||
{
|
||||
$bEnabled = MetaModel::GetConfig()->GetModuleSetting(
|
||||
$this->GetModuleName(),
|
||||
static::MODULE_SETTING_ENABLED,
|
||||
static::DEFAULT_MODULE_SETTING_ENABLED
|
||||
);
|
||||
if (!$bEnabled)
|
||||
{
|
||||
return new DateTime('3000-01-01');
|
||||
}
|
||||
|
||||
// 1st - Interpret the list of days as ordered numbers (monday = 1)
|
||||
//
|
||||
$aDays = $this->InterpretWeekDays();
|
||||
|
||||
// 2nd - Find the next active week day
|
||||
//
|
||||
$sProcessTime = MetaModel::GetConfig()->GetModuleSetting(
|
||||
$this->GetModuleName(),
|
||||
static::MODULE_SETTING_TIME,
|
||||
static::GetDefaultModuleSettingTime()
|
||||
);
|
||||
if (!preg_match('/[0-2]\d:[0-5]\d/', $sProcessTime))
|
||||
{
|
||||
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')");
|
||||
}
|
||||
$oNow = new DateTime();
|
||||
$iNextPos = false;
|
||||
for ($iDay = $oNow->format('N'); $iDay <= 7; $iDay++)
|
||||
{
|
||||
$iNextPos = array_search($iDay, $aDays, true);
|
||||
if ($iNextPos !== false)
|
||||
{
|
||||
if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sProcessTime))
|
||||
{
|
||||
break;
|
||||
}
|
||||
$iNextPos = false; // necessary on sundays
|
||||
}
|
||||
}
|
||||
|
||||
// 3rd - Compute the result
|
||||
//
|
||||
if ($iNextPos === false)
|
||||
{
|
||||
// Jump to the first day within the next week
|
||||
$iFirstDayOfWeek = $aDays[0];
|
||||
$iDayMove = $oNow->format('N') - $iFirstDayOfWeek;
|
||||
$oRet = clone $oNow;
|
||||
$oRet->modify('-'.$iDayMove.' days');
|
||||
$oRet->modify('+1 weeks');
|
||||
}
|
||||
else
|
||||
{
|
||||
$iNextDayOfWeek = $aDays[$iNextPos];
|
||||
$iMove = $iNextDayOfWeek - $oNow->format('N');
|
||||
$oRet = clone $oNow;
|
||||
$oRet->modify('+'.$iMove.' days');
|
||||
}
|
||||
list($sHours, $sMinutes) = explode(':', $sProcessTime);
|
||||
$oRet->setTime((int)$sHours, (int)$sMinutes);
|
||||
|
||||
return $oRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \iProcess
|
||||
*
|
||||
* @param int $iUnixTimeLimit
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function Process($iUnixTimeLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for {@link iProcess} implementations.<br>
|
||||
* An error happened during the processing but we can go on with the next implementations.
|
||||
*/
|
||||
class ProcessException extends CoreException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class ProcessInvalidConfigException extends ProcessException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,5 +260,4 @@ class ProcessException extends CoreException
|
||||
*/
|
||||
class ProcessFatalException extends CoreException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user