Compare commits
5498 Commits
Author | SHA1 | Date | |
---|---|---|---|
823e1cfd0e | |||
c0e6781dda | |||
341e002ef2 | |||
a87d04ef5f | |||
11656c72ca | |||
72ee7c9ab6 | |||
483ebd64fe | |||
1a6fadf976 | |||
9b3c7707f0 | |||
261ef2f312 | |||
0abb336850 | |||
82b55210d8 | |||
41f36ef5e6 | |||
71dfbff8d7 | |||
1c57e8dd1d | |||
625308b74b | |||
466e557c1d | |||
121013a48a | |||
1fcc5f92a8 | |||
1c8e2038f6 | |||
29b0a28173 | |||
bd6d5f0128 | |||
6bbd622a98 | |||
d39bf7bc86 | |||
ffd80cde21 | |||
65e2dc8dff | |||
e52c25ad0b | |||
55c7791efa | |||
ec2fc0ab4f | |||
16d4d16950 | |||
b7be76a7e4 | |||
d6072c8591 | |||
23d2631fd7 | |||
06b3690d48 | |||
3c32b3650e | |||
101bae34e8 | |||
f7d53906e2 | |||
bdc9e40627 | |||
d5dfdca9d2 | |||
ce6c4929a0 | |||
c3ac31de69 | |||
24e1238e50 | |||
281e578f4d | |||
1a88ae05e6 | |||
df0c579af0 | |||
a25dbc6bd2 | |||
8e1c8a5ba5 | |||
cce2983347 | |||
6c2bed771c | |||
ae265ba5e7 | |||
909c79559b | |||
97c8573de8 | |||
6274d2c1ff | |||
409b7edb94 | |||
6b82b3af83 | |||
3013f33b35 | |||
77fbb45c71 | |||
2a0849e49a | |||
ac8e713935 | |||
118dfc79b3 | |||
6727752a2d | |||
75a6a093ed | |||
922cba9f5a | |||
35d0b2aa3c | |||
776afaff03 | |||
1c46900156 | |||
08a2264709 | |||
f7db1bf20f | |||
ffd14a8734 | |||
161c1bcb80 | |||
02514ff446 | |||
fdce67d101 | |||
8d1cbc6b88 | |||
b73f8a1c28 | |||
00a0c3d795 | |||
6b8d769e43 | |||
10b79c586b | |||
3c3579a29d | |||
017f02afc4 | |||
df235541d1 | |||
a456047969 | |||
ac48e61264 | |||
604bf2db77 | |||
4055d3e68a | |||
393722038b | |||
54c90bec11 | |||
039ee80db4 | |||
9f30f356cb | |||
fd10883652 | |||
6805111c47 | |||
86ce4a75b4 | |||
03932db20d | |||
d3f247f6fb | |||
c5af0fb37c | |||
9532be0cdc | |||
e0748c2eb6 | |||
5811836238 | |||
92b3854516 | |||
e85801db50 | |||
53dd6a82e6 | |||
75b230b2ed | |||
47a5ddb442 | |||
d0f779bb9b | |||
568b79e854 | |||
06bbeb0d2e | |||
75bb94b9a7 | |||
dfd0f1ad2a | |||
7a4b1589af | |||
da9d8d9d62 | |||
e3bc6ce1d3 | |||
ecd0f5827a | |||
c8be7f84a4 | |||
826e6264eb | |||
cc0b6edb34 | |||
0e564a24c9 | |||
7da12be242 | |||
095e317f3b | |||
67eeef26a0 | |||
2273812b2d | |||
4842e3f62b | |||
01c69f0712 | |||
baa5b762e2 | |||
76cd034fd3 | |||
a929fb3482 | |||
5ea3e12e26 | |||
141a22b6ff | |||
3f1d19f53e | |||
fcfb3ea677 | |||
dfceb941db | |||
9db6e5ac13 | |||
aceb94da3e | |||
12c7682a26 | |||
5d282a4cc4 | |||
a8bf3ec857 | |||
bb9573a82f | |||
15534ba9fa | |||
6aecf5e796 | |||
25f81af87b | |||
c78b43f7b0 | |||
6daeb9e474 | |||
5986e8a378 | |||
14068d24a8 | |||
dd7ee7f2ef | |||
0f1bd2377e | |||
5326b94c04 | |||
17f8fb3b58 | |||
ceca7b10b5 | |||
89c0ae5ead | |||
89be290465 | |||
3c3b122fe4 | |||
61369e7ad1 | |||
2c31e1aefc | |||
eb28a76636 | |||
86afa350fa | |||
6864132afc | |||
49ab83efd3 | |||
27d7b07239 | |||
48ee5c5e1b | |||
be87e4c740 | |||
7f6d010b9c | |||
62437c8fac | |||
2d3b999d27 | |||
72655e6673 | |||
de0749b51b | |||
3598ab2954 | |||
67d94bce61 | |||
fa158effc3 | |||
3e3781bc28 | |||
bc70f39ba5 | |||
998eb3b8a1 | |||
8fd4d2f9bc | |||
f04bc17e28 | |||
ca0561d97c | |||
2251d34122 | |||
eb832f42e5 | |||
83b4103788 | |||
1b9c65189d | |||
c2281b93ef | |||
1b3601ce87 | |||
78905834bd | |||
c270546a9b | |||
ad15e8b827 | |||
f84bcbb878 | |||
62d4d8243a | |||
3e238af50a | |||
54a0add941 | |||
d84f94817b | |||
2939545c8c | |||
c4dc05a4c1 | |||
87b763ddae | |||
c745711a2e | |||
49c8f567e6 | |||
2a1b5e2900 | |||
f2ab357654 | |||
8ad199ee3d | |||
6ddadfd8e5 | |||
cee8b784a4 | |||
f8e2dd5fab | |||
20a4cc45d7 | |||
8db6367cba | |||
090a4318b3 | |||
d17fa93bb7 | |||
f030c2f064 | |||
323cea2e0b | |||
f81fad1c49 | |||
ad3e9aba65 | |||
b035efb710 | |||
ffc373e68f | |||
e42f0bd538 | |||
b86f7fbd4a | |||
96b12bf0d4 | |||
97e50f245c | |||
9d32fa2b86 | |||
5937915d21 | |||
ca15d8f362 | |||
f097111d70 | |||
177541bef3 | |||
3f2a33a7fe | |||
cd9c62b3a3 | |||
4a2d59e4b8 | |||
c702c41fed | |||
b3e3ead5ac | |||
9bfa8280fd | |||
55b4e7335d | |||
f7c2aab390 | |||
cdab4659a6 | |||
fc69015448 | |||
9e656294a6 | |||
8e91faf2d2 | |||
36c8619b63 | |||
d77afce37b | |||
bca34949a9 | |||
07baed8713 | |||
6687c324e5 | |||
03d1dacb88 | |||
77d8296642 | |||
999370646b | |||
d8f4af660f | |||
5f146bfbdc | |||
950ba8cc9d | |||
2448e50793 | |||
5e29699563 | |||
b78fc84a89 | |||
665c8dea6d | |||
159297e421 | |||
fc502a1c64 | |||
457c8e0f66 | |||
660398bad7 | |||
fad19249db | |||
060aa9e4d5 | |||
9052247e53 | |||
df06b1f7ba | |||
8d324f9c79 | |||
f18d4eee1d | |||
fd51122918 | |||
15bd0400ea | |||
1147b5c5e1 | |||
2cbd3d5923 | |||
11753b4476 | |||
f2a6d35351 | |||
c4a23de744 | |||
a47cbe49fe | |||
5f5815cbd9 | |||
e811660d7c | |||
10083e7ee8 | |||
d89455d86a | |||
5e7c9597cd | |||
49180ab4ed | |||
c4fc466876 | |||
75203d6e8e | |||
f61c2a977a | |||
a02ce894c8 | |||
2d92bd3963 | |||
b8c0b47faf | |||
2a8563ce9a | |||
f924a2b2b3 | |||
5846c111fe | |||
f86f38d8b0 | |||
68d0aaff84 | |||
f5f04c90d9 | |||
d8525bf123 | |||
25d6192e0e | |||
90a5a8a96a | |||
69852c82bc | |||
f3ae03a133 | |||
9b5cc38c94 | |||
890cf97127 | |||
87a1f2cd18 | |||
50fc319afd | |||
a2f53e1e58 | |||
e6b9cb16b5 | |||
6f2447533c | |||
6f946b32ac | |||
33e2dca864 | |||
a890a70beb | |||
e92c709796 | |||
bcf75ebfbd | |||
c8a6a21f9c | |||
a176556081 | |||
949373b39e | |||
e26beac06c | |||
4bfc75288f | |||
d1e4c9761f | |||
dbafb6f4bb | |||
7ad8e3ea05 | |||
e142f961d9 | |||
5c97b5cea6 | |||
d21cfcba78 | |||
c9300e5979 | |||
8cefdd027d | |||
c3ade0fe0f | |||
d3284c67d8 | |||
6b3085ef27 | |||
748e6d0873 | |||
a9abe8aaa1 | |||
1fbf91a9cb | |||
9485ebe4cb | |||
88e7cb8761 | |||
857a6ff808 | |||
2d6bbcec9e | |||
748bb3befb | |||
29d6b1c758 | |||
696ca111b7 | |||
a8381b4c18 | |||
0895abc30b | |||
3539c3b04e | |||
77aa46f753 | |||
42ef876963 | |||
3bfcaa4187 | |||
5a5e9dc72c | |||
4606d987b2 | |||
b403816c88 | |||
470c017184 | |||
0720db7b17 | |||
1a61f34c19 | |||
94eda284ed | |||
9ae67cd2f3 | |||
b6b5461241 | |||
9fac118004 | |||
92c7384816 | |||
9be5dab828 | |||
c6ae372429 | |||
22e0b71012 | |||
f0bec949bb | |||
0d42ca0740 | |||
18228b1b8e | |||
824ab8401a | |||
7249abc649 | |||
5336720809 | |||
3a7e4e8db6 | |||
51cc6b41a7 | |||
38b3a72c92 | |||
fb79bce39c | |||
2c6b29747a | |||
fd28afdd80 | |||
032a150b11 | |||
c34e249cd0 | |||
953ba662e8 | |||
e79ef549d6 | |||
5459aae163 | |||
a3145fbd00 | |||
bd04f94c76 | |||
74da56e58d | |||
b26e7dcb7d | |||
3cee46072b | |||
b590f91534 | |||
10e6822ad5 | |||
9944a192e2 | |||
8ad50b10dd | |||
ee90649833 | |||
a4601da9e0 | |||
b1fcd4ecc8 | |||
e110eba5d8 | |||
30e602adc2 | |||
1989d642fc | |||
1a3413f702 | |||
b61d78dbaa | |||
a0dca415b5 | |||
88fd7e5d49 | |||
0253e55de2 | |||
bff6911bb4 | |||
4542f9f9b2 | |||
323ff59b41 | |||
590d36ede2 | |||
a7cc6ee6d0 | |||
ad1edcf9a2 | |||
eeb96186c1 | |||
2e839715b5 | |||
548fd25756 | |||
ff2fbcddef | |||
022bc9ce7b | |||
cbe5dc9376 | |||
de564c31a0 | |||
8927026ee4 | |||
3cda662220 | |||
f9f55be851 | |||
05da19288e | |||
d2efd48aea | |||
3028fc13cd | |||
14bc21f3d5 | |||
b23b1f2e06 | |||
7a75eb3472 | |||
2cff4db256 | |||
666b564215 | |||
f46b7ea0e4 | |||
b2134f1841 | |||
7b76ab131f | |||
0b7c7678bd | |||
b967a09aa5 | |||
ca1ee90f52 | |||
65b62c7b5a | |||
4176043958 | |||
28927ad747 | |||
92d0618907 | |||
a9f3e1ba26 | |||
e0ba8a81fe | |||
ad9a1120f4 | |||
8619b49d19 | |||
409e10fad1 | |||
a7b4ea2d15 | |||
cd0d35279e | |||
f25b1a1154 | |||
bf2ddaef9f | |||
ca732f3ca6 | |||
9ffdfd25d0 | |||
aadcb23282 | |||
bc817b750e | |||
2e76d9d305 | |||
9300ab9640 | |||
3753808b98 | |||
446ad40f96 | |||
fb18127346 | |||
26623db2b7 | |||
1a27befb75 | |||
e2e261e01b | |||
713b5ebb96 | |||
7ab84f63c9 | |||
79efa1f1a9 | |||
1570d71470 | |||
da03bcfa5b | |||
eca93bc3af | |||
fbfb97bf14 | |||
67452ceb8d | |||
abf920ea36 | |||
9390809f6b | |||
a5737b7553 | |||
8fca6e2485 | |||
1702bcef88 | |||
ef4c0cdd45 | |||
4dbd5292bc | |||
2784ad2209 | |||
19a60d9e76 | |||
73223780a1 | |||
fc8b05efca | |||
13f236ea03 | |||
8372ee2ad2 | |||
d1efca6560 | |||
78b05a211d | |||
fff6c3b086 | |||
7878f972e5 | |||
74f33031a8 | |||
eeb2f78770 | |||
f24bd9a4b9 | |||
251d98ea03 | |||
c0963f90bd | |||
de41c5ac01 | |||
6794db3719 | |||
5bba67c169 | |||
95ac9e7d28 | |||
4d0a09cad0 | |||
bad28659df | |||
c21986a97e | |||
5ed49819ca | |||
5660620685 | |||
6c39349989 | |||
eea5e43149 | |||
a96bee2873 | |||
961fcb2ecd | |||
34aa4f4c25 | |||
17d1e7e4b4 | |||
a74f92a0a9 | |||
d160b5df52 | |||
26d55460fb | |||
05106a0d18 | |||
0724114e96 | |||
4b7826b078 | |||
497a51ea18 | |||
d682636992 | |||
2e556c175a | |||
90d8f0b129 | |||
b9e0e0db39 | |||
f9a1982b16 | |||
d5b52e78fc | |||
0cb4a00ca2 | |||
036469232a | |||
d7cdad6b6e | |||
003fedcef5 | |||
1d083f5f19 | |||
2758ec5f1b | |||
edc7a0b323 | |||
952bb60404 | |||
baffca39e6 | |||
a7a45b3c1c | |||
d914c6f613 | |||
31910f6e94 | |||
e2bd95780b | |||
150ea0c02f | |||
1a07031e2a | |||
da3e98e474 | |||
8363fdead5 | |||
af3345bdd2 | |||
7654446466 | |||
21113f8ffd | |||
036e18ba53 | |||
1d8836f230 | |||
4d0af131cb | |||
16c0c466f6 | |||
047f107f66 | |||
5768638a2e | |||
55c3badb40 | |||
63ef8f8f34 | |||
bf83bd85d2 | |||
3da45bdacd | |||
fa3cc1bfa3 | |||
1c9b42fc42 | |||
c4a4aeb1f3 | |||
a2e1f16a86 | |||
8651581fb5 | |||
ba171115cd | |||
0f1b4b3a85 | |||
7e2672bd46 | |||
75ee6d3691 | |||
49e0379cfd | |||
7684f8eb89 | |||
f87e0677aa | |||
aee11cb237 | |||
9029a94be1 | |||
87c5ba2024 | |||
a5018c438b | |||
8560e967c2 | |||
0f67af5f11 | |||
d226331f19 | |||
fc5630f3aa | |||
ea7c39bf14 | |||
b85c5e392b | |||
5ff93c45d6 | |||
0d09fee84c | |||
2e3769971b | |||
e4d1ab4440 | |||
b5c92a6a1d | |||
9cbe14fd8f | |||
955935f0ce | |||
eb92745950 | |||
f9369cee0e | |||
ccafb3e8e4 | |||
7f92710ec2 | |||
02e66468f2 | |||
a667b0370d | |||
ce1c3a852a | |||
19de4af4e7 | |||
a21517ed2e | |||
02ceb0e0bd | |||
ca341f6f6c | |||
b2a73203ed | |||
0fd9ff177e | |||
cc90fc2273 | |||
07aa29e4bc | |||
64ae2817a0 | |||
724ade6971 | |||
e4717f0e6d | |||
da1d28da2a | |||
f2948915b8 | |||
7b6922cfe0 | |||
c76b4c3f30 | |||
9fda66c29a | |||
781d9a5e24 | |||
6fdc6020a0 | |||
ad23734411 | |||
e48f3e2334 | |||
c6019faa0e | |||
20cab1770b | |||
58db7a75fa | |||
b40ab119c4 | |||
9b474de209 | |||
0ce3c1f131 | |||
97ec7d756b | |||
0a13e35413 | |||
112579c9d2 | |||
d2e3dfe700 | |||
b13a5a5043 | |||
be53996c7f | |||
3bea31ea12 | |||
3e1aed8641 | |||
27bb3de75c | |||
040785408c | |||
ef25c9c153 | |||
6823ce3dc8 | |||
78f7a1c063 | |||
fe3f767697 | |||
7398ceb5ef | |||
ebbf7d2e41 | |||
35cfb1a78f | |||
e5aa333b13 | |||
1dfbb9361f | |||
06fd8a15d8 | |||
efe74087f7 | |||
9dd7efeeb6 | |||
22687433fa | |||
c1396000d0 | |||
f67da9bd13 | |||
6c55881789 | |||
da03e95be9 | |||
fa4fb40872 | |||
03504a6402 | |||
0ca6c2913a | |||
840b962d55 | |||
3bc31b9d73 | |||
7168174c39 | |||
2944363e29 | |||
0e2295a8aa | |||
ead8d63525 | |||
50bce3d8c5 | |||
5eb277f501 | |||
cde775bded | |||
2d9e6d211c | |||
d133346e84 | |||
f1d5871957 | |||
c70d1e083a | |||
ff42c6a433 | |||
4b7d80aced | |||
e8b76b774b | |||
5632f91d34 | |||
a09ae7bfce | |||
6c75eba8f2 | |||
c8d83033a7 | |||
88333ef673 | |||
53c62a2301 | |||
047013d031 | |||
733ef26509 | |||
813d78d9b4 | |||
1c20abd750 | |||
016a809022 | |||
3e53329646 | |||
c0e3a0c96e | |||
7d26d202e2 | |||
9b59393ad2 | |||
6ac06f669b | |||
2e81467326 | |||
ccec25d46b | |||
1387bfae25 | |||
f1ab4f3c80 | |||
8cac9eae8b | |||
ecf0df8d5d | |||
f64fdce167 | |||
68baee6d33 | |||
ee03f49920 | |||
46a3d36986 | |||
ca3d331719 | |||
a485913372 | |||
de58ddcd07 | |||
a6b9e55a34 | |||
09a8d2c626 | |||
accc950511 | |||
2d9d8faa3d | |||
c0a02874f8 | |||
82786c6937 | |||
a5af8068ef | |||
c03ccd2cf7 | |||
ceae2be327 | |||
b86bf1d7c0 | |||
170c8a6be3 | |||
2c6ab43006 | |||
1a6d98d8a1 | |||
359193f1a6 | |||
aadd51f4d6 | |||
d4a3d67693 | |||
b84b3b4dde | |||
6c2534df81 | |||
b4f9ac45a7 | |||
29d696bdb4 | |||
2127d5ca16 | |||
f34acde600 | |||
eb54510036 | |||
65003dcc98 | |||
479c13a994 | |||
48a88e212c | |||
a58a65b5cf | |||
e18e149b9b | |||
c28b0590c2 | |||
88ead8b16b | |||
8b6ef5f03f | |||
efa82f4a9c | |||
81448227f9 | |||
c6f3a2e83d | |||
d7e4e424a2 | |||
fec70444ee | |||
529f86c873 | |||
724c9fe521 | |||
6cf511e6b7 | |||
79cc6137ad | |||
b7655ec501 | |||
587bb0fab2 | |||
86550e62ff | |||
1d165e8b71 | |||
e242d7ecab | |||
d13b01791b | |||
7e7d1f1f43 | |||
ef7cd70c5f | |||
106387fab8 | |||
8bf2d89906 | |||
54de5c4258 | |||
f4c386daf2 | |||
89f21660c3 | |||
5e2687bd44 | |||
690f8f1739 | |||
13af9832f7 | |||
5eb78c0ed9 | |||
92c8c0a653 | |||
a1096af3de | |||
0fe4c582a1 | |||
f915c591fa | |||
9f6202e639 | |||
433342c2a8 | |||
b72f16cb52 | |||
befbd1438d | |||
18f00cbe3c | |||
38ed0dc1aa | |||
2cabb31734 | |||
3af3db940c | |||
dabc0a4c2e | |||
ac0a51a8b5 | |||
ebf143002c | |||
08e8c3fa2c | |||
101da263fd | |||
b7d1f9e1f1 | |||
a22dc8b5ce | |||
9fad0cdcc8 | |||
1271185c5d | |||
5fdcfdd7bd | |||
22dea7f64f | |||
23c015f696 | |||
0ac0e9398b | |||
5c87a74d7b | |||
8c8fd91c7e | |||
54b858056f | |||
f262b661e9 | |||
adf0ac8f80 | |||
3b8a2d5b03 | |||
f19afc81ed | |||
982cf3bb9f | |||
7cec74d5e3 | |||
30227c9362 | |||
886ed303be | |||
3f43830154 | |||
229d521502 | |||
0cd487f211 | |||
6214f6a363 | |||
95b7d1f74e | |||
0b06e12ef9 | |||
fb2624bf7a | |||
a38097391d | |||
7b3e4cc67d | |||
d0854b9302 | |||
240a3afd9e | |||
8aeddf77c1 | |||
1306097cab | |||
a5b8a44c52 | |||
6e4b2bab77 | |||
3b77620511 | |||
5b82100c30 | |||
7d950f7f2c | |||
21fee2dbb1 | |||
b7fbf1f96f | |||
c2d531872d | |||
48de07f997 | |||
cca7530631 | |||
7aa6625e08 | |||
02a1870642 | |||
ac2b29628d | |||
1dba8f3eb8 | |||
de84e3471b | |||
7c7c36a5e6 | |||
44581b4682 | |||
2fe0a8e7b1 | |||
81d8eb54d0 | |||
663dfd12ec | |||
9c44759f96 | |||
327bf0ddb6 | |||
55f8e592c8 | |||
56d7dbedfc | |||
9b07bcf38e | |||
94af270ca6 | |||
91b93bd220 | |||
4af57f42b7 | |||
b4f5546a5f | |||
cb909e41de | |||
faac5a6c43 | |||
06d5b30544 | |||
c57b0e26e5 | |||
ab46dd9ab2 | |||
f2636c87d8 | |||
4901cb9052 | |||
a46848922f | |||
50a8b3a712 | |||
650fd20e0c | |||
23709679f2 | |||
d7069c8da8 | |||
19f1685d8a | |||
71fd25f02c | |||
fde15d6946 | |||
857fa447a1 | |||
4b34c1664d | |||
35a74f02b6 | |||
c71d68aae6 | |||
02fb491f9b | |||
9baf47f86c | |||
2048562006 | |||
b408c9d192 | |||
2ce3efb4fb | |||
da2c0b6440 | |||
2a87b98d9a | |||
aa2d5f0f06 | |||
8d5e8ccbd3 | |||
21a903b1e5 | |||
ef8c10fae7 | |||
2842005297 | |||
3bcff4b86f | |||
6c877ed334 | |||
b7f7c3d1db | |||
d98d986d4f | |||
85789361f2 | |||
05c9e7aa9a | |||
b54e5815ee | |||
367e43d773 | |||
329c7a3ad4 | |||
dde705805a | |||
9977fb8c3e | |||
465a9c5e03 | |||
4decb9b5d7 | |||
f235a65fe7 | |||
c4b2ebeea7 | |||
760907a67a | |||
c775d71642 | |||
bab9b3d9bc | |||
1a0f6b1721 | |||
4d0a1fd80b | |||
c332460074 | |||
d47290df01 | |||
24550749b7 | |||
63bb78a0fd | |||
7111fdb532 | |||
cfac4034a3 | |||
fb43aed601 | |||
ce0faaf556 | |||
7dfae68bb9 | |||
5fdb0c8ff5 | |||
87024d284a | |||
28e8af3f1f | |||
e6ae059bfb | |||
35bba82fb0 | |||
6a4fc3154b | |||
d39d8e7979 | |||
b05ced6f0a | |||
18058ed8ce | |||
eacb278566 | |||
735057f4dd | |||
5685fde159 | |||
08fd9894c6 | |||
d97fe3316b | |||
b9998df747 | |||
1544b07132 | |||
388395f5e4 | |||
0895e51a0a | |||
fde15d4ae2 | |||
41070f809c | |||
73556a40bb | |||
820cc6c0b0 | |||
d2be706829 | |||
d417ee0ce5 | |||
a90f616423 | |||
fc6729acfa | |||
cac0c14ecd | |||
2b804a01dc | |||
48b5e2e63f | |||
8a2faec55a | |||
02e8b77498 | |||
8ecaeaf4e7 | |||
e18aa2c49c | |||
575f0ec2b3 | |||
5b7fcb7b3d | |||
6e94dd9cd9 | |||
e985817582 | |||
8f61c40e13 | |||
aaf35147b9 | |||
ee295cf7dc | |||
0d6d43381c | |||
a66bc7d948 | |||
c405994451 | |||
9ede4c38f2 | |||
d98963fe9c | |||
6a85cae5ad | |||
090f367da0 | |||
96f027d310 | |||
aded5d5192 | |||
eea007a037 | |||
314db3505c | |||
095cab701a | |||
b30a0037fc | |||
5ee34dded5 | |||
be6649038e | |||
0e5f77daa5 | |||
17d4e7f3be | |||
52f25fe231 | |||
714396cbad | |||
cd2755dd5d | |||
fb97570b96 | |||
25b9844197 | |||
a5ab6b772a | |||
b0f064dac4 | |||
c5fad6075c | |||
12e885796c | |||
45eb9de2fc | |||
6eb9c37cad | |||
b5911f609a | |||
4e6f05fd29 | |||
0b7ae77cfe | |||
e718ff69f4 | |||
0c5f14b8d8 | |||
ca8ad39143 | |||
7531973551 | |||
6c008363cd | |||
0a566df789 | |||
525250f39a | |||
8d8d35a540 | |||
63d02f358c | |||
d364b11012 | |||
a5743ca323 | |||
a87431fc9c | |||
5cd61d8d1a | |||
3aa5cd285b | |||
9d1fcbfd20 | |||
f32d318cf6 | |||
70b500443f | |||
a65e8dcd63 | |||
8ac66696cb | |||
3d579cb689 | |||
bb779bdb97 | |||
dbd9d2bf34 | |||
937c36ca6d | |||
b57a83e9cf | |||
2e7931970d | |||
e0fe61ccc7 | |||
6ee961f618 | |||
c13f01899b | |||
8194ef7c67 | |||
c4fd214e04 | |||
4845ef0074 | |||
862ae313f4 | |||
cdc2594bba | |||
b255d0fddf | |||
83ecbdb75b | |||
aef19a9e9c | |||
0cd7a54904 | |||
53b78bf61d | |||
ca87ee2d3b | |||
91112037e9 | |||
74684864f0 | |||
471d28e4fe | |||
85de808044 | |||
ae494b8d66 | |||
d4d88cfdeb | |||
c85f208837 | |||
65a12d0e25 | |||
169a30f449 | |||
f6ec7dccd5 | |||
39e27d5082 | |||
95c8b7a975 | |||
162bf27617 | |||
832e0b535f | |||
84aa2b719c | |||
47c98e25e4 | |||
f9c866dadb | |||
3a74afcb18 | |||
cffbdc2928 | |||
a5bd94fe6e | |||
afcccc2354 | |||
19c6c403d7 | |||
df88e5a195 | |||
0bf76c3778 | |||
c8ea16040e | |||
653f9a6842 | |||
6973442e4a | |||
a451421ecd | |||
61379d2db1 | |||
3da3bf63fc | |||
4b7611f830 | |||
41e654c142 | |||
dc5484aa0a | |||
cc990de539 | |||
5d81b3d244 | |||
e8075dbbc8 | |||
7e426cfb5d | |||
abcf4c3a70 | |||
903c4e703c | |||
9f8f9fd786 | |||
ac13356737 | |||
abd64c2a9b | |||
e49b5c16c1 | |||
78b9374d2b | |||
df24c95a5d | |||
9b21690c27 | |||
18a49b9005 | |||
2c8767478c | |||
2628a6a782 | |||
6bbb602f6f | |||
bfde3e6be9 | |||
839d965d82 | |||
55815b60d1 | |||
a9cda0a75b | |||
9f2c9ac149 | |||
c2ea537b2c | |||
8cd9e993d9 | |||
36d5723e4d | |||
3dbbcee4dc | |||
762b89af38 | |||
b39c74c3de | |||
3b073186d4 | |||
048575f4eb | |||
9e33266c95 | |||
26ad49dd85 | |||
1c954b0e9e | |||
b038c8adf6 | |||
a3ceda9653 | |||
98db071fea | |||
cb63315eea | |||
52e025746a | |||
7dce2beb3b | |||
6641556084 | |||
2455ec0f28 | |||
6e9f30719b | |||
ead284fff7 | |||
bb932110dc | |||
003ffebf10 | |||
1746ff7919 | |||
7669918abb | |||
508ec87c96 | |||
0a8a8ecd72 | |||
5edb042dd3 | |||
2b329979c2 | |||
6b12d9746f | |||
c4e150af97 | |||
487d21b696 | |||
566a083dec | |||
58671aeea9 | |||
e0ac420cd4 | |||
7c15d8efd0 | |||
e74b515366 | |||
1569912204 | |||
a22d013776 | |||
21c6250214 | |||
a0f4929a57 | |||
8384602674 | |||
c069f384c1 | |||
b22f4cdc3e | |||
142b93e946 | |||
3b193134d2 | |||
52461041e1 | |||
84f8544210 | |||
e21933cd93 | |||
edac937b35 | |||
d7bf8fb9b0 | |||
e17559a87c | |||
9b73143b2c | |||
bb28ded0e7 | |||
690b862cce | |||
3ba76bde35 | |||
a5593535a0 | |||
1a40d5f4c5 | |||
b2c25db925 | |||
c7b414770c | |||
822a71b264 | |||
100d3dd3e3 | |||
e601461101 | |||
ceddacdd31 | |||
de1d4a6eac | |||
29d4d2d7ac | |||
13a99b1193 | |||
c824bf2e5a | |||
67fc3740f5 | |||
e4d3b100a8 | |||
a1e1b9dace | |||
00a1f57665 | |||
63b17453dd | |||
0449dd7936 | |||
adee18094b | |||
137d901078 | |||
117d67f9c4 | |||
482de27ef8 | |||
5c29625d31 | |||
3fd4aecd90 | |||
cb77280d73 | |||
185f501e77 | |||
15d98f43a7 | |||
1d158a3fde | |||
b9ce213df5 | |||
59e5f6edf3 | |||
69fc0b6973 | |||
ec477de8d8 | |||
c77d677874 | |||
58398f9918 | |||
b7c6113759 | |||
fbe047c877 | |||
7eebe5e6ef | |||
0dd310970f | |||
4fb4d17210 | |||
137e839a91 | |||
df6a0fd25c | |||
71fa697db8 | |||
f24f77f32f | |||
78f0d66299 | |||
21c87bb42d | |||
3be8f32909 | |||
73a799b722 | |||
d1e69faf6d | |||
7e7277653a | |||
3ec47fb236 | |||
ca945ed16c | |||
019c548b57 | |||
f204b3020f | |||
cc09d23c36 | |||
1b909a1783 | |||
2dbe718e9e | |||
fda3249d50 | |||
da37da7b7d | |||
971ebf1133 | |||
d13e8888d9 | |||
82d7783316 | |||
b343de6058 | |||
0c65c0d11e | |||
2f88ac9a7e | |||
32f70918b7 | |||
9c2cea92b7 | |||
573e67e790 | |||
4d96900c8c | |||
9d7e10604b | |||
9395321f4a | |||
044cc48bfd | |||
78488cdc95 | |||
b715329633 | |||
fb9448cf8e | |||
fb0ce1d36b | |||
9aee55b2c7 | |||
8d2389e033 | |||
465fde6611 | |||
4babff486e | |||
38a9ff25e3 | |||
b04d0b6ce3 | |||
56ea9917ec | |||
16e75fee79 | |||
f92653b202 | |||
29b825bfbb | |||
8ba07abe32 | |||
3370c9c9d6 | |||
b68c4c6d0e | |||
c088bb523b | |||
0a937cdcae | |||
2646805a77 | |||
2f8c5a099b | |||
42ec86a189 | |||
aa50495555 | |||
a3fdb3bc1e | |||
5844a57d8c | |||
ab186d190e | |||
c58a222887 | |||
8eff28c8e3 | |||
a734c972cd | |||
c670443132 | |||
9544c3305d | |||
6c815eeec1 | |||
f6530fd011 | |||
eb82c960aa | |||
be9bb5c671 | |||
618ba0da6b | |||
63c22bacfa | |||
e1c587ebf5 | |||
0dae6dc5c7 | |||
abf25824e9 | |||
ff03aaa957 | |||
c182530fb0 | |||
188e86a489 | |||
fcdc757441 | |||
da42e3bf9e | |||
8a70730dda | |||
dcc9b4b9d8 | |||
a1c19bbf04 | |||
5bc5e52936 | |||
3670b432e3 | |||
07695c957f | |||
36692b8f35 | |||
cf3fd7b832 | |||
03bfbdd9a7 | |||
cc01d8728e | |||
f0515d6369 | |||
993c283778 | |||
f159f0b304 | |||
c3d95644f0 | |||
98b05f8b8b | |||
0a49bd1738 | |||
862f8f3496 | |||
ed46aeb65a | |||
aa0b152b67 | |||
46482b7d2b | |||
2b68bb2659 | |||
e8cb55ab08 | |||
0c0cd2a2a4 | |||
1c550d3f31 | |||
15dea9bd1b | |||
a8d8fb658f | |||
2f3a39ad2c | |||
cece24b60a | |||
566f123c2d | |||
c8a546f6e9 | |||
056ce8421a | |||
c48da3d7f9 | |||
bc43689d41 | |||
b9194c223c | |||
eb9a894c0a | |||
50a664638d | |||
b74a741bb7 | |||
514d49bb15 | |||
27dd70953c | |||
1fe0740553 | |||
e486c9344a | |||
65f5dd7c60 | |||
1661fae398 | |||
cd3ccb0fc7 | |||
00e4a7ae24 | |||
821d18518d | |||
a5b79b1689 | |||
0fcc2b511e | |||
7be2729eb6 | |||
c5b15578cc | |||
247087b481 | |||
52ea9f66fa | |||
ebc7b59b20 | |||
623d5e775b | |||
5dc317b131 | |||
4d4512fcc6 | |||
5a83835b4d | |||
4c36ecc088 | |||
7e591e99e7 | |||
42506dabfd | |||
b491acb4e7 | |||
051c787bfe | |||
0178c694fe | |||
d8f4ec7a69 | |||
9332d40c9d | |||
badfafd8bb | |||
b2daeccc2c | |||
50e94976fa | |||
7ca90968a0 | |||
86b12eca8f | |||
af263364f8 | |||
ca75d9e475 | |||
615c3cc1aa | |||
58ba7af79c | |||
3f2733c033 | |||
56efada4a6 | |||
f233478ead | |||
f67f2deafb | |||
245375c28e | |||
fd0a331c88 | |||
ee5477414d | |||
8d6dc7f2e4 | |||
8dded3d437 | |||
8761c3500f | |||
e0d47d68c4 | |||
87f65862fb | |||
c266d916ac | |||
4cc1c59abe | |||
|
1d173dc25a | ||
|
c83336b853 | ||
d8636b4839 | |||
944474e151 | |||
|
8c7a2c5990 | ||
|
73e728118a | ||
|
27f5797086 | ||
|
e90f2cea84 | ||
|
76df6d2dcc | ||
|
c923567aba | ||
|
99bc5c55e5 | ||
|
fc21681ad2 | ||
5fb6346385 | |||
|
ed0e882ce3 | ||
|
ad6fac8450 | ||
|
aba48be013 | ||
|
1c92141f71 | ||
e7432f4b7f | |||
89c1012564 | |||
946a18a389 | |||
1ac9f85d85 | |||
7ef894513d | |||
f81b99badd | |||
56626ab671 | |||
b2d185cf1d | |||
667f5a8294 | |||
affb6d476f | |||
ce1a0d4b30 | |||
c5683c0a81 | |||
7dacf80a73 | |||
2112f1f4cf | |||
eafa935c9e | |||
cc57609816 | |||
d690331c7a | |||
f592ca0844 | |||
f7256bf27d | |||
737af38b70 | |||
84e01a2a35 | |||
bfa1e60e4e | |||
2a4dd3b70a | |||
ab0f98c977 | |||
81b25ae15e | |||
39cf9b1d74 | |||
7eb758bcc5 | |||
0de17eecfa | |||
3c332b06bc | |||
50e30a2f10 | |||
46c2455853 | |||
b2cbbf0c2d | |||
83ffd46644 | |||
9ee0e57b9c | |||
f92cee284b | |||
ca5a59c673 | |||
e5080015a6 | |||
0256856501 | |||
b1a2a0ce90 | |||
18c6f9d5fb | |||
a22e8745fe | |||
710f2cc2f0 | |||
fff26fd561 | |||
a97a215e0b | |||
eb1b735a95 | |||
26dce57cb6 | |||
9b1aa98424 | |||
bfd8797aa4 | |||
c67a1c0e8e | |||
552f2d7295 | |||
3207b5cd8e | |||
2d5722dbe8 | |||
1ed41e8fb0 | |||
714c4a4788 | |||
d60498e313 | |||
bf35165558 | |||
6a742aea74 | |||
c1d9d8da0c | |||
911876e4f9 | |||
1a3ef73c13 | |||
70f1bdd5a7 | |||
f27d643b8e | |||
cf1e574173 | |||
6e97d5c519 | |||
2739909b6c | |||
b7266092fa | |||
b6ba3bbc26 | |||
df041b2214 | |||
c45ef8ccf1 | |||
ddfef50a73 | |||
45c918e2ee | |||
1c16e14bac | |||
3ec95e1776 | |||
51b8d909c7 | |||
fe11a1cc3b | |||
c427b3ffe2 | |||
fca0ec707d | |||
d2b9ab906c | |||
291860aa2b | |||
6e46a49287 | |||
5287696476 | |||
69d7f10940 | |||
3d589a023d | |||
be62496d35 | |||
f77b40d4b2 | |||
4166d77ef9 | |||
432defa7ca | |||
29d505a262 | |||
5e706a7be8 | |||
264bbe8b58 | |||
ac9ab66986 | |||
ed80401feb | |||
71a03f83f0 | |||
bcc11ef379 | |||
e45c240f3e | |||
338ea4210b | |||
1336c8c5db | |||
d208512b45 | |||
3f8c6edc8c | |||
97767dc2cc | |||
51dacd7c27 | |||
e9ca38b9ab | |||
8becae3c11 | |||
6c595bdc7b | |||
def2f7c821 | |||
d80721f650 | |||
c05c286707 | |||
f91c35ecc7 | |||
59285fdfad | |||
e4547b226f | |||
aeb4eb9e2e | |||
cec369987b | |||
90418e22fd | |||
dbf9b264c6 | |||
9e82ee9a25 | |||
1e211fe564 | |||
ada54fab32 | |||
843c74492c | |||
f481459afc | |||
f8954abe3a | |||
29b4cf5564 | |||
c42620ef14 | |||
1213b6997e | |||
9e66ec9971 | |||
75e5d02fc7 | |||
497d99082e | |||
07e7ecf9f9 | |||
dd4ad63bfd | |||
f4b921eee1 | |||
7228adb77b | |||
cacc9e50eb | |||
f6600201fe | |||
0925372a70 | |||
844ba88a1a | |||
0dca0487ec | |||
5f2f9ee820 | |||
b5b361c705 | |||
7d5d856b75 | |||
9c924a75e2 | |||
ec8f179279 | |||
0025dba2aa | |||
0b8cd181e8 | |||
fc431fd190 | |||
b472780feb | |||
2961d04fda | |||
cbd74bcca1 | |||
28e919ba67 | |||
b36d2715d8 | |||
efdfe1aeb3 | |||
e254b4da22 | |||
1ee738ce64 | |||
fca35dfa9a | |||
87ee136faf | |||
cdf3810855 | |||
5652f252b8 | |||
40a2ca6e7f | |||
cfd7f0f083 | |||
548d82e9d4 | |||
ed725c6e83 | |||
f8294853f3 | |||
c753280771 | |||
69109e7e51 | |||
b2b57d3088 | |||
dfde6794a3 | |||
8aeca85b3b | |||
86a71afe0d | |||
86fb62a31c | |||
41611b1ce5 | |||
7b57b4f796 | |||
128cb6d290 | |||
6766e395e9 | |||
349cab2f02 | |||
c68b1870f0 | |||
3130c8da76 | |||
f2f0753584 | |||
04b04b8eef | |||
e56d16b58f | |||
47ea5538d5 | |||
4ec9bf8179 | |||
82fc3c6250 | |||
189f5e1365 | |||
1de6177929 | |||
bda043ebda | |||
7cdb236d36 | |||
5b56359db4 | |||
6ceedb3711 | |||
9743284242 | |||
49b0b9ade6 | |||
d3db216061 | |||
58c0a634d6 | |||
2a9f898c55 | |||
729a5ecd0c | |||
f6213610a9 | |||
098b886c9b | |||
87cc514de2 | |||
c22198d52d | |||
ff16d480c0 | |||
c3361343ab | |||
4e84e4fb38 | |||
1b00e853e3 | |||
0fd14d2fee | |||
821c8644c8 | |||
ef984055f1 | |||
d752ed4784 | |||
165f9edfef | |||
ee4d06413c | |||
2ca1a81879 | |||
1c75a7df26 | |||
830ccb2e71 | |||
318bc81bba | |||
22f371ccdb | |||
05caca8b17 | |||
379e8607a4 | |||
c36c8de863 | |||
0a29e83b3f | |||
7ff51d24fb | |||
03d27a5ee4 | |||
978fd08857 | |||
334ea6867a | |||
13b0cbddf8 | |||
d93286985c | |||
3635ba4947 | |||
d5e11f2d32 | |||
6de88ea3fa | |||
43ac79ddd4 | |||
bfd48adcf9 | |||
a85dedbeb3 | |||
29d46887e9 | |||
a6a37a4fc8 | |||
e6a0b3c84b | |||
ddd0d3bf10 | |||
83dbd90a91 | |||
a66c3368fa | |||
335d99a2ae | |||
3d03591b18 | |||
d0818a52df | |||
06c912c7a8 | |||
a017f3a74f | |||
06d140a27f | |||
7ebdebaa38 | |||
479e74d720 | |||
fd476c0ad3 | |||
2b7f5bbd33 | |||
cab3bfb2e0 | |||
405d0ff07e | |||
c761c08d70 | |||
7007009490 | |||
2289677b5e | |||
f1f6b41a95 | |||
ba94a3e5f8 | |||
16f9ddc833 | |||
ce15d55695 | |||
5502114fff | |||
07a105f53c | |||
03cb184fdb | |||
fa53c121b4 | |||
00da98f0fe | |||
29b5d9e11b | |||
17a8017a59 | |||
8bf9b4c6d5 | |||
084ee771bb | |||
b3c4a335e5 | |||
77a22feb4e | |||
57fc249a92 | |||
41f122783c | |||
65bdf8121f | |||
59aaa07e10 | |||
8e437f0aaf | |||
02efb4125d | |||
1b01099816 | |||
13cb7a4b69 | |||
41b704f4f5 | |||
6deaa5cb16 | |||
daa3d38695 | |||
d4713f15cd | |||
221d42193c | |||
2a2d162ef0 | |||
69e5bc3d92 | |||
a7a4949113 | |||
95a98a2bc7 | |||
d1fc4fc2d8 | |||
2c4f78fbfb | |||
8406e8ecf4 | |||
525f9cf048 | |||
9ad9a1df64 | |||
9a853523a4 | |||
40e25d9b6e | |||
a13bc2ed6d | |||
72be48405c | |||
f2bb8b964c | |||
db41e8f060 | |||
b71d33d4ff | |||
a7ec9f3059 | |||
7dc92583ac | |||
c0e3a32be0 | |||
0f069e0302 | |||
e22ad9998d | |||
c81b84b024 | |||
9db9708a9f | |||
a4068fe934 | |||
ca13f83d16 | |||
075f2f48ea | |||
2f5bebcaeb | |||
8b432f200f | |||
ff00bc34d6 | |||
0f49c1308c | |||
5cfa4291dc | |||
7ce77b98f0 | |||
02ae9a1820 | |||
317d2fc934 | |||
fdbb213670 | |||
3212072cea | |||
9184bf3390 | |||
aeb604468a | |||
fcab66dc45 | |||
e6a2070628 | |||
bdadd44efb | |||
6bbfc0094a | |||
371f2b6481 | |||
8d3b92ba21 | |||
49512b153c | |||
dd5d1213dc | |||
d1356ee1b7 | |||
3c19e4632c | |||
3eed5e0cf3 | |||
1c3b3e4501 | |||
01d04cd7fb | |||
c5e86713d2 | |||
3e4bbe12cb | |||
62d05de41b | |||
ee41cb5f2f | |||
654c253511 | |||
1ad9ae68b9 | |||
2a840251bc | |||
9d89064215 | |||
74739764f3 | |||
b8db212716 | |||
ae916975ee | |||
eea0234792 | |||
a8e261f517 | |||
4cd699b160 | |||
19697968c4 | |||
6f107718a4 | |||
8504b5f949 | |||
9144b2fd9f | |||
f6a479598d | |||
1ed9c0fae1 | |||
ad87c35d35 | |||
ed203095dc | |||
ff9cfd49e6 | |||
bf1302a0a4 | |||
ac8f65277e | |||
469581e37f | |||
32b4f3b7de | |||
8cf721bfe7 | |||
7f9f97c6a2 | |||
0bac09a48d | |||
d242199446 | |||
9a44401cf7 | |||
53593e08ab | |||
b357076a6f | |||
8510eb2798 | |||
bb8a12c1d1 | |||
15c69649b2 | |||
f02379453c | |||
848a2cf222 | |||
45376ce0d7 | |||
067a416fd9 | |||
f1eb8e821a | |||
ce60948d8d | |||
88c12710fc | |||
89390e1dba | |||
733526b6bd | |||
9e74d13e98 | |||
c44a6c42df | |||
a62135c172 | |||
55b4763cff | |||
677ecaf19c | |||
299f11bfd1 | |||
b8424ed6bd | |||
9a6d4f6911 | |||
75fc5a8233 | |||
25f74054ff | |||
df4c2d9014 | |||
1e28e021b9 | |||
47c87043b9 | |||
6873ad45fc | |||
fdfaee71db | |||
32048ffa12 | |||
d08a8f72db | |||
2570dc157a | |||
072e6b9ed4 | |||
232f0d2b1d | |||
620c989845 | |||
cea261469b | |||
6e342449f6 | |||
98503c649c | |||
62a1a9c3e4 | |||
59b153d480 | |||
60da2f174a | |||
b2bf9331d4 | |||
d174c639fd | |||
53469bab4a | |||
89933ed14e | |||
b6e122cf45 | |||
0836619ef0 | |||
1e627f55c2 | |||
13f93f5916 | |||
1956385a2b | |||
06bef3c5bf | |||
f4a71455fb | |||
332941fe83 | |||
5f148baad5 | |||
ee06dca830 | |||
ecce84afd1 | |||
a91de0528b | |||
0eac2b11c9 | |||
8ba635624e | |||
5540c010fa | |||
6897bf82ad | |||
eeeda6febb | |||
775d4f5872 | |||
3589b536da | |||
f0dcc903ec | |||
915997a3ff | |||
6aef6e81cd | |||
b256cafc6b | |||
f8f92e0579 | |||
d9fb3d093e | |||
eb55cb5ea4 | |||
914ea0dc79 | |||
20521c57da | |||
95dab7b7ab | |||
8c82f617a4 | |||
4aadb02de3 | |||
93cad06654 | |||
6862c8d4f5 | |||
674d7c0a56 | |||
dc1c0b6fe0 | |||
e2d202506f | |||
e0414c83dc | |||
e4916fa9cc | |||
0d31c15edf | |||
1688960767 | |||
ba9c5bd98b | |||
2f5c0be4c7 | |||
59a2406aaa | |||
bba8ba33ca | |||
9366b4d173 | |||
750e9f8881 | |||
967d8c929c | |||
3c8e438294 | |||
cb2a7f4997 | |||
40f7296430 | |||
06b32aa54e | |||
c12978f93a | |||
7fe695d6a9 | |||
78a05c4a55 | |||
71d8c1ae09 | |||
eba00a5039 | |||
fabd739896 | |||
2f44aceac5 | |||
deb7ca6143 | |||
c4a8bc6761 | |||
5e4a21627f | |||
fa43ddb202 | |||
800818c9b0 | |||
96ba0ed3e5 | |||
e966767f4f | |||
49e636a726 | |||
f0ffb1bb8e | |||
ece2ed97ad | |||
61c14b4189 | |||
de9c235275 | |||
aa7044e8c3 | |||
ccb440f386 | |||
a30f0977b8 | |||
8a5b045ae9 | |||
f8fc633297 | |||
64158856c2 | |||
97366a9622 | |||
346a10d1d4 | |||
5c0b2b00f9 | |||
69e9f78508 | |||
64bc960029 | |||
af49819e37 | |||
98bddca72a | |||
fb4d71c26c | |||
f8687b857e | |||
5195d970d2 | |||
50bff9081d | |||
837e13f7d2 | |||
4f44c8e817 | |||
9faea02ac3 | |||
67aea648eb | |||
4716733c34 | |||
fe07622042 | |||
b06f855ffc | |||
760ae91027 | |||
aa2db372e7 | |||
e4e9a808a6 | |||
6dc4951dec | |||
d77e8ba1e3 | |||
290aab12d8 | |||
d8ddf7b0d8 | |||
35f8f26409 | |||
136dfad982 | |||
269587a8f6 | |||
0bf783f1fa | |||
bfc1896028 | |||
cec51c03aa | |||
055e9d624c | |||
8023cb0826 | |||
fccc3795f4 | |||
93d35ba7b2 | |||
264ae85f0f | |||
1db350e937 | |||
899b02cf79 | |||
0eab5625b3 | |||
5c358028c9 | |||
d53e3b2df3 | |||
784d73f7ee | |||
9c6ef7a346 | |||
b908be1287 | |||
18563c61bc | |||
2981220cc3 | |||
6ad5d62d1f | |||
4af1e61f61 | |||
a53d32dda6 | |||
de22004f48 | |||
fb82059529 | |||
355572b927 | |||
45fd35bed5 | |||
0276406577 | |||
7b01190bcd | |||
0550e7a8f9 | |||
4697bd581f | |||
c605d31e48 | |||
201d97ec41 | |||
d41b8890ec | |||
b9e753153f | |||
556a2f6c1a | |||
9680e46eaf | |||
76017a68e3 | |||
faa3d7c895 | |||
bd1a174272 | |||
66cb645700 | |||
f4437eb72b | |||
52573c58ed | |||
538234fbb4 | |||
6eb4f8fe9f | |||
1d7483729c | |||
9ebe23aa0b | |||
f8a1dd5761 | |||
b09bb1a85a | |||
6bf3fc29b5 | |||
a27f2c2101 | |||
1e6dbf9243 | |||
67a55fb6d6 | |||
785daea994 | |||
14b66a7436 | |||
60166caf79 | |||
188dd6b17d | |||
29c5192b78 | |||
5b2075a6ac | |||
e610c22283 | |||
408a8ed60e | |||
5e25484263 | |||
2de6bfb149 | |||
25d1556210 | |||
ae71326bd0 | |||
60f74c3247 | |||
f567d7645d | |||
02766515c5 | |||
|
01dd64f3e1 | ||
|
cc8dcce9e3 | ||
d24379e1cf | |||
ab37ed0ea9 | |||
8a96138620 | |||
a659521c29 | |||
cad736d74b | |||
8670ee34d6 | |||
3d4be63df8 | |||
fbd17e0e38 | |||
f833181e37 | |||
908e5501d1 | |||
fa4eaa9576 | |||
bb0436f79f | |||
b5caba6e70 | |||
64af161bb2 | |||
3177faf3f7 | |||
e4b84b024f | |||
a4503f8abb | |||
4ec08675be | |||
e3c0ba1735 | |||
9a55d4ce02 | |||
2651f59735 | |||
e8f338e417 | |||
8c6aaf39c5 | |||
16997b9648 | |||
0f86ced72d | |||
1b2991e640 | |||
3293522dd1 | |||
8abb9f9ae4 | |||
b840d235ad | |||
8ad2d12c45 | |||
06358f6616 | |||
a3c1dc32ad | |||
bf447031eb | |||
82e73a3383 | |||
69d1648fbc | |||
400552a759 | |||
c3495cbc6d | |||
76ccd3458d | |||
f0fc978869 | |||
80020983c0 | |||
7c83923c46 | |||
415f1e18a6 | |||
2c7914be34 | |||
f18a568451 | |||
0c3b8182b9 | |||
ad538dd08f | |||
336992434b | |||
62866cf688 | |||
0af64f6792 | |||
d978e9ac5b | |||
071899ae2a | |||
844296ae33 | |||
a81385f4a3 | |||
3d0273f3a7 | |||
905cbab8d4 | |||
88bd282034 | |||
524bf1248e | |||
|
c073109f5a | ||
|
fcd11f5475 | ||
|
61e97681b6 | ||
|
7bce73f553 | ||
|
b60c4d4ba8 | ||
|
f98708677a | ||
|
010d04a67c | ||
|
56f9cd9b76 | ||
|
1d8aa3c0d3 | ||
|
1caefb2d99 | ||
|
b23d9f8c9b | ||
|
19aa822c8e | ||
|
cff4aeeda2 | ||
|
c10149eb42 | ||
|
e4e6aff2ee | ||
|
8c26b42dec | ||
|
da1f293379 | ||
|
a263ebc2a4 | ||
|
81ed0a5cac | ||
|
4ab2284231 | ||
058e6c4974 | |||
|
3da6f8970c | ||
1b3a467bc7 | |||
|
af74ff8c12 | ||
|
d82367104a | ||
|
13930a12a7 | ||
|
08e486c3cb | ||
|
03796c6bd1 | ||
|
0ec7a8dc4e | ||
|
dd15acf15c | ||
|
714f3b8ceb | ||
|
6489cec8c3 | ||
|
32154ffd6f | ||
|
e59eecebc8 | ||
|
0ecf080d03 | ||
|
cc78360984 | ||
d5bc4c87d9 | |||
c775bcd998 | |||
b8016a3bc1 | |||
0b2f514320 | |||
f35fbb8c71 | |||
c52c6f4438 | |||
3f52396e9d | |||
fa2e4b2be0 | |||
|
6608f4dbd9 | ||
|
8fdf1367e2 | ||
|
fe15df439b | ||
|
c03ef6fd65 | ||
|
48fb312730 | ||
|
1fa2bab090 | ||
|
2b02e058c4 | ||
|
aff2dce496 | ||
309a31639b | |||
2f45c1d0c3 | |||
5bb453739c | |||
6d53973d67 | |||
1d50ee3f93 | |||
8da52e715a | |||
|
aea20bb2ae | ||
|
378f719ec6 | ||
8a2191af25 | |||
01bc932fe3 | |||
|
10c79f6247 | ||
|
26318d73f4 | ||
|
9a4fd20017 | ||
|
91266119de | ||
|
495a1f30c6 | ||
|
b7573bd633 | ||
|
ec7ad7eb4f | ||
|
68e933eab4 | ||
|
74e6103d3b | ||
|
897af85d72 | ||
|
91fdd14d5d | ||
|
75ffd4b6b1 | ||
|
928f43bfe7 | ||
|
255349e93c | ||
|
3a12176bbb | ||
f2a324e7f1 | |||
|
cf290efa0a | ||
|
6e2b089ee8 | ||
|
a67047864a | ||
|
0e2542dba5 | ||
|
01ebc40fac | ||
|
02c7319035 | ||
|
23d8f1daaf | ||
|
0915f7901c | ||
|
67e873c7ed | ||
|
775b70ec80 | ||
|
9f38d65c6a | ||
c59f68b455 | |||
|
9fd078bdaa | ||
|
399e94d9cb | ||
|
bed633b5b1 | ||
|
6aa6916354 | ||
ea438faae3 | |||
1a8f99c7ee | |||
8b27aac5bd | |||
00bd968d32 | |||
5534ea0247 | |||
fe9a6a8518 | |||
|
cee76c53ce | ||
|
b1dabba247 | ||
|
8e17734144 | ||
|
041b232dc6 | ||
|
8174a0dc2a | ||
|
244b302a92 | ||
|
ad7001eeb7 | ||
|
157ecc16ca | ||
b2dd61e392 | |||
afbc7053e3 | |||
77e3a54158 | |||
2c981072a6 | |||
4b11331f81 | |||
be1a9515df | |||
35cc13ae2f | |||
0eaabc5f64 | |||
6a13590c9b | |||
64272d2c64 | |||
85651cb4db | |||
7417b932de | |||
|
93595a53ca | ||
|
8fc7ea86de | ||
|
8bfc8ca519 | ||
|
373a62a8be | ||
|
684212b031 | ||
|
9e229a5afe | ||
|
c6144c3aa8 | ||
|
10c3d01597 | ||
|
b0d4823bec | ||
|
40c6b8d787 | ||
|
edffeecda3 | ||
de202823d9 | |||
04324128f0 | |||
ef11622593 | |||
3f65b79e82 | |||
6f42bb480f | |||
84b8ffffa9 | |||
30baba0a08 | |||
3e5fde5839 | |||
2285dd1cc5 | |||
|
82b3c27b8b | ||
|
4890b04baf | ||
|
66c3636007 | ||
|
d24acb3bc2 | ||
|
8c9f3d0bd5 | ||
|
7e971a3e38 | ||
2ef99978c4 | |||
638db41369 | |||
7c6ca6c940 | |||
aad80bc484 | |||
1a4a85406d | |||
c1cce42737 | |||
|
2c0304369f | ||
|
c9ad1e1ef0 | ||
|
b66a9562f1 | ||
|
038d85219f | ||
|
19fcd10430 | ||
|
4a8e2ff541 | ||
|
0df34177ca | ||
|
66d0b16837 | ||
|
e26c319eba | ||
|
7ce41dad33 | ||
|
04413d3a83 | ||
|
ca388016f7 | ||
|
732fa5ffea | ||
|
fd3e17a27f | ||
|
c87face0a2 | ||
|
10218d0a63 | ||
|
ba58f2052f | ||
|
71739486cf | ||
|
6c29baf30f | ||
|
9cc840d3ba | ||
|
746f8d5a32 | ||
|
35103c73c7 | ||
|
1d4913417c | ||
|
141b05ad61 | ||
28a83cfd6b | |||
b360acca02 | |||
6fa4d6402c | |||
8f39d10465 | |||
307a5ea0e1 | |||
ba7aa5ed51 | |||
0ad1126efa | |||
3532288fcf | |||
4964d6b08b | |||
7355b06db4 | |||
d6c2cd62d2 | |||
827047b8cd | |||
9f2fb7732c | |||
|
dbf1f18e34 | ||
|
c6e1ef2aeb | ||
|
2aadc1bbaa | ||
|
cd6e6145f4 | ||
|
29396c8a10 | ||
|
bafb7b3bc3 | ||
142611e69d | |||
|
9dc533d7a9 | ||
|
cfb61590f0 | ||
|
3284486383 | ||
|
f5ba9c2ccb | ||
|
f4cc1af9ae | ||
|
66faa596dd | ||
|
3d243e3463 | ||
|
f57f9ec4bb | ||
|
015b0377ea | ||
|
4c406844cb | ||
|
06251825cc | ||
|
88a8793258 | ||
|
5d63297205 | ||
9a469dc71c | |||
|
6deda024c8 | ||
|
a5cb27611f | ||
|
dfde4ee228 | ||
|
5928881ce6 | ||
|
059efebddd | ||
|
3117ebedbe | ||
2fbf20a612 | |||
600799f35b | |||
8d284d55ff | |||
e7bbd18e4c | |||
abdf47cd01 | |||
33086ee933 | |||
f354377711 | |||
5e4eede049 | |||
9bcfca906b | |||
565788f81a | |||
4cf65fcd17 | |||
bf0cc8c4b6 | |||
283b98c6e7 | |||
fdae48ba2c | |||
c8f2648009 | |||
487e42394e | |||
f3d64c17f8 | |||
02f261b51a | |||
a33e4fe738 | |||
2a94973073 | |||
db9ac7292b | |||
dd14c02b64 | |||
c98ad08618 | |||
99d57bdcf3 | |||
7aa0cda992 | |||
1f9dd15f2c | |||
456b20b895 | |||
44b41c4cc1 | |||
19162c3572 | |||
500372a146 | |||
|
8edda8e586 | ||
|
d94a5db617 | ||
|
e4fc3c8cae | ||
|
7aeb6da244 | ||
|
4a893f6b29 | ||
|
da29b0ea3f | ||
|
77aaeba374 | ||
|
01dbf094c2 | ||
|
4660d25f93 | ||
|
bd881b6a80 | ||
|
7ce2d60b50 | ||
|
63f94e321f | ||
|
3e4cb99750 | ||
|
79c22bef27 | ||
6e0fedb15d | |||
|
fe70175221 | ||
|
8e66337cd8 | ||
|
10d8b78b70 | ||
0ac47e16af | |||
43196b5680 | |||
e2a9cfe252 | |||
|
e022892e7d | ||
|
b0308ad941 | ||
|
b86d88ed0e | ||
|
550c234656 | ||
b8f3d1c2c1 | |||
4b555ae12a | |||
17cc95ef22 | |||
2bf7020886 | |||
a3651b189f | |||
0951382c40 | |||
bd786bd6bb | |||
b49c7b5bf5 | |||
1f202ed38b | |||
2a9d8a1bc2 | |||
48bbaee29b | |||
b64c92bf22 | |||
a16550b0cd | |||
17420c1a33 | |||
3cc976b60e | |||
|
152c4fc712 | ||
57d15fc646 | |||
c6c9aad4d4 | |||
788ff73bbb | |||
51e4b03c1c | |||
0ed4c3752d | |||
e2998666b1 | |||
c2f6e591d2 | |||
0730ee36d0 | |||
050386826d | |||
0f77fd4d2b | |||
fc524450b6 | |||
b2094b7834 | |||
5bdd8a211d | |||
81f2fad880 | |||
333bc1f9cb | |||
04c597d0fe | |||
|
52c2f3f82e | ||
|
ae89206766 | ||
|
6e07c7ff4e | ||
|
d146b240e6 | ||
|
9a5104f37c | ||
|
c9d4d8aeda | ||
|
f020114588 | ||
|
ffd1e3e18a | ||
|
ef32aa45d2 | ||
|
f05e2ae497 | ||
|
0128e3620d | ||
|
155166ea8f | ||
|
bec2a671e0 | ||
|
53e10841d5 | ||
|
dcc0bd6d95 | ||
|
77781aa817 | ||
|
ce1b69d42b | ||
|
4f9e555e82 | ||
|
c0110c7c22 | ||
2a8a303de1 | |||
72c5bbc836 | |||
33ba0bef22 | |||
98684d3613 | |||
2e572a793b | |||
71fcae697d | |||
bc28e72aff | |||
950396a8a0 | |||
d736610248 | |||
fa4b762d00 | |||
|
225f38064c | ||
|
f034ea3b57 | ||
|
a26f07de0c | ||
|
34454b7238 | ||
|
5d3f06a527 | ||
05e0fad922 | |||
a3c2eb3978 | |||
|
d64c743467 | ||
|
be0b4ca818 | ||
|
e1d18c54d3 | ||
|
6578c455ae | ||
|
f8f315617d | ||
|
613d048fcc | ||
|
129a3b568b | ||
8ea56f8ae9 | |||
|
452d245e00 | ||
|
a4ad7645ea | ||
|
0a498fedb6 | ||
|
db9123362e | ||
|
44e7c653e6 | ||
|
4d222d8e8e | ||
|
e01a1a62e1 | ||
|
4446e93c6b | ||
|
04d953747a | ||
|
25aea3bfca | ||
|
33b4fa9139 | ||
|
7df429d5e2 | ||
|
9d729ee710 | ||
|
0af01481c4 | ||
|
04b602b118 | ||
2d07aa2c4d | |||
cb3a3d82c5 | |||
|
a566883b06 | ||
|
ae09556e8d | ||
0e8c03e79b | |||
d38a913bee | |||
|
b2d9f48faa | ||
|
3cc035d37c | ||
|
5ad0bed230 | ||
|
7db85004a0 | ||
|
7e2df69c95 | ||
|
9663e67bc3 | ||
f9810ade1d | |||
2442576010 | |||
|
bfbcb95510 | ||
|
ec8ead747a | ||
|
ebe76fad2a | ||
7dda7063d2 | |||
|
eaf9048479 | ||
|
51e6fd6b98 | ||
|
fc89f26d19 | ||
|
f22298a113 | ||
|
69150cb4db | ||
|
b9be27810e | ||
|
0a8646ebd9 | ||
|
524ea94bbc | ||
|
7c687e75c2 | ||
|
bf8b71e4bf | ||
bd3e068095 | |||
|
c8cc8ea9fd | ||
c201e70af5 | |||
323147ac85 | |||
b03488c689 | |||
|
5be1f4641f | ||
|
18a17e5576 | ||
0e3c9e779b | |||
615bf640a9 | |||
195f638469 | |||
29fe8f84d8 | |||
|
50354200af | ||
|
327387b6d6 | ||
|
23c5200aac | ||
|
92e0837576 | ||
|
94ce5a2d85 | ||
b7e475cc61 | |||
b31159513c | |||
4f64de7aa3 | |||
2fa77bc465 | |||
1d3483f315 | |||
|
93ae867328 | ||
|
09fdb34b7f | ||
|
4a4e44e681 | ||
|
957121d76e | ||
|
5c9a779dff | ||
|
3c0e80699b | ||
|
ac7d71e349 | ||
|
3e202102ea | ||
|
418b3b20c3 | ||
|
0e004a6f52 | ||
e315283830 | |||
78c28ca79f | |||
de24c11189 | |||
|
760257e3b2 | ||
|
07ea34eb9b | ||
|
f148b41782 | ||
cc713f1a16 | |||
ad692bd985 | |||
597a7493e2 | |||
|
5bc2ecdab8 | ||
c73722c5b4 | |||
798b1df093 | |||
|
4bc8b9b080 | ||
|
4c6be2f63c | ||
|
53246e9567 | ||
|
2638a58aac | ||
|
29aaf0c346 | ||
|
974b6ac3e1 | ||
|
21d8c58b96 | ||
|
c575e9c696 | ||
|
199022a244 | ||
|
ee91af4bdc | ||
|
3c0c290533 | ||
|
4b2183cc34 | ||
bbfe41e0fe | |||
4486995404 | |||
28988342a3 | |||
|
e37460f4f8 | ||
|
9b2221bed2 | ||
|
4a0848c003 | ||
|
99f57dfd31 | ||
|
86116c6563 | ||
e094a79a24 | |||
|
297016a87f | ||
|
318458b948 | ||
|
a49fda9657 | ||
|
16d848f884 | ||
|
a7e287b74c | ||
|
3aa29f8fa2 | ||
|
334f3c8e8a | ||
|
9de918120f | ||
|
bb9dbdd799 | ||
|
29ba48850c | ||
30edec7ff7 | |||
74d28667d9 | |||
2a90e078df | |||
76761079be | |||
b03055654f | |||
|
02d48bd724 | ||
|
d21bd7232d | ||
7d328124f4 | |||
17f2e87cb8 | |||
1700769354 | |||
c35b89c8b8 | |||
78c3d4e174 | |||
432906085d | |||
7d570763eb | |||
|
1f8fba7a71 | ||
|
ed9381925f | ||
|
f10be16de6 | ||
|
1d92f39f2f | ||
|
16fd8639cb | ||
|
f19d12743d | ||
|
4473d03265 | ||
e066336b9f | |||
0b0259ce7a | |||
7878bc74c6 | |||
|
14a961602b | ||
|
518f7947f8 | ||
|
c88d83e27c | ||
|
87cfd5bd15 | ||
|
3681fe6f30 | ||
1412c2c33b | |||
290b97dd33 | |||
5068888e7d | |||
2972c73929 | |||
47b4fe4f17 | |||
59b5c9b2d3 | |||
681b3d1c21 | |||
5ea92be85a | |||
760e2eb1d0 | |||
bdb093c4fd | |||
0570701203 | |||
e9a975610b | |||
8411f0323f | |||
0c9c3305c5 | |||
d7f3733081 | |||
fae639ee7c | |||
2d1a012a9c | |||
522caf2463 | |||
aca51a8d04 | |||
7b825054d2 | |||
f79e7bee9e | |||
5ae2f52fb6 | |||
|
12d788bad8 | ||
|
52f41b84cf | ||
|
77ed1336c1 | ||
|
ecd542f7ac | ||
74e2644dc4 | |||
c451ec6050 | |||
f2c7ddd147 | |||
8241a51078 | |||
52e7e72340 | |||
|
6cfdfc9c7d | ||
13c255b811 | |||
630aed70e7 | |||
8310343886 | |||
b6fd7f47e9 | |||
a418db8a11 | |||
71dde0cef6 | |||
99c2fa06ee | |||
ce304140ba | |||
f95eedb798 | |||
16817dcfea | |||
6d5ae0a3fc | |||
4cd8e98bea | |||
78f144073b | |||
504c7a8825 | |||
5de620251f | |||
d697717c69 | |||
|
6b704bd121 | ||
|
af75ca83e1 | ||
271f231d26 | |||
4ae440ccd9 | |||
1b747ec1d0 | |||
2951ce80ef | |||
aaefb93363 | |||
c84533e601 | |||
c1168c7ee8 | |||
48d1bf27a0 | |||
07a1d97149 | |||
eda1960d25 | |||
b66ce54ac3 | |||
|
7d07753abf | ||
|
0efa63007c | ||
|
787a323001 | ||
7f74c62555 | |||
095e0770d9 | |||
a6306439f5 | |||
f370dbe205 | |||
a714f6fa9d | |||
2d3ce1b172 | |||
|
fb81fa6cf6 | ||
|
70e723c48a | ||
|
1b7c0fc340 | ||
|
7581abc855 | ||
|
4ad4dc4ea3 | ||
d8a5d25e4d | |||
7b076ed0be | |||
|
db13e3d437 | ||
|
63a309b5f1 | ||
|
2746ac553b | ||
|
d66c26f0c0 | ||
|
46f531d2ec | ||
e1abf734c4 | |||
|
b593bf86fe | ||
1cb73244f2 | |||
fbd3c35991 | |||
2d8935d2c5 | |||
7508c9a38b | |||
4a81c99b9a | |||
|
e9ed9aaa2e | ||
|
16b934ccc4 | ||
|
cd4ed108b8 | ||
|
c0f44630ba | ||
|
1ed666dfd9 | ||
|
56b6545e54 | ||
|
eeac65ba45 | ||
|
518c74d877 | ||
2dd8e5c8d8 | |||
5a4a1279a6 | |||
6bbc77c0b5 | |||
8d3baea758 | |||
2adca800ec | |||
21abb228da | |||
a110f6afe6 | |||
|
a9bb3de500 | ||
|
4f98e463b5 | ||
|
7940d14307 | ||
|
f958e286a5 | ||
|
b4674af657 | ||
|
eba115218e | ||
|
55a7003cb6 | ||
de1c63a15f | |||
395d79d813 | |||
|
294ddd8798 | ||
|
3279ead197 | ||
2958a9fb88 | |||
bf14d2687f | |||
1a3f2f1fbf | |||
049ce3767e | |||
cea0f9cddf | |||
cc920635c3 | |||
242e695ab7 | |||
975d0c579d | |||
59c0ec0735 | |||
b4c4ff49f9 | |||
f76f4b95c9 | |||
097b888323 | |||
400278071e | |||
272de57267 | |||
3fa37cd001 | |||
23c03ed46d | |||
ac370dd89f | |||
f843b46333 | |||
71332d0636 | |||
30031d7188 | |||
6a6be677c9 | |||
|
bd2dc0ed7e | ||
|
653ef44087 | ||
|
91aea4d17c | ||
df18c2441a | |||
4c3e947ffa | |||
6a23966843 | |||
b49b2c103d | |||
dd78774357 | |||
947df17551 | |||
|
ce702d3de2 | ||
|
fd5b7ba7ad | ||
|
fef670a209 | ||
|
4f4b4b292e | ||
|
3acbaa72d1 | ||
|
350370eaf0 | ||
|
32d936b60d | ||
|
ed1d0f19d5 | ||
|
6ff1444deb | ||
|
4aa5938953 | ||
3f3ceaed31 | |||
|
bc070c05d7 | ||
|
7f113a6d82 | ||
|
fbdf44daa5 | ||
48166813fe | |||
|
c9507bf58b | ||
|
9c28c95aac | ||
|
8cdd5346ac | ||
b8dbf50033 | |||
4721782368 | |||
7c990e3def | |||
|
61bcce515e | ||
|
b9970c246a | ||
|
0ce7f2cc46 | ||
|
5894a5361f | ||
|
1c8f2f502f | ||
|
989ee2e57c | ||
95e7c5cc74 | |||
521c4b1834 | |||
8a11ef8118 | |||
7016df5753 | |||
020da0f9e3 | |||
a300220913 | |||
39aaa035b4 | |||
7d3634cd50 | |||
bb8d7c4294 | |||
a2743f8ed2 | |||
d83ffc4458 | |||
c004fec8c9 | |||
|
2e9402f1c8 | ||
|
462b7b9ed6 | ||
|
84b4023e19 | ||
|
2f36a0b69b | ||
|
442ba6b84d | ||
|
39cc4fbba5 | ||
9dd0b1aad9 | |||
|
dbdce944c2 | ||
|
52d092619b | ||
|
22ef9b519e | ||
bf9e887c00 | |||
993fa80624 | |||
f9109bb4a1 | |||
863169d32b | |||
12bec0e14f | |||
|
5dfe4d9e18 | ||
|
2ce6223959 | ||
|
8d016f929c | ||
|
e3a1b05f5d | ||
|
5eb422be37 | ||
|
66e4f2ffe9 | ||
9485c2ba5a | |||
860ff8c35a | |||
99f279c3e8 | |||
c11003a018 | |||
69564bfabe | |||
6f282e90a7 | |||
cd9214b15d | |||
cab89a41d3 | |||
3bbb14b217 | |||
c9fd1bc17b | |||
ca1c1d1d73 | |||
ec252292cc | |||
8d40bf9f10 | |||
aa8b322e07 | |||
81a1cd4de0 | |||
5096c4f37a | |||
0fed5d1998 | |||
e928b5bc73 | |||
e2731d8c52 | |||
6280e606b8 | |||
ded4ed6052 | |||
14975789c4 | |||
054c7ec945 | |||
711f702c7c | |||
776d85895c | |||
b873ea5eb5 | |||
|
3cd1f633ed | ||
|
12e21a3067 | ||
|
d9c0bc4b9b | ||
|
e73e481a70 | ||
|
21c1535343 | ||
eccb64356a | |||
cc31e1ac79 | |||
b1415bb9e0 | |||
eaccb4bb9d | |||
c54b9d262d | |||
|
c9679ec4c5 | ||
|
6fe1ecb294 | ||
|
a1e274537e | ||
|
0c1c3a7423 | ||
|
8a1887aa11 | ||
|
2489fffcb9 | ||
|
9d76304aca | ||
|
72a936e9ef | ||
0984abc205 | |||
92e5f06d46 | |||
7db65c45b1 | |||
4572612051 | |||
4150fa72f1 | |||
ac3f74581e | |||
2695a0a6d5 | |||
af0f00744a | |||
51fdad314a | |||
f5ea37e3b5 | |||
8fdac9753e | |||
bc60e9b857 | |||
bd23324501 | |||
fea3ff4075 | |||
3b74d630d2 | |||
9d785957cb | |||
91579cf0bc | |||
932caa814d | |||
6384e75393 | |||
6d5af81780 | |||
2c613b7186 | |||
bd2fd89c4f | |||
354c9d5d7e | |||
49b9dfd2f3 | |||
f8e15f3f5b | |||
d2b4e702fe | |||
ab723d6cd0 | |||
2d8f132437 | |||
e3a0f4b865 | |||
b9ec4399f7 | |||
c9be9bd24c | |||
1ed203925d | |||
42d7b814e7 | |||
b04560a049 | |||
36c1270733 | |||
7faac3cdfa | |||
0779284c5f | |||
6028cd4d0a | |||
f4131848e3 | |||
77c48682e1 | |||
f1fb22d2eb | |||
3ce482598e | |||
0282368bc7 | |||
0c509242c9 | |||
f9fb84cef4 | |||
9ddab7a03a | |||
615e04482b | |||
a0dc711cea | |||
7e324da4a3 | |||
618c0aa837 | |||
f025632394 | |||
6f029282b3 | |||
773a922af6 | |||
e92100a0d8 | |||
8a9aa3e33c | |||
d0838994d3 | |||
8282aaefa8 | |||
66449900eb | |||
c03fa4b4a5 | |||
9273e89431 | |||
548c55b658 | |||
27a1cc73fb | |||
2c49919d9a | |||
2d55016495 | |||
d1d4922baa | |||
3e48fc61b6 | |||
7d9f7c343a | |||
698d433c3b | |||
c8a6fd6165 | |||
af6e4beb32 | |||
92cbc0b6d4 | |||
cbb43f9174 | |||
3d928d866b | |||
0535dc951b | |||
21887439e4 | |||
0ae97913ee | |||
02ff10df39 | |||
b41c352bc5 | |||
5e49633f81 | |||
1b97a52ced | |||
650d57b7cb | |||
716495c9e2 | |||
47775ec420 | |||
f891e5a0c1 | |||
|
511dbd1246 | ||
|
ebbe211b92 | ||
|
44acb59ff7 | ||
|
10dffb328b | ||
|
d4a899fd8a | ||
|
d1e65d1bd9 | ||
|
412098f6b7 | ||
|
eb9b39161a | ||
|
d6c99942f1 | ||
|
1021300f11 | ||
800e95a92e | |||
0e9347f656 | |||
a421eaf31e | |||
306fce9a11 | |||
a08e6e94d9 | |||
fb05292d5d | |||
bec7c69058 | |||
7122f7f457 | |||
ec505de872 | |||
67b16b1039 | |||
37b5e09c1c | |||
9aeb4e1881 | |||
2ae3afb47f | |||
|
ddce685a40 | ||
1c8aeae41c | |||
3d8e6014be | |||
45bf016eea | |||
52d5c7a38e | |||
85dc3a3386 | |||
d8cb766519 | |||
90c422ed54 | |||
67fa9b0f2a | |||
d0923188e6 | |||
7b4f1b5c8c | |||
8e18a0a425 | |||
e729f185e0 | |||
fa698604b0 | |||
b9c1055c87 | |||
e4814fe26e | |||
36dde47de8 | |||
324195b5ec | |||
96a2ea054b | |||
655da7a2cc | |||
83ecfc4ba6 | |||
67c255952b | |||
|
55b25b239a | ||
|
0e4971da17 | ||
|
31a261de36 | ||
|
9c5c73ff95 | ||
|
3a4528a93d | ||
96068f7d5e | |||
95416e2341 | |||
2f88a3bd41 | |||
79df051d08 | |||
c90ca726c9 | |||
|
a172f67598 | ||
00bd01edae | |||
ba107ac872 | |||
d09e928338 | |||
c34eb7d84a | |||
d47f6e291c | |||
46c40ec7a3 | |||
3cabadc501 | |||
ca067121f9 | |||
9e4010a4d5 | |||
9908056c8e | |||
|
bf2b706358 | ||
|
0f0fc52a4f | ||
|
06ad3c3467 | ||
|
df3ee6e0e4 | ||
|
e9fc835baf | ||
|
07f8751501 | ||
|
ebca94dc3f | ||
1bade19380 | |||
f633f177d6 | |||
206ab7f9a1 | |||
04057c285a | |||
|
9dc6447de0 | ||
|
4a71b85602 | ||
992576613b | |||
baffa9cc16 | |||
692e01b2e8 | |||
489c5e59a3 | |||
6f663ec3fe | |||
b00e4ed91e | |||
63a831af1f | |||
d642560e30 | |||
fc11676d02 | |||
9016fb4cf2 | |||
d7d2d67480 | |||
0f0ae30621 | |||
32d898d72d | |||
5872159184 | |||
c87953a5c5 | |||
bd2d9425e7 | |||
ff93cf0956 | |||
5385a5289a | |||
09048e97a2 | |||
9d2ae04e88 | |||
aa18c441b2 | |||
9ea85fe46a | |||
f7a8efa52a | |||
958ffcd41f | |||
093c7109e9 | |||
7a81044d00 | |||
72d845f37f | |||
df87a23bbc | |||
40d3c97dc5 | |||
4090e8153b | |||
057b915513 | |||
6f4ebfbbcd | |||
b24ca52a45 | |||
cc630ccfa3 | |||
bc20e90209 | |||
5848941062 | |||
d4c79e95fd | |||
a6255053d3 | |||
aa4741d473 | |||
9f9817aee0 | |||
6dce12e621 | |||
82f06b1c19 | |||
749e9fe454 | |||
2082e016e0 | |||
a14fca6b1c | |||
7ea764f15f | |||
c7df5d50cc | |||
c5b637e902 | |||
16ccc1d376 | |||
0afbaf81ea | |||
73cfc61823 | |||
fa3a4c0fe8 | |||
c25bc1ab65 | |||
5bee7f1c5b | |||
76c8669f09 | |||
b23ed7e94b | |||
1050235785 | |||
148b780c68 | |||
4413420d40 | |||
1d95638dfa | |||
3b47002e71 | |||
482746ed5e | |||
4d5c85c414 | |||
65be0c4b6d | |||
b0079ddc1f | |||
44ab41289e | |||
ccb5ccdf42 | |||
b5f24f16a5 | |||
3d1d4914cc | |||
294c6c2370 | |||
e9ab9027ba | |||
92fb3f2347 | |||
b665045225 | |||
117530b8f1 | |||
1b1975b252 | |||
ddf03b670a | |||
bc7ed54aad | |||
7c8e6dec50 | |||
9555c86ce5 | |||
4ce0e2b8c1 | |||
d7c969224d | |||
301de2f18c | |||
eb9e5bdeae | |||
ebb3f6544f | |||
becac08795 | |||
8564dbd4c1 | |||
235e8b0f86 | |||
052a2b1746 | |||
b97465c8d4 | |||
7a5c8012d0 | |||
97ecf60181 | |||
4c09a771f1 | |||
3628faf4f0 | |||
d314ce6818 | |||
e84840d33f | |||
c97a0847a8 | |||
c8ababce27 | |||
4a32c284e1 | |||
dbddef8781 | |||
248ad3638d | |||
e7f4391e24 | |||
741c041f17 | |||
3f94b9f3de | |||
a8ebd8cc73 | |||
ff93b545b9 | |||
85f31d986d | |||
5ce8eefa6b | |||
5d09fb6146 | |||
fb6245fd0a | |||
d01a717709 | |||
0828862c10 | |||
3f48ab9e1e | |||
a1d7931c41 | |||
f2daa8fefd | |||
b64fd84ab8 | |||
8769b47756 | |||
c1938b3b2b | |||
8c3b161b15 | |||
57c4976fa1 | |||
6b22cc193b | |||
1fd6805186 | |||
78dfdcbdbd | |||
14c96fa5af | |||
710089acf1 | |||
5fbaeec1ae | |||
a7e9ef3cdb | |||
cb6d2b87ec | |||
743fee450d | |||
c79e348a76 | |||
76f9da92bd | |||
01b9f8c103 | |||
342df04879 | |||
579a3655df | |||
566f678eca | |||
837a15daa4 | |||
70a3030afc | |||
566b8a8453 | |||
dda001de7a | |||
82aec8cf2c | |||
f8da2dbb38 | |||
8437b71db8 | |||
8ed7d6ffe6 | |||
226234d16c | |||
96bd53531d | |||
3cbe429de4 | |||
92cdf2d5d1 | |||
1ebf25e5a8 | |||
760dcddd6c | |||
81e376cefa | |||
8ae137a68c | |||
c6f41a3517 | |||
1fca0aab7e | |||
067b3d1098 | |||
f1575bc2b4 | |||
20d0e0944e | |||
|
7dea7220ac | ||
|
ea317326cc | ||
|
d059bb1846 | ||
|
ef38d8f14d | ||
|
47df12b856 | ||
|
ae0cb8bc70 | ||
|
aeddcfc20a | ||
|
26ced2987b | ||
|
cd9291270e | ||
|
295b2a294e | ||
|
d2d62a019d | ||
|
3ff41b9952 | ||
|
74fa14dd35 | ||
|
22bff87bc1 | ||
|
553aa49518 | ||
|
6d6a1201c0 | ||
|
b23f087dc9 | ||
|
f37464b7ab | ||
|
e89de51932 | ||
|
d315991004 | ||
|
33f77c2b60 | ||
|
ff0c9e680f | ||
|
3720e017c6 | ||
|
8b156674ef | ||
|
d86cc8d72e | ||
c5b7e44c56 | |||
779f381424 | |||
e50645ff3a | |||
|
3589ae9cb9 | ||
|
aebc097828 | ||
|
8a32240339 | ||
|
ebc4bfa2ca | ||
|
5b5771f973 | ||
|
6c15770ea2 | ||
|
0134f11964 | ||
|
ab72401a3a | ||
|
e6789bb02a | ||
|
33d2a4d8c4 | ||
|
323b46be00 | ||
|
aaa31a5981 | ||
|
127e3704c0 | ||
|
bdd8d63d08 | ||
9281e13e87 | |||
fa8ec8534e | |||
fb3ca86d81 | |||
8ec673b549 | |||
4486ce6513 | |||
430befa3c4 | |||
5ba62c38ea | |||
a41492f174 | |||
665f9d336c | |||
c41aeb180d | |||
d8ec88cb46 | |||
6c12a2e772 | |||
27c91356fb | |||
ffe62bbbf9 | |||
3caa1eb6a1 | |||
50d46e8a0e | |||
fb52221d66 | |||
cf66ca0b99 | |||
bfcd71a518 | |||
33a4b0b2b7 | |||
fed35e00d4 | |||
f8013c4670 | |||
a29035f382 | |||
8f8965fe18 | |||
76229e6dfc | |||
ece9d87a79 | |||
fe0bd22668 | |||
892b2a833a | |||
a9c01cb906 | |||
a6b0921f12 | |||
54c472675c | |||
e1ef89b1c2 | |||
293cf382c0 | |||
35efa6f16b | |||
c3e436c75e | |||
15009b3503 | |||
7157e43baf | |||
b9976e2893 | |||
788fb8257e | |||
5114ddaf0f | |||
25887c88a5 | |||
612ad106e8 | |||
e252c087a8 | |||
b4c7a39054 | |||
a5d2278d31 | |||
2d093a61e0 | |||
d335660d30 | |||
5dc33bd8a5 | |||
706da4ab8f | |||
f67de97eb9 | |||
d3387330bd | |||
03eaed72a1 | |||
ec91858263 | |||
0bcd1c527c | |||
cbd3deede9 | |||
bd0062ecd2 | |||
96514f092a | |||
|
8b93bdbe11 | ||
|
364e6e4be5 | ||
|
1eb78c5cd8 | ||
|
3908d75240 | ||
|
1fe067aa25 | ||
|
bd3630f718 | ||
|
6506679466 | ||
|
3a88ae8dca | ||
|
a89f3e9329 | ||
|
f8decc4ce3 | ||
|
12e59b0b4b | ||
|
524bf2223a | ||
01da51ac9b | |||
|
ad0fa89ede | ||
|
479a546679 | ||
|
dc0638cab9 | ||
|
b1418461ad | ||
|
b58113a8ef | ||
|
346b2a8cec | ||
|
59f0fe537f | ||
|
d79861cbdf | ||
|
78f18afab8 | ||
|
54426593d5 | ||
|
0b8ae49b70 | ||
a55c2b9de4 | |||
97374fafb4 | |||
|
b1b77d767c | ||
|
2b94ba426a | ||
|
7594821ca7 | ||
|
d378cd94a2 | ||
|
a7158cf366 | ||
|
66ad9623da | ||
|
ff6ececbb9 | ||
|
f4f8cfe885 | ||
|
4e02938e3a | ||
|
06ec036d9a | ||
|
67565a1d93 | ||
|
3789ca2b42 | ||
|
a08367a992 | ||
|
93c13f3f16 | ||
|
f24688afa2 | ||
|
1442f75f15 | ||
|
ba06a9f69a | ||
|
b4da3b7d98 | ||
|
2f5a8c565d | ||
|
a07775f25a | ||
|
d25dbd3a81 | ||
|
cde0e52528 | ||
|
4d17eebdd6 | ||
|
452123813e | ||
|
26fe5fb214 | ||
|
d7991f702e | ||
|
39a449d92a | ||
|
1c1a97c22a | ||
|
080a601c3f | ||
|
5e481ca3d7 | ||
|
1f32a6e7cc | ||
16a95dc510 | |||
44d32d0677 | |||
|
1f37f1ca91 | ||
|
0f3cdfe3c6 | ||
|
6084179d1d | ||
|
490d39a9ba | ||
|
08bed9fc33 | ||
|
9240883e59 | ||
|
36ed072667 | ||
|
dfd6291563 | ||
|
babebc5a7e | ||
|
43da5f03db | ||
|
55c921025a | ||
|
3247e14a83 | ||
|
e3744bf7d8 | ||
|
695abf314a | ||
|
fc2fbf2103 | ||
|
4c0e0bd4b6 | ||
|
33b4337d0b | ||
|
6f7efd7420 | ||
|
108e285704 | ||
|
9de4b08d20 | ||
|
04fab0e06c | ||
|
6a9d194942 | ||
2ad1036a7f | |||
|
14f525a618 | ||
|
e90da78bad | ||
|
ba1d5bbf1f | ||
|
93e78c0963 | ||
|
03ae2b84f9 | ||
|
d209f40cf9 | ||
|
2510a1bc8d | ||
|
687a98df15 | ||
|
77fc370e28 | ||
|
a1d934ad7b | ||
|
9a8592cb68 | ||
|
cba87d3295 | ||
|
374439755c | ||
|
89a5828d99 | ||
|
c45fdc4895 | ||
|
df778fbee1 | ||
|
9630f093cd | ||
|
c2c67b55ff | ||
|
fd8a15812b | ||
|
e2f1d5e0e3 | ||
|
b9af44b99c | ||
|
020392ae3d | ||
|
650ae755be | ||
|
90ad9f29fb | ||
|
a6e245e83b | ||
|
c6d48a8fdf | ||
|
20ebf0d2c9 | ||
|
2d8c5cad07 | ||
|
0c4827b507 | ||
|
b495afc2e8 | ||
|
89ef3c84ab | ||
|
2d730ab100 | ||
|
4d9d71602e | ||
|
40a62401bc | ||
|
1f6c665479 | ||
|
fc90dc0d45 | ||
|
ef75ce3b28 | ||
|
ab95e70846 | ||
|
52b10d1382 | ||
|
9d97c0a75f | ||
|
1ca00c11e5 | ||
|
6bd248fb6a | ||
|
faf64a0660 | ||
|
7389f3026d | ||
|
7f4e03f2c6 | ||
|
90d0fc2127 | ||
|
ba5cdb3deb | ||
|
0432eb65b6 | ||
|
c8b16f2f25 | ||
|
86e9ef539b | ||
|
e7348012ba | ||
|
1dab50c5ff | ||
|
861d08768a | ||
|
ffe91f99d8 | ||
|
b0e8be710b | ||
|
51b6f4b51d | ||
|
b9ca6e500f | ||
|
1ed2e8ec35 | ||
|
541ab1728b | ||
|
9c9c95653c | ||
|
05920a3171 | ||
|
0b55bba9c6 | ||
|
b2969a748e | ||
|
92bbafdafd | ||
|
08127b1fd5 | ||
|
88b716a448 | ||
cb254d9a31 | |||
bbab45758f | |||
9864d8120c | |||
|
2d432a375a | ||
|
27154982ec | ||
|
6a76673dd3 | ||
|
2f41223c29 | ||
|
40a770a1f6 | ||
|
57821752f4 | ||
|
e54edf6fe1 | ||
|
993089841b | ||
|
02d3a41e26 | ||
|
e5b0ff0311 | ||
|
3fad88dcbc | ||
|
66c4395069 | ||
|
2f256c65f0 | ||
|
a4fe13124d | ||
|
316faabcbc | ||
|
8923dd9a2d | ||
|
125d3a2a5d | ||
|
2b72cb419e | ||
|
f4bff1b460 | ||
|
dc3e7f8356 | ||
|
e14d9b17b0 | ||
|
7d84df4722 | ||
|
0cdf031a53 | ||
|
39e6e38107 | ||
|
8112e732d7 | ||
|
812e7ca904 | ||
|
a233a1aa24 | ||
|
8de48859c2 | ||
|
d694d604a4 | ||
|
b5aa88483d | ||
|
0658c6a9bc | ||
|
d89b1f40c0 | ||
|
a62366d0a0 | ||
|
9e36af3846 | ||
|
1bd5e0b17c | ||
|
8ee77b8072 | ||
|
ffe8e7aa8a | ||
|
b9d4971aa6 | ||
|
6c893e4333 | ||
|
0512fd914f | ||
|
0cb9de7b8e | ||
|
fed8fb6ab1 | ||
|
8a7919cf6b | ||
|
f38f7ce547 | ||
|
1199a67ed6 | ||
|
6a27eb440b | ||
|
f4c764e2f6 | ||
|
7a4cc0c651 | ||
|
6e3647909b | ||
|
2c087edd85 | ||
|
9c9bea68de | ||
|
cd1f578011 | ||
|
eee99d43f9 | ||
|
2e9272d8c2 | ||
|
07049a4ab6 | ||
|
7d0f09ece9 | ||
f74d665fb3 | |||
|
e28b5d77c7 | ||
|
cb162a91de | ||
|
f01e9d3899 | ||
|
93d20a230c | ||
e4483538fe | |||
a73fc581b8 | |||
f6e4b6f9bd | |||
eec377a386 | |||
a375d9cd3a | |||
5c07089123 | |||
85843f985e | |||
cbe3f64e46 | |||
e2aa5d3e20 | |||
f392604977 | |||
00e6005983 | |||
cca005fb06 | |||
ce0297251c | |||
|
4839b306d9 | ||
|
b56320189a | ||
|
c7bf3a36cf | ||
f8887806a0 | |||
e5b1165333 | |||
154278ef98 | |||
|
3a80515b17 | ||
|
59ed2b7ad0 | ||
|
e9d97b49b1 | ||
296d1593e6 | |||
6ddec644ac | |||
3c385f4a41 | |||
37cf776789 | |||
2a197e886b | |||
1695d7d242 | |||
f60e1ab9e7 | |||
a079cadc68 | |||
c180f65af8 | |||
|
de6a3fffdc | ||
|
ddbeedd4d5 | ||
|
2f332d2bc3 | ||
|
cb8b5d4de1 | ||
|
0d157b8957 | ||
|
6d576a16a6 | ||
|
f7d2c36086 | ||
|
61a3dc6093 | ||
7766c16ed9 | |||
60bb775109 | |||
28c5c67e26 | |||
7fc128c1fc | |||
30f72c6859 | |||
a0a259f92f | |||
a7498110fb | |||
|
33d47a7e5c | ||
c30b839587 | |||
ab05c7a7f7 | |||
47851aa99a | |||
|
bb6750def5 | ||
|
9b6f8f1c11 | ||
|
7dc0b4caf8 | ||
|
5bcb36c23d | ||
|
f000db5746 | ||
|
e0adc83d60 | ||
|
2df93cb653 | ||
|
5ac2b33a2d | ||
88762ee5de | |||
b76724107e | |||
|
8d6bda4629 | ||
|
101b8ac0f0 | ||
|
2951b2cb5f | ||
|
5b895c8375 | ||
|
2c8be86f60 | ||
|
4d49ea0974 | ||
|
3def0e9b92 | ||
|
a6920c6c4e | ||
|
79442c9174 | ||
|
5fb09bd802 | ||
|
b668b586bf | ||
|
766a89ee56 | ||
|
96a6b9ff27 | ||
|
606c67ae7e | ||
|
21c70e7eab | ||
c10ad5d5da | |||
|
22bd4aa037 | ||
|
c48bb16655 | ||
|
3fe450e06e | ||
3bc9e52c3d | |||
10ef44aaaf | |||
20d5c4d221 | |||
|
31d3320f19 | ||
|
a894628696 | ||
|
d8d0d68f47 | ||
|
98a3a67478 | ||
|
95c269873f | ||
887ce73f02 | |||
f95d8a7961 | |||
0e002df2af | |||
|
14af9847f6 | ||
|
ef2aee3f59 | ||
|
40c862d251 | ||
|
3dcf8f1b96 | ||
|
74f0f60a8a | ||
|
0e4d1ed570 | ||
|
af72107c79 | ||
|
d900380822 | ||
|
32312a3e54 | ||
|
1244f2a60c | ||
|
b5d31033ff | ||
e584e9fd5f | |||
|
1eb994368e | ||
|
d75d78fa31 | ||
|
75539e2ef1 | ||
|
0bf94567bf | ||
|
8a3d876e8f | ||
|
688c923214 | ||
|
23de277cd6 | ||
f0a9371e5a | |||
|
df42bb55c9 | ||
|
fdeb89465d | ||
|
ca5e16d729 | ||
|
9dabff9d74 | ||
ee476e2842 | |||
|
19825afe2d | ||
|
f04a05168f | ||
|
9d7810ebf2 | ||
|
3b1f6a874a | ||
ec5b33dd0f | |||
55801d2d96 | |||
fdcbb22e0c | |||
e1bfde36dc | |||
f5bb4cb050 | |||
bcd1f4910a | |||
1d75d17e4d | |||
2393a17742 | |||
|
cc22f5ac1a | ||
af496ab23a | |||
|
6a7642e5a0 | ||
|
696d38b1f4 | ||
|
4ba7c59d32 | ||
ed2130e8e1 | |||
af94b2e5bc | |||
|
35408d32eb | ||
5fda899e88 | |||
|
73aeea6874 | ||
|
e6dc5dff75 | ||
68b4cab5ac | |||
|
fed10aa71d | ||
|
31173bcef3 | ||
|
8dff1cd069 | ||
|
ddb0f4f4a5 | ||
|
1cad66691c | ||
|
98f017d6c5 | ||
|
c6bda6ebb7 | ||
|
c1a1cdf1bd | ||
|
3f68897639 | ||
|
a5437ef333 | ||
|
041da51cac | ||
|
eaf479246e | ||
|
b45afbc245 | ||
|
c648d328d6 | ||
|
dde3a1c6a2 | ||
|
4fb0528ea5 | ||
|
0dc4420bff | ||
|
834de6a5f2 | ||
|
a8438fb722 | ||
|
878b3ecbb1 | ||
|
40ca6378a2 | ||
|
cff5bb8a4a | ||
|
1900495cd6 | ||
|
8da4cc0cfa | ||
|
418f5d74d2 | ||
|
734d3e67fa | ||
|
9367721d99 | ||
|
24d9d08f96 | ||
|
1beb70a5c3 | ||
|
e9c3c2ba22 | ||
|
17a7b63761 | ||
|
2935a4dd8e | ||
|
f6c1e2a9f3 | ||
|
3facabaeca | ||
|
3b8b09df59 | ||
|
0f85512bb8 | ||
|
691eed8ba4 | ||
|
9de5d5975b | ||
|
37b3bdb14a | ||
|
271beb06e9 | ||
|
34ef8d7237 | ||
|
da87070418 | ||
|
efc324c3db | ||
|
36e4cd8253 | ||
|
7e43f3adf4 | ||
|
3e53df3e7f | ||
|
ff4f1489f2 | ||
|
eea05bf358 | ||
|
d752d3b03b | ||
|
8d1c68a2c6 | ||
|
2b8466428d | ||
|
82a42d8daf | ||
|
606cd9de62 | ||
|
d4d8f0eab5 | ||
|
440fed288c | ||
|
668fda3d1d | ||
|
019a774ddc | ||
|
9b8d8c603f | ||
|
5b2e349726 | ||
|
0feee84a23 | ||
|
384ac6052f | ||
|
babf10f4bf | ||
|
f86eee254c | ||
|
29a2524231 | ||
|
d7f03521df | ||
|
2ad68ca01d | ||
|
d6f97b03bb | ||
|
78e6dd7adc | ||
|
f22eda7e6d | ||
|
beff8b1012 | ||
|
29036af835 | ||
|
f8683cc9e6 | ||
|
1a5935815a | ||
|
7be1dff6aa | ||
|
52f59c1061 | ||
|
f1207551a5 | ||
|
6d184fb0e4 | ||
37278e626f | |||
|
c8a313687f | ||
|
76e7f45ac1 | ||
|
3a637cc9fb | ||
|
bb782a7e8f | ||
|
ba7ceaa2cf | ||
|
b9864fbfb8 | ||
|
18bfadec1f | ||
|
aa2bfa5ddb | ||
|
a8eb0f39ad | ||
|
e7bd96af39 | ||
|
03b9ee2094 | ||
|
7c3c0c145c | ||
|
7699120fe1 | ||
|
31981a39e6 | ||
|
0e00d64620 | ||
|
a082bb130e | ||
|
1beadf188b | ||
|
b2700fc989 | ||
|
7dd83edb4c | ||
|
5d5b87d9e6 | ||
|
5deec55290 | ||
|
6c2074ca70 | ||
|
21fa4d242c | ||
|
4121504f60 | ||
|
1d9e6ddee4 | ||
|
fc0cf37fc3 | ||
|
b57d87859c | ||
|
c57b176f20 | ||
|
5ec18961de | ||
|
aaf0e1c459 | ||
|
92b78bc7a9 | ||
|
1eeb8fcac7 | ||
|
4535c05dd2 | ||
|
1cf8ff5ca1 | ||
|
258ebce4a1 | ||
|
6e7de11d64 | ||
|
8e64e6637e | ||
|
8efafd9683 | ||
|
757ac6672f | ||
|
8b2d09ed61 | ||
|
47e6121567 | ||
|
41408bc047 | ||
|
44c0eda419 | ||
|
945f45609c | ||
|
0ab9c3e309 | ||
|
bb7481aabe | ||
|
1fc11e26b7 | ||
|
23fdca6c52 | ||
|
72e12e17c0 | ||
|
311deabfb4 | ||
|
94e65e92aa | ||
|
49744a75b0 | ||
|
db9cb1f6ab | ||
|
51607bfbb7 | ||
|
815be8cd3b | ||
|
73cc7c0a91 | ||
|
c319240444 | ||
|
4b53936fa8 | ||
|
b74073645a | ||
|
185a3993db | ||
|
9920be0b20 | ||
|
aa318357fa | ||
|
45c9788228 | ||
|
3fe2e76741 | ||
|
0aad617a33 | ||
|
cd73ac6996 | ||
|
4c0811ccb6 | ||
|
812ad68832 | ||
|
8bbb19fb35 | ||
|
5bfceca3ec | ||
|
b91db6fbbc | ||
|
adaea91dbb | ||
|
7b286c7940 | ||
|
704930aa5d | ||
|
1da895bda8 | ||
|
d4ad266573 | ||
|
4406458c11 | ||
|
e7b320e5ad | ||
|
7b4bfcc484 | ||
|
cf7a0cf177 | ||
|
59354b4556 | ||
|
c0643c03a0 | ||
|
d641d9d673 | ||
|
f47fd18a12 | ||
|
a78db57ef5 | ||
|
5bdd1b13cd | ||
|
30a3caf75e | ||
|
043df9922d | ||
|
b01ea7aa42 | ||
|
2ee8f59c89 | ||
|
e3749b8fc7 | ||
|
0de6e5a1cb | ||
|
0cd84b7f2e | ||
|
caca2507ca | ||
|
b8c3e7a266 | ||
|
1a201d127a | ||
|
1d404290c3 | ||
|
53a2b8c270 | ||
|
33d4c02bb2 | ||
|
384c620ae7 | ||
|
3a6739fa4f | ||
|
a5fd6a99e0 | ||
|
1a881e2023 | ||
|
1e76d58f7e | ||
|
184fb45b70 | ||
|
06d379c747 | ||
|
5802814f15 | ||
|
867b0d3d0b | ||
|
966e88abd0 | ||
|
3287c300f5 | ||
|
36dddcf30b | ||
|
33e1ac75a6 | ||
|
2abcc365ae | ||
|
39f7421569 | ||
|
bafd6addbf | ||
|
6c4aa26608 | ||
|
c39ae60a42 | ||
|
2aa3e80e0a | ||
|
7245fb8804 | ||
|
88f50b825c | ||
|
de6c83380a | ||
|
49e8603ff9 | ||
|
793860f7d1 | ||
|
1828d9c7a3 | ||
|
fee358a385 | ||
|
9541002a39 | ||
|
de1dc21f4e | ||
|
b0272b4761 | ||
|
6b329558dd | ||
|
1c2e2d2d85 | ||
|
6f257433a5 | ||
|
0eafd2edfa | ||
|
19039a8eb2 | ||
|
07b7c5350f | ||
|
b85fdfcd9e | ||
|
b38628d726 | ||
|
642a1afea8 | ||
|
9dcc5a28a6 | ||
|
51361afc12 | ||
|
949e4468c5 | ||
|
21d649946f | ||
|
89c86300d4 | ||
|
bb59346027 | ||
|
1251f247d3 | ||
|
639fa7c85f | ||
|
86830a4c9b | ||
|
68eb2cc061 | ||
|
5c50a87ff9 | ||
|
62a4debf62 | ||
|
0a2e3cb28d | ||
|
dc31fc3ee6 | ||
|
41ae0e18e1 | ||
|
7d6a46c9b5 | ||
|
55bead4f4f | ||
|
1a5a163d4f | ||
|
5577b1b9b0 | ||
|
2c5986c127 | ||
|
6f48ed51bd | ||
|
c89eb7b505 | ||
|
8a7503a7c1 | ||
|
6f9f447763 | ||
|
fb0a9d74fc | ||
|
b0491002e8 | ||
|
226b4e03df | ||
|
96139d31fd | ||
|
9b53b55682 | ||
|
6de44652fa | ||
|
a83d577f66 | ||
|
47e8016c51 | ||
|
30c3196460 | ||
|
d20bd6d14f | ||
|
c0df60b319 | ||
|
44fd79e3b2 | ||
|
4107cb0df0 | ||
|
f56790516e | ||
|
b02326f0cc | ||
|
b8366f34cb | ||
|
e414988bee | ||
|
4215eb06b4 | ||
|
b35d48bdc2 | ||
|
3136da34ca | ||
|
b5640310b7 | ||
|
5e4f5ddf91 | ||
|
2ef87c0c1a | ||
|
9a26cf73d6 | ||
|
a9ee02d1bc | ||
|
c368746eae | ||
|
2e90cb5952 | ||
|
4c6762e55f | ||
|
496cbb2054 | ||
|
ff4a9c45ea | ||
|
20ed2464d4 | ||
|
671eb4001c | ||
|
3b128b7b9b | ||
|
3b2c78e178 | ||
|
c7c3b4e97e | ||
|
92d55df344 | ||
|
2b207f0499 | ||
|
5962ef846e | ||
|
04602aacea | ||
|
3ba789dde2 | ||
|
f987aecbff | ||
|
8023df17e6 | ||
|
354d9c5627 | ||
|
a8e74d471f | ||
|
82e1493ede | ||
|
21580cf4fa | ||
|
9158a48d39 | ||
|
24f463b77e | ||
|
d4d336d730 | ||
|
1c61bf5e88 | ||
|
f3d1c930d7 | ||
|
0af5e5663d | ||
|
7397630165 | ||
|
f41811a861 | ||
|
135df50a66 | ||
|
3c4e1f1294 | ||
|
d36a2048a6 | ||
|
ea8fd8e097 | ||
|
784d3b9cb8 | ||
|
34a26ea4ab | ||
|
972b86676e | ||
|
cafb3cd1ee | ||
|
dd00425e33 | ||
|
d486674d73 | ||
|
256c9c62b2 | ||
|
64b1ceeccb | ||
|
27df460d0c | ||
|
159c7f82e2 | ||
|
7a31eb4ff1 | ||
|
8fce54024e | ||
|
747d0455f1 | ||
|
8d089a0dc5 | ||
|
01bffadc87 | ||
|
f4048cfb4e | ||
|
ff951024ea | ||
|
3f23765791 | ||
|
2ad472e548 | ||
|
32b7ca8c00 | ||
|
e8326e848e | ||
|
13b70d499c | ||
|
a7b7512ed5 | ||
|
6d3cec1b65 | ||
|
67843f4f0f | ||
|
d06aa23eba | ||
|
8105d466c9 | ||
|
47eef28318 | ||
|
3a5702e36b | ||
|
f2e6af6dea | ||
|
20c2858c36 | ||
|
f667587274 | ||
|
8eed8d73fb | ||
|
5e43d6fd21 | ||
|
493b8ff6b2 | ||
|
e7424dc9dd | ||
|
96b0a1a9b9 | ||
|
52be6d2997 | ||
|
0a755dc1fa | ||
|
66c2546b7a | ||
|
459f55081c | ||
|
6634e99569 | ||
|
31987f4066 | ||
|
ca411cf9a1 | ||
|
72d3bb772f | ||
|
9a2274a716 | ||
|
ba7a0633b0 | ||
|
62da5cc5b5 | ||
|
f863b69a4d | ||
|
7783eb69ab | ||
|
6180b903c9 | ||
|
3508f3a6cf | ||
|
507912926d | ||
|
ca8b3e8d7b | ||
|
a7058e4c49 | ||
|
746163e0d1 | ||
|
ae98d2f1ae | ||
|
53c82522aa | ||
|
813dc501a3 | ||
|
b8e0d53288 | ||
|
b192070782 | ||
|
23fa96a2b6 | ||
|
6fae1187e3 | ||
|
2f27ca0235 | ||
|
bbc727d400 | ||
|
4f6f4139bb | ||
|
cd39cfe53c | ||
|
17890bc81d | ||
|
b5532c8662 | ||
|
71e12a5ada | ||
|
567a70d909 | ||
|
3fefff219d | ||
|
1915f554b7 | ||
|
aff90ba298 | ||
|
5de144f947 | ||
|
8833dca44f | ||
|
81a6496ee6 | ||
|
7b40871927 | ||
|
cf6b37f49d | ||
|
d0e1f5abe1 | ||
|
1a97c3b477 | ||
|
f615a37473 | ||
|
e7c19df92e | ||
|
b8772c0ac6 | ||
|
e5d838b345 | ||
|
41c44b4557 | ||
|
fc1ac0c5e7 | ||
|
27e4b9db3b | ||
|
d1d0a485d7 | ||
|
dc3d7dbe7c | ||
|
c88fbe4092 | ||
|
cff5837d41 | ||
|
c46907396c | ||
|
3355e0311e | ||
|
dd65cdb3c2 | ||
|
ec59a0c77c | ||
|
772bda27e6 | ||
|
34aac7834a | ||
|
8a66c3d1ae | ||
|
bcbcb79a12 | ||
|
a892fd9855 | ||
|
f6cf9c107a | ||
|
2fd69d0950 | ||
|
645cb7fef5 | ||
|
05f64946a6 | ||
|
227b3943a3 | ||
|
f5a31309b9 | ||
|
2d41fad30d | ||
|
c0494b6ae6 | ||
|
dbf12fc999 | ||
|
868271617a | ||
|
1d4e9a1862 | ||
|
d2f643634e | ||
|
8c8d42344d | ||
|
9596ca9932 | ||
|
7b5f1aab4e | ||
|
a741f0ddcd | ||
|
cde72fe1ce | ||
|
c83e8e3149 | ||
|
e07285259b | ||
|
1cfdd115bb | ||
|
00ad2cc3a4 | ||
|
fcd20f61e5 | ||
|
a37c02f8ac | ||
|
6df7256a98 | ||
|
fd02c81190 | ||
|
2c7f2b6c96 | ||
|
024f7451e6 | ||
|
f17161f9e9 | ||
|
f5bda47965 | ||
|
22dfce63b9 | ||
|
8abe700c42 | ||
|
5427853357 | ||
|
85c8e923d2 | ||
|
c5a4e16726 | ||
|
87d8f2a22a | ||
|
01cd75cfd0 | ||
|
0952e597e4 | ||
|
f382a5a16b | ||
|
96425a116f | ||
|
fdd52d206c | ||
|
23757e3fbc | ||
|
7e310da9c2 | ||
|
f80db3cacf | ||
|
c535d7560a | ||
|
cd41906adf | ||
|
97110dd032 | ||
|
dac78b6c02 | ||
|
4b296ff48f | ||
|
b6023ede0f | ||
|
617351290d | ||
|
0562fbe33c | ||
|
fa0323141b | ||
|
4be16c87e8 | ||
|
ccc5041dad | ||
|
0517dc4df4 | ||
|
5c6a90c0ac | ||
|
d4321076fc | ||
|
b2ed7b4866 | ||
|
f9eb28f6f3 | ||
|
174e087fc3 | ||
|
e6f75275f2 | ||
|
1749b1265f | ||
|
ac773706a2 | ||
|
7644da6401 | ||
|
a4a2973dc4 | ||
|
4786942409 | ||
|
3ebd99c284 | ||
|
8821da73a0 | ||
|
aa7a0926c4 | ||
|
63f1c6844f | ||
|
6477265a8a | ||
|
d0827ca3e7 | ||
|
31961f112d | ||
|
1e2f6b9a6b | ||
|
50d12a210a | ||
|
2384367a68 | ||
|
0dc4df3b98 | ||
|
26841c795c | ||
|
f8fa03e7de | ||
|
5c35bd3c1d | ||
|
1051fa0731 | ||
|
f0fe2c0177 | ||
|
589fe9f8cb | ||
|
4104fdf736 | ||
|
f2fc03ce91 | ||
|
2f3db2d426 | ||
|
c83e0e6b4f | ||
|
920f012007 | ||
|
107c41f409 | ||
|
93e2dd40e3 | ||
|
339241383f | ||
|
a056755826 | ||
|
2e929d142b | ||
|
62c0e29b44 | ||
|
b9bc252979 | ||
|
00a3243d87 | ||
|
96d2fc2e0d | ||
|
d0c14aaa49 | ||
|
b4e7a0f5f4 | ||
|
332127401f | ||
|
50fd8a3c9d | ||
|
5dfbe9a60d | ||
|
a2b2896d80 | ||
|
680af4c652 | ||
|
643a60ddd5 | ||
|
2c3124b462 | ||
|
5a151c577c | ||
|
fe2425bf5d | ||
|
fe7a6f3ca0 | ||
|
ef6928547b | ||
|
2f97898e6e | ||
|
61fb84d594 | ||
|
29a41a8d99 | ||
|
97c820c7d6 | ||
|
afeb66fd7d | ||
|
5291f058a7 | ||
|
72b82aa071 | ||
|
03568f6641 | ||
|
2171f1b6d6 | ||
|
db6e2c3a97 | ||
|
7772b25d6a | ||
|
7aad2deb53 | ||
|
3d140e1a36 | ||
|
a5327a959c | ||
|
25f22f4ff2 | ||
|
c0564f705c | ||
|
0b66f0ab2e | ||
|
e181178a54 | ||
|
33aed39f83 | ||
|
1901e06957 | ||
|
323042f563 | ||
|
1308ab8a5f | ||
|
b676ed401e | ||
|
f8430c9745 | ||
|
52f69a2b37 | ||
|
eec9b80e81 | ||
|
b1c4ce34a4 | ||
|
b45bb37c4f | ||
|
af3d4dfa41 | ||
|
c88da6198b | ||
|
06d71f44f6 | ||
|
5fb003bae6 | ||
|
9d444be061 | ||
|
175dd51a18 | ||
|
0216e0c1e1 | ||
|
2278f837cb | ||
|
bf13ccb675 | ||
|
9eed5ad28f | ||
|
4aaa6cbc58 | ||
|
26f88cbb26 | ||
|
a66a2c516d | ||
|
303455aec5 | ||
|
975c702d2c | ||
|
5d2bde567f | ||
|
cde9187b0d | ||
|
da4e8fc46c | ||
|
e222a7ded2 | ||
|
cda2d93812 | ||
|
02951c7c66 | ||
|
f08650f148 | ||
|
1b117eb8c0 | ||
|
62f58b16a0 | ||
|
c39e1640e2 | ||
|
bd43bf0e85 | ||
|
435c1fa05f | ||
|
6f228d168d | ||
|
4c93a1aa6d | ||
|
ae46017b20 | ||
|
dc426c25e3 | ||
|
6f82ddc1a2 | ||
|
2c1be3c3e2 | ||
|
96f1a83850 | ||
|
332bb6f1f9 | ||
|
eace81330f | ||
|
89ab970806 | ||
|
65a064ef92 | ||
|
a18df7cdf4 | ||
|
f0aff19b80 | ||
|
41ceb694d8 | ||
|
c3ab04ee79 | ||
|
3c7c7c628f | ||
|
13627f5e59 | ||
|
4b9f0b1ef7 | ||
|
be7ea6c4fb | ||
|
de7caa49c1 | ||
|
2e644e7cd4 | ||
|
80e5088b68 | ||
|
7229473a22 | ||
|
dc65a8e618 | ||
|
2404142d9c | ||
|
d5beaec9d7 | ||
|
78259f3da6 | ||
|
0a877b0d24 | ||
|
b9f49174da | ||
|
beb85b9e9a | ||
|
b6a448ca9b | ||
|
7011373627 | ||
|
b308b50476 | ||
|
582ebe2650 | ||
|
c2a3cd09b5 | ||
|
27e282245c | ||
|
42fd1dd842 | ||
|
d1bde29a81 | ||
|
6d8288ac9f | ||
|
2aa777fac2 | ||
|
027e75dd7e | ||
|
b8d464fea4 | ||
|
44d7b54e5d | ||
|
bf17ed81c0 | ||
|
b9b514263a | ||
|
7e8dbc3f0e | ||
|
75c796c5c2 | ||
|
aabe72594b | ||
|
59eab29353 | ||
|
8398aae329 | ||
|
12c935656b | ||
|
b746700d0c | ||
|
fef55731be | ||
|
c058d25d39 | ||
|
7edb7b4f0a | ||
|
2ddf76ef24 | ||
|
3ac6bb75ea | ||
|
d402ad9516 | ||
|
e05f0d1bef | ||
|
8d00613ce9 | ||
|
96b06cc19b | ||
|
9c6c0d664b | ||
|
030b42ab09 | ||
|
c0aaa15ad5 | ||
|
0c08e387b7 | ||
|
318a2d7e1c | ||
|
80c80aca3c | ||
|
f6d0635f1e | ||
|
901c21f894 | ||
|
1395ed4a0a | ||
|
9d9c6780df | ||
|
dfe31a2400 | ||
|
8885ddb362 | ||
|
b177a9eca1 | ||
|
b3a467e274 | ||
|
659bc7f922 | ||
|
084b5c73c5 | ||
|
4bca8f92f4 | ||
|
f8e11f4016 | ||
|
f26ca90a91 | ||
|
ad275ec629 | ||
|
d6eaa7cd50 | ||
|
2f40fd565a | ||
|
a42798f47c | ||
|
d7b9817ae0 | ||
|
9b6ece352b | ||
|
44d5866d3d | ||
|
a1c2a86d5a | ||
|
9c5642b9b0 | ||
|
f84613561e | ||
|
61984d5c78 | ||
|
711e5fef44 | ||
|
19af48b777 | ||
|
f89e2d3142 | ||
|
b36a0f069f | ||
|
0d5ed4bf8d | ||
|
63d3931549 | ||
|
092c4053b2 | ||
|
0ffe4f7b40 | ||
|
e576a62b2d | ||
|
b4b33ec600 | ||
|
2d4a4b323c | ||
|
70a496a749 | ||
|
7cf99fb99e | ||
|
05beea4ab1 | ||
|
36a2c0fcde | ||
|
590daa8b89 | ||
|
77df0f9de8 | ||
|
66ef114f56 | ||
|
5ece1ed117 | ||
|
f7b1e76387 | ||
|
a6a46fea76 | ||
|
a5441402c0 | ||
|
a3261a6a4b | ||
|
34f0f8ff0d | ||
|
4e88ec43ad | ||
|
8f696cc1cb | ||
|
707397f3ec | ||
|
04978ab13a | ||
|
04d585b277 | ||
|
1325b09fe9 | ||
|
86b552ec93 | ||
|
14aaa9af23 | ||
|
b050238af7 | ||
|
016790052c | ||
|
7986fc27d7 | ||
|
f26924461c | ||
|
f7b411a09f | ||
|
b3a094c4ee | ||
|
f25b27eae0 | ||
|
d2b6c54418 | ||
|
3feab64a17 | ||
|
711b3ffab9 | ||
|
1c065ba546 | ||
|
04c5fe5193 | ||
|
6f3e81f7ce | ||
|
64641b2417 | ||
|
18c5ca26a7 | ||
|
540ec4a796 | ||
|
29a4193450 | ||
|
1f4ba11970 | ||
|
3731ef209a | ||
|
6a075b9880 | ||
|
6647cf8bea | ||
|
8bc087bc89 | ||
|
dd39587938 | ||
|
4c43750e3a | ||
|
bd12f3d5d9 | ||
|
c541c2e742 | ||
|
a17a7e0807 | ||
|
0f851a7304 | ||
|
58b923fc18 | ||
|
0e93feb076 | ||
|
784a4935fd | ||
|
6976594a14 | ||
|
9b847547f3 | ||
|
e076950f0e | ||
|
fe273b8019 | ||
|
7cc5a928d0 | ||
|
5ff6a7d65b | ||
|
9960979944 | ||
|
6c870d23d2 | ||
|
1695e48db1 | ||
|
eea886c1c8 | ||
|
2c61f2a0b7 | ||
|
1aa57f0f35 | ||
|
368f98e959 | ||
|
67707f36ed | ||
|
59e42e81d8 | ||
|
635e561765 | ||
|
b96a089678 | ||
|
febbdf3923 | ||
|
cdb0dbc3b4 | ||
|
7e3dc1d1c0 | ||
|
f8e1f98002 | ||
|
8ba60263f7 | ||
|
18ab09cd3c | ||
|
6227b843fb | ||
|
3e65b0bc6a | ||
|
997ef55efb | ||
|
3675aa196e | ||
|
a4505c2d88 | ||
|
88cc62e15d | ||
|
26d28be381 | ||
|
f3013b0764 | ||
|
5801b09583 | ||
|
5bd3c0a9fe | ||
|
d374749ebc | ||
|
40fc832c7c | ||
|
2c803996f6 | ||
|
0aa0652de1 | ||
|
3a05406525 | ||
|
1a6ce51080 | ||
|
a7376f7f17 | ||
|
baffde2f07 | ||
|
03620979b6 | ||
|
b3cdc71b8d | ||
|
b89314610b | ||
|
0b400cdb35 | ||
|
cddf3ab4a5 | ||
|
fd633ccfd2 | ||
|
87b19c913a | ||
|
f062d209c8 | ||
|
6ec6e74c0b | ||
|
f97b2a7ed3 | ||
|
53bb2efeff | ||
|
8ee8229e3f | ||
|
ac15324da5 | ||
|
e94cb81b24 | ||
|
bf1819fc74 | ||
|
9c46c227d0 | ||
|
5a8420bd3d | ||
|
83b5234efb | ||
|
d31cedb23e | ||
|
a670fa4e5d | ||
|
74787dffbc | ||
|
7c956dd919 | ||
|
9ab2e0eefd | ||
|
38e05f0115 | ||
|
5a9e7405e0 | ||
|
c933abefc2 | ||
|
8b4775967d | ||
|
065c8832cb | ||
|
30542b157b | ||
|
d95142c3f1 | ||
|
c38c8b8694 | ||
|
603f28189e | ||
|
13a143815d | ||
|
c03a22436e | ||
|
80f091b59f | ||
|
8581911e61 | ||
|
4400b6de8b | ||
|
5a0998e139 | ||
|
14e0499bc8 | ||
|
54b5efd1d8 | ||
|
a049fcb269 | ||
|
7938ba7645 | ||
|
b54f2ed9bc | ||
|
7863b098ad | ||
|
d62ccb442f | ||
|
2c6e4ff6d8 | ||
|
dfcc6e640d | ||
|
69ad317888 | ||
|
38d80dab96 | ||
|
a4c077db0b | ||
|
299f936f64 | ||
|
2b59a39c7a | ||
|
35a7f614e9 | ||
|
fac102b038 | ||
|
83d9980486 | ||
|
0d7b674e0f | ||
|
5bfa992290 | ||
|
6dd3f034cb | ||
|
ad73150bc4 | ||
|
6529b611a4 | ||
|
1bd0d7b964 | ||
|
a7efdbf6c5 | ||
|
d6b2dc7e20 | ||
|
90d281b483 | ||
|
4387390dbc | ||
|
dca8fb57ab | ||
|
4a599c513c | ||
|
490e91e391 | ||
|
cc45d3d009 | ||
|
2e35c1fa2c | ||
|
ce610b2d0a | ||
|
529f495f3d | ||
|
6d05cc6f48 | ||
|
452f60dc9b | ||
|
01b83cd0f8 | ||
|
8ba7682a6c | ||
|
6883e3fe64 | ||
|
280b21c6f8 | ||
|
8726c17034 | ||
|
2899195ef8 | ||
|
cf99a0f7aa | ||
|
f96e7377f8 | ||
|
e7ffeeefbd | ||
|
6d5caf8623 | ||
|
20732d5f8a | ||
|
29ef8f06f5 | ||
|
125378ec93 | ||
|
a94d0b4433 | ||
|
a3ef3e9cb2 | ||
|
c38766258a | ||
|
7d67818b52 | ||
|
550a9c6462 | ||
|
c16746c9b1 | ||
|
9780470f62 | ||
|
0c9aadd621 | ||
|
d46b5e43dd | ||
|
c8ec4a7c77 | ||
|
4188264298 | ||
|
42fd538ccb | ||
|
14331ebd5e | ||
|
a371a3770e | ||
|
f1d1413314 | ||
|
46762d13b2 | ||
|
91accd2c0d | ||
|
0f2bba19d2 | ||
|
4e3263b5fe | ||
|
e3e59db275 | ||
|
8bb1d9954c | ||
|
2a59d74b33 | ||
|
a0bb56e388 | ||
|
24e7c84824 | ||
|
fe8d473a76 | ||
|
a4ac385577 | ||
|
4c348e44f0 | ||
|
c63a870843 | ||
|
a28419225a | ||
|
43f2ccca4f | ||
|
c010f4f518 | ||
|
52a22f5717 | ||
|
e44575d0ae | ||
|
3ea30e9268 | ||
|
ef141d72bf | ||
|
249e173b3e | ||
|
f32dbfc52d | ||
|
ef3e9db7f5 | ||
|
457b536fca | ||
|
2762c7df82 | ||
|
eca6b4fb87 | ||
|
23a1e929a3 | ||
|
329f252d82 | ||
|
c6aee2862f | ||
|
cc61fce0eb | ||
|
d82fadfe03 | ||
|
8fc49e3218 | ||
|
cc4c73355e | ||
|
8cace16d0d | ||
|
a9be62287a | ||
|
c39654d99f | ||
|
3e115982f8 | ||
|
29fbe0a001 | ||
|
617364f578 | ||
|
16894d1d90 | ||
|
9579315407 | ||
|
ff4d03c18a | ||
|
9354863b1e | ||
|
0ed4582cf0 | ||
|
eeeb5c3db8 | ||
|
51827c015b | ||
|
9d312c5582 | ||
|
cf8796f45a | ||
|
8756ff4bd5 | ||
|
624dae23c1 | ||
|
ed8f77755e | ||
|
9d1618d2ea | ||
|
172d2f763b | ||
|
f4e890f8e7 | ||
|
663842d8d0 | ||
|
efbc893d53 | ||
|
048e59e497 | ||
|
7c6befaa20 | ||
|
7df3330bb5 | ||
|
4975fa74c4 | ||
|
83d614c4e2 | ||
|
0f42f03d4e | ||
|
fc5b7172eb | ||
|
363057d568 | ||
|
9227fe5e3c | ||
|
4ed4a4e0d9 | ||
|
fd333a1090 | ||
|
9c66bfcf9b | ||
|
db9bebe596 | ||
|
30f72054ec | ||
|
d7d000ff1d | ||
|
842da132e0 | ||
|
638f2a99d8 | ||
|
ba991a79b3 | ||
|
3b5a424c34 | ||
|
2e0d9dd20c | ||
|
e1a09676b4 | ||
|
0ac70c9f51 | ||
|
6b2c44c3fc | ||
|
c963a61389 | ||
|
b30f70a4c8 | ||
|
a700dcb1aa | ||
|
2d93f5c5f5 | ||
|
75ac83331c | ||
|
e19e6548ee | ||
|
5151f64beb | ||
|
508cd838df | ||
|
f6474295d4 | ||
|
4641fcf3d1 | ||
|
63452426be | ||
|
3e3d3492d2 | ||
|
5f3572c1a6 | ||
|
0389499595 | ||
|
749d5ebe55 | ||
|
165eeaecb5 | ||
|
caf767aaaa | ||
|
7273c41e30 | ||
|
4843b93366 | ||
|
a400b65654 | ||
|
29e460ffad | ||
|
3734697e90 | ||
|
6d94f626fd | ||
|
d99bcbe9b2 | ||
|
06c32689ef | ||
|
b0966d036e | ||
|
9d71c34f3a | ||
|
600426da61 | ||
|
80cb7a114d | ||
|
f50e2ab8c2 | ||
|
d74a6e620c | ||
|
a948f590fa | ||
|
1037717809 | ||
|
36360e19a3 | ||
|
53a0289b9b | ||
|
dd1d3f793f | ||
|
9ce6c8bd9d | ||
|
9c7d9443ce | ||
|
d1272cb3c6 | ||
|
b7a90902ab | ||
|
4c29d94246 | ||
|
0d68f00710 | ||
|
9c94e84d82 | ||
|
397fbe8c26 | ||
|
943a4dddf8 | ||
|
1cc2f5e225 | ||
|
1515579141 | ||
|
1c96e44623 | ||
|
69b00a4250 | ||
|
3b8879dac9 | ||
|
2a769406ff | ||
|
3266154989 | ||
|
f9d05aa803 | ||
|
40c35a0de7 | ||
|
43b7864b70 | ||
|
f92cad8f71 | ||
|
b886cc21cb | ||
|
5b927d2a8e | ||
|
c324081076 | ||
|
76793e7282 | ||
|
cae10ab155 | ||
|
e0d94517e0 | ||
|
d75ec190b5 | ||
|
098eca657f | ||
|
a358d8d4da | ||
|
77c930d737 | ||
|
c5f3c0ac4b | ||
|
5c42dece4f | ||
|
3a85ec44eb | ||
|
7e0574f277 | ||
|
81f55490d3 | ||
|
5f1e9a4412 | ||
|
c485dcab7a | ||
|
8e7db68253 | ||
|
95665f8bb8 | ||
|
8535381f36 | ||
|
497d5286cc | ||
|
2209b65940 | ||
|
bbc2303fbd | ||
|
50b4efd6bd | ||
|
24f8267ac8 | ||
|
ca963adbbd | ||
|
2553a659c5 | ||
|
5e5dce0b29 | ||
|
25b6007300 | ||
|
d9359a60e2 | ||
|
902d70a663 | ||
|
1475ff30fa | ||
|
5647416cbc | ||
|
a25523b638 | ||
|
3960e68365 | ||
|
1a1071992e | ||
|
7fabae02e9 | ||
|
93ca724f08 | ||
|
b0c05a5200 | ||
|
514e0e83b6 | ||
|
ab6cba3574 | ||
|
4b38d4c3d6 | ||
|
e1f4a6dc8c | ||
|
85423bbf2c | ||
|
54ef6d95dd | ||
|
2fca58ab52 | ||
|
b436b16608 | ||
|
a2195dc572 | ||
|
1934ef4ef0 | ||
|
5e77c51f51 | ||
|
8cf09137fb | ||
|
4c1d91195b | ||
|
60148ffc4e | ||
|
faeb330579 | ||
|
bd854b20c3 | ||
|
31e9853ca7 | ||
|
cbc5cd2c4f | ||
|
3d1914e847 | ||
|
ea4aca1bee | ||
|
5a354b4f06 | ||
|
3fd624844e | ||
|
1eda5a7055 | ||
|
ef1cdbdfc7 | ||
|
de61445249 | ||
|
bb6d41b106 | ||
|
fab314a7ee | ||
|
b77bdbd08a | ||
|
67d2155569 | ||
|
0d41800c0f | ||
|
0ade031772 | ||
|
d25ebe52be | ||
|
8d814afa73 | ||
|
73cd16b953 | ||
|
5542ba5193 | ||
|
46a5a6b128 | ||
|
70ebd16e65 | ||
|
29f7304aea | ||
|
322b202d22 | ||
|
e2731575ba | ||
|
5616b19bef | ||
|
3d941f2c90 | ||
|
65c1220d75 | ||
|
883120455b | ||
|
e893a9ff3c | ||
|
a7fc3e23e0 | ||
|
c584612549 | ||
|
1573fa7695 | ||
|
7c5aacd4be | ||
|
d43a0a97d1 | ||
|
7b741f0f74 | ||
|
f0a2d7767a | ||
|
f7799861e6 | ||
|
67bdd386e2 | ||
|
4bab683c2b | ||
|
5e748eb3f2 | ||
|
1312de02d8 | ||
|
a06e71f6dc | ||
|
a3a059167c | ||
|
52e1efdddf | ||
|
9dac796d91 | ||
|
92e7b57e6b | ||
|
72a44219e2 | ||
|
ad9b9c0b19 | ||
|
934e5bc6f9 | ||
|
4e7d005924 | ||
|
d3e3769b62 | ||
|
8c12494412 | ||
|
2db3fd21f0 | ||
|
dfc72060fd | ||
|
ed807249fe | ||
|
f101b0612a | ||
|
da8fadecc3 | ||
|
a559558f9d | ||
|
467f03f0ad | ||
|
be614eae29 | ||
|
906ed547a6 | ||
|
fe0e40cb99 | ||
|
3c45d77023 | ||
|
e1e625b361 | ||
|
6a8bed0240 | ||
|
345e0c69f9 | ||
|
77d5a024b4 | ||
|
c63882b49a | ||
|
0afb4363ca | ||
|
3c37807ee5 | ||
|
27719f772a | ||
|
d343cfde44 | ||
|
6a6233e362 | ||
|
da7aea6838 | ||
|
f7a05e4bf6 | ||
|
fd951381f8 | ||
|
f1645e0ab8 | ||
|
36b0b5bc9e | ||
|
80a3abef2c | ||
|
d20b406cfb | ||
|
010c2e98df | ||
|
647e0a8b5b | ||
|
73800eabaa | ||
|
791d7c08f8 | ||
|
7f41418bed | ||
|
3794fe96a1 | ||
|
2fb054cc57 | ||
|
efed2febae | ||
|
205f054f0b | ||
|
d3c3ce32bc | ||
|
b9e5c6fb3a | ||
|
6b62351cd7 | ||
|
1b2fd01535 | ||
|
9b4688c1e7 | ||
|
3c7e965d1f | ||
|
463f6b0180 | ||
|
e8ad6f019d | ||
|
b80eab0939 | ||
|
498fd7f4d6 | ||
|
844acd8c8a | ||
|
79318d0408 | ||
|
7fd1259a79 | ||
|
c19b1daa63 | ||
|
b7e8434556 | ||
|
3310b88aca | ||
|
f061d0edc9 | ||
|
77f28be18b | ||
|
52ad23b4f9 | ||
|
f9617a45ee | ||
|
69e5d127cd | ||
|
48d3edac4f | ||
|
349e859c08 | ||
|
6393425895 | ||
|
229ef395db | ||
|
e02c2fd52f | ||
|
3b501ce9cf | ||
|
905825b47a | ||
|
17471ed4e0 | ||
|
768cb64c30 | ||
|
579a47435b | ||
|
9c283ce0c3 | ||
|
b03dcaa5ac | ||
|
4900188ab9 | ||
|
d06794d5dc | ||
|
46708cbca1 | ||
|
2568479ad8 | ||
|
aee4952dfd | ||
|
9d4784db42 | ||
|
2e6ce91b9b | ||
|
bca9cbfe02 | ||
|
ae682377d3 | ||
|
ed83251e9a | ||
|
3356a5bd76 | ||
|
ea2085d584 | ||
|
bc0185729c | ||
|
30e0b0c425 | ||
|
8d79dc3491 | ||
|
9b141bda45 | ||
|
345dc0e169 | ||
|
a2c7e3e270 | ||
|
7ea47bd69c | ||
|
8afb95689c | ||
|
0e182ce5ab | ||
|
2d010b36f2 | ||
|
564089b598 | ||
|
ab619ab0be | ||
|
54a888f25e | ||
|
b79138e15e | ||
|
e5e0f2c471 | ||
|
a3d0f7ac71 | ||
|
6eb697e427 | ||
|
72d5f46353 | ||
|
77230ab03f | ||
|
7ddc7bc90a | ||
|
0b4ce70555 | ||
|
fc3b40eab4 | ||
|
7ae925e3dc | ||
|
c2f68a4716 | ||
|
514c1d31b7 | ||
|
2ba13c89b8 | ||
|
987d03845d | ||
|
2ea7a4ad77 | ||
|
c64ccde509 | ||
|
e20c5487ce | ||
|
73ecc66869 | ||
|
51582b90ca | ||
|
2b3c36e4d2 | ||
|
3174d01518 | ||
|
b44ef817e8 | ||
|
193843ae14 | ||
|
179f27270c | ||
|
638606c87a | ||
|
1106c74c9f | ||
|
9ba587177e | ||
|
dc8216217d | ||
|
75afa19e1b | ||
|
c2ca2718e6 | ||
|
8a7377bfba | ||
|
84c3cb72c0 | ||
|
179c1b5ca0 | ||
|
4e27765e12 | ||
|
04c8f207b1 | ||
|
630a63185a | ||
|
dadac0a5ee | ||
|
fb1dc88fec | ||
|
b176e47df1 | ||
|
56cf213e41 | ||
|
5f8c692324 | ||
|
21e7bfaa97 | ||
|
b77c4571d2 | ||
|
ae64c1075a | ||
|
de001c5685 | ||
|
3226e9f37f | ||
|
1e87818a41 | ||
|
f5aeb60236 | ||
|
12dc91c986 | ||
|
335dc84064 | ||
|
b7022af095 | ||
|
c0c3d22d77 | ||
|
44f861290c | ||
|
d825de7b6c | ||
|
96a8e2993f | ||
|
543c4911da | ||
|
bf9ba87c37 | ||
|
f1e5ae5367 | ||
|
4111ae6270 | ||
|
77d4fcbdd8 | ||
|
ca2b7dda60 | ||
|
d235f78689 | ||
|
3681670b36 | ||
|
64104f59f2 | ||
|
8edc2d7ced | ||
|
232e0312fc | ||
|
328fdeef71 | ||
|
eda235904e | ||
|
92a0e76625 | ||
|
213c922664 | ||
|
3b1bf1c777 | ||
|
6330400c63 | ||
|
e11fc3d101 | ||
|
ab8f5b5dca | ||
|
8b864fe9f9 | ||
|
869bff6a36 | ||
|
b27d3dfaae | ||
|
17985b3514 | ||
|
27136da82b | ||
|
c246020a79 | ||
|
067b4c56f9 | ||
|
c66f28027b | ||
|
599fd49fa6 | ||
|
5b440c8700 | ||
|
1d94e5015f | ||
|
2053074e0b | ||
|
779a864761 | ||
|
bb80657c93 | ||
|
8c58135cda | ||
|
44736d8979 | ||
|
f3926d2832 | ||
|
e726f446e4 | ||
|
cc29d14c07 | ||
|
c460cb0bed | ||
|
dba71ce796 | ||
|
ab75b904a4 | ||
|
62341aed8c | ||
|
5cfea185de | ||
|
d3b07ddb88 | ||
|
2c0f96ee05 | ||
|
4b7626ea91 | ||
|
06c42aa8d6 | ||
|
82967f0e1b | ||
|
1af1553fc6 | ||
|
2f94b27fc8 | ||
|
55a2dc887f | ||
|
cc9fa44052 | ||
|
2f2f0c10d5 | ||
|
f4902bfed7 | ||
|
1ec6fa2d96 | ||
|
c2d3fccff4 | ||
|
4892c0f798 | ||
|
f768d40fd6 | ||
|
a7c4f5cbf3 | ||
|
92c1acb8f4 | ||
|
adb688c6fe | ||
|
538fd38bbb | ||
|
6c4433b6a1 | ||
|
29851a51f1 | ||
|
9f86fe4c9a | ||
|
b1ac2afb2e | ||
|
79940a7393 | ||
|
a81ac29e00 | ||
|
c9ba833698 | ||
|
45b200aa4a | ||
|
e4c4af5e1f | ||
|
5b122b167b | ||
|
5d8ad82ad6 | ||
|
9d059aa01b | ||
|
58f20b59d7 | ||
|
e3da2f3dba | ||
|
5329511c70 | ||
|
339b06f221 | ||
|
ea7b997551 | ||
|
d8daa26b32 | ||
|
932b78650a | ||
|
9ad9672a12 | ||
|
6d200124fd | ||
|
f42f0745ea | ||
|
a137f5e962 | ||
|
21ca53c9b0 | ||
|
e09cbf2e80 | ||
|
50b54f93ed | ||
|
5c157189f7 | ||
|
64157f89f2 | ||
|
89c5b3e535 | ||
|
6cad85c285 | ||
|
fc7bfdd316 | ||
|
ee010b9dae | ||
|
215adf465d | ||
|
c80d42a571 | ||
|
8dac462e79 | ||
|
7422df69fa | ||
|
b1a411f8e7 | ||
|
cd3d1d114b | ||
|
2fdb566fe1 | ||
|
d1783de185 | ||
|
6353f3a330 | ||
|
00a0ba769d | ||
|
bc1fa8c53f | ||
|
03d7a2db8e | ||
|
80398eca7f | ||
|
78a602b208 | ||
|
eeacf5494d | ||
|
9666e482e8 | ||
|
d25a42f07d | ||
|
c16a5bfac1 | ||
|
797e670c44 | ||
|
6527d0c03a | ||
|
7e6cffd19a | ||
|
d5065cde88 | ||
|
5adf44aeff | ||
|
8fdf0b9d8f | ||
|
6de8c27ce0 | ||
|
23aa89069e | ||
|
bb48004701 | ||
|
111263ba91 | ||
|
aaf380ae21 | ||
|
4f4f94e858 | ||
|
72c4681512 | ||
|
70bc030cd2 | ||
|
f0b82ce262 | ||
|
9e618dc123 | ||
|
031df8993d | ||
|
f8a3a365b6 | ||
|
bfb93cddd1 | ||
|
375a98e957 | ||
|
90a84b7084 | ||
|
0ed05e545f | ||
|
01b5f3458a | ||
|
0c65fc56bb | ||
|
dc55de352b | ||
|
1496712bcf | ||
|
d8eb134eba | ||
|
8c4ebad69a | ||
|
2615198d7a | ||
|
d25d319802 | ||
|
b015d2894f | ||
|
b443b22456 | ||
|
5816b3da36 | ||
|
1ff39b7f1d | ||
|
7b654184c1 | ||
|
cfff2132c5 | ||
|
73b612365f | ||
|
0caaa2c10e | ||
|
21aecaf825 | ||
|
257f836d4f | ||
|
72c727e773 | ||
|
d7ea320daa | ||
|
cedf04e68c | ||
|
e8c630c21a | ||
|
446734949b | ||
|
5f3d285452 | ||
|
49ced158a2 | ||
|
321115bdc1 | ||
|
977a6f2a08 | ||
|
91f998a602 | ||
|
7863ef5c8f | ||
|
5acfbdf787 | ||
|
99ecba2112 | ||
|
6894c73f21 | ||
|
b9571c6ed7 | ||
|
7614f7b1b0 | ||
|
2bf6880060 | ||
|
41c0e7e77e | ||
|
589fe23b5c | ||
|
88b2948057 | ||
|
e5a128bdb5 | ||
|
2562138de5 | ||
|
516946a608 | ||
|
a429a0c1c3 | ||
|
559157ecc6 | ||
|
d870722c3a | ||
|
88ff8c6449 | ||
|
a1b19d0032 | ||
|
3ca659b276 | ||
|
566f352317 | ||
|
d48c6f776c | ||
|
2229a11db7 | ||
|
a15f1ce1c8 | ||
|
74cb38d69c | ||
|
4e7aa22cd2 | ||
|
02f319eeda | ||
|
7e0a48d150 | ||
|
c8040983a6 | ||
|
b3595f144c | ||
|
c7a7ded396 | ||
|
cfc044a9f3 | ||
|
b6839bc0ac | ||
|
91ddf5a0f3 | ||
|
eabac93f1f | ||
|
daefeaf3a9 | ||
|
1392b371f6 | ||
|
b26a6fb09d | ||
|
0f683c6061 | ||
|
ba05ecd74a | ||
|
e5ab71be0a | ||
|
8797c166c6 | ||
|
4c399ecfe8 | ||
|
1dc451604b | ||
|
a040c6aac0 | ||
|
27beca355a | ||
|
c4e5a257d6 | ||
|
64f581ab7d | ||
|
bf1de5ae3c | ||
|
66e46bec66 | ||
|
1d93f10602 | ||
|
f6b607248c | ||
|
7bba87fed9 | ||
|
f770c0d9e2 | ||
|
83801a175c | ||
|
2e57893e08 | ||
|
ba1f8e6b3d | ||
|
c1f6f60c06 | ||
|
f181aa9954 | ||
|
f9e616aec1 | ||
|
1ba2d9dec6 | ||
|
c27d02d3c9 | ||
|
2769cc848d | ||
|
2283822c1f | ||
|
cd11cf45f5 | ||
|
0d836021a5 | ||
|
c9ce1678d0 | ||
|
63ce6b3fba | ||
|
36afbfcdc0 | ||
|
bdcc2dceb6 | ||
|
f79cd70b4a | ||
|
8c7efe9aa8 | ||
|
e602d4df4c | ||
|
1eb7895d63 | ||
|
29ef1d5e68 | ||
|
575e5f03a1 | ||
|
61ae279f6d | ||
|
71057a387a | ||
|
7d1b94f515 | ||
|
953f9f06de | ||
|
a49b3d0ef1 | ||
|
59b643fe63 | ||
|
0ef87983f3 | ||
|
d548ef117a | ||
|
d550401eba | ||
|
77851208d9 | ||
|
e5b7dd441d | ||
|
01f25d28e2 | ||
|
8abcb9f823 | ||
|
61d9184d81 | ||
|
be0e7cd729 | ||
|
2564bad609 | ||
|
70714be2ff | ||
|
6df8a83677 | ||
|
26827bc531 | ||
|
9cfa9a4e3a | ||
|
6bde927945 | ||
|
d4ce3526b9 | ||
|
6db5707da8 | ||
|
a720fe2611 | ||
|
ec5fd877da | ||
|
8a746b3661 | ||
|
108e0d3fbf | ||
|
1e39da2b65 | ||
|
af371a97e8 | ||
|
6df2f5c998 | ||
|
c0a6832074 | ||
|
ebd1daeea4 | ||
|
8e1afc98ff | ||
|
5827e7a916 | ||
|
cd041c4ee8 | ||
|
09f355f57e | ||
|
b0e43ed737 | ||
|
f66f230565 | ||
|
ee6b176784 | ||
|
8bc15e54f3 | ||
|
12b8bf2ca5 | ||
|
0d15efd316 | ||
|
01c71be0be | ||
|
26063d9b4b | ||
|
7b67951714 | ||
|
61e22d4831 | ||
|
9b9353adbb | ||
|
6be6a39a1a | ||
|
eff8baf506 | ||
|
87e9cdf546 | ||
|
88bf29bfb6 | ||
|
c556552bf0 | ||
|
d02fd09b6c | ||
|
91007c9515 | ||
|
b2284caae4 | ||
|
92542e8085 | ||
|
b41d28b0c8 | ||
|
2aa012479c | ||
|
8f8221c9e0 | ||
|
1a5428c671 | ||
|
851c8689f5 | ||
|
37588f7739 | ||
|
c9b55d87d5 | ||
|
84c35abdbe | ||
|
123b3c4c2f | ||
|
90946cf9f1 | ||
|
72c2ac151c | ||
|
c69230c97a | ||
|
1032877b50 | ||
|
e5a0fa0066 | ||
|
d42cc357fd | ||
|
ca1e2ba5cb | ||
|
4e5f2e015c | ||
|
966c2e5172 | ||
|
f766080bba | ||
|
3b3c6b5cdd | ||
|
e9b5fd9dca | ||
|
a3735b6223 | ||
|
ae4a7b0df0 | ||
|
464460c8cf | ||
|
e6ce520ea0 | ||
|
505db421ba | ||
|
b46a49eb01 | ||
|
89ba90e741 | ||
|
050d646a50 | ||
|
6c283cebad | ||
|
de791a977a | ||
|
d5f15d97a9 | ||
|
7cc1f3bfef | ||
|
c22ef52521 | ||
|
2be54777ff | ||
|
bf9709a4f2 | ||
|
5938c769db | ||
|
88c97e9bb1 | ||
|
fde0a2d0a1 | ||
|
3bb3f992ae | ||
|
5c24951ac5 | ||
|
054244a2f6 | ||
|
c645dbe79c | ||
|
2641659d91 | ||
|
88e3ccbd4c | ||
|
c6af3cfef9 | ||
|
17051b35d1 | ||
|
7caa81450c | ||
|
3e17e26028 | ||
|
c6a9fa9f28 | ||
|
09d9ae219c | ||
|
35e8542d6e | ||
|
64fd367086 | ||
|
8e691e1231 | ||
|
5c752c993e | ||
|
810772d623 | ||
|
7fd49fd33d | ||
|
5cd2d71ea3 | ||
|
a06218bdaf | ||
|
e679ebf1a3 | ||
|
260b9e13f0 | ||
|
50aeb22034 | ||
|
06fbc269d2 | ||
|
912d0e9bef | ||
|
7183d0158f | ||
|
f19094ba48 | ||
|
5b19187df4 | ||
|
7208d38448 | ||
|
a42edcbb02 | ||
|
679ba8b517 | ||
|
7eb5f82c67 | ||
|
a66f710c75 | ||
|
d808c316d1 | ||
|
04b1d8ebcc | ||
|
e6b367b1d8 | ||
|
b620d710e8 | ||
|
ff060094e0 | ||
|
6a55c99291 | ||
|
0eacd56612 | ||
|
f70d77a25e | ||
|
591f74543a | ||
|
867ce6569c | ||
|
0c23b2024c | ||
|
0a42877ecf | ||
|
27a3bdd085 | ||
|
89c4c7b3aa | ||
|
fe5302be14 | ||
|
432ded6bf6 | ||
|
b3f58afb33 | ||
|
5c4bdddb21 | ||
|
e87c5c492a | ||
|
e87172682c | ||
|
6144253853 | ||
|
5419b3fa51 | ||
|
1b83c4bb5e | ||
|
c307b5ad93 | ||
|
4b1a477320 | ||
|
6bb842c6a5 | ||
|
0ec33ae02c | ||
|
ad4397351c | ||
|
37e2526dd7 | ||
|
d98e0c67da | ||
|
59c79f71cd | ||
|
623355c555 | ||
|
ab26ff2cec | ||
|
933fd1be52 | ||
|
f51c04b355 | ||
|
ec2be096ec | ||
|
0c1273e69a | ||
|
9d05780472 | ||
|
8122fcb281 | ||
|
4c95df54ab | ||
|
8553d91f46 | ||
|
961a1d65b3 | ||
|
b7c561f461 | ||
|
f0f161d50f | ||
|
39cf6dc24b | ||
|
ea7e7c51e4 | ||
|
e83b5f0db3 | ||
|
1bcb142d1f | ||
|
a004ec2396 | ||
|
adf2de3ee9 | ||
|
afb66956a0 | ||
|
66afc9e661 | ||
|
791a7e649d | ||
|
7a02b8524d | ||
|
26e219af00 | ||
|
7f2f2a4b56 | ||
|
ceac534fb7 | ||
|
a44cbc5fbf | ||
|
524226bd3b | ||
|
98153c269f | ||
|
19f42ab108 | ||
|
4a9a63c3a9 | ||
|
31b1561750 | ||
|
72a37677c1 | ||
|
4959a3ea6c | ||
|
f4a706efae | ||
|
65ac9e291b | ||
|
15cc04f073 | ||
|
6115565520 | ||
|
e982814ab7 | ||
|
37f69c3fcb | ||
|
b9039fe685 | ||
|
00aa34d3cd | ||
|
f2c01e7e9f | ||
|
4504eb8662 | ||
|
2c95ca6de0 | ||
|
69b1dd2bbf | ||
|
63015b3b6f | ||
|
83e5b100f1 | ||
|
0f99ffbbae | ||
|
06927b1d13 | ||
|
0a85fbaea4 | ||
|
8dc8577244 | ||
|
1b5abd975d | ||
|
432b35b364 | ||
|
fe24f2208b | ||
|
c26436efc7 | ||
|
1596b0d0ef | ||
|
49f367424b | ||
|
b9bc756ab2 | ||
|
014e252d0d | ||
|
130895b5d9 | ||
|
981ccee71c | ||
|
00d8550371 | ||
|
aa724d146c | ||
|
72240c810d | ||
|
d26f8a38ba | ||
|
7a9afc6301 | ||
|
5e0ffe2678 | ||
|
7dc5f7242a | ||
|
37769a276f | ||
|
ff33e8f6ab | ||
|
5781f31d70 | ||
|
1203f9a141 | ||
|
eeee33879a | ||
|
b950b54ebc | ||
|
2696720745 | ||
|
dcde62917b | ||
|
78722d949a | ||
|
8bd34f7b44 | ||
|
3e0525d2fe | ||
|
57dd3ea049 | ||
|
14af494557 | ||
|
b92c42144c | ||
|
919bb80018 | ||
|
b144c5a513 | ||
|
2886fd46b2 | ||
|
da2ee4bec7 | ||
|
359961669f | ||
|
e546f91ca5 | ||
|
7f28f87dda | ||
|
66891e6389 | ||
|
af0d235d4a | ||
|
ae023db6bb | ||
|
fc381a78d3 | ||
|
c6306de2e7 | ||
|
fbdfcbfcb2 | ||
|
633d5879fa | ||
|
af449819b1 | ||
|
91f0da64c0 | ||
|
b2c0f117fe | ||
|
8e2e59d305 | ||
|
9b3595e40a | ||
|
5ad581bf3e | ||
|
d075fc14c2 | ||
|
09c7f07062 | ||
|
b032ae05d8 | ||
|
64934c608d | ||
|
4aba077397 | ||
|
3df45ed42e | ||
|
c459f0a774 | ||
|
8235622c80 | ||
|
65c85a22cd | ||
|
7cbeb69bbe | ||
|
1c5ec9eaae | ||
|
90904c3418 | ||
|
5f46e8c48f | ||
|
326e124f0a | ||
|
52b15ba0d8 | ||
|
145f1649cb | ||
|
2f4e5c0d18 | ||
|
a17d2f9feb | ||
|
8beca81ae4 | ||
|
818d600dc8 | ||
|
0190e4bb6f | ||
|
6b036d56a1 | ||
|
0240b342c7 | ||
|
4523fa5837 | ||
|
36ccffe074 | ||
|
20463e8728 | ||
|
ad47125c11 | ||
|
bd65a07b4d | ||
|
88350111a3 | ||
|
f03c7baaa8 | ||
|
da00cc651e | ||
|
16b911d489 | ||
|
8d713b34e4 | ||
|
f5a3aae819 | ||
|
d5be2e866c | ||
|
3a4c4c2b9a | ||
|
5bd619f95a | ||
|
5e16985b31 | ||
|
2c300934ca | ||
|
11e2eb9149 | ||
|
8bfd08ffe1 | ||
|
c8302f7203 | ||
|
ef481fc2de | ||
|
b3d1f187c9 | ||
|
a004b2edc7 | ||
|
4369679db4 | ||
|
308d43a94e | ||
|
68ac511781 | ||
|
41681855fa | ||
|
757c15fc48 | ||
|
19e1ae786a | ||
|
34756ea08f | ||
|
f488259ab7 | ||
|
318778bb54 | ||
|
b5fb1a6a91 | ||
|
7fc1693735 | ||
|
417deac31b | ||
|
ed0ab2f7ec | ||
|
2d81499f67 | ||
|
deee0e4951 | ||
|
08cd773f8b | ||
|
9a4fdf74de | ||
|
62916a38a4 | ||
|
7bffd95812 | ||
|
b9c4dfe001 | ||
|
fb3e467fd6 | ||
|
3040166318 | ||
|
8de6e2af0a | ||
|
8becd89e18 | ||
|
23e122f0f2 | ||
|
14d8d6749c | ||
|
82fe47c6ce | ||
|
5ad1204b3b | ||
|
1110b8ae54 | ||
|
f886bff812 | ||
|
46c67d84c1 | ||
|
e506450c7e | ||
|
1a01099142 | ||
|
0f83ffec8d | ||
|
6752cbc9f1 | ||
|
6b05cd1b90 | ||
|
76248deccf | ||
|
0e048a3866 | ||
|
9e51975995 | ||
|
a197c77134 | ||
|
4ded870086 | ||
|
a1f9cfc0a5 | ||
|
f4bd97bfa8 | ||
|
df149efed3 | ||
|
f0733fb532 | ||
|
e7c13029ce | ||
|
aab250c719 | ||
|
7f8fa07923 | ||
|
61758796f9 | ||
|
47bdbdaead | ||
|
32fa56a580 | ||
|
dfd991cc05 | ||
|
531a074839 | ||
|
fdd09c0f65 | ||
|
2120ee51f8 | ||
|
f22e6715a1 | ||
|
420121f5e1 | ||
|
42e5f393a7 | ||
|
56bffbcf36 | ||
|
5c94a30683 | ||
|
4538c3dec5 | ||
|
928a77ec7c | ||
|
515a90477f | ||
|
835b880cf8 | ||
|
6491aad51c | ||
|
ad8a515d16 | ||
|
dc7d5437ac | ||
|
30cd5bfac1 | ||
|
7ef88ac393 | ||
|
21d72536c9 | ||
|
71fa49c3df | ||
|
cd6a59b3fb | ||
|
94b240a755 | ||
|
fec53c0b38 | ||
|
2ba9a1450b | ||
|
c9f9de73c9 | ||
|
d1a01109bf | ||
|
fa93c10be8 | ||
|
9475bd989e | ||
|
471cc0d8eb | ||
|
b6051bda0d | ||
|
75e26c4369 | ||
|
4f17300d82 | ||
|
90061d42ca | ||
|
3c9860e1f7 | ||
|
6aa8456cce | ||
|
389d35af61 | ||
|
aa98f00262 | ||
|
ff463c520e | ||
|
122517bcd6 | ||
|
5d57ac4332 | ||
|
2a10893ac6 | ||
|
3d05a5928b | ||
|
f9825f1d11 | ||
|
7c1bce467f | ||
|
0a130fdcc3 | ||
|
f0a7765d05 | ||
|
0868fe52f2 | ||
|
5113cea733 | ||
|
bdf028e343 | ||
|
f79c46c200 | ||
|
0c1aa520ac | ||
|
4ca88cabe4 | ||
|
107e0a4741 | ||
|
5b6ff9a485 | ||
|
72c65e8cf2 | ||
|
c9461c6857 | ||
|
bd62b58c59 | ||
|
cffdb529ef | ||
|
3908d592fe | ||
|
17b0109ab8 | ||
|
6882e4bf89 | ||
|
dcfb429b93 | ||
|
1f1657e6c8 | ||
|
9d85c980a2 | ||
|
1e7bf74527 | ||
|
37e7eaf3ad | ||
|
053586947f | ||
|
adb8406b8e | ||
|
37a2320bb9 | ||
|
326d8afef0 | ||
|
045ac268d4 | ||
|
ee3b0dc8b1 | ||
|
f05922b090 | ||
|
6ffabd6468 | ||
|
60093046fa | ||
|
6f9924b2d7 | ||
|
15c9ac7e5d | ||
|
bc66591ccf | ||
|
9a2b62bb5b | ||
|
d4fb3bf48d | ||
|
f63178c29b | ||
|
69ed7060ed | ||
|
a3e17dfb83 | ||
|
2586da1d53 | ||
|
b5edd4ead9 | ||
|
bcf4b028da | ||
|
f9abf2f5da | ||
|
104561c8f7 | ||
|
05ac12b011 | ||
|
e8f0b25a5f | ||
|
7d3a84b3b2 | ||
|
210590b0cd | ||
|
2be1cdac5c | ||
|
9e25104b0e | ||
|
2358ab291e | ||
|
528153e13c | ||
|
7251101625 | ||
|
c7fdb3e997 | ||
|
f8668168dd | ||
|
c5825f7c0a | ||
|
5688d78bb4 | ||
|
130ad549dd | ||
|
783bf103eb | ||
|
afc8655e22 | ||
|
19368fc680 | ||
|
b1aa2df3d7 | ||
|
c164d819e9 | ||
|
ef04457b2d | ||
|
af97ef8f2d | ||
|
59fde383f0 | ||
|
50026f9092 | ||
|
f3dd28c1a9 | ||
|
cca61d7b8a | ||
|
ba2151cc24 | ||
|
face9279ee | ||
|
308992e8ce | ||
|
9a66fe707d | ||
|
3e867ad22d | ||
|
21bb21c751 | ||
|
f2e217c7f7 | ||
|
24c8c7ac7e | ||
|
0c68f36088 | ||
|
5d144c0058 | ||
|
02b5dd4848 | ||
|
3c9dda8f4d | ||
|
ae84756293 | ||
|
5c8ec1e41a | ||
|
94ea697b98 | ||
|
867c1af1b1 | ||
|
15d6243747 | ||
|
7e3eb1bc00 | ||
|
0915c3a2ea | ||
|
edf988a636 | ||
|
609fc0009e | ||
|
682b5f72ba | ||
|
7e56f15d83 | ||
|
a906b4e8d5 | ||
|
6b928642d3 | ||
|
47ccac17bc | ||
|
c4706113fc | ||
|
c7d8446615 | ||
|
4f9308ff3a | ||
|
73488251de | ||
|
692401b418 | ||
|
b88b2debd0 | ||
|
cb626278b1 | ||
|
9f3c2eec0c | ||
|
8bec4b2662 | ||
|
d7c240591e | ||
|
56081acd72 | ||
|
d829b4a3fb | ||
|
5038d40883 | ||
|
e88bdddbe9 | ||
|
1327b572ac | ||
|
725adb59d8 | ||
|
970deacd61 | ||
|
ef09d21284 | ||
|
a07b8ce2b8 | ||
|
dd7fd35215 | ||
|
0475d4b876 | ||
|
025fe6d8ee | ||
|
5d5ce25c1f | ||
|
9edc7280a4 | ||
|
46c3a58e8a | ||
|
11ea690f7f | ||
|
10ba4df582 | ||
|
1b3f54e49b | ||
|
640dafd9da | ||
|
2cc021ecad | ||
|
2bd8a196c9 | ||
|
4ceec4c378 | ||
|
f0d9534dbc | ||
|
8656c7a6a1 | ||
|
c16741f259 | ||
|
4bca49ec0b | ||
|
5fd6434bea | ||
|
0361e1f1a8 | ||
|
f2466b6f24 | ||
|
1a92430fd3 | ||
|
c8fc72613e | ||
|
b832fc5c6a | ||
|
9b5196e9ae | ||
|
1320026657 | ||
|
f6ed335b6c | ||
|
2cad57b459 | ||
|
16b847e0cc | ||
|
0c13bed3df | ||
|
74ff0c3772 | ||
|
bc268b9573 | ||
|
95e1903f42 | ||
|
a62e9f1c67 | ||
|
133f4fe7ee | ||
|
d2c14fc232 | ||
|
b351d20476 | ||
|
f3865f5a50 | ||
|
40933f3121 | ||
|
0696046446 | ||
|
1fcdb835bc | ||
|
495c6eff5e | ||
|
a56244937b | ||
|
dcd8edbede | ||
|
33c414e548 | ||
|
421d09a3f5 | ||
|
230be5ddd2 | ||
|
81c99763ca | ||
|
6b13d53b8e | ||
|
63ae54e200 | ||
|
ddc20e40ca | ||
|
35aeb2afdb | ||
|
ff7edd9b2d | ||
|
285d830ca3 |
35
.gitignore
vendored
35
.gitignore
vendored
@ -1,26 +1,13 @@
|
||||
# Fichiers temporaires
|
||||
site/tmp/*.zip
|
||||
site/tmp/*.gz
|
||||
|
||||
# Sauvegardes
|
||||
core/class/phpmailer/.DS_Store
|
||||
site/.DS_Store
|
||||
site/data/*
|
||||
site/tmp/*
|
||||
site/backup/*
|
||||
|
||||
# Fichiers de données
|
||||
site/data/*.json
|
||||
site/data/*.css
|
||||
|
||||
|
||||
# Fichiers uploadés
|
||||
site/file/source/*
|
||||
site/file/thumb/*
|
||||
|
||||
# Dossiers vides dans GitHub
|
||||
!.gitkeep
|
||||
/.git
|
||||
|
||||
# PHPStorm
|
||||
.idea/
|
||||
|
||||
# Trucs
|
||||
.gitignore
|
||||
site/file/*
|
||||
site/i18n/*.json
|
||||
.DS_Store
|
||||
core/vendor/tinymce/link_list.json
|
||||
robots.txt
|
||||
sitemap.xml
|
||||
.gitignore
|
||||
core/module/config/tool/data.key
|
45
.htaccess
45
.htaccess
@ -1,8 +1,47 @@
|
||||
# Cache le PHPSESSID de l'url
|
||||
SetEnv SESSION_USE_TRANS_SID 0
|
||||
# Active la compression GZIP - option Apache
|
||||
<IfModule mod_gzip.c>
|
||||
mod_gzip_on Yes
|
||||
mod_gzip_dechunk Yes
|
||||
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
|
||||
mod_gzip_item_include handler ^cgi-script$
|
||||
mod_gzip_item_include mime ^text\.*
|
||||
mod_gzip_item_include mime ^application/x-javascript.*
|
||||
mod_gzip_item_exclude mime ^image\.*
|
||||
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
|
||||
</IfModule>
|
||||
|
||||
# Active la compression DEFLATE - option Apache
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/shtml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
</IfModule>
|
||||
|
||||
# Bloque l'accès à la liste des fichiers
|
||||
Options -Indexes
|
||||
|
||||
# Attention, surtout ne rien modifier ci-dessous !
|
||||
# Désactive l'option de substitution automatique
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews
|
||||
</IfModule>
|
||||
|
||||
# Enlever le slash final des URL
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} ^(.+)/$
|
||||
RewriteRule ^ %1 [R=301,L]
|
||||
|
||||
# ne pas supprimer la ligne URL rewriting !
|
||||
# URL rewriting
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1794
CHANGES.md
Normal file → Executable file
1794
CHANGES.md
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
675
LICENSE
675
LICENSE
@ -1,674 +1 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
Cette œuvre est mise à disposition sous licence Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International. Pour voir une copie de cette licence, visitez http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
110
LISEZMOI.md
Normal file
110
LISEZMOI.md
Normal file
@ -0,0 +1,110 @@
|
||||
# ZwiiCMS 13.5.00
|
||||
|
||||
Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.
|
||||
|
||||
ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/). Il est désormais maintenu par Frédéric Tempez.
|
||||
|
||||
[Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Version initiale](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)
|
||||
|
||||
## Configuration recommandée
|
||||
|
||||
* PHP 7.2 ou plus
|
||||
* Support de .htaccess
|
||||
|
||||
## Licence
|
||||
|
||||
Cette œuvre est mise à disposition sous licence Attribution - Pas d'utilisation Commerciale - Pas de Modification 4.0 International.
|
||||
|
||||
Pour voir une copie de cette licence, visitez <http://creativecommons.org/licenses/by-nc-nd/4.0/> ou écrivez à Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||
|
||||
## Téléchargement de ZwiiCMS
|
||||
|
||||
Pour télécharger la dernière version publiée, rendez-vous :
|
||||
* sur [la page des mises à jour](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases)
|
||||
* ou sur [la page de téléchargement du site](https://zwiicms.fr/telechargement)
|
||||
|
||||
## Installation
|
||||
|
||||
Décompressez l'archive de Zwii et téléversez son contenu à la racine de votre serveur ou dans un sous-répertoire. C'est tout !
|
||||
|
||||
Vous trouverez de plus amples explications, en particulier pour une installation chez Free, dans la rubrique "Téléchargements" du forum.
|
||||
|
||||
## Procédures de mise à jour
|
||||
|
||||
A l'occasion de l'installation d'une verion majeure, il est recommandé de réaliser une copie de sauvegarde.
|
||||
|
||||
### Automatique
|
||||
|
||||
* Connectez-vous à votre site.
|
||||
* Si une mise à jour est disponible, elle vous est proposée dans la barre d'administration.
|
||||
* Cliquez sur le bouton "Mettre à jour".
|
||||
|
||||
### Manuelle
|
||||
|
||||
* Sauvegardez l'intégralité de votre site, spécialement le répertoire "site".
|
||||
* Décompressez la nouvelle version sur votre ordinateur.
|
||||
* Transférez son contenu sur votre serveur en activant le remplacement des fichiers.
|
||||
|
||||
## Arborescence générale
|
||||
|
||||
*Légende : [R] Répertoire - [F] Fichier*
|
||||
|
||||
```text
|
||||
[R] core Cœur du système
|
||||
[R] class Classes
|
||||
[R] layout Mise en page
|
||||
[R] module Modules du cœur
|
||||
[R] vendor Librairies extérieures
|
||||
[F] core.js.php Cœur javascript
|
||||
[F] core.php Cœur PHP
|
||||
|
||||
[R] module Modules de page
|
||||
[R] blog Blog
|
||||
[R] form Gestionnaire de formulaires
|
||||
[R] gallery Galerie
|
||||
[R] news Nouvelles
|
||||
[R] redirection Redirection
|
||||
|
||||
[R] site Contenu du site
|
||||
[R] backup Sauvegardes automatiques
|
||||
[R] i18N Langues de l'interface de Zwii
|
||||
[R] data Répertoire des données
|
||||
[R] fr Dossier localisé
|
||||
[F] page.json Données des pages
|
||||
[F] module.json Données des modules de pages
|
||||
[F] local.json Données du site propres à la langue
|
||||
[F] .default Indicateur de la langue de site par défaut
|
||||
[R] content Dossier des contenus de page
|
||||
[F] accueil.html Exemple contenu de la page d'accueil
|
||||
[R] font Dossier contenant les fontes installées
|
||||
[F] font.html Fichier contenant les appels des fontes à charger sur cdnFonts
|
||||
[F] font.css Fichier contenant la feuille de style liée aux polices de caractères locales
|
||||
[F] fontes.woff Fichiers locaux des fontes (woff, etc..)
|
||||
[R] modules Personnalisation des modules ou données propres
|
||||
[F] admin.css Thème des pages d'administration
|
||||
[F] admin.json Données de thème des pages d'administration
|
||||
[F] blacklist.json Journalisation des tentatives de connexion avec des comptes inconnus
|
||||
[F] config.json Configuration du site
|
||||
[F] core.json Configuration du noyau
|
||||
[F] custom.css Feuille de style de la personnalisation avancée
|
||||
[F] font.json Descripteur des fontes personnalisées
|
||||
[F] journal.log Journalisation des activités
|
||||
[F] language.json Langues de l'interface
|
||||
[F] profil.json Profils des utilisateurs
|
||||
[F] theme.css Thème du site
|
||||
[F] theme.json Données du site
|
||||
[F] user.json Données des utilisateurs
|
||||
[F] .backup Marqueur de la sauvegarde des fichiers si présent
|
||||
[R] file Répertoire d'upload du gestionnaire de fichiers
|
||||
[R] source Ressources diverses
|
||||
[R] thumb Miniatures des images
|
||||
[R] tmp Répertoire temporaire
|
||||
|
||||
[F] index.php Fichier d'initialisation de ZwiiCMS
|
||||
[F] robots.txt Filtrage des répertoires accessibles aux robots des moteurs de recherche
|
||||
[F] sitemap.xml Plan du site
|
||||
[F] sitemap.xml.gz Version compressée
|
||||
|
||||
Le fichiers .htaccess contribuent à la sécurité en filtrant l'accès aux répertoires sensibles.
|
||||
|
||||
```
|
135
README.md
135
README.md
@ -1,72 +1,109 @@
|
||||
# Zwii 9.1
|
||||
# ZwiiCMS 13.5.00
|
||||
|
||||
Zwii est un CMS sans base de données (Flat-File) qui permet à ses utilisateurs de créer et gérer facilement un site web sans aucune connaissance en programmation.
|
||||
Zwii is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge.
|
||||
|
||||
[Site](http://zwiicms.com/) - [Forum](http://forum.zwiicms.com/) - [GitHub version initiale](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)
|
||||
ZwiiCMS was created by a talented developer, [Rémi Jean](https://remijean.fr/). It is now maintained by Frédéric Tempez.
|
||||
|
||||
Zwii a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/), il est désormais maintenu par la communauté et hébergé sur ce git.
|
||||
[Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Initial version](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)
|
||||
|
||||
## Recommended configuration
|
||||
|
||||
## Configuration recommandée
|
||||
* PHP 7.2 or higher
|
||||
* .htaccess support
|
||||
|
||||
* PHP 5.6 ou plus
|
||||
* Support du .htaccess
|
||||
## License
|
||||
|
||||
This work is licensed under the Attribution-Noncommercial-No Derivative Works 4.0 International License.
|
||||
|
||||
To view a copy of this license, visit <http://creativecommons.org/licenses/by-nc-nd/4.0/> or write to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||
|
||||
## Downloading ZwiiCMS
|
||||
|
||||
To download the latest released version, go to :
|
||||
* [the Updates page](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases)
|
||||
* or at [the site download page](https://zwiicms.fr/download)
|
||||
|
||||
## Installation
|
||||
|
||||
Décompressez l'archive de Zwii sur votre serveur et c'est tout !
|
||||
Unzip the Zwii archive and upload its contents to the root of your server or to a subdirectory. That's all!
|
||||
|
||||
You will find more explanations, in particular for an installation at Free, in the "Downloads" section of the forum.
|
||||
|
||||
## Procédure de mise à jour de Zwii
|
||||
## Update procedures
|
||||
|
||||
### Mise à jour automatique
|
||||
When installing a major version, it is recommended to make a backup copy.
|
||||
|
||||
* Connectez vous à votre site,
|
||||
* Allez dans l'interface d'administration,
|
||||
* Si une mise à jour est disponible, elle vous est proposée,
|
||||
* Cliquez sur le bouton "Mettre à jour".
|
||||
### Automatic
|
||||
|
||||
### Mise à jour manuelle
|
||||
* Connect to your site.
|
||||
* If an update is available, it is proposed in the administration bar.
|
||||
* Click on the "Update" button.
|
||||
|
||||
**Note : La réécriture d'URL est automatiquement désactivée après une mise à jour manuelle. À vous de la réactiver depuis l'interface de configuration du site.**
|
||||
### Manual
|
||||
|
||||
* Sauvegardez l'intégralité du dossier ZwiiCMS de votre serveur et notamment le dossier 'site',
|
||||
* Décompressez la nouvelle version sur votre ordinateur dans un autre dossier,
|
||||
* Supprimez le dossier 'site' de la version décompressée
|
||||
* Transférez la nouvelle version sans le dossier 'site'
|
||||
* Save your entire site, especially the "site" directory.
|
||||
* Unzip the new version on your computer.
|
||||
* Transfer its content to your server by activating the file replacement.
|
||||
|
||||
En cas de difficulté avec la nouvelle version, il suffira de téléverser la sauvegarde originale.
|
||||
## General tree structure
|
||||
|
||||
### Mise à jour de la version 8 vers la version 9
|
||||
*Legend: [D] Directory - [FILE] File
|
||||
|
||||
Les données du site dans 'site/data' sont désormais stockées dans deux fichiers : core.json et theme.json
|
||||
````
|
||||
text
|
||||
[DIR] core Core of the system
|
||||
[DIR] class Classes
|
||||
[DIR] layout Layout
|
||||
[DIR] module Core modules
|
||||
[DIR] vendor External libraries
|
||||
[FILE] core.js.php Javascript core
|
||||
[FILE] core.php PHP core
|
||||
|
||||
Après la copie des fichiers ces deux fichiers sont créés à partir du data.json de la version 8, ce fichier est ensuite renommée en data_imported.json
|
||||
[DIR] module Page modules
|
||||
[DIR] blog Blog
|
||||
[DIR] form Form manager
|
||||
[DIR] gallery Gallery
|
||||
[DIR] news News
|
||||
[DIR] redirection Redirection
|
||||
|
||||
En cas de retour à une version 8, ce fichier devra être renommé en data.json
|
||||
[DIR] site Site content
|
||||
[DIR] backup Automatic backups
|
||||
[DIR] i18N Zwii Interface languages
|
||||
[DIR] data Data directory
|
||||
[DIR] en Localized folder
|
||||
[FILE] page.json Page data
|
||||
[FILE] module.json Page module data
|
||||
[FILE] local.json Language-specific site data
|
||||
[FILE] .default Unique file of default site language
|
||||
[DIR] content Folder of page contents
|
||||
[FILE] home.html Sample home page content
|
||||
[DIR] fonts Folder containing the installed fonts
|
||||
[FILE] fonts.html File containing the fonts calls to load on cdnFonts
|
||||
[FILE] fonts.css File containing the style sheet linked to the local fonts
|
||||
[FILE] fonts.woff Local font files (woff, etc..)
|
||||
[DIR] modules Customization of modules or own data
|
||||
[FILE] admin.css Theme of administration pages
|
||||
[FILE] admin.json Theme data for administration pages
|
||||
[FILE] blacklist.json Logging of login attempts with unknown accounts
|
||||
[FILE] config.json Site configuration
|
||||
[FILE] core.json Core configuration
|
||||
[FILE] custom.css Advanced customization stylesheet
|
||||
[FILE] font.json Custom font descriptor
|
||||
[FILE] journal.log Activities logging
|
||||
[FILE] language.json Interface languages database
|
||||
[FILE] profil.json Users profiles database
|
||||
[FILE] theme.css Site theme
|
||||
[FILE] theme.json Site database
|
||||
[FILE] user.json User database
|
||||
[FILE] .backup Marker for file backup if present
|
||||
[DIR] file File manager upload directory
|
||||
[DIR] source Various resources
|
||||
[DIR] thumb Image thumbnails
|
||||
[DIR] tmp Temporary directory
|
||||
|
||||
## Arborescence générale
|
||||
[FILE] index.php ZwiiCMS initialization file
|
||||
[FILE] robots.txt Filtering of directories accessible to search engine robots
|
||||
[FILE] sitemap.xml Sitemap
|
||||
[FILE] sitemap.xml.gz Compressed version
|
||||
|
||||
*Légende : [D] Dossier ; [F] Fichier*
|
||||
|
||||
```text
|
||||
[D] core Contient le coeur de Zwii
|
||||
[D] layout Contient les différentes structure de thème
|
||||
[D] module Contient les modules du coeur
|
||||
[D] vendor Contient les librairies
|
||||
[F] core.js.php Coeur JavaScript de Zwii
|
||||
[F] core.php Coeur PHP de Zwii
|
||||
[D] module Contient les modules de page
|
||||
[D] site Contient les données du site
|
||||
[D] backup Contient les 30 dernière sauvegardes automatiques du fichier data.json
|
||||
[D] data Contient les fichiers de données
|
||||
[F] core.json Fichier de données
|
||||
[F] theme.json Fichier du thème
|
||||
[F] custom.css Feuille de style de la personnalisation avancée
|
||||
[F] theme.css Thème stocké dans le fichier data.json compilé en CSS
|
||||
[D] file Contient les fichiers envoyés sur le serveur depuis le gestionnaire de fichiers
|
||||
[D] source Contient les fichiers
|
||||
[D] thumb Contient les miniatures des fichiers de type image
|
||||
[D] tmp Contient les fichiers temporaire
|
||||
[F] index.php Fichier d'initialisation de Zwii
|
||||
```
|
||||
The .htaccess files contribute to security by filtering access to sensitive directories.
|
||||
|
0
core/vendor/phpmailer/.htaccess → core/class/.htaccess
Executable file → Normal file
0
core/vendor/phpmailer/.htaccess → core/class/.htaccess
Executable file → Normal file
19
core/class/autoload.php
Normal file
19
core/class/autoload.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
class autoload {
|
||||
public static function autoloader () {
|
||||
require_once 'core/core.php';
|
||||
require_once 'core/class/router.class.php';
|
||||
require_once 'core/class/helper.class.php';
|
||||
require_once 'core/class/template.class.php';
|
||||
require_once 'core/class/layout.class.php';
|
||||
require_once 'core/class/sitemap/Runtime.class.php';
|
||||
require_once 'core/class/sitemap/FileSystem.class.php';
|
||||
require_once 'core/class/sitemap/SitemapGenerator.class.php';
|
||||
require_once 'core/class/phpmailer/PHPMailer.class.php';
|
||||
require_once 'core/class/phpmailer/Exception.class.php';
|
||||
require_once 'core/class/phpmailer/SMTP.class.php';
|
||||
require_once 'core/class/jsondb/Dot.class.php';
|
||||
require_once 'core/class/jsondb/JsonDb.class.php';
|
||||
}
|
||||
}
|
729
core/class/helper.class.php
Normal file
729
core/class/helper.class.php
Normal file
@ -0,0 +1,729 @@
|
||||
<?php
|
||||
|
||||
class helper
|
||||
{
|
||||
|
||||
/** Statut de la réécriture d'URL (pour éviter de lire le contenu du fichier .htaccess à chaque self::baseUrl()) */
|
||||
public static $rewriteStatus = null;
|
||||
|
||||
/** Filtres personnalisés */
|
||||
const FILTER_BOOLEAN = 1;
|
||||
const FILTER_DATETIME = 2; // filtre pour le champ de formulaire A conserver pour la compatibilité
|
||||
const FILTER_FLOAT = 3;
|
||||
const FILTER_ID = 4;
|
||||
const FILTER_INT = 5;
|
||||
const FILTER_MAIL = 6;
|
||||
const FILTER_PASSWORD = 7;
|
||||
const FILTER_STRING_LONG = 8;
|
||||
const FILTER_STRING_SHORT = 9;
|
||||
const FILTER_TIMESTAMP = 10; // Saisie d'une date en locatime
|
||||
const FILTER_URL = 11;
|
||||
const FILTER_DATE = 12; // filtre pour le champ de formulaire
|
||||
const FILTER_TIME = 13; // filtre pour le champ de formulair
|
||||
const FILTER_MONTH = 14; // filtre pour le champ de formulair
|
||||
const FILTER_YEAR = 16; // filtre pour le champ de formulair
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Traduire le message dans la langue déterminée
|
||||
*/
|
||||
|
||||
public static function translate($text)
|
||||
{
|
||||
|
||||
// La traduction existe déjà dans le core
|
||||
/*
|
||||
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
|
||||
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
|
||||
$data = array_merge($dialogues,[$text => '']);
|
||||
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
}
|
||||
*/
|
||||
return (array_key_exists($text, core::$dialog) && !empty(core::$dialog[$text]) ? core::$dialog[$text] : $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formate la date avec le script strftime en UTF8
|
||||
* Date au format time()
|
||||
* $format strftime
|
||||
*/
|
||||
public static function dateUTF8($format, $date, $locale = 'fr_FR')
|
||||
{
|
||||
require_once 'core/class/strftime/php-8.1-strftime.class.php';
|
||||
return mb_convert_encoding(\PHP81_BC\strftime($format, $date, $locale), 'UTF-8', mb_list_encodings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction pour assurer la traduction des messages
|
||||
*/
|
||||
public static function googleTranslate($to, $text)
|
||||
{
|
||||
if (!file_exists('site/i18n/' . $to . '.json')) {
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode([]));
|
||||
}
|
||||
if (!empty($text)) {
|
||||
//Lecture des données en ligne
|
||||
$data = json_decode(file_get_contents('site/i18n/' . $to . '.json'), true);
|
||||
// Mode traduction
|
||||
if ($to !== 'fr_FR') {
|
||||
$arrayjson = json_decode(file_get_contents('https://clients5.google.com/translate_a/t?client=dict-chrome-ex&sl=auto&tl=' . $to . '&q=' . rawurlencode($text)), true);
|
||||
$response = $arrayjson[0][0];
|
||||
// Captation
|
||||
if ($data !== '') {
|
||||
if (array_key_exists($text, $data)) {
|
||||
$data[$text] = $response;
|
||||
} else {
|
||||
$data = array_merge($data, [$text => $response]);
|
||||
}
|
||||
}
|
||||
// Mode alimentation des chaines
|
||||
} else {
|
||||
// Créer la variable
|
||||
$data = array_merge($data, [$text => '']);
|
||||
}
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Récupérer l'adresse IP sans tenir compte du proxy
|
||||
* @param integer Niveau d'anonymat 0 aucun, 1 octet à droite, etc..
|
||||
* @return string IP adress
|
||||
* Cette fonction est utilisée par user
|
||||
*/
|
||||
|
||||
public static function getIp($anon = 4)
|
||||
{
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
// Anonymiser l'adresse IP v4
|
||||
$d = array_slice(explode('.', $ip), 0, $anon);
|
||||
$d = implode('.', $d);
|
||||
$j = array_fill(0, 4 - $anon, 'x');
|
||||
$k = implode('.', $j);
|
||||
$ip = count($j) == 0 ? $d : $d . '.' . $k;
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction pour récupérer le numéro de version en ligne et le catalogue des modules
|
||||
* @param string $url à récupérer
|
||||
* @return mixed données récupérées
|
||||
*/
|
||||
|
||||
public static function getUrlContents($url)
|
||||
{
|
||||
// Ejecter free.fr
|
||||
if (strpos(self::baseUrl(), 'free.fr') > 0) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
function_exists('file_get_contents') &&
|
||||
ini_get('allow_url_fopen')
|
||||
) {
|
||||
$url_get_contents_data = @file_get_contents($url); // Masque un warning éventuel
|
||||
} elseif (function_exists('curl_version')) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
$url_get_contents_data = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
} elseif (
|
||||
function_exists('fopen') &&
|
||||
function_exists('stream_get_contents') &&
|
||||
ini_get('allow_url_fopen')
|
||||
) {
|
||||
$handle = fopen($url, "r");
|
||||
$url_get_contents_data = stream_get_contents($handle);
|
||||
} else {
|
||||
$url_get_contents_data = false;
|
||||
}
|
||||
return $url_get_contents_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les valeurs d'une colonne du tableau de données
|
||||
* @param array $array Tableau cible
|
||||
* @param string $column Colonne à extraire
|
||||
* @param string $sort Type de tri à appliquer au tableau (SORT_ASC, SORT_DESC, ou null)
|
||||
* @return array
|
||||
*/
|
||||
public static function arraycolumn($array, $column, $sort = null)
|
||||
{
|
||||
$newArray = [];
|
||||
if (empty($array) === false) {
|
||||
$newArray = array_map(function ($element) use ($column) {
|
||||
return $element[$column];
|
||||
}, $array);
|
||||
switch ($sort) {
|
||||
case 'SORT_ASC':
|
||||
asort($newArray);
|
||||
break;
|
||||
case 'SORT_DESC':
|
||||
arsort($newArray);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibilité avec les anciens modules
|
||||
*/
|
||||
public static function arrayCollumn($array, $column, $sort = null)
|
||||
{
|
||||
return (helper::arrayColumn($array, $column, $sort));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Génère un backup des données de site
|
||||
* @param string $folder dossier de sauvegarde
|
||||
* @param array $exclude dossier exclus
|
||||
* @return string nom du fichier de sauvegarde
|
||||
*/
|
||||
|
||||
public static function autoBackup($folder, $filter = ['backup', 'tmp'])
|
||||
{
|
||||
// Creation du ZIP
|
||||
$baseName = str_replace('/', '', helper::baseUrl(false, false));
|
||||
$baseName = empty($baseName) ? 'ZwiiCMS' : $baseName;
|
||||
$fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s', time()) . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$directory = 'site/';
|
||||
//$filter = array('backup','tmp','file');
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
return ($fileName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retourne la liste des modules installés dans un tableau composé
|
||||
* du nom réel
|
||||
* du numéro de version
|
||||
*/
|
||||
public static function getModules()
|
||||
{
|
||||
$modules = array();
|
||||
$dirs = array_diff(scandir('module'), array('..', '.'));
|
||||
foreach ($dirs as $key => $value) {
|
||||
// Dossier non vide
|
||||
if (file_exists('module/' . $value . '/' . $value . '.php')) {
|
||||
// Lire les constantes en gérant les erreurs de nom de classe
|
||||
try {
|
||||
$class_reflex = new \ReflectionClass($value);
|
||||
$class_constants = $class_reflex->getConstants();
|
||||
// Constante REALNAME
|
||||
if (array_key_exists('REALNAME', $class_constants)) {
|
||||
$realName = $value::REALNAME;
|
||||
} else {
|
||||
$realName = ucfirst($value);
|
||||
}
|
||||
// Constante VERSION
|
||||
if (array_key_exists('VERSION', $class_constants)) {
|
||||
$version = $value::VERSION;
|
||||
} else {
|
||||
$version = '0.0';
|
||||
}
|
||||
// Constante UPDATE
|
||||
if (array_key_exists('UPDATE', $class_constants)) {
|
||||
$update = $value::UPDATE;
|
||||
} else {
|
||||
$update = '0.0';
|
||||
}
|
||||
// Constante DELETE
|
||||
if (array_key_exists('DELETE', $class_constants)) {
|
||||
$delete = $value::DELETE;
|
||||
} else {
|
||||
$delete = true;
|
||||
}
|
||||
// Constante DATADIRECTORY
|
||||
if (array_key_exists('DATADIRECTORY', $class_constants)) {
|
||||
$dataDirectory = $value::DATADIRECTORY;
|
||||
} else {
|
||||
$dataDirectory = '';
|
||||
}
|
||||
// Affection
|
||||
$modules[$value] = [
|
||||
'name' => $value,
|
||||
'realName' => $realName,
|
||||
'version' => $version,
|
||||
'update' => $update,
|
||||
'delete' => $delete,
|
||||
'dataDirectory' => $dataDirectory
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
// on ne fait rien
|
||||
}
|
||||
}
|
||||
}
|
||||
return ($modules);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retourne true si le protocole est en TLS
|
||||
* @return bool
|
||||
*/
|
||||
public static function isHttps()
|
||||
{
|
||||
if (
|
||||
(empty($_SERVER['HTTPS']) === false and $_SERVER['HTTPS'] !== 'off')
|
||||
or $_SERVER['SERVER_PORT'] === 443
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retourne l'URL de base du site
|
||||
* @param bool $queryString Affiche ou non le point d'interrogation
|
||||
* @param bool $host Affiche ou non l'host
|
||||
* @return string
|
||||
*/
|
||||
public static function baseUrl($queryString = true, $host = true)
|
||||
{
|
||||
// Protocole
|
||||
$protocol = helper::isHttps() === true ? 'https://' : 'http://';
|
||||
// Host
|
||||
if ($host) {
|
||||
$host = $protocol . $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
// Pathinfo
|
||||
$pathInfo = pathinfo($_SERVER['PHP_SELF']);
|
||||
// Querystring
|
||||
if ($queryString and helper::checkRewrite() === false) {
|
||||
$queryString = '?';
|
||||
} else {
|
||||
$queryString = '';
|
||||
}
|
||||
return $host . rtrim($pathInfo['dirname'], ' ' . DIRECTORY_SEPARATOR) . '/' . $queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check le statut de l'URL rewriting
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkRewrite()
|
||||
{
|
||||
// N'interroge que le serveur Apache
|
||||
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
|
||||
self::$rewriteStatus = false;
|
||||
} else {
|
||||
// Ouvre et scinde le fichier .htaccess
|
||||
$htaccess = explode('# URL rewriting', file_get_contents('.htaccess'));
|
||||
// Retourne un boolean en fonction du contenu de la partie réservée à l'URL rewriting
|
||||
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') !== false);
|
||||
}
|
||||
return self::$rewriteStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le numéro de version de Zwii est en ligne
|
||||
* @return string
|
||||
*/
|
||||
public static function getOnlineVersion($channel)
|
||||
{
|
||||
return (helper::getUrlContents(common::ZWII_UPDATE_URL . $channel . '/version'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check si une nouvelle version de Zwii est disponible
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNewVersion($channel)
|
||||
{
|
||||
$version = helper::getOnlineVersion($channel);
|
||||
$update = false;
|
||||
if (!empty($version)) {
|
||||
$update = version_compare(common::ZWII_VERSION, $version) == -1;
|
||||
}
|
||||
return $update;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Génère des variations d'une couleur
|
||||
* @param string $rgba Code rgba de la couleur
|
||||
* @return array
|
||||
*/
|
||||
public static function colorVariants($rgba)
|
||||
{
|
||||
preg_match('#\(+(.*)\)+#', $rgba, $matches);
|
||||
$rgba = explode(', ', $matches[1]);
|
||||
return [
|
||||
'normal' => 'rgba(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ',' . $rgba[3] . ')',
|
||||
'darken' => 'rgba(' . max(0, $rgba[0] - 15) . ',' . max(0, $rgba[1] - 15) . ',' . max(0, $rgba[2] - 15) . ',' . $rgba[3] . ')',
|
||||
'veryDarken' => 'rgba(' . max(0, $rgba[0] - 20) . ',' . max(0, $rgba[1] - 20) . ',' . max(0, $rgba[2] - 20) . ',' . $rgba[3] . ')',
|
||||
'text' => self::relativeLuminanceW3C($rgba) > .22 ? "#222" : "#DDD",
|
||||
'rgb' => 'rgb(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ')',
|
||||
'invert' => 'rgba (' .
|
||||
($rgba[0] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[0] < 128 ? 255 : 0) . ')'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un cookie
|
||||
* @param string $cookieKey Clé du cookie à supprimer
|
||||
*/
|
||||
public static function deleteCookie($cookieKey)
|
||||
{
|
||||
setcookie($cookieKey, '', time() - 3600, helper::baseUrl(false, false), '', false, true);
|
||||
unset($_COOKIE[$cookieKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filtre une chaîne en fonction d'un tableau de données
|
||||
* @param string $text Chaîne à filtrer
|
||||
* @param int $filter Type de filtre à appliquer
|
||||
* @return string
|
||||
*/
|
||||
public static function filter($text, $filter)
|
||||
{
|
||||
$text = is_null($text) ? $text : trim($text);
|
||||
switch ($filter) {
|
||||
case self::FILTER_BOOLEAN:
|
||||
$text = (bool) $text;
|
||||
break;
|
||||
case self::FILTER_DATETIME:
|
||||
$timezone = new DateTimeZone(core::$timezone);
|
||||
$date = new DateTime($text);
|
||||
$date->setTimezone($timezone);
|
||||
$text = (int) $date->format('U');
|
||||
break;
|
||||
case self::FILTER_FLOAT:
|
||||
$text = str_replace(',', '.', $text); // Remplacer les virgules par des points
|
||||
$text = filter_var($text, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$text = (float) $text;
|
||||
break;
|
||||
case self::FILTER_ID:
|
||||
$text = mb_strtolower($text, 'UTF-8');
|
||||
$text = strip_tags(
|
||||
str_replace(
|
||||
explode(',', 'á,à,â,ä,ã,å,ç,é,è,ê,ë,í,ì,î,ï,ñ,ó,ò,ô,ö,õ,ú,ù,û,ü,ý,ÿ,\',", '),
|
||||
explode(',', 'a,a,a,a,a,a,c,e,e,e,e,i,i,i,i,n,o,o,o,o,o,u,u,u,u,y,y,-,-,-'),
|
||||
$text
|
||||
)
|
||||
);
|
||||
$text = preg_replace('/([^a-z0-9-])/', '', $text);
|
||||
// Supprime les emoji
|
||||
$text = preg_replace('/[[:^print:]]/', '', $text);
|
||||
// Supprime les tirets en fin de chaine (emoji en fin de nom)
|
||||
$text = rtrim($text, '-');
|
||||
// Cas où un identifiant est vide
|
||||
if (empty($text)) {
|
||||
$text = uniqid('');
|
||||
}
|
||||
// Un ID ne peut pas être un entier, pour éviter les conflits avec le système de pagination
|
||||
if (intval($text) !== 0) {
|
||||
$text = '_' . $text;
|
||||
}
|
||||
break;
|
||||
case self::FILTER_INT:
|
||||
$text = (int) filter_var($text, FILTER_SANITIZE_NUMBER_INT);
|
||||
break;
|
||||
case self::FILTER_MAIL:
|
||||
$text = filter_var($text, FILTER_SANITIZE_EMAIL);
|
||||
break;
|
||||
case self::FILTER_PASSWORD:
|
||||
$text = password_hash($text, PASSWORD_BCRYPT);
|
||||
break;
|
||||
case self::FILTER_STRING_LONG:
|
||||
$text = mb_substr(filter_var($text, FILTER_SANITIZE_FULL_SPECIAL_CHARS), 0, 500000);
|
||||
break;
|
||||
case self::FILTER_STRING_SHORT:
|
||||
$text = mb_substr(filter_var($text, FILTER_SANITIZE_FULL_SPECIAL_CHARS), 0, 500);
|
||||
break;
|
||||
case self::FILTER_TIMESTAMP:
|
||||
$text = date('Y-m-d H:i:s', $text);
|
||||
break;
|
||||
case self::FILTER_URL:
|
||||
$text = filter_var($text, FILTER_SANITIZE_URL);
|
||||
break;
|
||||
case self::FILTER_DATE:
|
||||
$text = date('Y-m-d', $text);
|
||||
break;
|
||||
case self::FILTER_TIME:
|
||||
$text = date('H:i', $text);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrémente une clé en fonction des clés ou des valeurs d'un tableau
|
||||
* @param mixed $key Clé à incrémenter
|
||||
* @param array $array Tableau à vérifier
|
||||
* @return string
|
||||
*/
|
||||
public static function increment($key, $array = [])
|
||||
{
|
||||
// Pas besoin d'incrémenter si la clef n'existe pas
|
||||
if ($array === []) {
|
||||
return $key;
|
||||
}
|
||||
// Incrémente la clef
|
||||
else {
|
||||
// Si la clef est numérique elle est incrémentée
|
||||
if (is_numeric($key)) {
|
||||
$newKey = $key;
|
||||
while (array_key_exists($newKey, $array) or in_array($newKey, $array)) {
|
||||
$newKey++;
|
||||
}
|
||||
}
|
||||
// Sinon l'incrémentation est ajoutée après la clef
|
||||
else {
|
||||
$i = 2;
|
||||
$newKey = $key;
|
||||
while (array_key_exists($newKey, $array) or in_array($newKey, $array)) {
|
||||
$newKey = $key . '-' . $i;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $newKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimise du css
|
||||
* @param string $css Css à minimiser
|
||||
* @return string
|
||||
*/
|
||||
public static function minifyCss($css)
|
||||
{
|
||||
// Supprime les commentaires
|
||||
$css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
|
||||
// Supprime les tabulations, espaces, nouvelles lignes, etc...
|
||||
$css = str_replace(["\r\n", "\r", "\n", "\t", ' ', ' ', ' '], '', $css);
|
||||
$css = preg_replace(['(( )+{)', '({( )+)'], '{', $css);
|
||||
$css = preg_replace(['(( )+})', '(}( )+)', '(;( )*})'], '}', $css);
|
||||
$css = preg_replace(['(;( )+)', '(( )+;)'], ';', $css);
|
||||
// Convertir les codes entités
|
||||
$css = htmlspecialchars_decode($css);
|
||||
// Supprime les balises HTML
|
||||
$css = strip_tags($css);
|
||||
// Retourne le css minifié
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimise du js
|
||||
* @param string $js Js à minimiser
|
||||
* @return string
|
||||
*/
|
||||
public static function minifyJs($js)
|
||||
{
|
||||
// Supprime les commentaires
|
||||
$js = preg_replace('/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/|\s*(?<![\:\=])\/\/.*/', '', $js);
|
||||
// Supprime les tabulations, espaces, nouvelles lignes, etc...
|
||||
$js = str_replace(["\r\n", "\r", "\t", "\n", ' ', ' ', ' '], '', $js);
|
||||
$js = preg_replace(['(( )+\))', '(\)( )+)'], ')', $js);
|
||||
// Retourne le js minifié
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un système de pagination (retourne un tableau contenant les informations sur la pagination (first, last, pages))
|
||||
* @param array $array Tableau de donnée à utiliser
|
||||
* @param string $url URL à utiliser, la dernière partie doit correspondre au numéro de page, par défaut utiliser $this->getUrl()
|
||||
* @param string $item pagination nombre d'éléments par page
|
||||
* @param null|int $sufix Suffixe de l'url
|
||||
* @return array
|
||||
*/
|
||||
public static function pagination($array, $url, $item, $suffix = null)
|
||||
{
|
||||
// Scinde l'url
|
||||
$url = explode('/', $url);
|
||||
// Url de pagination
|
||||
$urlPagination = is_numeric($url[count($url) - 1]) ? array_pop($url) : 1;
|
||||
// Url de la page courante
|
||||
$urlCurrent = implode('/', $url);
|
||||
// Nombre d'éléments à afficher
|
||||
$nbElements = count($array);
|
||||
// Nombre de page
|
||||
$nbPage = ceil($nbElements / $item);
|
||||
// Page courante
|
||||
$currentPage = is_numeric($urlPagination) ? self::filter($urlPagination, self::FILTER_INT) : 1;
|
||||
// Premier élément de la page
|
||||
$firstElement = ($currentPage - 1) * $item;
|
||||
// Dernier élément de la page
|
||||
$lastElement = $firstElement + $item;
|
||||
$lastElement = ($lastElement > $nbElements) ? $nbElements : $lastElement;
|
||||
// Mise en forme de la liste des pages
|
||||
$pages = '';
|
||||
if ($nbPage > 1) {
|
||||
for ($i = 1; $i <= $nbPage; $i++) {
|
||||
$disabled = ($i === $currentPage) ? ' class="disabled"' : false;
|
||||
$pages .= '<a href="' . helper::baseUrl() . $urlCurrent . '/' . $i . $suffix . '"' . $disabled . '>' . $i . '</a>';
|
||||
}
|
||||
$pages = '<div class="pagination">' . $pages . '</div>';
|
||||
}
|
||||
// Retourne un tableau contenant les informations sur la pagination
|
||||
return [
|
||||
'first' => $firstElement,
|
||||
'last' => $lastElement,
|
||||
'pages' => $pages
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcul de la luminance relative d'une couleur
|
||||
*/
|
||||
public static function relativeLuminanceW3C($rgba)
|
||||
{
|
||||
// Conversion en sRGB
|
||||
$RsRGB = $rgba[0] / 255;
|
||||
$GsRGB = $rgba[1] / 255;
|
||||
$BsRGB = $rgba[2] / 255;
|
||||
// Ajout de la transparence
|
||||
$RsRGBA = $rgba[3] * $RsRGB + (1 - $rgba[3]);
|
||||
$GsRGBA = $rgba[3] * $GsRGB + (1 - $rgba[3]);
|
||||
$BsRGBA = $rgba[3] * $BsRGB + (1 - $rgba[3]);
|
||||
// Calcul de la luminance
|
||||
$R = ($RsRGBA <= .03928) ? $RsRGBA / 12.92 : pow(($RsRGBA + .055) / 1.055, 2.4);
|
||||
$G = ($GsRGBA <= .03928) ? $GsRGBA / 12.92 : pow(($GsRGBA + .055) / 1.055, 2.4);
|
||||
$B = ($BsRGBA <= .03928) ? $BsRGBA / 12.92 : pow(($BsRGBA + .055) / 1.055, 2.4);
|
||||
return .2126 * $R + .7152 * $G + .0722 * $B;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les attributs d'une balise au bon format
|
||||
* @param array $array Liste des attributs ($key => $value)
|
||||
* @param array $exclude Clés à ignorer ($key)
|
||||
* @return string
|
||||
*/
|
||||
public static function sprintAttributes(array $array = [], array $exclude = [])
|
||||
{
|
||||
$exclude = array_merge(
|
||||
[
|
||||
'before',
|
||||
'classWrapper',
|
||||
'help',
|
||||
'label'
|
||||
],
|
||||
$exclude
|
||||
);
|
||||
$attributes = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (($value or $value === 0) and in_array($key, $exclude) === false) {
|
||||
// Désactive le message de modifications non enregistrées pour le champ
|
||||
if ($key === 'noDirty') {
|
||||
$attributes[] = 'data-no-dirty';
|
||||
}
|
||||
// Disabled
|
||||
// Readonly
|
||||
elseif (in_array($key, ['disabled', 'readonly'])) {
|
||||
$attributes[] = sprintf('%s', $key);
|
||||
}
|
||||
// Autres
|
||||
else {
|
||||
$attributes[] = sprintf('%s="%s"', $key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(' ', $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne un segment de chaîne sans couper de mot
|
||||
* @param string $text Texte à scinder
|
||||
* @param int $start (voir substr de PHP pour fonctionnement)
|
||||
* @param int $length (voir substr de PHP pour fonctionnement)
|
||||
* @return string
|
||||
*/
|
||||
public static function subword($text, $start, $length)
|
||||
{
|
||||
$text = trim($text);
|
||||
|
||||
// Vérifier si la longueur du texte sans les balises dépasse la longueur souhaitée
|
||||
if (mb_strlen(strip_tags($text)) > $length) {
|
||||
// Utiliser mb_substr pour couper le texte
|
||||
$text = mb_substr($text, $start, $length);
|
||||
|
||||
// S'assurer que le texte ne se termine pas au milieu d'un mot
|
||||
$lastSpace = mb_strrpos($text, ' ');
|
||||
if ($lastSpace !== false) {
|
||||
$text = mb_substr($text, 0, $lastSpace);
|
||||
}
|
||||
|
||||
// Fermer les balises HTML ouvertes
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML('<div>' . $text . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||||
$text = $dom->saveHTML();
|
||||
|
||||
// Retirer la balise de conteneur ajoutée
|
||||
$text = preg_replace('~^<div>(.*)</div>$~s', '$1', $text);
|
||||
|
||||
// Ajouter des points de suspension si le texte a été coupé
|
||||
$text .= '...';
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cryptage
|
||||
* @param string $key la clé d'encryptage
|
||||
* @param string $string la chaine à coder
|
||||
* @return string
|
||||
*/
|
||||
public static function encrypt($string, $key)
|
||||
{
|
||||
$encrypted = openssl_encrypt($string, "AES-256-CBC", $key, 0, substr(md5($key), 0, 16));
|
||||
return base64_encode($encrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Décryptage
|
||||
* @param string $key la clé d'encryptage
|
||||
* @param string $string la chaine à décoder
|
||||
* @return string
|
||||
*/
|
||||
public static function decrypt($string, $key)
|
||||
{
|
||||
$decrypted = openssl_decrypt(base64_decode($string), "AES-256-CBC", $key, 0, substr(md5($key), 0, 16));
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
}
|
477
core/class/jsondb/Dot.class.php
Normal file
477
core/class/jsondb/Dot.class.php
Normal file
@ -0,0 +1,477 @@
|
||||
<?php
|
||||
|
||||
namespace Prowebcraft;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* Dot Notation
|
||||
*
|
||||
* This class provides dot notation access to arrays, so it's easy to handle
|
||||
* multidimensional data in a clean way.
|
||||
*/
|
||||
class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
{
|
||||
|
||||
/** @var array Data */
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array|null $data Data
|
||||
*/
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of path, default value if path doesn't exist or all data
|
||||
*
|
||||
* @param array $array Source Array
|
||||
* @param mixed|null $key Path
|
||||
* @param mixed|null $default Default value
|
||||
* @return mixed Value of path
|
||||
*/
|
||||
public static function getValue($array, $key, $default = null)
|
||||
{
|
||||
if (is_string($key)) {
|
||||
// Iterate path
|
||||
$keys = explode('.', $key);
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($array[$key])) {
|
||||
return $default;
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
// Get value
|
||||
return $array;
|
||||
} elseif (is_null($key)) {
|
||||
// Get all data
|
||||
return $array;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value or array of values to path
|
||||
*
|
||||
* @param array $array Target array with data
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
*/
|
||||
public static function setValue(&$array, $key, $value)
|
||||
{
|
||||
if (is_string($key)) {
|
||||
// Iterate path
|
||||
$keys = explode('.', $key);
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($array[$key]) || !is_array($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
// Set value to path
|
||||
$array = $value;
|
||||
} elseif (is_array($key)) {
|
||||
// Iterate array of paths and values
|
||||
foreach ($key as $k => $v) {
|
||||
self::setValue($array, $k, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add value or array of values to path
|
||||
*
|
||||
* @param array $array Target array with data
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
* @param boolean $pop Helper to pop out last key if value is an array
|
||||
*/
|
||||
public static function addValue(&$array, $key, $value = null, $pop = false)
|
||||
{
|
||||
if (is_array($key)) {
|
||||
// Iterate array of paths and values
|
||||
foreach ($key as $k => $v) {
|
||||
self::addValue($array, $k, $v);
|
||||
}
|
||||
} else {
|
||||
// Iterate path
|
||||
$keys = explode('.', (string)$key);
|
||||
if ($pop === true) {
|
||||
array_pop($keys);
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($array[$key]) || !is_array($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
// Add value to path
|
||||
$array[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete path or array of paths
|
||||
*
|
||||
* @param array $array Target array with data
|
||||
* @param mixed $key Path or array of paths to delete
|
||||
*/
|
||||
public static function deleteValue(&$array, $key)
|
||||
{
|
||||
if (is_string($key)) {
|
||||
// Iterate path
|
||||
$keys = explode('.', $key);
|
||||
$last = array_pop($keys);
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($array[$key])) {
|
||||
return;
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
if (isset($array[$last])) {
|
||||
// Detele path
|
||||
unset($array[$last]);
|
||||
}
|
||||
} elseif (is_array($key)) {
|
||||
// Iterate array of paths
|
||||
foreach ($key as $k) {
|
||||
self::deleteValue($array, $k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get value of path, default value if path doesn't exist or all data
|
||||
*
|
||||
* @param mixed|null $key Path
|
||||
* @param mixed|null $default Default value
|
||||
* @return mixed Value of path
|
||||
*/
|
||||
public function get($key, $default = null, $asObject = false)
|
||||
{
|
||||
$value = self::getValue($this->data, $key, $default);
|
||||
if ($asObject && is_array($value)) {
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value or array of values to path
|
||||
*
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
* @return $this
|
||||
*/
|
||||
public function set($key, $value = null)
|
||||
{
|
||||
self::setValue($this->data, $key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add value or array of values to path
|
||||
*
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
* @param boolean $pop Helper to pop out last key if value is an array
|
||||
* @return $this
|
||||
*/
|
||||
public function add($key, $value = null, $pop = false)
|
||||
{
|
||||
self::addValue($this->data, $key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if path exists
|
||||
*
|
||||
* @param string $key Path
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$keys = explode('.', (string)$key);
|
||||
$data = &$this->data;
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($data[$key])) {
|
||||
return false;
|
||||
}
|
||||
$data = &$data[$key];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete path or array of paths
|
||||
*
|
||||
* @param mixed $key Path or array of paths to delete
|
||||
* @return $this
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
self::deleteValue($this->data, $key);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase numeric value
|
||||
*
|
||||
* @param string $key
|
||||
* @param float $number
|
||||
* @return float
|
||||
*/
|
||||
public function plus(string $key, float $number): float
|
||||
{
|
||||
$newAmount = $this->get($key, 0) + $number;
|
||||
$this->set($key, $newAmount);
|
||||
|
||||
return $newAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce numeric value
|
||||
*
|
||||
* @param string $key
|
||||
* @param float $number
|
||||
* @return float
|
||||
*/
|
||||
public function minus(string $key, float $number): float
|
||||
{
|
||||
$newAmount = $this->get($key, 0) - $number;
|
||||
$this->set($key, $newAmount);
|
||||
|
||||
return $newAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data, data from path or array of paths and
|
||||
* optionally format path if it doesn't exist
|
||||
*
|
||||
* @param mixed|null $key Path or array of paths to clean
|
||||
* @param boolean $format Format option
|
||||
*/
|
||||
public function clear($key = null, $format = false)
|
||||
{
|
||||
if (is_string($key)) {
|
||||
// Iterate path
|
||||
$keys = explode('.', $key);
|
||||
$data = &$this->data;
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($data[$key]) || !is_array($data[$key])) {
|
||||
if ($format === true) {
|
||||
$data[$key] = [];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$data = &$data[$key];
|
||||
}
|
||||
// Clear path
|
||||
$data = [];
|
||||
} elseif (is_array($key)) {
|
||||
// Iterate array
|
||||
foreach ($key as $k) {
|
||||
$this->clear($k, $format);
|
||||
}
|
||||
} elseif (is_null($key)) {
|
||||
// Clear all data
|
||||
$this->data = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data as a reference
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function setDataAsRef(array &$data)
|
||||
{
|
||||
$this->data = &$data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetGet($offset): mixed
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
$this->delete($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic methods
|
||||
*/
|
||||
public function __set($key, $value = null)
|
||||
{
|
||||
$this->set($key, $value);
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->has($key);
|
||||
}
|
||||
|
||||
public function __unset($key)
|
||||
{
|
||||
$this->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for emptiness
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return !(bool)count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all data as array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as json string
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return json_encode($this->data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __toArray(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element
|
||||
* @link https://php.net/manual/en/iterator.current.php
|
||||
* @return mixed Can return any type.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function current(): mixed
|
||||
{
|
||||
return current($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element
|
||||
* @link https://php.net/manual/en/iterator.next.php
|
||||
* @return void Any returned value is ignored.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function next(): void
|
||||
{
|
||||
next($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
* @link https://php.net/manual/en/iterator.key.php
|
||||
* @return mixed scalar on success, or null on failure.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function key(): mixed
|
||||
{
|
||||
return key($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid
|
||||
* @link https://php.net/manual/en/iterator.valid.php
|
||||
* @return bool The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function valid(): bool
|
||||
{
|
||||
$key = key($this->data);
|
||||
return ($key !== NULL && $key !== FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element
|
||||
* @link https://php.net/manual/en/iterator.rewind.php
|
||||
* @return void Any returned value is ignored.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
reset($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
}
|
191
core/class/jsondb/JsonDb.class.php
Normal file
191
core/class/jsondb/JsonDb.class.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Andrey Mistulov
|
||||
* Company: Aristos
|
||||
* Date: 14.03.2017
|
||||
* Time: 15:25
|
||||
*/
|
||||
|
||||
namespace Prowebcraft;
|
||||
|
||||
/**
|
||||
* Class Data
|
||||
* @package Aristos
|
||||
*/
|
||||
class JsonDb extends \Prowebcraft\Dot
|
||||
{
|
||||
protected $db = '';
|
||||
protected $data = null;
|
||||
protected $config = [];
|
||||
// Tentative d'encodage après échec
|
||||
const MAX_JSON_ENCODE_ATTEMPTS = 5;
|
||||
// Tentative d'écriture après échec
|
||||
const MAX_FILE_WRITE_ATTEMPTS = 5;
|
||||
// Délais entre deux tentaives
|
||||
const RETRY_DELAY_SECONDS = 1;
|
||||
|
||||
public function __construct($config = [])
|
||||
{
|
||||
$this->config = array_merge([
|
||||
'name' => 'data.json',
|
||||
'backup' => false,
|
||||
'dir' => getcwd()
|
||||
], $config);
|
||||
$this->loadData();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload data from file
|
||||
* @return $this
|
||||
*/
|
||||
public function reload()
|
||||
{
|
||||
$this->loadData(true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set value or array of values to path
|
||||
*
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
* @param bool $save Save data to database
|
||||
* @return $this
|
||||
*/
|
||||
public function set($key, $value = null, $save = true)
|
||||
{
|
||||
parent::set($key, $value);
|
||||
if ($save)
|
||||
$this->save();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add value or array of values to path
|
||||
*
|
||||
* @param mixed $key Path or array of paths and values
|
||||
* @param mixed|null $value Value to set if path is not an array
|
||||
* @param boolean $pop Helper to pop out last key if value is an array
|
||||
* @param bool $save Save data to database
|
||||
* @return $this
|
||||
*/
|
||||
public function add($key, $value = null, $pop = false, $save = true)
|
||||
{
|
||||
parent::add($key, $value, $pop);
|
||||
if ($save)
|
||||
$this->save();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete path or array of paths
|
||||
*
|
||||
* @param mixed $key Path or array of paths to delete
|
||||
* @param bool $save Save data to database
|
||||
* @return $thisurn $this
|
||||
*/
|
||||
public function delete($key, $save = true)
|
||||
{
|
||||
parent::delete($key);
|
||||
if ($save)
|
||||
$this->save();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data, data from path or array of paths and
|
||||
* optionally format path if it doesn't exist
|
||||
*
|
||||
* @param mixed|null $key Path or array of paths to clean
|
||||
* @param boolean $format Format option
|
||||
* @param bool $save Save data to database
|
||||
* @return $this
|
||||
*/
|
||||
public function clear($key = null, $format = false, $save = true)
|
||||
{
|
||||
parent::clear($key, $format);
|
||||
if ($save)
|
||||
$this->save();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Local database upload
|
||||
* @param bool $reload Reboot data?
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
protected function loadData($reload = false)
|
||||
{
|
||||
if ($this->data === null || $reload) {
|
||||
$this->db = $this->config['dir'] . $this->config['name'];
|
||||
if (!file_exists($this->db)) {
|
||||
return null; // Rebuild database manage by CMS
|
||||
} else {
|
||||
if ($this->config['backup']) {
|
||||
try {
|
||||
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
|
||||
} catch (\Exception $e) {
|
||||
error_log('Erreur de chargement : ' . $e);
|
||||
exit('Erreur de chargement : ' . $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->data = json_decode(file_get_contents($this->db), true);
|
||||
if (!$this->data === null) {
|
||||
throw new \InvalidArgumentException('Database file ' . $this->db
|
||||
. ' contains invalid json object. Please validate or remove file');
|
||||
}
|
||||
}
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save database
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
// Encode les données au format JSON avec les options spécifiées
|
||||
//$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
|
||||
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
|
||||
|
||||
// Vérifie la longueur de la chaîne JSON encodée
|
||||
$encoded_length = strlen($encoded_data);
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempt = 0;
|
||||
|
||||
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
|
||||
while ($attempt < 5) {
|
||||
// Essaye d'écrire les données encodées dans le fichier de base de données
|
||||
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
|
||||
|
||||
//$now = \DateTime::createFromFormat('U.u', microtime(true));
|
||||
//file_put_contents("tmplog.txt", '[JsonDb][' . $now->format('H:i:s.u') . ']--' . $this->db . "\r\n", FILE_APPEND);
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result === $encoded_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
break;
|
||||
}
|
||||
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempt++;
|
||||
|
||||
// Attente
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// Vérifie si l'écriture a échoué même après plusieurs tentatives
|
||||
if ($write_result !== $encoded_length) {
|
||||
// Enregistre un message d'erreur dans le journal des erreurs
|
||||
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
|
||||
// Affiche un message d'erreur et termine le script
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
}
|
||||
}
|
||||
}
|
19
core/class/jsondb/LICENSE.md
Normal file
19
core/class/jsondb/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2016-2017 Andrey Mistulov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
269
core/class/jsondb/README.md
Normal file
269
core/class/jsondb/README.md
Normal file
@ -0,0 +1,269 @@
|
||||
# Dot - PHP dot notation array access
|
||||
Based on [adbario/php-dot-notation](https://github.com/adbario/php-dot-notation) package
|
||||
|
||||
Easy access to multidimensional arrays with dot notation.
|
||||
With dot notation, your code is cleaner and handling deeper arrays is super easy.
|
||||
|
||||
This class implements PHP's ArrayAccess class, so Dot object can also be used the same way as normal arrays with additional dot notation.
|
||||
|
||||
With Dot you can change this:
|
||||
|
||||
```php
|
||||
echo $data['info']['home']['address'];
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
```php
|
||||
echo $data->get('info.home.address');
|
||||
```
|
||||
|
||||
or even this:
|
||||
|
||||
```php
|
||||
echo $data['info.home.address'];
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Via composer:
|
||||
|
||||
```
|
||||
composer require adbario/php-dot-notation
|
||||
```
|
||||
|
||||
Or just copy the class file Dot.php and handle namespace yourself.
|
||||
|
||||
#### With [Composer](https://getcomposer.org/):
|
||||
|
||||
```
|
||||
composer require adbario/php-dot-notation
|
||||
```
|
||||
|
||||
#### Manual installation:
|
||||
1. Download the latest release
|
||||
2. Extract the files into your project
|
||||
3. require_once '/path/to/php-dot-notation/src/Dot.php';
|
||||
|
||||
## Usage
|
||||
|
||||
This array will be used as a reference on this guide:
|
||||
|
||||
```php
|
||||
$array = [
|
||||
'user' => [
|
||||
'firstname' => 'John',
|
||||
'lastname' => 'Smith'
|
||||
],
|
||||
'info' => [
|
||||
'kids' => [
|
||||
0 => 'Laura',
|
||||
1 => 'Chris',
|
||||
2 => 'Little Johnny'
|
||||
],
|
||||
'home' => [
|
||||
'address' => 'Rocky Road 3'
|
||||
]
|
||||
]
|
||||
];
|
||||
```
|
||||
|
||||
### Create a Dot object
|
||||
|
||||
To start with an empty array, just create a new Dot object:
|
||||
|
||||
```php
|
||||
$data = new \Adbar\Dot;
|
||||
```
|
||||
|
||||
If you have an array already available, inject it to the Dot object:
|
||||
|
||||
```php
|
||||
$data = new \Adbar\Dot($array);
|
||||
```
|
||||
|
||||
Set an array after creating the Dot object:
|
||||
|
||||
```php
|
||||
$data->setArray($array);
|
||||
```
|
||||
|
||||
Set an array as a reference, and all changes will be made directly to the original array:
|
||||
|
||||
```php
|
||||
$data->setReference($array);
|
||||
```
|
||||
|
||||
### Set a value
|
||||
|
||||
Set i.e. a phone number in the 'home' array:
|
||||
|
||||
```php
|
||||
$data->set('info.home.tel', '09-123-456-789');
|
||||
|
||||
// Array style
|
||||
$data['info.home.tel'] = '09-123-456-789';
|
||||
```
|
||||
|
||||
Set multiple values at once:
|
||||
|
||||
```php
|
||||
$data->set([
|
||||
'user.haircolor' => 'blue',
|
||||
'info.home.address' => 'Private Lane 1'
|
||||
]);
|
||||
```
|
||||
|
||||
If the value already exists, Dot will override it with a new value.
|
||||
|
||||
### Get a value
|
||||
|
||||
```php
|
||||
echo $data->get('info.home.address');
|
||||
|
||||
// Default value if the path doesn't exist
|
||||
echo $data->get('info.home.country', 'some default value');
|
||||
|
||||
// Array style
|
||||
echo $data['info.home.address'];
|
||||
```
|
||||
|
||||
Get all the stored values:
|
||||
|
||||
```php
|
||||
$values = $data->all();
|
||||
``
|
||||
|
||||
Get a value from a path and remove it:
|
||||
|
||||
```php
|
||||
$address = $data->pull('home.address');
|
||||
```
|
||||
|
||||
Get all the stored values and remove them:
|
||||
|
||||
```php
|
||||
$values = $data->pull();
|
||||
```
|
||||
|
||||
### Add a value
|
||||
|
||||
```php
|
||||
$data->add('info.kids', 'Amy');
|
||||
```
|
||||
|
||||
Multiple values at once:
|
||||
|
||||
```php
|
||||
$data->add('info.kids', [
|
||||
'Ben', 'Claire'
|
||||
]);
|
||||
```
|
||||
|
||||
### Check if a value exists
|
||||
|
||||
```php
|
||||
if ($data->has('info.home.address')) {
|
||||
// Do something...
|
||||
}
|
||||
|
||||
// Array style
|
||||
if (isset($data['info.home.address'])) {
|
||||
// Do something...
|
||||
}
|
||||
```
|
||||
|
||||
### Delete a value
|
||||
|
||||
```php
|
||||
$data->delete('info.home.address');
|
||||
|
||||
// Array style
|
||||
unset($data['info.home.address']);
|
||||
```
|
||||
|
||||
Multiple values at once:
|
||||
|
||||
```php
|
||||
$data->delete([
|
||||
'user.lastname', 'info.home.address'
|
||||
]);
|
||||
```
|
||||
|
||||
### Clear values
|
||||
|
||||
Delete all the values from a path:
|
||||
|
||||
```php
|
||||
$data->clear('info.home');
|
||||
```
|
||||
|
||||
Clear multiple paths at once:
|
||||
|
||||
```php
|
||||
$data->clear([
|
||||
'user', 'info.home'
|
||||
]);
|
||||
```
|
||||
|
||||
Clear all data:
|
||||
|
||||
```php
|
||||
$data->clear();
|
||||
```
|
||||
|
||||
### Sort the values
|
||||
|
||||
You can sort the values of a given path or all the stored values.
|
||||
|
||||
Sort the values of a path:
|
||||
|
||||
```php
|
||||
$kids = $data->sort('info.kids');
|
||||
|
||||
// Sort recursively
|
||||
$info = $data->sort('info');
|
||||
```
|
||||
|
||||
Sort all the values
|
||||
|
||||
```php
|
||||
$sorted = $data->sort();
|
||||
|
||||
// Sort recursively
|
||||
$sorted = $data->sort();
|
||||
```
|
||||
|
||||
### Magic methods
|
||||
|
||||
Magic methods can be used to handle single level data (without dot notation). These examples are not using the same data array as examples above.
|
||||
|
||||
Set a value:
|
||||
|
||||
```php
|
||||
$data->name = 'John';
|
||||
```
|
||||
|
||||
Get a value:
|
||||
|
||||
```php
|
||||
echo $data->name;
|
||||
```
|
||||
|
||||
Check if a value exists:
|
||||
|
||||
```php
|
||||
if (isset($data->name)) {
|
||||
// Do something...
|
||||
}
|
||||
```
|
||||
|
||||
Delete a value:
|
||||
|
||||
```php
|
||||
unset($data->name);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT license](LICENSE.md)
|
1359
core/class/layout.class.php
Normal file
1359
core/class/layout.class.php
Normal file
File diff suppressed because it is too large
Load Diff
3
core/class/phpmailer/.htaccess
Normal file
3
core/class/phpmailer/.htaccess
Normal file
@ -0,0 +1,3 @@
|
||||
# Bloque l'accès à la librairie
|
||||
Order deny,allow
|
||||
Deny from all
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer Exception class.
|
||||
* PHP Version 5.5.
|
||||
@ -9,7 +10,7 @@
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2012 - 2017 Marcus Bointon
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
@ -34,6 +35,6 @@ class Exception extends \Exception
|
||||
*/
|
||||
public function errorMessage()
|
||||
{
|
||||
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
|
||||
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1458
core/class/phpmailer/SMTP.class.php
Normal file
1458
core/class/phpmailer/SMTP.class.php
Normal file
File diff suppressed because it is too large
Load Diff
28
core/class/phpmailer/i18n/phpmailer.lang-de.php
Normal file
28
core/class/phpmailer/i18n/phpmailer.lang-de.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* German PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP-Fehler: Konnte keine Verbindung zum SMTP-Host herstellen.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-Fehler: Daten werden nicht akzeptiert.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'E-Mail-Inhalt ist leer.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Unbekannte Kodierung: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Konnte folgenden Befehl nicht ausführen: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Zugriff auf folgende Datei fehlgeschlagen: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Dateifehler: Konnte folgende Datei nicht öffnen: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Die folgende Absenderadresse ist nicht korrekt: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Mail-Funktion konnte nicht initialisiert werden.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Die Adresse ist ungültig: ';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Ungültiger Hosteintrag: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Ungültiger Host: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wird nicht unterstützt.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Bitte geben Sie mindestens eine Empfängeradresse an.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-Fehler: Die folgenden Empfänger sind nicht korrekt: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Fehler beim Signieren: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'Verbindung zum SMTP-Server fehlgeschlagen.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Fehler vom SMTP-Server: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Kann Variable nicht setzen oder zurücksetzen: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Fehlende Erweiterung: ';
|
33
core/class/phpmailer/i18n/phpmailer.lang-el.php
Normal file
33
core/class/phpmailer/i18n/phpmailer.lang-el.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Greek PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Σφάλμα SMTP: Αδυναμία πιστοποίησης.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Η έκδοση PHP που χρησιμοποιείτε παρουσιάζει σφάλμα που μπορεί να έχει ως αποτέλεσμα κατεστραμένα μηνύματα. Για να το διορθώσετε, αλλάξτε τον τρόπο αποστολής σε SMTP, απενεργοποιήστε την επιλογή mail.add_x_header στο αρχείο php.ini, αλλάξτε λειτουργικό σε MacOS ή Linux ή αναβαθμίστε την PHP σε έκδοση 7.0.17+ ή 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Σφάλμα SMTP: Αδυναμία σύνδεσης με τον φιλοξενητή SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Σφάλμα SMTP: Μη αποδεκτά δεδομένα.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Η ηλεκτρονική επιστολή δεν έχει περιεχόμενο.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Άγνωστη μορφή κωδικοποίησης: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Αδυναμία εκτέλεσης: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Απουσία επέκτασης: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Αδυναμία πρόσβασης στο αρχείο: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Σφάλμα Αρχείου: Αδυναμία ανοίγματος αρχείου: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Η ακόλουθη διεύθυνση αποστολέα δεν είναι σωστή: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Αδυναμία εκκίνησης συνάρτησης Mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Μη έγκυρη διεύθυνση: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Μη έγκυρο όνομα κεφαλίδας ή τιμή';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Μη έγκυρη εισαγωγή φιλοξενητή: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Μη έγκυρος φιλοξενητής: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer δεν υποστηρίζεται.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Δώστε τουλάχιστον μια ηλεκτρονική διεύθυνση παραλήπτη.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Σφάλμα SMTP: Οι παρακάτω διευθύνσεις παραλήπτη δεν είναι έγκυρες: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Σφάλμα υπογραφής: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Κώδικάς SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Πρόσθετες πληροφορίες SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'Αποτυχία σύνδεσης SMTP.';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Λεπτομέρεια: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Σφάλμα με τον διακομιστή SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Αδυναμία ορισμού ή επαναφοράς μεταβλητής: ';
|
31
core/class/phpmailer/i18n/phpmailer.lang-es.php
Normal file
31
core/class/phpmailer/i18n/phpmailer.lang-es.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Spanish PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Matt Sturdy <matt.sturdy@gmail.com>
|
||||
* @author Crystopher Glodzienski Cardoso <crystopher.glodzienski@gmail.com>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Codificación desconocida: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Imposible ejecutar: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Debe proporcionar al menos una dirección de email de destino.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinos fallaron: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Error al firmar: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Código del servidor SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Información adicional del servidor SMTP: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido';
|
38
core/class/phpmailer/i18n/phpmailer.lang-fr.php
Normal file
38
core/class/phpmailer/i18n/phpmailer.lang-fr.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* French PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* Some French punctuation requires a thin non-breaking space (U+202F) character before it,
|
||||
* for example before a colon or exclamation mark.
|
||||
* There is one of these characters between these quotes: " "
|
||||
* @see http://unicode.org/udhr/n/notes_fra.html
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : échec de l’authentification.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Votre version de PHP est affectée par un bug qui peut entraîner des messages corrompus. Pour résoudre ce problème, passez à l’envoi par SMTP, désactivez l’option mail.add_x_header dans le fichier php.ini, passez à MacOS ou Linux, ou passez PHP à la version 7.0.17+ ou 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Erreur SMTP : impossible de se connecter au serveur SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP : données incorrectes.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Corps du message vide.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Encodage inconnu : ';
|
||||
$PHPMAILER_LANG['execute'] = 'Impossible de lancer l’exécution : ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extension manquante : ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Impossible d’accéder au fichier : ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Ouverture du fichier impossible : ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'L’adresse d’expéditeur suivante a échoué : ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Impossible d’instancier la fonction mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Adresse courriel non valide : ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nom ou valeur de l’en-tête non valide';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Entrée d’hôte non valide : ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Hôte non valide : ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : les destinataires suivants ont échoué : ';
|
||||
$PHPMAILER_LANG['signing'] = 'Erreur de signature : ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Code SMTP : ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Informations supplémentaires SMTP : ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'La fonction SMTP connect() a échouée.';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Détails : ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Erreur du serveur SMTP : ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Impossible d’initialiser ou de réinitialiser une variable : ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extension manquante : ';
|
28
core/class/phpmailer/i18n/phpmailer.lang-it.php
Normal file
28
core/class/phpmailer/i18n/phpmailer.lang-it.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Italian PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Ilias Bartolini <brain79@inwind.it>
|
||||
* @author Stefano Sabatini <sabas88@gmail.com>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Impossibile autenticarsi.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Impossibile connettersi all\'host SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dati non accettati dal server.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Il corpo del messaggio è vuoto';
|
||||
$PHPMAILER_LANG['encoding'] = 'Codifica dei caratteri sconosciuta: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Impossibile eseguire l\'operazione: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Impossibile accedere al file: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'File Error: Impossibile aprire il file: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'I seguenti indirizzi mittenti hanno generato errore: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Impossibile istanziare la funzione mail';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Impossibile inviare, l\'indirizzo email non è valido: ';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Deve essere fornito almeno un indirizzo ricevente';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = 'Mailer non supportato';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato un errore: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Errore nella firma: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fallita.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Errore del server SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Impossibile impostare o resettare la variabile: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Estensione mancante: ';
|
27
core/class/phpmailer/i18n/phpmailer.lang-pt.php
Normal file
27
core/class/phpmailer/i18n/phpmailer.lang-pt.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Portuguese (European) PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Jonadabe <jonadabe@hotmail.com>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';
|
31
core/class/phpmailer/i18n/phpmailer.lang-tr.php
Normal file
31
core/class/phpmailer/i18n/phpmailer.lang-tr.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Turkish PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Elçin Özel
|
||||
* @author Can Yılmaz
|
||||
* @author Mehmet Benlioğlu
|
||||
* @author @yasinaydin
|
||||
* @author Ogün Karakuş
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Oturum açılamadı.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP Hatası: SMTP sunucusuna bağlanılamadı.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hatası: Veri kabul edilmedi.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Mesajın içeriği boş';
|
||||
$PHPMAILER_LANG['encoding'] = 'Bilinmeyen karakter kodlama: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Çalıştırılamadı: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Dosyaya erişilemedi: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Dosya Hatası: Dosya açılamadı: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Belirtilen adreslere gönderme başarısız: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Örnek e-posta fonksiyonu oluşturulamadı.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Geçersiz e-posta adresi: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' e-posta kütüphanesi desteklenmiyor.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'En az bir alıcı e-posta adresi belirtmelisiniz.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatası: Belirtilen alıcılara ulaşılamadı: ';
|
||||
$PHPMAILER_LANG['signing'] = 'İmzalama hatası: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP connect() fonksiyonu başarısız.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Değişken ayarlanamadı ya da sıfırlanamadı: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Eklenti bulunamadı: ';
|
898
core/class/router.class.php
Normal file
898
core/class/router.class.php
Normal file
@ -0,0 +1,898 @@
|
||||
<?php
|
||||
|
||||
class core extends common
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructeur du coeur
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// Token CSRF
|
||||
if (empty($_SESSION['csrf'])) {
|
||||
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(64));
|
||||
}
|
||||
|
||||
// Fuseau horaire
|
||||
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
|
||||
date_default_timezone_set(common::$timezone);
|
||||
// Supprime les fichiers temporaires
|
||||
$lastClearTmp = mktime(0, 0, 0);
|
||||
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
|
||||
$iterator = new DirectoryIterator(common::TEMP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile() &&
|
||||
$fileInfos->getBasename() !== '.htaccess' &&
|
||||
$fileInfos->getBasename() !== '.gitkeep'
|
||||
) {
|
||||
@unlink($fileInfos->getPathname());
|
||||
}
|
||||
}
|
||||
// Date de la dernière suppression
|
||||
$this->setData(['core', 'lastClearTmp', $lastClearTmp]);
|
||||
}
|
||||
// Backup automatique des données
|
||||
$lastBackup = mktime(0, 0, 0);
|
||||
if (
|
||||
$this->getData(['config', 'autoBackup'])
|
||||
and $lastBackup > $this->getData(['core', 'lastBackup']) + 86400
|
||||
and $this->getData(['user']) // Pas de backup pendant l'installation
|
||||
) {
|
||||
// Copie des fichier de données
|
||||
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
// Date du dernier backup
|
||||
$this->setData(['core', 'lastBackup', $lastBackup]);
|
||||
// Supprime les backups de plus de 30 jours
|
||||
$iterator = new DirectoryIterator(common::BACKUP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile()
|
||||
and $fileInfos->getBasename() !== '.htaccess'
|
||||
and $fileInfos->getMTime() + (86400 * 30) < time()
|
||||
) {
|
||||
@unlink($fileInfos->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Crée le fichier de personnalisation avancée
|
||||
if (file_exists(common::DATA_DIR . 'custom.css') === false) {
|
||||
$this->secure_file_put_contents(common::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
|
||||
chmod(common::DATA_DIR . 'custom.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation
|
||||
if (file_exists(common::DATA_DIR . 'theme.css') === false) {
|
||||
$this->secure_file_put_contents(common::DATA_DIR . 'theme.css', '');
|
||||
chmod(common::DATA_DIR . 'theme.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation de l'administration
|
||||
if (file_exists(common::DATA_DIR . 'admin.css') === false) {
|
||||
$this->secure_file_put_contents(common::DATA_DIR . 'admin.css', '');
|
||||
chmod(common::DATA_DIR . 'admin.css', 0755);
|
||||
}
|
||||
|
||||
// Check la version rafraichissement du theme
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'theme.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
|
||||
// Version
|
||||
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
|
||||
|
||||
|
||||
/**
|
||||
* Import des polices de caractères
|
||||
* A partir du CDN
|
||||
* ou dans le dossier site/file/source/fonts
|
||||
* ou pas du tout si fonte webSafe
|
||||
*/
|
||||
|
||||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
// Fontes installées
|
||||
$fonts = [
|
||||
$this->getData(['theme', 'text', 'font']),
|
||||
$this->getData(['theme', 'title', 'font']),
|
||||
$this->getData(['theme', 'header', 'font']),
|
||||
$this->getData(['theme', 'menu', 'font']),
|
||||
$this->getData(['theme', 'footer', 'font'])
|
||||
];
|
||||
// Suppression des polices identiques
|
||||
$fonts = array_unique($fonts);
|
||||
|
||||
|
||||
/**
|
||||
* Charge les fontes
|
||||
*/
|
||||
foreach ($fonts as $fontId) {
|
||||
foreach (['websafe', 'imported', 'files'] as $typeFont) {
|
||||
if (isset($fontsAvailable[$typeFont][$fontId])) {
|
||||
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fond du body
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'body', 'backgroundColor']));
|
||||
// Body
|
||||
$css .= 'body{font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
|
||||
if ($themeBodyImage = $this->getData(['theme', 'body', 'image'])) {
|
||||
// Image dans html pour éviter les déformations.
|
||||
$css .= 'html {background-image:url("../file/source/' . $themeBodyImage . '");background-position:' . $this->getData(['theme', 'body', 'imagePosition']) . ';background-attachment:' . $this->getData(['theme', 'body', 'imageAttachment']) . ';background-size:' . $this->getData(['theme', 'body', 'imageSize']) . ';background-repeat:' . $this->getData(['theme', 'body', 'imageRepeat']) . '}';
|
||||
// Couleur du body transparente
|
||||
$css .= 'body {background-color: rgba(0,0,0,0)}';
|
||||
} else {
|
||||
// Pas d'image couleur du body
|
||||
$css .= 'html {background-color:' . $colors['normal'] . ';}';
|
||||
}
|
||||
// Icône BacktoTop
|
||||
$css .= '#backToTop {background-color:' . $this->getData(['theme', 'body', 'toTopbackgroundColor']) . ';color:' . $this->getData(['theme', 'body', 'toTopColor']) . ';}';
|
||||
// Site
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'text', 'linkColor']));
|
||||
$css .= 'a{color:' . $colors['normal'] . '}';
|
||||
// Couleurs de site dans TinyMCe
|
||||
$css .= 'div.mce-edit-area {font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
|
||||
// Site dans TinyMCE
|
||||
$css .= '.editorWysiwyg, .editorWysiwygComment {background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
|
||||
$css .= 'span.mce-text{background-color: unset !important;}';
|
||||
$css .= 'body,.row > div{font-size:' . $this->getData(['theme', 'text', 'fontSize']) . '}';
|
||||
$css .= 'body{color:' . $this->getData(['theme', 'text', 'textColor']) . '}';
|
||||
$css .= 'select,input[type=password],input[type=email],input[type=text],input[type=date],input[type=time],input[type=week],input[type=month],input[type=datetime-local],.inputFile,select,textarea{color:' . $this->getData(['theme', 'text', 'textColor']) . ';background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
|
||||
// spécifiques au module de blog
|
||||
$css .= '.blogDate {color:' . $this->getData(['theme', 'text', 'textColor']) . ';}.blogPicture img{border:1px solid ' . $this->getData(['theme', 'text', 'textColor']) . '; box-shadow: 1px 1px 5px ' . $this->getData(['theme', 'text', 'textColor']) . ';}';
|
||||
// Couleur fixée dans admin.css
|
||||
$css .= '.container {max-width:' . $this->getData(['theme', 'site', 'width']) . '}';
|
||||
$margin = $this->getData(['theme', 'site', 'margin']) ? '0' : '20px';
|
||||
// Marge supplémentaire lorsque le pied de page est fixe
|
||||
if (
|
||||
$this->getData(['theme', 'footer', 'fixed']) === true &&
|
||||
$this->getData(['theme', 'footer', 'position']) === 'body'
|
||||
) {
|
||||
|
||||
$marginBottomLarge = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 31) . 'px';
|
||||
$marginBottomSmall = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 93) . 'px';
|
||||
} else {
|
||||
$marginBottomSmall = $margin;
|
||||
$marginBottomLarge = $margin;
|
||||
}
|
||||
$css .= $this->getData(['theme', 'site', 'width']) === '100%'
|
||||
? '@media (min-width: 769px) {#site{margin:0 auto ' . $marginBottomLarge . ' 0 !important;}}@media (max-width: 768px) {#site{margin:0 auto ' . $marginBottomSmall . ' 0 !important;}}#site.light{margin:5% auto !important;} body{margin:0 auto !important;} #bar{margin:0 auto !important;} body > header{margin:0 auto !important;} body > nav {margin: 0 auto !important;} body > footer {margin:0 auto !important;}'
|
||||
: '@media (min-width: 769px) {#site{margin: ' . $margin . ' auto ' . $marginBottomLarge . ' auto !important;}}@media (max-width: 768px) {#site{margin: ' . $margin . ' auto ' . $marginBottomSmall . ' auto !important;}}#site.light{margin: 5% auto !important;} body{margin:0px 10px;} #bar{margin: 0 -10px;} body > header{margin: 0 -10px;} body > nav {margin: 0 -10px;} body > footer {margin: 0 -10px;} ';
|
||||
$css .= $this->getData(['theme', 'site', 'width']) === '750px'
|
||||
? '.button, button{font-size:0.8em;}'
|
||||
: '';
|
||||
$css .= '#site{background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';border-radius:' . $this->getData(['theme', 'site', 'radius']) . ';box-shadow:' . $this->getData(['theme', 'site', 'shadow']) . ' #212223;}';
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'button', 'backgroundColor']));
|
||||
$css .= '.speechBubble,.button,.button:hover,button[type=submit],.pagination a,.pagination a:hover,input[type=checkbox]:checked + label:before,input[type=radio]:checked + label:before,.helpContent{background-color:' . $colors['normal'] . ';color:' . $colors['text'] . '}';
|
||||
$css .= '.helpButton span{color:' . $colors['normal'] . '}';
|
||||
$css .= 'input[type=text]:hover,input[type=date]:hover,input[type=time]:hover,input[type=week]:hover,input[type=month]:hover,input[type=datetime-local]:hover,input[type=password]:hover,.inputFile:hover,select:hover,textarea:hover{border-color:' . $colors['normal'] . '}';
|
||||
$css .= '.speechBubble:before{border-color:' . $colors['normal'] . ' transparent transparent transparent}';
|
||||
$css .= '.button:hover,button[type=submit]:hover,.pagination a:hover,input[type=checkbox]:not(:active):checked:hover + label:before,input[type=checkbox]:active + label:before,input[type=radio]:checked:hover + label:before,input[type=radio]:not(:checked):active + label:before{background-color:' . $colors['darken'] . '}';
|
||||
$css .= '.helpButton span:hover{color:' . $colors['darken'] . '}';
|
||||
$css .= '.button:active,button[type=submit]:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}';
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor']));
|
||||
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'title', 'font'])] . ';font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
|
||||
$css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}';
|
||||
// Les blocs
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundColor']));
|
||||
$css .= '.block {border: 1px solid ' . $this->getdata(['theme', 'block', 'borderColor']) . ';}.block h4 {background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
|
||||
|
||||
// Bannière
|
||||
|
||||
// Eléments communs
|
||||
if ($this->getData(['theme', 'header', 'margin'])) {
|
||||
if ($this->getData(['theme', 'menu', 'position']) === 'site-first') {
|
||||
$css .= 'header{margin:0 20px}';
|
||||
} else {
|
||||
$css .= 'header{margin:20px 20px 0 20px}';
|
||||
}
|
||||
}
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'header', 'backgroundColor']));
|
||||
$css .= 'header{background-color:' . $colors['normal'] . ';}';
|
||||
|
||||
// Bannière de type papier peint
|
||||
if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper') {
|
||||
$css .= 'header{background-size:' . $this->getData(['theme', 'header', 'imageContainer']) . '}';
|
||||
$css .= 'header{background-color:' . $colors['normal'];
|
||||
|
||||
// Valeur de hauteur traditionnelle
|
||||
$css .= ';height:' . $this->getData(['theme', 'header', 'height']) . ';line-height:' . $this->getData(['theme', 'header', 'height']);
|
||||
|
||||
$css .= ';text-align:' . $this->getData(['theme', 'header', 'textAlign']) . '}';
|
||||
if ($themeHeaderImage = $this->getData(['theme', 'header', 'image'])) {
|
||||
$css .= 'header{background-image:url("../file/source/' . $themeHeaderImage . '");background-position:' . $this->getData(['theme', 'header', 'imagePosition']) . ';background-repeat:' . $this->getData(['theme', 'header', 'imageRepeat']) . '}';
|
||||
}
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'header', 'textColor']));
|
||||
$css .= 'header span{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'header', 'font'])] . ';font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}';
|
||||
}
|
||||
|
||||
// Bannière au Contenu HTML
|
||||
if ($this->getData(['theme', 'header', 'feature']) === 'feature') {
|
||||
// Hauteur de la taille du contenu perso
|
||||
$css .= 'header {height:' . $this->getData(['theme', 'header', 'height']) . '; min-height:' . $this->getData(['theme', 'header', 'height']) . ';overflow: hidden;}';
|
||||
}
|
||||
|
||||
// Menu
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'menu', 'backgroundColor']));
|
||||
$css .= 'nav,nav.navMain a{background-color:' . $colors['normal'] . '}';
|
||||
$css .= 'nav a,#toggle span,nav a:hover{color:' . $this->getData(['theme', 'menu', 'textColor']) . '}';
|
||||
$css .= 'nav a:hover{background-color:' . $colors['darken'] . '}';
|
||||
$css .= 'nav a.active{color:' . $this->getData(['theme', 'menu', 'activeTextColor']) . ';}';
|
||||
if ($this->getData(['theme', 'menu', 'activeColorAuto']) === true) {
|
||||
$css .= 'nav a.active{background-color:' . $colors['veryDarken'] . '}';
|
||||
} else {
|
||||
$css .= 'nav a.active{background-color:' . $this->getData(['theme', 'menu', 'activeColor']) . '}';
|
||||
}
|
||||
$css .= 'nav #burgerText{color:' . $colors['text'] . '}';
|
||||
// Sous menu
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'menu', 'backgroundColorSub']));
|
||||
$css .= 'nav .navSub a{background-color:' . $colors['normal'] . '}';
|
||||
$css .= 'nav .navMain a.active {border-radius:' . $this->getData(['theme', 'menu', 'radius']) . '}';
|
||||
$css .= '#menu{text-align:' . $this->getData(['theme', 'menu', 'textAlign']) . '}';
|
||||
if ($this->getData(['theme', 'menu', 'margin'])) {
|
||||
if (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'site-first'
|
||||
or $this->getData(['theme', 'menu', 'position']) === 'site-second'
|
||||
) {
|
||||
$css .= 'nav{padding:10px 10px 0 10px;}';
|
||||
} else {
|
||||
$css .= 'nav{padding:0 10px}';
|
||||
}
|
||||
} else {
|
||||
$css .= 'nav{margin:0}';
|
||||
}
|
||||
if (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'top'
|
||||
) {
|
||||
$css .= 'nav{padding:0 10px;}';
|
||||
}
|
||||
|
||||
$css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) . ';font-family:' . $fonts[$this->getData(['theme', 'menu', 'font'])] . ';font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}';
|
||||
// Pied de page
|
||||
$colors = helper::colorVariants($this->getData(['theme', 'footer', 'backgroundColor']));
|
||||
if ($this->getData(['theme', 'footer', 'margin'])) {
|
||||
$css .= 'footer{padding:0 20px;}';
|
||||
} else {
|
||||
$css .= 'footer{padding:0}';
|
||||
}
|
||||
|
||||
$css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:' . $fonts[$this->getData(['theme', 'footer', 'font'])] . ';font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}';
|
||||
$css .= 'footer {background-color:' . $colors['normal'] . ';color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
|
||||
//$css .= 'footer a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
|
||||
$css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
|
||||
|
||||
$css .= 'footer #footerbody > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
|
||||
$css .= '@media (max-width: 768px) {footer #footerbody > div { padding: 2px }}';
|
||||
$css .= '#footerSocials{text-align:' . $this->getData(['theme', 'footer', 'socialsAlign']) . '}';
|
||||
$css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}';
|
||||
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
|
||||
|
||||
// Enregistre la personnalisation
|
||||
$this->secure_file_put_contents(common::DATA_DIR . 'theme.css', $css);
|
||||
|
||||
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
|
||||
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||
header("Pragma: no-cache");
|
||||
}
|
||||
|
||||
// Check la version rafraichissement du theme admin
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
|
||||
|
||||
// Version
|
||||
$css = '/*' . md5(json_encode($this->getData(['admin']))) . '*/';
|
||||
|
||||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
/**
|
||||
* Import des polices de caractères
|
||||
* A partir du CDN ou dans le dossier site/file/source/fonts
|
||||
*/
|
||||
$fonts = [
|
||||
$this->getData(['admin', 'fontText']),
|
||||
$this->getData(['admin', 'fontTitle']),
|
||||
];
|
||||
// Suppression des polices identiques
|
||||
$fonts = array_unique($fonts);
|
||||
|
||||
/**
|
||||
* Charge les fontes
|
||||
*/
|
||||
foreach ($fonts as $fontId) {
|
||||
foreach (['websafe', 'imported', 'files'] as $typeFont) {
|
||||
if (isset($fontsAvailable[$typeFont][$fontId])) {
|
||||
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Thème Administration
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColor']));
|
||||
$css .= '#site{background-color:' . $colors['normal'] . ';}';
|
||||
$css .= 'p, div, label, select, input, table, span {font-family:' . $fonts[$this->getData(['admin', 'fontText'])] . '}';
|
||||
$css .= 'body,.row > div {font-size:' . $this->getData(['admin', 'fontSize']) . '}';
|
||||
$css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:' . $fonts[$this->getData(['admin', 'fontTitle'])] . ';color:' . $this->getData(['admin', 'colorTitle']) . ';}';
|
||||
$css .= '.container {max-width:' . $this->getData(['admin', 'width']) . '}';
|
||||
$margin = $this->getData(['theme', 'site', 'margin']) ? '0' : '20px';
|
||||
// Marge supplémentaire lorsque le pied de page est fixe
|
||||
if (
|
||||
$this->getData(['theme', 'footer', 'fixed']) === true &&
|
||||
$this->getData(['theme', 'footer', 'position']) === 'body'
|
||||
) {
|
||||
|
||||
$marginBottomLarge = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 31) . 'px';
|
||||
$marginBottomSmall = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 93) . 'px';
|
||||
} else {
|
||||
$marginBottomSmall = $margin;
|
||||
$marginBottomLarge = $margin;
|
||||
}
|
||||
$css .= $this->getData(['admin', 'width']) === '100%'
|
||||
? '@media (min-width: 769px) {#site{margin:0 auto ' . $marginBottomLarge . ' 0 !important;}}@media (max-width: 768px) {#site{margin:0 auto ' . $marginBottomSmall . ' 0 !important;}}#site.light{margin:5% auto !important;} body{margin:0 auto !important;} #bar{margin:0 auto !important;} body > header{margin:0 auto !important;} body > nav {margin: 0 auto !important;} body > footer {margin:0 auto !important;}'
|
||||
: '@media (min-width: 769px) {#site{margin: ' . $margin . ' auto ' . $marginBottomLarge . ' auto !important;}}@media (max-width: 768px) {#site{margin: ' . $margin . ' auto ' . $marginBottomSmall . ' auto !important;}}#site.light{margin: 5% auto !important;} body{margin:0px 10px;} #bar{margin: 0 -10px;} body > header{margin: 0 -10px;} body > nav {margin: 0 -10px;} body > footer {margin: 0 -10px;} ';
|
||||
$css .= $this->getData(['admin', 'width']) === '750px'
|
||||
? '.button, button{font-size:0.8em;}'
|
||||
: '';
|
||||
|
||||
// TinyMCE
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'colorText']));
|
||||
$css .= 'body:not(.editorWysiwyg), body:not(editorWysiwygComment),span .zwiico-help {color:' . $colors['normal'] . ';}';
|
||||
$css .= 'table thead tr, table thead tr .zwiico-help{ background-color:' . $colors['normal'] . '; color:' . $colors['text'] . ';}';
|
||||
$css .= 'table thead th { color:' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButton']));
|
||||
$css .= 'input[type=checkbox]:checked + label::before,.speechBubble{background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
|
||||
$css .= '.speechBubble::before {border-color:' . $colors['normal'] . ' transparent transparent transparent;}';
|
||||
$css .= '.button {background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}.button:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonGrey']));
|
||||
$css .= '.button.buttonGrey {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGrey:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonGrey:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonRed']));
|
||||
$css .= '.button.buttonRed {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonRed:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonRed:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonHelp']));
|
||||
$css .= '.button.buttonHelp {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonHelp:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonHelp:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonGreen']));
|
||||
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}';
|
||||
$colors = helper::colorVariants($this->getData(['admin', 'backgroundBlockColor']));
|
||||
$css .= '.buttonTab, .block {border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}.buttonTab, .block h4 {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
|
||||
$css .= 'table tr,input[type=email],input[type=date],input[type=time],input[type=month],input[type=week],input[type=datetime-local],input[type=text],input[type=password],select:not(#barSelectLanguage),select:not(#barSelectPage),textarea:not(.editorWysiwyg), textarea:not(.editorWysiwygComment),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}';
|
||||
// Bordure du contour TinyMCE
|
||||
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
|
||||
// Enregistre la personnalisation
|
||||
$this->secure_file_put_contents(common::DATA_DIR . 'admin.css', $css);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Auto-chargement des classes
|
||||
* @param string $className Nom de la classe à charger
|
||||
*/
|
||||
public static function autoload($className)
|
||||
{
|
||||
|
||||
$classPath = strtolower($className) . '/' . strtolower($className) . '.php';
|
||||
// Module du coeur
|
||||
if (is_readable('core/module/' . $classPath)) {
|
||||
require 'core/module/' . $classPath;
|
||||
}
|
||||
// Module
|
||||
elseif (is_readable(common::MODULE_DIR . $classPath)) {
|
||||
require common::MODULE_DIR . $classPath;
|
||||
}
|
||||
// Librairie
|
||||
elseif (is_readable('core/vendor/' . $classPath)) {
|
||||
require 'core/vendor/' . $classPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Routage des modules
|
||||
*/
|
||||
public function router()
|
||||
{
|
||||
|
||||
$layout = new layout($this);
|
||||
|
||||
// Installation
|
||||
if (
|
||||
$this->getData(['user']) === []
|
||||
and $this->getUrl(0) !== 'install'
|
||||
) {
|
||||
http_response_code(302);
|
||||
header('Location:' . helper::baseUrl() . 'install');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Journalisation
|
||||
$this->saveLog();
|
||||
|
||||
// Force la déconnexion des membres bannis ou d'une seconde session
|
||||
if (
|
||||
$this->isConnected() === true
|
||||
and ($this->getUser('group') === common::GROUP_BANNED
|
||||
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
|
||||
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
|
||||
)
|
||||
) {
|
||||
$user = new user;
|
||||
$user->logout();
|
||||
}
|
||||
// Mode maintenance
|
||||
if (
|
||||
$this->getData(['config', 'maintenance'])
|
||||
and in_array($this->getUrl(0), ['maintenance', 'user']) === false
|
||||
and $this->getUrl(1) !== 'login'
|
||||
and ($this->isConnected() === false
|
||||
or ($this->isConnected() === true
|
||||
and $this->getUser('group') < common::GROUP_ADMIN
|
||||
)
|
||||
)
|
||||
) {
|
||||
// Déconnexion
|
||||
$user = new user;
|
||||
$user->logout();
|
||||
// Redirection
|
||||
http_response_code(302);
|
||||
header('Location:' . helper::baseUrl() . 'maintenance');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Check l'accès à la page
|
||||
$access = null;
|
||||
if ($this->getData(['page', $this->getUrl(0)]) !== null) {
|
||||
if (
|
||||
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
|
||||
or ($this->isConnected() === true
|
||||
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * 10 + $this->getUser('profil')) >= ($this->getData(['page', $this->getUrl(0), 'group']) * 10 + $this->getData(['page', $this->getUrl(0), 'profil']))
|
||||
)
|
||||
) {
|
||||
$access = true;
|
||||
} else {
|
||||
if ($this->getUrl(0) === $this->getData(['locale', 'homePageId'])) {
|
||||
$access = 'login';
|
||||
} else {
|
||||
$access = false;
|
||||
}
|
||||
}
|
||||
// Empêcher l'accès aux pages désactivées par URL directe
|
||||
if (
|
||||
($this->getData(['page', $this->getUrl(0), 'disable']) === true
|
||||
and $this->isConnected() === false
|
||||
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') < common::GROUP_EDITOR
|
||||
)
|
||||
) {
|
||||
$access = false;
|
||||
}
|
||||
// Lève une erreur si l'url est celle d'une page avec des éléments surnuméraires https://www.site.fr/page/truc
|
||||
if (
|
||||
array_key_exists($this->getUrl(0), $this->getData(['page']))
|
||||
and $this->getUrl(1)
|
||||
and $this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
|
||||
) {
|
||||
$access = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contrôle si la page demandée est en édition ou accès à la gestion du site
|
||||
* conditions de blocage :
|
||||
* - Les deux utilisateurs qui accèdent à la même page sont différents
|
||||
* - les URLS sont identiques
|
||||
* - Une partie de l'URL fait partie de la liste de filtrage (édition d'un module etc..)
|
||||
* - L'édition est ouverte depuis un temps dépassé, on considère que la page est restée ouverte et qu'elle ne sera pas validée
|
||||
*/
|
||||
$accessInfo['userName'] = '';
|
||||
$accessInfo['pageId'] = '';
|
||||
if ($this->getData(['user'])) {
|
||||
foreach ($this->getData(['user']) as $userId => $userIds) {
|
||||
if (!is_null($this->getData(['user', $userId, 'accessUrl']))) {
|
||||
$t = explode('/', $this->getData(['user', $userId, 'accessUrl']));
|
||||
}
|
||||
if (
|
||||
$this->getUser('id') &&
|
||||
$userId !== $this->getUser('id') &&
|
||||
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
|
||||
array_intersect($t, common::$concurrentAccess) &&
|
||||
//array_intersect($t, common::$accessExclude) !== false &&
|
||||
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
|
||||
) {
|
||||
$access = false;
|
||||
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
|
||||
$accessInfo['pageId'] = end($t);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Accès concurrent stocke la page visitée
|
||||
if (
|
||||
$this->isConnected() === true
|
||||
&& $this->getUser('id')
|
||||
&& !$this->isPost()
|
||||
) {
|
||||
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()], false);
|
||||
$this->setData(['user', $this->getUser('id'), 'accessTimer', time()]);
|
||||
}
|
||||
// Breadcrumb
|
||||
$title = $this->getData(['page', $this->getUrl(0), 'title']);
|
||||
if (
|
||||
!empty($this->getData(['page', $this->getUrl(0), 'parentPageId'])) &&
|
||||
$this->getData(['page', $this->getUrl(0), 'breadCrumb'])
|
||||
) {
|
||||
$title = '<a href="' . helper::baseUrl() .
|
||||
$this->getData(['page', $this->getUrl(0), 'parentPageId']) .
|
||||
'">' .
|
||||
ucfirst($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'parentPageId']), 'title'])) .
|
||||
'</a> › ' .
|
||||
$this->getData(['page', $this->getUrl(0), 'title']);
|
||||
}
|
||||
|
||||
|
||||
// Importe le style de la page principale
|
||||
$inlineStyle[] = $this->getData(['page', $this->getUrl(0), 'css']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'css']);
|
||||
// Importe le script de la page principale
|
||||
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']);
|
||||
|
||||
// Importe le contenu, le CSS et le script des barres
|
||||
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']);
|
||||
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
|
||||
|
||||
|
||||
// Importe la page simple sans module ou avec un module inexistant
|
||||
if (
|
||||
$this->getData(['page', $this->getUrl(0)]) !== null
|
||||
and ($this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
|
||||
or !class_exists($this->getData(['page', $this->getUrl(0), 'moduleId']))
|
||||
)
|
||||
and $access
|
||||
) {
|
||||
|
||||
// Importe le CSS de la page principale
|
||||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
'content' => $this->getPage($this->getUrl(0), common::$siteContent),
|
||||
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
|
||||
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
|
||||
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
|
||||
'iconUrl' => $this->getData(['page', $this->getUrl(0), 'iconUrl']),
|
||||
'disable' => $this->getData(['page', $this->getUrl(0), 'disable']),
|
||||
'contentRight' => $contentRight,
|
||||
'contentLeft' => $contentLeft,
|
||||
'inlineStyle' => $inlineStyle,
|
||||
'inlineScript' => $inlineScript,
|
||||
]);
|
||||
|
||||
}
|
||||
// Importe le module
|
||||
else {
|
||||
// Id du module, et valeurs en sortie de la page s'il s'agit d'un module de page
|
||||
|
||||
if ($access and $this->getData(['page', $this->getUrl(0), 'moduleId'])) {
|
||||
$moduleId = $this->getData(['page', $this->getUrl(0), 'moduleId']);
|
||||
|
||||
// Construit un meta absent
|
||||
$metaDescription = $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog' && !empty($this->getUrl(1)) && in_array($this->getUrl(1), $this->getData(['module']))
|
||||
? strip_tags(substr($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'content']), 0, 159))
|
||||
: $this->getData(['page', $this->getUrl(0), 'metaDescription']);
|
||||
|
||||
// Importe le CSS de la page principale
|
||||
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
|
||||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
// Meta description = 160 premiers caractères de l'article
|
||||
'content' => $pageContent,
|
||||
'metaDescription' => $metaDescription,
|
||||
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
|
||||
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
|
||||
'iconUrl' => $this->getData(['page', $this->getUrl(0), 'iconUrl']),
|
||||
'disable' => $this->getData(['page', $this->getUrl(0), 'disable']),
|
||||
'contentRight' => $contentRight,
|
||||
'contentLeft' => $contentLeft,
|
||||
'inlineStyle' => $inlineStyle,
|
||||
'inlineScript' => $inlineScript,
|
||||
]);
|
||||
} else {
|
||||
$moduleId = $this->getUrl(0);
|
||||
$pageContent = '';
|
||||
}
|
||||
|
||||
// Check l'existence du module
|
||||
if (class_exists($moduleId)) {
|
||||
/** @var common $module */
|
||||
$module = new $moduleId;
|
||||
|
||||
// Check l'existence de l'action
|
||||
$action = '';
|
||||
$ignore = true;
|
||||
if (!is_null($this->getUrl(1))) {
|
||||
foreach (explode('-', $this->getUrl(1)) as $actionPart) {
|
||||
if ($ignore) {
|
||||
$action .= $actionPart;
|
||||
$ignore = false;
|
||||
} else {
|
||||
$action .= ucfirst($actionPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
$action = array_key_exists($action, $module::$actions) ? $action : 'index';
|
||||
if (array_key_exists($action, $module::$actions)) {
|
||||
$module->$action();
|
||||
$output = $module->output;
|
||||
// Check le groupe de l'utilisateur
|
||||
if (
|
||||
($module::$actions[$action] === common::GROUP_VISITOR
|
||||
or ($this->isConnected() === true
|
||||
and $this->getUser('group') >= $module::$actions[$action]
|
||||
and $this->getUser('permission', $moduleId, $action)
|
||||
)
|
||||
)
|
||||
and $output['access'] === true
|
||||
) {
|
||||
// Enregistrement du contenu de la méthode POST lorsqu'une notice est présente
|
||||
if (common::$inputNotices) {
|
||||
foreach ($_POST as $postId => $postValue) {
|
||||
if (is_array($postValue)) {
|
||||
foreach ($postValue as $subPostId => $subPostValue) {
|
||||
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
|
||||
}
|
||||
} else {
|
||||
common::$inputBefore[$postId] = $postValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sinon traitement des données de sortie qui requiert qu'aucune notice ne soit présente
|
||||
else {
|
||||
// Notification
|
||||
if ($output['notification']) {
|
||||
if ($output['state'] === true) {
|
||||
$notification = 'ZWII_NOTIFICATION_SUCCESS';
|
||||
} elseif ($output['state'] === false) {
|
||||
$notification = 'ZWII_NOTIFICATION_ERROR';
|
||||
} else {
|
||||
$notification = 'ZWII_NOTIFICATION_OTHER';
|
||||
}
|
||||
$_SESSION[$notification] = $output['notification'];
|
||||
}
|
||||
// Redirection
|
||||
if ($output['redirect']) {
|
||||
http_response_code(301);
|
||||
header('Location:' . $output['redirect']);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
// Données en sortie applicables même lorsqu'une notice est présente
|
||||
// Affichage
|
||||
if ($output['display']) {
|
||||
$this->addOutput([
|
||||
'display' => $output['display']
|
||||
]);
|
||||
}
|
||||
// Contenu brut
|
||||
if ($output['content']) {
|
||||
$this->addOutput([
|
||||
'content' => $output['content']
|
||||
]);
|
||||
}
|
||||
// Contenu par vue
|
||||
elseif ($output['view']) {
|
||||
// Chemin en fonction d'un module du coeur ou d'un module
|
||||
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : '';
|
||||
// CSS
|
||||
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
|
||||
if (file_exists($stylePath)) {
|
||||
$this->addOutput([
|
||||
'style' => file_get_contents($stylePath)
|
||||
]);
|
||||
}
|
||||
if ($output['style']) {
|
||||
$this->addOutput([
|
||||
'style' => file_get_contents($output['style'])
|
||||
]);
|
||||
}
|
||||
|
||||
// JS
|
||||
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
|
||||
if (file_exists($scriptPath)) {
|
||||
ob_start();
|
||||
include $scriptPath;
|
||||
$this->addOutput([
|
||||
'script' => ob_get_clean()
|
||||
]);
|
||||
}
|
||||
// Vue
|
||||
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
|
||||
if (file_exists($viewPath)) {
|
||||
ob_start();
|
||||
include $viewPath;
|
||||
$modpos = $this->getData(['page', $this->getUrl(0), 'modulePosition']);
|
||||
if ($modpos === 'top') {
|
||||
$this->addOutput([
|
||||
'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '')
|
||||
]);
|
||||
} elseif ($modpos === 'free' && strstr($pageContent, '[MODULE]')) {
|
||||
if (strstr($pageContent, '[MODULE]', true) === false) {
|
||||
$begin = strstr($pageContent, '[]', true);
|
||||
} else {
|
||||
$begin = strstr($pageContent, '[MODULE]', true);
|
||||
}
|
||||
if (strstr($pageContent, '[MODULE]') === false) {
|
||||
$end = strstr($pageContent, '[]');
|
||||
} else {
|
||||
$end = strstr($pageContent, '[MODULE]');
|
||||
}
|
||||
$cut = 8;
|
||||
$end = substr($end, -strlen($end) + $cut);
|
||||
$this->addOutput([
|
||||
'content' => ($output['showPageContent'] ? $begin : '') . ob_get_clean() . ($output['showPageContent'] ? $end : '')
|
||||
]);
|
||||
} else {
|
||||
$this->addOutput([
|
||||
'content' => ($output['showPageContent'] ? $pageContent : '') . ob_get_clean()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Librairies
|
||||
if ($output['vendor'] !== $this->output['vendor']) {
|
||||
$this->addOutput([
|
||||
'vendor' => array_merge($this->output['vendor'], $output['vendor'])
|
||||
]);
|
||||
}
|
||||
|
||||
if ($output['title'] !== null) {
|
||||
$this->addOutput([
|
||||
'title' => $output['title']
|
||||
]);
|
||||
}
|
||||
// Affiche le bouton d'édition de la page dans la barre de membre
|
||||
if ($output['showBarEditButton']) {
|
||||
$this->addOutput([
|
||||
'showBarEditButton' => $output['showBarEditButton']
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Erreur 403
|
||||
else {
|
||||
$access = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Erreurs
|
||||
if ($access === 'login') {
|
||||
http_response_code(302);
|
||||
header('Location:' . helper::baseUrl() . 'user/login/');
|
||||
exit();
|
||||
}
|
||||
if ($access === false) {
|
||||
http_response_code(403);
|
||||
if ($accessInfo['userName']) {
|
||||
$this->addOutput([
|
||||
'title' => 'Accès verrouillé',
|
||||
'content' => template::speech('<p>' . sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
|
||||
|
||||
]);
|
||||
} else {
|
||||
if (
|
||||
$this->getData(['locale', 'page403']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['locale', 'page403'])])
|
||||
) {
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['locale', 'page403']));
|
||||
} else {
|
||||
$this->addOutput([
|
||||
'title' => 'Accès interdit',
|
||||
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
|
||||
]);
|
||||
}
|
||||
}
|
||||
} elseif ($this->output['content'] === '') {
|
||||
http_response_code(404);
|
||||
// Pour éviter une 404, bascule dans l'espace correct si la page existe dans cette langue.
|
||||
// Parcourir les espaces
|
||||
foreach (common::$languages as $langId => $value) {
|
||||
;
|
||||
if (
|
||||
// l'espace existe
|
||||
is_dir(common::DATA_DIR . $langId) &&
|
||||
file_exists(common::DATA_DIR . $langId . '/page.json')
|
||||
) {
|
||||
// Lire les données des pages
|
||||
$pagesId = json_decode(file_get_contents(common::DATA_DIR . $langId . '/page.json'), true);
|
||||
if (
|
||||
// La page existe
|
||||
is_array($pagesId['page']) &&
|
||||
array_key_exists($this->getUrl(0), $pagesId['page'])
|
||||
) {
|
||||
// Basculer
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $langId;
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
$this->getData(['locale', 'page404']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['locale', 'page404'])])
|
||||
) {
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['locale', 'page404']));
|
||||
} else {
|
||||
$this->addOutput([
|
||||
'title' => 'Page indisponible',
|
||||
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Mise en forme des métas
|
||||
if ($this->output['metaTitle'] === '') {
|
||||
if ($this->output['title']) {
|
||||
$this->addOutput([
|
||||
'metaTitle' => strip_tags($this->output['title']) . ' - ' . $this->getData(['locale', 'title'])
|
||||
]);
|
||||
} else {
|
||||
$this->addOutput([
|
||||
'metaTitle' => $this->getData(['locale', 'title'])
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($this->output['metaDescription'] === '') {
|
||||
$this->addOutput([
|
||||
'metaDescription' => $this->getData(['locale', 'metaDescription'])
|
||||
]);
|
||||
}
|
||||
switch ($this->output['display']) {
|
||||
// Layout brut
|
||||
case common::DISPLAY_RAW:
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout vide
|
||||
case common::DISPLAY_LAYOUT_BLANK:
|
||||
require 'core/layout/blank.php';
|
||||
break;
|
||||
// Affichage en JSON
|
||||
case common::DISPLAY_JSON:
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($this->output['content']);
|
||||
break;
|
||||
// RSS feed
|
||||
case common::DISPLAY_RSS:
|
||||
header('Content-type: application/rss+xml; charset=UTF-8');
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout allégé
|
||||
case common::DISPLAY_LAYOUT_LIGHT:
|
||||
ob_start();
|
||||
require 'core/layout/light.php';
|
||||
$content = ob_get_clean();
|
||||
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués
|
||||
$content = mb_convert_encoding($content, 'UTF-8', 'UTF-8');
|
||||
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles
|
||||
$content = preg_replace('/[\t ]+/u', ' ', $content);
|
||||
echo $content;
|
||||
break;
|
||||
// Layout principal
|
||||
case common::DISPLAY_LAYOUT_MAIN:
|
||||
ob_start();
|
||||
require 'core/layout/main.php';
|
||||
$content = ob_get_clean();
|
||||
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués
|
||||
$content = mb_convert_encoding($content, 'UTF-8', 'UTF-8');
|
||||
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles
|
||||
$content = preg_replace('/[\t ]+/u', ' ', $content);
|
||||
echo $content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
36
core/class/sitemap/FileSystem.class.php
Normal file
36
core/class/sitemap/FileSystem.class.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Icamys\SitemapGenerator;
|
||||
|
||||
class FileSystem
|
||||
{
|
||||
public function file_get_contents($filepath)
|
||||
{
|
||||
return file_get_contents($filepath);
|
||||
}
|
||||
|
||||
public function file_put_contents($filepath, $content, $flags = 0)
|
||||
{
|
||||
return file_put_contents($filepath, $content, $flags);
|
||||
}
|
||||
|
||||
public function file_exists($filepath)
|
||||
{
|
||||
return file_exists($filepath);
|
||||
}
|
||||
|
||||
public function rename($oldname, $newname)
|
||||
{
|
||||
return rename($oldname, $newname);
|
||||
}
|
||||
|
||||
public function copy($source, $destination)
|
||||
{
|
||||
return copy($source, $destination);
|
||||
}
|
||||
|
||||
public function unlink($filepath)
|
||||
{
|
||||
return unlink($filepath);
|
||||
}
|
||||
}
|
36
core/class/sitemap/Runtime.class.php
Normal file
36
core/class/sitemap/Runtime.class.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Icamys\SitemapGenerator;
|
||||
|
||||
class Runtime
|
||||
{
|
||||
public function extension_loaded($extname)
|
||||
{
|
||||
return extension_loaded($extname);
|
||||
}
|
||||
|
||||
public function is_writable($filepath)
|
||||
{
|
||||
return is_writable($filepath);
|
||||
}
|
||||
|
||||
public function curl_init($url)
|
||||
{
|
||||
return curl_init($url);
|
||||
}
|
||||
|
||||
public function curl_setopt($handle, $option, $value)
|
||||
{
|
||||
return curl_setopt($handle, $option, $value);
|
||||
}
|
||||
|
||||
public function curl_exec($handle)
|
||||
{
|
||||
return curl_exec($handle);
|
||||
}
|
||||
|
||||
public function curl_getinfo($handle, $option = null)
|
||||
{
|
||||
return curl_getinfo($handle, $option);
|
||||
}
|
||||
}
|
715
core/class/sitemap/SitemapGenerator.class.php
Normal file
715
core/class/sitemap/SitemapGenerator.class.php
Normal file
@ -0,0 +1,715 @@
|
||||
<?php
|
||||
|
||||
namespace Icamys\SitemapGenerator;
|
||||
|
||||
use BadMethodCallException;
|
||||
use DateTime;
|
||||
use Icamys\SitemapGenerator\Extensions\GoogleVideoExtension;
|
||||
use InvalidArgumentException;
|
||||
use OutOfRangeException;
|
||||
use RuntimeException;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* Class SitemapGenerator
|
||||
* @package Icamys\SitemapGenerator
|
||||
*/
|
||||
class SitemapGenerator
|
||||
{
|
||||
/**
|
||||
* Max size of a sitemap according to spec.
|
||||
* @see https://www.sitemaps.org/protocol.html
|
||||
*/
|
||||
private const MAX_FILE_SIZE = 52428800;
|
||||
|
||||
/**
|
||||
* Max number of urls per sitemap according to spec.
|
||||
* @see https://www.sitemaps.org/protocol.html
|
||||
*/
|
||||
private const MAX_URLS_PER_SITEMAP = 50000;
|
||||
|
||||
/**
|
||||
* Max number of sitemaps per index file according to spec.
|
||||
* @see http://www.sitemaps.org/protocol.html
|
||||
*/
|
||||
private const MAX_SITEMAPS_PER_INDEX = 50000;
|
||||
|
||||
/**
|
||||
* Total max number of URLs.
|
||||
*/
|
||||
private const TOTAL_MAX_URLS = self::MAX_URLS_PER_SITEMAP * self::MAX_SITEMAPS_PER_INDEX;
|
||||
|
||||
/**
|
||||
* Max url length according to spec.
|
||||
* @see https://www.sitemaps.org/protocol.html#xmlTagDefinitions
|
||||
*/
|
||||
private const MAX_URL_LEN = 2048;
|
||||
|
||||
/**
|
||||
* Robots file name
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
private $robotsFileName = "robots.txt";
|
||||
/**
|
||||
* Name of sitemap file
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
private $sitemapFileName = "sitemap.xml";
|
||||
/**
|
||||
* Name of sitemap index file
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
private $sitemapIndexFileName = "sitemap-index.xml";
|
||||
/**
|
||||
* Quantity of URLs per single sitemap file.
|
||||
* If Your links are very long, sitemap file can be bigger than 10MB,
|
||||
* in this case use smaller value.
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
private $maxUrlsPerSitemap = self::MAX_URLS_PER_SITEMAP;
|
||||
/**
|
||||
* If true, two sitemap files (.xml and .xml.gz) will be created and added to robots.txt.
|
||||
* If true, .gz file will be submitted to search engines.
|
||||
* If quantity of URLs will be bigger than 50.000, option will be ignored,
|
||||
* all sitemap files except sitemap index will be compressed.
|
||||
* @var bool
|
||||
* @access public
|
||||
*/
|
||||
private $isCompressionEnabled = false;
|
||||
/**
|
||||
* URL to Your site.
|
||||
* Script will use it to send sitemaps to search engines.
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $baseURL;
|
||||
/**
|
||||
* Base path. Relative to script location.
|
||||
* Use this if Your sitemap and robots files should be stored in other
|
||||
* directory then script.
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $basePath;
|
||||
/**
|
||||
* Version of this class
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $classVersion = "4.3.1";
|
||||
/**
|
||||
* Search engines URLs
|
||||
* @var array of strings
|
||||
* @access private
|
||||
*/
|
||||
private $searchEngines = [
|
||||
[
|
||||
"http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=USERID&url=",
|
||||
"http://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=",
|
||||
],
|
||||
"http://www.google.com/ping?sitemap=",
|
||||
"http://submissions.ask.com/ping?sitemap=",
|
||||
"http://www.bing.com/ping?sitemap=",
|
||||
"http://www.webmaster.yandex.ru/ping?sitemap=",
|
||||
];
|
||||
/**
|
||||
* Array with urls
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $urls;
|
||||
/**
|
||||
* Lines for robots.txt file that are written if file does not exist
|
||||
* @var array
|
||||
*/
|
||||
private $sampleRobotsLines = [
|
||||
"User-agent: *",
|
||||
"Disallow: /",
|
||||
"User-agent: Googlebot",
|
||||
"Allow: /",
|
||||
"User-agent: bingbot",
|
||||
"Allow: /",
|
||||
"User-agent: Slurp",
|
||||
"Allow: /",
|
||||
"User-agent: DuckDuckBot",
|
||||
"Allow: /",
|
||||
"User-agent: Baiduspider",
|
||||
"Allow: /"
|
||||
];
|
||||
/**
|
||||
* @var array list of valid changefreq values according to the spec
|
||||
*/
|
||||
private $validChangefreqValues = [
|
||||
'always',
|
||||
'hourly',
|
||||
'daily',
|
||||
'weekly',
|
||||
'monthly',
|
||||
'yearly',
|
||||
'never',
|
||||
];
|
||||
/**
|
||||
* @var float[] list of valid priority values according to the spec
|
||||
*/
|
||||
private $validPriorities = [
|
||||
0.0,
|
||||
0.1,
|
||||
0.2,
|
||||
0.3,
|
||||
0.4,
|
||||
0.5,
|
||||
0.6,
|
||||
0.7,
|
||||
0.8,
|
||||
0.9,
|
||||
1.0,
|
||||
];
|
||||
/**
|
||||
* @var FileSystem object used to communicate with file system
|
||||
*/
|
||||
private $fs;
|
||||
/**
|
||||
* @var Runtime object used to communicate with runtime
|
||||
*/
|
||||
private $runtime;
|
||||
|
||||
/**
|
||||
* @var XMLWriter Used for writing xml to files
|
||||
*/
|
||||
private $xmlWriter;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $flushedSitemapFilenameFormat;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $flushedSitemapSize = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $flushedSitemapCounter = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $flushedSitemaps = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isSitemapStarted = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $totalUrlCount = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $urlsetClosingTagLen = 10; // strlen("</urlset>\n")
|
||||
private $sitemapUrlCount = 0;
|
||||
private $generatedFiles = [];
|
||||
|
||||
/**
|
||||
* @param string $baseURL You site URL
|
||||
* @param string $basePath Relative path where sitemap and robots should be stored.
|
||||
* @param FileSystem|null $fs
|
||||
* @param Runtime|null $runtime
|
||||
*/
|
||||
public function __construct(string $baseURL, string $basePath = "", FileSystem $fs = null, Runtime $runtime = null)
|
||||
{
|
||||
$this->urls = [];
|
||||
$this->baseURL = rtrim($baseURL, '/');
|
||||
|
||||
if ($fs === null) {
|
||||
$this->fs = new FileSystem();
|
||||
} else {
|
||||
$this->fs = $fs;
|
||||
}
|
||||
|
||||
if ($runtime === null) {
|
||||
$this->runtime = new Runtime();
|
||||
} else {
|
||||
$this->runtime = $runtime;
|
||||
}
|
||||
|
||||
if ($this->runtime->is_writable($basePath) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('the provided basePath (%s) should be a writable directory,', $basePath) .
|
||||
' please check its existence and permissions'
|
||||
);
|
||||
}
|
||||
if (strlen($basePath) > 0 && substr($basePath, -1) != DIRECTORY_SEPARATOR) {
|
||||
$basePath = $basePath . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
$this->basePath = $basePath;
|
||||
|
||||
$this->xmlWriter = $this->createXmlWriter();
|
||||
$this->flushedSitemapFilenameFormat = sprintf("sm-%%d-%d.xml", time());
|
||||
}
|
||||
|
||||
private function createXmlWriter(): XMLWriter
|
||||
{
|
||||
$w = new XMLWriter();
|
||||
$w->openMemory();
|
||||
$w->setIndent(true);
|
||||
return $w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return SitemapGenerator
|
||||
*/
|
||||
public function setSitemapFilename(string $filename = ''): SitemapGenerator
|
||||
{
|
||||
if (strlen($filename) === 0) {
|
||||
throw new InvalidArgumentException('sitemap filename should not be empty');
|
||||
}
|
||||
if (pathinfo($filename, PATHINFO_EXTENSION) !== 'xml') {
|
||||
throw new InvalidArgumentException('sitemap filename should have *.xml extension');
|
||||
}
|
||||
$this->sitemapFileName = $filename;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return $this
|
||||
*/
|
||||
public function setSitemapIndexFilename(string $filename = ''): SitemapGenerator
|
||||
{
|
||||
if (strlen($filename) === 0) {
|
||||
throw new InvalidArgumentException('filename should not be empty');
|
||||
}
|
||||
$this->sitemapIndexFileName = $filename;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return $this
|
||||
*/
|
||||
public function setRobotsFileName(string $filename): SitemapGenerator
|
||||
{
|
||||
if (strlen($filename) === 0) {
|
||||
throw new InvalidArgumentException('filename should not be empty');
|
||||
}
|
||||
$this->robotsFileName = $filename;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxUrlsPerSitemap(int $value): SitemapGenerator
|
||||
{
|
||||
if ($value < 1 || self::MAX_URLS_PER_SITEMAP < $value) {
|
||||
throw new OutOfRangeException(
|
||||
sprintf('value %d is out of range 1-%d', $value, self::MAX_URLS_PER_SITEMAP)
|
||||
);
|
||||
}
|
||||
$this->maxUrlsPerSitemap = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableCompression(): SitemapGenerator
|
||||
{
|
||||
$this->isCompressionEnabled = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function disableCompression(): SitemapGenerator
|
||||
{
|
||||
$this->isCompressionEnabled = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isCompressionEnabled(): bool
|
||||
{
|
||||
return $this->isCompressionEnabled;
|
||||
}
|
||||
|
||||
public function validate(
|
||||
string $path,
|
||||
DateTime $lastModified = null,
|
||||
string $changeFrequency = null,
|
||||
float $priority = null,
|
||||
array $alternates = null,
|
||||
array $extensions = [])
|
||||
{
|
||||
if (!(1 <= mb_strlen($path) && mb_strlen($path) <= self::MAX_URL_LEN)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf("The urlPath argument length must be between 1 and %d.", self::MAX_URL_LEN)
|
||||
);
|
||||
}
|
||||
if ($changeFrequency !== null && !in_array($changeFrequency, $this->validChangefreqValues)) {
|
||||
throw new InvalidArgumentException(
|
||||
'The change frequency argument should be one of: %s' . implode(',', $this->validChangefreqValues)
|
||||
);
|
||||
}
|
||||
if ($priority !== null && !in_array($priority, $this->validPriorities)) {
|
||||
throw new InvalidArgumentException("Priority argument should be a float number in the range [0.0..1.0]");
|
||||
}
|
||||
if ($extensions !== null && isset($extensions['google_video'])) {
|
||||
GoogleVideoExtension::validate($this->baseURL . $path, $extensions['google_video']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add url components.
|
||||
* Instead of storing all urls in the memory, the generator will flush sets of added urls
|
||||
* to the temporary files created on your disk.
|
||||
* The file format is 'sm-{index}-{timestamp}.xml'
|
||||
* @param string $path
|
||||
* @param DateTime|null $lastModified
|
||||
* @param string|null $changeFrequency
|
||||
* @param float|null $priority
|
||||
* @param array|null $alternates
|
||||
* @param array $extensions
|
||||
* @return $this
|
||||
*/
|
||||
public function addURL(
|
||||
string $path,
|
||||
DateTime $lastModified = null,
|
||||
string $changeFrequency = null,
|
||||
float $priority = null,
|
||||
array $alternates = null,
|
||||
array $extensions = []
|
||||
): SitemapGenerator
|
||||
{
|
||||
$this->validate($path, $lastModified, $changeFrequency, $priority, $alternates, $extensions);
|
||||
|
||||
if ($this->totalUrlCount >= self::TOTAL_MAX_URLS) {
|
||||
throw new OutOfRangeException(
|
||||
sprintf("Max url limit reached (%d)", self::TOTAL_MAX_URLS)
|
||||
);
|
||||
}
|
||||
if ($this->isSitemapStarted === false) {
|
||||
$this->writeSitemapStart();
|
||||
}
|
||||
|
||||
$this->writeSitemapUrl($this->baseURL . $path, $lastModified, $changeFrequency, $priority, $alternates, $extensions);
|
||||
|
||||
if ($this->totalUrlCount % 1000 === 0 || $this->sitemapUrlCount >= $this->maxUrlsPerSitemap) {
|
||||
$this->flushWriter();
|
||||
}
|
||||
|
||||
if ($this->sitemapUrlCount === $this->maxUrlsPerSitemap) {
|
||||
$this->writeSitemapEnd();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function writeSitemapStart()
|
||||
{
|
||||
$this->xmlWriter->startDocument("1.0", "UTF-8");
|
||||
$this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this)));
|
||||
$this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion));
|
||||
$this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c')));
|
||||
$this->xmlWriter->startElement('urlset');
|
||||
$this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
|
||||
$this->xmlWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
|
||||
$this->xmlWriter->writeAttribute('xmlns:video', 'http://www.google.com/schemas/sitemap-video/1.1');
|
||||
$this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
||||
$this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
|
||||
$this->isSitemapStarted = true;
|
||||
}
|
||||
|
||||
private function writeSitemapUrl($loc, $lastModified, $changeFrequency, $priority, $alternates, $extensions)
|
||||
{
|
||||
$this->xmlWriter->startElement('url');
|
||||
$this->xmlWriter->writeElement('loc', htmlspecialchars($loc, ENT_QUOTES));
|
||||
|
||||
if ($lastModified !== null) {
|
||||
$this->xmlWriter->writeElement('lastmod', $lastModified->format(DateTime::ATOM));
|
||||
}
|
||||
|
||||
if ($changeFrequency !== null) {
|
||||
$this->xmlWriter->writeElement('changefreq', $changeFrequency);
|
||||
}
|
||||
|
||||
if ($priority !== null) {
|
||||
$this->xmlWriter->writeElement('priority', number_format($priority, 1, ".", ""));
|
||||
}
|
||||
|
||||
if (is_array($alternates) && count($alternates) > 0) {
|
||||
foreach ($alternates as $alternate) {
|
||||
if (is_array($alternate) && isset($alternate['hreflang']) && isset($alternate['href'])) {
|
||||
$this->xmlWriter->startElement('xhtml:link');
|
||||
$this->xmlWriter->writeAttribute('rel', 'alternate');
|
||||
$this->xmlWriter->writeAttribute('hreflang', $alternate['hreflang']);
|
||||
$this->xmlWriter->writeAttribute('href', $alternate['href']);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($extensions as $extName => $extFields) {
|
||||
if ($extName === 'google_video') {
|
||||
GoogleVideoExtension::writeVideoTag($this->xmlWriter, $loc, $extFields);
|
||||
}
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement(); // url
|
||||
$this->sitemapUrlCount++;
|
||||
$this->totalUrlCount++;
|
||||
}
|
||||
|
||||
private function flushWriter()
|
||||
{
|
||||
$targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter);
|
||||
$flushedString = $this->xmlWriter->outputMemory(true);
|
||||
$flushedStringLen = mb_strlen($flushedString);
|
||||
|
||||
if ($flushedStringLen === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->flushedSitemapSize += $flushedStringLen;
|
||||
|
||||
if ($this->flushedSitemapSize > self::MAX_FILE_SIZE - $this->urlsetClosingTagLen) {
|
||||
$this->writeSitemapEnd();
|
||||
$this->writeSitemapStart();
|
||||
}
|
||||
$this->fs->file_put_contents($targetSitemapFilepath, $flushedString, FILE_APPEND);
|
||||
}
|
||||
|
||||
private function writeSitemapEnd()
|
||||
{
|
||||
$targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter);
|
||||
$this->xmlWriter->endElement(); // urlset
|
||||
$this->xmlWriter->endDocument();
|
||||
$this->fs->file_put_contents($targetSitemapFilepath, $this->xmlWriter->flush(true), FILE_APPEND);
|
||||
$this->isSitemapStarted = false;
|
||||
$this->flushedSitemaps[] = $targetSitemapFilepath;
|
||||
$this->flushedSitemapCounter++;
|
||||
$this->sitemapUrlCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush all stored urls from memory to the disk and close all necessary tags.
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->flushWriter();
|
||||
if ($this->isSitemapStarted) {
|
||||
$this->writeSitemapEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move flushed files to their final location. Compress if necessary.
|
||||
*/
|
||||
public function finalize()
|
||||
{
|
||||
$this->generatedFiles = [];
|
||||
|
||||
if (count($this->flushedSitemaps) === 1) {
|
||||
$targetSitemapFilename = $this->sitemapFileName;
|
||||
if ($this->isCompressionEnabled) {
|
||||
$targetSitemapFilename .= '.gz';
|
||||
}
|
||||
|
||||
$targetSitemapFilepath = $this->basePath . $targetSitemapFilename;
|
||||
|
||||
if ($this->isCompressionEnabled) {
|
||||
$this->fs->copy($this->flushedSitemaps[0], 'compress.zlib://' . $targetSitemapFilepath);
|
||||
$this->fs->unlink($this->flushedSitemaps[0]);
|
||||
} else {
|
||||
$this->fs->rename($this->flushedSitemaps[0], $targetSitemapFilepath);
|
||||
}
|
||||
$this->generatedFiles['sitemaps_location'] = [$targetSitemapFilepath];
|
||||
$this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $targetSitemapFilename;
|
||||
} else if (count($this->flushedSitemaps) > 1) {
|
||||
$ext = '.' . pathinfo($this->sitemapFileName, PATHINFO_EXTENSION);
|
||||
$targetExt = $ext;
|
||||
if ($this->isCompressionEnabled) {
|
||||
$targetExt .= '.gz';
|
||||
}
|
||||
|
||||
$sitemapsUrls = [];
|
||||
$targetSitemapFilepaths = [];
|
||||
foreach ($this->flushedSitemaps as $i => $flushedSitemap) {
|
||||
$targetSitemapFilename = str_replace($ext, ($i + 1) . $targetExt, $this->sitemapFileName);
|
||||
$targetSitemapFilepath = $this->basePath . $targetSitemapFilename;
|
||||
|
||||
if ($this->isCompressionEnabled) {
|
||||
$this->fs->copy($flushedSitemap, 'compress.zlib://' . $targetSitemapFilepath);
|
||||
$this->fs->unlink($flushedSitemap);
|
||||
} else {
|
||||
$this->fs->rename($flushedSitemap, $targetSitemapFilepath);
|
||||
}
|
||||
$sitemapsUrls[] = htmlspecialchars($this->baseURL . '/' . $targetSitemapFilename, ENT_QUOTES);
|
||||
$targetSitemapFilepaths[] = $targetSitemapFilepath;
|
||||
}
|
||||
|
||||
$targetSitemapIndexFilepath = $this->basePath . $this->sitemapIndexFileName;
|
||||
$this->createSitemapIndex($sitemapsUrls, $targetSitemapIndexFilepath);
|
||||
$this->generatedFiles['sitemaps_location'] = $targetSitemapFilepaths;
|
||||
$this->generatedFiles['sitemaps_index_location'] = $targetSitemapIndexFilepath;
|
||||
$this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $this->sitemapIndexFileName;
|
||||
} else {
|
||||
throw new RuntimeException('failed to finalize, please add urls and flush first');
|
||||
}
|
||||
}
|
||||
|
||||
private function createSitemapIndex($sitemapsUrls, $sitemapIndexFileName)
|
||||
{
|
||||
$this->xmlWriter->flush(true);
|
||||
$this->writeSitemapIndexStart();
|
||||
foreach ($sitemapsUrls as $sitemapsUrl) {
|
||||
$this->writeSitemapIndexUrl($sitemapsUrl);
|
||||
}
|
||||
$this->writeSitemapIndexEnd();
|
||||
$this->fs->file_put_contents(
|
||||
$sitemapIndexFileName,
|
||||
$this->xmlWriter->flush(true),
|
||||
FILE_APPEND
|
||||
);
|
||||
}
|
||||
|
||||
private function writeSitemapIndexStart()
|
||||
{
|
||||
$this->xmlWriter->startDocument("1.0", "UTF-8");
|
||||
$this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this)));
|
||||
$this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion));
|
||||
$this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c')));
|
||||
$this->xmlWriter->startElement('sitemapindex');
|
||||
$this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
|
||||
$this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
||||
$this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
|
||||
}
|
||||
|
||||
private function writeSitemapIndexUrl($url)
|
||||
{
|
||||
$this->xmlWriter->startElement('sitemap');
|
||||
$this->xmlWriter->writeElement('loc', htmlspecialchars($url, ENT_QUOTES));
|
||||
$this->xmlWriter->writeElement('lastmod', date('c'));
|
||||
$this->xmlWriter->endElement(); // sitemap
|
||||
}
|
||||
|
||||
private function writeSitemapIndexEnd()
|
||||
{
|
||||
$this->xmlWriter->endElement(); // sitemapindex
|
||||
$this->xmlWriter->endDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Array of previously generated files
|
||||
*/
|
||||
public function getGeneratedFiles(): array
|
||||
{
|
||||
return $this->generatedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will inform search engines about newly created sitemaps.
|
||||
* Google, Ask, Bing and Yahoo will be noticed.
|
||||
* If You don't pass yahooAppId, Yahoo still will be informed,
|
||||
* but this method can be used once per day. If You will do this often,
|
||||
* message that limit was exceeded will be returned from Yahoo.
|
||||
* @param string $yahooAppId Your site Yahoo appid.
|
||||
* @return array of messages and http codes from each search engine
|
||||
* @access public
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function submitSitemap($yahooAppId = null): array
|
||||
{
|
||||
if (count($this->generatedFiles) === 0) {
|
||||
throw new BadMethodCallException("To update robots.txt, call finalize() first.");
|
||||
}
|
||||
if (!$this->runtime->extension_loaded('curl')) {
|
||||
throw new BadMethodCallException("cURL extension is needed to do submission.");
|
||||
}
|
||||
$searchEngines = $this->searchEngines;
|
||||
$searchEngines[0] = isset($yahooAppId) ?
|
||||
str_replace("USERID", $yahooAppId, $searchEngines[0][0]) :
|
||||
$searchEngines[0][1];
|
||||
$result = [];
|
||||
for ($i = 0; $i < count($searchEngines); $i++) {
|
||||
$submitUrl = $searchEngines[$i] . htmlspecialchars($this->generatedFiles['sitemaps_index_url'], ENT_QUOTES);
|
||||
$submitSite = $this->runtime->curl_init($submitUrl);
|
||||
$this->runtime->curl_setopt($submitSite, CURLOPT_RETURNTRANSFER, true);
|
||||
$responseContent = $this->runtime->curl_exec($submitSite);
|
||||
$response = $this->runtime->curl_getinfo($submitSite);
|
||||
$submitSiteShort = array_reverse(explode(".", parse_url($searchEngines[$i], PHP_URL_HOST)));
|
||||
$result[] = [
|
||||
"site" => $submitSiteShort[1] . "." . $submitSiteShort[0],
|
||||
"fullsite" => $submitUrl,
|
||||
"http_code" => $response['http_code'],
|
||||
"message" => str_replace("\n", " ", strip_tags($responseContent)),
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds sitemap url to robots.txt file located in basePath.
|
||||
* If robots.txt file exists,
|
||||
* the function will append sitemap url to file.
|
||||
* If robots.txt does not exist,
|
||||
* the function will create new robots.txt file with sample content and sitemap url.
|
||||
* @access public
|
||||
* @throws BadMethodCallException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function updateRobots(): SitemapGenerator
|
||||
{
|
||||
if (count($this->generatedFiles) === 0) {
|
||||
throw new BadMethodCallException("To update robots.txt, call finalize() first.");
|
||||
}
|
||||
|
||||
$robotsFilePath = $this->basePath . $this->robotsFileName;
|
||||
|
||||
$robotsFileContent = $this->createNewRobotsContentFromFile($robotsFilePath);
|
||||
|
||||
$this->fs->file_put_contents($robotsFilePath, $robotsFileContent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filepath
|
||||
* @return string
|
||||
*/
|
||||
private function createNewRobotsContentFromFile($filepath): string
|
||||
{
|
||||
if ($this->fs->file_exists($filepath)) {
|
||||
$robotsFileContent = "";
|
||||
$robotsFile = explode(PHP_EOL, $this->fs->file_get_contents($filepath));
|
||||
foreach ($robotsFile as $key => $value) {
|
||||
if (substr($value, 0, 8) == 'Sitemap:') {
|
||||
unset($robotsFile[$key]);
|
||||
} else {
|
||||
$robotsFileContent .= $value . PHP_EOL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$robotsFileContent = $this->getSampleRobotsContent();
|
||||
}
|
||||
|
||||
$robotsFileContent .= "Sitemap: {$this->generatedFiles['sitemaps_index_url']}";
|
||||
|
||||
return $robotsFileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
private function getSampleRobotsContent(): string
|
||||
{
|
||||
return implode(PHP_EOL, $this->sampleRobotsLines) . PHP_EOL;
|
||||
}
|
||||
}
|
217
core/class/strftime/php-8.1-strftime.class.php
Normal file
217
core/class/strftime/php-8.1-strftime.class.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
namespace PHP81_BC;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use IntlDateFormatter;
|
||||
use IntlGregorianCalendar;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Locale-formatted PHP81_BC\PHP81_BC\strftime using IntlDateFormatter (PHP 8.1 compatible)
|
||||
* This provides a cross-platform alternative to PHP81_BC\PHP81_BC\strftime() for when it will be removed from PHP.
|
||||
* Note that output can be slightly different between libc sprintf and this function as it is using ICU.
|
||||
*
|
||||
* Usage:
|
||||
* use function \PHP81_BC\PHP81_BC\PHP81_BC\strftime;
|
||||
* echo PHP81_BC\PHP81_BC\strftime('%A %e %B %Y %X', new \DateTime('2021-09-28 00:00:00'), 'fr_FR');
|
||||
*
|
||||
* Original use:
|
||||
* \setlocale(LC_TIME, 'fr_FR.UTF-8');
|
||||
* echo \PHP81_BC\PHP81_BC\strftime('%A %e %B %Y %X', strtotime('2021-09-28 00:00:00'));
|
||||
*
|
||||
* @param string $format Date format
|
||||
* @param integer|string|DateTime $timestamp Timestamp
|
||||
* @return string
|
||||
* @author BohwaZ <https://bohwaz.net/>
|
||||
*/
|
||||
function strftime (string $format, $timestamp = null, ?string $locale = null) : string {
|
||||
if (!($timestamp instanceof DateTimeInterface)) {
|
||||
$timestamp = is_int($timestamp) ? '@' . $timestamp : (string) $timestamp;
|
||||
|
||||
try {
|
||||
$timestamp = new DateTime($timestamp);
|
||||
} catch (Exception $e) {
|
||||
throw new InvalidArgumentException('$timestamp argument is neither a valid UNIX timestamp, a valid date-time string or a DateTime object.', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
$timestamp->setTimezone(new DateTimeZone(date_default_timezone_get()));
|
||||
|
||||
if (empty($locale)) {
|
||||
// get current locale
|
||||
$locale = setlocale(LC_TIME, '0');
|
||||
}
|
||||
// remove trailing part not supported by ext-intl locale
|
||||
$locale = preg_replace('/[^\w-].*$/', '', $locale);
|
||||
|
||||
$intl_formats = [
|
||||
'%a' => 'EEE', // An abbreviated textual representation of the day Sun through Sat
|
||||
'%A' => 'EEEE', // A full textual representation of the day Sunday through Saturday
|
||||
'%b' => 'MMM', // Abbreviated month name, based on the locale Jan through Dec
|
||||
'%B' => 'MMMM', // Full month name, based on the locale January through December
|
||||
'%h' => 'MMM', // Abbreviated month name, based on the locale (an alias of %b) Jan through Dec
|
||||
];
|
||||
|
||||
$intl_formatter = function (DateTimeInterface $timestamp, string $format) use ($intl_formats, $locale) {
|
||||
$tz = $timestamp->getTimezone();
|
||||
$date_type = IntlDateFormatter::FULL;
|
||||
$time_type = IntlDateFormatter::FULL;
|
||||
$pattern = '';
|
||||
|
||||
switch ($format) {
|
||||
// %c = Preferred date and time stamp based on locale
|
||||
// Example: Tue Feb 5 00:45:10 2009 for February 5, 2009 at 12:45:10 AM
|
||||
case '%c':
|
||||
$date_type = IntlDateFormatter::LONG;
|
||||
$time_type = IntlDateFormatter::SHORT;
|
||||
break;
|
||||
|
||||
// %x = Preferred date representation based on locale, without the time
|
||||
// Example: 02/05/09 for February 5, 2009
|
||||
case '%x':
|
||||
$date_type = IntlDateFormatter::SHORT;
|
||||
$time_type = IntlDateFormatter::NONE;
|
||||
break;
|
||||
|
||||
// Localized time format
|
||||
case '%X':
|
||||
$date_type = IntlDateFormatter::NONE;
|
||||
$time_type = IntlDateFormatter::MEDIUM;
|
||||
break;
|
||||
|
||||
default:
|
||||
$pattern = $intl_formats[$format];
|
||||
}
|
||||
|
||||
// In October 1582, the Gregorian calendar replaced the Julian in much of Europe, and
|
||||
// the 4th October was followed by the 15th October.
|
||||
// ICU (including IntlDateFormattter) interprets and formats dates based on this cutover.
|
||||
// Posix (including PHP81_BC\PHP81_BC\strftime) and timelib (including DateTimeImmutable) instead use
|
||||
// a "proleptic Gregorian calendar" - they pretend the Gregorian calendar has existed forever.
|
||||
// This leads to the same instants in time, as expressed in Unix time, having different representations
|
||||
// in formatted strings.
|
||||
// To adjust for this, a custom calendar can be supplied with a cutover date arbitrarily far in the past.
|
||||
$calendar = IntlGregorianCalendar::createInstance();
|
||||
$calendar->setGregorianChange(PHP_INT_MIN);
|
||||
|
||||
return (new IntlDateFormatter($locale, $date_type, $time_type, $tz, $calendar, $pattern))->format($timestamp);
|
||||
};
|
||||
|
||||
// Same order as https://www.php.net/manual/en/function.PHP81_BC\PHP81_BC\strftime.php
|
||||
$translation_table = [
|
||||
// Day
|
||||
'%a' => $intl_formatter,
|
||||
'%A' => $intl_formatter,
|
||||
'%d' => 'd',
|
||||
'%e' => function ($timestamp) {
|
||||
return sprintf('% 2u', $timestamp->format('j'));
|
||||
},
|
||||
'%j' => function ($timestamp) {
|
||||
// Day number in year, 001 to 366
|
||||
return sprintf('%03d', $timestamp->format('z')+1);
|
||||
},
|
||||
'%u' => 'N',
|
||||
'%w' => 'w',
|
||||
|
||||
// Week
|
||||
'%U' => function ($timestamp) {
|
||||
// Number of weeks between date and first Sunday of year
|
||||
$day = new DateTime(sprintf('%d-01 Sunday', $timestamp->format('Y')));
|
||||
return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7);
|
||||
},
|
||||
'%V' => 'W',
|
||||
'%W' => function ($timestamp) {
|
||||
// Number of weeks between date and first Monday of year
|
||||
$day = new DateTime(sprintf('%d-01 Monday', $timestamp->format('Y')));
|
||||
return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7);
|
||||
},
|
||||
|
||||
// Month
|
||||
'%b' => $intl_formatter,
|
||||
'%B' => $intl_formatter,
|
||||
'%h' => $intl_formatter,
|
||||
'%m' => 'm',
|
||||
|
||||
// Year
|
||||
'%C' => function ($timestamp) {
|
||||
// Century (-1): 19 for 20th century
|
||||
return floor($timestamp->format('Y') / 100);
|
||||
},
|
||||
'%g' => function ($timestamp) {
|
||||
return substr($timestamp->format('o'), -2);
|
||||
},
|
||||
'%G' => 'o',
|
||||
'%y' => 'y',
|
||||
'%Y' => 'Y',
|
||||
|
||||
// Time
|
||||
'%H' => 'H',
|
||||
'%k' => function ($timestamp) {
|
||||
return sprintf('% 2u', $timestamp->format('G'));
|
||||
},
|
||||
'%I' => 'h',
|
||||
'%l' => function ($timestamp) {
|
||||
return sprintf('% 2u', $timestamp->format('g'));
|
||||
},
|
||||
'%M' => 'i',
|
||||
'%p' => 'A', // AM PM (this is reversed on purpose!)
|
||||
'%P' => 'a', // am pm
|
||||
'%r' => 'h:i:s A', // %I:%M:%S %p
|
||||
'%R' => 'H:i', // %H:%M
|
||||
'%S' => 's',
|
||||
'%T' => 'H:i:s', // %H:%M:%S
|
||||
'%X' => $intl_formatter, // Preferred time representation based on locale, without the date
|
||||
|
||||
// Timezone
|
||||
'%z' => 'O',
|
||||
'%Z' => 'T',
|
||||
|
||||
// Time and Date Stamps
|
||||
'%c' => $intl_formatter,
|
||||
'%D' => 'm/d/Y',
|
||||
'%F' => 'Y-m-d',
|
||||
'%s' => 'U',
|
||||
'%x' => $intl_formatter,
|
||||
];
|
||||
|
||||
$out = preg_replace_callback('/(?<!%)%([_#-]?)([a-zA-Z])/', function ($match) use ($translation_table, $timestamp) {
|
||||
$prefix = $match[1];
|
||||
$char = $match[2];
|
||||
$pattern = '%'.$char;
|
||||
if ($pattern == '%n') {
|
||||
return "\n";
|
||||
} elseif ($pattern == '%t') {
|
||||
return "\t";
|
||||
}
|
||||
|
||||
if (!isset($translation_table[$pattern])) {
|
||||
throw new InvalidArgumentException(sprintf('Format "%s" is unknown in time format', $pattern));
|
||||
}
|
||||
|
||||
$replace = $translation_table[$pattern];
|
||||
|
||||
if (is_string($replace)) {
|
||||
$result = $timestamp->format($replace);
|
||||
} else {
|
||||
$result = $replace($timestamp, $pattern);
|
||||
}
|
||||
|
||||
switch ($prefix) {
|
||||
case '_':
|
||||
// replace leading zeros with spaces but keep last char if also zero
|
||||
return preg_replace('/\G0(?=.)/', ' ', $result);
|
||||
case '#':
|
||||
case '-':
|
||||
// remove leading zeros but keep last char if also zero
|
||||
return preg_replace('/^0+(?=.)/', '', $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}, $format);
|
||||
|
||||
$out = str_replace('%%', '%', $out);
|
||||
return $out;
|
||||
}
|
991
core/class/template.class.php
Normal file
991
core/class/template.class.php
Normal file
@ -0,0 +1,991 @@
|
||||
<?php
|
||||
|
||||
class template
|
||||
{
|
||||
|
||||
/**
|
||||
* Crée un bouton
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function button($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'class' => '',
|
||||
'disabled' => false,
|
||||
'href' => 'javascript:void(0);',
|
||||
'ico' => '',
|
||||
'id' => $nameId,
|
||||
'name' => $nameId,
|
||||
'target' => '',
|
||||
'uniqueSubmission' => false,
|
||||
'value' => 'Bouton',
|
||||
'help' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['value'] = helper::translate($attributes['value']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Retourne le html
|
||||
return sprintf(
|
||||
'<a %s class="button %s %s %s" %s>%s</a>',
|
||||
helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']),
|
||||
$attributes['disabled'] ? 'disabled' : '',
|
||||
$attributes['class'],
|
||||
$attributes['uniqueSubmission'] ? 'uniqueSubmission' : '',
|
||||
$attributes['help'] ? ' title="' . $attributes['help'] . '" ' : '',
|
||||
($attributes['ico'] ? template::ico($attributes['ico'], ['margin' => 'right']) : '') . $attributes['value']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ captcha
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function captcha($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'name' => $nameId,
|
||||
'value' => '',
|
||||
'limit' => false, // captcha simple
|
||||
'type' => 'alpha' // num(érique) ou alpha(bétique)
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
// $attributes['value'] = helper::translate($attributes['value']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Captcha quatre opérations
|
||||
// Limite addition et soustraction selon le type de captcha
|
||||
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
||||
$letters = ['u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'];
|
||||
$limit = $attributes['limit'] ? count($letters) - 1 : 10;
|
||||
|
||||
// Tirage de l'opération
|
||||
mt_srand();
|
||||
// Captcha simple limité à l'addition
|
||||
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
|
||||
|
||||
// Limite si multiplication ou division
|
||||
if ($operator > 2) {
|
||||
$limit = 10;
|
||||
}
|
||||
|
||||
// Tirage des nombres
|
||||
mt_srand();
|
||||
$firstNumber = mt_rand(1, $limit);
|
||||
mt_srand();
|
||||
$secondNumber = mt_rand(1, $limit);
|
||||
|
||||
// Permutation si addition ou soustraction
|
||||
if (($operator < 3) and ($firstNumber < $secondNumber)) {
|
||||
$temp = $firstNumber;
|
||||
$firstNumber = $secondNumber;
|
||||
$secondNumber = $temp;
|
||||
}
|
||||
|
||||
// Icône de l'opérateur et calcul du résultat
|
||||
switch ($operator) {
|
||||
case 1:
|
||||
$operator = template::ico('plus', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber + $secondNumber;
|
||||
break;
|
||||
case 2:
|
||||
$operator = template::ico('minus', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber - $secondNumber;
|
||||
break;
|
||||
case 3:
|
||||
$operator = template::ico('cancel', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber * $secondNumber;
|
||||
break;
|
||||
case 4:
|
||||
$operator = template::ico('divide', ['fontSize' => '2em;']);
|
||||
$limit2 = [10, 10, 6, 5, 4, 3, 2, 2, 2, 2];
|
||||
for ($i = 1; $i <= $firstNumber; $i++) {
|
||||
$limit = $limit2[$i - 1];
|
||||
}
|
||||
mt_srand();
|
||||
$secondNumber = mt_rand(1, $limit);
|
||||
$firstNumber = $firstNumber * $secondNumber;
|
||||
$result = $firstNumber / $secondNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
// Hashage du résultat
|
||||
$result = password_hash($result, PASSWORD_BCRYPT);
|
||||
|
||||
// Codage des valeurs de l'opération
|
||||
$firstLetter = uniqid();
|
||||
$secondLetter = uniqid();
|
||||
|
||||
// Masquage image source pour éviter un décodage
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
|
||||
|
||||
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="captcha inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
$html .= self::label(
|
||||
$attributes['id'],
|
||||
'<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" /> <strong>' . $operator . '</strong> <img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" />' . template::ico('eq', ['fontSize' => '2em;']),
|
||||
[
|
||||
'help' => $attributes['help']
|
||||
]
|
||||
);
|
||||
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
|
||||
// captcha
|
||||
$html .= sprintf(
|
||||
'<input type="text" %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
|
||||
// Champ résultat codé
|
||||
$html .= self::hidden($attributes['id'] . 'Result', [
|
||||
'value' => $result,
|
||||
'before' => false
|
||||
]);
|
||||
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une case à cocher à sélection multiple
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param string $value Valeur de la case à cocher
|
||||
* @param string $label Label de la case à cocher
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function checkbox($nameId, $value, $label, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'before' => true,
|
||||
'checked' => '',
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'name' => $nameId
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$label = helper::translate($label);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['checked'] = (bool) common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Case à cocher
|
||||
$html .= sprintf(
|
||||
'<input type="checkbox" value="%s" %s>',
|
||||
$value,
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
// Label
|
||||
$html .= self::label($attributes['id'], '<span>' . $label . '</span>', [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ date
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @param string type date seule ; time heure seule ; datetime-local (jour et heure)
|
||||
* @return string
|
||||
*/
|
||||
public static function date($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'autocomplete' => 'on',
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
'name' => $nameId,
|
||||
'placeholder' => '',
|
||||
'readonly' => false,
|
||||
'value' => '',
|
||||
'type' => 'date',
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
|
||||
// Filtre selon le type
|
||||
switch ($attributes['type']) {
|
||||
case 'datetime-local':
|
||||
$filter = helper::FILTER_TIMESTAMP;
|
||||
break;
|
||||
case 'date':
|
||||
$filter = helper::FILTER_DATE; // Pour générer une valeur uniquement sur la date
|
||||
break;
|
||||
case 'time':
|
||||
$filter = helper::FILTER_TIME; // Pour générer une valeur uniquement sur l'heure
|
||||
break;
|
||||
default:
|
||||
$filter = null; // pas de filtre pour month and year
|
||||
break;
|
||||
}
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
} else {
|
||||
$attributes['value'] = ($attributes['value'] ? helper::filter($attributes['value'], $filter) : '');
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Date visible
|
||||
$html .= '<div class="inputDateManagerWrapper">';
|
||||
$html .= sprintf(
|
||||
'<input type="' . $attributes['type'] . '" class="datepicker %s" value="%s" %s>',
|
||||
$attributes['class'],
|
||||
$attributes['value'],
|
||||
helper::sprintAttributes($attributes, ['class', 'value'])
|
||||
);
|
||||
$html .= '</div>';
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Crée un champ d'upload de fichier
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function file($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'extensions' => '',
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'type' => 2,
|
||||
'value' => '',
|
||||
'folder' => '',
|
||||
'language' => 'fr_FR'
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['value'] = helper::translate($attributes['value']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Champ caché contenant l'url de la page
|
||||
$html .= self::hidden($attributes['id'], [
|
||||
'class' => 'inputFileHidden',
|
||||
'disabled' => $attributes['disabled'],
|
||||
'maxlength' => $attributes['maxlength'],
|
||||
'value' => $attributes['value']
|
||||
]);
|
||||
// Champ d'upload
|
||||
$html .= '<div class="inputFileManagerWrapper">';
|
||||
$html .= sprintf(
|
||||
'<a
|
||||
href="' .
|
||||
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
|
||||
'?relative_url=1' .
|
||||
'&lang=' . $attributes['language'] .
|
||||
'&field_id=' . $attributes['id'] .
|
||||
'&type=' . $attributes['type'] .
|
||||
'&akey=' . md5_file(core::DATA_DIR . 'core.json') .
|
||||
// Ajoute le nom du dossier si la variable est passée
|
||||
(!empty($attributes['folder']) ? '&fldr=' . $attributes['folder'] : '') .
|
||||
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
|
||||
. '"
|
||||
class="inputFile %s %s"
|
||||
%s
|
||||
data-lity
|
||||
>
|
||||
' . self::ico('upload-cloud', ['margin' => 'right']) . '
|
||||
<span class="inputFileLabel"></span>
|
||||
</a>',
|
||||
$attributes['class'],
|
||||
$attributes['disabled'] ? 'disabled' : '',
|
||||
helper::sprintAttributes($attributes, ['class', 'extensions', 'type', 'maxlength'])
|
||||
|
||||
);
|
||||
$html .= self::button($attributes['id'] . 'Delete', [
|
||||
'class' => 'inputFileDelete',
|
||||
'value' => self::ico('cancel')
|
||||
]);
|
||||
$html .= '</div>';
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ferme un formulaire
|
||||
* @return string
|
||||
*/
|
||||
public static function formClose()
|
||||
{
|
||||
return '</form>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ouvre un formulaire protégé par CSRF
|
||||
* @param string $id Id du formulaire
|
||||
* @return string
|
||||
*/
|
||||
public static function formOpen($id)
|
||||
{
|
||||
// Ouverture formulaire
|
||||
$html = '<form id="' . $id . '" method="post">';
|
||||
// Stock le token CSRF
|
||||
$html .= self::hidden('csrf', [
|
||||
'value' => htmlentities($_SESSION['csrf'], ENT_QUOTES | ENT_HTML5, 'UTF-8')
|
||||
]);
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Crée une aide qui s'affiche au survole
|
||||
* @param string $text Texte de l'aide
|
||||
* @return string
|
||||
*/
|
||||
public static function help($text)
|
||||
{
|
||||
return '<span class="helpButton" data-tippy-content="' . $text . '">' . self::ico('help') . '<!----></span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ caché
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function hidden($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'noDirty' => false,
|
||||
'id' => $nameId,
|
||||
//'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'value' => ''
|
||||
], $attributes);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Texte
|
||||
$html = sprintf('<input type="hidden" %s>', helper::sprintAttributes($attributes, ['before']));
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un icône
|
||||
* @Array :
|
||||
* @param string $ico Classe de l'icône
|
||||
* @param string $margin Ajoute un margin autour de l'icône (choix : left, right, all)
|
||||
* @param bool $animate Ajoute une animation à l'icône
|
||||
* @param string $fontSize Taille de la police
|
||||
* @param string $href lien vers une url
|
||||
* @param string $help popup d'aide
|
||||
* @param string $id de l'élement
|
||||
* @return string
|
||||
*/
|
||||
// public static function ico($ico, $margin = '', $animate = false, $fontSize = '1em') {
|
||||
public static function ico($ico, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'margin' => '',
|
||||
'animate' => false,
|
||||
'fontSize' => '1em',
|
||||
'href' => '',
|
||||
'attr' => '',
|
||||
'help' => '',
|
||||
'id' => '',
|
||||
], $attributes);
|
||||
// Traduction de l'aide
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Contenu de l'icône
|
||||
$alt = $attributes['help'] ? $attributes['help'] : $ico;
|
||||
$item = $attributes['href'] ? '<a id="' . $attributes['id'] . '" data-tippy-content="' . $attributes['help'] . '" alt="' . $alt . '" href="' . $attributes['href'] . '" ' . $attributes['attr'] . ' >' : '';
|
||||
$item .= '<span class="zwiico-' . $ico . ($attributes['margin'] ? ' zwiico-margin-' . $attributes['margin'] : '') . ($attributes['animate'] ? ' animate-spin' : '') . '" style="font-size:' . $attributes['fontSize'] . '"><!----></span>';
|
||||
$item .= ($attributes['href']) ? '</a>' : '';
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un drapeau du site courante
|
||||
* @param string $langId Id de la langue à affiche ou selected pour la langue courante
|
||||
* @param string size en pixels ou en rem
|
||||
* @return string
|
||||
*/
|
||||
public static function flag($langId, $size = 'auto')
|
||||
{
|
||||
$lang = 'fr_FR';
|
||||
switch ($langId) {
|
||||
case '':
|
||||
break;
|
||||
case array_key_exists($langId, core::$languages):
|
||||
$lang = $langId;
|
||||
break;
|
||||
case 'selected':
|
||||
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
$lang = $_SESSION['ZWII_SITE_CONTENT'];
|
||||
} else {
|
||||
$lang = 'fr_FR';
|
||||
}
|
||||
}
|
||||
return '<img class="flag" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"
|
||||
width="' . $size . '"
|
||||
height="' . $size . '"
|
||||
title="' . $lang . '"
|
||||
alt="(' . $lang . ')"/>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un label
|
||||
* @param string $for For du label
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @param string $text Texte du label
|
||||
* @return string
|
||||
*/
|
||||
public static function label($for, $text, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'class' => '',
|
||||
'for' => $for,
|
||||
'help' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$text = helper::translate($text);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
|
||||
if (
|
||||
get_called_class() !== 'template'
|
||||
) {
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
}
|
||||
if ($attributes['help'] !== '') {
|
||||
$text = $text . self::help($attributes['help']);
|
||||
}
|
||||
// Retourne le html
|
||||
return sprintf(
|
||||
'<label %s>%s</label>',
|
||||
helper::sprintAttributes($attributes),
|
||||
$text
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ mail
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function mail($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'autocomplete' => 'on',
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
//'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'placeholder' => '',
|
||||
'readonly' => false,
|
||||
'value' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Texte
|
||||
$html .= sprintf(
|
||||
'<input type="email" %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une notice
|
||||
* @param string $id Id du champ
|
||||
* @param string $notice Notice
|
||||
* @return string
|
||||
*/
|
||||
public static function notice($id, $notice)
|
||||
{
|
||||
return ' <span id="' . $id . 'Notice" class="notice ' . ($notice ? '' : 'displayNone') . '">' . $notice . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ mot de passe
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function password($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'autocomplete' => 'on',
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
//'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'placeholder' => '',
|
||||
'readonly' => false
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Mot de passe
|
||||
$html .= sprintf(
|
||||
'<input type="password" %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ sélection
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $options Liste des options du champ de sélection ($value => $text)
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function select($nameId, array $options, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
'name' => $nameId,
|
||||
'selected' => '',
|
||||
'font' => [],
|
||||
'multiple' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Stocker les fontes et remettre à zéro le tableau des fontes transmis pour éviter une erreur de sprintAttributes
|
||||
if (empty($attributes['font']) === false) {
|
||||
$fonts = $attributes['font'];
|
||||
$attributes['font'] = [];
|
||||
}
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['selected'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Attribut multiple
|
||||
if ($attributes['multiple'] === true) {
|
||||
echo "ppp";
|
||||
$attributes['multiple'] = 'multiple';
|
||||
}
|
||||
// Début sélection
|
||||
$html .= sprintf(
|
||||
'<select %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
foreach ($options as $value => $text) {
|
||||
// Select des liste de fontes
|
||||
$html .= isset($fonts) ? sprintf(
|
||||
'<option value="%s"%s style="font-family: %s;">%s</option>',
|
||||
$value,
|
||||
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
|
||||
$fonts[$value],
|
||||
$text
|
||||
// Select standard
|
||||
) : sprintf(
|
||||
'<option value="%s"%s>%s</option>',
|
||||
$value,
|
||||
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
|
||||
helper::translate($text)
|
||||
);
|
||||
}
|
||||
// Fin sélection
|
||||
$html .= '</select>';
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Crée une bulle de dialogue
|
||||
* @param string $text Texte de la bulle
|
||||
* @return string
|
||||
*/
|
||||
public static function speech($text)
|
||||
{
|
||||
return '<div class="speech"><div class="speechBubble">' . helper::translate($text) . '</div>' . template::ico('mimi speechMimi', ['fontSize' => '7em']) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un bouton validation
|
||||
* @param string $nameId Nom & id du bouton validation
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function submit($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'class' => '',
|
||||
'disabled' => false,
|
||||
'ico' => 'check',
|
||||
'id' => $nameId,
|
||||
'name' => $nameId,
|
||||
'uniqueSubmission' => false, //true avant 9.1.08
|
||||
'value' => 'Enregistrer'
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['value'] = helper::translate($attributes['value']);
|
||||
// Retourne le html
|
||||
return sprintf(
|
||||
'<button type="submit" class="%s%s" %s>%s</button>',
|
||||
$attributes['class'],
|
||||
$attributes['uniqueSubmission'] ? 'uniqueSubmission' : '',
|
||||
helper::sprintAttributes($attributes, ['class', 'ico', 'value']),
|
||||
($attributes['ico'] ? template::ico($attributes['ico'], ['margin' => 'right']) : '') . $attributes['value']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un tableau
|
||||
* @param array $cols Cols des colonnes (format: [col colonne1, col colonne2, etc])
|
||||
* @param array $body Contenu (format: [[contenu1, contenu2, etc], [contenu1, contenu2, etc]])
|
||||
* @param array $head Entêtes (format : [[titre colonne1, titre colonne2, etc])
|
||||
* @param array $rowsId Id pour la numérotation des rows (format : [id colonne1, id colonne2, etc])
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function table(array $cols = [], array $body = [], array $head = [], array $attributes = [], array $rowsId = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'id' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
foreach ($head as $value) {
|
||||
$head[array_search($value, $head)] = helper::translate($value);
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Début tableau
|
||||
$html .= '<table id="' . $attributes['id'] . '" class="table ' . $attributes['class'] . '">';
|
||||
// Entêtes
|
||||
if ($head) {
|
||||
// Début des entêtes
|
||||
$html .= '<thead>';
|
||||
$html .= '<tr class="nodrag">';
|
||||
$i = 0;
|
||||
foreach ($head as $th) {
|
||||
$html .= '<th class="col' . $cols[$i++] . '">' . $th . '</th>';
|
||||
}
|
||||
// Fin des entêtes
|
||||
$html .= '</tr>';
|
||||
$html .= '</thead>';
|
||||
}
|
||||
// Pas de tableau d'Id transmis, générer une numérotation
|
||||
if (empty($rowsId)) {
|
||||
$rowsId = range(0, count($body));
|
||||
}
|
||||
// Début contenu
|
||||
$j = 0;
|
||||
foreach ($body as $tr) {
|
||||
// Id de ligne pour les tableaux drag and drop
|
||||
$html .= '<tr id="' . $rowsId[$j++] . '">';
|
||||
$i = 0;
|
||||
foreach ($tr as $td) {
|
||||
$html .= '<td class="col' . $cols[$i++] . '">' . $td . '</td>';
|
||||
}
|
||||
$html .= '</tr>';
|
||||
}
|
||||
// Fin contenu
|
||||
$html .= '</tbody>';
|
||||
// Fin tableau
|
||||
$html .= '</table>';
|
||||
// Fin container
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ texte court
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function text($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'autocomplete' => 'on',
|
||||
'before' => true,
|
||||
'class' => '',
|
||||
'classWrapper' => '',
|
||||
'noDirty' => false,
|
||||
'disabled' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
//'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'placeholder' => '',
|
||||
'readonly' => false,
|
||||
'value' => '',
|
||||
'type' => 'text'
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Texte
|
||||
$html .= sprintf(
|
||||
'<input type="' . $attributes['type'] . '" %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un champ texte long
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @return string
|
||||
*/
|
||||
public static function textarea($nameId, array $attributes = [])
|
||||
{
|
||||
// Attributs par défaut
|
||||
$attributes = array_merge([
|
||||
'before' => true,
|
||||
'class' => '', // editorWysiwyg et editor possible pour utiliser un éditeur (il faut également instancier les librairies)
|
||||
'classWrapper' => '',
|
||||
'disabled' => false,
|
||||
'noDirty' => false,
|
||||
'help' => '',
|
||||
'id' => $nameId,
|
||||
'label' => '',
|
||||
//'maxlength' => '500',
|
||||
'name' => $nameId,
|
||||
'readonly' => false,
|
||||
'value' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Label
|
||||
if ($attributes['label']) {
|
||||
$html .= self::label($attributes['id'], $attributes['label'], [
|
||||
'help' => $attributes['help']
|
||||
]);
|
||||
}
|
||||
// Notice
|
||||
$notice = '';
|
||||
if (array_key_exists($attributes['id'], common::$inputNotices)) {
|
||||
$notice = common::$inputNotices[$attributes['id']];
|
||||
$attributes['class'] .= ' notice';
|
||||
}
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Texte long
|
||||
$html .= sprintf(
|
||||
'<textarea %s>%s</textarea>',
|
||||
helper::sprintAttributes($attributes, ['value']),
|
||||
$attributes['value']
|
||||
);
|
||||
// Fin du wrapper
|
||||
$html .= '</div>';
|
||||
// Retourne le html
|
||||
return $html;
|
||||
}
|
||||
}
|
397
core/core.js.php
Executable file → Normal file
397
core/core.js.php
Executable file → Normal file
@ -1,13 +1,14 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
var core = {};
|
||||
@ -15,8 +16,8 @@ var core = {};
|
||||
/**
|
||||
* Crée un message d'alerte
|
||||
*/
|
||||
core.alert = function(text) {
|
||||
var lightbox = lity(function($) {
|
||||
core.alert = function (text) {
|
||||
var lightbox = lity(function ($) {
|
||||
return $("<div>")
|
||||
.addClass("lightbox")
|
||||
.append(
|
||||
@ -27,15 +28,15 @@ core.alert = function(text) {
|
||||
$("<a>")
|
||||
.addClass("button")
|
||||
.text("Ok")
|
||||
.on("click", function() {
|
||||
.on("click", function () {
|
||||
lightbox.close();
|
||||
})
|
||||
)
|
||||
)
|
||||
}(jQuery));
|
||||
// Validation de la lightbox avec le bouton entrée
|
||||
$(document).on("keyup", function(event) {
|
||||
if(event.keyCode === 13) {
|
||||
$(document).on("keyup", function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
lightbox.close();
|
||||
}
|
||||
});
|
||||
@ -45,22 +46,22 @@ core.alert = function(text) {
|
||||
/**
|
||||
* Génère des variations d'une couleur
|
||||
*/
|
||||
core.colorVariants = function(rgba) {
|
||||
core.colorVariants = function (rgba) {
|
||||
rgba = rgba.match(/\(+(.*)\)/);
|
||||
rgba = rgba[1].split(", ");
|
||||
return {
|
||||
"normal": "rgba(" + rgba[0] + "," + rgba[1] + "," + rgba[2] + "," + rgba[3] + ")",
|
||||
"darken": "rgba(" + Math.max(0, rgba[0] - 15) + "," + Math.max(0, rgba[1] - 15) + "," + Math.max(0, rgba[2] - 15) + "," + rgba[3] + ")",
|
||||
"veryDarken": "rgba(" + Math.max(0, rgba[0] - 20) + "," + Math.max(0, rgba[1] - 20) + "," + Math.max(0, rgba[2] - 20) + "," + rgba[3] + ")",
|
||||
"text": core.relativeLuminanceW3C(rgba) > .22 ? "inherit" : "white"
|
||||
"text": core.relativeLuminanceW3C(rgba) > .22 ? "#222" : "#DDD"
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Crée un message de confirmation
|
||||
*/
|
||||
core.confirm = function(text, yesCallback, noCallback) {
|
||||
var lightbox = lity(function($) {
|
||||
core.confirm = function (text, yesCallback, noCallback) {
|
||||
var lightbox = lity(function ($) {
|
||||
return $("<div>")
|
||||
.addClass("lightbox")
|
||||
.append(
|
||||
@ -70,21 +71,21 @@ core.confirm = function(text, yesCallback, noCallback) {
|
||||
.append(
|
||||
$("<a>")
|
||||
.addClass("button grey")
|
||||
.text("Non")
|
||||
.on("click", function() {
|
||||
.text("<?php echo helper::translate('Non');?>")
|
||||
.on("click", function () {
|
||||
lightbox.options('button', true);
|
||||
lightbox.close();
|
||||
if(typeof noCallback !== "undefined") {
|
||||
if (typeof noCallback !== "undefined") {
|
||||
noCallback();
|
||||
}
|
||||
}),
|
||||
$("<a>")
|
||||
.addClass("button")
|
||||
.text("Oui")
|
||||
.on("click", function() {
|
||||
.text("<?php echo helper::translate('Oui');?>")
|
||||
.on("click", function () {
|
||||
lightbox.options('button', true);
|
||||
lightbox.close();
|
||||
if(typeof yesCallback !== "undefined") {
|
||||
if (typeof yesCallback !== "undefined") {
|
||||
yesCallback();
|
||||
}
|
||||
})
|
||||
@ -93,19 +94,19 @@ core.confirm = function(text, yesCallback, noCallback) {
|
||||
}(jQuery));
|
||||
// Callback lors d'un clic sur le fond et sur la croix de fermeture
|
||||
lightbox.options('button', false);
|
||||
$(document).on('lity:close', function(event, instance) {
|
||||
if(
|
||||
instance.options('button') === false
|
||||
&& typeof noCallback !== "undefined"
|
||||
$(document).on('lity:close', function (event, instance) {
|
||||
if (
|
||||
instance.options('button') === false &&
|
||||
typeof noCallback !== "undefined"
|
||||
) {
|
||||
noCallback();
|
||||
}
|
||||
});
|
||||
// Validation de la lightbox avec le bouton entrée
|
||||
$(document).on("keyup", function(event) {
|
||||
if(event.keyCode === 13) {
|
||||
$(document).on("keyup", function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
lightbox.close();
|
||||
if(typeof yesCallback !== "undefined") {
|
||||
if (typeof yesCallback !== "undefined") {
|
||||
yesCallback();
|
||||
}
|
||||
}
|
||||
@ -116,7 +117,7 @@ core.confirm = function(text, yesCallback, noCallback) {
|
||||
/**
|
||||
* Scripts à exécuter en dernier
|
||||
*/
|
||||
core.end = function() {
|
||||
core.end = function () {
|
||||
/**
|
||||
* Modifications non enregistrées du formulaire
|
||||
*/
|
||||
@ -126,23 +127,24 @@ core.end = function() {
|
||||
// - Les champs avec data-no-dirty
|
||||
var inputsDOM = formDOM.find("input:not([data-no-dirty]), select:not([data-no-dirty]), textarea:not(.editorWysiwyg):not([data-no-dirty])");
|
||||
var inputSerialize = inputsDOM.serialize();
|
||||
$(window).on("beforeunload", function() {
|
||||
if(inputsDOM.serialize() !== inputSerialize) {
|
||||
return "Les modifications que vous avez apportées ne seront peut-être pas enregistrées.";
|
||||
$(window).on("beforeunload", function () {
|
||||
if (inputsDOM.serialize() !== inputSerialize) {
|
||||
message = "<?php echo helper::translate('Les modifications que vous avez apportées ne seront peut-être pas enregistrées.');?>";
|
||||
return message;
|
||||
}
|
||||
});
|
||||
formDOM.submit(function() {
|
||||
formDOM.submit(function () {
|
||||
$(window).off("beforeunload");
|
||||
});
|
||||
};
|
||||
$(function() {
|
||||
$(function () {
|
||||
core.end();
|
||||
});
|
||||
|
||||
/**
|
||||
* Ajoute une notice
|
||||
*/
|
||||
core.noticeAdd = function(id, notice) {
|
||||
core.noticeAdd = function (id, notice) {
|
||||
$("#" + id + "Notice").text(notice).removeClass("displayNone");
|
||||
$("#" + id).addClass("notice");
|
||||
};
|
||||
@ -150,7 +152,7 @@ core.noticeAdd = function(id, notice) {
|
||||
/**
|
||||
* Supprime une notice
|
||||
*/
|
||||
core.noticeRemove = function(id) {
|
||||
core.noticeRemove = function (id) {
|
||||
$("#" + id + "Notice").text("").addClass("displayNone");
|
||||
$("#" + id).removeClass("notice");
|
||||
};
|
||||
@ -158,22 +160,23 @@ core.noticeRemove = function(id) {
|
||||
/**
|
||||
* Scripts à exécuter en premier
|
||||
*/
|
||||
core.start = function() {
|
||||
core.start = function () {
|
||||
/**
|
||||
* Remonter en haut au clic sur le bouton
|
||||
*/
|
||||
var backToTopDOM = $("#backToTop");
|
||||
backToTopDOM.on("click", function() {
|
||||
$("body, html").animate({scrollTop: 0}, "400");
|
||||
backToTopDOM.on("click", function () {
|
||||
$("body, html").animate({
|
||||
scrollTop: 0
|
||||
}, "400");
|
||||
});
|
||||
/**
|
||||
* Affiche / Cache le bouton pour remonter en haut
|
||||
*/
|
||||
$(window).on("scroll", function() {
|
||||
if($(this).scrollTop() > 200) {
|
||||
$(window).on("scroll", function () {
|
||||
if ($(this).scrollTop() > 200) {
|
||||
backToTopDOM.fadeIn();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
backToTopDOM.fadeOut();
|
||||
}
|
||||
});
|
||||
@ -182,109 +185,130 @@ core.start = function() {
|
||||
*/
|
||||
var notificationTimer;
|
||||
$("#notification")
|
||||
.on("mouseenter", function() {
|
||||
.on("mouseenter", function () {
|
||||
clearTimeout(notificationTimer);
|
||||
$("#notificationProgress")
|
||||
.stop()
|
||||
.width("100%");
|
||||
})
|
||||
.on("mouseleave", function() {
|
||||
.on("mouseleave", function () {
|
||||
// Disparition de la notification
|
||||
notificationTimer = setTimeout(function() {
|
||||
notificationTimer = setTimeout(function () {
|
||||
$("#notification").fadeOut();
|
||||
}, 2000);
|
||||
}, 3000);
|
||||
// Barre de progression
|
||||
$("#notificationProgress").animate({
|
||||
"width": "0%"
|
||||
}, 2000, "linear");
|
||||
}, 3000, "linear");
|
||||
})
|
||||
.trigger("mouseleave");
|
||||
$("#notificationClose").on("click", function() {
|
||||
$("#notificationClose").on("click", function () {
|
||||
clearTimeout(notificationTimer);
|
||||
$("#notification").fadeOut();
|
||||
$("#notificationProgress").stop();
|
||||
});
|
||||
|
||||
/**
|
||||
* Traitement du formulaire cookies
|
||||
*/
|
||||
$("#cookieForm").submit(function (event) {
|
||||
|
||||
// Variables des cookies
|
||||
var getUrl = window.location;
|
||||
var domain = "domain=" + getUrl.hostname + ";";
|
||||
var basePath = getUrl.pathname.substring(0, getUrl.pathname.lastIndexOf('/') + 1);
|
||||
var path = "path=" + basePath + ";";
|
||||
var e = new Date();
|
||||
e.setFullYear(e.getFullYear() + 1);
|
||||
var expires = "expires=" + e.toUTCString() + ";";
|
||||
|
||||
// Stocke le cookie d'acceptation
|
||||
document.cookie = "ZWII_COOKIE_CONSENT=true; samesite=lax; " + domain + path + expires;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Fermeture de la popup des cookies
|
||||
*/
|
||||
$("#cookieConsent .cookieClose").on("click", function () {
|
||||
$('#cookieConsent').addClass("displayNone");
|
||||
});
|
||||
|
||||
/**
|
||||
* Commande de gestion des cookies dans le footer
|
||||
*/
|
||||
|
||||
$("#footerLinkCookie").on("click", function () {
|
||||
$("#cookieConsent").removeClass("displayNone");
|
||||
});
|
||||
|
||||
/**
|
||||
* Affiche / Cache le menu en mode responsive
|
||||
*/
|
||||
var menuDOM = $("#menu");
|
||||
$("#toggle").on("click", function() {
|
||||
$("#toggle").on("click", function () {
|
||||
menuDOM.slideToggle();
|
||||
});
|
||||
$(window).on("resize", function() {
|
||||
if($(window).width() > 768) {
|
||||
$(window).on("resize", function () {
|
||||
if ($(window).width() > 768) {
|
||||
menuDOM.css("display", "");
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Message sur l'utilisation des cookies
|
||||
*/
|
||||
if(<?php echo json_encode($this->getData(['config', 'cookieConsent'])); ?>) {
|
||||
if(document.cookie.indexOf("ZWII_COOKIE_CONSENT") === -1) {
|
||||
$("body").append(
|
||||
$("<div>").attr("id", "cookieConsent").append(
|
||||
$("<span>").text("En poursuivant votre navigation sur ce site, vous acceptez l'utilisation de cookies."),
|
||||
$("<span>")
|
||||
.attr("id", "cookieConsentConfirm")
|
||||
.text("OK")
|
||||
.on("click", function() {
|
||||
// Créé le cookie d'acceptation
|
||||
var expires = new Date();
|
||||
expires.setFullYear(expires.getFullYear() + 1);
|
||||
expires = "expires=" + expires.toUTCString();
|
||||
document.cookie = "ZWII_COOKIE_CONSENT=true;" + expires;
|
||||
// Ferme le message
|
||||
$(this).parents("#cookieConsent").fadeOut();
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Choix de page dans la barre de membre
|
||||
*/
|
||||
$("#barSelectPage").on("change", function() {
|
||||
$("#barSelectPage").on("change", function () {
|
||||
var pageUrl = $(this).val();
|
||||
if(pageUrl) {
|
||||
if (pageUrl) {
|
||||
$(location).attr("href", pageUrl);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Champs d'upload de fichiers
|
||||
*/
|
||||
// Mise à jour de l'affichage des champs d'upload
|
||||
$(".inputFileHidden").on("change", function() {
|
||||
$(".inputFileHidden").on("change", function () {
|
||||
var inputFileHiddenDOM = $(this);
|
||||
var fileName = inputFileHiddenDOM.val();
|
||||
if(fileName === "") {
|
||||
fileName = "Choisissez un fichier";
|
||||
$(".inputFileDelete").addClass("disabled");
|
||||
}
|
||||
else {
|
||||
$(".inputFileDelete").removeClass("disabled");
|
||||
if (fileName === "") {
|
||||
//fileName = "Sélectionner un fichier";
|
||||
fileName = "<?php echo helper::translate('Sélectionner un fichier');?>";
|
||||
$(inputFileHiddenDOM).addClass("disabled");
|
||||
} else {
|
||||
$(inputFileHiddenDOM).removeClass("disabled");
|
||||
}
|
||||
inputFileHiddenDOM.parent().find(".inputFileLabel").text(fileName);
|
||||
}).trigger("change");
|
||||
// Suppression du fichier contenu dans le champ
|
||||
$(".inputFileDelete").on("click", function() {
|
||||
$(".inputFileDelete").on("click", function () {
|
||||
$(this).parents(".inputWrapper").find(".inputFileHidden").val("").trigger("change");
|
||||
});
|
||||
// Suppression de la date contenu dans le champ
|
||||
$(".inputDateDelete").on("click", function () {
|
||||
$(this).parents(".inputWrapper").find(".datepicker").val("").trigger("change");
|
||||
});
|
||||
// Confirmation de mise à jour
|
||||
$("#barUpdate").on("click", function() {
|
||||
return core.confirm("Effectuer la mise à jour ?", function() {
|
||||
$("#barUpdate").on("click", function () {
|
||||
message = "<?php echo helper::translate('Mise à jour') . ' ?';?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", $("#barUpdate").attr("href"));
|
||||
});
|
||||
});
|
||||
// Confirmation de déconnexion
|
||||
$("#barLogout").on("click", function() {
|
||||
return core.confirm("Se déconnecter ?", function() {
|
||||
$("#barLogout").on("click", function () {
|
||||
message = "<?php echo helper::translate('Se déconnecter') . ' ?';?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", $("#barLogout").attr("href"));
|
||||
});
|
||||
});
|
||||
/**
|
||||
* Bloque la multi-soumission des boutons
|
||||
*/
|
||||
$("form").on("submit", function() {
|
||||
$("form").on("submit", function () {
|
||||
$(this).find(".uniqueSubmission")
|
||||
.addClass("disabled")
|
||||
.prop("disabled", true)
|
||||
@ -296,65 +320,83 @@ core.start = function() {
|
||||
/**
|
||||
* Check adresse email
|
||||
*/
|
||||
$("[type=email]").on("change", function() {
|
||||
$("[type=email]").on("change", function () {
|
||||
var _this = $(this);
|
||||
var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
|
||||
if(pattern.test(_this.val())) {
|
||||
if (pattern.test(_this.val())) {
|
||||
core.noticeRemove(_this.attr("id"));
|
||||
}
|
||||
else {
|
||||
core.noticeAdd(_this.attr("id"), "Format incorrect");
|
||||
} else {
|
||||
message = "<?php echo helper::translate('Format incorrect');?>";
|
||||
core.noticeAdd(_this.attr("id"), message);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Iframes et vidéos responsives
|
||||
*/
|
||||
var elementDOM = $("iframe, video, embed");
|
||||
var elementDOM = $("iframe, video, embed, object");
|
||||
// Calcul du ratio et suppression de la hauteur / largeur des iframes
|
||||
elementDOM.each(function() {
|
||||
elementDOM.each(function () {
|
||||
var _this = $(this);
|
||||
_this
|
||||
.data("ratio", _this.height() / _this.width())
|
||||
.data("maxwidth", _this.width())
|
||||
.removeAttr("width height");
|
||||
});
|
||||
// Prend la largeur du parent et détermine la hauteur à l'aide du ratio lors du resize de la fenêtre
|
||||
$(window).on("resize", function() {
|
||||
elementDOM.each(function() {
|
||||
$(window).on("resize", function () {
|
||||
elementDOM.each(function () {
|
||||
var _this = $(this);
|
||||
var width = _this.parent().first().width();
|
||||
if (width > _this.data("maxwidth")) {
|
||||
width = _this.data("maxwidth");
|
||||
}
|
||||
_this
|
||||
.width(width)
|
||||
.height(width * _this.data("ratio"));
|
||||
});
|
||||
}).trigger("resize");
|
||||
|
||||
// Ajouter l'attribut data-lity afin de faire la liaison avec lity
|
||||
//$("a[rel='data-lity']").attr("data-lity","");
|
||||
|
||||
// Ajouter la classe Gallery afin de faire la liaison avec simplelightbox
|
||||
//$("a[rel='gallery']").addClass("gallery","");
|
||||
/*
|
||||
* Header responsive
|
||||
*/
|
||||
$(window).on("resize", function () {
|
||||
var responsive = "<?php echo $this->getdata(['theme','header','imageContainer']);?>";
|
||||
if (responsive === "cover" || responsive === "contain") {
|
||||
var widthpx = "<?php echo $this->getdata(['theme','site','width']);?>";
|
||||
var width = widthpx.substr(0, widthpx.length - 2);
|
||||
var heightpx = "<?php echo $this->getdata(['theme','header','height']);?>";
|
||||
var height = heightpx.substr(0, heightpx.length - 2);
|
||||
var ratio = width / height;
|
||||
if (($(window).width() / ratio) <= height) {
|
||||
$("header").height($(window).width() / ratio);
|
||||
}
|
||||
}
|
||||
}).trigger("resize");
|
||||
|
||||
|
||||
// Appel dans init.js
|
||||
// $('.gallery').simpleLightbox();
|
||||
|
||||
};
|
||||
|
||||
|
||||
core.start();
|
||||
|
||||
/**
|
||||
* Confirmation de suppression
|
||||
*/
|
||||
$("#pageDelete").on("click", function() {
|
||||
$("#pageDelete").on("click", function () {
|
||||
var _this = $(this);
|
||||
return core.confirm("Êtes-vous sûr de vouloir supprimer cette page ?", function() {
|
||||
message = "<?php echo helper::translate('Confirmez-vous la suppression de cette page ?');?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Calcul de la luminance relative d'une couleur
|
||||
*/
|
||||
core.relativeLuminanceW3C = function(rgba) {
|
||||
core.relativeLuminanceW3C = function (rgba) {
|
||||
// Conversion en sRGB
|
||||
var RsRGB = rgba[0] / 255;
|
||||
var GsRGB = rgba[1] / 255;
|
||||
@ -369,3 +411,144 @@ core.relativeLuminanceW3C = function(rgba) {
|
||||
var B = (BsRGBA <= .03928) ? BsRGBA / 12.92 : Math.pow((BsRGBA + .055) / 1.055, 2.4);
|
||||
return .2126 * R + .7152 * G + .0722 * B;
|
||||
};
|
||||
|
||||
// Fonctions
|
||||
function setCookie(name, value, days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Define function to capitalize the first letter of a string
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
/**
|
||||
* Affiche le sous-menu quand il est sticky
|
||||
*/
|
||||
$("nav").mouseenter(function () {
|
||||
$("#navfixedlogout .navSub").css({
|
||||
'pointer-events': 'auto'
|
||||
});
|
||||
$("#navfixedconnected .navSub").css({
|
||||
'pointer-events': 'auto'
|
||||
});
|
||||
});
|
||||
$("nav").mouseleave(function () {
|
||||
$("#navfixedlogout .navSub").css({
|
||||
'pointer-events': 'none'
|
||||
});
|
||||
$("#navfixedconnected .navSub").css({
|
||||
'pointer-events': 'none'
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Chargement paresseux des images et des iframes
|
||||
*/
|
||||
$("img").attr("loading", "lazy");
|
||||
|
||||
/**
|
||||
* Effet accordéon
|
||||
*/
|
||||
$('.accordion').each(function (e) {
|
||||
// on stocke l'accordéon dans une variable locale
|
||||
var accordion = $(this);
|
||||
// on récupère la valeur data-speed si elle existe
|
||||
var toggleSpeed = accordion.attr('data-speed') || 100;
|
||||
|
||||
// fonction pour afficher un élément
|
||||
function open(item, speed) {
|
||||
// on récupère tous les éléments, on enlève l'élément actif de ce résultat, et on les cache
|
||||
accordion.find('.accordion-item').not(item).removeClass('active')
|
||||
.find('.accordion-content').slideUp(speed);
|
||||
// on affiche l'élément actif
|
||||
item.addClass('active')
|
||||
.find('.accordion-content').slideDown(speed);
|
||||
}
|
||||
|
||||
function close(item, speed) {
|
||||
accordion.find('.accordion-item').removeClass('active')
|
||||
.find('.accordion-content').slideUp(speed);
|
||||
}
|
||||
|
||||
// on initialise l'accordéon, sans animation
|
||||
open(accordion.find('.active:first'), 0);
|
||||
|
||||
// au clic sur un titre...
|
||||
accordion.on('click', '.accordion-title', function (ev) {
|
||||
ev.preventDefault();
|
||||
// Masquer l'élément déjà actif
|
||||
if ($(this).closest('.accordion-item').hasClass('active')) {
|
||||
close($(this).closest('.accordion-item'), toggleSpeed);
|
||||
} else {
|
||||
// ...on lance l'affichage de l'élément, avec animation
|
||||
open($(this).closest('.accordion-item'), toggleSpeed);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Icône du Menu Burger
|
||||
*/
|
||||
$("#toggle").click(function () {
|
||||
var changeIcon = $('#toggle').children("span");
|
||||
if ($(changeIcon).hasClass('zwiico-menu')) {
|
||||
$(changeIcon).removeClass('zwiico-menu').addClass('zwiico-cancel');
|
||||
} else {
|
||||
$(changeIcon).addClass('zwiico-menu');
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove ID Facebook from URL
|
||||
*/
|
||||
if (/^\?fbclid=/.test(location.search)) {
|
||||
location.replace(location.href.replace(/\?fbclid.+/, ""));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sélection d'une langue du site
|
||||
*/
|
||||
$("select#barSelectLanguage").on("change", function () {
|
||||
// La langue courante ne déclenche pas de chargement
|
||||
var langSelected = $(this).val();
|
||||
var langSelected = langSelected.split("/");
|
||||
// Lit le cookie de langue
|
||||
var langSession = "<?php echo isset($_SESSION['ZWII_SITE_CONTENT']) ? $_SESSION['ZWII_SITE_CONTENT'] : '';?>";
|
||||
// Découpe l'URL pour exclure le changement de page avec le thème
|
||||
var url = window.location;
|
||||
var currentUrl = url.href.split("/");
|
||||
// Change si différent, corrige le problème avec le thème et le rechargement de la langue.
|
||||
if ((currentUrl !== "?theme" ||
|
||||
currentUrl !== "theme") &&
|
||||
langSelected[6] !== langSession
|
||||
) {
|
||||
//$(location).attr("href", langUrl);
|
||||
var select = document.getElementById("barSelectLanguage");
|
||||
var selectedOption = select.options[select.selectedIndex];
|
||||
if (selectedOption.value !== "") {
|
||||
window.location = selectedOption.value; }
|
||||
}
|
||||
});
|
||||
|
||||
});
|
3988
core/core.php
3988
core/core.php
File diff suppressed because it is too large
Load Diff
56
core/include/checkup.php
Normal file
56
core/include/checkup.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Vérification de la version de PHP
|
||||
*/
|
||||
|
||||
if(version_compare(PHP_VERSION, '7.2.0', '<') ) {
|
||||
exit('PHP 7.2+ mini requis - PHP 7.2+ mini required');
|
||||
|
||||
}
|
||||
|
||||
if ( version_compare(PHP_VERSION, '8.3.999', '>') ) {
|
||||
exit('PHP 8.3 pas encore supporté, installez PHP 7.n ou PHP 8.1.n - PHP 8.3 not yet supported, install PHP 7.n or PHP 8.1.n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check les modules installés
|
||||
*/
|
||||
|
||||
$e = [
|
||||
'gd',
|
||||
'json',
|
||||
'date',
|
||||
'mbstring',
|
||||
'zip',
|
||||
'intl',
|
||||
'exif',
|
||||
'Phar',
|
||||
'fileinfo',
|
||||
'session'
|
||||
];
|
||||
$m = get_loaded_extensions();
|
||||
$b = false;
|
||||
foreach ($e as $k => $v) {
|
||||
if (array_search($v,$m) === false) {
|
||||
$b = true;
|
||||
echo '<pre><p>Module PHP : ' . $v . ' manquant - Module PHP ' . $v . ' missing.</p></pre>';
|
||||
}
|
||||
}
|
||||
if ($b)
|
||||
exit('<pre><p>ZwiiCMS ne peut pas démarrer ; activez les extensions requises dans PHP.ini- ZwiiCMS cannot start, enabled PHP missing extensions into PHP.ini</p></pre>');
|
||||
/**
|
||||
* Contrôle les htacess
|
||||
*/
|
||||
|
||||
$d = [
|
||||
'',
|
||||
'site/data/',
|
||||
'site/backup/',
|
||||
'site/tmp/',
|
||||
// 'site/i18n/', pas contrôler pour éviter les pbs de mise à jour
|
||||
];
|
||||
foreach ($d as $key) {
|
||||
if (file_exists($key . '.htaccess') === false)
|
||||
exit('<pre>ZwiiCMS ne peut pas démarrer, le fichier ' .$key . '.htaccess est manquant.<br />ZwiiCMS cannot start, file ' . $key . '.htaccess is missing.</pre>' );
|
||||
}
|
52
core/include/pre-update.php
Normal file
52
core/include/pre-update.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mise à jour avant v12
|
||||
* */
|
||||
|
||||
if (file_exists('site/data/core.json')) {
|
||||
$core = json_decode(file_get_contents('site/data/core.json'), true);
|
||||
$version = $core['core']['dataVersion'];
|
||||
// Avant version 12.0.00
|
||||
if (
|
||||
$version < 12000
|
||||
) {
|
||||
// Correspondance pour les dossiers de langue à convertir
|
||||
$languages = [
|
||||
'fr' => 'fr_FR',
|
||||
'en' => 'en_EN',
|
||||
'pt' => 'pt_PT'
|
||||
];
|
||||
// Convertit les dossiers vers la nouvelle structure
|
||||
foreach ($languages as $key => $value) {
|
||||
if (
|
||||
is_dir('site/data/' . $key) &&
|
||||
!is_dir('site/data/' . $value)
|
||||
) {
|
||||
$end = rename('site/data/' . $key, 'site/data/' . $value);
|
||||
}
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// Renomme les bases de données
|
||||
if (
|
||||
$version < 12400
|
||||
) {
|
||||
// Renommage les fichiers de données au pluriel
|
||||
$t = [
|
||||
'site/data/languages.json' => 'site/data/language.json',
|
||||
'site/data/fonts.json' => 'site/data/font.json'
|
||||
];
|
||||
foreach ($t as $k => $v) {
|
||||
if (file_exists($k)) {
|
||||
$d = file_get_contents($k);
|
||||
$d = str_replace('"' . basename($k, '.json') . '"' , '"' . basename($v, '.json') . '"', $d);
|
||||
file_put_contents($v, $d);
|
||||
unlink($k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1118
core/include/update.inc.php
Normal file
1118
core/include/update.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,14 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
/**
|
||||
|
17
core/layout/blank.php
Executable file → Normal file
17
core/layout/blank.php
Executable file → Normal file
@ -1,8 +1,8 @@
|
||||
<?php $layout = new layout($this); ?>
|
||||
<!DOCTYPE html>
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr">
|
||||
<html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$siteContent, 0, 2); ?>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php $layout->showMetaTitle(); ?>
|
||||
<?php $layout->showMetaDescription(); ?>
|
||||
@ -10,12 +10,17 @@
|
||||
<?php $layout->showMetaImage(); ?>
|
||||
<?php $layout->showFavicon(); ?>
|
||||
<?php $layout->showVendor(); ?>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showFonts(); ?>
|
||||
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
|
||||
<?php endif; ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/blank.css">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/theme.css?<?php echo md5_file('site/data/theme.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/custom.css?<?php echo md5_file('site/data/custom.css'); ?>"></head>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>theme.css?<?php echo md5_file(self::DATA_DIR.'theme.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showContent(); ?>
|
||||
<?php $layout->showScript(); ?>
|
||||
</body>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,14 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -17,4 +18,16 @@
|
||||
/* Site */
|
||||
#site {
|
||||
max-width: 600px !important;
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
|
||||
#site > section:not(.message),
|
||||
input[type='password'], input[type='text']
|
||||
{
|
||||
background-color: rgba(255, 255, 255, 1) !important;
|
||||
color: rgba(33, 34, 35, 1) !important;
|
||||
}
|
||||
|
||||
section {
|
||||
min-height: 0px;
|
||||
}
|
18
core/layout/light.php
Executable file → Normal file
18
core/layout/light.php
Executable file → Normal file
@ -1,8 +1,8 @@
|
||||
<?php $layout = new layout($this); ?>
|
||||
<!DOCTYPE html>
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr">
|
||||
<html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$siteContent, 0, 2); ?>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php $layout->showMetaTitle(); ?>
|
||||
<?php $layout->showMetaDescription(); ?>
|
||||
@ -10,15 +10,19 @@
|
||||
<?php $layout->showMetaImage(); ?>
|
||||
<?php $layout->showFavicon(); ?>
|
||||
<?php $layout->showVendor(); ?>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showFonts(); ?>
|
||||
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
|
||||
<?php endif; ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/light.css">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/theme.css?<?php echo md5_file('site/data/theme.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/custom.css?<?php echo md5_file('site/data/custom.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>theme.css?<?php echo md5_file(self::DATA_DIR.'theme.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showNotification(); ?>
|
||||
<div id="site" class="container">
|
||||
<div id="site" class="container light">
|
||||
<section><?php $layout->showContent(); ?></section>
|
||||
</div>
|
||||
<?php $layout->showScript(); ?>
|
||||
|
22
core/layout/mail.php
Executable file → Normal file
22
core/layout/mail.php
Executable file → Normal file
@ -1,7 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php echo substr(self::$siteContent, 0, 2);?>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
@ -71,7 +72,7 @@
|
||||
<div style="display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;mso-hide:all;font-family: sans-serif;">
|
||||
<?php echo $subject; ?>
|
||||
</div>
|
||||
<div style="max-width: 500px; margin: auto;" class="email-container">
|
||||
<div style="max-width: 500px; margin: auto; margin-top: 30px; border: #aaa 1px solid;" class="email-container">
|
||||
<!--[if mso]>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="500" align="center">
|
||||
<tr>
|
||||
@ -83,7 +84,7 @@
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="border-bottom: 1px solid #EBEEF2; padding: 20px; font-family: 'Open Sans', sans-serif; font-size: 19px; line-height: 24px; text-align: center; color: #212223;">
|
||||
<?php echo $this->getData(['config', 'title']); ?>
|
||||
<?php echo $this->getData(['locale', 'title']); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -109,7 +110,18 @@
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="border-top: 1px solid #EBEEF2; padding: 20px; text-align: center; font-family: 'Open Sans', sans-serif; font-size: 12px; line-height: 17px; color: #212223;">
|
||||
<a href="<?php echo helper::baseUrl(false); ?>" target="_blank"><?php echo $this->getData(['config', 'title']); ?></a>
|
||||
<a href="<?php echo helper::baseUrl(false); ?>" target="_blank">
|
||||
<?php
|
||||
if($this->getData(['module', $this->getUrl(0), 'config', 'signature' ]) === 'logo' && is_file( 'site/file/source/'. $this->getData(['module', $this->getUrl(0), 'config', 'logoUrl' ]))){
|
||||
$imageFile = helper::baseUrl(false).'site/file/source/'. $this->getData(['module', $this->getUrl(0), 'config', 'logoUrl' ]) ;
|
||||
$imageBase64 = base64_encode(file_get_contents($imageFile));
|
||||
?><img src=" data:image/<?php echo pathinfo($imageFile, PATHINFO_EXTENSION); ?>;base64,<?php echo $imageBase64; ?>" border="0" width="<?php echo $this->getData(['module', $this->getUrl(0), 'config', 'logoWidth']) ?>%" >
|
||||
<?php
|
||||
}
|
||||
else{
|
||||
echo $this->getData(['locale', 'title']);
|
||||
} ?>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
403
core/layout/main.php
Executable file → Normal file
403
core/layout/main.php
Executable file → Normal file
@ -1,8 +1,11 @@
|
||||
<?php $layout = new layout($this); ?>
|
||||
<!DOCTYPE html>
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr">
|
||||
<html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$siteContent, 0, 2); ?>">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta meta="description=" content="ZwiiCMS le CMS multilingue sans base de données">
|
||||
<meta name="generator" content="ZiiCMS https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php $layout->showMetaTitle(); ?>
|
||||
<?php $layout->showMetaDescription(); ?>
|
||||
@ -10,303 +13,205 @@
|
||||
<?php $layout->showMetaImage(); ?>
|
||||
<?php $layout->showFavicon(); ?>
|
||||
<?php $layout->showVendor(); ?>
|
||||
<?php $layout->showAnalytics(); ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/theme.css?<?php echo md5_file('site/data/theme.css'); ?>">
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>site/data/custom.css?<?php echo md5_file('site/data/custom.css'); ?>">
|
||||
<link rel="import" href="<?php echo helper::baseUrl(false); ?>site/data/head.inc.html">
|
||||
<?php $layout->showFonts(); ?>
|
||||
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
|
||||
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
|
||||
<?php endif; ?>
|
||||
<link rel="stylesheet"
|
||||
href="<?php echo helper::baseUrl(false); ?>core/layout/common.css?<?php echo md5_file('core/layout/common.css'); ?>">
|
||||
<link rel="stylesheet"
|
||||
href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>theme.css?<?php echo md5_file(self::DATA_DIR . 'theme.css'); ?>">
|
||||
<link rel="stylesheet"
|
||||
href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR . 'custom.css'); ?>">
|
||||
<!-- Détection RSS -->
|
||||
<?php if (
|
||||
($this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog'
|
||||
or $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'news')
|
||||
and $this->getData(['module', $this->getUrl(0), 'config', 'feeds']) === TRUE
|
||||
): ?>
|
||||
<link rel="alternate" type="application/rss+xml"
|
||||
href="'<?php echo helper::baseUrl() . $this->getUrl(0) . '/rss'; ?>" title="fLUX rss">
|
||||
<?php endif; ?>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showInlineStyle(); ?>
|
||||
<!-- Script perso dans le header -->
|
||||
<?php if (file_exists(self::DATA_DIR . 'head.inc.html')) {
|
||||
include(self::DATA_DIR . 'head.inc.html');
|
||||
} ?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php $layout->showStyle(); ?>
|
||||
<?php $layout->showBar(); ?>
|
||||
<?php $layout->showNotification(); ?>
|
||||
<?php if($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top' ): ?>
|
||||
<!-- Barre d'administration -->
|
||||
<?php if ($this->getUser('group') > self::GROUP_MEMBER): ?>
|
||||
<?php $layout->showBar(); ?>
|
||||
<?php endif; ?>
|
||||
<!-- Notifications -->
|
||||
<?php $layout->showNotification(); ?>
|
||||
<!-- Menu dans le fond du site avant la bannière -->
|
||||
<nav
|
||||
<?php if ($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top'): ?>
|
||||
<!-- Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté -->
|
||||
<?php
|
||||
// Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté
|
||||
//
|
||||
if($this->getData(['theme', 'menu', 'position']) === 'top' &&
|
||||
$this->getData(['theme', 'menu', 'fixed']) === true) {
|
||||
if ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD'))
|
||||
{echo 'id="navfixedlogout"';}
|
||||
elseif ($this->getUrl(0) !== 'theme')
|
||||
{echo 'id="navfixedconnected"';}
|
||||
if (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'top'
|
||||
and $this->getData(['theme', 'menu', 'fixed']) === true
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') > self::GROUP_MEMBER
|
||||
) {
|
||||
echo '<nav id="navfixedconnected" >';
|
||||
} else {
|
||||
echo '<nav id="navfixedlogout" >';
|
||||
}
|
||||
?>
|
||||
>
|
||||
<div id="toggle"><?php echo template::ico('menu'); ?></div>
|
||||
<div id="menu" class="
|
||||
<?php if($this->getData(['theme', 'menu', 'position']) === 'top'){echo 'container-large';}else{echo'container';}
|
||||
?>">
|
||||
|
||||
<?php $layout->showMenu(); ?>
|
||||
<!-- Menu Burger -->
|
||||
<div id="toggle">
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
|
||||
<?php echo template::ico('menu', ['fontSize' => '2em']); ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php if($this->getData(['theme', 'header', 'position']) === 'body'): ?>
|
||||
<!-- Bannière dans le fond du site -->
|
||||
<header>
|
||||
<!-- fin du menu burger -->
|
||||
<?php
|
||||
if ($this->getData(['theme','header','linkHome'])){
|
||||
echo "<a href='" . helper::baseUrl(false) . "'>" ;} ?>
|
||||
<?php if(
|
||||
$menuClass = $this->getData(['theme', 'menu', 'position']) === 'top' ? 'class="container-large"' : 'class="container"';
|
||||
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
|
||||
?>
|
||||
<div id="menu" <?php echo $menuClass; ?>>
|
||||
<?php $layout->showMenu(); ?>
|
||||
</div> <!--fin menu -->
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<!-- Bannière dans le fond du site -->
|
||||
<?php if ($this->getData(['theme', 'header', 'position']) === 'body'): ?>
|
||||
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '<a href="' . helper::baseUrl(false) . '">' : ''; ?>
|
||||
<?php
|
||||
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
|
||||
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
|
||||
$headerClass .= $this->getData(['theme', 'header', 'wide']) === 'none' ? '' : 'container';
|
||||
?>
|
||||
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
|
||||
<?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper'): ?>
|
||||
<?php if (
|
||||
$this->getData(['theme', 'header', 'textHide']) === false
|
||||
// Affiche toujours le titre de la bannière pour l'édition du thème
|
||||
OR ($this->getUrl(0) === 'theme' AND $this->getUrl(1) === 'header')
|
||||
or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header')
|
||||
): ?>
|
||||
<div class="container">
|
||||
<span><?php echo $this->getData(['config', 'title']); ?></span>
|
||||
<span id="themeHeaderTitle">
|
||||
<?php echo $this->getData(['locale', 'title']); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span id="themeHeaderTitle"> </span>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<div id="featureContent">
|
||||
<?php echo $this->getData(['theme', 'header', 'featureContent']); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
if ($this->getData(['theme','header','linkHome'])){echo "</a>";}
|
||||
?>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($this->getData(['theme', 'menu', 'position']) === 'body-second'): ?>
|
||||
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '</a>' : ''; ?>
|
||||
<?php endif; ?>
|
||||
<!-- Menu dans le fond du site après la bannière -->
|
||||
<?php if ($this->getData(['theme', 'menu', 'position']) === 'body-second'): ?>
|
||||
<nav>
|
||||
<div id="toggle"><?php echo template::ico('menu'); ?></div>
|
||||
<div id="menu" class="container">
|
||||
<!-- Menu burger -->
|
||||
<div id="toggle">
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
|
||||
<?php echo template::ico('menu', ['fontSize' => '2em']); ?>
|
||||
</div>
|
||||
<!-- fin du menu burger -->
|
||||
<?php
|
||||
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
|
||||
?>
|
||||
<div id="menu" <?php echo $menuClass; ?>>
|
||||
<?php $layout->showMenu(); ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<!-- Site -->
|
||||
<div id="site" class="container">
|
||||
<?php if($this->getData(['theme', 'menu', 'position']) === 'site-first'): ?>
|
||||
<?php endif; ?>
|
||||
<!-- Site -->
|
||||
<div id="site" class="container">
|
||||
<?php if ($this->getData(['theme', 'menu', 'position']) === 'site-first'): ?>
|
||||
<!-- Menu dans le site avant la bannière -->
|
||||
<nav>
|
||||
<div id="toggle"><?php echo template::ico('menu'); ?></div>
|
||||
<div id="toggle">
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
|
||||
<?php echo template::ico('menu', ['fontSize' => '2em']); ?>
|
||||
</div>
|
||||
<div id="menu" class="container">
|
||||
<?php $layout->showMenu(); ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php if(
|
||||
<?php if (
|
||||
$this->getData(['theme', 'header', 'position']) === 'site'
|
||||
// Affiche toujours la bannière pour l'édition du thème
|
||||
OR (
|
||||
$this->getData(['theme', 'header', 'position']) === 'hide'
|
||||
AND $this->getUrl(0) === 'theme'
|
||||
or ($this->getData(['theme', 'header', 'position']) === 'hide'
|
||||
and $this->getUrl(0) === 'theme'
|
||||
)
|
||||
): ?>
|
||||
<!-- Bannière dans le site -->
|
||||
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '<a href="' . helper::baseUrl(false) . '">' : ''; ?>
|
||||
<?php
|
||||
if ($this->getData(['theme','header','linkHome'])){
|
||||
echo "<a href='" . helper::baseUrl(false) . "'>" ;} ?>
|
||||
<header <?php if($this->getData(['theme', 'header', 'position']) === 'hide'): ?>class="displayNone"<?php endif; ?>>
|
||||
<?php if(
|
||||
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
|
||||
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
|
||||
?>
|
||||
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
|
||||
<?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper'): ?>
|
||||
<?php if (
|
||||
$this->getData(['theme', 'header', 'textHide']) === false
|
||||
// Affiche toujours le titre de la bannière pour l'édition du thème
|
||||
OR ($this->getUrl(0) === 'theme' AND $this->getUrl(1) === 'header')
|
||||
or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header')
|
||||
): ?>
|
||||
<div class="container">
|
||||
<span><?php echo $this->getData(['config', 'title']); ?></span>
|
||||
</div>
|
||||
<span id="themeHeaderTitle">
|
||||
<?php echo $this->getData(['locale', 'title']); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span id="themeHeaderTitle"> </span>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<div id="featureContent">
|
||||
<?php echo $this->getData(['theme', 'header', 'featureContent']); ?>
|
||||
</diV>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
<?php
|
||||
if ($this->getData(['theme','header','linkHome'])){echo "</a>";} ?>
|
||||
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '</a>' : ''; ?>
|
||||
<?php endif; ?>
|
||||
<?php if(
|
||||
<?php if (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'site-second' ||
|
||||
$this->getData(['theme', 'menu', 'position']) === 'site'
|
||||
// Affiche toujours le menu pour l'édition du thème
|
||||
OR (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'hide'
|
||||
AND $this->getUrl(0) === 'theme'
|
||||
or ($this->getData(['theme', 'menu', 'position']) === 'hide'
|
||||
and $this->getUrl(0) === 'theme'
|
||||
)
|
||||
): ?>
|
||||
<!-- Menu dans le site après la bannière -->
|
||||
<nav <?php if($this->getData(['theme', 'menu', 'position']) === 'hide'): ?>class="displayNone"<?php endif; ?>>
|
||||
<div id="toggle"><?php echo template::ico('menu'); ?></div>
|
||||
<nav <?php if ($this->getData(['theme', 'menu', 'position']) === 'hide'): ?>class="displayNone" <?php endif; ?>>
|
||||
<div id="toggle">
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
|
||||
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
|
||||
<?php echo template::ico('menu', ['fontSize' => '2em']); ?>
|
||||
</div>
|
||||
<div id="menu" class="container">
|
||||
<?php $layout->showMenu(); ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<!-- Corps de page -->
|
||||
<section>
|
||||
<?php
|
||||
// Gabarit :
|
||||
// Récupérer la config de la page courante
|
||||
$blocks = explode('-',$this->getData(['page',$this->getUrl(0),'block']));
|
||||
// recherche si la seconde URL fait référence à un article pour appliquer les barres
|
||||
$blogItem = false;
|
||||
if (is_array ($this->getdata(['module',$this->getData(['page', $this->getUrl(0), 'moduleId'])]))) {
|
||||
$blogItem = array_key_exists($this->getUrl(1),$this->getdata(['module',$this->getData(['page', $this->getUrl(0), 'moduleId'])]));
|
||||
}
|
||||
// Initialiser
|
||||
$blockleft=$blockright="";
|
||||
switch (sizeof($blocks)) {
|
||||
case 1 : // une colonne
|
||||
$content = 'col'. $blocks[0] ;
|
||||
break;
|
||||
case 2 : // 2 blocks
|
||||
if ($blocks[0] < $blocks[1]) { // détermine la position de la colonne
|
||||
$blockleft = 'col'. $blocks[0];
|
||||
$content = 'col'. $blocks[1] ;
|
||||
} else {
|
||||
$content = 'col' . $blocks[0];
|
||||
$blockright = 'col' . $blocks[1];
|
||||
}
|
||||
break;
|
||||
case 3 : // 3 blocks
|
||||
$blockleft = 'col' . $blocks[0];
|
||||
$content = 'col' . $blocks[1];
|
||||
$blockright = 'col' . $blocks[2];
|
||||
}
|
||||
// Page pleine pour la configuration des modules et l'édition des pages sauf l'affichae d'un article de blog
|
||||
if ((sizeof($blocks) === 1 ||
|
||||
!empty($this->getUrl(1))) &&
|
||||
$blogItem === false
|
||||
) { // Pleine page en mode configuration
|
||||
$layout->showContent();
|
||||
} else {
|
||||
?>
|
||||
<div class="row siteContainer">
|
||||
<?php
|
||||
if ($blockleft !== "") :?>
|
||||
<div class="<?php echo $blockleft; ?>" id="contentLeft">
|
||||
<?php $layout->showBarContentLeft(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="<?php echo $content; ?>
|
||||
" id="contentSite"><?php $layout->showContent(); ?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
if ($blockright !== "") :?>
|
||||
<div class="<?php echo $blockright; ?>" id="contentRight">
|
||||
<?php $layout->showBarContentRight(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</section>
|
||||
<?php $layout->showMain(); ?>
|
||||
<!-- footer -->
|
||||
<?php if(
|
||||
$this->getData(['theme', 'footer', 'position']) === 'site'
|
||||
// Affiche toujours le pied de page pour l'édition du thème
|
||||
OR (
|
||||
$this->getData(['theme', 'footer', 'position']) === 'hide'
|
||||
AND $this->getUrl(0) === 'theme'
|
||||
)
|
||||
): ?>
|
||||
<!-- Pied de page dans le site -->
|
||||
|
||||
<footer <?php if($this->getData(['theme', 'footer', 'position']) === 'hide'): ?>class="displayNone"<?php endif; ?>>
|
||||
<div class="container">
|
||||
<div class="row" id="footersite">
|
||||
<div class="col4" id="footersiteLeft"> <!-- bloc gauche -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'left') {
|
||||
$layout->showFooterText();}
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'left') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'left') {
|
||||
$layout->showCopyright(); }
|
||||
?>
|
||||
<?php $layout->showFooter(); ?>
|
||||
<!-- Fin du site -->
|
||||
<?php echo $this->getData(['theme', 'footer', 'position']) === 'site' ? '</div>' : ''; ?>
|
||||
<!-- Lien remonter en haut -->
|
||||
<div id="backToTop">
|
||||
<?php echo template::ico('up'); ?>
|
||||
</div>
|
||||
<div class="col4" id="footersiteCenter"> <!-- bloc central -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'center') {
|
||||
$layout->showFooterText(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'center') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'center') {
|
||||
$layout->showCopyright(); }
|
||||
?>
|
||||
</div>
|
||||
<div class="col4" id="footersiteRight"> <!-- bloc droite -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'right') {
|
||||
$layout->showFooterText(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'right') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'right') {
|
||||
$layout->showCopyright(); }
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if($this->getData(['theme', 'footer', 'position']) === 'body'): ?>
|
||||
<!-- Pied de page dans le fond du site -->
|
||||
<footer>
|
||||
<div class="container-large">
|
||||
<div class="row" id="footerbody">
|
||||
<div class="col4" id="footerbodyLeft"> <!-- bloc gauche -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'left') {
|
||||
$layout->showFooterText(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'left') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'left') {
|
||||
$layout->showCopyright(); }
|
||||
?>
|
||||
</div>
|
||||
<div class="col4" id="footerbodyCenter"> <!-- bloc central -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'center') {
|
||||
$layout->showFooterText(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'center') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'center') {
|
||||
$layout->showCopyright(); }
|
||||
?>
|
||||
</div>
|
||||
<div class="col4" id="footerbodyRight"> <!-- bloc droite -->
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'textPosition']) === 'right') {
|
||||
$layout->showFooterText(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'socialsPosition']) === 'right') {
|
||||
$layout->showSocials(); }
|
||||
?>
|
||||
<?php
|
||||
if($this->getData(['theme', 'footer', 'copyrightPosition']) === 'right') {
|
||||
$layout->showCopyright();}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
<!-- Lien remonter en haut -->
|
||||
<div id="backToTop"><?php echo template::ico('up'); ?></div>
|
||||
<?php $layout->showScript();?>
|
||||
<?php
|
||||
// Fichier include
|
||||
if (file_exists('site/data/script.inc.php')) {
|
||||
include ('site/data/script.inc.php');
|
||||
}
|
||||
?>
|
||||
<!-- Affichage du consentement aux cookies-->
|
||||
<?php $layout->showCookies(); ?>
|
||||
<!-- Les scripts -->
|
||||
<?php $layout->showScript(); ?>
|
||||
<!-- Script perso dans body -->
|
||||
<?php if (file_exists(self::DATA_DIR . 'body.inc.html')) {
|
||||
include(self::DATA_DIR . 'body.inc.html');
|
||||
} ?>
|
||||
</body>
|
||||
|
||||
</html>
|
855
core/module/config/config.php
Executable file → Normal file
855
core/module/config/config.php
Executable file → Normal file
@ -8,18 +8,30 @@
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class config extends common {
|
||||
class config extends common
|
||||
{
|
||||
|
||||
public static $actions = [
|
||||
'backup' => self::GROUP_ADMIN,
|
||||
'copyBackups' => self::GROUP_ADMIN,
|
||||
'delBackups' => self::GROUP_ADMIN,
|
||||
'configMetaImage' => self::GROUP_ADMIN,
|
||||
'generateFiles' => self::GROUP_ADMIN,
|
||||
'updateRobots' => self::GROUP_ADMIN,
|
||||
'index' => self::GROUP_ADMIN
|
||||
'sitemap' => self::GROUP_ADMIN,
|
||||
'index' => self::GROUP_ADMIN,
|
||||
'restore' => self::GROUP_ADMIN,
|
||||
'updateBaseUrl' => self::GROUP_ADMIN,
|
||||
'script' => self::GROUP_ADMIN,
|
||||
'logReset' => self::GROUP_ADMIN,
|
||||
'logDownload' => self::GROUP_ADMIN,
|
||||
'blacklistReset' => self::GROUP_ADMIN,
|
||||
'blacklistDownload' => self::GROUP_ADMIN,
|
||||
'register' => self::GROUP_ADMIN,
|
||||
];
|
||||
|
||||
public static $timezones = [
|
||||
@ -137,226 +149,795 @@ class config extends common {
|
||||
'Pacific/Fiji' => '(GMT+12:00) Fiji',
|
||||
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka'
|
||||
];
|
||||
// Nombre d'objets par page
|
||||
public static $ItemsList = [
|
||||
5 => '5 articles',
|
||||
10 => '10 articles',
|
||||
15 => '15 articles',
|
||||
20 => '20 articles'
|
||||
// Type de proxy
|
||||
public static $proxyType = [
|
||||
'tcp://' => 'TCP',
|
||||
'http://' => 'HTTP'
|
||||
];
|
||||
// Authentification SMTP
|
||||
public static $SMTPauth = [
|
||||
true => 'Oui',
|
||||
false => 'Non'
|
||||
];
|
||||
// Encryptation SMTP
|
||||
public static $SMTPEnc = [
|
||||
'' => 'Aucune',
|
||||
'tls' => 'START TLS',
|
||||
'ssl' => 'SSL/TLS'
|
||||
];
|
||||
// Sécurité de la connexion - tentative max avant blocage
|
||||
public static $connectAttempt = [
|
||||
999 => 'Sécurité désactivée',
|
||||
3 => '3 tentatives',
|
||||
5 => '5 tentatives',
|
||||
10 => '10 tentatives'
|
||||
];
|
||||
// Sécurité de la connexion - durée du blocage
|
||||
public static $connectTimeout = [
|
||||
0 => 'Sécurité désactivée',
|
||||
300 => '5 minutes',
|
||||
600 => '10 minutes',
|
||||
900 => '15 minutes'
|
||||
];
|
||||
// Anonymisation des IP du journal
|
||||
public static $anonIP = [
|
||||
4 => 'Non tronquée',
|
||||
3 => 'Niveau 1 (192.168.12.x)',
|
||||
2 => 'Niveau 2 (192.168.x.x)',
|
||||
1 => 'Niveau 3 (192.x.x.x)',
|
||||
];
|
||||
public static $captchaTypes = [
|
||||
'num' => 'Chiffres',
|
||||
'alpha' => 'Lettres'
|
||||
];
|
||||
public static $updateDelay = [
|
||||
86400 => '1',
|
||||
172800 => '2',
|
||||
345600 => '4',
|
||||
604800 => '7',
|
||||
1209600 => '14',
|
||||
];
|
||||
|
||||
// Langue traduite courante
|
||||
public static $i18nSite = 'fr_FR';
|
||||
|
||||
public function generateFiles() {
|
||||
// Mettre à jour le site map
|
||||
$successSitemap=$this->createSitemap('all');
|
||||
// Variable pour construire la liste des pages du site
|
||||
public static $onlineVersion = '';
|
||||
public static $updateButtonText = 'Réinstaller';
|
||||
|
||||
public static $imageOpenGraph = [];
|
||||
|
||||
/**
|
||||
* Génére les fichiers pour les crawlers
|
||||
* Sitemap compressé et non compressé
|
||||
* Robots.txt
|
||||
*/
|
||||
public function sitemap()
|
||||
{
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
// Mettre à jour le site map
|
||||
$successSitemap = $this->updateSitemap();
|
||||
|
||||
// Creer un fichier robots.txt
|
||||
$successRobots=$this->updateRobots();
|
||||
if ( $successSitemap === true &&
|
||||
$successRobots >= 100) {
|
||||
$success = true;
|
||||
} else {
|
||||
$success = false;
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => ($successSitemap === true && $successRobots >= 100) ? 'Création réussie' : 'Echec d\'écriture',
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'state' => ($successSitemap === true && $successRobots >=100) ? true : false
|
||||
'notification' => $successSitemap ? helper::translate('La carte du site a été mise à jour') : helper::translate('Echec de l\'écriture, vérifiez les permissions'),
|
||||
'state' => $successSitemap
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un fichier robots.txt lors du changement de réécriture
|
||||
*/
|
||||
}
|
||||
|
||||
public function updateRobots() {
|
||||
// Créer le fichier robot si absent
|
||||
if (!file_exists('robots.txt')) {
|
||||
$this->createRobots();
|
||||
}
|
||||
// backup
|
||||
rename ('robots.txt','robots.bak');
|
||||
$fileold = fopen('robots.bak','r');
|
||||
$filenew = fopen('robots.txt','w');
|
||||
while(!feof($fileold)) {
|
||||
$data = fgets($fileold);
|
||||
if (strpos($data,'sitemap.xml') == 0) {
|
||||
fwrite($filenew, $data);
|
||||
} else {
|
||||
fwrite($filenew, 'Sitemap: ' . helper::baseUrl() . 'sitemap.xml' . PHP_EOL);
|
||||
fwrite($filenew, 'Sitemap: ' . helper::baseUrl() . 'sitemap.xml.gz' . PHP_EOL);
|
||||
fwrite($filenew, '# ZWII CONFIG ---------' . PHP_EOL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose($fileold);
|
||||
unlink('robots.bak');
|
||||
return(fclose($filenew));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sauvegarde des données
|
||||
*/
|
||||
public function backup() {
|
||||
|
||||
public function backup()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
// Creation du ZIP
|
||||
$fileName = date('Y-m-d-h-i-s', time()) . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
if($zip->open('site/tmp/' . $fileName, ZipArchive::CREATE) === TRUE){
|
||||
foreach(configHelper::scanDir('site/') as $file) {
|
||||
$zip->addFile($file);
|
||||
$filter = $this->getInput('configBackupOption', helper::FILTER_BOOLEAN) === true ? ['backup', 'tmp'] : ['backup', 'tmp', 'file'];
|
||||
$fileName = helper::autoBackup(self::TEMP_DIR, $filter);
|
||||
// Créer le répertoire manquant
|
||||
if (!is_dir(self::FILE_DIR . 'source/backup')) {
|
||||
mkdir(self::FILE_DIR . 'source/backup', 0755);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
// Téléchargement du ZIP
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
||||
header('Content-Length: ' . filesize('site/tmp/' . $fileName));
|
||||
readfile('site/tmp/' . $fileName);
|
||||
// Copie dans les fichiers
|
||||
$success = copy(self::TEMP_DIR . $fileName, self::FILE_DIR . 'source/backup/' . $fileName);
|
||||
// Détruire le temporaire
|
||||
unlink(self::TEMP_DIR . $fileName);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_RAW
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => json_encode($success)
|
||||
]);
|
||||
unlink('site/tmp/' . $fileName);
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Sauvegarder'),
|
||||
'view' => 'backup'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Réalise une copie d'écran du site
|
||||
* https://www.codexworld.com/capture-screenshot-website-url-php-google-api/
|
||||
*/
|
||||
public function configMetaImage() {
|
||||
public function configMetaImage()
|
||||
{
|
||||
// fonction désactivée pour un site local
|
||||
if ( strpos(helper::baseUrl(false),'localhost') > 0 OR strpos(helper::baseUrl(false),'127.0.0.1') > 0) {
|
||||
$site = 'https://zwiicms.com/'; } else {
|
||||
$site = helper::baseUrl(false); }
|
||||
if (strpos(helper::baseUrl(false), 'localhost') > 0 or strpos(helper::baseUrl(false), '127.0.0.1') > 0) {
|
||||
$site = 'https://zwiicms.fr/';
|
||||
} else {
|
||||
$site = helper::baseUrl(false);
|
||||
}
|
||||
|
||||
$googlePagespeedData = file_get_contents('https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url='. $site .'&screenshot=true');
|
||||
$googlePagespeedData = json_decode($googlePagespeedData, true);
|
||||
$screenshot = $googlePagespeedData['screenshot']['data'];
|
||||
$screenshot = str_replace(array('_','-'),array('/','+'),$screenshot);
|
||||
$data = 'data:image/jpeg;base64,'.$screenshot;
|
||||
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data));
|
||||
file_put_contents( 'site/file/source/screenshot.png',$data);
|
||||
// Clé de l'API
|
||||
$token = $this->getData(['config', 'seo', 'keyApi']);
|
||||
|
||||
// Succès de l'opération par défaut
|
||||
$success = false;
|
||||
$data = false;
|
||||
|
||||
// lire l'API si le token est fourni
|
||||
if (!empty($token)) {
|
||||
// Tente de connecter 5 fois l'API
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$data = helper::getUrlContents('https://shot.screenshotapi.net/screenshot?token=' . $token . '&url=' . $site . '&width=1200&height=627&output=json&file_type=jpeg&no_cookie_banners=true&wait_for_event=load');
|
||||
if ($data !== false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traitement des données reçues valides.
|
||||
if (!empty($token) && $data !== false) {
|
||||
$data = json_decode($data, true);
|
||||
$img = $data['screenshot'];
|
||||
// Effacer l'image et la miniature png
|
||||
if (file_exists(self::FILE_DIR . 'thumb/screenshot.jpg')) {
|
||||
unlink(self::FILE_DIR . 'thumb/screenshot.jpg');
|
||||
}
|
||||
if (file_exists(self::FILE_DIR . 'source/screenshot.jpg')) {
|
||||
unlink(self::FILE_DIR . 'source/screenshot.jpg');
|
||||
}
|
||||
$success = copy($img, self::FILE_DIR . 'source/screenshot.jpg');
|
||||
}
|
||||
|
||||
$notification = empty($token)
|
||||
? 'La clé de l\'API ne peut pas être vide'
|
||||
: ($success === false ? 'Service en ligne inaccessible' : 'Capture d\'écran générée avec succès');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => 'Image tag réinitialisée',
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'state' => true
|
||||
'notification' => helper::translate($notification),
|
||||
'state' => ($success === false or empty($token)) ? false : true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Procédure d'importation
|
||||
*/
|
||||
public function restore()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
$success = false;
|
||||
|
||||
if ($this->getInput('configRestoreImportFile', null, true)) {
|
||||
|
||||
$fileZip = $this->getInput('configRestoreImportFile');
|
||||
$file_parts = pathinfo($fileZip);
|
||||
// Validité du nom du fichier sélectionné
|
||||
if ($file_parts['extension'] !== 'zip') {
|
||||
// Valeurs en sortie erreur
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Restaurer'),
|
||||
'view' => 'restore',
|
||||
'notification' => helper::translate('Archive invalide'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
// Ouverture de l'archive
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open(self::FILE_DIR . 'source/' . $fileZip) === FALSE) {
|
||||
// Valeurs en sortie erreur
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Restaurer'),
|
||||
'view' => 'restore',
|
||||
'notification' => helper::translate('Archive invalide'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Extraction de l'archive dans un dossier temporaire
|
||||
$tmpDir = uniqid(8);
|
||||
$success = $zip->extractTo(self::TEMP_DIR . $tmpDir);
|
||||
// Version de l'archive
|
||||
$data = json_decode(file_get_contents(self::TEMP_DIR . $tmpDir . '/data/core.json'), true);
|
||||
$dataVersion = $data['core']['dataVersion'];
|
||||
// Version non prises en charge <9 ou erreur d'extraction
|
||||
if (intval(substr($dataVersion, 0, 1)) <= 9 or !$success) {
|
||||
// Valeurs en sortie erreur
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Restaurer'),
|
||||
'view' => 'restore',
|
||||
'notification' => helper::translate('Archive invalide'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Fermer le zip
|
||||
$zip->close();
|
||||
|
||||
// Option active, préservation des utilisateurs
|
||||
if ($this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true) {
|
||||
$users = $this->getData(['user']);
|
||||
}
|
||||
|
||||
// Copie dans le dossier /site/data
|
||||
$success = $this->copyDir(self::TEMP_DIR . $tmpDir, 'site/');
|
||||
$this->deleteDir(self::TEMP_DIR . $tmpDir);
|
||||
|
||||
// Restaurer les users originaux d'une v10 si option cochée
|
||||
if (
|
||||
$this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true
|
||||
) {
|
||||
$this->setData(['user', $users]);
|
||||
}
|
||||
}
|
||||
|
||||
// Message de notification
|
||||
$notification = $success === true ? 'Restauration effectuée avec succès' : 'Erreur inconnue';
|
||||
$redirect = $this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true ? helper::baseUrl() . 'config/restore' : helper::baseUrl() . 'user/login/';
|
||||
// Valeurs en sortie erreur
|
||||
$this->addOutput([
|
||||
'redirect' => $redirect,
|
||||
'notification' => helper::translate($notification),
|
||||
'state' => $success
|
||||
]);
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Restaurer'),
|
||||
'view' => 'restore'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*/
|
||||
public function index() {
|
||||
public function index()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if($this->isPost()) {
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
// Basculement en mise à jour auto, remise à 0 du compteur
|
||||
if (
|
||||
$this->getData(['config', 'autoUpdate']) === false &&
|
||||
$this->getInput('configAutoUpdate', helper::FILTER_BOOLEAN) === true
|
||||
) {
|
||||
$this->setData(['core', 'lastAutoUpdate', 0]);
|
||||
}
|
||||
|
||||
// Sauvegarder la configuration
|
||||
$this->setData([
|
||||
'config',
|
||||
[
|
||||
'analyticsId' => $this->getInput('configAnalyticsId'),
|
||||
'favicon' => $this->getInput('configFavicon'),
|
||||
'faviconDark' => $this->getInput('configFaviconDark'),
|
||||
'timezone' => $this->getInput('configTimezone', helper::FILTER_STRING_SHORT, true),
|
||||
'autoUpdate' => $this->getInput('configAutoUpdate', helper::FILTER_BOOLEAN),
|
||||
'autoUpdateHtaccess' => $this->getInput('configAutoUpdateHtaccess', helper::FILTER_BOOLEAN),
|
||||
'autoBackup' => $this->getInput('configAutoBackup', helper::FILTER_BOOLEAN),
|
||||
'maintenance' => $this->getInput('configMaintenance', helper::FILTER_BOOLEAN),
|
||||
'cookieConsent' => $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN),
|
||||
'favicon' => $this->getInput('configFavicon'),
|
||||
'homePageId' => $this->getInput('configHomePageId', helper::FILTER_ID, true),
|
||||
'metaDescription' => $this->getInput('configMetaDescription', helper::FILTER_STRING_LONG, true),
|
||||
'proxyType' => $this->getInput('configProxyType'),
|
||||
'proxyUrl' => $this->getInput('configProxyUrl'),
|
||||
'proxyPort' => $this->getInput('configProxyPort', helper::FILTER_INT),
|
||||
'autoUpdateDelay' => $this->getInput('configAutoUpdateDelay', helper::FILTER_INT),
|
||||
'social' => [
|
||||
'facebookId' => $this->getInput('configSocialFacebookId'),
|
||||
'linkedinId' => $this->getInput('configSocialLinkedinId'),
|
||||
'instagramId' => $this->getInput('configSocialInstagramId'),
|
||||
'pinterestId' => $this->getInput('configSocialPinterestId'),
|
||||
'twitterId' => $this->getInput('configSocialTwitterId'),
|
||||
'youtubeId' => $this->getInput('configSocialYoutubeId')
|
||||
'facebookId' => $this->getInput('socialFacebookId'),
|
||||
'linkedinId' => $this->getInput('socialLinkedinId'),
|
||||
'instagramId' => $this->getInput('socialInstagramId'),
|
||||
'pinterestId' => $this->getInput('socialPinterestId'),
|
||||
'twitterId' => $this->getInput('socialTwitterId'),
|
||||
'youtubeId' => $this->getInput('socialYoutubeId'),
|
||||
'youtubeUserId' => $this->getInput('socialYoutubeUserId'),
|
||||
'githubId' => $this->getInput('socialGithubId'),
|
||||
'redditId' => $this->getInput('socialRedditId'),
|
||||
'twitchId' => $this->getInput('socialTwitchId'),
|
||||
'vimeoId' => $this->getInput('socialVimeoId'),
|
||||
'steamId' => $this->getInput('socialSteamId'),
|
||||
],
|
||||
'timezone' => $this->getInput('configTimezone', helper::FILTER_STRING_SHORT, true),
|
||||
'title' => $this->getInput('configTitle', helper::FILTER_STRING_SHORT, true),
|
||||
'itemsperPage' => $this->getInput('itemsperPage', helper::FILTER_INT,true)
|
||||
'smtp' => [
|
||||
'enable' => $this->getInput('smtpEnable', helper::FILTER_BOOLEAN),
|
||||
'host' => $this->getInput('smtpHost', helper::FILTER_STRING_SHORT),
|
||||
'port' => $this->getInput('smtpPort', helper::FILTER_INT),
|
||||
'auth' => $this->getInput('smtpAuth', helper::FILTER_BOOLEAN),
|
||||
'secure' => $this->getInput('smtpSecure', helper::FILTER_STRING_SHORT),
|
||||
'username' => $this->getInput('smtpUsername', helper::FILTER_STRING_SHORT),
|
||||
'password' => helper::encrypt($this->getInput('smtpPassword', helper::FILTER_STRING_SHORT), $this->getInput('smtpHost', helper::FILTER_STRING_SHORT)),
|
||||
'from' => $this->getInput('smtpFrom', helper::FILTER_MAIL, true),
|
||||
],
|
||||
'seo' => [
|
||||
'robots' => $this->getInput('seoRobots', helper::FILTER_BOOLEAN),
|
||||
'openGraphImage' => $this->getInput('seoOpenGraphImage', helper::FILTER_STRING_SHORT),
|
||||
],
|
||||
'connect' => [
|
||||
'attempt' => $this->getInput('connectAttempt', helper::FILTER_INT),
|
||||
'timeout' => $this->getInput('connectTimeout', helper::FILTER_INT),
|
||||
'log' => $this->getInput('connectLog', helper::FILTER_BOOLEAN),
|
||||
'anonymousIp' => $this->getInput('connectAnonymousIp', helper::FILTER_INT),
|
||||
'captcha' => $this->getInput('connectCaptcha', helper::FILTER_BOOLEAN),
|
||||
'captchaStrong' => $this->getInput('connectCaptchaStrong', helper::FILTER_BOOLEAN),
|
||||
'autoDisconnect' => $this->getInput('connectAutoDisconnect', helper::FILTER_BOOLEAN),
|
||||
'captchaType' => $this->getInput('connectCaptchaType'),
|
||||
'showPassword' => $this->getInput('connectShowPassword', helper::FILTER_BOOLEAN),
|
||||
'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN)
|
||||
]
|
||||
]
|
||||
]);
|
||||
if(self::$inputNotices === []) {
|
||||
|
||||
// Efface les fichiers de backup lorsque l'option est désactivée
|
||||
if ($this->getInput('configFileBackup', helper::FILTER_BOOLEAN) === false) {
|
||||
$path = realpath('site/data');
|
||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
|
||||
if (strpos($filename, 'backup.json')) {
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
if (file_exists('site/data/.backup'))
|
||||
unlink('site/data/.backup');
|
||||
} else {
|
||||
touch('site/data/.backup');
|
||||
}
|
||||
// Notice
|
||||
if (self::$inputNotices === []) {
|
||||
// Active la réécriture d'URL
|
||||
$rewrite = $this->getInput('rewrite', helper::FILTER_BOOLEAN);
|
||||
if(
|
||||
$rewrite = $this->getInput('configRewrite', helper::FILTER_BOOLEAN);
|
||||
if (
|
||||
$rewrite
|
||||
AND helper::checkRewrite() === false
|
||||
and helper::checkRewrite() === false
|
||||
) {
|
||||
// Ajout des lignes dans le .htaccess
|
||||
file_put_contents(
|
||||
'.htaccess',
|
||||
PHP_EOL .
|
||||
'<ifModule mod_rewrite.c>' . PHP_EOL .
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$rewriteData =
|
||||
'# URL rewriting' . PHP_EOL .
|
||||
'<IfModule mod_rewrite.c>' . PHP_EOL .
|
||||
"\tRewriteEngine on" . PHP_EOL .
|
||||
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
|
||||
"\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL .
|
||||
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
|
||||
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
|
||||
'</ifModule>',
|
||||
FILE_APPEND
|
||||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting';
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
$this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
// Change le statut de la réécriture d'URL (pour le helper::baseUrl() de la redirection)
|
||||
helper::$rewriteStatus = true;
|
||||
}
|
||||
// Désactive la réécriture d'URL
|
||||
elseif(
|
||||
elseif (
|
||||
$rewrite === false
|
||||
AND helper::checkRewrite()
|
||||
and helper::checkRewrite()
|
||||
) {
|
||||
// Suppression des lignes dans le .htaccess
|
||||
$htaccess = explode('# URL rewriting', file_get_contents('.htaccess'));
|
||||
file_put_contents('.htaccess', $htaccess[0] . '# URL rewriting');
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$fileContent = explode('# URL rewriting', $fileContent);
|
||||
$fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2];
|
||||
$this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
// Change le statut de la réécriture d'URL (pour le helper::baseUrl() de la redirection)
|
||||
helper::$rewriteStatus = false;
|
||||
}
|
||||
}
|
||||
// Générer robots.txt et sitemap
|
||||
$this->generateFiles();
|
||||
$this->siteMap();
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $this->getUrl(),
|
||||
'notification' => 'Modifications enregistrées',
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Initialisation du screen
|
||||
if (!file_exists('site/file/source/screenshot.png')) {
|
||||
$this->configMetaImage();
|
||||
}
|
||||
|
||||
// Activation du bouton de mise à jour
|
||||
if (
|
||||
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)
|
||||
&& $this->getData(['core', 'updateAvailable']) === false
|
||||
&& $this->getData(['config', 'autoUpdate'])
|
||||
) {
|
||||
$this->setData(['core', 'updateAvailable', true]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => 'Configuration',
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
// Variable de version
|
||||
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
|
||||
self::$updateButtonText = helper::translate('Mise à jour');
|
||||
}
|
||||
|
||||
|
||||
// Sélecteur de délais, compléter avec la traduction en jours
|
||||
foreach (self::$updateDelay as $key => $value) {
|
||||
self::$updateDelay[$key] = $key === 86400 ? $value . ' ' . helper::translate('jour') : $value . ' ' . helper::translate('jours');
|
||||
}
|
||||
|
||||
// Paramètres de l'image OpenGraph
|
||||
$imagePath = self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']);
|
||||
|
||||
// Par défaut
|
||||
self::$imageOpenGraph['type'] = '';
|
||||
self::$imageOpenGraph['size'] = '';
|
||||
self::$imageOpenGraph['wide'] = '';
|
||||
self::$imageOpenGraph['height'] = '';
|
||||
self::$imageOpenGraph['ratio'] = 0;
|
||||
if (
|
||||
$this->getData(['config', 'seo', 'openGraphImage'])
|
||||
&& file_exists($imagePath)
|
||||
) {
|
||||
// Infos sur l'image Open Graph
|
||||
$typeMime = exif_imagetype($imagePath);
|
||||
switch ($typeMime) {
|
||||
case IMAGETYPE_JPEG:
|
||||
$typeMime = 'jpeg';
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$typeMime = 'png';
|
||||
break;
|
||||
default:
|
||||
$typeMime = image_type_to_mime_type($typeMime);
|
||||
}
|
||||
self::$imageOpenGraph['type'] = $typeMime;
|
||||
$imageSize = getimagesize($imagePath);
|
||||
self::$imageOpenGraph['wide'] = $imageSize[0];
|
||||
self::$imageOpenGraph['height'] = $imageSize[1];
|
||||
self::$imageOpenGraph['ratio'] = self::$imageOpenGraph['wide'] / self::$imageOpenGraph['height'];
|
||||
|
||||
self::$imageOpenGraph['size'] = filesize($imagePath);
|
||||
$tailleEnOctets = filesize($imagePath);
|
||||
|
||||
if ($tailleEnOctets >= 1024 * 1024) {
|
||||
// Si la taille est supérieure ou égale à 1 Mo, afficher en mégaoctets
|
||||
self::$imageOpenGraph['size'] = round($tailleEnOctets / (1024 * 1024), 2) . ' Mo';
|
||||
} else {
|
||||
// Sinon, afficher en kilooctets
|
||||
self::$imageOpenGraph['size'] = round($tailleEnOctets / 1024, 2) . ' Ko';
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class configHelper extends helper {
|
||||
public function script()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
// Ecrire les fichiers de script
|
||||
if ($this->geturl(2) === 'head') {
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
|
||||
}
|
||||
if ($this->geturl(2) === 'body') {
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Éditeur de script dans ' . ucfirst($this->geturl(2))),
|
||||
'vendor' => [
|
||||
'codemirror'
|
||||
],
|
||||
'view' => 'script',
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => sprintf(helper::translate('Éditeur de script %s'), ucfirst($this->geturl(2))),
|
||||
'vendor' => [
|
||||
'codemirror'
|
||||
],
|
||||
'view' => 'script'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scan le contenu d'un dossier et de ses sous-dossiers
|
||||
* @param string $dir Dossier à scanner
|
||||
* @return array
|
||||
* Vider le fichier de log
|
||||
*/
|
||||
public static function scanDir($dir) {
|
||||
$dirContent = [];
|
||||
$iterator = new DirectoryIterator($dir);
|
||||
foreach($iterator as $fileInfos) {
|
||||
if(in_array($fileInfos->getFilename(), ['.', '..', 'backup'])) {
|
||||
continue;
|
||||
}
|
||||
elseif($fileInfos->isDir()) {
|
||||
$dirContent = array_merge($dirContent, self::scanDir($fileInfos->getPathname()));
|
||||
}
|
||||
else {
|
||||
$dirContent[] = $fileInfos->getPathname();
|
||||
|
||||
public function logReset()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
if (file_exists(self::DATA_DIR . 'journal.log')) {
|
||||
unlink(self::DATA_DIR . 'journal.log');
|
||||
// Créer les en-têtes des journaux
|
||||
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Journal réinitialisé avec succès'),
|
||||
'state' => true
|
||||
]);
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Aucun journal à effacer'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $dirContent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Télécharger le fichier de log
|
||||
*/
|
||||
public function logDownload()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
$fileName = self::DATA_DIR . 'journal.log';
|
||||
if (file_exists($fileName)) {
|
||||
ob_start();
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
||||
header('Content-Length: ' . filesize($fileName));
|
||||
ob_clean();
|
||||
ob_end_flush();
|
||||
readfile($fileName);
|
||||
exit();
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Aucun fichier journal à télécharger'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tableau des IP blacklistés
|
||||
*/
|
||||
public function blacklistDownload()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
ob_start();
|
||||
$fileName = self::TEMP_DIR . 'blacklist.log';
|
||||
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
|
||||
$this->secure_file_put_contents($fileName, $d);
|
||||
if (file_exists($fileName)) {
|
||||
$d = $this->getData(['blacklist']);
|
||||
$data = '';
|
||||
foreach ($d as $key => $item) {
|
||||
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail'], self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI);
|
||||
$data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
|
||||
}
|
||||
$this->secure_file_put_contents($fileName, $data, FILE_APPEND);
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
||||
header('Content-Length: ' . filesize($fileName));
|
||||
ob_clean();
|
||||
ob_end_flush();
|
||||
readfile($fileName);
|
||||
unlink(self::TEMP_DIR . 'blacklist.log');
|
||||
exit();
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Aucune liste noire à télécharger'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Réinitialiser les ip blacklistées
|
||||
*/
|
||||
|
||||
public function blacklistReset()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
if (file_exists(self::DATA_DIR . 'blacklist.json')) {
|
||||
$this->setData(['blacklist', []]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Liste noire réinitialisée avec succès'),
|
||||
'state' => true
|
||||
]);
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => helper::translate('Aucune liste noire à effacer'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupération des backups auto dans le gestionnaire de fichiers
|
||||
*/
|
||||
public function copyBackups()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
|
||||
$success = $this->copyDir(self::BACKUP_DIR, self::FILE_DIR . 'source/backup');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => $success ? helper::translate('Copie terminée avec succès') : helper::translate('Copie terminée avec des erreurs'),
|
||||
'state' => $success
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vider le dosser des sauvegardes automatisées
|
||||
*/
|
||||
public function delBackups()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
$path = realpath(self::BACKUP_DIR);
|
||||
$success = $fail = 0;
|
||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
|
||||
if (strpos($filename, '.zip')) {
|
||||
|
||||
$r = unlink($filename);
|
||||
$success = $r === true ? $success + 1 : $success;
|
||||
$fail = $r === false ? $fail + 1 : $fail;
|
||||
}
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
'view' => 'index',
|
||||
'notification' => $success . helper::translate('Fichiers effacés') . ' - ' . helper::translate('Échecs') . ': ' . $fail,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction pour vérifier la présence du module de réécriture
|
||||
* @return bool
|
||||
*/
|
||||
public function isModRewriteEnabled()
|
||||
{
|
||||
// Check if Apache and mod_rewrite is loaded
|
||||
if (function_exists('apache_get_modules')) {
|
||||
$modules = apache_get_modules();
|
||||
return in_array('mod_rewrite', $modules);
|
||||
} else {
|
||||
// Fallback if not using Apache or unable to detect modules
|
||||
return getenv('HTTP_MOD_REWRITE') == 'On' || getenv('REDIRECT_STATUS') == '200';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
|
||||
* @return never
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->setData([
|
||||
'user',
|
||||
$this->getUser('id'),
|
||||
'view',
|
||||
[
|
||||
'config' => $this->getUrl(2),
|
||||
'page' => $this->getData(['user', $this->getUser('id'), 'view', 'page']),
|
||||
]
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config/' . $this->getUrl(2),
|
||||
]);
|
||||
}
|
||||
}
|
BIN
core/module/config/ressource/ajax-loader.png
Executable file
BIN
core/module/config/ressource/ajax-loader.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
4
core/module/config/tool/.htaccess
Normal file
4
core/module/config/tool/.htaccess
Normal file
@ -0,0 +1,4 @@
|
||||
<Files "data.key">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
47
core/module/config/tool/autobackup.php
Normal file
47
core/module/config/tool/autobackup.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour être appelé via une requête HTTP GET avec une clé spécifique pour déclencher la création d'une archive ZIP de sauvegarde.
|
||||
|
||||
Exemple d'appel dans une URL :
|
||||
http://example.com/chemin/vers/autobackup.php?key=your_secret_key
|
||||
|
||||
La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la création de l'archive soit autorisée. Si la clé est valide, le script parcourt le répertoire spécifié et ajoute les fichiers à l'archive ZIP. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
$key = $_GET['key'];
|
||||
$storedKey = file_get_contents('data.key');
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
exit();
|
||||
}
|
||||
// Création du ZIP
|
||||
$filter = ['backup', 'tmp'];
|
||||
$fileName = date('Y-m-d-H-i-s', time()) . '-rolling-backup.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open('../../../../site/backup/' . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$directory = '../../../../site';
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
http_response_code(201);
|
||||
}
|
49
core/module/config/tool/cleanautobackup.php
Normal file
49
core/module/config/tool/cleanautobackup.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour supprimer les fichiers ayant l'extension 'tar.gz' dans un répertoire de sauvegarde si leur dernière modification remonte à un certain nombre de jours spécifié via une requête HTTP GET.
|
||||
|
||||
Exemple d'appel dans une URL avec le nombre de jours spécifié :
|
||||
http://example.com/chemin/vers/script.php?days=7&key=your_secret_key
|
||||
|
||||
Le script vérifie également la présence et la validité d'une clé spécifique pour déclencher son exécution. La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la suppression des fichiers soit autorisée. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
// Récupération de la clé fournie en GET
|
||||
$key = $_GET['key'];
|
||||
|
||||
// Récupération de la clé stockée dans le fichier data.key
|
||||
$storedKey = file_get_contents('data.key');
|
||||
|
||||
// Vérification de correspondance entre les clés
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Récupère le nombre de jours à partir de la variable GET 'days'
|
||||
$days = isset ($_GET['days']) ? (int) $_GET['days'] : 1; // Par défaut à 1 si non spécifié
|
||||
|
||||
// Chemin vers le répertoire contenant les fichiers
|
||||
$directory = '../../../../site/backup/'; // Remplacez par le chemin réel
|
||||
|
||||
// Convertit le nombre de jours en secondes
|
||||
$timeLimit = strtotime("-$days days");
|
||||
|
||||
// Crée un nouvel objet DirectoryIterator
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
// Vérifie si l'élément courant est un fichier et a l'extension 'tar.gz'
|
||||
if ($file->isFile() && $file->getExtension() === 'tar.gz') {
|
||||
// Vérifie si le fichier a été modifié avant la limite de temps
|
||||
if ($file->getMTime() < $timeLimit) {
|
||||
// Supprime le fichier
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Si la clé est manquante, affiche un message d'erreur et arrête l'exécution du script
|
||||
http_response_code(201);
|
||||
}
|
18
core/module/config/view/backup/backup.css
Executable file
18
core/module/config/view/backup/backup.css
Executable file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
12
core/module/config/view/backup/backup.js.php
Normal file
12
core/module/config/view/backup/backup.js.php
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
$(document).ready((function(){$("#configBackupForm").submit((function(e){e.preventDefault();var url="<?php echo helper::baseUrl() . $this->getUrl(0); ?>/backup",message_success="<?php echo helper::translate('Sauvegarde générée avec succès'); ?>",message_error="<?php echo helper::translate('Erreur : sauvegarde non générée !'); ?>",message_title="<?php echo helper::translate('Sauvegarder'); ?>";$.ajax({type:"POST",url:url,data:$("form").serialize(),success:function(data){$("body, .button").css("cursor","default"),core.alert(message_success)},error:function(data){$("body, .button").css("cursor","default"),core.alert(message_error)},complete:function(){$("#configBackupSubmit").removeClass("disabled").prop("disabled",!1),$("#configBackupSubmit").removeClass("uniqueSubmission").prop("uniqueSubmission",!1),$("#configBackupSubmit span").removeClass("zwiico-spin animate-spin"),$("#configBackupSubmit span").addClass("zwiico-check zwiico-margin-right").text(message_title)}})})),$("#configBackupSubmit").on("click",(function(){if($("input[name=configBackupOption]").is(":checked")){var message_warning="<?php echo helper::translate('La sauvegarde des fichiers peut prendre du temps. Continuer ?'); ?>";return core.confirm(message_warning,(function(){$("body, .button").css("cursor","wait"),$("form#configBackupForm").submit()}))}}))}));
|
36
core/module/config/view/backup/backup.php
Normal file
36
core/module/config/view/backup/backup.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php echo template::formOpen('configBackupForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('configBackupBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'config',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configBackupSubmit', [
|
||||
'value' => 'Sauvegarder',
|
||||
'uniqueSubmission' => true
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Paramètres de la sauvegarde'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::checkbox('configBackupOption', true, 'Inclure le contenu du gestionnaire de fichiers', [
|
||||
'checked' => true,
|
||||
'help' => 'Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col12">
|
||||
<em>L'archive est générée dans <a href="<?php echo helper::baseUrl(false); ?>core/vendor/filemanager/dialog.php?fldr=backup&type=0&akey=<?php echo md5_file(self::DATA_DIR . 'core.json'); ?>&lang=<?php echo $this->getData(['user', $this->getUser('id'), 'language']);?>" data-lity>le dossier Backup</a> du gestionnaire de fichiers.</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
134
core/module/config/view/connect/connect.php
Normal file
134
core/module/config/view/connect/connect.php
Normal file
@ -0,0 +1,134 @@
|
||||
<div id="connectContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Sécurité de la connexion'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/connexion" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php // echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('connectShowPassword', true, 'Dévoiler le mot de passe', [
|
||||
'checked' => $this->getData(['config', 'connect', 'showPassword']),
|
||||
'help' => 'Le survol d\'une icône de l\'écran de connexion affiche temporairement le mot de passe.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('connectAutoDisconnect', true, 'Déconnexion automatique', [
|
||||
'checked' => $this->getData(['config', 'connect', 'autoDisconnect']),
|
||||
'help' => 'Déconnecte les sessions ouvertes précédemment sur d\'autres navigateurs ou terminaux. Activation recommandée.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('connectRedirectLogin', true, 'Redirection vers la connexion', [
|
||||
'checked' => $this->getData(['config', 'connect', 'redirectLogin']),
|
||||
'help' => 'Cette redirection ne concerne que les pages d\'administration du site.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::select('connectAttempt', $module::$connectAttempt, [
|
||||
'label' => 'Limitation des tentatives',
|
||||
'selected' => $this->getData(['config', 'connect', 'attempt'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('connectTimeout', $module::$connectTimeout, [
|
||||
'label' => 'Blocage après échecs',
|
||||
'selected' => $this->getData(['config', 'connect', 'timeout'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<label id="helpBlacklist"><?php echo helper::translate('Liste noire'); ?>
|
||||
<?php echo template::help(
|
||||
'La liste noire énumère les tentatives de connexion à partir de comptes inexistants. Sont stockés : la date, l\'heure, le nom du compte et l\'IP.
|
||||
Après le nombre de tentatives autorisées, l\'IP et le compte sont bloqués.'
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
<?php echo template::button('ConnectBlackListDownload', [
|
||||
'href' => helper::baseUrl() . 'config/blacklistDownload',
|
||||
'value' => 'Télécharger la liste',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('CnnectBlackListReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/blacklistReset',
|
||||
'value' => 'Réinitialiser la liste',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('connectCaptcha', true, 'Captcha à la connexion', [
|
||||
'checked' => $this->getData(['config', 'connect', 'captcha'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('connectCaptchaStrong', true, 'Captcha complexe', [
|
||||
'checked' => $this->getData(['config', 'connect', 'captchaStrong']),
|
||||
'help' => 'Option recommandée pour sécuriser la connexion. S\'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('connectCaptchaType', $module::$captchaTypes, [
|
||||
'label' => 'Type de captcha',
|
||||
'selected' => $this->getData(['config', 'connect', 'captchaType'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Journalisation'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/journalisation" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php // echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>
|
||||
-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('connectLog', true, 'Activer la journalisation', [
|
||||
'checked' => $this->getData(['config', 'connect', 'log'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('connectAnonymousIp', $module::$anonIP, [
|
||||
'label' => 'Anonymat des adresses IP',
|
||||
'selected' => $this->getData(['config', 'connect', 'anonymousIp']),
|
||||
'help' => 'La règlementation française impose un anonymat de niveau 2'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('ConfigLogDownload', [
|
||||
'href' => helper::baseUrl() . 'config/logDownload',
|
||||
'value' => 'Télécharger le journal',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('ConnectLogReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/logReset',
|
||||
'value' => 'Réinitialiser le journal',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
67
core/module/config/view/index/index.css
Executable file
67
core/module/config/view/index/index.css
Executable file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
#setupContainer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.buttonNotice {
|
||||
border: 2px solid red !important;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* Style the tab */
|
||||
.tab {
|
||||
margin-top: 1.8em;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tab~.tabContent {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.buttonTab {
|
||||
display: inline-block;
|
||||
transition: 0.3s;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
width: 160px;
|
||||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.buttonTab:hover {
|
||||
filter: saturate(200%);
|
||||
}
|
||||
|
||||
.activeButton {
|
||||
background-color: #00BFFF;
|
||||
}
|
||||
|
||||
.greenInfo, .redInfo {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.greenInfo {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.redInfo {
|
||||
color: red;
|
||||
}
|
287
core/module/config/view/index/index.js.php
Normal file
287
core/module/config/view/index/index.js.php
Normal file
@ -0,0 +1,287 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
/**
|
||||
* Confirmation de suppression
|
||||
*/
|
||||
$("#configBackupDelButton").on("click", function () {
|
||||
var _this = $(this);
|
||||
var message_warning = "<?php echo helper::translate('Supprimer toutes les sauvegardes automatiques ?'); ?>";
|
||||
return core.confirm(message_warning, function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
||||
|
||||
// Positionnement inital des options
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Afficher et masquer options smtp
|
||||
*/
|
||||
if ($("input[name=smtpEnable]").is(':checked')) {
|
||||
$("#smtpParam").addClass("disabled");
|
||||
$("#smtpParam").slideDown();
|
||||
} else {
|
||||
$("#smtpParam").removeClass("disabled");
|
||||
$("#smtpParam").slideUp();
|
||||
}
|
||||
/**
|
||||
* Afficher et masquer options Auth
|
||||
*/
|
||||
|
||||
if ($("select[name=smtpAuth]").val() == true) {
|
||||
$("#smtpAuthParam").addClass("disabled");
|
||||
$("#smtpAuthParam").slideDown();
|
||||
} else {
|
||||
$("#smtpAuthParam").removeClass("disabled");
|
||||
$("#smtpAuthParam").slideUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Afficher et masquer les options de captcha
|
||||
*/
|
||||
|
||||
if ($("input[name=connectCaptcha]").is(':checked')) {
|
||||
$("#connectCaptchaStrongWrapper").addClass("disabled");
|
||||
$("#connectCaptchaStrongWrapper").slideDown();
|
||||
$("#connectCaptchaTypeWrapper").addClass("disabled");
|
||||
$("#connectCaptchaTypeWrapper").slideDown();
|
||||
} else {
|
||||
$("#connectCaptchaStrongWrapper").removeClass("disabled");
|
||||
$("#connectCaptchaStrongWrapper").slideUp();
|
||||
$("#connectCaptchaTypeWrapper").removeClass("disabled");
|
||||
$("#connectCaptchaTypeWrapper").slideUp();
|
||||
$("#connectCaptchaStrong").prop("checked", false);
|
||||
}
|
||||
|
||||
var configLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'config']);?>";
|
||||
// Non défini, valeur par défaut
|
||||
if (configLayout == "") {
|
||||
configLayout = "setup";
|
||||
}
|
||||
|
||||
$("#socialContainer").hide();
|
||||
$("#connectContainer").hide();
|
||||
$("#networkContainer").hide();
|
||||
$("#setupContainer").hide();
|
||||
$("#" + configLayout + "Container").show();
|
||||
$("#config" + capitalizeFirstLetter(configLayout) + "Button").addClass("activeButton");
|
||||
|
||||
|
||||
// Gestion des événements
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Afficher et masquer options smtp
|
||||
*/
|
||||
$("input[name=smtpEnable]").on("change", function () {
|
||||
if ($("input[name=smtpEnable]").is(':checked')) {
|
||||
$("#smtpParam").addClass("disabled");
|
||||
$("#smtpParam").slideDown();
|
||||
} else {
|
||||
$("#smtpParam").removeClass("disabled");
|
||||
$("#smtpParam").slideUp();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Afficher et masquer options Auth
|
||||
*/
|
||||
|
||||
$("select[name=smtpAuth]").on("change", function () {
|
||||
if ($("select[name=smtpAuth]").val() == true) {
|
||||
$("#smtpAuthParam").addClass("disabled");
|
||||
$("#smtpAuthParam").slideDown();
|
||||
} else {
|
||||
$("#smtpAuthParam").removeClass("disabled");
|
||||
$("#smtpAuthParam").slideUp();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Options de blocage de connexions
|
||||
* Contrôle la cohérence des sélections et interdit une seule valeur Aucune
|
||||
*/
|
||||
$("select[name=connectAttempt]").on("change", function () {
|
||||
if ($("select[name=connectAttempt]").val() === "999") {
|
||||
$("select[name=connectTimeout]").val(0);
|
||||
} else {
|
||||
if ($("select[name=connectTimeout]").val() === "0") {
|
||||
$("select[name=connectTimeout]").val(300);
|
||||
}
|
||||
}
|
||||
});
|
||||
$("select[name=connectTimeout]").on("change", function () {
|
||||
if ($("select[name=connectTimeout]").val() === "0") {
|
||||
$("select[name=connectAttempt]").val(999);
|
||||
} else {
|
||||
if ($("select[name=connectAttempt]").val() === "999") {
|
||||
$("select[name=connectAttempt]").val(3);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Captcha strong si captcha sélectionné
|
||||
*/
|
||||
$("input[name=connectCaptcha]").on("change", function () {
|
||||
|
||||
if ($("input[name=connectCaptcha]").is(':checked')) {
|
||||
$("#connectCaptchaStrongWrapper").addClass("disabled");
|
||||
$("#connectCaptchaStrongWrapper").slideDown();
|
||||
$("#connectCaptchaTypeWrapper").addClass("disabled");
|
||||
$("#connectCaptchaTypeWrapper").slideDown();
|
||||
|
||||
} else {
|
||||
$("#connectCaptchaStrongWrapper").removeClass("disabled");
|
||||
$("#connectCaptchaStrongWrapper").slideUp();
|
||||
$("#connectCaptchaTypeWrapper").removeClass("disabled");
|
||||
$("#connectCaptchaTypeWrapper").slideUp();
|
||||
$("#connectCaptchaStrong").prop("checked", false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Sélection de la page de configuration à afficher
|
||||
*/
|
||||
$("#configSetupButton").on("click", function () {
|
||||
$("#socialContainer").hide();
|
||||
$("#connectContainer").hide();
|
||||
$("#networkContainer").hide();
|
||||
$("#setupContainer").show();
|
||||
$("#configSetupButton").addClass("activeButton");
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
});
|
||||
$("#configSocialButton").on("click", function () {
|
||||
$("#connectContainer").hide();
|
||||
$("#setupContainer").hide();
|
||||
$("#networkContainer").hide();
|
||||
$("#socialContainer").show();
|
||||
$("#configSetupButton").removeClass("activeButton");
|
||||
$("#configSocialButton").addClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
});
|
||||
$("#configConnectButton").on("click", function () {
|
||||
$("#setupContainer").hide();
|
||||
$("#socialContainer").hide();
|
||||
$("#networkContainer").hide();
|
||||
$("#connectContainer").show();
|
||||
$("#configSetupButton").removeClass("activeButton");
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").addClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
});
|
||||
$("#configNetworkButton").on("click", function () {
|
||||
$("#setupContainer").hide();
|
||||
$("#socialContainer").hide();
|
||||
$("#connectContainer").hide();
|
||||
$("#networkContainer").show();
|
||||
$("#configSetupButton").removeClass("activeButton");
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").addClass("activeButton");
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Aspect de la souris
|
||||
*/
|
||||
$("#socialMetaImage, #socialSiteMap, #configBackupCopyButton").click(function (event) {
|
||||
$('body, .button').css('cursor', 'wait');
|
||||
});
|
||||
|
||||
|
||||
// Mise en évidence des erreurs de saisie dans les boutons de sélection
|
||||
var containers = ["setup", "social", "connect", "network"];
|
||||
$.each(containers, function (index, value) {
|
||||
var a = $("div#" + value + "Container").find("input.notice").not(".displayNone");
|
||||
if (a.length > 0) {
|
||||
$("#config" + capitalizeFirstLetter(value) + "Button").addClass("buttonNotice");
|
||||
} else {
|
||||
$("#config" + capitalizeFirstLetter(value) + "Button").removeClass("buttonNotice");
|
||||
}
|
||||
});
|
||||
|
||||
// Contrôle l'image Open Screen Graph
|
||||
// Type d'image
|
||||
$("span#screenType").each(function(){
|
||||
var text = $(this).text();
|
||||
if (text.includes("jpg") || text.includes("jpeg") || text.includes("png")) {
|
||||
$(this).css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
}
|
||||
});
|
||||
// La largeur
|
||||
$("span#screenWide").each(function(){
|
||||
var screenId = parseInt($(this).text());
|
||||
if (screenId >= 1200) {
|
||||
$(this).css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
}
|
||||
});
|
||||
// La hauteur
|
||||
$("span#screenHeight").each(function(){
|
||||
var screenId = parseInt($(this).text());
|
||||
if (screenId >= 630) {
|
||||
$(this).css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
}
|
||||
});
|
||||
// Le ratio
|
||||
$('span#screenRatio').each(function(){
|
||||
var ratio = parseFloat($(this).text());
|
||||
if (ratio >= 1.90 && ratio <= 1.92) {
|
||||
$(this).css("color", "green");
|
||||
$("#screenFract").css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
$("#screenFract").css("color", "red");
|
||||
}
|
||||
});
|
||||
// Le poids
|
||||
$('span#screenWeight').each(function(index){
|
||||
var weight = parseFloat($(this).text());
|
||||
var fileType = $('span#screenType').eq(index).text();
|
||||
if ((fileType === "jpg" || fileType === "jpeg") && weight < 5000000) {
|
||||
$(this).css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
}
|
||||
});
|
||||
|
||||
$('span#screenWeight').each(function(index){
|
||||
var weight = parseFloat($(this).text());
|
||||
var fileType = $('span#screenType').eq(index).text();
|
||||
|
||||
if (fileType === "png" && weight <= 1000000) {
|
||||
$(this).css("color", "green");
|
||||
} else {
|
||||
$(this).css("color", "red");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Define function to capitalize the first letter of a string
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
232
core/module/config/view/index/index.php
Executable file → Normal file
232
core/module/config/view/index/index.php
Executable file → Normal file
@ -1,213 +1,49 @@
|
||||
<?php echo template::formOpen('configForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col2">
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('configBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl(false),
|
||||
'ico' => 'home',
|
||||
'value' => 'Accueil'
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<?php echo template::submit('configSubmit'); ?>
|
||||
<div class="col2 offset7">
|
||||
<?php echo template::button('configLocaleButton', [
|
||||
'value' => 'Identité',
|
||||
'href' => helper::baseUrl() . 'language/site'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::submit('Submit'); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<div class="block">
|
||||
<h4>Informations générales</h4>
|
||||
</div>
|
||||
|
||||
<?php echo template::select('configHomePageId', helper::arrayCollumn($this->getData(['page']), 'title', 'SORT_ASC'), [
|
||||
'label' => 'Page d\'accueil',
|
||||
'selected' => $this->getData(['config', 'homePageId'])
|
||||
<div class="tab">
|
||||
<?php echo template::button('configSetupButton', [
|
||||
'value' => 'Configuration',
|
||||
'class' => 'buttonTab',
|
||||
//'href' => helper::baseUrl() . 'config/register/setup'
|
||||
]); ?>
|
||||
<?php echo template::button('configSocialButton', [
|
||||
'value' => 'Référencement',
|
||||
'class' => 'buttonTab',
|
||||
//'href' => helper::baseUrl() . 'config/register/social'
|
||||
]); ?>
|
||||
|
||||
<?php echo template::text('configTitle', [
|
||||
'label' => 'Titre du site',
|
||||
'value' => $this->getData(['config', 'title']),
|
||||
'help' => 'Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.'
|
||||
<?php echo template::button('configConnectButton', [
|
||||
'value' => 'Connexion',
|
||||
'class' => 'buttonTab',
|
||||
//'href' => helper::baseUrl() . 'config/register/connect'
|
||||
]); ?>
|
||||
<?php echo template::textarea('configMetaDescription', [
|
||||
'label' => 'Description du site',
|
||||
'value' => $this->getData(['config', 'metaDescription']),
|
||||
'help' => 'Elle apparaît dans les partages sur les réseaux sociaux.'
|
||||
<?php echo template::button('configNetworkButton', [
|
||||
'value' => 'Réseau',
|
||||
'class' => 'buttonTab',
|
||||
//'href' => helper::baseUrl() . 'config/register/network'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="block">
|
||||
<h4>Options avancées</h4>
|
||||
<?php echo template::file('configFavicon', [
|
||||
'type' => 1,
|
||||
'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
|
||||
'label' => 'Favicon',
|
||||
'value' => $this->getData(['config', 'favicon'])
|
||||
]); ?>
|
||||
<?php echo template::text('configAnalyticsId', [
|
||||
'help' => 'Saisissez l\'ID de suivi.',
|
||||
'label' => 'Google Analytics',
|
||||
'placeholder' => 'UA-XXXXXXXX-X',
|
||||
'value' => $this->getData(['config', 'analyticsId'])
|
||||
]); ?>
|
||||
<?php echo template::checkbox('configCookieConsent', true, 'Message de consentement pour l\'utilisation des cookies', [
|
||||
'checked' => $this->getData(['config', 'cookieConsent'])
|
||||
]); ?>
|
||||
<?php echo template::checkbox('rewrite', true, 'Réécriture d\'URL', [
|
||||
'checked' => helper::checkRewrite(),
|
||||
'help' => 'Vérifiez d\'abord que votre serveur l\'autorise : ce n\'est pas le cas chez Free.'
|
||||
]); ?>
|
||||
<?php echo template::select('itemsperPage', $module::$ItemsList, [
|
||||
'label' => 'Articles par page ("Blog" et "News")',
|
||||
'selected' => $this->getData(['config', 'itemsperPage'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="block">
|
||||
<h4>Copie d'écran OpenGraph</h4>
|
||||
<div class="row">
|
||||
<div class="col8 offset2">
|
||||
<img src='<?php echo helper::baseUrl(false) . 'site/file/source/screenshot.png';?>' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<?php echo template::button('configMetaImage', [
|
||||
'href' => helper::baseUrl() . 'config/configMetaImage',
|
||||
'value' => 'Rafraîchir la capture d\'écran'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<p>Cette capture d'écran est nécessaire aux partages sur les réseaux sociaux. Elle est régénérée lorsque le fichier "screenshot.png" est effacé du gestionnaire de fichiers.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<div class="block">
|
||||
<h4>Réseaux sociaux</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialFacebookId', [
|
||||
'help' => 'Saisissez votre ID : https://www.facebook.com/[ID].',
|
||||
'label' => 'Facebook',
|
||||
'value' => $this->getData(['config', 'social', 'facebookId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialInstagramId', [
|
||||
'help' => 'Saisissez votre ID : https://www.instagram.com/[ID].',
|
||||
'label' => 'Instagram',
|
||||
'value' => $this->getData(['config', 'social', 'instagramId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
</div>
|
||||
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialYoutubeId', [
|
||||
'help' => 'Saisissez votre ID : https://www.youtube.com/channel/[ID].',
|
||||
'label' => 'Youtube',
|
||||
'value' => $this->getData(['config', 'social', 'youtubeId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialTwitterId', [
|
||||
'help' => 'Saisissez votre ID : https://twitter.com/[ID].',
|
||||
'label' => 'Twitter',
|
||||
'value' => $this->getData(['config', 'social', 'twitterId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialPinterestId', [
|
||||
'help' => 'Saisissez votre ID : https://pinterest.com/[ID].',
|
||||
'label' => 'Pinterest',
|
||||
'value' => $this->getData(['config', 'social', 'pinterestId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('configSocialLinkedinId', [
|
||||
'help' => 'Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[CETTE PARTIE].',
|
||||
'label' => 'Linkedin',
|
||||
'value' => $this->getData(['config', 'social', 'linkedinId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block">
|
||||
<h4>Système</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('configVersion', [
|
||||
'label' => 'ZwiiCMS',
|
||||
'readonly' => true,
|
||||
'value' => common::ZWII_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('moduleRedirectionVersion', [
|
||||
'label' => 'Module "Redirection"',
|
||||
'readonly' => true,
|
||||
'value' => redirection::REDIRECTION_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('moduleFormVersion', [
|
||||
'label' => 'Module "Form"',
|
||||
'readonly' => true,
|
||||
'value' => form::FORM_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('moduleGalleryVersion', [
|
||||
'label' => 'Module "Gallery"',
|
||||
'readonly' => true,
|
||||
'value' => gallery::GALLERY_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('moduleNewsVersion', [
|
||||
'label' => 'Module "News"',
|
||||
'readonly' => true,
|
||||
'value' => news::NEWS_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('moduleBlogVersion', [
|
||||
'label' => 'Module "Blog"',
|
||||
'readonly' => true,
|
||||
'value' => blog::BLOG_VERSION
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::select('configTimezone', $module::$timezones, [
|
||||
'label' => 'Fuseau horaire',
|
||||
'selected' => $this->getData(['config', 'timezone'])
|
||||
]); ?>
|
||||
<?php echo template::checkbox('configMaintenance', true, 'Site en maintenance', [
|
||||
'checked' => $this->getData(['config', 'maintenance'])
|
||||
]); ?>
|
||||
<?php echo template::checkbox('configAutoBackup', true, 'Sauvegarde automatique', [
|
||||
'checked' => $this->getData(['config', 'autoBackup']),
|
||||
'help' => 'Le fichier de données est copié quotidiennement dans le dossier \'site/backup\'. La sauvegarde est conservée pendant 30 jours.'
|
||||
]); ?>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<?php echo template::button('configExport', [
|
||||
'href' => helper::baseUrl() . 'config/backup',
|
||||
'value' => 'Exporter une copie du site<br>(données, thème et fichiers)'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<?php echo template::button('configSiteMap', [
|
||||
'href' => helper::baseUrl() . 'config/generateFiles',
|
||||
'value' => 'Générer sitemap.xml et robots.txt'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include('core/module/config/view/setup/setup.php') ?>
|
||||
<?php include('core/module/config/view/social/social.php') ?>
|
||||
<?php include('core/module/config/view/connect/connect.php') ?>
|
||||
<?php include('core/module/config/view/network/network.php') ?>
|
||||
<?php echo template::formClose(); ?>
|
115
core/module/config/view/network/network.php
Normal file
115
core/module/config/view/network/network.php
Normal file
@ -0,0 +1,115 @@
|
||||
<div id="networkContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/reseau" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col2">
|
||||
<?php echo template::select('configProxyType', $module::$proxyType, [
|
||||
'label' => 'Type de proxy',
|
||||
'selected' => $this->getData(['config', 'proxyType'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col8">
|
||||
<?php echo template::text('configProxyUrl', [
|
||||
'label' => 'Adresse du proxy',
|
||||
'placeholder' => 'cache.proxy.fr',
|
||||
'value' => $this->getData(['config', 'proxyUrl'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::text('configProxyPort', [
|
||||
'label' => 'Port du proxy',
|
||||
'placeholder' => '6060',
|
||||
'value' => $this->getData(['config', 'proxyPort'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('SMTP'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/smtp" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('smtpFrom', [
|
||||
'label' => 'Expéditeur',
|
||||
'placeholder' => 'no-reply@host',
|
||||
'value' => $this->getData(['config', 'smtp', 'from']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::checkbox('smtpEnable', true, 'SMTP personnalisé', [
|
||||
'checked' => $this->getData(['config', 'smtp', 'enable']),
|
||||
'help' => 'Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d\'envoi de mail.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="smtpParam">
|
||||
<div class="row">
|
||||
<div class="col8">
|
||||
<?php echo template::text('smtpHost', [
|
||||
'label' => 'Adresse SMTP',
|
||||
'placeholder' => 'smtp.fr',
|
||||
'value' => $this->getData(['config', 'smtp', 'host'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::text('smtpPort', [
|
||||
'label' => 'Port SMTP',
|
||||
'placeholder' => '589',
|
||||
'value' => $this->getData(['config', 'smtp', 'port'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::select('smtpAuth', $module::$SMTPauth, [
|
||||
'label' => 'Authentification',
|
||||
'selected' => $this->getData(['config', 'smtp', 'auth'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="smtpAuthParam">
|
||||
<div class="row">
|
||||
<div class="col5">
|
||||
<?php echo template::text('smtpUsername', [
|
||||
'label' => 'Nom utilisateur',
|
||||
'value' => $this->getData(['config', 'smtp', 'username'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::password('smtpPassword', [
|
||||
'label' => 'Mot de passe',
|
||||
'autocomplete' => 'off',
|
||||
'value' => $this->getData(['config', 'smtp', 'password'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::select('smtpSecure', $module::$SMTPEnc, [
|
||||
'label' => 'Sécurité',
|
||||
'selected' => $this->getData(['config', 'smtp', 'secure'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
18
core/module/config/view/restore/restore.css
Normal file
18
core/module/config/view/restore/restore.css
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
12
core/module/config/view/restore/restore.js.php
Normal file
12
core/module/config/view/restore/restore.js.php
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
$(document).ready((function(){$("#configRestoreSubmit").click((function(event){$("body, .button").css("cursor","wait")}))}));
|
43
core/module/config/view/restore/restore.php
Normal file
43
core/module/config/view/restore/restore.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php echo template::formOpen('configRestoreForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('configRestoreBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'config',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configRestoreSubmit', [
|
||||
'value' => 'Restaurer',
|
||||
'uniqueSubmission' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Archive à restaurer'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<div class="row">
|
||||
<?php echo template::file('configRestoreImportFile', [
|
||||
'label' => 'Sélectionnez une archive au format ZIP',
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'type' => 2,
|
||||
'help' => 'L\'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<?php echo template::checkbox('configRestoreImportUser', true, 'Préserver les comptes des utilisateurs déjà installés', [
|
||||
'checked' => true
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
18
core/module/config/view/script/script.css
Executable file
18
core/module/config/view/script/script.css
Executable file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
37
core/module/config/view/script/script.php
Normal file
37
core/module/config/view/script/script.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php echo template::formOpen('configScript'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('configManageBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'config',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configManageSubmit', [
|
||||
'value' => 'Valider',
|
||||
'ico' => 'check'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($this->geturl(2) === 'head') : ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('configScriptHead', [
|
||||
'value' => file_exists(self::DATA_DIR . 'head.inc.html') ? file_get_contents(self::DATA_DIR . 'head.inc.html') : '',
|
||||
'class' => 'editor'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if ($this->geturl(2) === 'body') : ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('configScriptBody', [
|
||||
'value' => file_exists(self::DATA_DIR . 'body.inc.html') ? file_get_contents(self::DATA_DIR . 'body.inc.html') : '',
|
||||
'class' => 'editor'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php echo template::formClose(); ?>
|
199
core/module/config/view/setup/setup.php
Normal file
199
core/module/config/view/setup/setup.php
Normal file
@ -0,0 +1,199 @@
|
||||
<div id="setupContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::file('configFavicon', [
|
||||
'type' => 1,
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
|
||||
'label' => 'Favicon',
|
||||
'value' => $this->getData(['config', 'favicon']),
|
||||
'folder' => $this->getData(['config', 'favicon']) ? dirname($this->getData(['config', 'favicon'])) : ''
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::file('configFaviconDark', [
|
||||
'type' => 1,
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'help' => 'Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
|
||||
'label' => 'Favicon thème sombre',
|
||||
'value' => $this->getData(['config', 'faviconDark']),
|
||||
'folder' => $this->getData(['config', 'faviconDark']) ? dirname($this->getData(['config', 'faviconDark'])) : ''
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::select('configTimezone', $module::$timezones, [
|
||||
'label' => 'Fuseau horaire',
|
||||
'selected' => $this->getData(['config', 'timezone']),
|
||||
'help' => 'Le fuseau horaire est utile au bon référencement'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configCookieConsent', true, 'Message de consentement aux cookies', [
|
||||
'checked' => $this->getData(['config', 'cookieConsent']),
|
||||
'help' => 'Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
|
||||
'checked' => helper::checkRewrite(),
|
||||
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
|
||||
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'Apache') === false and $module->isModRewriteEnabled()
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Mise à jour automatisée'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configAutoUpdate', true, 'Rechercher une mise à jour en ligne', [
|
||||
'checked' => $this->getData(['config', 'autoUpdate']),
|
||||
'help' => 'La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.',
|
||||
'disabled' => empty(helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL))
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configAutoUpdateHtaccess', true, 'Préserver le fichier htaccess racine', [
|
||||
'checked' => $this->getData(['config', 'autoUpdateHtaccess']),
|
||||
'help' => 'Lors d\'une mise à jour automatique, conserve le fichier htaccess de la racine du site.',
|
||||
'disabled' => empty(helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL))
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::select('configAutoUpdateDelay', $module::$updateDelay, [
|
||||
'label' => 'Fréquence de recherche',
|
||||
'selected' => $this->getData(['config', 'autoUpdateDelay']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 offset1 verticalAlignBottom">
|
||||
<pre>Version installée : <strong><?php echo common::ZWII_VERSION; ?></strong></pre>
|
||||
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL); ?></strong></pre>
|
||||
</div>
|
||||
<div class="col3 offset2 verticalAlignBottom">
|
||||
<?php echo template::button('configUpdateForced', [
|
||||
'ico' => 'download-cloud',
|
||||
'href' => helper::baseUrl() . 'install/update',
|
||||
'value' => $module::$updateButtonText,
|
||||
'class' => 'buttonRed',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Maintenance'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configAutoBackup', true, 'Sauvegarde automatique quotidienne du site', [
|
||||
'checked' => $this->getData(['config', 'autoBackup']),
|
||||
'help' => 'Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('configMaintenance', true, 'Site en maintenance', [
|
||||
'checked' => $this->getData(['config', 'maintenance'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::button('configBackupButton', [
|
||||
'href' => helper::baseUrl() . 'config/backup',
|
||||
'value' => 'Sauvegarder les données du site',
|
||||
'ico' => 'download-cloud'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::button('configRestoreButton', [
|
||||
'href' => helper::baseUrl() . 'config/restore',
|
||||
'value' => 'Restaurer les données du site',
|
||||
'ico' => 'upload-cloud'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::button('configBackupCopyButton', [
|
||||
'href' => helper::baseUrl() . 'config/copyBackups',
|
||||
'value' => 'Copier sauvegardes auto',
|
||||
'ico' => 'docs'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::button('configBackupDelButton', [
|
||||
'href' => helper::baseUrl() . 'config/delBackups',
|
||||
'value' => 'Vider dossier sauvegardes auto',
|
||||
'ico' => 'trash',
|
||||
'class' => 'buttonRed'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Scripts externes'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('socialScriptHead', [
|
||||
'href' => helper::baseUrl() . 'config/script/head',
|
||||
'value' => 'Script dans head',
|
||||
'ico' => 'pencil'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('socialScriptBody', [
|
||||
'href' => helper::baseUrl() . 'config/script/body',
|
||||
'value' => 'Script dans body',
|
||||
'ico' => 'pencil'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a
|
||||
href="https://forum.zwiicms.fr" target="_blank">Forum</a>
|
||||
</h4>
|
||||
<div class="row textAlignCenter">
|
||||
<div class="col12">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img
|
||||
alt="Licence Creative Commons" style="border-width:0"
|
||||
src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
|
||||
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license"
|
||||
href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons
|
||||
Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0
|
||||
International.</a></p>
|
||||
<p>Pour voir une copie de cette licence, visitez
|
||||
http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box
|
||||
1866, Mountain View, CA 94042, USA.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
178
core/module/config/view/social/social.php
Normal file
178
core/module/config/view/social/social.php
Normal file
@ -0,0 +1,178 @@
|
||||
<div id="socialContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Capture d\'écran Open Graph'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::file('seoOpenGraphImage', [
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Image Open Graph',
|
||||
'value' => $this->getData(['config', 'seo', 'openGraphImage']),
|
||||
'folder' => $this->getData(['config', 'seo', 'openGraphImage']) ? dirname($this->getData(['config', 'seo', 'openGraphImage'])) : '',
|
||||
'type' => 1,
|
||||
'help' => sprintf('%s : JPG - PNG<br />', helper::translate('Format')) .
|
||||
sprintf('%s : 1200 x 630 pixels<br />', helper::translate('Dimensions minimales')) .
|
||||
sprintf('%s : 1.91:1<br />', helper::translate('Ratio')) .
|
||||
sprintf('%s : %s, %s<br />', helper::translate('Taille maximale du fichier'), helper::translate('5 Mo pour les images JPEG'), helper::translate('1 Mo pour les images PNG'))
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col10 textAlignCenter">
|
||||
<?php if( !empty($module::$imageOpenGraph['type']) ): ?>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWide">%s</span> x <span id="screenHeight">%s</span> pixels', helper::translate('Dimensions minimales'), $module::$imageOpenGraph['wide'], $module::$imageOpenGraph['height'] ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenRatio">%s</span><span id="screenFract">:1</span>' , helper::translate('Ratio'), round($module::$imageOpenGraph['ratio'], 2)); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWeight">%s</span>', helper::translate('Poids'), $module::$imageOpenGraph['size']); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php if (
|
||||
$this->getData(['config', 'seo', 'openGraphImage']) &&
|
||||
file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
|
||||
): ?>
|
||||
<img
|
||||
src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Référencement'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::button('socialSiteMap', [
|
||||
'href' => helper::baseUrl() . 'config/sitemap',
|
||||
'value' => 'Générer sitemap.xml et robots.txt'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 offset1">
|
||||
<?php echo template::checkbox('seoRobots', true, 'Autoriser les robots à référencer le site', [
|
||||
'checked' => $this->getData(['config', 'seo', 'robots'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialFacebookId', [
|
||||
'help' => 'Saisissez votre ID : https://www.facebook.com/[ID].',
|
||||
'label' => template::ico('facebook', ['margin' => 'right']) . 'Facebook',
|
||||
'value' => $this->getData(['config', 'social', 'facebookId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialInstagramId', [
|
||||
'help' => 'Saisissez votre ID : https://www.instagram.com/[ID].',
|
||||
'label' => template::ico('instagram', ['margin' => 'right']) . 'Instagram',
|
||||
'value' => $this->getData(['config', 'social', 'instagramId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialTwitterId', [
|
||||
'help' => 'Saisissez votre ID : https://twitter.com/[ID].',
|
||||
'label' => template::ico('twitter', ['margin' => 'right']) . 'Twitter',
|
||||
'value' => $this->getData(['config', 'social', 'twitterId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialRedditId', [
|
||||
'help' => 'Saisissez votre ID Reddit : https://www.reddit.com/user/[ID].',
|
||||
'label' => template::ico('reddit', ['margin' => 'right']) . 'Reddit',
|
||||
'value' => $this->getData(['config', 'social', 'redditId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialYoutubeId', [
|
||||
'help' => 'ID de la chaîne : https://www.youtube.com/channel/[ID].',
|
||||
'label' => template::ico('youtube', ['margin' => 'right']) . 'Chaîne Youtube',
|
||||
'value' => $this->getData(['config', 'social', 'youtubeId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialYoutubeUserId', [
|
||||
'help' => 'Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].',
|
||||
'label' => template::ico('youtube', ['margin' => 'right']) . 'Youtube',
|
||||
'value' => $this->getData(['config', 'social', 'youtubeUserId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialVimeoId', [
|
||||
'help' => 'Saisissez votre ID Viemo : https://vimeo.com/[ID].',
|
||||
'label' => template::ico('vimeo', ['margin' => 'right']) . 'Vimeo',
|
||||
'value' => $this->getData(['config', 'social', 'vimeoId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialPinterestId', [
|
||||
'help' => 'Saisissez votre ID : https://pinterest.com/[ID].',
|
||||
'label' => template::ico('pinterest', ['margin' => 'right']) . 'Pinterest',
|
||||
'value' => $this->getData(['config', 'social', 'pinterestId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialLinkedinId', [
|
||||
'help' => 'Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].',
|
||||
'label' => template::ico('linkedin', ['margin' => 'right']) . 'Linkedin',
|
||||
'value' => $this->getData(['config', 'social', 'linkedinId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialGithubId', [
|
||||
'help' => 'Saisissez votre ID Github : https://github.com/[ID].',
|
||||
'label' => template::ico('github', ['margin' => 'right']) . 'Github',
|
||||
'value' => $this->getData(['config', 'social', 'githubId'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialTwitchId', [
|
||||
'help' => 'Saisissez votre ID Twitch : https://www.twitch.tv/[ID].',
|
||||
'label' => template::ico('twitch', ['margin' => 'right']) . 'Twitch',
|
||||
'value' => $this->getData(['config', 'social', 'twitchId'])
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
<div class="col3">
|
||||
<?php echo template::text('socialSteamId', [
|
||||
'help' => 'Saisissez votre ID Viemo : https://steamcommunity.com/id/[ID].',
|
||||
'label' => template::ico('steam', ['margin' => 'right']) . 'Steam',
|
||||
'value' => $this->getData(['config', 'social', 'steamId'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
50
core/module/dashboard/dashboard.php
Normal file
50
core/module/dashboard/dashboard.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class dashboard extends common
|
||||
{
|
||||
|
||||
public static $actions = [
|
||||
'index' => self::GROUP_ADMIN,
|
||||
];
|
||||
|
||||
|
||||
|
||||
public static $infos = [];
|
||||
|
||||
/**
|
||||
* Dashboard
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
self::$infos['webserver'] = $_SERVER['SERVER_SOFTWARE'];
|
||||
self::$infos['php']['version'] = phpversion();
|
||||
self::$infos['php']['extension'] = get_loaded_extensions();
|
||||
|
||||
self::$infos['system']['memory'] = memory_get_usage() . ' octets';
|
||||
self::$infos['system']['peek'] = 'Pic de mémoire utilisée : ' . memory_get_peak_usage() . ' octets';
|
||||
|
||||
$loadAverage = sys_getloadavg();
|
||||
self::$infos['system']['charge'] = 'Charge moyenne (1 min / 5 min / 15 min) : ' . implode(' / ', $loadAverage) . '</P>';
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Tableau de bord'),
|
||||
'view' => 'index'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
54
core/module/dashboard/view/index/index.php
Normal file
54
core/module/dashboard/view/index/index.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php echo template::formOpen('dashboard'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('dashboardFormBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl(false),
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Système'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<p>
|
||||
<?php echo helper::translate('Serveur Web'); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo $module::$infos['webserver']; ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<p>
|
||||
<?php echo helper::translate('PHP') . ' ' . $module::$infos['php']['version']; ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo implode(' - ', $module::$infos['php']['extension']); ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<p>
|
||||
<?php echo helper::translate('Mémoire'); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo $module::$infos['system']['memory']; ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo $module::$infos['system']['charge']; ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo $module::$infos['system']['peek']; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
426
core/module/install/install.php
Executable file → Normal file
426
core/module/install/install.php
Executable file → Normal file
@ -2,35 +2,93 @@
|
||||
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class install extends common {
|
||||
|
||||
class install extends common
|
||||
{
|
||||
|
||||
public static $actions = [
|
||||
'index' => self::GROUP_VISITOR,
|
||||
"postinstall" => self::GROUP_VISITOR,
|
||||
'steps' => self::GROUP_ADMIN,
|
||||
'update' => self::GROUP_ADMIN,
|
||||
'removeAll' => self::GROUP_ADMIN,
|
||||
'update' => self::GROUP_ADMIN
|
||||
];
|
||||
|
||||
// Type de proxy
|
||||
public static $proxyType = [
|
||||
'tcp://' => 'TCP',
|
||||
'http://' => 'HTTP'
|
||||
];
|
||||
|
||||
public static $updateButtonText = 'Réinstaller';
|
||||
|
||||
public static $newVersion;
|
||||
|
||||
// Fichiers des Interface
|
||||
public static $i18nFiles = [];
|
||||
|
||||
/**
|
||||
* Installation
|
||||
* Pré-installation - choix de la langue
|
||||
*/
|
||||
public function index() {
|
||||
public function index()
|
||||
{
|
||||
// Accès refusé
|
||||
if($this->getData(['user']) !== []) {
|
||||
if ($this->getData(['user']) !== []) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
//$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
$lang = $this->getInput('installLanguage');
|
||||
// Pour la suite de l'installation
|
||||
// setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', false, false);
|
||||
|
||||
$_SESSION['ZWII_UI'] = $this->getInput('installLanguage');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'install/postinstall'
|
||||
]);
|
||||
}
|
||||
|
||||
// Liste des langues UI disponibles
|
||||
if (is_dir(self::I18N_DIR)) {
|
||||
foreach ($this->getData(['language']) as $lang => $value) {
|
||||
self::$i18nFiles[$lang] = self::$languages[$lang];
|
||||
}
|
||||
}
|
||||
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
'title' => helper::translate('ZwiiCMS Installation'),
|
||||
'view' => 'index'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* post Installation
|
||||
*/
|
||||
public function postInstall()
|
||||
{
|
||||
// Accès refusé
|
||||
if ($this->getData(['user']) !== []) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
@ -39,38 +97,49 @@ class install extends common {
|
||||
// Accès autorisé
|
||||
else {
|
||||
// Soumission du formulaire
|
||||
if($this->isPost()) {
|
||||
if (
|
||||
//$this->getUser('permission', __CLASS__, __FUNCTION__) !== true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
$success = true;
|
||||
|
||||
// Double vérification pour le mot de passe
|
||||
if($this->getInput('installPassword', helper::FILTER_STRING_SHORT, true) !== $this->getInput('installConfirmPassword', helper::FILTER_STRING_SHORT, true)) {
|
||||
if ($this->getInput('installPassword', helper::FILTER_STRING_SHORT, true) !== $this->getInput('installConfirmPassword', helper::FILTER_STRING_SHORT, true)) {
|
||||
self::$inputNotices['installConfirmPassword'] = 'Incorrect';
|
||||
$success = false;
|
||||
}
|
||||
// Crée l'utilisateur
|
||||
// Utilisateur
|
||||
$userFirstname = $this->getInput('installFirstname', helper::FILTER_STRING_SHORT, true);
|
||||
$userLastname = $this->getInput('installLastname', helper::FILTER_STRING_SHORT, true);
|
||||
$userMail = $this->getInput('installMail', helper::FILTER_MAIL, true);
|
||||
$userId = $this->getInput('installId', helper::FILTER_ID, true);
|
||||
// Configure certaines données par défaut
|
||||
if ($this->getInput('installDefaultData',helper::FILTER_BOOLEAN) === FALSE) {
|
||||
foreach($this->getHierarchy(null, false) as $parentPageId => $childrenPageIds) {
|
||||
if ( $parentPageId !== 'accueil') {
|
||||
$this->deleteData(['page',$parentPageId]);
|
||||
|
||||
// Validation de la langue transmise
|
||||
self::$i18nUI = $_SESSION['ZWII_UI'];
|
||||
self::$i18nUI = array_key_exists(self::$i18nUI, self::$languages) ? self::$i18nUI : 'fr_FR';
|
||||
// par défaut le contenu est la langue d'installation
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = self::$i18nUI;
|
||||
|
||||
// Création du dossier de langue avec le marqueur de langue par défaut
|
||||
if (!is_dir(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
mkdir(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT']);
|
||||
touch(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT'] . '/.default');
|
||||
}
|
||||
foreach($childrenPageIds as $childKey) {
|
||||
$this->deleteData(['page', $childKey]);
|
||||
}
|
||||
}
|
||||
// Ajouter ici la liste des pages privées qui ne sont pas vues lors de l'installation.
|
||||
$this->deleteData(['page', 'privee']);
|
||||
// Effacer les fichiers par défaut
|
||||
if (is_dir('site/file/source/galerie')) {
|
||||
$this->removeAll('site/file/source/galerie');
|
||||
$this->removeAll('site/file/thumb/galerie');
|
||||
}
|
||||
} else {
|
||||
$this->setData(['module', 'blog', 'mon-premier-article', 'userId', $userId]);
|
||||
$this->setData(['module', 'blog', 'mon-deuxieme-article', 'userId', $userId]);
|
||||
$this->setData(['module', 'blog', 'mon-troisieme-article', 'userId', $userId]);
|
||||
|
||||
// Installation du site de test
|
||||
if (
|
||||
$this->getInput('installDefaultData', helper::FILTER_BOOLEAN) === false
|
||||
&& $_SESSION['ZWII_SITE_CONTENT'] === 'fr_FR'
|
||||
) {
|
||||
$sample = true;
|
||||
}
|
||||
$this->initData('page', $_SESSION['ZWII_SITE_CONTENT'], $sample);
|
||||
$this->initData('module', $_SESSION['ZWII_SITE_CONTENT'], $sample);
|
||||
$this->initData('locale', $_SESSION['ZWII_SITE_CONTENT'], $sample);
|
||||
|
||||
// Création de l'utilisateur si les données sont complétées.
|
||||
// success retour de l'enregistrement des données
|
||||
$this->setData([
|
||||
'user',
|
||||
$userId,
|
||||
@ -78,38 +147,95 @@ class install extends common {
|
||||
'firstname' => $userFirstname,
|
||||
'forgot' => 0,
|
||||
'group' => self::GROUP_ADMIN,
|
||||
'profil' => 0,
|
||||
'lastname' => $userLastname,
|
||||
'pseudo' => 'Admin',
|
||||
'signature' => 1,
|
||||
'mail' => $userMail,
|
||||
'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true)
|
||||
'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true),
|
||||
'language' => $_SESSION['ZWII_SITE_CONTENT']
|
||||
]
|
||||
]);
|
||||
|
||||
// Envoie le mail
|
||||
$sent = $this->sendMail(
|
||||
// Sent contient true si réussite sinon code erreur d'envoi en clair
|
||||
$this->sendMail(
|
||||
$userMail,
|
||||
'Installation de votre site',
|
||||
'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
|
||||
'Vous trouverez ci-dessous les détails de votre installation.<br><br>' .
|
||||
'Voici les détails de votre installation.<br><br>' .
|
||||
'<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' .
|
||||
'<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>' .
|
||||
'<strong>Mot de passe du compte :</strong> ' . $this->getInput('installPassword')
|
||||
'<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>',
|
||||
null,
|
||||
'no-reply@localhost'
|
||||
);
|
||||
// Générer un fichier robots.txt
|
||||
$this->createRobots();
|
||||
// Créer sitemap
|
||||
$this->createSitemap('all');
|
||||
|
||||
// Nettoyage fr par défaut
|
||||
if (
|
||||
$_SESSION['ZWII_SITE_CONTENT'] !== 'fr_FR'
|
||||
) {
|
||||
if (is_dir(self::DATA_DIR . 'fr_FR'))
|
||||
$this->deleteDir(self::DATA_DIR . 'fr_FR');
|
||||
}
|
||||
|
||||
// Sauvegarder la configuration du Proxy
|
||||
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')], false);
|
||||
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')], false);
|
||||
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)], false);
|
||||
|
||||
// Images exemples livrées dans tous les cas
|
||||
try {
|
||||
// Décompression dans le dossier de fichier temporaires
|
||||
if (file_exists(self::TEMP_DIR . 'files.tar.gz')) {
|
||||
unlink(self::TEMP_DIR . 'files.tar.gz');
|
||||
}
|
||||
if (file_exists(self::TEMP_DIR . 'files.tar')) {
|
||||
unlink(self::TEMP_DIR . 'files.tar');
|
||||
}
|
||||
copy('core/module/install/ressource/files.tar.gz', self::TEMP_DIR . 'files.tar.gz');
|
||||
$pharData = new PharData(self::TEMP_DIR . 'files.tar.gz');
|
||||
$pharData->decompress();
|
||||
// Installation
|
||||
$pharData->extractTo(__DIR__ . '/../../../', null, true);
|
||||
} catch (Exception $e) {
|
||||
$success = $e->getMessage();
|
||||
}
|
||||
|
||||
// Nettoyage
|
||||
unlink(self::TEMP_DIR . 'files.tar.gz');
|
||||
unlink(self::TEMP_DIR . 'files.tar');
|
||||
|
||||
// Créer le dossier des fontes
|
||||
if (!is_dir(self::DATA_DIR . 'font')) {
|
||||
mkdir(self::DATA_DIR . 'font');
|
||||
}
|
||||
|
||||
// Copie des langues de l'UI et génération de la base de données
|
||||
if (is_dir(self::I18N_DIR) === false) {
|
||||
mkdir(self::I18N_DIR);
|
||||
}
|
||||
|
||||
// Créer la base de données des langues
|
||||
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
|
||||
|
||||
// Fixe l'adresse from pour les envois d'email
|
||||
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])], false);
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl(false),
|
||||
'notification' => ($sent === true ? 'Installation terminée' : $sent),
|
||||
'state' => ($sent === true ? true : null)
|
||||
'redirect' => helper::baseUrl(),
|
||||
'notification' => helper::translate('Installation terminée'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('config');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
'title' => 'Installation',
|
||||
'view' => 'index'
|
||||
'title' => helper::translate('Installation'),
|
||||
'view' => 'postinstall'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -117,128 +243,240 @@ class install extends common {
|
||||
/**
|
||||
* Étapes de mise à jour
|
||||
*/
|
||||
public function steps() {
|
||||
switch($this->getInput('step', helper::FILTER_INT)) {
|
||||
public function steps()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
switch ($this->getInput('step', helper::FILTER_INT)) {
|
||||
// Préparation
|
||||
case 1:
|
||||
$success = true;
|
||||
// Copie du fichier de données
|
||||
copy('site/data/core.json', 'site/backup/' . date('Y-m-d', time()) . '-core-update.json');
|
||||
copy('site/data/theme.json', 'site/backup/' . date('Y-m-d', time()) . '-theme-update.json');
|
||||
// Nettoyage des fichiers temporaires
|
||||
if(file_exists('site/tmp/update.tar.gz')) {
|
||||
$success = unlink('site/tmp/update.tar.gz');
|
||||
$message = '';
|
||||
// RAZ la mise à jour auto
|
||||
$this->setData(['core', 'updateAvailable', false]);
|
||||
// Backup du dossier Data
|
||||
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
// Sauvegarde htaccess
|
||||
if ($this->getData(['config', 'autoUpdateHtaccess'])) {
|
||||
$success = copy('.htaccess', '.htaccess' . '.bak');
|
||||
$message = $success ? '' : 'Erreur de copie du fichier htaccess';
|
||||
}
|
||||
if(file_exists('site/tmp/update.tar')) {
|
||||
$success = unlink('site/tmp/update.tar');
|
||||
// Nettoyage des fichiers d'installation précédents
|
||||
if ($success && file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
$success = unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
|
||||
}
|
||||
if ($success && file_exists(self::TEMP_DIR . 'update.tar')) {
|
||||
$success = unlink(self::TEMP_DIR . 'update.tar');
|
||||
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => null
|
||||
'data' => $message
|
||||
]
|
||||
]);
|
||||
break;
|
||||
// Téléchargement
|
||||
case 2:
|
||||
// Téléchargement depuis le serveur de Zwii
|
||||
$success = (file_put_contents('site/tmp/update.tar.gz', file_get_contents('https://zwiicms.com/update/update.tar.gz')) !== false);
|
||||
$success = true;
|
||||
$message = '';
|
||||
$this->secure_file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
|
||||
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
|
||||
$md5origin = explode(' ', $md5origin);
|
||||
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
|
||||
// Vérifier si les checksums correspondent
|
||||
if ($md5origin[0] === $md5target) {
|
||||
$success = true;
|
||||
$message = "";
|
||||
} else {
|
||||
$success = false;
|
||||
$message = 'Erreur de téléchargement ou de somme de contrôle';
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
http_response_code(500);
|
||||
}
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => null
|
||||
'data' => $message
|
||||
]
|
||||
]);
|
||||
break;
|
||||
// Installation
|
||||
case 3:
|
||||
$success = true;
|
||||
$message = '';
|
||||
|
||||
// Check la réécriture d'URL avant d'écraser les fichiers
|
||||
$rewrite = helper::checkRewrite();
|
||||
if (helper::checkRewrite()) {
|
||||
touch(self::DATA_DIR . '.rewrite');
|
||||
}
|
||||
|
||||
// Décompression et installation
|
||||
try {
|
||||
// Décompression dans le dossier de fichier temporaires
|
||||
$pharData = new PharData('site/tmp/update.tar.gz');
|
||||
$pharData = new PharData(self::TEMP_DIR . 'update.tar.gz');
|
||||
$pharData->decompress();
|
||||
// Installation
|
||||
$pharData->extractTo(__DIR__ . '/../../../', null, true);
|
||||
} catch (Exception $e) {
|
||||
$success = $e->getMessage();
|
||||
$message = $e->getMessage();
|
||||
$success = false;
|
||||
http_response_code(500);
|
||||
}
|
||||
// Netooyage du dossier
|
||||
if(file_exists('site/tmp/update.tar.gz')) {
|
||||
unlink('site/tmp/update.tar.gz');
|
||||
|
||||
// Nettoyage du dossier
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
}
|
||||
if(file_exists('site/tmp/update.tar')) {
|
||||
unlink('site/tmp/update.tar');
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar');
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => $rewrite
|
||||
'data' => $message,
|
||||
]
|
||||
]);
|
||||
break;
|
||||
// Configuration
|
||||
case 4:
|
||||
$success = true;
|
||||
// Réécriture d'URL
|
||||
if($this->getInput('data', helper::FILTER_BOOLEAN)) {
|
||||
$success = (file_put_contents(
|
||||
'.htaccess',
|
||||
PHP_EOL .
|
||||
'<ifModule mod_rewrite.c>' . PHP_EOL .
|
||||
$message = '';
|
||||
|
||||
/**
|
||||
* Restaure le fichier htaccess
|
||||
*/
|
||||
// Recopie htaccess
|
||||
if (
|
||||
$this->getData(['config', 'autoUpdateHtaccess']) === true
|
||||
) {
|
||||
// L'écraser avec le backup
|
||||
$success = copy('.htaccess.bak', '.htaccess');
|
||||
if ($success === false) {
|
||||
$message = helper::translate('La copie de sauvegarde du fichier htaccess n\'a pas été restaurée !');
|
||||
http_response_code(500);
|
||||
}
|
||||
// Effacer le backup
|
||||
unlink('.htaccess.bak');
|
||||
} else {
|
||||
/**
|
||||
* Restaure la réécriture d'URL
|
||||
*/
|
||||
if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$rewriteData = PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL .
|
||||
'<IfModule mod_rewrite.c>' . PHP_EOL .
|
||||
"\tRewriteEngine on" . PHP_EOL .
|
||||
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
|
||||
"\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL .
|
||||
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
|
||||
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
|
||||
'</ifModule>',
|
||||
FILE_APPEND
|
||||
) !== false);
|
||||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
$success = $this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
unlink(self::DATA_DIR . '.rewrite');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les dictionnaires des langues depuis les nouveaux modèles installés
|
||||
*/
|
||||
require_once('core/module/install/ressource/defaultdata.php');
|
||||
$installedLanguages = $this->getData(['language']);
|
||||
$defaultLanguages = init::$defaultData['language'];
|
||||
foreach ($installedLanguages as $key => $value) {
|
||||
|
||||
if (
|
||||
isset($defaultLanguages[$key]['date']) &&
|
||||
$defaultLanguages[$key]['date'] > $value['date'] &&
|
||||
isset($defaultLanguages[$key]['version']) &&
|
||||
$defaultLanguages[$key]['version'] >= $value['version']
|
||||
|
||||
) {
|
||||
copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json');
|
||||
$this->setData(['language', $key, $defaultLanguages[$key]]);
|
||||
}
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => null
|
||||
'data' => $message
|
||||
]
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mise à jour
|
||||
*/
|
||||
public function update() {
|
||||
public function update()
|
||||
{
|
||||
// Action interdite
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
// Nouvelle version
|
||||
self::$newVersion = file_get_contents('http://zwiicms.com/update/version');
|
||||
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version');
|
||||
|
||||
// Variable de version
|
||||
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
|
||||
self::$updateButtonText = helper::translate('Mise à jour');
|
||||
}
|
||||
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
'title' => 'Mise à jour',
|
||||
'title' => helper::translate(self::$updateButtonText),
|
||||
'view' => 'update'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Effacer un dossier non vide.
|
||||
*/
|
||||
private function removeAll ( $path ) {
|
||||
foreach ( new DirectoryIterator($path) as $item ):
|
||||
if ( $item->isFile() ) unlink($item->getRealPath());
|
||||
if ( !$item->isDot() && $item->isDir() ) $this->removeAll($item->getRealPath());
|
||||
endforeach;
|
||||
|
||||
rmdir($path);
|
||||
}
|
||||
|
||||
}
|
10
core/module/install/ressource/.htaccess
Normal file
10
core/module/install/ressource/.htaccess
Normal file
@ -0,0 +1,10 @@
|
||||
# Bloque l'accès aux données
|
||||
<Files *.json>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</Files>
|
||||
# Bloque l'accès htaccess
|
||||
<Files .htaccess>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</Files>
|
File diff suppressed because it is too large
Load Diff
BIN
core/module/install/ressource/files.tar.gz
Normal file
BIN
core/module/install/ressource/files.tar.gz
Normal file
Binary file not shown.
693
core/module/install/ressource/i18n/en_EN.json
Normal file
693
core/module/install/ressource/i18n/en_EN.json
Normal file
@ -0,0 +1,693 @@
|
||||
{
|
||||
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "'Do not display' creates an orphan page not accessible through menus.",
|
||||
"'Sauvegarder et télécharger les données du module": "'Save and download module data",
|
||||
"1 jour": "1 jour",
|
||||
"1/4 : Préparation...": "1/4: preparation ...",
|
||||
"10 minutes": "10 minutes",
|
||||
"10 tentatives": "10 attempts",
|
||||
"14 jours": "14 days",
|
||||
"15 minutes": "15 minutes",
|
||||
"2 jours": "2 days",
|
||||
"2/4 : Téléchargement...": "2/4: Download ...",
|
||||
"3 tentatives": "3 attempts",
|
||||
"3/4 : Installation...": "3/4 : Installation...",
|
||||
"4 jours": "4 days",
|
||||
"4/4 : Configuration...": "4/4 : Setup...",
|
||||
"5 minutes": "5 minutes",
|
||||
"5 tentatives": "5 attempts",
|
||||
"7 jours": "7 days",
|
||||
"Accueil": "Homepage",
|
||||
"Accède au site": "Access to the site",
|
||||
"Accède aux pages réservées": "Access to restricted pages",
|
||||
"Accède aux pages réservées et à un dossier partagé": "Access to restricted pages and a shared folder",
|
||||
"Accès bloqué %d minutes": "Blocked access %d minutes",
|
||||
"Accès désactivé": "Access disabled",
|
||||
"Accès interdit, erreur 403": "Access prohibited, error 403",
|
||||
"Action interdite": "Prohibited action",
|
||||
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "Compulsory activation according to French laws unless you use your own consent system.",
|
||||
"Activer": "Enable",
|
||||
"Activer la journalisation": "Activate journalization",
|
||||
"Actualiser": "Update",
|
||||
"Adaptation": "Adaptation",
|
||||
"Administrateur": "Administrator",
|
||||
"Administration": "Administration",
|
||||
"Adresse SMTP": "SMTP Address",
|
||||
"Adresse du proxy": "Proxy address",
|
||||
"Adresse électronique": "email address",
|
||||
"Affectation": "Assignment",
|
||||
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "Displays the name of the parent page followed by the page name, the title should not be hidden.",
|
||||
"Affiche les icônes de gestion du compte et de déconnexion des membres simples connectés": "Displays account management and logout icons for logged-in regular members",
|
||||
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "In order to ensure the proper functioning of Zwii, please do not close this page before the end of the operation.",
|
||||
"Aide": "Help",
|
||||
"Ajouter": "Add",
|
||||
"Ajouter un profil": "Add Profile",
|
||||
"Ajouter un utilisateur": "Add a user",
|
||||
"Ajouter une fonte": "Add a cast iron",
|
||||
"Alignement": "Alignment",
|
||||
"Aligner la bannière avec le contenu": "Align the banner with the contents",
|
||||
"Ancien mot de passe": "Old Password",
|
||||
"Anonymat des adresses IP": "Anonymity of IP addresses",
|
||||
"Apache URL intelligent": "Intelligent Apache URL",
|
||||
"Apache URL intelligentes": "Intelligent Apache URL",
|
||||
"Apparence": "Appearance",
|
||||
"Appliquer": "Apply",
|
||||
"Approuver un commentaire": "Approve Comment",
|
||||
"Après": "After",
|
||||
"Après la bannière": "After the banner",
|
||||
"Après le contenu de la page": "After the content of the page",
|
||||
"Archive": "Archive",
|
||||
"Archive ZIP": "Zip archive",
|
||||
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "Archive copied in the Modules folder",
|
||||
"Archive de thème invalide": "Invalid theme archive",
|
||||
"Archive invalide": "Invalid archive",
|
||||
"Archive invalide, l'écriture dans le dossier core est interdite": "Invalid archive, writing in the core file is prohibited",
|
||||
"Archive invalide, le descripteur est absent": "Invalid archive, the descriptor is absent",
|
||||
"Archive invalide, le fichier de classe est absent": "Invalide archive, the class file is absent",
|
||||
"Archive invalide, les dossiers ne correspondent pas au descripteur": "Invalid archive, the files do not correspond to the descriptor",
|
||||
"Archive non spécifiée ou introuvable": "Archive not specified or not found",
|
||||
"Archive à restaurer": "Archive to restore",
|
||||
"Arrière plan": "Background",
|
||||
"Arrière plan des blocs": "Blocks background",
|
||||
"Arrière plan des champs": "Fields background",
|
||||
"Arrondi des angles": "Rounding of angles",
|
||||
"Au centre": "Center",
|
||||
"Au début": "At first",
|
||||
"Au milieu au centre": "In the middle in the center",
|
||||
"Au milieu à droite": "In the middle right",
|
||||
"Au milieu à gauche": "In the middle on the left",
|
||||
"Au-dessus du site": "Above the site",
|
||||
"Aucun": "None",
|
||||
"Aucun dossier": "No Folder",
|
||||
"Aucun fichier journal à télécharger": "No log file to download",
|
||||
"Aucun journal à effacer": "No log file to erase",
|
||||
"Aucun menu": "No menu",
|
||||
"Aucune": "None",
|
||||
"Aucune liste noire à effacer": "No blacklist to erase",
|
||||
"Aucune liste noire à télécharger": "No blacklist to download",
|
||||
"Auteur :": "Author:",
|
||||
"Authentification": "Authentication",
|
||||
"Automatique": "Automatique",
|
||||
"Autoriser les robots à référencer le site": "Allow robots to reference the site",
|
||||
"Autorisé": "Allowed",
|
||||
"Avant la bannière": "Before the banner",
|
||||
"Avant le contenu de la page": "Before the content of the page",
|
||||
"Background": "Background",
|
||||
"Banni": "Ban",
|
||||
"Bannière": "Banner",
|
||||
"Bannière cliquable": "Clickable banner",
|
||||
"Barre 1/3 - page 2/3": "Sidebar 1/3 - page 2/3",
|
||||
"Barre 1/4 - page 1/2 - barre 1/4": "Sidebar 1/4 - page 1/2 - Sidebar 1/4",
|
||||
"Barre 1/4 - page 3/4": "Sidebar 1/4 - page 3/4",
|
||||
"Barre 2/12 - page 7/12 - barre 3/12": "Sidebar 2/12 - page 7/12 - Sidebar 3/12",
|
||||
"Barre 3/12 - page 7/12 - barre 2/12": "Sidebar 3/12 - page 7/12 - Sidebar 2/12",
|
||||
"Barre de membre": "Member bar",
|
||||
"Barre latérale": "Sidebar",
|
||||
"Barre latérale droite :": "Right sidebar:",
|
||||
"Barre latérale gauche :": "Left sidebar:",
|
||||
"Barres latérales": "Side bars",
|
||||
"Bienvenue %s %s": "Welcome %s %s",
|
||||
"Blocage après échecs": "Blocking after chess",
|
||||
"Blog": "Blog",
|
||||
"Bords arrondis": "Rounded edges",
|
||||
"Bordure des blocs": "Blocks border",
|
||||
"Bordure des champs": "Fields border",
|
||||
"Bouton Aide": "Help button",
|
||||
"Bouton Standard": "Standard button",
|
||||
"Bouton de validation": "Validation button",
|
||||
"Bouton effacement": "Delete button",
|
||||
"Bouton retour": "Return button",
|
||||
"Bouton standard": "Standard button",
|
||||
"Bouton validation": "Validation button",
|
||||
"Boutons": "Buttons",
|
||||
"Caché": "Hidden",
|
||||
"Cachée": "Hidden",
|
||||
"Captcha complexe": "Complex captcha",
|
||||
"Captcha à la connexion": "Captcha at connecting",
|
||||
"Captcha, identifiant ou mot de passe incorrects": "Incorrect captcha, login or password",
|
||||
"Capture d'écran Open Graph": "Open Graph screenshot",
|
||||
"Capture d'écran générée avec succès": "Successful generated screenshot",
|
||||
"Casse": "Case",
|
||||
"Catalogue": "Store",
|
||||
"Catégorie": "Category",
|
||||
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "This member upload or download files in the 'Sharing' folder and its subfolders",
|
||||
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "This page should not appear in the menu tree. Create an orphan page.",
|
||||
"Cette redirection ne concerne que les pages d'administration du site.": "This redirection only concerns the administration pages of the site.",
|
||||
"Chaîne Youtube": "Youtube channel",
|
||||
"Chiffres": "Numbers",
|
||||
"Cible": "Target",
|
||||
"Cliquez sur une zone afin d'accéder à ses options de personnalisation.": "Click on an area to access its customization options.",
|
||||
"Commentaire": "Comment",
|
||||
"Complète": "Complete",
|
||||
"Compte administrateur": "Administrator account",
|
||||
"Compte de l'utilisateur": "User Account",
|
||||
"Compte verrouillé": "Locked",
|
||||
"Configuration": "Setup",
|
||||
"Configuration du module": "Module setup",
|
||||
"Configurer": "Configure",
|
||||
"Configurer mon compte": "Set up my account",
|
||||
"Confirmation": "Confirmation",
|
||||
"Confirmer la suppression de cet utilisateur": "Confirm the deletion of this user",
|
||||
"Confirmer la dissociation du module de cette page": "Confirm the dissociation of the module of this page",
|
||||
"Confirmer la désinstallation du module": "Confirm the uninstalling of the module",
|
||||
"Confirmer la suppression de cet utilisateur": "Confirm the deletion of this user",
|
||||
"Confirmer la suppression de cette langue": "Confirm deletion of this language",
|
||||
"Confirmer la suppression de la page": "Confirm the deletion of the page",
|
||||
"Confirmer la suppression des données du module": "Confirm the deletion of module data",
|
||||
"Confirmez-vous la suppression de cette page ?": "Do you confirm the deletion of this page?",
|
||||
"Connexion": "Connection",
|
||||
"Consulter l'aide en ligne": "Online help",
|
||||
"Contents": "Contents",
|
||||
"Contenu": "Contents",
|
||||
"Contenu HTML": "HTML contents",
|
||||
"Contenu avancé": "Advanced contents",
|
||||
"Contenu du menu vertical": "Vertical menu content",
|
||||
"Contrôle total": "Full control",
|
||||
"Cookies": "Cookies",
|
||||
"Cookies Zwii": "Cookies Zwii",
|
||||
"Copie de contenus localisés": "Localized content copy",
|
||||
"Copie de sites inter-langues": "Copy of inter-language sites",
|
||||
"Copie des traductions rédigées": "Copy of written translations",
|
||||
"Copie terminée avec des erreurs": "Copy finished with errors",
|
||||
"Copie terminée avec succès": "Copy successfully completed",
|
||||
"Copier": "Copy",
|
||||
"Copier sauvegardes auto": "Copy auto backups",
|
||||
"Couleur de fond automatique": "Automatic background color",
|
||||
"Couleur icône haut de page": "Color of top page icon",
|
||||
"Couleur texte page active": "Active page text color",
|
||||
"Couleur unie ou papier-peint": "United color or wallpaper",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "Visible color in the absence of an image. <br /> The horizontal cursor regulates the level of transparency.",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "Visible color in the absence of an image. <br /> The horizontal cursor regulates the level of transparency. The color of the text is automatic.",
|
||||
"Couleurs": "Colors",
|
||||
"Dans le site": "Into the site",
|
||||
"Dans quelle langue utiliserez-vous Zwii ?": "In which language will you use Zwii?",
|
||||
"Date": "Date",
|
||||
"Description": "Site description",
|
||||
"Disponible si le consentement des cookies est activé.": "Available if cookie consent is enabled.",
|
||||
"Disposition": "Layout",
|
||||
"Données %s copiées vers %s": "Data %s copied to %s",
|
||||
"Données des modules": "Module data",
|
||||
"Données importées": "Imported data",
|
||||
"Dossier": "Folder",
|
||||
"Droits sur les dossiers": "Folder authorizations",
|
||||
"Droits sur les fichiers": "File authorizations",
|
||||
"Dupliquer": "Duplicate",
|
||||
"Dupliquer la page": "Duplicate the page",
|
||||
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "Disconnects the previously opened sessions on other browsers or terminals. Recommended activation.",
|
||||
"Déconnecter": "Disconnect",
|
||||
"Déconnexion !": "Logout!",
|
||||
"Déconnexion automatique": "Automatic disconnection",
|
||||
"Définir par défaut": "Set as default",
|
||||
"Dévoiler le mot de passe": "Reveal the password",
|
||||
"Effacer": "Delete",
|
||||
"Effacer la page": "Delete the page",
|
||||
"Effacer tous les commentaires": "Delete all Comments",
|
||||
"Effacer toutes les statistiques": "Delete all statistics",
|
||||
"Effacer un commentaire": "Delete Comment",
|
||||
"Effacer une catégorie": "Delete category",
|
||||
"Emplacement :": "Location:",
|
||||
"Emplacement dans le menu": "Location in the menu",
|
||||
"En bas au centre": "Down in the center",
|
||||
"En bas à droite": "At the bottom right",
|
||||
"En bas à gauche": "At the bottom left",
|
||||
"En cas de changement de module, les données du module précédent seront supprimées.": "In the event of a module change, data from the previous module will be deleted.",
|
||||
"En dessous du site": "Below the site",
|
||||
"En haut au centre": "Top in the center",
|
||||
"En haut à droite": "Top right",
|
||||
"En haut à gauche": "On the top corner left",
|
||||
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "In free position add the module by placing [module] to the desired location in your page.",
|
||||
"En-dehors du site": "Outside the site",
|
||||
"Enregistrer": "Save",
|
||||
"Envoyer un message de confirmation": "Send a confirmation message",
|
||||
"Erreur : sauvegarde non générée !": "Error: non-generated backup!",
|
||||
"Erreur d'URL": "URL error",
|
||||
"Erreur d'extraction, vérifiez les permissions": "Extraction error, check permissions",
|
||||
"Erreur de copie": "Copy error",
|
||||
"Erreur de copie, vérifiez les permissions": "Copy error, check permissions",
|
||||
"Erreur de lecture, vérifiez les permissions": "Reading error, check permissions",
|
||||
"Erreur inconnue": "unknown error",
|
||||
"Erreur inconnue, le module n'est pas installé": "Unknown error, the module is not installed",
|
||||
"Export CSV": "Export CSV",
|
||||
"Expéditeur": "From",
|
||||
"Extension": "Extension",
|
||||
"Extraire": "Extract",
|
||||
"Facebook": "Facebook",
|
||||
"Famille": "Family",
|
||||
"Favicon thème sombre": "Dark theme favicon",
|
||||
"Feuille de style spécifique à la page.": "Style sheet specific to the page.",
|
||||
"Fichiers": "Files",
|
||||
"Fichiers effacés": "Erased files",
|
||||
"Fil d'Ariane dans le titre": "Breadcrumb in the title",
|
||||
"Fond du sous-menu": "Background of the submenu",
|
||||
"FontId": "FontId",
|
||||
"Fonte": "Font",
|
||||
"Fonte actualisée": "Update",
|
||||
"Fonte créée": "Font created",
|
||||
"Fonte en ligne": "Online font",
|
||||
"Fonte installée": "Installed font",
|
||||
"Fonte non créée, ressource absente !": "Font not created, absent resource!",
|
||||
"Fonte supprimée": "Font deleted",
|
||||
"Fontes": "Fonts",
|
||||
"Format incorrect": "Wrong format",
|
||||
"Formulaire": "Form",
|
||||
"Fréquence de recherche": "Search frequency",
|
||||
"Fuseau horaire": "Time zone",
|
||||
"Gabarits de page - Barre latérale": "Page templates - Sidebar",
|
||||
"Gestion": "Management",
|
||||
"Gestion des modules": "Module management",
|
||||
"Gestion des thèmes": "Themes management",
|
||||
"Gestionnaire de fichiers": "File Manager",
|
||||
"Github": "Github",
|
||||
"Grande": "Large",
|
||||
"Grande (220%)": "Grande (220%)",
|
||||
"Grande (300px)": "Grande (300px)",
|
||||
"Gras": "Fetter",
|
||||
"Groupe": "Group",
|
||||
"Groupe associé": "Associated Group",
|
||||
"Groupe requis pour accéder à la page :": "Group required to access the page:",
|
||||
"Groupes": "Groups",
|
||||
"Générer sitemap.xml et robots.txt": "Generate sitemap.xml and robots.txt",
|
||||
"Générer une capture Open Graph": "Generate an Open Graph capture",
|
||||
"Gérer les catégories": "Manage categories",
|
||||
"Gérer les commentaires": "Manage comments",
|
||||
"Gérer les données": "Manage Data",
|
||||
"Hauteur": "Height:",
|
||||
"Hauteur de l'image": "Image Height",
|
||||
"Hauteur de l'image sélectionnée": "Selected Image Height",
|
||||
"Hauteur maximale": "Maximum height",
|
||||
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "Channel ID: https://www.youtube.com/channel/ [ID].",
|
||||
"Icône": "Icon",
|
||||
"Icône avec bulle de texte": "Icon with text bubble",
|
||||
"Icône haut de page, couleur arrière-plan": "Top page icon, background color",
|
||||
"Identifiant": "Identifier",
|
||||
"Identifiant (sans espace ni majuscule)": "Identifier (without space or capital letters)",
|
||||
"Identité": "Identity",
|
||||
"Identité de la fonte": "Identity of the font",
|
||||
"Identité du site": "Site identity",
|
||||
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "It appears in the title bar and sharing on social networks.",
|
||||
"Image": "Image",
|
||||
"Image étirée (100% 100%)": "Stretched image (100% 100%)",
|
||||
"Important": "Important",
|
||||
"Importante": "Important",
|
||||
"Importation d'utilisateurs": "Import of users",
|
||||
"Importation de fichier plat CSV": "CSV flat file import",
|
||||
"Importation effectuée": "Import done",
|
||||
"Importer": "Import",
|
||||
"Importer dans": "Import into",
|
||||
"Importer des utilisateurs en masse": "Import mass users",
|
||||
"Impossible d'ouvrir l'archive": "Impossible to open the archive",
|
||||
"Impossible de modifier votre propre groupe.": "Unable to modify your own group.",
|
||||
"Impossible de soumettre le formulaire, car il contient des erreurs": "Unable to submit the form, as it contains errors",
|
||||
"Impossible de supprimer une page contenant des pages enfants": "Unable to delete a page containing children's pages",
|
||||
"Impossible de supprimer votre propre compte": "Unable to delete your own account",
|
||||
"Inclure le contenu du gestionnaire de fichiers": "Include the content of the file manager",
|
||||
"Incorrect": "Incorrect",
|
||||
"Informations": "Informations",
|
||||
"Instagram": "Instagram",
|
||||
"Installation terminée": "Installation completed",
|
||||
"Installer": "Install",
|
||||
"Installer depuis le catalogue en ligne": "Install from the online catalog",
|
||||
"Installer depuis une archive": "Install from an archive",
|
||||
"Installer les données d'un module": "Install a module data",
|
||||
"Installer ou mettre à jour un module téléchargé": "Install or update a downloaded module",
|
||||
"Installer un module": "Install a module",
|
||||
"Installer un thème archivé (site ou administration)": "Install an archived theme (site or administration)",
|
||||
"Instructions JS ou jquery spécifiques à la page.": "JS or JQuery instructions specific to the page.",
|
||||
"Interface": "Interface",
|
||||
"Jeton invalide": "Invalid token",
|
||||
"Journal réinitialisé avec succès": "Log file successfully reset",
|
||||
"Journalisation": "Journalization",
|
||||
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "The archive was deposited in the file manager. Archives below version 9 are not accepted.",
|
||||
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "The identifier is defined when creating the account, it cannot be changed.",
|
||||
"La carte du site a été mise à jour": "The site card has been updated",
|
||||
"La copie de sauvegarde du fichier htaccess n'a pas été restaurée !": "Backup copy of htaccess file has not been restored!",
|
||||
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "The description of a page participates in its referencing, each page must have a different description.",
|
||||
"La page %s est ouverte par l'utilisateur %s": "Page %s opened by user %s",
|
||||
"La page demandée n'existe pas ou est introuvable (erreur 404)": "This page does not exists (error 404)",
|
||||
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "The page is displayed in a horizontal menu but not in the vertical menu of a sidebar.",
|
||||
"La première page que vos visiteurs verront.": "The first page that your visitors will see.",
|
||||
"La règlementation française impose un anonymat de niveau 2": "French regulations require level 2 anonymity",
|
||||
"La réécriture d'URL n'a pas été restaurée !": "URL rewriting has not been restored!",
|
||||
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "The backup of the files can take time. Continue?",
|
||||
"La suppression a échoué": "The deletion failed",
|
||||
"La version installée est plus récente": "The installed version is more recent",
|
||||
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "The verification is daily. Option deactivated if the server configuration does not allow it.",
|
||||
"Langue de l'administration": "Language of administration",
|
||||
"Langue du site par défaut": "Default site language",
|
||||
"Langue par défaut": "Default language",
|
||||
"Langues": "Languages",
|
||||
"Langues disponibles": "Available languages",
|
||||
"Langues installées": "Installed languages",
|
||||
"Largeur": "Width",
|
||||
"Largeur de l'image": "Image Width",
|
||||
"Largeur du site": "Site Width",
|
||||
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "The horizontal cursor regulates the level of transparency, place it on the left for invisible highlights.",
|
||||
"Le curseur horizontal règle le niveau de transparence.": "The horizontal cursor regulates the level of transparency.",
|
||||
"Le fuseau horaire est utile au bon référencement": "The time zone is useful for the right SEO",
|
||||
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "The accessory menu is aligned to the right of the menu bar, it is a place reserved for flags and the login button.",
|
||||
"Le menu horizontal intégral": "The full horizontal menu",
|
||||
"Le module %s a été %s": "The module %s was %s",
|
||||
"Le module %s de la page %s a été supprimé": "The %s module of the %s has been deleted",
|
||||
"Le module %s est désinstallé, il reste peut-être des données dans %s": "The module %s is uninstalled, there may be data in %s",
|
||||
"Le sous-menu de la page parente": "The parent page submenu",
|
||||
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "Flyover of an icon on the connection screen temporarily displays the password.",
|
||||
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "The short title is displayed in the menus. It can be identical to the page title.",
|
||||
"Les langues sélectionnées sont identiques": "The selected languages are identical",
|
||||
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "Legal notices are compulsory in France. An option of the footer adds a discrete link to this page.",
|
||||
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "The changes you have made may not be recorded.",
|
||||
"Les tailles des polices de la bannière, de menu et de pied de page sont proportionnelles à cette taille.": "The font sizes of the banner, menu and footer are proportional to this size.",
|
||||
"Lettres": "Letters",
|
||||
"Libre": "Libre",
|
||||
"Licence :": "Licence:",
|
||||
"Lien de connexion": "Login link",
|
||||
"Lien page des mentions légales.": "Link of legal notices.",
|
||||
"Liens": "Links",
|
||||
"Limitation des tentatives": "Limitation of attempts",
|
||||
"Limitée au site": "Limited to the site",
|
||||
"Linkedin": "Linkedin",
|
||||
"Liste noire": "Blacklist",
|
||||
"Liste noire réinitialisée avec succès": "Blacklist successfully reset",
|
||||
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "During an automatic update, keeps the htaccess file of the site root.",
|
||||
"Léger": "Light",
|
||||
"Légère": "Light",
|
||||
"Maigre": "Lean",
|
||||
"Maintenance": "Maintenance",
|
||||
"Majuscule à chaque mot": "Capper with each word",
|
||||
"Majuscules": "Capital letters",
|
||||
"Marges verticales": "Vertical margins",
|
||||
"Masquer la bannière en écran réduit": "Hide the banner in reduced screen",
|
||||
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "Hide the page and children's pages in the menu of a sidebar",
|
||||
"Masquer les pages enfants dans le menu horizontal": "Hide children's pages in the horizontal menu",
|
||||
"Membre": "Member",
|
||||
"Membre avec droit de partage": "Member with sharing rights",
|
||||
"Membre simple": "Simple member",
|
||||
"Mentions légales": "Legal notice",
|
||||
"Menu": "Menu",
|
||||
"Menu accessoire": "Accessory menu",
|
||||
"Menu burger dans écran réduit": "Burger menu in reduced screen",
|
||||
"Menu standard": "Standard menu",
|
||||
"Message d'acceptation des Cookies": "Cookie acceptance message",
|
||||
"Message de consentement aux cookies": "Cookie consent message",
|
||||
"Mettre à jour": "Update",
|
||||
"Mettre à jour le module orphelin": "Update the orphan module",
|
||||
"Minuscules": "Tiny",
|
||||
"Mise en forme des titres": "Formatting of titles",
|
||||
"Mise en forme du texte": "Text formatting",
|
||||
"Mise en forme du titre": "Title formatting",
|
||||
"Mise en page": "Layout",
|
||||
"Mise à jour": "Update",
|
||||
"Mise à jour automatisée": "Automated update",
|
||||
"Mise à jour terminée avec succès.": "Successful update completed.",
|
||||
"Modifications enregistrées": "Modifications recorded",
|
||||
"Module": "Module",
|
||||
"Module de la page": "Page module",
|
||||
"Modules": "Modules",
|
||||
"Modules configurés": "Configured modules",
|
||||
"Modules installés": "Installed modules",
|
||||
"Modules orphelins": "Orphaned modules",
|
||||
"Mot de passe": "Password",
|
||||
"Mot de passe oublié": "Forgot your password",
|
||||
"Mot de passe perdu": "Lost password",
|
||||
"Motorisé par": "Powered by",
|
||||
"Moyen": "Medium",
|
||||
"Moyenne": "Medium",
|
||||
"Moyenne (200%)": "Average (200%)",
|
||||
"Moyenne (200px)": "Average (200px)",
|
||||
"Méta-description": "Meta-description",
|
||||
"Méta-titre": "Meta title",
|
||||
"Ne pas afficher": "Do not display",
|
||||
"Ne pas charger l'exemple de site (utilisateurs avancés)": "Do not load the example of a site (advanced users)",
|
||||
"Ne pas répéter": "Do not repeat",
|
||||
"Ne pas saisir les balises": "Don't type tags",
|
||||
"News": "",
|
||||
"Niveau 1 (192.168.12.x)": "Level 1 (192.168.12.x)",
|
||||
"Niveau 2 (192.168.x.x)": "Level 2 (192.168.x.x)",
|
||||
"Niveau 3 (192.x.x.x)": "Level 3 (192.x.x.x)",
|
||||
"Nom": "Last Name",
|
||||
"Nom Prénom": "Last name First Name",
|
||||
"Nom du profil": "Profile Name",
|
||||
"Nom utilisateur": "Username",
|
||||
"Non": "No",
|
||||
"Non tronquée": "Unmanned",
|
||||
"Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.": "Our site is currently under maintenance. We are sorry for the inconvenience caused and do our best to be quickly back.",
|
||||
"Nouveau contenu localisé": "New localized content",
|
||||
"Nouveau mot de passe": "New Password",
|
||||
"Nouveau mot de passe enregistré": "New password recorded",
|
||||
"Nouvel utilisateur": "New user",
|
||||
"Nouvelle page créée": "New page created",
|
||||
"Nouvelle page ou barre latérale": "New page or sidebar",
|
||||
"Obligatoire": "Missing",
|
||||
"Ombre": "Shadow",
|
||||
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "Active option in disconnected mode only, children's pages are visible and accessible.",
|
||||
"Option recommandée pour sécuriser la connexion. S'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.": "Recommended option to secure the connection. Applies to all the Captchas of the site. Simple Captcha is limited to an addition of numbers from 0 to 10. Complex Captcha uses four numbers of 0 to 20. Recommended activation.",
|
||||
"Options": "Options",
|
||||
"Options avancées": "Advanced options",
|
||||
"Origine": "Origin",
|
||||
"Oui": "Yes",
|
||||
"Page": "Page",
|
||||
"Page 2/3 - barre 1/3": "Page 2/3 - Sidebar 1/3",
|
||||
"Page 3/4 - barre 1/4": "Page 3/4 - Sidebar 1/4",
|
||||
"Page associée": "Associated page",
|
||||
"Page de recherche": "Search page",
|
||||
"Page dupliquée": "Duplicate page",
|
||||
"Page et module dupliqués": "Duplicated page and module",
|
||||
"Page inexistante, erreur 404": "Page non-existent, error 404",
|
||||
"Page non cliquable": "Non-clickable page",
|
||||
"Page parent": "Parent page",
|
||||
"Page standard": "Standard page",
|
||||
"Page supprimée": "Deleted page",
|
||||
"Pages dans le menu": "Pages in the menu",
|
||||
"Pages du site": "Site pages",
|
||||
"Pages et les modules de": "Pages and modules of",
|
||||
"Pages orphelines": "Orphan pages",
|
||||
"Papier peint": "Wallpaper",
|
||||
"Par défaut le menu est affiché APRES le contenu de la page. Pour le positionner à un emplacement précis, insérez [MENU] dans le contenu de la page.": "By default the menu is displayed after the content of the page. To position it at a specific location, insert [MENU] into the content of the page.",
|
||||
"Paramètres": "Settings",
|
||||
"Paramètres de la localisation": "Location parameters",
|
||||
"Paramètres de la sauvegarde": "Backup settings",
|
||||
"Paramètres du profil": "Profile Settings",
|
||||
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "Settings to use when your host does not offer the mail sending feature.",
|
||||
"Pas de marge au-dessus et en dessous du site": "No margin above and below the site",
|
||||
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Remember to delete your browser's cache if the favicon does not change.",
|
||||
"Permission": "Permission",
|
||||
"Permission et référencement": "Permission and SEO",
|
||||
"Permissions": "Permissions",
|
||||
"Permissions sur les dossiers": "Folder Permissions",
|
||||
"Permissions sur les fichiers": "File Permissions",
|
||||
"Permissions sur les pages": "Page Permissions",
|
||||
"Petite": "Small",
|
||||
"Petite (150px)": "Small (150px)",
|
||||
"Petite (180%)": "Petite (180%)",
|
||||
"Pied de page": "Footer",
|
||||
"Pinterest": "Pinterest",
|
||||
"Plan du site": "Sitemap",
|
||||
"Police des titres": "Titles font",
|
||||
"Police du texte": "Text font",
|
||||
"Port SMTP": "SMTP port",
|
||||
"Port du proxy": "Proxy port",
|
||||
"Position": "Position",
|
||||
"Position du module": "Position of the module",
|
||||
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "To define the page as a sidebar, choose the option from the list.",
|
||||
"Presse Papier": "Clipboard",
|
||||
"Presse papier": "Clipboard",
|
||||
"Profils des groupes": "Group Profiles",
|
||||
"Proportionnelle à la taille définie dans le site.": "Proportional to that defined in the site.",
|
||||
"Prénom": "First name",
|
||||
"Prénom Nom": "Firstname name",
|
||||
"Préparation de la mise à jour": "Preparation of the update",
|
||||
"Préserver le fichier htaccess racine": "Preserve the root htaccess file",
|
||||
"Préserver les comptes des utilisateurs déjà installés": "Preserve user accounts already installed",
|
||||
"Prévenir l'utilisateur par mail": "Prevent the user by email",
|
||||
"Prévisualiser": "Preview",
|
||||
"Pseudo": "Pseudo",
|
||||
"Rang 9 > rang 1. Le profil de rang 1 n'est pas modifiable.": "Rank 9 > Rank 1. The profile of Rank 1 is not editable.",
|
||||
"Ratio": "Ratio",
|
||||
"Ratio :": "Ratio:",
|
||||
"Recherche": "Search",
|
||||
"Recherche dans le site": "Search on the site",
|
||||
"Rechercher": "Search",
|
||||
"Rechercher une mise à jour en ligne": "Search for an online update",
|
||||
"Redirection": "Redirection",
|
||||
"Redirection vers la connexion": "Redirection to connection",
|
||||
"Renommer": "Rename",
|
||||
"Renseignez les champs ci-dessous pour finaliser l'installation.": "Fill in the fields below to finalize the installation.",
|
||||
"Responsive (contain)": "Responsive (contain)",
|
||||
"Responsive (cover)": "Responsive (cover)",
|
||||
"Restauration des bases de données absentes": "Restoring missing databases",
|
||||
"Restauration effectuée avec succès": "Restoration successfully completed",
|
||||
"Restaurer": "Restore",
|
||||
"Restaurer les données du site": "Restore site data",
|
||||
"Rester connecté sur ce navigateur": "Stay connected on this browser",
|
||||
"Retour": "Return",
|
||||
"Rien à importer, erreur de format ou fichier incorrect": "Nothing to import, format error or incorrect file",
|
||||
"Rédacteur": "Editor",
|
||||
"Référencement": "SEO",
|
||||
"Réinitialisation du mot de passe": "Reset password",
|
||||
"Réinitialiser avec le thème par défaut": "Reset with the default theme",
|
||||
"Réinitialiser la feuille de style": "Reset the style sheet",
|
||||
"Réinitialiser la liste": "Reset the list",
|
||||
"Réinitialiser le journal": "Reset the log file",
|
||||
"Réinstaller": "Reinstall",
|
||||
"Répétition": "Repetition",
|
||||
"Réseau": "Network",
|
||||
"Réseaux sociaux": "Social networks",
|
||||
"S'ouvre dans un nouvel onglet": "Opens in a new tab",
|
||||
"SMTP": "SMTP",
|
||||
"SMTP personnalisé": "Custom SMTP",
|
||||
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "Enter the key, then validate the form before clicking on the generation button",
|
||||
"Saisissez le Titre de gestion des cookies.": "Enter the title of the cookie management window.",
|
||||
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "Enter the message for cookies set by Zwiicms, necessary for operation and which do not require consent.",
|
||||
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "Enter the text of the link to the legal notices, the page must be defined in the site configuration.",
|
||||
"Saisissez votre ID : https://pinterest.com/[ID].": "Enter your ID: https://pinterest.com/[ID].",
|
||||
"Saisissez votre ID : https://twitter.com/[ID].": "Enter your ID: https://twitter.com/[ID].",
|
||||
"Saisissez votre ID : https://www.facebook.com/[ID].": "Enter your ID: https://www.facebook.com/).",
|
||||
"Saisissez votre ID : https://www.instagram.com/[ID].": "Enter your ID: https://www.instagram.com/ [ID].",
|
||||
"Saisissez votre ID Github : https://github.com/[ID].": "Enter your GitHub ID: https://github.com/[ID].",
|
||||
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "Enter your LinkedIn ID: https://fr.linkedin.com/in/[ID].",
|
||||
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "Enter your user ID: https://www.youtube.com/user/ [ID].",
|
||||
"Sauvegarde": "Backup",
|
||||
"Sauvegarde automatique quotidienne du site": "Daily automatic backup of the site",
|
||||
"Sauvegarde du thème dans le": "Backup of the theme in the",
|
||||
"Sauvegarde générée avec succès": "Successfully generated backup.",
|
||||
"Sauvegarder": "Backup",
|
||||
"Sauvegarder et télécharger le module": "Save and download the module",
|
||||
"Sauvegarder le module dans le gestionnaire de fichiers": "Save the module in the file manager",
|
||||
"Sauvegarder les données du module dans le gestionnaire de fichiers": "Save module data in the file manager",
|
||||
"Sauvegarder les données du site": "Save site data",
|
||||
"Script dans body": "Script in body",
|
||||
"Script dans head": "Script in head",
|
||||
"Scripts externes": "External scripts",
|
||||
"Se déconnecter": "Logout",
|
||||
"Service en ligne inaccessible": "Inaccessible online service",
|
||||
"Seul un administrateur peut se connecter lors d'une maintenance": "Only an administrator can login during maintenance",
|
||||
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "If the content of the file manager is very large, it is better to copy by FTP.",
|
||||
"Signature": "Signature",
|
||||
"Site": "Site",
|
||||
"Site en maintenance": "Site under maintenance",
|
||||
"Size": "Size",
|
||||
"Source": "Source",
|
||||
"Standard": "Standard",
|
||||
"Style": "Style",
|
||||
"Suppression interdite": "Deletion prohibited",
|
||||
"Suppression interdite, page active dans la configuration de la langue du site": "Deletion not allowed, page is active in the site's language configuration",
|
||||
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "Deletes the question mark in the URLs, the option is unavailable with other web servers",
|
||||
"Supprimer": "Delete",
|
||||
"Supprimer la page": "Delete the page",
|
||||
"Supprimer le module": "Delete the module",
|
||||
"Supprimer toutes les sauvegardes automatiques ?": "Remove all automatic backups?",
|
||||
"Sur l'axe horizontal": "On the horizontal axis",
|
||||
"Sur l'axe vertical": "On the vertical axis",
|
||||
"Sur les deux axes": "On both axes",
|
||||
"Sécurité": "Security",
|
||||
"Sécurité de la connexion": "Connection security",
|
||||
"Sécurité désactivée": "Safety deactivated",
|
||||
"Sélectionner un fichier": "Select a file",
|
||||
"Sélectionnez au moins un contenu à afficher": "Select at least one content to display",
|
||||
"Sélectionnez la langue à copier vers une langue cible": "Select the language to copy to a target language",
|
||||
"Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Select an icon adapted to a dark theme. <br> Remember to delete your browser's cache if the favicon does not change.",
|
||||
"Sélectionnez une image ou une icône de petite dimension": "Select a small image or icon",
|
||||
"Sélectionnez une langue": "Select a language",
|
||||
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "Select a page containing the 'research' module. An option of the footer adds a discrete link to this page.",
|
||||
"Sélectionnez une page pour activer": "Select a page to activate",
|
||||
"Séparateur": "Separator",
|
||||
"Taille": "Size",
|
||||
"Text": "Text",
|
||||
"Texte": "Text",
|
||||
"Thème": "Theme",
|
||||
"Thème de l'administration": "Administration theme",
|
||||
"Thème du site": "Site theme",
|
||||
"Thème importé": "Imported theme",
|
||||
"Thèmes": "Themes",
|
||||
"Titre": "Title",
|
||||
"Titre court": "Short title",
|
||||
"Titre masqué": "Masked title",
|
||||
"Titre masqué dans la page": "Masked hidden in the page",
|
||||
"Titres": "Titles",
|
||||
"Tous les dossiers": "All Folders",
|
||||
"Tous les droits d'édition des contenus": "All content editing rights",
|
||||
"Tout Effacer": "Clear All",
|
||||
"Traduction supprimée": "Translation deleted",
|
||||
"Très grande": "Very large",
|
||||
"Très grande (240%)": "Very large (240%)",
|
||||
"Très grande (400px)": "Very large (400px)",
|
||||
"Très important": "Very important",
|
||||
"Très importante": "Very important",
|
||||
"Très léger": "Very light",
|
||||
"Très légère": "Very light",
|
||||
"Très petite": "Very small",
|
||||
"Très petite (100px) ": "Very small (100px)",
|
||||
"Très petite (160%)": "Very small (160%)",
|
||||
"Twitter": "Twitter",
|
||||
"Type de captcha": "Type of Captcha",
|
||||
"Type de proxy": "Proxy type",
|
||||
"Téléchargement et validation de l'archive": "Download and validation of the archive",
|
||||
"Télécharger": "Download",
|
||||
"Télécharger la liste": "Download list",
|
||||
"Télécharger le journal": "Download logs",
|
||||
"Télécharger le module dans le gestionnaire de fichiers": "Download the module in the file manager",
|
||||
"Téléverser": "Upload",
|
||||
"URL incorrecte": "Incorrect url",
|
||||
"Un mail a été envoyé pour confirmer la réinitialisation": "An email was sent to confirm the reset",
|
||||
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "An archive of the file /site/data is kept for 30 days. Recommended activation",
|
||||
"Une erreur est survenue lors de l'étape :": "An error occurred during the stage:",
|
||||
"Url du fichier de fonte": "Font file URL",
|
||||
"Utilisateur inexistant": "Non-existent user",
|
||||
"Utilisateur supprimé": "User deleted",
|
||||
"Utilisateurs": "Users",
|
||||
"Valider": "Submit",
|
||||
"Version": "Version",
|
||||
"Version n°": "Version n°",
|
||||
"Vider dossier sauvegardes auto": "Empty auto backup files",
|
||||
"Visiteur": "Visitor",
|
||||
"Vous n'êtes pas autorisé à consulter cette page (erreur 403)": "You are not authorised to view this page (error 403)",
|
||||
"Youtube": "Youtube",
|
||||
"ZwiiCMS - Installation": "ZwiiCMS - Installation",
|
||||
"actualisé": "updated",
|
||||
"favicon.ico": "favicon.ico",
|
||||
"faviconDark.ico": "favicondark.ico",
|
||||
"gestionnaire de fichiers": "file manager",
|
||||
"installé": "installed",
|
||||
"jour": "day",
|
||||
"jours": "days",
|
||||
"sauvegardé avec succès": "successfully saved",
|
||||
"vers": "to",
|
||||
"À droite": "Right",
|
||||
"À gauche": "Left",
|
||||
"À l'emplacement du mot clé [MODULE] dans la page": "At the location of the keyword [MODULE] on the page",
|
||||
"Échec de l'écriture, vérifiez les permissions": "Failure of writing, check permissions",
|
||||
"Échecs": "Fail",
|
||||
"Éditer": "Edit",
|
||||
"Éditer la page": "Edit the page",
|
||||
"Éditer les dialogues": "Edit dialogs",
|
||||
"Éditer une catégorie": "Edit category",
|
||||
"Éditeur": "Editor",
|
||||
"Éditeur CSS": "CSS editor",
|
||||
"Éditeur JS": "JS editor",
|
||||
"Éditeur de script %s": "Script editor %s",
|
||||
"Éditeur de script dans Body": "Script editor in Body",
|
||||
"Éditeur de script dans Head": "Script editor in Head",
|
||||
"Éditeur simple": "Simple editor",
|
||||
"Édition des pages": "Page editing",
|
||||
"Édition du profil %s": "Edit Profile %s",
|
||||
"Éléments": "Items",
|
||||
"Étendu sur la page": "Spread across the page",
|
||||
"Étiquettes des pages spéciales": "Special pages labels",
|
||||
"Dimensions minimales": "Minimum dimensions",
|
||||
"Taille maximale du fichier": "Maximum file size",
|
||||
"5 Mo pour les images JPEG": "5 MB for JPEG images",
|
||||
"1 Mo pour les images PNG": "1 MB for PNG images",
|
||||
"Poids": "Weight",
|
||||
"Supprimer ce profil ?": "Delete this profile?",
|
||||
"Masqué": "Hidden",
|
||||
"Haut de page": "Top of Page",
|
||||
"Bas de page": "Bottom of Page",
|
||||
"Petit triangle": "Small Triangle",
|
||||
"Grand triangle": "Large Triangle",
|
||||
"Flèche": "Arrow",
|
||||
"Modèle": "Template",
|
||||
"Bouton de navigation droit": "Right Navigation Button",
|
||||
"Bouton de navigation gauche": "Left Navigation Button",
|
||||
"Groupes / Profils": "Groups / Profiles",
|
||||
"Prénom commence par": "First Name starts with",
|
||||
"Nom commence par": "Last Name starts with",
|
||||
"Impossible de réinitialiser le mot de passe de ce compte !": "Impossible to reset this account password!"
|
||||
}
|
693
core/module/install/ressource/i18n/es.json
Normal file
693
core/module/install/ressource/i18n/es.json
Normal file
@ -0,0 +1,693 @@
|
||||
{
|
||||
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "'No mostrar' crea una página huérfana a la que no se puede acceder a través de los menús.",
|
||||
"'Sauvegarder et télécharger les données du module": "Guardar y descargar de los datos del módulo",
|
||||
"1 jour": "1 Jour",
|
||||
"1/4 : Préparation...": "1/4: Preparando...",
|
||||
"10 minutes": "10 minutos",
|
||||
"10 tentatives": "6 intentos",
|
||||
"14 jours": "14 dias",
|
||||
"15 minutes": "15 minutos",
|
||||
"2 jours": "2 dias",
|
||||
"2/4 : Téléchargement...": "2/4: Descargando...",
|
||||
"3 tentatives": "3 intentos",
|
||||
"3/4 : Installation...": "3/4: Instalando...",
|
||||
"4 jours": "4 días",
|
||||
"4/4 : Configuration...": "4/4: Configuración...",
|
||||
"5 minutes": "5 minutos",
|
||||
"5 tentatives": "5 intentos",
|
||||
"7 jours": "7 días",
|
||||
"Accueil": "Inicio",
|
||||
"Accède au site": "Acceso al sitio",
|
||||
"Accède aux pages réservées": "Acceso a páginas restringidas",
|
||||
"Accède aux pages réservées et à un dossier partagé": "Acceso a páginas restringidas y una carpeta compartida",
|
||||
"Accès bloqué %d minutes": "Acceso bloqueado minutos",
|
||||
"Accès désactivé": "Acceso desactivado",
|
||||
"Accès interdit, erreur 403": "Acceso denegado, error 403",
|
||||
"Action interdite": "Acción no permitida",
|
||||
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "Activación obligatoria según las leyes francesas a menos que utilice su propio sistema de consentimiento.",
|
||||
"Activer": "Activar",
|
||||
"Activer la journalisation": "Habilitar registro",
|
||||
"Actualiser": "Actualizar",
|
||||
"Adaptation": "Adaptación",
|
||||
"Administrateur": "Administrador",
|
||||
"Administration": "Administración",
|
||||
"Adresse SMTP": "Dirección SMTP",
|
||||
"Adresse du proxy": "Dirección proxy",
|
||||
"Adresse électronique": "Correo electrónico",
|
||||
"Affectation": "Asignación",
|
||||
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "Mostrar el nombre de la página principal seguido del nombre de la página, el título no debe ocultarse.",
|
||||
"Affiche les icônes de gestion du compte et de déconnexion des membres simples connectés": "Muestra los iconos de gestión de cuenta y cierre de sesión para miembros regulares conectados",
|
||||
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "Para garantizar el correcto funcionamiento de Zwii, no cierre esta página antes de que se complete la operación",
|
||||
"Aide": "Ayuda",
|
||||
"Ajouter": "Agregar",
|
||||
"Ajouter un profil": "Agregar un perfil",
|
||||
"Ajouter un utilisateur": "Agregar usuario",
|
||||
"Ajouter une fonte": "Añadir tipografía",
|
||||
"Alignement": "Alineación de contenido",
|
||||
"Aligner la bannière avec le contenu": "Alinear el banner con el contenido",
|
||||
"Ancien mot de passe": "Antigua contraseña",
|
||||
"Anonymat des adresses IP": "Anonimato de la dirección IP",
|
||||
"Apache URL intelligent": "URL inteligente de Apache",
|
||||
"Apache URL intelligentes": "URL inteligentes de Apache",
|
||||
"Apparence": "Apariencia",
|
||||
"Appliquer": "Aplicar",
|
||||
"Approuver un commentaire": "Aprobar comentarios",
|
||||
"Après": "Después",
|
||||
"Après la bannière": "Después del banner",
|
||||
"Après le contenu de la page": "Después del contenido de la página",
|
||||
"Archive": "Archivo",
|
||||
"Archive ZIP": "Archivo ZIP",
|
||||
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "Archivo copiado a la carpeta Módulos del administrador de archivos",
|
||||
"Archive de thème invalide": "Archivo de tema no válido",
|
||||
"Archive invalide": "Archivo no válido",
|
||||
"Archive invalide, l'écriture dans le dossier core est interdite": "Archivo no válido, está prohibido escribir en la carpeta core",
|
||||
"Archive invalide, le descripteur est absent": "Archivo no válido, falta el descriptor",
|
||||
"Archive invalide, le fichier de classe est absent": "Archivo no válido, falta el archivo de clase",
|
||||
"Archive invalide, les dossiers ne correspondent pas au descripteur": "Archivo no válido, las carpetas no coinciden con el descriptor",
|
||||
"Archive non spécifiée ou introuvable": "Archivo no especificado o no encontrado",
|
||||
"Archive à restaurer": "Archivo para restaurar",
|
||||
"Arrière plan": "Fondo",
|
||||
"Arrière plan des blocs": "Fondo de bloques",
|
||||
"Arrière plan des champs": "Fondo de zona",
|
||||
"Arrondi des angles": "Redondeo de ángulos",
|
||||
"Au centre": "En el centro",
|
||||
"Au début": "Al principio",
|
||||
"Au milieu au centre": "En el medio en el centro",
|
||||
"Au milieu à droite": "En el medio derecho",
|
||||
"Au milieu à gauche": "En el medio a la izquierda",
|
||||
"Au-dessus du site": "Por encima del sitio",
|
||||
"Aucun": "Ninguno",
|
||||
"Aucun dossier": "Sin carpeta",
|
||||
"Aucun fichier journal à télécharger": "No hay archivos de registro para descargar",
|
||||
"Aucun journal à effacer": "No hay registros para borrar",
|
||||
"Aucun menu": "Ningún menú",
|
||||
"Aucune": "Ninguna",
|
||||
"Aucune liste noire à effacer": "No hay lista negra para borrar",
|
||||
"Aucune liste noire à télécharger": "No hay lista negra para descargar",
|
||||
"Auteur :": "Autor",
|
||||
"Authentification": "Autenticación",
|
||||
"Automatique": "Automáquica",
|
||||
"Autoriser les robots à référencer le site": "Permitir que los robots hagan referencia al sitio",
|
||||
"Autorisé": "Autorizado",
|
||||
"Avant la bannière": "Antes del banner",
|
||||
"Avant le contenu de la page": "Antes del contenido de la página",
|
||||
"Background": "Fondo",
|
||||
"Banni": "Prohibición",
|
||||
"Bannière": "Banner",
|
||||
"Bannière cliquable": "Banner",
|
||||
"Barre 1/3 - page 2/3": "Barra 1/3 - página 2/3",
|
||||
"Barre 1/4 - page 1/2 - barre 1/4": "Barra 1/4 - página 1/2 - Barra 1/4",
|
||||
"Barre 1/4 - page 3/4": "Barra 1/4 - página 3/4",
|
||||
"Barre 2/12 - page 7/12 - barre 3/12": "Barra 2/12 - página 7/12 - Barra 3/12",
|
||||
"Barre 3/12 - page 7/12 - barre 2/12": "Barra 3/12 - página 7/12 - Barra 2/12",
|
||||
"Barre de membre": "Barra de miembro",
|
||||
"Barre latérale": "Barra lateral",
|
||||
"Barre latérale droite :": "Barra lateral derecha:",
|
||||
"Barre latérale gauche :": "Barra lateral izquierda:",
|
||||
"Barres latérales": "Barras laterales",
|
||||
"Bienvenue %s %s": "Bienvenido %s %s",
|
||||
"Blocage après échecs": "Bloquear después de fallar",
|
||||
"Blog": "Blog",
|
||||
"Bords arrondis": "Bordes redondeados",
|
||||
"Bordure des blocs": "Borde de bloques",
|
||||
"Bordure des champs": "Borde de zona",
|
||||
"Bouton Aide": "Boton de ayuda",
|
||||
"Bouton Standard": "Botón estándar",
|
||||
"Bouton de validation": "Botón Validación",
|
||||
"Bouton effacement": "Botón Eliminar",
|
||||
"Bouton retour": "Botón de retroceso",
|
||||
"Bouton standard": "Botón estándar",
|
||||
"Bouton validation": "Botón de validación",
|
||||
"Boutons": "Botones",
|
||||
"Caché": "Oculto",
|
||||
"Cachée": "Oculto",
|
||||
"Captcha complexe": "Captcha complejo",
|
||||
"Captcha à la connexion": "Captcha al iniciar sesión",
|
||||
"Captcha, identifiant ou mot de passe incorrects": "Captcha, nombre de usuario o contraseña incorrecta",
|
||||
"Capture d'écran Open Graph": "Captura de pantalla de Open Graph",
|
||||
"Capture d'écran générée avec succès": "Captura de pantalla generada con éxito",
|
||||
"Casse": "Roto",
|
||||
"Catalogue": "Catálogo",
|
||||
"Catégorie": "Categoría",
|
||||
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "Este miembro podrá cargar o descargar archivos en la carpeta 'compartir' y sus subcarpetas",
|
||||
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "Esta página no debería aparecer en el árbol del menú. Crear una página huérfana.",
|
||||
"Cette redirection ne concerne que les pages d'administration du site.": "Esta redirección solo afecta a las páginas de administración del sitio.",
|
||||
"Chaîne Youtube": "Canal de Youtube",
|
||||
"Chiffres": "Cifras",
|
||||
"Cible": "Objetivo",
|
||||
"Cliquez sur une zone afin d'accéder à ses options de personnalisation.": "Haga clic en un área para acceder a sus opciones de personalización.",
|
||||
"Commentaire": "Comentario",
|
||||
"Complète": "sin truncar",
|
||||
"Compte administrateur": "Cuenta de administrador",
|
||||
"Compte de l'utilisateur": "Cuenta de usuario",
|
||||
"Compte verrouillé": "Cuenta bloqueada",
|
||||
"Configuration": "Configuración",
|
||||
"Configuration du module": "Configuración del módulo",
|
||||
"Configurer": "Configurar",
|
||||
"Configurer mon compte": "Configurar mi cuenta",
|
||||
"Confirmation": "Confirmación",
|
||||
"Confirmer la suppression de cet utilisateur": "Confirmar eliminación de este usuario",
|
||||
"Confirmer la dissociation du module de cette page": "Confirmar desvincular módulo de esta página",
|
||||
"Confirmer la désinstallation du module": "Confirmar la desinstalación del módulo",
|
||||
"Confirmer la suppression de cet utilisateur": "Confirme la eliminación de este usuario",
|
||||
"Confirmer la suppression de cette langue": "Confirmar eliminación de este idioma",
|
||||
"Confirmer la suppression de la page": "Confirmar la eliminación de la página",
|
||||
"Confirmer la suppression des données du module": "Confirmar la eliminación de datos del módulo",
|
||||
"Confirmez-vous la suppression de cette page ?": "¿Confirma la eliminación de esta página?",
|
||||
"Connexion": "Conexión",
|
||||
"Consulter l'aide en ligne": "Consultar la ayuda en línea",
|
||||
"Contents": "Contenido",
|
||||
"Contenu": "Contenido",
|
||||
"Contenu HTML": "Contenido HTML",
|
||||
"Contenu avancé": "Contenido avanzado",
|
||||
"Contenu du menu vertical": "Contenido del menú vertical",
|
||||
"Contrôle total": "Control total",
|
||||
"Cookies": "Cookies",
|
||||
"Cookies Zwii": "Cookies Zwii",
|
||||
"Copie de contenus localisés": "Copia de contenidos localizados",
|
||||
"Copie de sites inter-langues": "Copia del sitio multilingües",
|
||||
"Copie des traductions rédigées": "Copia de traducciones redactadas",
|
||||
"Copie terminée avec des erreurs": "Copia completada con errores",
|
||||
"Copie terminée avec succès": "Copia completada con éxito",
|
||||
"Copier": "Copiar",
|
||||
"Copier sauvegardes auto": "Copiar guardados automáticos",
|
||||
"Couleur de fond automatique": "Color de fondo automático",
|
||||
"Couleur icône haut de page": "Color del icono superior de la página",
|
||||
"Couleur texte page active": "Color del texto de página activa",
|
||||
"Couleur unie ou papier-peint": "Color unido o papel tapiz",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "Color visible en ausencia de una imagen.<br />El control deslizante horizontal ajusta el nivel de transparencia.",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "Color visible en ausencia de una imagen.<br />El control deslizante horizontal ajusta el nivel de transparencia. El color del texto es automático.",
|
||||
"Couleurs": "Colores",
|
||||
"Dans le site": "En el sitio",
|
||||
"Dans quelle langue utiliserez-vous Zwii ?": "¿En qué idioma usará Zwii?",
|
||||
"Date": "fecha",
|
||||
"Description": "Descripción del sitio",
|
||||
"Disponible si le consentement des cookies est activé.": "Disponible si se ha otorgado el consentimiento de las cookies.",
|
||||
"Disposition": "Arreglo",
|
||||
"Données %s copiées vers %s": "Datos %s copiados hacia %s",
|
||||
"Données des modules": "Datos de los módulos",
|
||||
"Données importées": "Datos importados",
|
||||
"Dossier": "Carpeta",
|
||||
"Droits sur les dossiers": "Derechos de las carpetas",
|
||||
"Droits sur les fichiers": "Derechos de los archivos",
|
||||
"Dupliquer": "Duplicar",
|
||||
"Dupliquer la page": "Duplicar la página",
|
||||
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "Desconecte sesiones abiertas previamente en otros navegadores o dispositivos. Activación recomendada.",
|
||||
"Déconnecter": "Desconectar",
|
||||
"Déconnexion !": "¡Cerrar sesión!",
|
||||
"Déconnexion automatique": "Cierre de sesión automático",
|
||||
"Définir par défaut": "Establecer como predeterminado",
|
||||
"Dévoiler le mot de passe": "Revelar la contraseña",
|
||||
"Effacer": "Borrar",
|
||||
"Effacer la page": "Borrar página",
|
||||
"Effacer tous les commentaires": "Borrar todos los comentarios",
|
||||
"Effacer toutes les statistiques": "Borrar todas las estadísticas",
|
||||
"Effacer un commentaire": "Borrar el comentario",
|
||||
"Effacer une catégorie": "Borrar categoría",
|
||||
"Emplacement :": "Ubicación",
|
||||
"Emplacement dans le menu": "Ubicación en el menú",
|
||||
"En bas au centre": "Abajo en el centro",
|
||||
"En bas à droite": "Abajo a la derecha",
|
||||
"En bas à gauche": "Abajo a la izquierda",
|
||||
"En cas de changement de module, les données du module précédent seront supprimées.": "Al cambiar de módulo se borrarán los datos del módulo anterior.",
|
||||
"En dessous du site": "Debajo del sitio",
|
||||
"En haut au centre": "Cubra en el centro",
|
||||
"En haut à droite": "Arriba a la derecha",
|
||||
"En haut à gauche": "Arriba a la izquierda",
|
||||
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "En posición libre agregue el módulo colocando [MODULE] en la ubicación deseada en su página.",
|
||||
"En-dehors du site": "Fuera del sitio",
|
||||
"Enregistrer": "Registrar",
|
||||
"Envoyer un message de confirmation": "Enviar mensaje de confirmación",
|
||||
"Erreur : sauvegarde non générée !": "Error: copia de seguridad no generada!",
|
||||
"Erreur d'URL": "Error de URL",
|
||||
"Erreur d'extraction, vérifiez les permissions": "Error de extracción, verifique los permisos",
|
||||
"Erreur de copie": "Error de copia",
|
||||
"Erreur de copie, vérifiez les permissions": "error de copia, verifique las permisiones",
|
||||
"Erreur de lecture, vérifiez les permissions": "Error de lectura, verifique los permisos",
|
||||
"Erreur inconnue": "error desconocido",
|
||||
"Erreur inconnue, le module n'est pas installé": "Error desconocido, el módulo no está instalado",
|
||||
"Export CSV": "Exportar CSV",
|
||||
"Expéditeur": "Remitente",
|
||||
"Extension": "Extensión",
|
||||
"Extraire": "Extraer",
|
||||
"Facebook": "Facebook",
|
||||
"Famille": "Vínculo",
|
||||
"Favicon thème sombre": "favicon de tema oscuro",
|
||||
"Feuille de style spécifique à la page.": "Hoja de estilo específica de la página.",
|
||||
"Fichiers": "Archivos",
|
||||
"Fichiers effacés": "archivos borrados",
|
||||
"Fil d'Ariane dans le titre": "Migas de pan en el título",
|
||||
"Fond du sous-menu": "Fondo del submenú",
|
||||
"FontId": "ID de fuente",
|
||||
"Fonte": "Fuente",
|
||||
"Fonte actualisée": "fuente actualizada",
|
||||
"Fonte créée": "Fuente creada",
|
||||
"Fonte en ligne": "Tipografía en línea",
|
||||
"Fonte installée": "Tipografía instalada",
|
||||
"Fonte non créée, ressource absente !": "¡Fuente no creada, por falta recurso!",
|
||||
"Fonte supprimée": "Fuente eliminada",
|
||||
"Fontes": "Tipografias",
|
||||
"Format incorrect": "Formato incorrecto",
|
||||
"Formulaire": "Formulario",
|
||||
"Fréquence de recherche": "Frecuencia de búsqueda",
|
||||
"Fuseau horaire": "Zona horaria",
|
||||
"Gabarits de page - Barre latérale": "Patrón de página - Barra lateral",
|
||||
"Gestion": "Administrar",
|
||||
"Gestion des modules": "Gestión de módulos",
|
||||
"Gestion des thèmes": "Gestión de temas",
|
||||
"Gestionnaire de fichiers": "Administrador de archivos",
|
||||
"Github": "Github",
|
||||
"Grande": "Grande",
|
||||
"Grande (220%)": "Grande (220%)",
|
||||
"Grande (300px)": "Grande (300px)",
|
||||
"Gras": "Negrita",
|
||||
"Groupe": "Grupo",
|
||||
"Groupe associé": "Grupo asociado",
|
||||
"Groupe requis pour accéder à la page :": "Grupo necesario para acceder a la página:",
|
||||
"Groupes": "Grupos",
|
||||
"Générer sitemap.xml et robots.txt": "Generar sitemap.xml y robots.txt",
|
||||
"Générer une capture Open Graph": "Generar una captura de Open Graph",
|
||||
"Gérer les catégories": "Gestionar categorías",
|
||||
"Gérer les commentaires": "Administrar comentarios",
|
||||
"Gérer les données": "Administrar datos",
|
||||
"Hauteur": "Altura",
|
||||
"Hauteur de l'image": "Altura de la imagen",
|
||||
"Hauteur de l'image sélectionnée": "Altura de la imagen seleccionada",
|
||||
"Hauteur maximale": "Altura máxima",
|
||||
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "ID del canal: https://www.youtube.com/channel/[ID].",
|
||||
"Icône": "Icono",
|
||||
"Icône avec bulle de texte": "Icono con burbuja de texto",
|
||||
"Icône haut de page, couleur arrière-plan": "Icono superior de la página, color de fondo",
|
||||
"Identifiant": "Identificación",
|
||||
"Identifiant (sans espace ni majuscule)": "Identificación (sin espacios ni mayúsculas)",
|
||||
"Identité": "Identificación",
|
||||
"Identité de la fonte": "Identidad de tipografía",
|
||||
"Identité du site": "identidad del sitio",
|
||||
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "Aparece en la barra de título y se comparte en redes sociales.",
|
||||
"Image": "Imagen",
|
||||
"Image étirée (100% 100%)": "Imagen estirada (100% 100%)",
|
||||
"Important": "Importante",
|
||||
"Importante": "Importante",
|
||||
"Importation d'utilisateurs": "Importación de usuarios",
|
||||
"Importation de fichier plat CSV": "Importar archivo plano CSV",
|
||||
"Importation effectuée": "Importación realizada",
|
||||
"Importer": "Importar",
|
||||
"Importer dans": "Importar a",
|
||||
"Importer des utilisateurs en masse": "Importar usuarios de forma masiva",
|
||||
"Impossible d'ouvrir l'archive": "No se puede abrir el archivo",
|
||||
"Impossible de modifier votre propre groupe.": "No puede editar su propio grupo.",
|
||||
"Impossible de soumettre le formulaire, car il contient des erreurs": "No se puede enviar el formulario porque contiene errores",
|
||||
"Impossible de supprimer une page contenant des pages enfants": "No se puede eliminar una página que contiene páginas secundarias",
|
||||
"Impossible de supprimer votre propre compte": "No puede eliminar su propia cuenta",
|
||||
"Inclure le contenu du gestionnaire de fichiers": "Incluir el contenido del administrador de archivos",
|
||||
"Incorrect": "Incorrecto",
|
||||
"Informations": "Información",
|
||||
"Instagram": "Instagram",
|
||||
"Installation terminée": "instalación completa",
|
||||
"Installer": "Instalar",
|
||||
"Installer depuis le catalogue en ligne": "Instalar desde el archivo en línea",
|
||||
"Installer depuis une archive": "Instalar desde un archivo",
|
||||
"Installer les données d'un module": "Instalar datos de un módulo",
|
||||
"Installer ou mettre à jour un module téléchargé": "Instalar o actualizar un módulo descargado",
|
||||
"Installer un module": "Instalar un módulo",
|
||||
"Installer un thème archivé (site ou administration)": "Instalar un tema archivado (sitio o administración)",
|
||||
"Instructions JS ou jquery spécifiques à la page.": "Instrucciones JS o jquery específicas de la página.",
|
||||
"Interface": "Idiomas interfaz",
|
||||
"Jeton invalide": "Simbolo no valido",
|
||||
"Journal réinitialisé avec succès": "Registro reiniciado con éxito",
|
||||
"Journalisation": "Inicio sesión",
|
||||
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "El archivo ha sido depositado en el administrador de archivos. No se aceptan archivos inferiores a la versión 9.",
|
||||
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "El identificador se define al crear la cuenta, no se puede modificar.",
|
||||
"La carte du site a été mise à jour": "El mapa del sitio ha sido actualizado.",
|
||||
"La copie de sauvegarde du fichier htaccess n'a pas été restaurée !": "¡La copia de seguridad del archivo htaccess no ha sido restaurada!",
|
||||
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "La descripción de una página participa en su referenciación, cada página debe tener una descripción diferente.",
|
||||
"La page %s est ouverte par l'utilisateur %s": "La página %s ha sido abierta por el usuario %s",
|
||||
"La page demandée n'existe pas ou est introuvable (erreur 404)": "La page demandée n'existe pas ou est introuvable (erreur 404)",
|
||||
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "La página se muestra en un menú horizontal pero no en el menú vertical de una barra lateral.",
|
||||
"La première page que vos visiteurs verront.": "La primera página que verán tus visitantes.",
|
||||
"La règlementation française impose un anonymat de niveau 2": "La normativa francesa impone el anonimato de nivel 2",
|
||||
"La réécriture d'URL n'a pas été restaurée !": "¡La reescritura de URL no ha sido restaurada!",
|
||||
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "La copia de seguridad de los archivos puede tardar un poco. ¿Desea continuar?",
|
||||
"La suppression a échoué": "Eliminación fallida",
|
||||
"La version installée est plus récente": "La versión instalada es más nueva.",
|
||||
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "La comprobación es diaria. Opción deshabilitada si la configuración del servidor no lo permite.",
|
||||
"Langue de l'administration": "Idioma de la administración",
|
||||
"Langue du site par défaut": "Idioma predeterminado del sitio",
|
||||
"Langue par défaut": "Idioma predeterminado",
|
||||
"Langues": "Idiomas",
|
||||
"Langues disponibles": "Idiomas Disponibles",
|
||||
"Langues installées": "Idiomas instalados",
|
||||
"Largeur": "Anchura o Ancho",
|
||||
"Largeur de l'image": "Ancho de la imagen",
|
||||
"Largeur du site": "Ancho del sitio",
|
||||
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "El control deslizante horizontal establece el nivel de transparencia, colóquelo completamente hacia la izquierda para obtener un resaltado invisible.",
|
||||
"Le curseur horizontal règle le niveau de transparence.": "El cursor horizontal regula el nivel de transparencia.",
|
||||
"Le fuseau horaire est utile au bon référencement": "La zona horaria es útil para una buena referencia",
|
||||
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "El menù accesorio está alineado a la derecha de la barra de menú, es un marcador de posición para las banderas y el botón de inicio de sesión",
|
||||
"Le menu horizontal intégral": "El menú horizontal completo",
|
||||
"Le module %s a été %s": "El módulo %s ha sido %s",
|
||||
"Le module %s de la page %s a été supprimé": "Se eliminó el módulo %s de la página %s",
|
||||
"Le module %s est désinstallé, il reste peut-être des données dans %s": "El módulo %s está desinstalado, es posible que queden datos en %s",
|
||||
"Le sous-menu de la page parente": "El submenú de la página principal",
|
||||
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "Al pasar el cursor sobre un ícono de la pantalla de inicio de sesión, se muestra temporalmente la contraseña",
|
||||
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "El título corto se muestra en los menús. Puede ser el mismo que el título de la página.",
|
||||
"Les langues sélectionnées sont identiques": "Los idiomas seleccionados son idénticos",
|
||||
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "Los avisos legales son obligatorios en Francia. Una opción en el pie de página agrega un enlace discreto a esta página.",
|
||||
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "Es posible que no se guarden los cambios realizados.",
|
||||
"Les tailles des polices de la bannière, de menu et de pied de page sont proportionnelles à cette taille.": "Los tamaños de fuente del banner, menú y pie de página son proporcionales a este tamaño.",
|
||||
"Lettres": "Letras",
|
||||
"Libre": "Libre",
|
||||
"Licence :": "Licencia",
|
||||
"Lien de connexion": "Enlace de inicio de sesión",
|
||||
"Lien page des mentions légales.": "Enlace página aviso legal.",
|
||||
"Liens": "Enlaces",
|
||||
"Limitation des tentatives": "Limitación de intentos",
|
||||
"Limitée au site": "Limitado al sitio",
|
||||
"Linkedin": "Linkedin",
|
||||
"Liste noire": "Lista negra",
|
||||
"Liste noire réinitialisée avec succès": "Lista negra restablecida con éxito",
|
||||
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "Durante una actualización automática, mantenga el archivo htaccess de la raíz del sitio.",
|
||||
"Léger": "Ligero",
|
||||
"Légère": "Ligera",
|
||||
"Maigre": "Delgado",
|
||||
"Maintenance": "Mantenimiento",
|
||||
"Majuscule à chaque mot": "Capper con cada palabra",
|
||||
"Majuscules": "Letras mayúsculas",
|
||||
"Marges verticales": "Márgenes verticales",
|
||||
"Masquer la bannière en écran réduit": "Ocultar el banner en pantalla reducida",
|
||||
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "Ocultar página y páginas secundarias en un menú de la barra lateral",
|
||||
"Masquer les pages enfants dans le menu horizontal": "Ocultar páginas secundarias en el menú horizontal",
|
||||
"Membre": "Miembro",
|
||||
"Membre avec droit de partage": "Miembro con derecho de compartir",
|
||||
"Membre simple": "Miembro simple",
|
||||
"Mentions légales": "Notas legales",
|
||||
"Menu": "Menù",
|
||||
"Menu accessoire": "Menú accesorio",
|
||||
"Menu burger dans écran réduit": "Menú hamburguesa en pantalla reducida",
|
||||
"Menu standard": "Menú estándar",
|
||||
"Message d'acceptation des Cookies": "Mensaje de aceptación de cookies",
|
||||
"Message de consentement aux cookies": "Mensaje de consentimiento de cookies",
|
||||
"Mettre à jour": "Actualizar",
|
||||
"Mettre à jour le module orphelin": "Actualizar módulo huérfano",
|
||||
"Minuscules": "Diminuto",
|
||||
"Mise en forme des titres": "Formato de título",
|
||||
"Mise en forme du texte": "Formato de texto",
|
||||
"Mise en forme du titre": "Formato de título",
|
||||
"Mise en page": "Diseño",
|
||||
"Mise à jour": "actualización",
|
||||
"Mise à jour automatisée": "Actualización automática",
|
||||
"Mise à jour terminée avec succès.": "Actualización completada con éxito.",
|
||||
"Modifications enregistrées": "Cambios guardados",
|
||||
"Module": "Módulo",
|
||||
"Module de la page": "Módulo de página",
|
||||
"Modules": "Módulos",
|
||||
"Modules configurés": "Módulos Configurados",
|
||||
"Modules installés": "Módulos instalados",
|
||||
"Modules orphelins": "Módulos huérfanos",
|
||||
"Mot de passe": "Contraseña",
|
||||
"Mot de passe oublié": "Contraseña olvidada",
|
||||
"Mot de passe perdu": "Contraseña perdida",
|
||||
"Motorisé par": "Motorizado por",
|
||||
"Moyen": "Medio",
|
||||
"Moyenne": "Media",
|
||||
"Moyenne (200%)": "Promedio (200%)",
|
||||
"Moyenne (200px)": "Promedio (200px)",
|
||||
"Méta-description": "Meta-descripción",
|
||||
"Méta-titre": "Meta-título",
|
||||
"Ne pas afficher": "No se muestra",
|
||||
"Ne pas charger l'exemple de site (utilisateurs avancés)": "No cargar sitio de muestra (usuarios avanzados)",
|
||||
"Ne pas répéter": "No repitas",
|
||||
"Ne pas saisir les balises": "No ingrese las etiquetas",
|
||||
"News": "Noticias",
|
||||
"Niveau 1 (192.168.12.x)": "Nivel 1 (192.168.12.x)",
|
||||
"Niveau 2 (192.168.x.x)": "Nivel 2 (192.168.x.x)",
|
||||
"Niveau 3 (192.x.x.x)": "Nivel 3 (192.x.x.x)",
|
||||
"Nom": "Nombre",
|
||||
"Nom Prénom": "Apellido nombre",
|
||||
"Nom du profil": "Nombre del perfil",
|
||||
"Nom utilisateur": "Nombre de usuario",
|
||||
"Non": "No",
|
||||
"Non tronquée": "Sin personal",
|
||||
"Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.": "Nuestro sitio está actualmente en mantenimiento. Lamentamos las molestias y estamos haciendo todo lo posible para regresar lo antes posible",
|
||||
"Nouveau contenu localisé": "Nuevo contenido localizado",
|
||||
"Nouveau mot de passe": "Nueva contraseña",
|
||||
"Nouveau mot de passe enregistré": "Nueva contraseña guardada",
|
||||
"Nouvel utilisateur": "Nuevo usuario",
|
||||
"Nouvelle page créée": "Nueva página creada",
|
||||
"Nouvelle page ou barre latérale": "Nueva página o barra lateral",
|
||||
"Obligatoire": "Obligatorio",
|
||||
"Ombre": "Sombra",
|
||||
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "Opción activa solo en modo fuera de línea, las páginas secundarias son visibles y accesibles.",
|
||||
"Option recommandée pour sécuriser la connexion. S'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.": "Opción recomendada para asegurar la conexión. Se aplica a todos los captchas en el sitio. El captcha simple está limitado a una suma de números del 0 al 10. El captcha complejo usa cuatro operaciones de números del 0 al 20. Activación recomendada.",
|
||||
"Options": "Opciones",
|
||||
"Options avancées": "Opciones avanzadas",
|
||||
"Origine": "Origen",
|
||||
"Oui": "Sí",
|
||||
"Page": "Página",
|
||||
"Page 2/3 - barre 1/3": "página 2/3 - Barra 1/3",
|
||||
"Page 3/4 - barre 1/4": "página 3/4 - Barra 1/4",
|
||||
"Page associée": "Página asociada",
|
||||
"Page de recherche": "Página de búsqueda",
|
||||
"Page dupliquée": "Página duplicada",
|
||||
"Page et module dupliqués": "Página y módulo duplicados",
|
||||
"Page inexistante, erreur 404": "La página no existe, error 404",
|
||||
"Page non cliquable": "No se puede hacer clic en la página",
|
||||
"Page parent": "Página principal",
|
||||
"Page standard": "Página estándar",
|
||||
"Page supprimée": "página eliminada",
|
||||
"Pages dans le menu": "Páginas del menú",
|
||||
"Pages du site": "Páginas del sitio",
|
||||
"Pages et les modules de": "Páginas y módulos",
|
||||
"Pages orphelines": "Páginas huérfanas",
|
||||
"Papier peint": "Color de fondo",
|
||||
"Par défaut le menu est affiché APRES le contenu de la page. Pour le positionner à un emplacement précis, insérez [MENU] dans le contenu de la page.": "Por defecto, el menú se muestra DESPUÉS del contenido de la página. Para colocarlo en una ubicación específica, inserte [MENÚ] en el contenido de la página.",
|
||||
"Paramètres": "Configuraciones",
|
||||
"Paramètres de la localisation": "Configuración de la ubicación",
|
||||
"Paramètres de la sauvegarde": "Configuración de copia de seguridad",
|
||||
"Paramètres du profil": "Configuración del perfil",
|
||||
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "Configuraciones para usar cuando su host no ofrece la funcionalidad para enviar correo.",
|
||||
"Pas de marge au-dessus et en dessous du site": "Sin margen encima y debajo del sitio",
|
||||
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Recuerde eliminar el caché de su navegador si el favicon no cambia.",
|
||||
"Permission": "Permiso",
|
||||
"Permission et référencement": "Permiso y referenciación",
|
||||
"Permissions": "Permisos",
|
||||
"Permissions sur les dossiers": "Permisos de las carpetas",
|
||||
"Permissions sur les fichiers": "Permisos de los archivos",
|
||||
"Permissions sur les pages": "Permisos de las páginas",
|
||||
"Petite": "Pequeño",
|
||||
"Petite (150px)": "Pequeño (150px)",
|
||||
"Petite (180%)": "Petite (180%)",
|
||||
"Pied de page": "Pie de página",
|
||||
"Pinterest": "Pinterest",
|
||||
"Plan du site": "Mapa del sitio",
|
||||
"Police des titres": "Tipografía del titulo",
|
||||
"Police du texte": "Tipografía del texto",
|
||||
"Port SMTP": "Puerto SMTP",
|
||||
"Port du proxy": "Puerto proxy",
|
||||
"Position": "Posición",
|
||||
"Position du module": "Posición del módulo",
|
||||
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "Para configurar la página como barra lateral, elija la opción de la lista.",
|
||||
"Presse Papier": "Portapapeles",
|
||||
"Presse papier": "Portapapeles",
|
||||
"Profils des groupes": "Perfiles de grupos",
|
||||
"Proportionnelle à la taille définie dans le site.": "Proporcional a la definida en el sitio.",
|
||||
"Prénom": "Nombre de pila",
|
||||
"Prénom Nom": "Nombre Apellido",
|
||||
"Préparation de la mise à jour": "Preparáción de la actualización",
|
||||
"Préserver le fichier htaccess racine": "Conservar archivo raíz htaccess",
|
||||
"Préserver les comptes des utilisateurs déjà installés": "Conservar las cuentas de usuario ya instaladas",
|
||||
"Prévenir l'utilisateur par mail": "Notificar al usuario por correo electrónico",
|
||||
"Prévisualiser": "Previsualizar",
|
||||
"Pseudo": "Apodo",
|
||||
"Rang 9 > rang 1. Le profil de rang 1 n'est pas modifiable.": "Rango 9 > rango 1. El perfil del rango 1 no se puede modificar.",
|
||||
"Ratio": "Proporción",
|
||||
"Ratio :": "Relación",
|
||||
"Recherche": "Buscar",
|
||||
"Recherche dans le site": "Buscar en el sitio",
|
||||
"Rechercher": "Buscar",
|
||||
"Rechercher une mise à jour en ligne": "Buscar una actualización en línea",
|
||||
"Redirection": "Redirección",
|
||||
"Redirection vers la connexion": "Redirección hacia conexión",
|
||||
"Renommer": "Renombrar",
|
||||
"Renseignez les champs ci-dessous pour finaliser l'installation.": "Complete las zonas a continuación para terminar la instalación.",
|
||||
"Responsive (contain)": "Responsivo (contener)",
|
||||
"Responsive (cover)": "Responsivo (cobertura)",
|
||||
"Restauration des bases de données absentes": "Restauración de bases de datos faltantes",
|
||||
"Restauration effectuée avec succès": "Restauración completada con éxito",
|
||||
"Restaurer": "Restaurar",
|
||||
"Restaurer les données du site": "Restaurar datos del sitio",
|
||||
"Rester connecté sur ce navigateur": "Permanecer conectado en este navegador",
|
||||
"Retour": "Retroceder",
|
||||
"Rien à importer, erreur de format ou fichier incorrect": "Nada que importar, error de formato o archivo incorrecto",
|
||||
"Rédacteur": "Editor",
|
||||
"Référencement": "Referenciación",
|
||||
"Réinitialisation du mot de passe": "Restablecer la contraseña de usuario",
|
||||
"Réinitialiser avec le thème par défaut": "establecer tema predeterminado",
|
||||
"Réinitialiser la feuille de style": "Restablecer hoja de estilo",
|
||||
"Réinitialiser la liste": "Restablecer lista",
|
||||
"Réinitialiser le journal": "Restablecer registro",
|
||||
"Réinstaller": "Reinstalar",
|
||||
"Répétition": "Repetición",
|
||||
"Réseau": "La red",
|
||||
"Réseaux sociaux": "Redes sociales",
|
||||
"S'ouvre dans un nouvel onglet": "Se abre en una nueva pestaña",
|
||||
"SMTP": "SMTP",
|
||||
"SMTP personnalisé": "SMTP personalizado",
|
||||
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "Ingrese la clave, luego valide el formulario antes de hacer clic en el botón generar",
|
||||
"Saisissez le Titre de gestion des cookies.": "Introduce el título de la ventana de gestión de cookies.",
|
||||
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "Ingrese el mensaje para las cookies colocadas por ZwiiCMS, necesarias para su funcionamiento y que no requieren consentimiento.",
|
||||
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "Ingrese el texto del enlace a los avisos legales, la página debe estar definida en la configuración del sitio.",
|
||||
"Saisissez votre ID : https://pinterest.com/[ID].": "Ingrese su ID: https://pinterest.com/[ID].",
|
||||
"Saisissez votre ID : https://twitter.com/[ID].": "Ingrese su ID: https://twitter.com/[ID].",
|
||||
"Saisissez votre ID : https://www.facebook.com/[ID].": "Ingrese su ID: https://www.facebook.com/[ID].",
|
||||
"Saisissez votre ID : https://www.instagram.com/[ID].": "Ingrese su ID: https://www.instagram.com/[ID].",
|
||||
"Saisissez votre ID Github : https://github.com/[ID].": "Ingrese su ID de Github: https://github.com/[ID].",
|
||||
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "Ingrese su ID de Linkedin: https://fr.linkedin.com/in/[ID].",
|
||||
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "Ingrese su ID de usuario: https://www.youtube.com/user/[ID].",
|
||||
"Sauvegarde": "Salvaguardad",
|
||||
"Sauvegarde automatique quotidienne du site": "Copia de seguridad diaria automática del sitio",
|
||||
"Sauvegarde du thème dans le": "Guardando tema en el",
|
||||
"Sauvegarde générée avec succès": "Copia de seguridad generada con éxito",
|
||||
"Sauvegarder": "Para salvaguardar",
|
||||
"Sauvegarder et télécharger le module": "Guardar y descargar módulo",
|
||||
"Sauvegarder le module dans le gestionnaire de fichiers": "Guardar módulo en el administrador de archivos",
|
||||
"Sauvegarder les données du module dans le gestionnaire de fichiers": "Guardar de los datos del módulo en el administrador de archivos",
|
||||
"Sauvegarder les données du site": "Guardar datos del sitio",
|
||||
"Script dans body": "Script en el body",
|
||||
"Script dans head": "Script en el head",
|
||||
"Scripts externes": "Guiones externos",
|
||||
"Se déconnecter": "Desconectarse",
|
||||
"Service en ligne inaccessible": "Servicio en línea inaccesible",
|
||||
"Seul un administrateur peut se connecter lors d'une maintenance": "Solo un administrador puede iniciar sesión durante un mantenimiento",
|
||||
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "Si el contenido del administrador de archivos es muy grande, es mejor copiar por FTP.",
|
||||
"Signature": "Firma",
|
||||
"Site": "Idiomas instalados",
|
||||
"Site en maintenance": "Sitio en mantenimiento",
|
||||
"Size": "Tamaño",
|
||||
"Source": "Fuente",
|
||||
"Standard": "Estándar",
|
||||
"Style": "Estilo",
|
||||
"Suppression interdite": "Borrado prohibido",
|
||||
"Suppression interdite, page active dans la configuration de la langue du site": "Eliminación no permitida, la página está activa en la configuración de idioma del sitio",
|
||||
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "Eliminar el signo de interrogación en las URL, la opción no está disponible con otros servidores web",
|
||||
"Supprimer": "Borrar",
|
||||
"Supprimer la page": "Eliminar página",
|
||||
"Supprimer le module": "Eliminar módulo",
|
||||
"Supprimer toutes les sauvegardes automatiques ?": "¿Eliminar todos los guardados automáticos?",
|
||||
"Sur l'axe horizontal": "En el eje horizontal",
|
||||
"Sur l'axe vertical": "En el eje vertical",
|
||||
"Sur les deux axes": "En ambos hachas",
|
||||
"Sécurité": "Seguridad",
|
||||
"Sécurité de la connexion": "Seguridad de la conexión",
|
||||
"Sécurité désactivée": "Seguridad desactivada",
|
||||
"Sélectionner un fichier": "Seleccione un archivo",
|
||||
"Sélectionnez au moins un contenu à afficher": "Seleccione al menos un contenido para mostrar",
|
||||
"Sélectionnez la langue à copier vers une langue cible": "Seleccione el idioma para copiar hacia oyto idioma",
|
||||
"Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Seleccione un ícono adecuado para un tema oscuro.<br>Recuerde eliminar el caché de su navegador si el favicon no cambia",
|
||||
"Sélectionnez une image ou une icône de petite dimension": "Seleccione una imagen o icono pequeño",
|
||||
"Sélectionnez une langue": "Seleccione un idioma",
|
||||
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "Seleccione una página que contenga el módulo 'Buscar'. Una opción de pie de página agrega un enlace discreto a esta página.",
|
||||
"Sélectionnez une page pour activer": "Seleccione una página para activar",
|
||||
"Séparateur": "Separador",
|
||||
"Taille": "Tamaño",
|
||||
"Text": "Texto",
|
||||
"Texte": "Texto",
|
||||
"Thème": "Tema",
|
||||
"Thème de l'administration": "Tema de administración",
|
||||
"Thème du site": "Tema del sitio",
|
||||
"Thème importé": "Tema importado",
|
||||
"Thèmes": "Temas",
|
||||
"Titre": "Título",
|
||||
"Titre court": "Título corto",
|
||||
"Titre masqué": "Título enmascarado",
|
||||
"Titre masqué dans la page": "Título oculto en la página",
|
||||
"Titres": "Títulos",
|
||||
"Tous les dossiers": "Todas las carpetas",
|
||||
"Tous les droits d'édition des contenus": "Todos los derechos de edición de contenido",
|
||||
"Tout Effacer": "Borrar todo",
|
||||
"Traduction supprimée": "Traducción eliminada",
|
||||
"Très grande": "Muy grande",
|
||||
"Très grande (240%)": "Muy grande (240%)",
|
||||
"Très grande (400px)": "Muy grande (400px)",
|
||||
"Très important": "Muy importante",
|
||||
"Très importante": "Muy importante",
|
||||
"Très léger": "Muy ligero",
|
||||
"Très légère": "Muy ligera",
|
||||
"Très petite": "Muy pequeño",
|
||||
"Très petite (100px) ": "Muy pequeño (100px)",
|
||||
"Très petite (160%)": "Muy pequeño (160%)",
|
||||
"Twitter": "Twitter",
|
||||
"Type de captcha": "Tipo de captcha",
|
||||
"Type de proxy": "Tipo de proxy",
|
||||
"Téléchargement et validation de l'archive": "Descarga y validación del archivo",
|
||||
"Télécharger": "Descargar",
|
||||
"Télécharger la liste": "Descargar la revista",
|
||||
"Télécharger le journal": "Descargar la revista",
|
||||
"Télécharger le module dans le gestionnaire de fichiers": "Descargar módulo al administrador de archivos",
|
||||
"Téléverser": "Subir",
|
||||
"URL incorrecte": "URL incorrecta",
|
||||
"Un mail a été envoyé pour confirmer la réinitialisation": "Se ha enviado un correo electrónico para confirmar el restablecimiento.",
|
||||
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "Un archivo que contiene la carpeta /site/data se conserva durante 30 días. Activación recomendada .",
|
||||
"Une erreur est survenue lors de l'étape :": "Ocurrió un error durante el proceso",
|
||||
"Url du fichier de fonte": "Url del archivo de tipo de letra",
|
||||
"Utilisateur inexistant": "Usuario inexistente",
|
||||
"Utilisateur supprimé": "Usuario eliminado",
|
||||
"Utilisateurs": "Usuarios",
|
||||
"Valider": "Validar",
|
||||
"Version": "Versión",
|
||||
"Version n°": "Número de versión",
|
||||
"Vider dossier sauvegardes auto": "Carpeta de autoguardado vacía",
|
||||
"Visiteur": "Visitante",
|
||||
"Vous n'êtes pas autorisé à consulter cette page (erreur 403)": "No está autorizado para ver esta página (error 403)",
|
||||
"Youtube": "YouTube",
|
||||
"ZwiiCMS - Installation": "ZwiiCMS - Instalación",
|
||||
"actualisé": "actualizado",
|
||||
"favicon.ico": "Recuerde borrar el caché de su navegador si el favicon no cambia.",
|
||||
"faviconDark.ico": "faviconDark.ico",
|
||||
"gestionnaire de fichiers": "administrador de archivos",
|
||||
"installé": "instalado",
|
||||
"jour": "día",
|
||||
"jours": "días",
|
||||
"sauvegardé avec succès": "Guardado exitosamente",
|
||||
"vers": "hacia",
|
||||
"À droite": "A la derecha",
|
||||
"À gauche": "A la izquierda",
|
||||
"À l'emplacement du mot clé [MODULE] dans la page": "En la ubicación de la palabra clave [MODULE] en la página",
|
||||
"Échec de l'écriture, vérifiez les permissions": "Escritura fallida, verifique los permisos",
|
||||
"Échecs": "Fracasos",
|
||||
"Éditer": "Editar",
|
||||
"Éditer la page": "Editar página",
|
||||
"Éditer les dialogues": "Editar los diálogos",
|
||||
"Éditer une catégorie": "Editar categoría",
|
||||
"Éditeur": "Editor",
|
||||
"Éditeur CSS": "Editor de CSS",
|
||||
"Éditeur JS": "Editor de JS",
|
||||
"Éditeur de script %s": "Editor de script %s",
|
||||
"Éditeur de script dans Body": "Éditor del script en el Body",
|
||||
"Éditeur de script dans Head": "Éditor del script en el Head",
|
||||
"Éditeur simple": "Editor simple",
|
||||
"Édition des pages": "Edición de páginas",
|
||||
"Édition du profil %s": "Edición del perfil %s",
|
||||
"Éléments": "Elementos",
|
||||
"Étendu sur la page": "Extendido en la página",
|
||||
"Étiquettes des pages spéciales": "Etiquetas de páginas especiales",
|
||||
"Dimensions minimales": "Dimensiones mínimas",
|
||||
"Taille maximale du fichier": "Tamaño máximo de archivo",
|
||||
"5 Mo pour les images JPEG": "5 MB para imágenes JPEG",
|
||||
"1 Mo pour les images PNG": "1 MB para imágenes PNG",
|
||||
"Poids": "Peso",
|
||||
"Supprimer ce profil ?": "¿Eliminar este perfil?",
|
||||
"Masqué": "Oculto",
|
||||
"Haut de page": "Parte superior de la página",
|
||||
"Bas de page": "Parte inferior de la página",
|
||||
"Petit triangle": "Triángulo pequeño",
|
||||
"Grand triangle": "Triángulo grande",
|
||||
"Flèche": "Flecha",
|
||||
"Modèle": "Plantilla",
|
||||
"Bouton de navigation droit": "Botón de navegación derecha",
|
||||
"Bouton de navigation gauche": "Botón de navegación izquierda",
|
||||
"Groupes / Profils": "Grupos / Perfiles",
|
||||
"Prénom commence par": "El nombre comienza con",
|
||||
"Nom commence par": "El apellido comienza con",
|
||||
"Impossible de réinitialiser le mot de passe de ce compte !": "No puedo restablecer la contraseña de esta cuenta."
|
||||
}
|
693
core/module/install/ressource/i18n/fr_FR.json
Normal file
693
core/module/install/ressource/i18n/fr_FR.json
Normal file
@ -0,0 +1,693 @@
|
||||
{
|
||||
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "",
|
||||
"'Sauvegarder et télécharger les données du module": "",
|
||||
"1 jour": "",
|
||||
"1/4 : Préparation...": "",
|
||||
"10 minutes": "",
|
||||
"10 tentatives": "",
|
||||
"14 jours": "",
|
||||
"15 minutes": "",
|
||||
"2 jours": "",
|
||||
"2/4 : Téléchargement...": "",
|
||||
"3 tentatives": "",
|
||||
"3/4 : Installation...": "",
|
||||
"4 jours": "",
|
||||
"4/4 : Configuration...": "",
|
||||
"5 minutes": "",
|
||||
"5 tentatives": "",
|
||||
"7 jours": "",
|
||||
"Accueil": "",
|
||||
"Accède au site": "",
|
||||
"Accède aux pages réservées": "",
|
||||
"Accède aux pages réservées et à un dossier partagé": "",
|
||||
"Accès bloqué %d minutes": "",
|
||||
"Accès désactivé": "",
|
||||
"Accès interdit, erreur 403": "",
|
||||
"Action interdite": "",
|
||||
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "",
|
||||
"Activer": "",
|
||||
"Activer la journalisation": "",
|
||||
"Actualiser": "",
|
||||
"Adaptation": "",
|
||||
"Administrateur": "",
|
||||
"Administration": "",
|
||||
"Adresse SMTP": "",
|
||||
"Adresse du proxy": "",
|
||||
"Adresse électronique": "",
|
||||
"Affectation": "",
|
||||
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "",
|
||||
"Affiche les icônes de gestion du compte et de déconnexion des membres simples connectés": "",
|
||||
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "",
|
||||
"Aide": "",
|
||||
"Ajouter": "",
|
||||
"Ajouter un profil": "",
|
||||
"Ajouter un utilisateur": "",
|
||||
"Ajouter une fonte": "",
|
||||
"Alignement": "",
|
||||
"Aligner la bannière avec le contenu": "",
|
||||
"Ancien mot de passe": "",
|
||||
"Anonymat des adresses IP": "",
|
||||
"Apache URL intelligent": "",
|
||||
"Apache URL intelligentes": "",
|
||||
"Apparence": "",
|
||||
"Appliquer": "",
|
||||
"Approuver un commentaire": "",
|
||||
"Après": "",
|
||||
"Après la bannière": "",
|
||||
"Après le contenu de la page": "",
|
||||
"Archive": "",
|
||||
"Archive ZIP": "",
|
||||
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "",
|
||||
"Archive de thème invalide": "",
|
||||
"Archive invalide": "",
|
||||
"Archive invalide, l'écriture dans le dossier core est interdite": "",
|
||||
"Archive invalide, le descripteur est absent": "",
|
||||
"Archive invalide, le fichier de classe est absent": "",
|
||||
"Archive invalide, les dossiers ne correspondent pas au descripteur": "",
|
||||
"Archive non spécifiée ou introuvable": "",
|
||||
"Archive à restaurer": "",
|
||||
"Arrière plan": "",
|
||||
"Arrière plan des blocs": "",
|
||||
"Arrière plan des champs": "",
|
||||
"Arrondi des angles": "",
|
||||
"Au centre": "",
|
||||
"Au début": "",
|
||||
"Au milieu au centre": "",
|
||||
"Au milieu à droite": "",
|
||||
"Au milieu à gauche": "",
|
||||
"Au-dessus du site": "",
|
||||
"Aucun": "",
|
||||
"Aucun dossier": "",
|
||||
"Aucun fichier journal à télécharger": "",
|
||||
"Aucun journal à effacer": "",
|
||||
"Aucun menu": "",
|
||||
"Aucune": "",
|
||||
"Aucune liste noire à effacer": "",
|
||||
"Aucune liste noire à télécharger": "",
|
||||
"Auteur :": "",
|
||||
"Authentification": "",
|
||||
"Automatique": "",
|
||||
"Autoriser les robots à référencer le site": "",
|
||||
"Autorisé": "",
|
||||
"Avant la bannière": "",
|
||||
"Avant le contenu de la page": "",
|
||||
"Background": "",
|
||||
"Banni": "",
|
||||
"Bannière": "",
|
||||
"Bannière cliquable": "",
|
||||
"Barre 1/3 - page 2/3": "",
|
||||
"Barre 1/4 - page 1/2 - barre 1/4": "",
|
||||
"Barre 1/4 - page 3/4": "",
|
||||
"Barre 2/12 - page 7/12 - barre 3/12": "",
|
||||
"Barre 3/12 - page 7/12 - barre 2/12": "",
|
||||
"Barre de membre": "",
|
||||
"Barre latérale": "",
|
||||
"Barre latérale droite :": "",
|
||||
"Barre latérale gauche :": "",
|
||||
"Barres latérales": "",
|
||||
"Bienvenue %s %s": "",
|
||||
"Blocage après échecs": "",
|
||||
"Blog": "",
|
||||
"Bords arrondis": "",
|
||||
"Bordure des blocs": "",
|
||||
"Bordure des champs": "",
|
||||
"Bouton Aide": "",
|
||||
"Bouton Standard": "",
|
||||
"Bouton de validation": "",
|
||||
"Bouton effacement": "",
|
||||
"Bouton retour": "",
|
||||
"Bouton standard": "",
|
||||
"Bouton validation": "",
|
||||
"Boutons": "",
|
||||
"Caché": "",
|
||||
"Cachée": "",
|
||||
"Captcha complexe": "",
|
||||
"Captcha à la connexion": "",
|
||||
"Captcha, identifiant ou mot de passe incorrects": "",
|
||||
"Capture d'écran Open Graph": "",
|
||||
"Capture d'écran générée avec succès": "",
|
||||
"Casse": "",
|
||||
"Catalogue": "",
|
||||
"Catégorie": "",
|
||||
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "",
|
||||
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "",
|
||||
"Cette redirection ne concerne que les pages d'administration du site.": "",
|
||||
"Chaîne Youtube": "",
|
||||
"Chiffres": "",
|
||||
"Cible": "",
|
||||
"Cliquez sur une zone afin d'accéder à ses options de personnalisation.": "",
|
||||
"Commentaire": "",
|
||||
"Complète": "",
|
||||
"Compte administrateur": "",
|
||||
"Compte de l'utilisateur": "",
|
||||
"Compte verrouillé": "",
|
||||
"Configuration": "",
|
||||
"Configuration du module": "",
|
||||
"Configurer": "",
|
||||
"Configurer mon compte": "",
|
||||
"Confirmation": "",
|
||||
"Confirmer la suppression de cet utilisateur": "",
|
||||
"Confirmer la dissociation du module de cette page": "",
|
||||
"Confirmer la désinstallation du module": "",
|
||||
"Confirmer la suppression de cet utilisateur": "",
|
||||
"Confirmer la suppression de cette langue": "",
|
||||
"Confirmer la suppression de la page": "",
|
||||
"Confirmer la suppression des données du module": "",
|
||||
"Confirmez-vous la suppression de cette page ?": "",
|
||||
"Connexion": "",
|
||||
"Consulter l'aide en ligne": "",
|
||||
"Contents": "",
|
||||
"Contenu": "",
|
||||
"Contenu HTML": "",
|
||||
"Contenu avancé": "",
|
||||
"Contenu du menu vertical": "",
|
||||
"Contrôle total": "",
|
||||
"Cookies": "",
|
||||
"Cookies Zwii": "",
|
||||
"Copie de contenus localisés": "",
|
||||
"Copie de sites inter-langues": "",
|
||||
"Copie des traductions rédigées": "",
|
||||
"Copie terminée avec des erreurs": "",
|
||||
"Copie terminée avec succès": "",
|
||||
"Copier": "",
|
||||
"Copier sauvegardes auto": "",
|
||||
"Couleur de fond automatique": "",
|
||||
"Couleur icône haut de page": "",
|
||||
"Couleur texte page active": "",
|
||||
"Couleur unie ou papier-peint": "",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "",
|
||||
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "",
|
||||
"Couleurs": "",
|
||||
"Dans le site": "",
|
||||
"Dans quelle langue utiliserez-vous Zwii ?": "",
|
||||
"Date": "",
|
||||
"Description": "",
|
||||
"Disponible si le consentement des cookies est activé.": "",
|
||||
"Disposition": "",
|
||||
"Données %s copiées vers %s": "",
|
||||
"Données des modules": "",
|
||||
"Données importées": "",
|
||||
"Dossier": "",
|
||||
"Droits sur les dossiers": "",
|
||||
"Droits sur les fichiers": "",
|
||||
"Dupliquer": "",
|
||||
"Dupliquer la page": "",
|
||||
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "",
|
||||
"Déconnecter": "",
|
||||
"Déconnexion !": "",
|
||||
"Déconnexion automatique": "",
|
||||
"Définir par défaut": "",
|
||||
"Dévoiler le mot de passe": "",
|
||||
"Effacer": "",
|
||||
"Effacer la page": "",
|
||||
"Effacer tous les commentaires": "",
|
||||
"Effacer toutes les statistiques": "",
|
||||
"Effacer un commentaire": "",
|
||||
"Effacer une catégorie": "",
|
||||
"Emplacement :": "",
|
||||
"Emplacement dans le menu": "",
|
||||
"En bas au centre": "",
|
||||
"En bas à droite": "",
|
||||
"En bas à gauche": "",
|
||||
"En cas de changement de module, les données du module précédent seront supprimées.": "",
|
||||
"En dessous du site": "",
|
||||
"En haut au centre": "",
|
||||
"En haut à droite": "",
|
||||
"En haut à gauche": "",
|
||||
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "",
|
||||
"En-dehors du site": "",
|
||||
"Enregistrer": "",
|
||||
"Envoyer un message de confirmation": "",
|
||||
"Erreur : sauvegarde non générée !": "",
|
||||
"Erreur d'URL": "",
|
||||
"Erreur d'extraction, vérifiez les permissions": "",
|
||||
"Erreur de copie": "",
|
||||
"Erreur de copie, vérifiez les permissions": "",
|
||||
"Erreur de lecture, vérifiez les permissions": "",
|
||||
"Erreur inconnue": "",
|
||||
"Erreur inconnue, le module n'est pas installé": "",
|
||||
"Export CSV": "",
|
||||
"Expéditeur": "",
|
||||
"Extension": "",
|
||||
"Extraire": "",
|
||||
"Facebook": "",
|
||||
"Famille": "",
|
||||
"Favicon thème sombre": "",
|
||||
"Feuille de style spécifique à la page.": "",
|
||||
"Fichiers": "",
|
||||
"Fichiers effacés": "",
|
||||
"Fil d'Ariane dans le titre": "",
|
||||
"Fond du sous-menu": "",
|
||||
"FontId": "",
|
||||
"Fonte": "",
|
||||
"Fonte actualisée": "",
|
||||
"Fonte créée": "",
|
||||
"Fonte en ligne": "",
|
||||
"Fonte installée": "",
|
||||
"Fonte non créée, ressource absente !": "",
|
||||
"Fonte supprimée": "",
|
||||
"Fontes": "",
|
||||
"Format incorrect": "",
|
||||
"Formulaire": "",
|
||||
"Fréquence de recherche": "",
|
||||
"Fuseau horaire": "",
|
||||
"Gabarits de page - Barre latérale": "",
|
||||
"Gestion": "",
|
||||
"Gestion des modules": "",
|
||||
"Gestion des thèmes": "",
|
||||
"Gestionnaire de fichiers": "",
|
||||
"Github": "",
|
||||
"Grande": "",
|
||||
"Grande (220%)": "",
|
||||
"Grande (300px)": "",
|
||||
"Gras": "",
|
||||
"Groupe": "",
|
||||
"Groupe associé": "",
|
||||
"Groupe requis pour accéder à la page :": "",
|
||||
"Groupes": "",
|
||||
"Générer sitemap.xml et robots.txt": "",
|
||||
"Générer une capture Open Graph": "",
|
||||
"Gérer les catégories": "",
|
||||
"Gérer les commentaires": "",
|
||||
"Gérer les données": "",
|
||||
"Hauteur": "",
|
||||
"Hauteur de l'image": "",
|
||||
"Hauteur de l'image sélectionnée": "",
|
||||
"Hauteur maximale": "",
|
||||
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "",
|
||||
"Icône": "",
|
||||
"Icône avec bulle de texte": "",
|
||||
"Icône haut de page, couleur arrière-plan": "",
|
||||
"Identifiant": "",
|
||||
"Identifiant (sans espace ni majuscule)": "",
|
||||
"Identité": "",
|
||||
"Identité de la fonte": "",
|
||||
"Identité du site": "",
|
||||
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "",
|
||||
"Image": "",
|
||||
"Image étirée (100% 100%)": "",
|
||||
"Important": "",
|
||||
"Importante": "",
|
||||
"Importation d'utilisateurs": "",
|
||||
"Importation de fichier plat CSV": "",
|
||||
"Importation effectuée": "",
|
||||
"Importer": "",
|
||||
"Importer dans": "",
|
||||
"Importer des utilisateurs en masse": "",
|
||||
"Impossible d'ouvrir l'archive": "",
|
||||
"Impossible de modifier votre propre groupe.": "",
|
||||
"Impossible de soumettre le formulaire, car il contient des erreurs": "",
|
||||
"Impossible de supprimer une page contenant des pages enfants": "",
|
||||
"Impossible de supprimer votre propre compte": "",
|
||||
"Inclure le contenu du gestionnaire de fichiers": "",
|
||||
"Incorrect": "",
|
||||
"Informations": "",
|
||||
"Instagram": "",
|
||||
"Installation terminée": "",
|
||||
"Installer": "",
|
||||
"Installer depuis le catalogue en ligne": "",
|
||||
"Installer depuis une archive": "",
|
||||
"Installer les données d'un module": "",
|
||||
"Installer ou mettre à jour un module téléchargé": "",
|
||||
"Installer un module": "",
|
||||
"Installer un thème archivé (site ou administration)": "",
|
||||
"Instructions JS ou jquery spécifiques à la page.": "",
|
||||
"Interface": "",
|
||||
"Jeton invalide": "",
|
||||
"Journal réinitialisé avec succès": "",
|
||||
"Journalisation": "",
|
||||
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "",
|
||||
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "",
|
||||
"La carte du site a été mise à jour": "",
|
||||
"La copie de sauvegarde du fichier htaccess n'a pas été restaurée !": "",
|
||||
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "",
|
||||
"La page %s est ouverte par l'utilisateur %s": "",
|
||||
"La page demandée n'existe pas ou est introuvable (erreur 404)": "",
|
||||
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "",
|
||||
"La première page que vos visiteurs verront.": "",
|
||||
"La règlementation française impose un anonymat de niveau 2": "",
|
||||
"La réécriture d'URL n'a pas été restaurée !": "",
|
||||
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "",
|
||||
"La suppression a échoué": "",
|
||||
"La version installée est plus récente": "",
|
||||
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "",
|
||||
"Langue de l'administration": "",
|
||||
"Langue du site par défaut": "",
|
||||
"Langue par défaut": "",
|
||||
"Langues": "",
|
||||
"Langues disponibles": "",
|
||||
"Langues installées": "",
|
||||
"Largeur": "",
|
||||
"Largeur de l'image": "",
|
||||
"Largeur du site": "",
|
||||
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "",
|
||||
"Le curseur horizontal règle le niveau de transparence.": "",
|
||||
"Le fuseau horaire est utile au bon référencement": "",
|
||||
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "",
|
||||
"Le menu horizontal intégral": "",
|
||||
"Le module %s a été %s": "",
|
||||
"Le module %s de la page %s a été supprimé": "",
|
||||
"Le module %s est désinstallé, il reste peut-être des données dans %s": "",
|
||||
"Le sous-menu de la page parente": "",
|
||||
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "",
|
||||
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "",
|
||||
"Les langues sélectionnées sont identiques": "",
|
||||
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "",
|
||||
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "",
|
||||
"Les tailles des polices de la bannière, de menu et de pied de page sont proportionnelles à cette taille.": "",
|
||||
"Lettres": "",
|
||||
"Libre": "",
|
||||
"Licence :": "",
|
||||
"Lien de connexion": "",
|
||||
"Lien page des mentions légales.": "",
|
||||
"Liens": "",
|
||||
"Limitation des tentatives": "",
|
||||
"Limitée au site": "",
|
||||
"Linkedin": "",
|
||||
"Liste noire": "",
|
||||
"Liste noire réinitialisée avec succès": "",
|
||||
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "",
|
||||
"Léger": "",
|
||||
"Légère": "",
|
||||
"Maigre": "",
|
||||
"Maintenance": "",
|
||||
"Majuscule à chaque mot": "",
|
||||
"Majuscules": "",
|
||||
"Marges verticales": "",
|
||||
"Masquer la bannière en écran réduit": "",
|
||||
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "",
|
||||
"Masquer les pages enfants dans le menu horizontal": "",
|
||||
"Membre": "",
|
||||
"Membre avec droit de partage": "",
|
||||
"Membre simple": "",
|
||||
"Mentions légales": "",
|
||||
"Menu": "",
|
||||
"Menu accessoire": "",
|
||||
"Menu burger dans écran réduit": "",
|
||||
"Menu standard": "",
|
||||
"Message d'acceptation des Cookies": "",
|
||||
"Message de consentement aux cookies": "",
|
||||
"Mettre à jour": "",
|
||||
"Mettre à jour le module orphelin": "",
|
||||
"Minuscules": "",
|
||||
"Mise en forme des titres": "",
|
||||
"Mise en forme du texte": "",
|
||||
"Mise en forme du titre": "",
|
||||
"Mise en page": "",
|
||||
"Mise à jour": "",
|
||||
"Mise à jour automatisée": "",
|
||||
"Mise à jour terminée avec succès.": "",
|
||||
"Modifications enregistrées": "",
|
||||
"Module": "",
|
||||
"Module de la page": "",
|
||||
"Modules": "",
|
||||
"Modules configurés": "",
|
||||
"Modules installés": "",
|
||||
"Modules orphelins": "",
|
||||
"Mot de passe": "",
|
||||
"Mot de passe oublié": "",
|
||||
"Mot de passe perdu": "",
|
||||
"Motorisé par": "",
|
||||
"Moyen": "",
|
||||
"Moyenne": "",
|
||||
"Moyenne (200%)": "",
|
||||
"Moyenne (200px)": "",
|
||||
"Méta-description": "",
|
||||
"Méta-titre": "",
|
||||
"Ne pas afficher": "",
|
||||
"Ne pas charger l'exemple de site (utilisateurs avancés)": "",
|
||||
"Ne pas répéter": "",
|
||||
"Ne pas saisir les balises": "",
|
||||
"News": "",
|
||||
"Niveau 1 (192.168.12.x)": "",
|
||||
"Niveau 2 (192.168.x.x)": "",
|
||||
"Niveau 3 (192.x.x.x)": "",
|
||||
"Nom": "",
|
||||
"Nom Prénom": "",
|
||||
"Nom du profil": "",
|
||||
"Nom utilisateur": "",
|
||||
"Non": "",
|
||||
"Non tronquée": "",
|
||||
"Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.": "",
|
||||
"Nouveau contenu localisé": "",
|
||||
"Nouveau mot de passe": "",
|
||||
"Nouveau mot de passe enregistré": "",
|
||||
"Nouvel utilisateur": "",
|
||||
"Nouvelle page créée": "",
|
||||
"Nouvelle page ou barre latérale": "",
|
||||
"Obligatoire": "",
|
||||
"Ombre": "",
|
||||
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "",
|
||||
"Option recommandée pour sécuriser la connexion. S'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.": "",
|
||||
"Options": "",
|
||||
"Options avancées": "",
|
||||
"Origine": "",
|
||||
"Oui": "",
|
||||
"Page": "",
|
||||
"Page 2/3 - barre 1/3": "",
|
||||
"Page 3/4 - barre 1/4": "",
|
||||
"Page associée": "",
|
||||
"Page de recherche": "",
|
||||
"Page dupliquée": "",
|
||||
"Page et module dupliqués": "",
|
||||
"Page inexistante, erreur 404": "",
|
||||
"Page non cliquable": "",
|
||||
"Page parent": "",
|
||||
"Page standard": "",
|
||||
"Page supprimée": "",
|
||||
"Pages dans le menu": "",
|
||||
"Pages du site": "",
|
||||
"Pages et les modules de": "",
|
||||
"Pages orphelines": "",
|
||||
"Papier peint": "",
|
||||
"Par défaut le menu est affiché APRES le contenu de la page. Pour le positionner à un emplacement précis, insérez [MENU] dans le contenu de la page.": "",
|
||||
"Paramètres": "",
|
||||
"Paramètres de la localisation": "",
|
||||
"Paramètres de la sauvegarde": "",
|
||||
"Paramètres du profil": "",
|
||||
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "",
|
||||
"Pas de marge au-dessus et en dessous du site": "",
|
||||
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "",
|
||||
"Permission": "",
|
||||
"Permission et référencement": "",
|
||||
"Permissions": "",
|
||||
"Permissions sur les dossiers": "",
|
||||
"Permissions sur les fichiers": "",
|
||||
"Permissions sur les pages": "",
|
||||
"Petite": "",
|
||||
"Petite (150px)": "",
|
||||
"Petite (180%)": "",
|
||||
"Pied de page": "",
|
||||
"Pinterest": "",
|
||||
"Plan du site": "",
|
||||
"Police des titres": "",
|
||||
"Police du texte": "",
|
||||
"Port SMTP": "",
|
||||
"Port du proxy": "",
|
||||
"Position": "",
|
||||
"Position du module": "",
|
||||
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "",
|
||||
"Presse Papier": "",
|
||||
"Presse papier": "",
|
||||
"Profils des groupes": "",
|
||||
"Proportionnelle à la taille définie dans le site.": "",
|
||||
"Prénom": "",
|
||||
"Prénom Nom": "",
|
||||
"Préparation de la mise à jour": "",
|
||||
"Préserver le fichier htaccess racine": "",
|
||||
"Préserver les comptes des utilisateurs déjà installés": "",
|
||||
"Prévenir l'utilisateur par mail": "",
|
||||
"Prévisualiser": "",
|
||||
"Pseudo": "",
|
||||
"Rang 9 > rang 1. Le profil de rang 1 n'est pas modifiable.": "",
|
||||
"Ratio": "",
|
||||
"Ratio :": "",
|
||||
"Recherche": "",
|
||||
"Recherche dans le site": "",
|
||||
"Rechercher": "",
|
||||
"Rechercher une mise à jour en ligne": "",
|
||||
"Redirection": "",
|
||||
"Redirection vers la connexion": "",
|
||||
"Renommer": "",
|
||||
"Renseignez les champs ci-dessous pour finaliser l'installation.": "",
|
||||
"Responsive (contain)": "",
|
||||
"Responsive (cover)": "",
|
||||
"Restauration des bases de données absentes": "",
|
||||
"Restauration effectuée avec succès": "",
|
||||
"Restaurer": "",
|
||||
"Restaurer les données du site": "",
|
||||
"Rester connecté sur ce navigateur": "",
|
||||
"Retour": "",
|
||||
"Rien à importer, erreur de format ou fichier incorrect": "",
|
||||
"Rédacteur": "",
|
||||
"Référencement": "",
|
||||
"Réinitialisation du mot de passe": "",
|
||||
"Réinitialiser avec le thème par défaut": "",
|
||||
"Réinitialiser la feuille de style": "",
|
||||
"Réinitialiser la liste": "",
|
||||
"Réinitialiser le journal": "",
|
||||
"Réinstaller": "",
|
||||
"Répétition": "",
|
||||
"Réseau": "",
|
||||
"Réseaux sociaux": "",
|
||||
"S'ouvre dans un nouvel onglet": "",
|
||||
"SMTP": "",
|
||||
"SMTP personnalisé": "",
|
||||
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "",
|
||||
"Saisissez le Titre de gestion des cookies.": "",
|
||||
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "",
|
||||
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "",
|
||||
"Saisissez votre ID : https://pinterest.com/[ID].": "",
|
||||
"Saisissez votre ID : https://twitter.com/[ID].": "",
|
||||
"Saisissez votre ID : https://www.facebook.com/[ID].": "",
|
||||
"Saisissez votre ID : https://www.instagram.com/[ID].": "",
|
||||
"Saisissez votre ID Github : https://github.com/[ID].": "",
|
||||
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "",
|
||||
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "",
|
||||
"Sauvegarde": "",
|
||||
"Sauvegarde automatique quotidienne du site": "",
|
||||
"Sauvegarde du thème dans le": "",
|
||||
"Sauvegarde générée avec succès": "",
|
||||
"Sauvegarder": "",
|
||||
"Sauvegarder et télécharger le module": "",
|
||||
"Sauvegarder le module dans le gestionnaire de fichiers": "",
|
||||
"Sauvegarder les données du module dans le gestionnaire de fichiers": "",
|
||||
"Sauvegarder les données du site": "",
|
||||
"Script dans body": "",
|
||||
"Script dans head": "",
|
||||
"Scripts externes": "",
|
||||
"Se déconnecter": "",
|
||||
"Service en ligne inaccessible": "",
|
||||
"Seul un administrateur peut se connecter lors d'une maintenance": "",
|
||||
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "",
|
||||
"Signature": "",
|
||||
"Site": "",
|
||||
"Site en maintenance": "",
|
||||
"Size": "",
|
||||
"Source": "",
|
||||
"Standard": "",
|
||||
"Style": "",
|
||||
"Suppression interdite": "",
|
||||
"Suppression interdite, page active dans la configuration de la langue du site": "",
|
||||
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "",
|
||||
"Supprimer": "",
|
||||
"Supprimer la page": "",
|
||||
"Supprimer le module": "",
|
||||
"Supprimer toutes les sauvegardes automatiques ?": "",
|
||||
"Sur l'axe horizontal": "",
|
||||
"Sur l'axe vertical": "",
|
||||
"Sur les deux axes": "",
|
||||
"Sécurité": "",
|
||||
"Sécurité de la connexion": "",
|
||||
"Sécurité désactivée": "",
|
||||
"Sélectionner un fichier": "",
|
||||
"Sélectionnez au moins un contenu à afficher": "",
|
||||
"Sélectionnez la langue à copier vers une langue cible": "",
|
||||
"Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "",
|
||||
"Sélectionnez une image ou une icône de petite dimension": "",
|
||||
"Sélectionnez une langue": "",
|
||||
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "",
|
||||
"Sélectionnez une page pour activer": "",
|
||||
"Séparateur": "",
|
||||
"Taille": "",
|
||||
"Text": "",
|
||||
"Texte": "",
|
||||
"Thème": "",
|
||||
"Thème de l'administration": "",
|
||||
"Thème du site": "",
|
||||
"Thème importé": "",
|
||||
"Thèmes": "",
|
||||
"Titre": "",
|
||||
"Titre court": "",
|
||||
"Titre masqué": "",
|
||||
"Titre masqué dans la page": "",
|
||||
"Titres": "",
|
||||
"Tous les dossiers": "",
|
||||
"Tous les droits d'édition des contenus": "",
|
||||
"Tout Effacer": "",
|
||||
"Traduction supprimée": "",
|
||||
"Très grande": "",
|
||||
"Très grande (240%)": "",
|
||||
"Très grande (400px)": "",
|
||||
"Très important": "",
|
||||
"Très importante": "",
|
||||
"Très léger": "",
|
||||
"Très légère": "",
|
||||
"Très petite": "",
|
||||
"Très petite (100px) ": "",
|
||||
"Très petite (160%)": "",
|
||||
"Twitter": "",
|
||||
"Type de captcha": "",
|
||||
"Type de proxy": "",
|
||||
"Téléchargement et validation de l'archive": "",
|
||||
"Télécharger": "",
|
||||
"Télécharger la liste": "",
|
||||
"Télécharger le journal": "",
|
||||
"Télécharger le module dans le gestionnaire de fichiers": "",
|
||||
"Téléverser": "",
|
||||
"URL incorrecte": "",
|
||||
"Un mail a été envoyé pour confirmer la réinitialisation": "",
|
||||
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "",
|
||||
"Une erreur est survenue lors de l'étape :": "",
|
||||
"Url du fichier de fonte": "",
|
||||
"Utilisateur inexistant": "",
|
||||
"Utilisateur supprimé": "",
|
||||
"Utilisateurs": "",
|
||||
"Valider": "",
|
||||
"Version": "",
|
||||
"Version n°": "",
|
||||
"Vider dossier sauvegardes auto": "",
|
||||
"Visiteur": "",
|
||||
"Vous n'êtes pas autorisé à consulter cette page (erreur 403)": "",
|
||||
"Youtube": "",
|
||||
"ZwiiCMS - Installation": "",
|
||||
"actualisé": "",
|
||||
"favicon.ico": "",
|
||||
"faviconDark.ico": "",
|
||||
"gestionnaire de fichiers": "",
|
||||
"installé": "",
|
||||
"jour": "",
|
||||
"jours": "",
|
||||
"sauvegardé avec succès": "",
|
||||
"vers": "",
|
||||
"À droite": "",
|
||||
"À gauche": "",
|
||||
"À l'emplacement du mot clé [MODULE] dans la page": "",
|
||||
"Échec de l'écriture, vérifiez les permissions": "",
|
||||
"Échecs": "",
|
||||
"Éditer": "",
|
||||
"Éditer la page": "",
|
||||
"Éditer les dialogues": "",
|
||||
"Éditer une catégorie": "",
|
||||
"Éditeur": "",
|
||||
"Éditeur CSS": "",
|
||||
"Éditeur JS": "",
|
||||
"Éditeur de script %s": "",
|
||||
"Éditeur de script dans Body": "",
|
||||
"Éditeur de script dans Head": "",
|
||||
"Éditeur simple": "",
|
||||
"Édition des pages": "",
|
||||
"Édition du profil %s": "",
|
||||
"Éléments": "",
|
||||
"Étendu sur la page": "",
|
||||
"Étiquettes des pages spéciales": "",
|
||||
"Dimensions minimales": "",
|
||||
"Taille maximale du fichier": "",
|
||||
"5 Mo pour les images JPEG": "",
|
||||
"1 Mo pour les images PNG": "",
|
||||
"Poids": "",
|
||||
"Supprimer ce profil ?": "",
|
||||
"Masqué": "",
|
||||
"Haut de page": "",
|
||||
"Bas de page": "",
|
||||
"Petit triangle": "",
|
||||
"Grand triangle": "",
|
||||
"Flèche": "",
|
||||
"Modèle": "",
|
||||
"Bouton de navigation droit": "",
|
||||
"Bouton de navigation gauche": "",
|
||||
"Groupes / Profils": "",
|
||||
"Prénom commence par": "",
|
||||
"Nom commence par": "",
|
||||
"Impossible de réinitialiser le mot de passe de ce compte !": ""
|
||||
}
|
18
core/module/install/view/index/index.css
Executable file
18
core/module/install/view/index/index.css
Executable file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
@ -1,36 +0,0 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Affichage de l'id en simulant FILTER_ID
|
||||
*/
|
||||
$("#installId").on("change keydown keyup", function(event) {
|
||||
var userId = $(this).val();
|
||||
if(
|
||||
event.keyCode !== 8 // BACKSPACE
|
||||
&& event.keyCode !== 37 // LEFT
|
||||
&& event.keyCode !== 39 // RIGHT
|
||||
&& event.keyCode !== 46 // DELETE
|
||||
&& window.getSelection().toString() !== userId // Texte sélectionné
|
||||
) {
|
||||
var searchReplace = {
|
||||
"á": "a", "à": "a", "â": "a", "ä": "a", "ã": "a", "å": "a", "ç": "c", "é": "e", "è": "e", "ê": "e", "ë": "e", "í": "i", "ì": "i", "î": "i", "ï": "i", "ñ": "n", "ó": "o", "ò": "o", "ô": "o", "ö": "o", "õ": "o", "ú": "u", "ù": "u", "û": "u", "ü": "u", "ý": "y", "ÿ": "y",
|
||||
"Á": "A", "À": "A", "Â": "A", "Ä": "A", "Ã": "A", "Å": "A", "Ç": "C", "É": "E", "È": "E", "Ê": "E", "Ë": "E", "Í": "I", "Ì": "I", "Î": "I", "Ï": "I", "Ñ": "N", "Ó": "O", "Ò": "O", "Ô": "O", "Ö": "O", "Õ": "O", "Ú": "U", "Ù": "U", "Û": "U", "Ü": "U", "Ý": "Y", "Ÿ": "Y",
|
||||
"'": "-", "\"": "-", " ": "-"
|
||||
};
|
||||
userId = userId.replace(/[áàâäãåçéèêëíìîïñóòôöõúùûüýÿ'" ]/ig, function(match) {
|
||||
return searchReplace[match];
|
||||
});
|
||||
userId = userId.replace(/[^a-z0-9-]/ig, "");
|
||||
$(this).val(userId);
|
||||
}
|
||||
});
|
58
core/module/install/view/index/index.php
Executable file → Normal file
58
core/module/install/view/index/index.php
Executable file → Normal file
@ -1,54 +1,20 @@
|
||||
<p>Veuillez saisir les champs ci-dessous afin de terminer l'installation.</p>
|
||||
<?php echo template::formOpen('installForm'); ?>
|
||||
<?php echo template::text('installId', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Identifiant'
|
||||
]); ?>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::password('installPassword', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Mot de passe'
|
||||
<h3>
|
||||
<?php echo helper::translate('Dans quelle langue utiliserez-vous Zwii ?'); ?>
|
||||
</h3>
|
||||
<div class="row">
|
||||
<div class="col6 offset3">
|
||||
<?php echo template::select('installLanguage', $module::$i18nFiles, [
|
||||
'label' => 'Langues installées',
|
||||
'selected' => array_key_exists ('fr_FR', $module::$i18nFiles) ? 'fr_FR': reset($module::$i18nFiles),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::password('installConfirmPassword', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Confirmation'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::mail('installMail', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Adresse mail'
|
||||
]); ?>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('installFirstname', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Prénom'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('installLastname', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Nom'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::checkbox('installDefaultData',true , 'Charger un exemple de site', [
|
||||
'checked' => true
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3 offset9">
|
||||
<?php echo template::submit('installSubmit', [
|
||||
'value' => 'Installer'
|
||||
'value' => 'Suivant'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
22
core/module/install/view/postinstall/postinstall.css
Normal file
22
core/module/install/view/postinstall/postinstall.css
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
13
core/module/install/view/postinstall/postinstall.js.php
Normal file
13
core/module/install/view/postinstall/postinstall.js.php
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
$("#installId").on("change keydown keyup",(function(event){var userId=$(this).val();if(8!==event.keyCode&&37!==event.keyCode&&39!==event.keyCode&&46!==event.keyCode&&window.getSelection().toString()!==userId){var searchReplace={"á":"a","à":"a","â":"a","ä":"a","ã":"a","å":"a","ç":"c","é":"e","è":"e","ê":"e","ë":"e","í":"i","ì":"i","î":"i","ï":"i","ñ":"n","ó":"o","ò":"o","ô":"o","ö":"o","õ":"o","ú":"u","ù":"u","û":"u","ü":"u","ý":"y","ÿ":"y","Á":"A","À":"A","Â":"A","Ä":"A","Ã":"A","Å":"A","Ç":"C","É":"E","È":"E","Ê":"E","Ë":"E","Í":"I","Ì":"I","Î":"I","Ï":"I","Ñ":"N","Ó":"O","Ò":"O","Ô":"O","Ö":"O","Õ":"O","Ú":"U","Ù":"U","Û":"U","Ü":"U","Ý":"Y","Ÿ":"Y","'":"-",'"':"-"," ":"-"};userId=(userId=userId.replace(/[áàâäãåçéèêëíìîïñóòôöõúùûüýÿ'" ]/gi,(function(match){return searchReplace[match]}))).replace(/[^a-z0-9-]/gi,""),$(this).val(userId)}}));
|
119
core/module/install/view/postinstall/postinstall.php
Normal file
119
core/module/install/view/postinstall/postinstall.php
Normal file
@ -0,0 +1,119 @@
|
||||
<p>
|
||||
<?php echo helper::translate('Renseignez les champs ci-dessous pour finaliser l\'installation.'); ?>
|
||||
</p>
|
||||
<?php echo template::formOpen('installForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<details open>
|
||||
<summary>
|
||||
<span class="title">
|
||||
<?php echo helper::translate('Compte administrateur'); ?>
|
||||
</span>
|
||||
</summary>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('installFirstname', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Prénom'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('installLastname', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Nom'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('installId', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Identifiant'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::mail('installMail', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Adresse électronique'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::password('installPassword', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Mot de passe'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::password('installConfirmPassword', [
|
||||
'autocomplete' => 'off',
|
||||
'label' => 'Confirmation'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<details close>
|
||||
<summary>
|
||||
<span class="title">
|
||||
<?php echo helper::translate('Options avancées'); ?>
|
||||
</span>
|
||||
</summary>
|
||||
<?php if ($_SESSION['ZWII_UI'] === 'fr_FR'): ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::checkbox('installDefaultData', true, 'Ne pas charger l\'exemple de site (utilisateurs avancés)', [
|
||||
'checked' => false
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::select('installProxyType', $module::$proxyType, [
|
||||
'label' => 'Type de proxy'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('installProxyUrl', [
|
||||
'label' => 'Adresse du proxy',
|
||||
'placeholder' => 'cache.proxy.fr'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::text('installProxyPort', [
|
||||
'label' => 'Port du proxy',
|
||||
'placeholder' => '6060'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::hidden('installLanguage', [
|
||||
'value' => $this->getUrl(2)
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<div class="row">
|
||||
<div class="col2">
|
||||
<?php echo template::button('installPrevious', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl(true) . '?install',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 offset7">
|
||||
<?php echo template::submit('installSubmit', [
|
||||
'value' => 'Installer'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
18
core/module/install/view/update/update.css
Executable file
18
core/module/install/view/update/update.css
Executable file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
123
core/module/install/view/update/update.js.php
Executable file → Normal file
123
core/module/install/view/update/update.js.php
Executable file → Normal file
@ -1,70 +1,95 @@
|
||||
/**
|
||||
* Exécution des différentes étapes de mise à jour
|
||||
*/
|
||||
function step(i, data) {
|
||||
// Affiche le texte de progression
|
||||
var errors = [
|
||||
"<?php echo helper::translate('Préparation de la mise à jour'); ?>",
|
||||
"<?php echo helper::translate('Téléchargement et validation de l\'archive'); ?>",
|
||||
"<?php echo helper::translate('Installation'); ?>",
|
||||
"<?php echo helper::translate('Configuration'); ?>"
|
||||
];
|
||||
$(".installUpdateProgressText").hide();
|
||||
$(".installUpdateProgressText[data-id=" + i + "]").show();
|
||||
// Requête ajax
|
||||
|
||||
$("body").css("cursor", "wait");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "<?php echo helper::baseUrl(false); ?>?install/steps", // Ignore la réécriture d'URL
|
||||
url: "<?php echo helper::baseUrl(false); ?>?install/steps",
|
||||
data: {
|
||||
step: i,
|
||||
data: data
|
||||
},
|
||||
// Succès de la requête
|
||||
success: function(result) {
|
||||
setTimeout(function() {
|
||||
// Succès
|
||||
if(result.success === true) {
|
||||
// Fin de la mise à jour
|
||||
if(i === 4) {
|
||||
// Affiche le message de succès
|
||||
success: function (result) {
|
||||
setTimeout(function () {
|
||||
if (4 === i) {
|
||||
$("#installUpdateSuccess").show();
|
||||
// Déverrouille le bouton "Terminer"
|
||||
$("body").css("cursor", "default");
|
||||
$("#installUpdateEnd").removeClass("disabled");
|
||||
// Cache le texte de progression
|
||||
$("#installUpdateProgress").hide();
|
||||
}
|
||||
// Prochaine étape
|
||||
else {
|
||||
} else {
|
||||
step(i + 1, result.data);
|
||||
}
|
||||
}
|
||||
// Échec
|
||||
else {
|
||||
// Affiche le message d'erreur
|
||||
$("#installUpdateErrorStep").text(i);
|
||||
$("#installUpdateError").show();
|
||||
// Déverrouille le bouton "Terminer"
|
||||
$("#installUpdateEnd").removeClass("disabled");
|
||||
// Cache le texte de progression
|
||||
$("#installUpdateProgress").hide();
|
||||
// Affiche le résultat dans la console
|
||||
console.error(result);
|
||||
}
|
||||
}, 2000);
|
||||
},
|
||||
// Échec de la requête
|
||||
error: function(xhr) {
|
||||
// Affiche le message d'erreur
|
||||
$("#installUpdateErrorStep").text(0);
|
||||
$("#installUpdateError").show();
|
||||
// Déverrouille le bouton "Terminer"
|
||||
$("#installUpdateEnd").removeClass("disabled");
|
||||
// Cache le texte de progression
|
||||
$("#installUpdateProgress").hide();
|
||||
// Affiche l'erreur dans la console
|
||||
console.error(xhr);
|
||||
error: function (xhr) {
|
||||
console.log(i);
|
||||
console.log(xhr.responseText);
|
||||
console.log(errors);
|
||||
|
||||
// Vérification du code d'erreur HTTP pour gérer la déconnexion
|
||||
if (xhr.status === 401 || xhr.status === 403) {
|
||||
alert("Votre session a expiré. Veuillez vous reconnecter.");
|
||||
window.location.href = "?user/login"; // Redirige vers la page de connexion
|
||||
} else {
|
||||
// Appel de la fonction de gestion d'erreur
|
||||
showError(i, xhr.responseText, errors);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(window).on("load", step(1, null));
|
||||
|
||||
/**
|
||||
* Paramètres par défaut au chargement
|
||||
*/
|
||||
$( document ).ready(function() {
|
||||
$("section").addClass("updateForm");
|
||||
function showError(step, message, errors) {
|
||||
$("body").css("cursor", "default");
|
||||
$("#installUpdateErrorStep").text(errors[step] + " (étape n°" + step + ")");
|
||||
$("#installUpdateError").show();
|
||||
$("#installUpdateEnd").removeClass("disabled");
|
||||
$("#installUpdateProgress").hide();
|
||||
|
||||
// Vérifier si l'accolade ouvrante est trouvée et qu'elle n'est pas en première position
|
||||
if (typeof message !== 'object') {
|
||||
|
||||
// Trouver la position du premier "{" pour repérer le début du tableau
|
||||
const startOfArray = message.indexOf('{');
|
||||
|
||||
if (startOfArray !== -1 && startOfArray > 0) {
|
||||
// Extraire le message du warning jusqu'au début du tableau
|
||||
const warningMessage = message.substring(0, startOfArray).trim();
|
||||
|
||||
// Extraire le tableau JSON entre les accolades
|
||||
const jsonString = message.substring(startOfArray);
|
||||
|
||||
try {
|
||||
const jsonData = JSON.parse(jsonString);
|
||||
|
||||
// Afficher les résultats si le parsing JSON est réussi
|
||||
if (jsonData) {
|
||||
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
|
||||
jsonData.data.replace(/^"(.*)"$/, '$1') +
|
||||
"<br>" +
|
||||
warningMessage.replace(/<[^p].*?>/g, ""));
|
||||
}
|
||||
} catch (e) {
|
||||
// Afficher un message générique en cas d'erreur de parsing
|
||||
console.error("Erreur de parsing JSON : ", e);
|
||||
$("#installUpdateErrorMessage").html("Une erreur inattendue est survenue lors du traitement des détails de l'erreur.");
|
||||
}
|
||||
} else {
|
||||
// Si pas de JSON détecté, afficher le message brut
|
||||
$("#installUpdateErrorMessage").html("Message d'erreur : " + message);
|
||||
}
|
||||
} else {
|
||||
$("#installUpdateErrorMessage").html(message);
|
||||
}
|
||||
}
|
||||
|
||||
$(window).on("load", function () {
|
||||
step(1, null);
|
||||
});
|
57
core/module/install/view/update/update.php
Executable file → Normal file
57
core/module/install/view/update/update.php
Executable file → Normal file
@ -1,24 +1,45 @@
|
||||
<p><strong>Mise à jour de Zwii <?php echo self::ZWII_VERSION; ?> vers Zwii <?php echo $module::$newVersion; ?>.</strong></p>
|
||||
<p>Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.</p>
|
||||
<div class="row">
|
||||
<div id="updateContainer">
|
||||
<p><strong>
|
||||
<?php echo helper::translate('Version'); ?>
|
||||
|
||||
<?php echo self::ZWII_VERSION; ?>
|
||||
<?php echo helper::translate('vers'); ?>
|
||||
|
||||
<?php echo $module::$newVersion; ?>
|
||||
</strong></p>
|
||||
<p>
|
||||
<?php echo helper::translate('Afin d\'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l\'opération.'); ?>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col9 verticalAlignMiddle">
|
||||
<div id="installUpdateProgress">
|
||||
<?php echo template::ico('spin', '', true); ?>
|
||||
<span class="installUpdateProgressText" data-id="1">1/4 : Préparation...</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="2">2/4 : Téléchargement...</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="3">3/4 : Installation...</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="4">4/4 : Configuration...</span>
|
||||
<?php echo template::ico('spin', ['animate' => true]); ?>
|
||||
<span class="installUpdateProgressText" data-id="1">
|
||||
<?php echo helper::translate('1/4 : Préparation...'); ?>
|
||||
</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="2">
|
||||
<?php echo helper::translate('2/4 : Téléchargement...'); ?>
|
||||
</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="3">
|
||||
<?php echo helper::translate('3/4 : Installation...'); ?>
|
||||
</span>
|
||||
<span class="installUpdateProgressText displayNone" data-id="4">
|
||||
<?php echo helper::translate('4/4 : Configuration...'); ?>
|
||||
</span>
|
||||
</div>
|
||||
<div id="installUpdateError" class="colorRed displayNone">
|
||||
<?php echo template::ico('cancel', ''); ?>
|
||||
Une erreur est survenue lors de l'étape <span id="installUpdateErrorStep"></span>.
|
||||
<div id="installUpdateError" class="message colorRed displayNone">
|
||||
<?php echo template::ico('cancel'); ?>
|
||||
<strong>
|
||||
<?php echo helper::translate('Une erreur est survenue lors de l\'étape :') . '<br>'; ?>
|
||||
<span id="installUpdateErrorStep"> </span>.
|
||||
</strong>
|
||||
</div>
|
||||
<div id="installUpdateSuccess" class="colorGreen displayNone">
|
||||
<?php echo template::ico('check', ''); ?>
|
||||
Mise à jour terminée avec succès.
|
||||
<div id="installUpdateSuccess" class="message colorGreen displayNone">
|
||||
<?php echo template::ico('check'); ?>
|
||||
<?php echo helper::translate('Mise à jour terminée avec succès.'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col3 verticalAlignMiddle">
|
||||
<div class="col3 verticalAlignTop">
|
||||
<?php echo template::button('installUpdateEnd', [
|
||||
'value' => 'Terminer',
|
||||
'href' => helper::baseUrl() . 'config',
|
||||
@ -26,4 +47,10 @@
|
||||
'class' => 'disabled'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<p><em><span class="colorRed" id="installUpdateErrorMessage"></span></em></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
712
core/module/language/language.php
Normal file
712
core/module/language/language.php
Normal file
@ -0,0 +1,712 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class language extends common
|
||||
{
|
||||
|
||||
// URL langues de l'UI en ligne
|
||||
const ZWII_UI_URL = 'https://forge.chapril.org/ZwiiCMS-Team/zwiicms-translations/raw/branch/master/v13/';
|
||||
|
||||
public static $actions = [
|
||||
'index' => self::GROUP_ADMIN,
|
||||
'copy' => self::GROUP_ADMIN,
|
||||
'add' => self::GROUP_ADMIN,
|
||||
// Ajouter une langue de contenu
|
||||
'edit' => self::GROUP_ADMIN,
|
||||
// Éditer une langue de l'UI
|
||||
'locale' => self::GROUP_ADMIN,
|
||||
// Éditer une langue de contenu
|
||||
'delete' => self::GROUP_ADMIN,
|
||||
// Effacer une langue de contenu ou de l'interface
|
||||
'content' => self::GROUP_VISITOR,
|
||||
'update' => self::GROUP_ADMIN,
|
||||
'default' => self::GROUP_ADMIN
|
||||
];
|
||||
|
||||
const PAGINATION = '20';
|
||||
|
||||
// Language contents
|
||||
public static $translateOptions = [];
|
||||
|
||||
// Page pour la configuration dans la langue
|
||||
public static $pagesList = [];
|
||||
public static $orphansList = [];
|
||||
public static $pages = '';
|
||||
|
||||
// Liste des langues installées
|
||||
public static $languagesUiInstalled = [];
|
||||
public static $languagesInstalled = [];
|
||||
public static $languagesStore = [];
|
||||
public static $dialogues = [];
|
||||
|
||||
// Liste des langues cibles
|
||||
public static $languagesTarget = [];
|
||||
|
||||
// Activation du bouton de copie
|
||||
public static $siteCopy = true;
|
||||
|
||||
// Localisation en cours d'édition
|
||||
public static $locales = [];
|
||||
|
||||
//UI
|
||||
// Fichiers des langues de l'interface
|
||||
public static $i18nFiles = [];
|
||||
|
||||
/**
|
||||
* Met à jour les traduction du site depuis le store
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
$lang = $this->getUrl(2);
|
||||
// Action interdite ou URl avec le code langue incorrecte
|
||||
if (
|
||||
array_key_exists($lang, self::$languages) === false
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => false,
|
||||
'notification' => helper::translate('Action interdite')
|
||||
]);
|
||||
}
|
||||
|
||||
// Télécharger le descripteur en ligne
|
||||
$languageData = json_decode(helper::getUrlContents(self::ZWII_UI_URL . $lang . '.json'), true);
|
||||
$descripteur = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
|
||||
$success = false;
|
||||
if (
|
||||
is_array($languageData) &&
|
||||
is_array($descripteur['language'][$lang])
|
||||
) {
|
||||
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
|
||||
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $languageData);
|
||||
$success = is_int($success) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'notification' => $success ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs',
|
||||
'state' => $success
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration avancée des langues
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
// Initialisation
|
||||
$success = false;
|
||||
$copyFrom = $this->getInput('translateFormCopySource');
|
||||
$toCreate = $this->getInput('translateFormCopyTarget');
|
||||
if ($copyFrom !== $toCreate) {
|
||||
// Création du dossier
|
||||
if (is_dir(self::DATA_DIR . $toCreate) === false) { // Si le dossier est déjà créé
|
||||
$success = mkdir(self::DATA_DIR . $toCreate, 0755);
|
||||
$success = mkdir(self::DATA_DIR . $toCreate . '/content', 0755);
|
||||
} else {
|
||||
$success = true;
|
||||
}
|
||||
// Copier les données par défaut
|
||||
$success = (copy(self::DATA_DIR . $copyFrom . '/locale.json', self::DATA_DIR . $toCreate . '/locale.json') === true && $success === true) ? true : false;
|
||||
$success = (copy(self::DATA_DIR . $copyFrom . '/module.json', self::DATA_DIR . $toCreate . '/module.json') === true && $success === true) ? true : false;
|
||||
$success = (copy(self::DATA_DIR . $copyFrom . '/page.json', self::DATA_DIR . $toCreate . '/page.json') === true && $success === true) ? true : false;
|
||||
$success = ($this->copyDir(self::DATA_DIR . $copyFrom . '/content', self::DATA_DIR . $toCreate . '/content') === true && $success === true) ? true : false;
|
||||
// Enregistrer la langue
|
||||
if ($success) {
|
||||
$notification = sprintf(helper::translate('Données %s copiées vers %s'), self::$languages[$copyFrom], self::$languages[$toCreate]);
|
||||
} else {
|
||||
$notification = helper::translate('Erreur de copie, vérifiez les permissions');
|
||||
}
|
||||
} else {
|
||||
$success = false;
|
||||
$notification = helper::translate('Les langues sélectionnées sont identiques');
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => $notification,
|
||||
'title' => 'Utilitaire de copie',
|
||||
'view' => 'index',
|
||||
'state' => $success
|
||||
]);
|
||||
}
|
||||
|
||||
// Tableau des langues installées
|
||||
foreach (self::$languages as $key => $value) {
|
||||
// tableau des langues installées
|
||||
if (is_dir(self::DATA_DIR . $key)) {
|
||||
self::$languagesTarget[$key] = self::$languages[$key];
|
||||
}
|
||||
}
|
||||
|
||||
// Langues cibles fr en plus
|
||||
self::$languagesInstalled = self::$languagesTarget;
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Copie de contenus localisés'),
|
||||
'view' => 'copy'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
// Langues du site
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
foreach (self::$languages as $key => $value) {
|
||||
// tableau des langues installées
|
||||
if (is_dir(self::DATA_DIR . $key)) {
|
||||
if (
|
||||
file_exists(self::DATA_DIR . $key . '/page.json') &&
|
||||
file_exists(self::DATA_DIR . $key . '/module.json') &&
|
||||
file_exists(self::DATA_DIR . $key . '/locale.json')
|
||||
) {
|
||||
if (file_exists(self::DATA_DIR . $key . '/.default')) {
|
||||
$messageLocale = helper::translate('Langue par défaut');
|
||||
} elseif (isset($_SESSION['ZWII_SITE_CONTENT']) && $_SESSION['ZWII_SITE_CONTENT'] === $key) {
|
||||
$messageLocale = helper::translate('Langue du site sélectionnée');
|
||||
} else {
|
||||
$messageLocale = '';
|
||||
}
|
||||
self::$languagesInstalled[] = [
|
||||
template::flag($key, '20 %') . ' ' . $value . ' (' . $key . ')',
|
||||
$messageLocale,
|
||||
template::button('translateContentLanguageLocaleEdit' . $key, [
|
||||
'class' => file_exists(self::DATA_DIR . $key . '/locale.json') ? '' : ' disabled',
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/locale/' . $key,
|
||||
'value' => template::ico('pencil'),
|
||||
'help' => 'Éditer'
|
||||
]),
|
||||
template::button('translateContentLanguageLocaleDelete' . $key, [
|
||||
'class' => 'translateDelete buttonRed' . ($messageLocale ? ' disabled' : ''),
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/locale/' . $key,
|
||||
'value' => template::ico('trash'),
|
||||
'help' => 'Supprimer',
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Activation du bouton de copie
|
||||
self::$siteCopy = count(self::$languagesInstalled) > 1 ? false : true;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
// Langues de l'UI
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
// Langues attachées à des utilisateurs non effaçables
|
||||
$usersUI = [];
|
||||
$users = $this->getData(['user']);
|
||||
foreach ($users as $key => $value) {
|
||||
array_push($usersUI, $this->getData(['user', $key, 'language']));
|
||||
}
|
||||
|
||||
// Langues installées
|
||||
$installedUI = $this->getData(['language']);
|
||||
|
||||
if (array_key_exists('language', $installedUI)) {
|
||||
$installedUI = $installedUI['language'];
|
||||
}
|
||||
|
||||
// Langues disponibles en ligne
|
||||
$storeUI = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
|
||||
$storeUI = $storeUI ? $storeUI['language'] : null;
|
||||
|
||||
// Construction du tableau à partir des langues disponibles dans le store
|
||||
foreach ($installedUI as $file => $value) {
|
||||
// La langue est-elle référencée ?
|
||||
if (array_key_exists(basename($file, '.json'), $installedUI)) {
|
||||
// La langue est déjà installée
|
||||
self::$languagesUiInstalled[$file] = [
|
||||
template::flag($file, '20 %') . ' ' . self::$languages[$file],
|
||||
$value['version'],
|
||||
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
|
||||
//self::$i18nUI === $file ? helper::translate('Interface') : '',
|
||||
'',
|
||||
/*
|
||||
template::button('translateContentLanguageUIEdit' . $file, [
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $file,
|
||||
'value' => template::ico('pencil'),
|
||||
'help' => 'Éditer',
|
||||
'disabled' => 'fr_FR' === $file
|
||||
]),
|
||||
*/
|
||||
|
||||
template::button('translateContentLanguageUIDownload' . $file, [
|
||||
'class' => isset($storeUI[$file]['version']) && version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '',
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
|
||||
'value' => template::ico('update'),
|
||||
'help' => 'Mise à jour',
|
||||
]),
|
||||
template::button('translateContentLanguageUIDelete' . $file, [
|
||||
'class' => 'translateDelete buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''),
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/ui/' . $file,
|
||||
'value' => template::ico('trash'),
|
||||
'help' => 'Supprimer',
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
// Construction du tableau à partir des langues disponibles dans le store
|
||||
if ($storeUI) {
|
||||
foreach ($storeUI as $file => $value) {
|
||||
|
||||
// La langue est-elle installée ?
|
||||
if (array_key_exists($file, $installedUI) === false) {
|
||||
self::$languagesStore[$file] = [
|
||||
template::flag($file, '20 %') . ' ' . self::$languages[$file],
|
||||
$value['version'],
|
||||
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
|
||||
'',
|
||||
template::button('translateContentLanguageUIDownload' . $file, [
|
||||
'class' => 'buttonGreen',
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
|
||||
'value' => template::ico('shopping-basket'),
|
||||
'help' => 'Installer',
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer vers la fenêtre
|
||||
switch ($this->getUrl(1)) {
|
||||
case 'interface':
|
||||
setcookie('translateLayout', 'ui', time() + 3600, '/', '', false, false);
|
||||
break;
|
||||
case 'site':
|
||||
setcookie('translateLayout', 'content', time() + 3600, '/', '', false, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Langues'),
|
||||
'view' => 'index'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Ajouter une langue de contenu
|
||||
*/
|
||||
|
||||
public function add()
|
||||
{
|
||||
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
$lang = $this->getInput('translateAddContent');
|
||||
|
||||
// Constructeur pour cette langue
|
||||
$this->jsonDB($lang);
|
||||
|
||||
// Création du contenu
|
||||
$this->initData('page', $lang);
|
||||
$this->initData('module', $lang);
|
||||
$this->initData('locale', $lang);
|
||||
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
// Préparation de l'affichage du formulaire
|
||||
//-----------------------------------------
|
||||
|
||||
// Tableau des langues non installées
|
||||
foreach (self::$languages as $key => $value) {
|
||||
if (!is_dir(self::DATA_DIR . $key))
|
||||
self::$i18nFiles[$key] = $value;
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Nouveau contenu localisé'),
|
||||
'view' => 'add'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Edition des paramètres de la langue de contenu
|
||||
*/
|
||||
public function locale()
|
||||
{
|
||||
// Action interdite ou URl avec le code langue incorrecte
|
||||
$lang = $this->getUrl(2);
|
||||
if (
|
||||
array_key_exists($lang, self::$languages) === false
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => false,
|
||||
'notification' => helper::translate('Action interdite')
|
||||
]);
|
||||
}
|
||||
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
// Sauvegarder les locales
|
||||
$data = [
|
||||
'locale' => [
|
||||
'homePageId' => $this->getInput('localeHomePageId', helper::FILTER_ID, true),
|
||||
'page404' => $this->getInput('localePage404'),
|
||||
'page403' => $this->getInput('localePage403'),
|
||||
'page302' => $this->getInput('localePage302'),
|
||||
'legalPageId' => $this->getInput('localeLegalPageId'),
|
||||
'searchPageId' => $this->getInput('localeSearchPageId'),
|
||||
'poweredPageLabel' => empty($this->getInput('localePoweredPageLabel', helper::FILTER_STRING_SHORT)) ? 'Motorisé par' : $this->getInput('localePoweredPageLabel', helper::FILTER_STRING_SHORT),
|
||||
'searchPageLabel' => empty($this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT),
|
||||
'legalPageLabel' => empty($this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT),
|
||||
'sitemapPageLabel' => empty($this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du site' : $this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT),
|
||||
'metaDescription' => $this->getInput('localeMetaDescription', helper::FILTER_STRING_LONG, true),
|
||||
'title' => $this->getInput('localeTitle', helper::FILTER_STRING_SHORT, true),
|
||||
'cookies' => [
|
||||
// Les champs sont obligatoires si l'option consentement des cookies est active
|
||||
'mainLabel' => $this->getInput('localeCookiesZwiiText', helper::FILTER_STRING_LONG, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'titleLabel' => $this->getInput('localeCookiesTitleText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'linkLegalLabel' => $this->getInput('localeCookiesLinkMlText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'cookiesFooterText' => $this->getInput('localeCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'buttonValidLabel' => $this->getInput('localeCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN))
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Sauvegarde hors méthodes si la langue n'est pas celle de l'UI
|
||||
if ($lang === self::$siteContent) {
|
||||
// Enregistrer les données par lecture directe du formulaire
|
||||
$this->setData(['locale', $data['locale']]);
|
||||
} else {
|
||||
// Sauver sur le disque
|
||||
$this->secure_file_put_contents(self::DATA_DIR . $lang . '/locale.json', $data);
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $this->getUrl(),
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
|
||||
// Préparation de l'affichage du formulaire
|
||||
//-----------------------------------------
|
||||
|
||||
// La locale est-elle celle de la langue de l'UI ?
|
||||
if ($lang === self::$siteContent) {
|
||||
self::$locales[$lang]['locale'] = $this->getData(['locale']);
|
||||
} else {
|
||||
// Lire les locales sans passer par les méthodes
|
||||
self::$locales[$lang] = json_decode(file_get_contents(self::DATA_DIR . $lang . '/locale.json'), true);
|
||||
}
|
||||
|
||||
// Générer la liste des pages disponibles
|
||||
self::$pagesList = $this->getData(['page']);
|
||||
foreach (self::$pagesList as $page => $pageId) {
|
||||
if (
|
||||
$this->getData(['page', $page, 'block']) === 'bar' ||
|
||||
$this->getData(['page', $page, 'disable']) === true
|
||||
) {
|
||||
unset(self::$pagesList[$page]);
|
||||
}
|
||||
}
|
||||
|
||||
self::$orphansList = $this->getData(['page']);
|
||||
foreach (self::$orphansList as $page => $pageId) {
|
||||
if (
|
||||
$this->getData(['page', $page, 'block']) === 'bar' ||
|
||||
$this->getData(['page', $page, 'disable']) === true ||
|
||||
$this->getdata(['page', $page, 'position']) !== 0
|
||||
) {
|
||||
unset(self::$orphansList[$page]);
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Paramètres de la localisation') . ' ' . template::flag($lang, '20 %'),
|
||||
'view' => 'locale'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edition de la langue de l'interface
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$lang = $this->getUrl(2);
|
||||
// Action interdite ou URl avec le code langue incorrecte
|
||||
if (
|
||||
array_key_exists($lang, self::$languages) === false
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => false,
|
||||
'notification' => helper::translate('Action interdite')
|
||||
]);
|
||||
}
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
|
||||
// Sauvegarder les champs de la langue
|
||||
$data = json_decode(file_get_contents(self::I18N_DIR . $lang . '.json'), true);
|
||||
foreach ($data as $key => $value) {
|
||||
$target = $this->getInput('translateString' . array_search($key, array_keys($data)));
|
||||
if (empty($target) === false) {
|
||||
$data[$key] = $target;
|
||||
}
|
||||
}
|
||||
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
|
||||
|
||||
// Mettre à jour le descripteur
|
||||
$this->setData([
|
||||
'language',
|
||||
$lang,
|
||||
[
|
||||
'version' => $this->getInput('translateEditVersion'),
|
||||
'date' => $this->getInput('translateEditDate', helper::FILTER_DATETIME),
|
||||
]
|
||||
]);
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
// Construction du formulaire
|
||||
|
||||
// Chargement des dialogue de la langue cible
|
||||
if (!isset($data)) {
|
||||
$data = json_decode(file_get_contents(self::I18N_DIR . $this->getUrl(2) . '.json'), true);
|
||||
}
|
||||
|
||||
// Ajout des champs absents selon la langue de référence
|
||||
$dataFr = json_decode(file_get_contents(self::I18N_DIR . 'fr_FR.json'), true);
|
||||
foreach ($dataFr as $key => $value) {
|
||||
if (!array_key_exists($key, $data)) {
|
||||
$data[$key] = '';
|
||||
}
|
||||
}
|
||||
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
|
||||
|
||||
// Tableau des chaines à traduire dans la langue sélectionnée
|
||||
foreach ($data as $key => $value) {
|
||||
$dialogues[] = ['source' => $key, 'target' => $value];
|
||||
}
|
||||
|
||||
// Pagination
|
||||
$pagination = helper::pagination($dialogues, $this->getUrl(), self::PAGINATION);
|
||||
|
||||
// Liste des pages
|
||||
self::$pages = $pagination['pages'];
|
||||
|
||||
// Articles en fonction de la pagination
|
||||
for ($i = $pagination['first']; $i < $pagination['last']; $i++) {
|
||||
self::$dialogues[$i] = $dialogues[$i];
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Éditer les dialogues') . ' ' . template::flag($lang, '20 %'),
|
||||
'view' => 'edit',
|
||||
'vendor' => [
|
||||
'flatpickr',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/***
|
||||
* Effacer une langue de contenu
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
// Action interdite ou URl avec le code langue incorrecte
|
||||
$target = $this->getUrl(2);
|
||||
$lang = $this->getUrl(3);
|
||||
if (
|
||||
array_key_exists($lang, self::$languages) === false
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => false,
|
||||
'notification' => helper::translate('Action interdite')
|
||||
]);
|
||||
}
|
||||
switch ($target) {
|
||||
case 'locale':
|
||||
$success = false;
|
||||
// Effacement d'une site dans une langue
|
||||
if (is_dir(self::DATA_DIR . $lang) === true) {
|
||||
$success = $this->deleteDir(self::DATA_DIR . $lang);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
|
||||
'state' => $success
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'ui':
|
||||
$success = false;
|
||||
// Effacement d'une langue de l'interface
|
||||
if (file_exists(self::I18N_DIR . $lang . '.json') === true) {
|
||||
$this->deleteData(['language', $lang]);
|
||||
$success = unlink(self::I18N_DIR . $lang . '.json');
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
|
||||
'state' => $success
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
# Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Modifie la langue du site par défaut
|
||||
*
|
||||
*/
|
||||
public function default()
|
||||
{
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
// Action interdite ou URl avec le code langue incorrecte
|
||||
$lang = $this->getUrl(2);
|
||||
if (
|
||||
array_key_exists($lang, self::$languages) === false
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => false,
|
||||
'notification' => helper::translate('Action interdite')
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (self::$languages as $key => $value) {
|
||||
if (file_exists(self::DATA_DIR . $key . '/.default')) {
|
||||
unlink(self::DATA_DIR . $key . '/.default');
|
||||
touch(self::DATA_DIR . $lang . '/.default');
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'language',
|
||||
'state' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Traitement du changement de langue
|
||||
* Fonction utilisée par le noyau
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
// Langue sélectionnée
|
||||
$lang = $this->getUrl(2);
|
||||
/**
|
||||
* Changement de la langue si
|
||||
* différe de la langue active
|
||||
* déjà initialisée
|
||||
* fait partie des langues installées
|
||||
*/
|
||||
|
||||
if (
|
||||
is_dir(self::DATA_DIR . $lang) &&
|
||||
array_key_exists($lang, self::$languages) === true
|
||||
) {
|
||||
|
||||
// Stocker la sélection
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $lang;
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl()
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
20
core/module/language/view/add/add.css
Normal file
20
core/module/language/view/add/add.css
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** @import url("site/data/admin.css"); */
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
29
core/module/language/view/add/add.php
Normal file
29
core/module/language/view/add/add.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php echo template::formOpen('translateAddForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('translateFormBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'language',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('translateFormSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Sélectionnez une langue'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4 offset4">
|
||||
<?php echo template::select('translateAddContent', $module::$i18nFiles, [
|
||||
'label' => 'Langues disponibles'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
20
core/module/language/view/copy/copy.css
Normal file
20
core/module/language/view/copy/copy.css
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** @import url("site/data/admin.css"); */
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
36
core/module/language/view/copy/copy.php
Normal file
36
core/module/language/view/copy/copy.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php echo template::formOpen('translateFormCopy'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('translateFormCopyBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'language',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('translateFormCopySubmit', [
|
||||
'value' => 'Copier'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Sélectionnez la langue à copier vers une langue cible'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::select('translateFormCopySource', $module::$languagesInstalled, [
|
||||
'label' => 'Source'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('translateFormCopyTarget', $module::$languagesTarget, [
|
||||
'label' => 'Cible'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
20
core/module/language/view/edit/edit.css
Normal file
20
core/module/language/view/edit/edit.css
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** @import url("site/data/admin.css"); */
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
59
core/module/language/view/edit/edit.php
Normal file
59
core/module/language/view/edit/edit.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php echo template::formOpen('translateUIForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('translateUIFormBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'language',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('translateUIFormSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('translateEditVersion', [
|
||||
'label' => 'Version n°',
|
||||
'value' => $this->getData(['language', $this->getUrl(2), 'version'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::date('translateEditDate', [
|
||||
'label' => 'Date de publication',
|
||||
'type' => 'datetime-local',
|
||||
'value' => $this->getData(['language', $this->getUrl(2), 'date'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<div class="row">
|
||||
<?php foreach ($module::$dialogues as $key => $value) : ?>
|
||||
<div class="col6">
|
||||
<?php echo sprintf('%g -', $key); ?>
|
||||
<?php echo $value['source']; ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('translateString' . $key, [
|
||||
'label' => '',
|
||||
'value' => $value['target']
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php echo $module::$pages; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
54
core/module/language/view/index/index.css
Normal file
54
core/module/language/view/index/index.css
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
#setupContainer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.buttonNotice {
|
||||
border: 2px solid red !important;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* Style the tab */
|
||||
.tab {
|
||||
margin-top: 1.8em;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tab ~ .tabContent {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.buttonTab {
|
||||
display: inline-block;
|
||||
transition: 0.3s;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
width: 160px;
|
||||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.buttonTab:hover {
|
||||
filter: saturate(200%);
|
||||
}
|
||||
|
||||
.activeButton {
|
||||
background-color: #00BFFF;
|
||||
}
|
88
core/module/language/view/index/index.js.php
Normal file
88
core/module/language/view/index/index.js.php
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
var translateLayout = getCookie("translateLayout");
|
||||
if (translateLayout == null) {
|
||||
translateLayout = "content";
|
||||
setCookie("translateLayout", "content");
|
||||
|
||||
}
|
||||
$("#contentContainer").hide();
|
||||
$("#uiContainer").hide();
|
||||
$("#" + translateLayout + "Container").show();
|
||||
$("#translate" + capitalizeFirstLetter(translateLayout) + "Button").addClass("activeButton");
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Sélecteur de fonctions
|
||||
|
||||
$("#translateUiButton").on("click", function() {
|
||||
$("#contentContainer").hide();
|
||||
$("#uiContainer").show();
|
||||
$(this).addClass("activeButton");
|
||||
$("#translateContentButton").removeClass("activeButton");
|
||||
setCookie("translateLayout", "ui");
|
||||
|
||||
});
|
||||
$("#translateContentButton").on("click", function() {
|
||||
$("#uiContainer").hide();
|
||||
$("#contentContainer").show();
|
||||
$(this).addClass("activeButton");
|
||||
$("#translateUiButton").removeClass("activeButton");
|
||||
setCookie("translateLayout", "content");
|
||||
// Afficher les boutons liés au contenu
|
||||
$(".contentButtonContainer").show();
|
||||
});
|
||||
|
||||
/**
|
||||
* Confirmation de suppression
|
||||
*/
|
||||
$(".translateDelete").on("click", function() {
|
||||
var _this = $(this);
|
||||
var message_delete = "<?php echo helper::translate('Confirmer la suppression de cette langue'); ?>";
|
||||
return core.confirm(message_delete, function() {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Fonctions
|
||||
function setCookie(name, value, days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Define function to capitalize the first letter of a string
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
98
core/module/language/view/index/index.php
Normal file
98
core/module/language/view/index/index.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php echo template::formOpen('translateForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('translateFormBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl(),
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /**echo template::button('translateHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/prise-en-charge-des-langues-etrangeres',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp',
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]);*/?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab">
|
||||
<?php echo template::button('translateUiButton', [
|
||||
'value' => 'Interface',
|
||||
'class' => 'buttonTab'
|
||||
]); ?>
|
||||
<?php echo template::button('translateContentButton', [
|
||||
'value' => 'Site',
|
||||
'class' => 'buttonTab'
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
<div id="uiContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Langues installées'); ?>
|
||||
</h4>
|
||||
<?php if ($module::$languagesUiInstalled): ?>
|
||||
<?php echo template::table([2, 1, 1, 5, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '']); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Catalogue'); ?>
|
||||
</h4>
|
||||
<?php if ($module::$languagesStore): ?>
|
||||
<?php echo template::table([2, 1, 2, 6, 1], $module::$languagesStore, ['Langues', 'Version', 'Date', '', '']); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="contentContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="col4 offset2">
|
||||
<?php echo template::button('translateButtonCopyContent', [
|
||||
'href' => helper::baseUrl() . 'language/copy',
|
||||
'ico' => 'docs',
|
||||
'disabled' => $module::$siteCopy,
|
||||
'value' => 'Copie de contenus localisés'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::button('translateButtonAddContent', [
|
||||
'href' => helper::baseUrl() . 'language/add',
|
||||
'ico' => 'plus',
|
||||
'class' => 'buttonGreen',
|
||||
'value' => 'Nouveau contenu localisé'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Langues installées'); ?>
|
||||
</h4>
|
||||
<?php if ($module::$languagesInstalled): ?>
|
||||
<?php echo template::table([2, 6, 1, 1], $module::$languagesInstalled, ['Langues', '', '', '']); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echo template::formClose(); ?>
|
20
core/module/language/view/locale/locale.css
Normal file
20
core/module/language/view/locale/locale.css
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** @import url("site/data/admin.css"); */
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
206
core/module/language/view/locale/locale.php
Normal file
206
core/module/language/view/locale/locale.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php echo template::formOpen('translateLocaleForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('translateFormBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'language',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('translateFormSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Identité du site'); ?>
|
||||
<!--<span id="localeHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
|
||||
<a href="https://doc.zwiicms.fr/localisation-et-identite" target="_blank">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::text('localeTitle', [
|
||||
'label' => 'Titre',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['title'],
|
||||
'help' => 'Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('localeMetaDescription', [
|
||||
'label' => 'Description',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['metaDescription'],
|
||||
'help' => 'La description d\'une page participe à son référencement, chaque page doit disposer d\'une description différente.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Assignation des pages spéciales') ?>
|
||||
<!--<span id="localeHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
|
||||
<a href="https://doc.zwiicms.fr/localisation-et-identite" target="_blank">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('localeHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
|
||||
'label' => 'Accueil',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['homePageId'],
|
||||
'help' => 'La première page que vos visiteurs verront.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::select('localePage403', array_merge(['none' => 'Page par défaut'], helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [
|
||||
'label' => 'Accès interdit, erreur 403',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['page403'],
|
||||
'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::select('localePage404', array_merge(['none' => 'Page par défaut'], helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [
|
||||
'label' => 'Page inexistante, erreur 404',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['page404'],
|
||||
'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('localeLegalPageId', array_merge(['none' => 'Aucune'], helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC')), [
|
||||
'label' => 'Mentions légales',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['legalPageId'],
|
||||
'help' => 'Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::select('localeSearchPageId', array_merge(['none' => 'Aucune'], helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC')), [
|
||||
'label' => 'Recherche dans le site',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['searchPageId'],
|
||||
'help' => 'Sélectionnez une page contenant le module \'Recherche\'. Une option du pied de page ajoute un lien discret vers cette page.'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php
|
||||
echo template::select('localePage302', array_merge(['none' => 'Page par défaut'], helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [
|
||||
'label' => 'Site en maintenance',
|
||||
'selected' => $module::$locales[$this->getUrl(2)]['locale']['page302'],
|
||||
'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Étiquettes des pages spéciales'); ?>
|
||||
<!--<span id="labelHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
|
||||
<a href="https://doc.zwiicms.fr/Étiquettes-des-pages-speciales" target="_blank">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('localePoweredPageLabel', [
|
||||
'label' => 'Motorisé par',
|
||||
'placeholder' => 'Motorisé par',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['poweredPageLabel']
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('localeLegalPageLabel', [
|
||||
'label' => 'Mentions légales',
|
||||
'placeholder' => 'Mentions légales',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['legalPageLabel']
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('localeSearchPageLabel', [
|
||||
'label' => 'Rechercher',
|
||||
'placeholder' => 'Rechercher',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['searchPageLabel']
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4 offset2">
|
||||
<?php echo template::text('localeSitemapPageLabel', [
|
||||
'label' => 'Plan du site',
|
||||
'placeholder' => 'Plan du site',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['sitemapPageLabel'],
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('localeCookiesFooterText', [
|
||||
'label' => 'Cookies',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['cookiesFooterText'],
|
||||
'placeHolder' => 'Cookies'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Message d\'acceptation des Cookies'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
|
||||
<a href="https://doc.zwiicms.fr/cookies" target="_blank">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('localeCookiesTitleText', [
|
||||
'help' => 'Saisissez le Titre de gestion des cookies.',
|
||||
'label' => 'Titre',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['titleLabel'],
|
||||
'placeHolder' => 'Cookies essentiels'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('localeCookiesButtonText', [
|
||||
'label' => 'Bouton de validation',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['buttonValidLabel'],
|
||||
'placeHolder' => 'J\'ai compris'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col8">
|
||||
<?php echo template::textarea('localeCookiesZwiiText', [
|
||||
'help' => 'Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.',
|
||||
'label' => 'Cookies Zwii',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['mainLabel'],
|
||||
'placeHolder' => 'Ce site utilise des cookies nécessaires à son fonctionnement, ils permettent de fluidifier son fonctionnement par exemple en mémorisant les données de connexion, la langue que vous avez choisie ou la validation de ce message.'
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
<div class="col4">
|
||||
<?php echo template::text('localeCookiesLinkMlText', [
|
||||
'help' => 'Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.',
|
||||
'label' => 'Lien page des mentions légales.',
|
||||
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['linkLegalLabel'],
|
||||
'placeHolder' => 'Consulter les mentions légales'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
0
core/module/language/view/store/store.php
Normal file
0
core/module/language/view/store/store.php
Normal file
1
core/module/language/view/update/update.php
Normal file
1
core/module/language/view/update/update.php
Normal file
@ -0,0 +1 @@
|
||||
<?php // Résolument vide
|
37
core/module/maintenance/maintenance.php
Executable file → Normal file
37
core/module/maintenance/maintenance.php
Executable file → Normal file
@ -2,17 +2,19 @@
|
||||
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class maintenance extends common {
|
||||
class maintenance extends common
|
||||
{
|
||||
|
||||
public static $actions = [
|
||||
'index' => self::GROUP_VISITOR
|
||||
@ -21,13 +23,34 @@ class maintenance extends common {
|
||||
/**
|
||||
* Maintenance
|
||||
*/
|
||||
public function index() {
|
||||
public function index()
|
||||
{
|
||||
// Redirection vers l'accueil après rafraîchissement et que la maintenance est terminée.
|
||||
if ($this->getData(['config', 'maintenance']) == False) {
|
||||
header('Location:' . helper::baseUrl());
|
||||
exit();
|
||||
}
|
||||
// Page perso définie et existante
|
||||
if (
|
||||
$this->getData(['locale', 'page302']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['locale', 'page302'])])
|
||||
) {
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
'title' => $this->getData(['page', $this->getData(['locale', 'page302']), 'hideTitle'])
|
||||
? ''
|
||||
: $this->getData(['page', $this->getData(['locale', 'page302']), 'title']),
|
||||
//'content' => $this->getdata(['page',$this->getData(['locale','page302']),'content']),
|
||||
'content' => $this->getPage($this->getData(['locale', 'page302']), self::$siteContent),
|
||||
'view' => 'index'
|
||||
]);
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
'title' => 'Maintenance en cours...',
|
||||
'title' => helper::translate('Maintenance en cours...'),
|
||||
'view' => 'index'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1
core/module/maintenance/view/index/index.css
Executable file
1
core/module/maintenance/view/index/index.css
Executable file
@ -0,0 +1 @@
|
||||
/* vide */
|
6
core/module/maintenance/view/index/index.php
Executable file → Normal file
6
core/module/maintenance/view/index/index.php
Executable file → Normal file
@ -1,8 +1,10 @@
|
||||
<p>Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.</p>
|
||||
<p>
|
||||
<?php echo helper::translate('Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.'); ?>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col4 offset8 textAlignCenter">
|
||||
<?php echo template::button('maintenanceLogin', [
|
||||
'value' => 'Administration',
|
||||
'value' => 'Connexion',
|
||||
'href' => helper::baseUrl() . 'user/login',
|
||||
'ico' => 'lock'
|
||||
]); ?>
|
||||
|
620
core/module/page/page.php
Executable file → Normal file
620
core/module/page/page.php
Executable file → Normal file
@ -9,17 +9,22 @@
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2019, Frédéric Tempez
|
||||
* @license GNU General Public License, version 3
|
||||
* @link http://zwiicms.com/
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
class page extends common {
|
||||
class page extends common
|
||||
{
|
||||
|
||||
public static $actions = [
|
||||
'add' => self::GROUP_MODERATOR,
|
||||
'delete' => self::GROUP_MODERATOR,
|
||||
'edit' => self::GROUP_MODERATOR
|
||||
'add' => self::GROUP_EDITOR,
|
||||
'delete' => self::GROUP_EDITOR,
|
||||
'edit' => self::GROUP_EDITOR,
|
||||
'duplicate' => self::GROUP_EDITOR,
|
||||
'jsEditor' => self::GROUP_EDITOR,
|
||||
'cssEditor' => self::GROUP_EDITOR,
|
||||
'register' => self::GROUP_EDITOR,
|
||||
];
|
||||
public static $pagesNoParentId = [
|
||||
'' => 'Aucune'
|
||||
@ -32,33 +37,130 @@ class page extends common {
|
||||
public static $typeMenu = [
|
||||
'text' => 'Texte',
|
||||
'icon' => 'Icône',
|
||||
'icontitle' => 'Icône et bulle'
|
||||
'icontitle' => 'Icône avec bulle de texte'
|
||||
];
|
||||
// Position du module
|
||||
public static $modulePosition = [
|
||||
'bottom' => 'En bas',
|
||||
'top' => 'En haut',
|
||||
'free' => 'Libre'
|
||||
'bottom' => 'Après le contenu de la page',
|
||||
'top' => 'Avant le contenu de la page',
|
||||
'free' => 'À l\'emplacement du mot clé [MODULE] dans la page'
|
||||
];
|
||||
public static $pageBlocks = [
|
||||
'12' => 'Pleine page',
|
||||
'4-8' => 'Barre latérale 1/3 - Page 2/3',
|
||||
'8-4' => 'Page 2/3 - Barre latérale 1/3',
|
||||
'3-9' => 'Barre latérale 1/4 - Page 3/4',
|
||||
'9-3' => 'Page 3/4 - Barre latérale 1/4',
|
||||
'3-6-3' => 'Barre latérale 1/4 - Page 1/2 - Barre latérale 1/4',
|
||||
'bar' => 'Barre latérale'
|
||||
'12' => 'Page standard',
|
||||
'bar' => 'Barre latérale',
|
||||
'4-8' => 'Barre 1/3 - page 2/3',
|
||||
'8-4' => 'Page 2/3 - barre 1/3',
|
||||
'3-9' => 'Barre 1/4 - page 3/4',
|
||||
'9-3' => 'Page 3/4 - barre 1/4',
|
||||
'3-6-3' => 'Barre 1/4 - page 1/2 - barre 1/4',
|
||||
'2-7-3' => 'Barre 2/12 - page 7/12 - barre 3/12',
|
||||
'3-7-2' => 'Barre 3/12 - page 7/12 - barre 2/12',
|
||||
];
|
||||
public static $displayMenu = [
|
||||
'none' => 'Aucun',
|
||||
'parents' => 'Menu principal',
|
||||
'children' => 'Sous-menu de la page parente'
|
||||
'none' => 'Aucun menu',
|
||||
'parents' => 'Le menu horizontal intégral',
|
||||
'children' => 'Le sous-menu de la page parente'
|
||||
];
|
||||
public static $extraPosition = [
|
||||
false => 'Menu standard',
|
||||
true => 'Menu accessoire'
|
||||
];
|
||||
|
||||
public static $userProfils = [];
|
||||
|
||||
public static $navIconTemplate = [
|
||||
'dir' => 'Petit triangle',
|
||||
'open' => 'Grand triangle',
|
||||
'big' => 'Flèche',
|
||||
];
|
||||
|
||||
public static $navIconPosition = [
|
||||
'none' => 'Masqué',
|
||||
'top' => 'Haut de page',
|
||||
'bottom' => 'Bas de page',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Duplication
|
||||
*/
|
||||
public function duplicate()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id de langue uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// Adresse sans le token
|
||||
$page = $this->getUrl(2);
|
||||
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
// Duplication de la page
|
||||
$pageTitle = $this->getData(['page', $page, 'title']);
|
||||
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
|
||||
$pageId = helper::increment($pageId, self::$coreModuleIds);
|
||||
$pageId = helper::increment($pageId, self::$moduleIds);
|
||||
$data = $this->getData([
|
||||
'page',
|
||||
$page
|
||||
]);
|
||||
// Ecriture
|
||||
$this->setData(['page', $pageId, $data], false);
|
||||
$notification = helper::translate('Page dupliquée');
|
||||
// Duplication du module présent
|
||||
if ($this->getData(['page', $page, 'moduleId'])) {
|
||||
$data = $this->getData(['module', $page]);
|
||||
$this->setData(['module', $pageId, $data], false);
|
||||
$notification = helper::translate('Page et module dupliqués');
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('page');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
|
||||
'notification' => $notification,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Création
|
||||
*/
|
||||
public function add() {
|
||||
public function add()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id de langue uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
} else {
|
||||
$pageTitle = 'Nouvelle page';
|
||||
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
|
||||
$this->setData([
|
||||
@ -68,7 +170,7 @@ class page extends common {
|
||||
'typeMenu' => 'text',
|
||||
'iconUrl' => '',
|
||||
'disable' => false,
|
||||
'content' => 'Contenu de votre nouvelle page.',
|
||||
'content' => $pageId . '.html',
|
||||
'hideTitle' => false,
|
||||
'breadCrumb' => false,
|
||||
'metaDescription' => '',
|
||||
@ -80,80 +182,149 @@ class page extends common {
|
||||
'group' => self::GROUP_VISITOR,
|
||||
'targetBlank' => false,
|
||||
'title' => $pageTitle,
|
||||
'shortTitle' => $pageTitle,
|
||||
'block' => '12',
|
||||
'barLeft' => '',
|
||||
'barRight' => '',
|
||||
'navLeft' => 'none',
|
||||
'navRight' => 'none',
|
||||
'navTemplate' => 'dir',
|
||||
'displayMenu' => '0',
|
||||
'hideMenuSide' => false,
|
||||
'hideMenuHead' => false,
|
||||
'hideMenuChildren' => false
|
||||
'hideMenuChildren' => false,
|
||||
'js' => '',
|
||||
'css' => ''
|
||||
]
|
||||
]);
|
||||
// Met à jour le site map
|
||||
$this->createSitemap('all');
|
||||
// Creation du contenu de la page
|
||||
if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
|
||||
mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
|
||||
}
|
||||
//$this->secure_file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
|
||||
$this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$siteContent);
|
||||
|
||||
// Ne met à jour le sitemap pour éviter un warning, de toute manière la nouvelle page doit être éditée.
|
||||
// $this->updateSitemap();
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $pageId,
|
||||
'notification' => 'Nouvelle page créée',
|
||||
'notification' => helper::translate('Nouvelle page créée'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppression
|
||||
*/
|
||||
public function delete() {
|
||||
public function delete()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id de langue uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// $url prend l'adresse sans le token
|
||||
$url = explode('&',$this->getUrl(2));
|
||||
$page = $this->getUrl(2);
|
||||
// La page n'existe pas
|
||||
if($this->getData(['page', $url[0]]) === null) {
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page d'accueil
|
||||
elseif($url[0] === $this->getData(['config', 'homePageId'])) {
|
||||
elseif ($page === $this->getData(['locale', 'homePageId'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
|
||||
'notification' => 'Impossible de supprimer la page d\'accueil'
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
// Jeton incorrect
|
||||
elseif(!isset($_GET['csrf'])) {
|
||||
// Impossible de supprimer la page affectée
|
||||
elseif ($page === $this->getData(['locale', 'searchPageId'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
|
||||
'notification' => 'Jeton invalide'
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
elseif ($_GET['csrf'] !== $_SESSION['csrf']) {
|
||||
// Impossible de supprimer la page affectée
|
||||
elseif ($page === $this->getData(['locale', 'legalPageId'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
|
||||
'notification' => 'Suppression non autorisée'
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
elseif ($page === $this->getData(['locale', 'page404'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
elseif ($page === $this->getData(['locale', 'page403'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
elseif ($page === $this->getData(['locale', 'page302'])) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer une page contenant des enfants
|
||||
elseif($this->getHierarchy($url[0])) {
|
||||
elseif ($this->getHierarchy($page, null)) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
|
||||
'notification' => 'Impossible de supprimer une page contenant des enfants'
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent,
|
||||
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
|
||||
]);
|
||||
}
|
||||
// Suppression
|
||||
else {
|
||||
// Met à jour le site map
|
||||
$this->createSitemap('all');
|
||||
// Effacer le dossier du module
|
||||
$moduleId = $this->getData(['page', $page, 'moduleId']);
|
||||
$modulesData = helper::getModules();
|
||||
if (
|
||||
array_key_exists($moduleId, $modulesData)
|
||||
&& is_dir($modulesData[$moduleId]['dataDirectory'] . $page)
|
||||
) {
|
||||
$this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $page);
|
||||
}
|
||||
// Effacer la page
|
||||
$this->deleteData(['page', $url[0]]);
|
||||
$this->deleteData(['module', $url[0]]);
|
||||
$this->deleteData(['page', $page]);
|
||||
if (file_exists(self::DATA_DIR . self::$siteContent . '/content/' . $page . '.html')) {
|
||||
unlink(self::DATA_DIR . self::$siteContent . '/content/' . $page . '.html');
|
||||
}
|
||||
$this->deleteData(['module', $page]);
|
||||
|
||||
// Met à jour le sitemap
|
||||
$this->updateSitemap();
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl(false),
|
||||
'notification' => 'Page supprimée',
|
||||
'notification' => helper::translate('Page supprimée'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
@ -163,9 +334,24 @@ class page extends common {
|
||||
/**
|
||||
* Édition
|
||||
*/
|
||||
public function edit() {
|
||||
public function edit()
|
||||
{
|
||||
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id de langue uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// La page n'existe pas
|
||||
if($this->getData(['page', $this->getUrl(2)]) === null) {
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $this->getUrl(2)]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
@ -174,11 +360,21 @@ class page extends common {
|
||||
// La page existe
|
||||
else {
|
||||
// Soumission du formulaire
|
||||
if($this->isPost()) {
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
// Si le Title n'est pas vide, premier test pour positionner la notification du champ obligatoire
|
||||
if ($this->getInput('pageEditTitle', helper::FILTER_ID, true) !== null && $this->getInput('pageEditTitle') !== '') {
|
||||
// Génére l'ID si le titre de la page a changé
|
||||
if ($this->getInput('pageEditTitle') !== $this->getData(['page', $this->getUrl(2), 'title'])) {
|
||||
$pageId = $this->getInput('pageEditTitle', helper::FILTER_ID, true);
|
||||
} else {
|
||||
$pageId = $this->getUrl(2);
|
||||
}
|
||||
// un dossier existe du même nom (erreur en cas de redirection)
|
||||
if (file_exists($pageId)) {
|
||||
$pageId = uniqid($pageId . '-');
|
||||
$pageId = uniqid($pageId);
|
||||
}
|
||||
// Si l'id a changée
|
||||
if ($pageId !== $this->getUrl(2)) {
|
||||
@ -187,48 +383,90 @@ class page extends common {
|
||||
$pageId = helper::increment($pageId, self::$coreModuleIds);
|
||||
$pageId = helper::increment($pageId, self::$moduleIds);
|
||||
// Met à jour les enfants
|
||||
foreach($this->getHierarchy($this->getUrl(2)) as $childrenPageId) {
|
||||
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId]);
|
||||
foreach ($this->getHierarchy($this->getUrl(2), null) as $childrenPageId) {
|
||||
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId], false);
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('page');
|
||||
// Change l'id de page dans les données des modules
|
||||
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])]);
|
||||
if ($this->getData(['module', $this->getUrl(2)]) !== null) {
|
||||
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])], false);
|
||||
$this->deleteData(['module', $this->getUrl(2)]);
|
||||
// Renommer le dossier du module
|
||||
$moduleId = $this->getData(['page', $this->getUrl(2), 'moduleId']);
|
||||
$modulesData = helper::getModules();
|
||||
if (is_dir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2))) {
|
||||
// Placer la feuille de style dans un dossier au nom de la nouvelle instance
|
||||
mkdir($modulesData[$moduleId]['dataDirectory'] . $pageId, 0755);
|
||||
copy($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2), $modulesData[$moduleId]['dataDirectory'] . $pageId);
|
||||
$this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2));
|
||||
// Mettre à jour le nom de la feuille de style
|
||||
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId], false);
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('module');
|
||||
}
|
||||
// Si la page correspond à la page d'accueil, change l'id dans la configuration du site
|
||||
if($this->getData(['config', 'homePageId']) === $this->getUrl(2)) {
|
||||
$this->setData(['config', 'homePageId', $pageId]);
|
||||
if ($this->getData(['locale', 'homePageId']) === $this->getUrl(2)) {
|
||||
$this->setData(['locale', 'homePageId', $pageId]);
|
||||
}
|
||||
}
|
||||
// Supprime les données du module en cas de changement de module
|
||||
if($this->getInput('pageEditModuleId') !== $this->getData(['page', $this->getUrl(2), 'moduleId'])) {
|
||||
if ($this->getInput('pageEditModuleId') !== $this->getData(['page', $this->getUrl(2), 'moduleId'])) {
|
||||
$this->deleteData(['module', $pageId]);
|
||||
}
|
||||
// Supprime l'ancienne page si l'id a changée
|
||||
if($pageId !== $this->getUrl(2)) {
|
||||
if ($pageId !== $this->getUrl(2)) {
|
||||
$this->deleteData(['page', $this->getUrl(2)]);
|
||||
if (file_exists(self::DATA_DIR . self::$siteContent . '/content/' . $this->getUrl(2) . '.html')) {
|
||||
unlink(self::DATA_DIR . self::$siteContent . '/content/' . $this->getUrl(2) . '.html');
|
||||
}
|
||||
}
|
||||
// Traitement des pages spéciales affectées dans la config :
|
||||
if ($this->getUrl(2) === $this->getData(['locale', 'legalPageId'])) {
|
||||
$this->setData(['locale', 'legalPageId', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['locale', 'searchPageId'])) {
|
||||
$this->setData(['locale', 'searchPageId', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['locale', 'page404'])) {
|
||||
$this->setData(['locale', 'page404', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['locale', 'page403'])) {
|
||||
$this->setData(['locale', 'page403', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['locale', 'page302'])) {
|
||||
$this->setData(['locale', 'page302', $pageId], false);
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('locale');
|
||||
// Si la page est une page enfant, actualise les positions des autres enfants du parent, sinon actualise les pages sans parents
|
||||
$lastPosition = 1;
|
||||
$hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy());
|
||||
$position = $this->getInput('pageEditPosition', helper::FILTER_INT);
|
||||
foreach($hierarchy as $hierarchyPageId) {
|
||||
$extraPosition = $this->getinput('pageEditExtraPosition', helper::FILTER_BOOLEAN);
|
||||
foreach ($hierarchy as $hierarchyPageId) {
|
||||
|
||||
// Ne traite que les pages du menu sélectionné
|
||||
if ($this->getData(['page', $hierarchyPageId, 'extraPosition']) === $extraPosition) {
|
||||
// Ignore la page en cours de modification
|
||||
if($hierarchyPageId === $this->getUrl(2)) {
|
||||
if ($hierarchyPageId === $this->getUrl(2)) {
|
||||
continue;
|
||||
}
|
||||
// Incrémente de +1 pour laisser la place à la position de la page en cours de modification
|
||||
if($lastPosition === $position) {
|
||||
if ($lastPosition === $position) {
|
||||
$lastPosition++;
|
||||
}
|
||||
// Change la position
|
||||
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition]);
|
||||
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition], false);
|
||||
// Incrémente pour la prochaine position
|
||||
$lastPosition++;
|
||||
}
|
||||
}
|
||||
if ($this->getinput('pageEditBlock') !== 'bar') {
|
||||
$barLeft = $this->getinput('pageEditBarLeft');
|
||||
$barRight = $this->getinput('pageEditBarRight');
|
||||
$hideTitle = $this->getInput('pageEditHideTitle', helper::FILTER_BOOLEAN);
|
||||
|
||||
} else {
|
||||
// Une barre ne peut pas avoir de barres
|
||||
$barLeft = "";
|
||||
@ -237,6 +475,53 @@ class page extends common {
|
||||
$position = 0;
|
||||
$hideTitle = true;
|
||||
}
|
||||
// Une page parent devient orpheline, les pages enfants le devienne pour éviter une incohérence
|
||||
if (
|
||||
$position === 0 &&
|
||||
$position !== $this->getData(['page', $this->getUrl(2), 'position']) &&
|
||||
$this->getinput('pageEditBlock') !== 'bar'
|
||||
) {
|
||||
foreach ($this->getHierarchy($pageId) as $parentId => $childId) {
|
||||
if ($this->getData(['page', $childId, 'parentPageId']) === $pageId) {
|
||||
$this->setData(['page', $childId, 'position', 0], false);
|
||||
}
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('page');
|
||||
}
|
||||
|
||||
// La page est une barre latérale qui a été renommée : changer le nom de la barre dans les pages qui l'utilisent
|
||||
if ($this->getinput('pageEditBlock') === 'bar') {
|
||||
foreach ($this->getHierarchy() as $eachPageId => $parentId) {
|
||||
if ($this->getData(['page', $eachPageId, 'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $eachPageId, 'barRight', $pageId], false);
|
||||
}
|
||||
if ($this->getData(['page', $eachPageId, 'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $eachPageId, 'barLeft', $pageId], false);
|
||||
}
|
||||
foreach ($parentId as $childId) {
|
||||
if ($this->getData(['page', $childId, 'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $childId, 'barRight', $pageId], false);
|
||||
}
|
||||
if ($this->getData(['page', $childId, 'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $childId, 'barLeft', $pageId], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Détermine le groupe selon que la page est une barre ou une page standard
|
||||
$group = $this->getinput('pageEditBlock') !== 'bar' ? $this->getInput('pageEditGroup', helper::FILTER_INT) : 0;
|
||||
|
||||
//Détermine le profil d'utilisateur en fonction du groupe sinon le groupe vaut 0
|
||||
$profil = 0;
|
||||
if (
|
||||
$this->getinput('pageEditBlock') !== 'bar' ||
|
||||
$group === 1 ||
|
||||
$group === 2
|
||||
) {
|
||||
$profil = $this->getInput('pageEditProfil' . $group, helper::FILTER_INT);
|
||||
}
|
||||
|
||||
// Modifie la page ou en crée une nouvelle si l'id a changé
|
||||
$this->setData([
|
||||
'page',
|
||||
@ -244,91 +529,108 @@ class page extends common {
|
||||
[
|
||||
'typeMenu' => $this->getinput('pageTypeMenu'),
|
||||
'iconUrl' => $this->getinput('pageIconUrl'),
|
||||
'disable'=> $this->getinput('pageEditDisable', helper::FILTER_BOOLEAN),
|
||||
'content' => (empty($this->getInput('pageEditContent', null)) ? "<p></p>" : $this->getInput('pageEditContent', null)) ,
|
||||
'disable' => $this->getinput('pageEditDisable', helper::FILTER_BOOLEAN),
|
||||
'content' => $pageId . '.html',
|
||||
'hideTitle' => $hideTitle,
|
||||
'breadCrumb' => $this->getInput('pageEditbreadCrumb', helper::FILTER_BOOLEAN),
|
||||
'metaDescription' => $this->getInput('pageEditMetaDescription', helper::FILTER_STRING_LONG),
|
||||
'metaTitle' => $this->getInput('pageEditMetaTitle'),
|
||||
'moduleId' => $this->getInput('pageEditModuleId'),
|
||||
'modulePosition' => $this->getInput('configModulePosition'),
|
||||
'modulePosition' => $this->getInput('pageModulePosition'),
|
||||
'parentPageId' => $this->getInput('pageEditParentPageId'),
|
||||
'position' => $position,
|
||||
'group' => $this->getInput('pageEditGroup', helper::FILTER_INT),
|
||||
'group' => $group,
|
||||
'profil' => $profil,
|
||||
'targetBlank' => $this->getInput('pageEditTargetBlank', helper::FILTER_BOOLEAN),
|
||||
'title' => $this->getInput('pageEditTitle', helper::FILTER_STRING_SHORT, true),
|
||||
'title' => $this->getInput('pageEditTitle', helper::FILTER_STRING_SHORT),
|
||||
'shortTitle' => $this->getInput('pageEditShortTitle', helper::FILTER_STRING_SHORT, true),
|
||||
'block' => $this->getinput('pageEditBlock'),
|
||||
'barLeft' => $barLeft,
|
||||
'barRight' => $barRight,
|
||||
'navLeft' => $this->getInput('pageEditNavLeft'),
|
||||
'navRight' => $this->getInput('pageEditNavRight'),
|
||||
'navTemplate' => $this->getInput('pageEditNavTemplate'),
|
||||
'displayMenu' => $this->getinput('pageEditDisplayMenu'),
|
||||
'hideMenuSide' => $this->getinput('pageEditHideMenuSide', helper::FILTER_BOOLEAN),
|
||||
'hideMenuHead' => $this->getinput('pageEditHideMenuHead', helper::FILTER_BOOLEAN),
|
||||
'hideMenuChildren' => $this->getinput('pageEditHideMenuChildren', helper::FILTER_BOOLEAN),
|
||||
'extraPosition' => $this->getinput('pageEditExtraPosition', helper::FILTER_BOOLEAN),
|
||||
'css' => $this->getData(['page', $this->getUrl(2), 'css']) == null ? '' : $this->getData(['page', $this->getUrl(2), 'css']),
|
||||
'js' => $this->getData(['page', $this->getUrl(2), 'js']) == null ? '' : $this->getData(['page', $this->getUrl(2), 'js']),
|
||||
]
|
||||
]);
|
||||
// Barre renommée : changement le nom de la barre dans les pages mères
|
||||
if ($this->getinput('pageEditBlock') === 'bar') {
|
||||
foreach ($this->getHierarchy() as $eachPageId=>$parentId) {
|
||||
if ($this->getData(['page',$eachPageId,'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page',$eachPageId,'barRight',$pageId]);
|
||||
|
||||
// Creation du contenu de la page
|
||||
if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
|
||||
mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
|
||||
}
|
||||
if ($this->getData(['page',$eachPageId,'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page',$eachPageId,'barLeft',$pageId]);
|
||||
}
|
||||
foreach ($parentId as $childId) {
|
||||
if ($this->getData(['page',$childId,'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page',$childId,'barRight',$pageId]);
|
||||
}
|
||||
if ($this->getData(['page',$childId,'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page',$childId,'barLeft',$pageId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Met à jour le site map
|
||||
$this->createSitemap('all');
|
||||
$content = empty($this->getInput('pageEditContent', null)) ? '<p></p>' : str_replace('<p></p>', '<p> </p>', $this->getInput('pageEditContent', null));
|
||||
$this->setPage($pageId, $content, self::$siteContent);
|
||||
|
||||
// Met à jour le sitemap
|
||||
$this->updateSitemap();
|
||||
|
||||
// Redirection vers la configuration
|
||||
if($this->getInput('pageEditModuleRedirect', helper::FILTER_BOOLEAN)) {
|
||||
if (
|
||||
$this->getInput('pageEditModuleRedirect', helper::FILTER_BOOLEAN)
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $pageId . '/config',
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Redirection vers la page
|
||||
else {
|
||||
} else {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $pageId,
|
||||
'notification' => 'Modifications enregistrées',
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Liste des modules
|
||||
$moduleIds = [
|
||||
'' => 'Aucun'
|
||||
];
|
||||
$iterator = new DirectoryIterator('module/');
|
||||
foreach($iterator as $fileInfos) {
|
||||
if(is_file($fileInfos->getPathname() . '/' . $fileInfos->getFilename() . '.php')) {
|
||||
$moduleIds[$fileInfos->getBasename()] = ucfirst($fileInfos->getBasename());
|
||||
}
|
||||
// Construction du formulaire
|
||||
|
||||
// Met à jour le sitemap
|
||||
$this->updateSitemap();
|
||||
|
||||
// Création du sélecteur de modules
|
||||
self::$moduleIds = [];
|
||||
foreach (helper::getModules() as $key => $values) {
|
||||
self::$moduleIds[$key] = $values['realName'] . ' (' . $key . ')';
|
||||
}
|
||||
self::$moduleIds = $moduleIds;
|
||||
self::$moduleIds = array_merge(['' => 'Aucun'], self::$moduleIds);
|
||||
|
||||
// Pages sans parent
|
||||
foreach($this->getHierarchy() as $parentPageId => $childrenPageIds) {
|
||||
if($parentPageId !== $this->getUrl(2)) {
|
||||
foreach ($this->getHierarchy() as $parentPageId => $childrenPageIds) {
|
||||
if ($parentPageId !== $this->getUrl(2)) {
|
||||
self::$pagesNoParentId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']);
|
||||
}
|
||||
}
|
||||
// Pages barre latérales
|
||||
foreach($this->getHierarchy(null,false,true) as $parentPageId => $childrenPageIds) {
|
||||
if($parentPageId !== $this->getUrl(2) &&
|
||||
$this->getData(['page', $parentPageId, 'block']) === 'bar') {
|
||||
foreach ($this->getHierarchy(null, false, true) as $parentPageId => $childrenPageIds) {
|
||||
if (
|
||||
$parentPageId !== $this->getUrl(2) &&
|
||||
$this->getData(['page', $parentPageId, 'block']) === 'bar'
|
||||
) {
|
||||
self::$pagesBarId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']);
|
||||
}
|
||||
}
|
||||
// Profils installés
|
||||
// Profils disponibles
|
||||
foreach ($this->getData(['profil']) as $profilId => $profilData) {
|
||||
if ($profilId < self::GROUP_MEMBER) {
|
||||
continue;
|
||||
}
|
||||
if ($profilId === self::GROUP_ADMIN) {
|
||||
self::$userProfils[$profilId][self::GROUP_ADMIN] = $profilData['name'];
|
||||
continue;
|
||||
}
|
||||
foreach ($profilData as $key => $value) {
|
||||
self::$userProfils[$profilId][$key] = $profilData[$key]['name'];
|
||||
}
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => $this->getData(['page', $this->getUrl(2), 'title']),
|
||||
@ -340,4 +642,108 @@ class page extends common {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Éditeur de feuille de style
|
||||
*/
|
||||
public function cssEditor()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
$css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le CSS
|
||||
$this->setData([
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'css',
|
||||
$css
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Éditeur CSS'),
|
||||
'vendor' => [
|
||||
'codemirror'
|
||||
],
|
||||
'view' => 'cssEditor'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Éditeur de feuille de style
|
||||
*/
|
||||
public function jsEditor()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
$js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le JS
|
||||
$this->setData([
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'js',
|
||||
$js
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Éditeur Js'),
|
||||
'vendor' => [
|
||||
'codemirror'
|
||||
],
|
||||
'view' => 'jsEditor'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les informations sur les pages en omettant les clés CSS et JS qui occasionnent des bugs d'affichage dans l'éditeur de page
|
||||
* @return string tableau associatif des pages dans le menu
|
||||
*/
|
||||
public function getPageInfo()
|
||||
{
|
||||
$p = $this->getData(['page']);
|
||||
$d = array_map(function ($d) {
|
||||
unset($d["css"], $d["js"]);
|
||||
return $d;
|
||||
}, $p);
|
||||
return json_encode($d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
|
||||
* @return never
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->setData([
|
||||
'user',
|
||||
$this->getUser('id'),
|
||||
'view',
|
||||
[
|
||||
'page' => $this->getUrl(2),
|
||||
'config' => $this->getData(['user', $this->getUser('id'), 'view', 'config']),
|
||||
]
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(3) . '/' . self::$siteContent,
|
||||
]);
|
||||
}
|
||||
}
|
18
core/module/page/view/cssEditor/cssEditor.css
Normal file
18
core/module/page/view/cssEditor/cssEditor.css
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user