mirror of
https://github.com/getgrav/grav.git
synced 2025-12-05 15:29:57 +01:00
Compare commits
942 Commits
1.6.6
...
1.7.0-rc.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bc46c49d2 | ||
|
|
292d45a7db | ||
|
|
2d375954ab | ||
|
|
7ff6d2a828 | ||
|
|
bcbfa0e32a | ||
|
|
ccac8a93bc | ||
|
|
453cd62a51 | ||
|
|
56e1cbc78e | ||
|
|
58cd77449c | ||
|
|
db92c7b32d | ||
|
|
6ba54d2b3d | ||
|
|
987429208c | ||
|
|
2eae104c7a | ||
|
|
6f2be2a2d2 | ||
|
|
e75960fee3 | ||
|
|
ec71ccdd0d | ||
|
|
a5d47a36f0 | ||
|
|
866b63530a | ||
|
|
57feac985c | ||
|
|
c72c980ad2 | ||
|
|
790d29cbfb | ||
|
|
b9947f6984 | ||
|
|
79b7c3c38f | ||
|
|
a9df896538 | ||
|
|
ad713a1342 | ||
|
|
b58479cba6 | ||
|
|
107341f33f | ||
|
|
1ed0fcb379 | ||
|
|
63892782b4 | ||
|
|
f5a480c72e | ||
|
|
d80a29b34d | ||
|
|
5aefc60f2e | ||
|
|
683c1fe477 | ||
|
|
6b4692f6c7 | ||
|
|
1351f11551 | ||
|
|
58280b8d3f | ||
|
|
652ca75f40 | ||
|
|
4b5f1590aa | ||
|
|
152c987ed4 | ||
|
|
19311c7ec1 | ||
|
|
eec2d122cc | ||
|
|
62f39fe39c | ||
|
|
394fce3825 | ||
|
|
9c6934c0aa | ||
|
|
993bc5170b | ||
|
|
d285eda4c2 | ||
|
|
0bcbe39521 | ||
|
|
78502b2026 | ||
|
|
df0c806381 | ||
|
|
d089a1d9c8 | ||
|
|
e41072c448 | ||
|
|
36d18d531c | ||
|
|
fb18412fb3 | ||
|
|
9a8c2b9aa5 | ||
|
|
678b39a170 | ||
|
|
d03b0d92f4 | ||
|
|
11f9ba74e8 | ||
|
|
f4f5bffcd9 | ||
|
|
d763f9c63e | ||
|
|
44acd3a969 | ||
|
|
4d7510dc11 | ||
|
|
f4a3efc3bc | ||
|
|
40bc980084 | ||
|
|
cf62d1dfa2 | ||
|
|
378e59563d | ||
|
|
1196e06dd6 | ||
|
|
028bbf08c6 | ||
|
|
1d6a474b31 | ||
|
|
79e68eb5df | ||
|
|
13a1c7cfee | ||
|
|
a3812141dd | ||
|
|
5833f1e2da | ||
|
|
88311f21cf | ||
|
|
64b33d60f4 | ||
|
|
8ccbcf0488 | ||
|
|
4fb485d1dd | ||
|
|
244c34a536 | ||
|
|
52a704e53d | ||
|
|
5852ca4179 | ||
|
|
04820b8adc | ||
|
|
5be92b7a8a | ||
|
|
addecbbb22 | ||
|
|
ec8bf9357a | ||
|
|
432b4b1e68 | ||
|
|
ea5935b1d1 | ||
|
|
65db6ea26c | ||
|
|
a77b5e69e7 | ||
|
|
c9da739ea3 | ||
|
|
fa3c9095c7 | ||
|
|
9e4ee6ec91 | ||
|
|
95442ef0b5 | ||
|
|
1f92ec715a | ||
|
|
f81503dd70 | ||
|
|
0642e34a77 | ||
|
|
4e8e3e1865 | ||
|
|
48170d2fa0 | ||
|
|
8936e82e9b | ||
|
|
e0162d276d | ||
|
|
14ff7fae33 | ||
|
|
2c78b3efca | ||
|
|
5104bde6d4 | ||
|
|
59f05ec8a2 | ||
|
|
20047fbdaf | ||
|
|
81dd33c2e9 | ||
|
|
1cf390206e | ||
|
|
8169a6f3f8 | ||
|
|
2165ded8d4 | ||
|
|
ef80e28d1d | ||
|
|
234abb38d9 | ||
|
|
3a722ba44e | ||
|
|
3f56c5a727 | ||
|
|
e55b239536 | ||
|
|
c2f374f0db | ||
|
|
29c6a70611 | ||
|
|
0bbbe96ae0 | ||
|
|
40010f7ff7 | ||
|
|
49aae0c50e | ||
|
|
5ea7ec1013 | ||
|
|
75ee0670f6 | ||
|
|
6e327880a3 | ||
|
|
ceaa20d5d4 | ||
|
|
10589e7940 | ||
|
|
5e9a7a112a | ||
|
|
a672a765b4 | ||
|
|
4794097992 | ||
|
|
f012d2d13a | ||
|
|
d0a22ad416 | ||
|
|
6dee662b40 | ||
|
|
1d8b87e33f | ||
|
|
5db91538c6 | ||
|
|
7d6fb9eee6 | ||
|
|
694b14511d | ||
|
|
bbab97137f | ||
|
|
3408db0c9b | ||
|
|
1bbf8dffeb | ||
|
|
887b34dd31 | ||
|
|
0f5166d690 | ||
|
|
e507300134 | ||
|
|
e38c5cac4a | ||
|
|
463a55897c | ||
|
|
192cc4eb9b | ||
|
|
e5fe28b720 | ||
|
|
defc70e656 | ||
|
|
d589dbcbea | ||
|
|
3ed8620d7a | ||
|
|
bc5501eecb | ||
|
|
2ae6bac390 | ||
|
|
118621cb8b | ||
|
|
3118ed5f56 | ||
|
|
ac17fc8efd | ||
|
|
85c1ec67c2 | ||
|
|
959a2ec379 | ||
|
|
1372c9b1cc | ||
|
|
67dd5f256d | ||
|
|
2c3ced3fba | ||
|
|
a592f6fe0b | ||
|
|
9123cb7796 | ||
|
|
df09c01a25 | ||
|
|
b97301d82d | ||
|
|
6b887a98cd | ||
|
|
18a26b42e2 | ||
|
|
85de4ed0e3 | ||
|
|
80125ce298 | ||
|
|
27542d4fa4 | ||
|
|
a47e446b60 | ||
|
|
471fb4da6f | ||
|
|
a2a6888982 | ||
|
|
864a938f8d | ||
|
|
bdd30238bf | ||
|
|
528ce7131e | ||
|
|
53bd1641bb | ||
|
|
b10725cebc | ||
|
|
719cc5466a | ||
|
|
e373cf18e0 | ||
|
|
7ef5fa5630 | ||
|
|
d139b0388a | ||
|
|
014ab5d7ee | ||
|
|
64f3949967 | ||
|
|
7913edd34b | ||
|
|
2136dc34fe | ||
|
|
c559b42151 | ||
|
|
a33d974c74 | ||
|
|
ede7af6b9d | ||
|
|
5cd4bf5c98 | ||
|
|
045fae9b6f | ||
|
|
bbd46644e0 | ||
|
|
3e67c0a878 | ||
|
|
924f01158d | ||
|
|
8d5dd60fb4 | ||
|
|
958ea586ec | ||
|
|
5f6cc58186 | ||
|
|
426f59e41a | ||
|
|
fff9fa0ca5 | ||
|
|
57aced69cf | ||
|
|
afac6baa11 | ||
|
|
b4630aeb38 | ||
|
|
cac02663e6 | ||
|
|
e59f1e5a82 | ||
|
|
90d077d7c2 | ||
|
|
a77d6bcfa0 | ||
|
|
bee5abfbf0 | ||
|
|
664447a67b | ||
|
|
b850443090 | ||
|
|
98d0c760a9 | ||
|
|
76bb7fe4af | ||
|
|
26584b9909 | ||
|
|
6a9724dd3e | ||
|
|
c7a41ddfda | ||
|
|
2df05dd16d | ||
|
|
50c2c55554 | ||
|
|
d72b99c5b2 | ||
|
|
5adadfdb40 | ||
|
|
7574195ca2 | ||
|
|
5b5ef98495 | ||
|
|
226e5350b7 | ||
|
|
b9b83c3b16 | ||
|
|
971fb2b19a | ||
|
|
378b60783c | ||
|
|
d901558481 | ||
|
|
1515ee9193 | ||
|
|
9c34471800 | ||
|
|
6f16f6f134 | ||
|
|
7c0dcd6808 | ||
|
|
33790dbb33 | ||
|
|
ea8b7b7a3a | ||
|
|
8714aa9202 | ||
|
|
3731d61b78 | ||
|
|
927e99fcb3 | ||
|
|
ef6ec100f2 | ||
|
|
386a39e274 | ||
|
|
38d3b5cf43 | ||
|
|
5718299210 | ||
|
|
2e64d560b1 | ||
|
|
82270e0c13 | ||
|
|
ca22b56148 | ||
|
|
eca3896bfc | ||
|
|
1c2c38545a | ||
|
|
464e1fc6c7 | ||
|
|
02b8499b0c | ||
|
|
b5caa41386 | ||
|
|
a8ff0e3892 | ||
|
|
ebab884441 | ||
|
|
2c95992eb1 | ||
|
|
1666774a1e | ||
|
|
3cc0dc08db | ||
|
|
f9bcf48700 | ||
|
|
8a618fee64 | ||
|
|
a6f7637134 | ||
|
|
f04ef0b359 | ||
|
|
608457bd01 | ||
|
|
508cf1ffdb | ||
|
|
6f38933e81 | ||
|
|
8ff2ca4c5a | ||
|
|
6a0d5c69ab | ||
|
|
2747877195 | ||
|
|
584b33d41a | ||
|
|
f4330ff77d | ||
|
|
60c43184cb | ||
|
|
2fe2eb9f21 | ||
|
|
04ee52d1ad | ||
|
|
99e047171f | ||
|
|
ddc8668837 | ||
|
|
e568b992a9 | ||
|
|
23221a8f8f | ||
|
|
4eed10cd4b | ||
|
|
da02c0992a | ||
|
|
2437112f3c | ||
|
|
276b4bb0ab | ||
|
|
acf271344d | ||
|
|
7b5d6f7031 | ||
|
|
767ce29e39 | ||
|
|
daad16ef1b | ||
|
|
1718135614 | ||
|
|
a269d49392 | ||
|
|
3a8775f545 | ||
|
|
842dc0d49e | ||
|
|
3f9ed2f344 | ||
|
|
5640baa175 | ||
|
|
f102a8cb3d | ||
|
|
a65c468e81 | ||
|
|
4cc3f44caa | ||
|
|
8afe004a7f | ||
|
|
185e9b5272 | ||
|
|
78b76cf023 | ||
|
|
3606d3d0bd | ||
|
|
3be95e752f | ||
|
|
1532de8f20 | ||
|
|
95bd217c3c | ||
|
|
f633c921cc | ||
|
|
e8c79ffd97 | ||
|
|
e842eb9d9e | ||
|
|
71bdb5e25e | ||
|
|
b58f36b5af | ||
|
|
dc20f4f32a | ||
|
|
c765fff4b3 | ||
|
|
032f5654a4 | ||
|
|
0e01e52cac | ||
|
|
37b2c97dc1 | ||
|
|
c61b07febb | ||
|
|
620fd7ed88 | ||
|
|
b314ea13aa | ||
|
|
3e8572dbe9 | ||
|
|
5ba7b4154c | ||
|
|
ad8d0a2ab1 | ||
|
|
4a1e16449d | ||
|
|
41d31cb5ea | ||
|
|
909e2cbf89 | ||
|
|
1290503895 | ||
|
|
a204b24d78 | ||
|
|
8be5a2182b | ||
|
|
ee30694cf1 | ||
|
|
37a9a30187 | ||
|
|
de34910a6d | ||
|
|
86c969998f | ||
|
|
158874039a | ||
|
|
175cebc4a1 | ||
|
|
20aba0fd7c | ||
|
|
efc2da90d3 | ||
|
|
12ad800d1f | ||
|
|
de6c35f4ab | ||
|
|
46816a74e9 | ||
|
|
1111c3d1b1 | ||
|
|
e919685ad3 | ||
|
|
238ba9b9b4 | ||
|
|
1d966a0c92 | ||
|
|
3e87b21a8e | ||
|
|
21309f1451 | ||
|
|
225644f82b | ||
|
|
285fffc7df | ||
|
|
7c760387f3 | ||
|
|
94ff668044 | ||
|
|
270b1191f5 | ||
|
|
6208c516c2 | ||
|
|
b695c9591e | ||
|
|
911da0f34f | ||
|
|
14c2e257a0 | ||
|
|
52ec745ed0 | ||
|
|
8f42dc3c33 | ||
|
|
45530114a7 | ||
|
|
5b8baed0bc | ||
|
|
936e95a146 | ||
|
|
61a3f3f7c1 | ||
|
|
b3545ccb8b | ||
|
|
d217f1e4fb | ||
|
|
bb373061ae | ||
|
|
c65cb83348 | ||
|
|
e3a6436031 | ||
|
|
f56a5f0ad6 | ||
|
|
9044721c89 | ||
|
|
ce5729ba53 | ||
|
|
fc70a50fd6 | ||
|
|
a8d61cb5de | ||
|
|
d8af66cfd7 | ||
|
|
1aa69e61ac | ||
|
|
be3ecf1377 | ||
|
|
571674a4f5 | ||
|
|
a06520337f | ||
|
|
bf2b7dcf7b | ||
|
|
86faceb94f | ||
|
|
963e365da4 | ||
|
|
4332ac35db | ||
|
|
7e5d58f94b | ||
|
|
6b3b6106bf | ||
|
|
f0c12e6246 | ||
|
|
741934b1da | ||
|
|
35e7bfe506 | ||
|
|
dcc2ddfdb8 | ||
|
|
f59441eb55 | ||
|
|
9cb6ddf742 | ||
|
|
035a84b55d | ||
|
|
d892343e57 | ||
|
|
aaa3976e5a | ||
|
|
0d4afd7a37 | ||
|
|
a3a8976fdf | ||
|
|
4edb1ca61b | ||
|
|
d6374f259a | ||
|
|
7b4f40d3b1 | ||
|
|
9c4eb549b7 | ||
|
|
c380fb638b | ||
|
|
908e993727 | ||
|
|
4128864e39 | ||
|
|
304f800018 | ||
|
|
fcc0c5e345 | ||
|
|
77887d83e9 | ||
|
|
3514ff64fe | ||
|
|
b56ede81f0 | ||
|
|
427c39e88e | ||
|
|
e450923409 | ||
|
|
c862b0bc26 | ||
|
|
575a1e4603 | ||
|
|
a74ccad282 | ||
|
|
7cb678bdb6 | ||
|
|
14110d5475 | ||
|
|
c742eee1cc | ||
|
|
ffeb5648c6 | ||
|
|
86c87929ec | ||
|
|
e0e92b843c | ||
|
|
a996137317 | ||
|
|
9fb55d8d0f | ||
|
|
861f53c5dc | ||
|
|
a588395ba9 | ||
|
|
e80b7fe19e | ||
|
|
4e23f07fcd | ||
|
|
a571f42e1b | ||
|
|
2fd5492286 | ||
|
|
4e227fcae5 | ||
|
|
99c6a78134 | ||
|
|
a93ef3f752 | ||
|
|
0814d5e3bb | ||
|
|
2e8be3c67f | ||
|
|
191bf8730a | ||
|
|
09e8dfdbfd | ||
|
|
a1ea841034 | ||
|
|
f9f836959c | ||
|
|
c4ce2d1648 | ||
|
|
0f66032c9b | ||
|
|
8678f22f6b | ||
|
|
4ca1f1f4ca | ||
|
|
913efdbd6a | ||
|
|
9c123f7d3d | ||
|
|
2b00e93f22 | ||
|
|
8322a0cfa3 | ||
|
|
ab6b82eaaa | ||
|
|
b16e8066ca | ||
|
|
09e10d16ea | ||
|
|
ef8e1c2fdf | ||
|
|
e2843e6477 | ||
|
|
bc1dd2a7b4 | ||
|
|
3e52101bf8 | ||
|
|
d11772b681 | ||
|
|
32a9acc62e | ||
|
|
d568ddfa5c | ||
|
|
1656f0160b | ||
|
|
14b33824b1 | ||
|
|
7902912269 | ||
|
|
2db04e43d1 | ||
|
|
467c33d3e1 | ||
|
|
87f17d296d | ||
|
|
feeee9ef86 | ||
|
|
7ba964f161 | ||
|
|
77205fb3d8 | ||
|
|
4bba284bf5 | ||
|
|
a6e78de197 | ||
|
|
8fc7755e90 | ||
|
|
fdfb5bb8ac | ||
|
|
d0800136b7 | ||
|
|
d368aeafd4 | ||
|
|
e59c596886 | ||
|
|
411656a9d6 | ||
|
|
8599faaf3b | ||
|
|
90e55ead29 | ||
|
|
f85c94b403 | ||
|
|
b4fa7e38b9 | ||
|
|
411871f636 | ||
|
|
b01d1baa53 | ||
|
|
c3c33e954c | ||
|
|
edd0bc25a2 | ||
|
|
6c57104658 | ||
|
|
26d7181eca | ||
|
|
1fb611655f | ||
|
|
b561c2b47c | ||
|
|
9beefb3162 | ||
|
|
41851b73b9 | ||
|
|
c325c24897 | ||
|
|
efd4e52571 | ||
|
|
565f26db8e | ||
|
|
b641b0e442 | ||
|
|
2a6276a941 | ||
|
|
eb1b9567df | ||
|
|
7dafa2a207 | ||
|
|
5253aa6aef | ||
|
|
1b34530a4a | ||
|
|
ae41b6f5ff | ||
|
|
4d09a345a4 | ||
|
|
8ac3451fbc | ||
|
|
15f1f2a03d | ||
|
|
ffa9ef6a7e | ||
|
|
a75c0cbe62 | ||
|
|
c795ead402 | ||
|
|
91270c9c66 | ||
|
|
9259c2f660 | ||
|
|
138d1e93e3 | ||
|
|
5db9f16174 | ||
|
|
342eac1047 | ||
|
|
88c859fde2 | ||
|
|
8b5bce0b6d | ||
|
|
09c4cf66f5 | ||
|
|
46b859b8df | ||
|
|
a7c23c58e5 | ||
|
|
d206711354 | ||
|
|
0007100a97 | ||
|
|
3d999501a0 | ||
|
|
52f83775e3 | ||
|
|
a35cf5a830 | ||
|
|
39837d0826 | ||
|
|
66bd6a4046 | ||
|
|
4e9d3395e0 | ||
|
|
248c7764f0 | ||
|
|
f72eb1b002 | ||
|
|
25caa5138a | ||
|
|
dffb227df6 | ||
|
|
7c161d5cbc | ||
|
|
7b2313ef0b | ||
|
|
1ad2a3f212 | ||
|
|
1f2363b623 | ||
|
|
d1c069c2ee | ||
|
|
67e772a5ce | ||
|
|
59bb167bd4 | ||
|
|
5c9eb1cdb8 | ||
|
|
94a54d2a82 | ||
|
|
f201d48112 | ||
|
|
df51b64b35 | ||
|
|
93ff915737 | ||
|
|
e30ab9a043 | ||
|
|
8e59a08f9e | ||
|
|
5a874006b4 | ||
|
|
5d639cc633 | ||
|
|
ab7038b49e | ||
|
|
651b354d3e | ||
|
|
90c2079529 | ||
|
|
fa064301a2 | ||
|
|
5424047d02 | ||
|
|
ce2b80aeb9 | ||
|
|
e91ae5542d | ||
|
|
922f263005 | ||
|
|
01af81a0a6 | ||
|
|
bd8c274f38 | ||
|
|
05fb69daa7 | ||
|
|
21f95eba53 | ||
|
|
4ef56054ee | ||
|
|
bec9292a5c | ||
|
|
0fa6328816 | ||
|
|
b30240c340 | ||
|
|
59eb3b4cb2 | ||
|
|
5fa047c1b7 | ||
|
|
30481da51d | ||
|
|
beb8f09a9d | ||
|
|
603bb6c878 | ||
|
|
dac3e57fd4 | ||
|
|
b601d2c8fd | ||
|
|
ab75201f11 | ||
|
|
45b1b0a2ef | ||
|
|
ca2f657c98 | ||
|
|
5c33882f5b | ||
|
|
0f85214693 | ||
|
|
4570c00041 | ||
|
|
4a0c8846e2 | ||
|
|
41e51cd86d | ||
|
|
e2ed3098a3 | ||
|
|
4e9ca82a0f | ||
|
|
f032f310b5 | ||
|
|
6b665b112c | ||
|
|
d9dbe5520d | ||
|
|
5b8674122a | ||
|
|
2e245cd36f | ||
|
|
e36a2ea1b0 | ||
|
|
53b7c95b0d | ||
|
|
46975cca22 | ||
|
|
a418acc32b | ||
|
|
eeb35fc521 | ||
|
|
90ca9f9d49 | ||
|
|
ba267a389e | ||
|
|
0ab99806db | ||
|
|
c300a3b8f8 | ||
|
|
8480fb68ac | ||
|
|
8e82056afa | ||
|
|
3e34d54b9a | ||
|
|
9ad7b208ba | ||
|
|
1fa62d2bdc | ||
|
|
b659c56aec | ||
|
|
3bd02b95fe | ||
|
|
9e5ad84a48 | ||
|
|
40a6c4bf72 | ||
|
|
22acffac5c | ||
|
|
ede749821d | ||
|
|
f26e518c03 | ||
|
|
0f6a517589 | ||
|
|
3530f4fdef | ||
|
|
b92476d40d | ||
|
|
0d0bb2c229 | ||
|
|
de59bad0f8 | ||
|
|
72ad49610c | ||
|
|
dcd1f3b10d | ||
|
|
52cf554ea2 | ||
|
|
f30f6485ba | ||
|
|
dd8b503aa0 | ||
|
|
dab30673e0 | ||
|
|
13689c2065 | ||
|
|
6e23627f26 | ||
|
|
7db85cc79c | ||
|
|
9b6f218f33 | ||
|
|
829da9ee3a | ||
|
|
033b54104e | ||
|
|
e5cedd074b | ||
|
|
a6741cb761 | ||
|
|
8cbc2a27cd | ||
|
|
5f1639dc63 | ||
|
|
ed87faad92 | ||
|
|
8d8b803e66 | ||
|
|
e4ed00d84a | ||
|
|
239f34d40c | ||
|
|
20b9ca56fa | ||
|
|
647ae0fda3 | ||
|
|
806dbd9ee5 | ||
|
|
1ab8442630 | ||
|
|
040c34d693 | ||
|
|
505661404b | ||
|
|
a2ea6faf4d | ||
|
|
ce51491b4d | ||
|
|
8942aa8afc | ||
|
|
d241223aa3 | ||
|
|
256cbe3f12 | ||
|
|
8b31ee173e | ||
|
|
182970eb78 | ||
|
|
9ed3da3df2 | ||
|
|
14eaa4d00a | ||
|
|
e134e3dbd9 | ||
|
|
5bfb168cd7 | ||
|
|
5aef09a410 | ||
|
|
76732ab671 | ||
|
|
d16f83fdd8 | ||
|
|
02e10ff8fe | ||
|
|
6a44d8f286 | ||
|
|
4b614d871f | ||
|
|
f54d9af758 | ||
|
|
f883191d99 | ||
|
|
de5ead78d1 | ||
|
|
44bbdf7e39 | ||
|
|
4b4eedf467 | ||
|
|
bb477fd3b1 | ||
|
|
758e316a65 | ||
|
|
2c38e24d00 | ||
|
|
3286d70092 | ||
|
|
9fc37e46fa | ||
|
|
f304f429c5 | ||
|
|
ca24e63d22 | ||
|
|
65c73f639f | ||
|
|
d2833a1997 | ||
|
|
aa8f764436 | ||
|
|
f1909d80db | ||
|
|
7718dd7e98 | ||
|
|
cc66070e85 | ||
|
|
bbdc54b406 | ||
|
|
c013f63b26 | ||
|
|
aa007badb5 | ||
|
|
618a59921a | ||
|
|
bb2e7a720b | ||
|
|
039f71dc61 | ||
|
|
c36e6abd66 | ||
|
|
c2b1142b7a | ||
|
|
e03fb200a6 | ||
|
|
27b8db4c10 | ||
|
|
a964a34a6f | ||
|
|
1c28fd4c4c | ||
|
|
e8529e7d0b | ||
|
|
a6032af594 | ||
|
|
ea49415e14 | ||
|
|
7b26022f9f | ||
|
|
443fecfeb6 | ||
|
|
c3324e3702 | ||
|
|
9e60408769 | ||
|
|
3737bc9371 | ||
|
|
3d2360c995 | ||
|
|
08b8505b6d | ||
|
|
afd53d76c2 | ||
|
|
9607a99a7d | ||
|
|
7e63935001 | ||
|
|
3d767a4d25 | ||
|
|
ee53e1be6e | ||
|
|
57c65ad881 | ||
|
|
a372ae90c2 | ||
|
|
676924cce5 | ||
|
|
c8739c40a5 | ||
|
|
36a3a95ed9 | ||
|
|
95c58c8361 | ||
|
|
66c17a8f53 | ||
|
|
00ff9ac42d | ||
|
|
7172da8ed6 | ||
|
|
c55ea919ef | ||
|
|
53216631a6 | ||
|
|
69d6b52a0e | ||
|
|
e13a8304e6 | ||
|
|
3c2b17853c | ||
|
|
ea1e0a76c1 | ||
|
|
833fe8b729 | ||
|
|
23d508b390 | ||
|
|
288b2a1953 | ||
|
|
e8b24479b9 | ||
|
|
1485c23aba | ||
|
|
d43357f366 | ||
|
|
86b1f1fbac | ||
|
|
c8e5aa05f9 | ||
|
|
04ccce1f67 | ||
|
|
5826821895 | ||
|
|
3ed341304b | ||
|
|
025e73affd | ||
|
|
5635ba2bb7 | ||
|
|
b5e26133a7 | ||
|
|
95637a243c | ||
|
|
cd417a1509 | ||
|
|
631ae3d3d5 | ||
|
|
7c34224304 | ||
|
|
6062e47377 | ||
|
|
c97faa0238 | ||
|
|
a94abb4fb2 | ||
|
|
8ab317b49a | ||
|
|
44dda3d607 | ||
|
|
75ed986437 | ||
|
|
3ac785b9ce | ||
|
|
de367e1558 | ||
|
|
4fead303d1 | ||
|
|
41898af46f | ||
|
|
fe8833876c | ||
|
|
e116998914 | ||
|
|
053f96dec1 | ||
|
|
94494c3c96 | ||
|
|
69b39b4b21 | ||
|
|
5afae3c3f2 | ||
|
|
eed3d84a10 | ||
|
|
e7b996104f | ||
|
|
02f544f813 | ||
|
|
69b5a779e4 | ||
|
|
3f176c1924 | ||
|
|
91d20d8840 | ||
|
|
6998505e3c | ||
|
|
ffa2e0a6f6 | ||
|
|
b54e4fb71b | ||
|
|
8f391d327a | ||
|
|
e0e29f468b | ||
|
|
89b9cc5367 | ||
|
|
fa5c1e495d | ||
|
|
7fdb2c10cb | ||
|
|
e422eebd3c | ||
|
|
3dca7e3539 | ||
|
|
75210b102e | ||
|
|
f0e97a7277 | ||
|
|
f6c30cbeae | ||
|
|
cca7b6b1d4 | ||
|
|
e16c81516e | ||
|
|
c765787102 | ||
|
|
dff3872b43 | ||
|
|
3c91cea232 | ||
|
|
a2e9c013ad | ||
|
|
dd82ab45bc | ||
|
|
46b710b435 | ||
|
|
a6d3e1ee8e | ||
|
|
140c9a941f | ||
|
|
2b29b17044 | ||
|
|
5316f0f28c | ||
|
|
eb58fe9e97 | ||
|
|
5d4ea87402 | ||
|
|
9f1d7240a9 | ||
|
|
ac4d6cc8d0 | ||
|
|
84894274f0 | ||
|
|
ea09002012 | ||
|
|
601ec5cb7a | ||
|
|
565947e074 | ||
|
|
25d1767e6c | ||
|
|
c079f9b95b | ||
|
|
85ec2ee3a0 | ||
|
|
20cfb45c14 | ||
|
|
5314558a8e | ||
|
|
965f69f680 | ||
|
|
02b93d510a | ||
|
|
13a56dd4da | ||
|
|
4cf1b8c400 | ||
|
|
9c805a4317 | ||
|
|
b7b1182e14 | ||
|
|
8dfb0ca993 | ||
|
|
f695aaaea4 | ||
|
|
b398d04d96 | ||
|
|
574df5cf80 | ||
|
|
ac9ef4da76 | ||
|
|
a10893eaad | ||
|
|
34dcd8c346 | ||
|
|
5079077e1d | ||
|
|
0e0d5b23be | ||
|
|
e6c8b30882 | ||
|
|
a222e353ba | ||
|
|
1f120a0127 | ||
|
|
fe05c9b87b | ||
|
|
f795a634b5 | ||
|
|
888b93926c | ||
|
|
687f29f912 | ||
|
|
273bc9d970 | ||
|
|
d593d5a392 | ||
|
|
18fb688cde | ||
|
|
d8fccb0edd | ||
|
|
5843347c46 | ||
|
|
30cfe3bdfa | ||
|
|
fedb0625b8 | ||
|
|
72d012e401 | ||
|
|
8d77b50055 | ||
|
|
42eefbd34c | ||
|
|
e5e5bf1bd8 | ||
|
|
01ec334127 | ||
|
|
916469a903 | ||
|
|
55f205c801 | ||
|
|
8a3fc57cd8 | ||
|
|
6cd1cca4fc | ||
|
|
1c9926ff38 | ||
|
|
638477b06d | ||
|
|
7e3ca73b0e | ||
|
|
57a3a20868 | ||
|
|
4e45c5be95 | ||
|
|
ca89156c4f | ||
|
|
dc5390b3dc | ||
|
|
0e8c7eae99 | ||
|
|
115bdb7e10 | ||
|
|
9738c55633 | ||
|
|
23921c1a35 | ||
|
|
1f3547b15b | ||
|
|
6974a24669 | ||
|
|
2cf35ec2c7 | ||
|
|
d21bb6b8c7 | ||
|
|
9b8b480c8c | ||
|
|
ac654d56d0 | ||
|
|
db9e1a197e | ||
|
|
19bb9a6966 | ||
|
|
b7a1c7b72a | ||
|
|
042486bc73 | ||
|
|
42cc1c6b01 | ||
|
|
407d2c8323 | ||
|
|
8ab14c0639 | ||
|
|
48c281024f | ||
|
|
f7e1bec0cf | ||
|
|
41c7973fc7 | ||
|
|
bc93e70d11 | ||
|
|
320ab41435 | ||
|
|
7213c393fd | ||
|
|
6caadc8396 | ||
|
|
e0d1385061 | ||
|
|
e1eed973a2 | ||
|
|
f4645fc77e | ||
|
|
136ec07450 | ||
|
|
e01605de55 | ||
|
|
5cc48c4e01 | ||
|
|
5e2545c606 | ||
|
|
d227a82056 | ||
|
|
0fd2627cea | ||
|
|
cfcd955cc2 | ||
|
|
7d59b69709 | ||
|
|
e8eb1d9a44 | ||
|
|
2117748f18 | ||
|
|
e76733e8c3 | ||
|
|
2da5f90e9c | ||
|
|
81b100cd3b | ||
|
|
19be8f5104 | ||
|
|
9825daa79b | ||
|
|
10d405112c | ||
|
|
ad64a9d857 | ||
|
|
c4c70d082c | ||
|
|
23a928c5b7 | ||
|
|
8a7f624558 | ||
|
|
331f416e36 | ||
|
|
3a48c79b21 | ||
|
|
0c66de25c4 | ||
|
|
92e8dbf4ea | ||
|
|
aca04cee6b | ||
|
|
0bd227c22d | ||
|
|
7bc45bd9e0 | ||
|
|
9e5363b4df | ||
|
|
37f69d89cc | ||
|
|
30e96aa4ff | ||
|
|
7e1d3b260e | ||
|
|
be558ccac9 | ||
|
|
e991056106 | ||
|
|
b795155345 | ||
|
|
99d0c7cb3e | ||
|
|
01b85f19bc | ||
|
|
65ba214494 | ||
|
|
ccff51144e | ||
|
|
c8f6e7b0e1 | ||
|
|
7cccf8e237 | ||
|
|
e1f646c308 | ||
|
|
2a49a2ba7c | ||
|
|
e9bbd1e0b0 | ||
|
|
84e259f0f1 | ||
|
|
b3f4461f34 | ||
|
|
1df6b76e25 | ||
|
|
2153e20bc5 | ||
|
|
0cbc98ab53 | ||
|
|
0915a0413d | ||
|
|
f4d3d302f4 | ||
|
|
5d5e2264c0 | ||
|
|
b39fc72bd2 | ||
|
|
d6d50c4b66 | ||
|
|
791ef8ad88 | ||
|
|
e0861e5505 | ||
|
|
48c9176d90 | ||
|
|
33cb20561e | ||
|
|
0acb38f586 | ||
|
|
1a41e00a4f | ||
|
|
48ef93e495 | ||
|
|
3f7da86711 | ||
|
|
11aa2314d5 | ||
|
|
179c5065ca | ||
|
|
7c60f73942 | ||
|
|
7095c665b7 | ||
|
|
c6d94885e0 | ||
|
|
d9ddab8239 | ||
|
|
a118d45177 | ||
|
|
416c400367 | ||
|
|
e6839530d8 | ||
|
|
fea9e53be3 | ||
|
|
c5b3792a60 | ||
|
|
4f83b5da5b | ||
|
|
504c8faf4c | ||
|
|
4d6db5b334 | ||
|
|
ec1fc1f1e3 | ||
|
|
563cf8900c | ||
|
|
0850c2f362 | ||
|
|
f30334d80f | ||
|
|
9057a804a2 | ||
|
|
4c5c26033a | ||
|
|
a4f679adcf | ||
|
|
e9e12392ac | ||
|
|
6b4663c2ff | ||
|
|
0411c3a98b | ||
|
|
972a758ac9 | ||
|
|
05d72306c6 | ||
|
|
18b7c0955d | ||
|
|
71cbbf4e1e | ||
|
|
0606e12872 | ||
|
|
afc7cac5ab | ||
|
|
471e3d8954 | ||
|
|
89a92cddc7 | ||
|
|
74988f1254 | ||
|
|
f2f2bc1cf8 | ||
|
|
31c5809e4a | ||
|
|
b4b8b63e24 | ||
|
|
9c0de8b0d3 | ||
|
|
f4cca777c2 | ||
|
|
8d7d143d01 | ||
|
|
d9109e9934 | ||
|
|
be8eb63944 | ||
|
|
9342981d8c | ||
|
|
6e9af3bb29 | ||
|
|
7e39755154 | ||
|
|
97af8919fc | ||
|
|
6cdfaeb8fb | ||
|
|
864c5027c6 |
@@ -13,5 +13,5 @@ indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# 2 space indentation
|
||||
[*.{yaml,.yml}]
|
||||
[*.{yaml,yml}]
|
||||
indent_size = 2
|
||||
|
||||
8
.github/FUNDING.yml
vendored
Normal file
8
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: grav
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: # Replace with a single custom sponsorship URL
|
||||
44
.phan/config.php
Normal file
44
.phan/config.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
return [
|
||||
"target_php_version" => null,
|
||||
'pretend_newer_core_functions_exist' => true,
|
||||
'allow_missing_properties' => false,
|
||||
'null_casts_as_any_type' => false,
|
||||
'null_casts_as_array' => false,
|
||||
'array_casts_as_null' => false,
|
||||
'strict_method_checking' => true,
|
||||
'quick_mode' => false,
|
||||
'simplify_ast' => false,
|
||||
'directory_list' => [
|
||||
'.',
|
||||
],
|
||||
"exclude_analysis_directory_list" => [
|
||||
'vendor/'
|
||||
],
|
||||
'exclude_file_list' => [
|
||||
'system/src/Grav/Common/Errors/Resources/layout.html.php',
|
||||
'tests/_support/AcceptanceTester.php',
|
||||
'tests/_support/FunctionalTester.php',
|
||||
'tests/_support/UnitTester.php',
|
||||
],
|
||||
'autoload_internal_extension_signatures' => [
|
||||
'memcached' => '.phan/internal_stubs/memcached.phan_php',
|
||||
'memcache' => '.phan/internal_stubs/memcache.phan_php',
|
||||
'redis' => '.phan/internal_stubs/Redis.phan_php',
|
||||
],
|
||||
'plugins' => [
|
||||
'AlwaysReturnPlugin',
|
||||
'UnreachableCodePlugin',
|
||||
'DuplicateArrayKeyPlugin',
|
||||
'PregRegexCheckerPlugin',
|
||||
'PrintfCheckerPlugin',
|
||||
],
|
||||
'suppress_issue_types' => [
|
||||
'PhanUnreferencedUseNormal',
|
||||
'PhanTypeObjectUnsetDeclaredProperty',
|
||||
'PhanTraitParentReference',
|
||||
'PhanTypeInvalidThrowsIsInterface',
|
||||
'PhanRequiredTraitNotAdded',
|
||||
'PhanDeprecatedFunction', // Uncomment this to see all the deprecated calls
|
||||
]
|
||||
];
|
||||
5153
.phan/internal_stubs/Redis.phan_php
Normal file
5153
.phan/internal_stubs/Redis.phan_php
Normal file
File diff suppressed because it is too large
Load Diff
460
.phan/internal_stubs/memcache.phan_php
Normal file
460
.phan/internal_stubs/memcache.phan_php
Normal file
@@ -0,0 +1,460 @@
|
||||
<?php
|
||||
|
||||
// Start of memcache v.3.0.8
|
||||
|
||||
class MemcachePool {
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Open memcached server connection
|
||||
* @link https://php.net/manual/en/memcache.connect.php
|
||||
* @param string $host <p>
|
||||
* Point to the host where memcached is listening for connections. This parameter
|
||||
* may also specify other transports like <em>unix:///path/to/memcached.sock</em>
|
||||
* to use UNIX domain sockets, in this case <b>port</b> must also
|
||||
* be set to <em>0</em>.
|
||||
* </p>
|
||||
* @param int $port [optional] <p>
|
||||
* Point to the port where memcached is listening for connections. Set this
|
||||
* parameter to <em>0</em> when using UNIX domain sockets.
|
||||
* </p>
|
||||
* <p>
|
||||
* Please note: <b>port</b> defaults to
|
||||
* {@link https://php.net/manual/ru/memcache.ini.php#ini.memcache.default-port memcache.default_port}
|
||||
* if not specified. For this reason it is wise to specify the port
|
||||
* explicitly in this method call.
|
||||
* </p>
|
||||
* @param int $timeout [optional] <p>Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow.</p>
|
||||
* @return bool <p>Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.</p>
|
||||
*/
|
||||
public function connect ($host, $port, $timeout = 1) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.0.0)<br/>
|
||||
* Add a memcached server to connection pool
|
||||
* @link https://php.net/manual/en/memcache.addserver.php
|
||||
* @param string $host <p>
|
||||
* Point to the host where memcached is listening for connections. This parameter
|
||||
* may also specify other transports like unix:///path/to/memcached.sock
|
||||
* to use UNIX domain sockets, in this case <i>port</i> must also
|
||||
* be set to 0.
|
||||
* </p>
|
||||
* @param int $port [optional] <p>
|
||||
* Point to the port where memcached is listening for connections.
|
||||
* Set this
|
||||
* parameter to 0 when using UNIX domain sockets.
|
||||
* </p>
|
||||
* <p>
|
||||
* Please note: <i>port</i> defaults to
|
||||
* memcache.default_port
|
||||
* if not specified. For this reason it is wise to specify the port
|
||||
* explicitly in this method call.
|
||||
* </p>
|
||||
* @param bool $persistent [optional] <p>
|
||||
* Controls the use of a persistent connection. Default to <b>TRUE</b>.
|
||||
* </p>
|
||||
* @param int $weight [optional] <p>
|
||||
* Number of buckets to create for this server which in turn control its
|
||||
* probability of it being selected. The probability is relative to the
|
||||
* total weight of all servers.
|
||||
* </p>
|
||||
* @param int $timeout [optional] <p>
|
||||
* Value in seconds which will be used for connecting to the daemon. Think
|
||||
* twice before changing the default value of 1 second - you can lose all
|
||||
* the advantages of caching if your connection is too slow.
|
||||
* </p>
|
||||
* @param int $retry_interval [optional] <p>
|
||||
* Controls how often a failed server will be retried, the default value
|
||||
* is 15 seconds. Setting this parameter to -1 disables automatic retry.
|
||||
* Neither this nor the <i>persistent</i> parameter has any
|
||||
* effect when the extension is loaded dynamically via <b>dl</b>.
|
||||
* </p>
|
||||
* <p>
|
||||
* Each failed connection struct has its own timeout and before it has expired
|
||||
* the struct will be skipped when selecting backends to serve a request. Once
|
||||
* expired the connection will be successfully reconnected or marked as failed
|
||||
* for another <i>retry_interval</i> seconds. The typical
|
||||
* effect is that each web server child will retry the connection about every
|
||||
* <i>retry_interval</i> seconds when serving a page.
|
||||
* </p>
|
||||
* @param bool $status [optional] <p>
|
||||
* Controls if the server should be flagged as online. Setting this parameter
|
||||
* to <b>FALSE</b> and <i>retry_interval</i> to -1 allows a failed
|
||||
* server to be kept in the pool so as not to affect the key distribution
|
||||
* algorithm. Requests for this server will then failover or fail immediately
|
||||
* depending on the <i>memcache.allow_failover</i> setting.
|
||||
* Default to <b>TRUE</b>, meaning the server should be considered online.
|
||||
* </p>
|
||||
* @param callable $failure_callback [optional] <p>
|
||||
* Allows the user to specify a callback function to run upon encountering an
|
||||
* error. The callback is run before failover is attempted. The function takes
|
||||
* two parameters, the hostname and port of the failed server.
|
||||
* </p>
|
||||
* @param int $timeoutms [optional] <p>
|
||||
* </p>
|
||||
* @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function addServer ($host, $port = 11211, $persistent = true, $weight = null, $timeout = 1, $retry_interval = 15, $status = true, callable $failure_callback = null, $timeoutms = null) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.1.0)<br/>
|
||||
* Changes server parameters and status at runtime
|
||||
* @link https://secure.php.net/manual/en/memcache.setserverparams.php
|
||||
* @param string $host <p>Point to the host where memcached is listening for connections.</p.
|
||||
* @param int $port [optional] <p>
|
||||
* Point to the port where memcached is listening for connections.
|
||||
* </p>
|
||||
* @param int $timeout [optional] <p>
|
||||
* Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow.
|
||||
* </p>
|
||||
* @param int $retry_interval [optional] <p>
|
||||
* Controls how often a failed server will be retried, the default value
|
||||
* is 15 seconds. Setting this parameter to -1 disables automatic retry.
|
||||
* Neither this nor the <b>persistent</b> parameter has any
|
||||
* effect when the extension is loaded dynamically via {@link https://secure.php.net/manual/en/function.dl.php dl()}.
|
||||
* </p>
|
||||
* @param bool $status [optional] <p>
|
||||
* Controls if the server should be flagged as online. Setting this parameter
|
||||
* to <b>FALSE</b> and <b>retry_interval</b> to -1 allows a failed
|
||||
* server to be kept in the pool so as not to affect the key distribution
|
||||
* algorithm. Requests for this server will then failover or fail immediately
|
||||
* depending on the <b>memcache.allow_failover</b> setting.
|
||||
* Default to <b>TRUE</b>, meaning the server should be considered online.
|
||||
* </p>
|
||||
* @param callable $failure_callback [optional] <p>
|
||||
* Allows the user to specify a callback function to run upon encountering an error. The callback is run before failover is attempted.
|
||||
* The function takes two parameters, the hostname and port of the failed server.
|
||||
* </p>
|
||||
* @return bool <p>Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.</p>
|
||||
*/
|
||||
public function setServerParams ($host, $port = 11211, $timeout = 1, $retry_interval = 15, $status = true, callable $failure_callback = null) {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function setFailureCallback () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.1.0)<br/>
|
||||
* Returns server status
|
||||
* @link https://php.net/manual/en/memcache.getserverstatus.php
|
||||
* @param string $host Point to the host where memcached is listening for connections.
|
||||
* @param int $port Point to the port where memcached is listening for connections.
|
||||
* @return int Returns a the servers status. 0 if server is failed, non-zero otherwise
|
||||
*/
|
||||
public function getServerStatus ($host, $port = 11211) {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function findServer () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Return version of the server
|
||||
* @link https://php.net/manual/en/memcache.getversion.php
|
||||
* @return string|false Returns a string of server version number or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function getVersion () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.0.0)<br/>
|
||||
* Add an item to the server. If the key already exists, the value will not be added and <b>FALSE</b> will be returned.
|
||||
* @link https://php.net/manual/en/memcache.add.php
|
||||
* @param string $key The key that will be associated with the item.
|
||||
* @param mixed $var The variable to store. Strings and integers are stored as is, other types are stored serialized.
|
||||
* @param int $flag [optional] <p>
|
||||
* Use <b>MEMCACHE_COMPRESSED</b> to store the item
|
||||
* compressed (uses zlib).
|
||||
* </p>
|
||||
* @param int $expire [optional] <p>Expiration time of the item.
|
||||
* If it's equal to zero, the item will never expire.
|
||||
* You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).</p>
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. Returns <b>FALSE</b> if such key already exist. For the rest Memcache::add() behaves similarly to Memcache::set().
|
||||
*/
|
||||
public function add ($key , $var, $flag = null, $expire = null) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Stores an item var with key on the memcached server. Parameter expire is expiration time in seconds.
|
||||
* If it's 0, the item never expires (but memcached server doesn't guarantee this item to be stored all the time,
|
||||
* it could be deleted from the cache to make place for other items).
|
||||
* You can use MEMCACHE_COMPRESSED constant as flag value if you want to use on-the-fly compression (uses zlib).
|
||||
* @link https://php.net/manual/en/memcache.set.php
|
||||
* @param string $key The key that will be associated with the item.
|
||||
* @param mixed $var The variable to store. Strings and integers are stored as is, other types are stored serialized.
|
||||
* @param int $flag [optional] Use MEMCACHE_COMPRESSED to store the item compressed (uses zlib).
|
||||
* @param int $expire [optional] Expiration time of the item. If it's equal to zero, the item will never expire. You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function set ($key, $var, $flag = null, $expire = null) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Replace value of the existing item
|
||||
* @link https://php.net/manual/en/memcache.replace.php
|
||||
* @param string $key <p>The key that will be associated with the item.</p>
|
||||
* @param mixed $var <p>The variable to store. Strings and integers are stored as is, other types are stored serialized.</p>
|
||||
* @param int $flag [optional] <p>Use <b>MEMCACHE_COMPRESSED</b> to store the item compressed (uses zlib).</p>
|
||||
* @param int $expire [optional] <p>Expiration time of the item. If it's equal to zero, the item will never expire. You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).</p>
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
public function replace ($key, $var, $flag = null, $expire = null) {}
|
||||
|
||||
public function cas () {}
|
||||
|
||||
public function append () {}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function prepend () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Retrieve item from the server
|
||||
* @link https://php.net/manual/en/memcache.get.php
|
||||
* @param string|array $key <p>
|
||||
* The key or array of keys to fetch.
|
||||
* </p>
|
||||
* @param int|array $flags [optional] <p>
|
||||
* If present, flags fetched along with the values will be written to this parameter. These
|
||||
* flags are the same as the ones given to for example {@link https://php.net/manual/en/memcache.set.php Memcache::set()}.
|
||||
* The lowest byte of the int is reserved for pecl/memcache internal usage (e.g. to indicate
|
||||
* compression and serialization status).
|
||||
* </p>
|
||||
* @return string|array|false <p>
|
||||
* Returns the string associated with the <b>key</b> or
|
||||
* an array of found key-value pairs when <b>key</b> is an {@link https://php.net/manual/en/language.types.array.php array}.
|
||||
* Returns <b>FALSE</b> on failure, <b>key</b> is not found or
|
||||
* <b>key</b> is an empty {@link https://php.net/manual/en/language.types.array.php array}.
|
||||
* </p>
|
||||
*/
|
||||
public function get ($key, &$flags = null) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Delete item from the server
|
||||
* https://secure.php.net/manual/ru/memcache.delete.php
|
||||
* @param $key string The key associated with the item to delete.
|
||||
* @param $timeout int [optional] This deprecated parameter is not supported, and defaults to 0 seconds. Do not use this parameter.
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function delete ($key, $timeout = 0 ) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Get statistics of the server
|
||||
* @link https://php.net/manual/ru/memcache.getstats.php
|
||||
* @param string $type [optional] <p>
|
||||
* The type of statistics to fetch.
|
||||
* Valid values are {reset, malloc, maps, cachedump, slabs, items, sizes}.
|
||||
* According to the memcached protocol spec these additional arguments "are subject to change for the convenience of memcache developers".</p>
|
||||
* @param int $slabid [optional] <p>
|
||||
* Used in conjunction with <b>type</b> set to
|
||||
* cachedump to identify the slab to dump from. The cachedump
|
||||
* command ties up the server and is strictly to be used for
|
||||
* debugging purposes.
|
||||
* </p>
|
||||
* @param int $limit [optional] <p>
|
||||
* Used in conjunction with <b>type</b> set to cachedump to limit the number of entries to dump.
|
||||
* </p>
|
||||
* @return array|false Returns an associative array of server statistics or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function getStats ($type = null, $slabid = null, $limit = 100) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.0.0)<br/>
|
||||
* Get statistics from all servers in pool
|
||||
* @link https://php.net/manual/en/memcache.getextendedstats.php
|
||||
* @param string $type [optional] <p>The type of statistics to fetch. Valid values are {reset, malloc, maps, cachedump, slabs, items, sizes}. According to the memcached protocol spec these additional arguments "are subject to change for the convenience of memcache developers".</p>
|
||||
* @param int $slabid [optional] <p>
|
||||
* Used in conjunction with <b>type</b> set to
|
||||
* cachedump to identify the slab to dump from. The cachedump
|
||||
* command ties up the server and is strictly to be used for
|
||||
* debugging purposes.
|
||||
* </p>
|
||||
* @param int $limit Used in conjunction with type set to cachedump to limit the number of entries to dump.
|
||||
* @return array|false Returns a two-dimensional associative array of server statistics or <b>FALSE</b>
|
||||
* Returns a two-dimensional associative array of server statistics or <b>FALSE</b>
|
||||
* on failure.
|
||||
*/
|
||||
public function getExtendedStats ($type = null, $slabid = null, $limit = 100) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 2.0.0)<br/>
|
||||
* Enable automatic compression of large values
|
||||
* @link https://php.net/manual/en/memcache.setcompressthreshold.php
|
||||
* @param int $thresold <p>Controls the minimum value length before attempting to compress automatically.</p>
|
||||
* @param float $min_saving [optional] <p>Specifies the minimum amount of savings to actually store the value compressed. The supplied value must be between 0 and 1. Default value is 0.2 giving a minimum 20% compression savings.</p>
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function setCompressThreshold ($thresold, $min_saving = 0.2) {}
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Increment item's value
|
||||
* @link https://php.net/manual/en/memcache.increment.php
|
||||
* @param $key string Key of the item to increment.
|
||||
* @param $value int [optional] increment the item by <b>value</b>
|
||||
* @return int|false Returns new items value on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function increment ($key, $value = 1) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Decrement item's value
|
||||
* @link https://php.net/manual/en/memcache.decrement.php
|
||||
* @param $key string Key of the item do decrement.
|
||||
* @param $value int Decrement the item by <b>value</b>.
|
||||
* @return int|false Returns item's new value on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function decrement ($key, $value = 1) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.4.0)<br/>
|
||||
* Close memcached server connection
|
||||
* @link https://php.net/manual/en/memcache.close.php
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function close () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 1.0.0)<br/>
|
||||
* Flush all existing items at the server
|
||||
* @link https://php.net/manual/en/memcache.flush.php
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function flush () {}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a connection to a set of memcache servers.
|
||||
* @link https://php.net/manual/en/class.memcache.php
|
||||
*/
|
||||
class Memcache extends MemcachePool {
|
||||
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.4.0)<br/>
|
||||
* Open memcached server persistent connection
|
||||
* @link https://php.net/manual/en/memcache.pconnect.php
|
||||
* @param string $host <p>
|
||||
* Point to the host where memcached is listening for connections. This parameter
|
||||
* may also specify other transports like unix:///path/to/memcached.sock
|
||||
* to use UNIX domain sockets, in this case <i>port</i> must also
|
||||
* be set to 0.
|
||||
* </p>
|
||||
* @param int $port [optional] <p>
|
||||
* Point to the port where memcached is listening for connections. Set this
|
||||
* parameter to 0 when using UNIX domain sockets.
|
||||
* </p>
|
||||
* @param int $timeout [optional] <p>
|
||||
* Value in seconds which will be used for connecting to the daemon. Think
|
||||
* twice before changing the default value of 1 second - you can lose all
|
||||
* the advantages of caching if your connection is too slow.
|
||||
* </p>
|
||||
* @return mixed a Memcache object or <b>FALSE</b> on failure.
|
||||
*/
|
||||
public function pconnect ($host, $port, $timeout = 1) {}
|
||||
}
|
||||
|
||||
// string $host [, int $port [, int $timeout ]]
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)</br>
|
||||
* Memcache::connect — Open memcached server connection
|
||||
* @link https://php.net/manual/en/memcache.connect.php
|
||||
* @param string $host <p>
|
||||
* Point to the host where memcached is listening for connections.
|
||||
* This parameter may also specify other transports like
|
||||
* unix:///path/to/memcached.sock to use UNIX domain sockets,
|
||||
* in this case port must also be set to 0.
|
||||
* </p>
|
||||
* @param int $port [optional] <p>
|
||||
* Point to the port where memcached is listening for connections.
|
||||
* Set this parameter to 0 when using UNIX domain sockets.
|
||||
* Note: port defaults to memcache.default_port if not specified.
|
||||
* For this reason it is wise to specify the port explicitly in this method call.
|
||||
* </p>
|
||||
* @param int $timeout [optional] <p>
|
||||
* Value in seconds which will be used for connecting to the daemon.
|
||||
* </p>
|
||||
* @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure.
|
||||
*/
|
||||
function memcache_connect ($host, $port, $timeout = 1) {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.4.0)
|
||||
* Memcache::pconnect — Open memcached server persistent connection
|
||||
*
|
||||
* @link https://php.net/manual/en/memcache.pconnect.php#example-5242
|
||||
* @param $host
|
||||
* @param null $port
|
||||
* @param int $timeout
|
||||
* @return Memcache
|
||||
*/
|
||||
function memcache_pconnect ($host, $port=null, $timeout=1) {}
|
||||
|
||||
function memcache_add_server () {}
|
||||
|
||||
function memcache_set_server_params () {}
|
||||
|
||||
function memcache_set_failure_callback () {}
|
||||
|
||||
function memcache_get_server_status () {}
|
||||
|
||||
function memcache_get_version () {}
|
||||
|
||||
function memcache_add () {}
|
||||
|
||||
function memcache_set () {}
|
||||
|
||||
function memcache_replace () {}
|
||||
|
||||
function memcache_cas () {}
|
||||
|
||||
function memcache_append () {}
|
||||
|
||||
function memcache_prepend () {}
|
||||
|
||||
function memcache_get () {}
|
||||
|
||||
function memcache_delete () {}
|
||||
|
||||
/**
|
||||
* (PECL memcache >= 0.2.0)<br/>
|
||||
* Turn debug output on/off
|
||||
* @link https://php.net/manual/en/function.memcache-debug.php
|
||||
* @param bool $on_off <p>
|
||||
* Turns debug output on if equals to <b>TRUE</b>.
|
||||
* Turns debug output off if equals to <b>FALSE</b>.
|
||||
* </p>
|
||||
* @return bool <b>TRUE</b> if PHP was built with --enable-debug option, otherwise
|
||||
* returns <b>FALSE</b>.
|
||||
*/
|
||||
function memcache_debug ($on_off) {}
|
||||
|
||||
function memcache_get_stats () {}
|
||||
|
||||
function memcache_get_extended_stats () {}
|
||||
|
||||
function memcache_set_compress_threshold () {}
|
||||
|
||||
function memcache_increment () {}
|
||||
|
||||
function memcache_decrement () {}
|
||||
|
||||
function memcache_close () {}
|
||||
|
||||
function memcache_flush () {}
|
||||
|
||||
define ('MEMCACHE_COMPRESSED', 2);
|
||||
define ('MEMCACHE_USER1', 65536);
|
||||
define ('MEMCACHE_USER2', 131072);
|
||||
define ('MEMCACHE_USER3', 262144);
|
||||
define ('MEMCACHE_USER4', 524288);
|
||||
define ('MEMCACHE_HAVE_SESSION', 1);
|
||||
|
||||
// End of memcache v.3.0.8
|
||||
?>
|
||||
1308
.phan/internal_stubs/memcached.phan_php
Normal file
1308
.phan/internal_stubs/memcached.phan_php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ php:
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
@@ -12,13 +13,6 @@ notifications:
|
||||
email:
|
||||
on_success: never
|
||||
on_failure: always
|
||||
hipchat:
|
||||
# hipchat_api@grav
|
||||
rooms:
|
||||
- secure: "bqO0wM1B7bJnQw2fuhquSXEqI9gw6WmFytIh9sEWXzbYTzTUP5t0PcKOd3FT2BNMRaDxPJLVl+vG/oqmqDUBkEmOGcG504IQjeNzZqnMz0tXQMIcCc22Las9tFfc4Jf6RVi/qGomFtHGE9Wgii+TAN4zqZaufbNjwd8SyjO0+W8="
|
||||
template:
|
||||
- '%{repository}#%{build_number} (%{branch}): Travis Job Finished [%{duration}] (<a href="%{build_url}">Details</a>)'
|
||||
format: html
|
||||
slack:
|
||||
secure: dowksPsxxCxGKT6nis5hUgkp6+ZDAhoqzQHF9rJnx4hx0iEygPhVBs7pKl9yL2jubYJoLs+EXwE7z1dYgDAEJh4BnfrCokCMLpFGcxVxQC/HeAUdSQ2/RtdBYR5PRT75ScaFpqM/SfXXZVtnwVXAw9Z+JC6BjQ9vmn23m51Jw4k=
|
||||
env:
|
||||
|
||||
565
CHANGELOG.md
565
CHANGELOG.md
@@ -1,19 +1,566 @@
|
||||
# v1.7.0-rc.8
|
||||
## 03/19/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added `MediaTrait::freeMedia()` method to free media (and memory)
|
||||
* Added `Folder::hasChildren()` method to determine if a folder has child folders
|
||||
1. [](#improved)
|
||||
* Save memory when updating large flex indexes
|
||||
* Better `Content-Encoding` handling in Apache when content compression is disabled [#2619](https://github.com/getgrav/grav/issues/2619)
|
||||
1. [](#bugfix)
|
||||
* Fixed creating new `Flex User` when folder storage has been selected
|
||||
* Fixed some bugs in Flex root page methods
|
||||
* Fixed bad default redirect code in `ControllerResponseTrait::createRedirectResponse()`
|
||||
* Fixed issue with PHP `HTTP_X_HTTP_METHOD_OVERRIDE` [#2847](https://github.com/getgrav/grav/issues/2847)
|
||||
* Fixed numeric usernames not working in `Flex Users`
|
||||
* Implemented missing Flex `$page->move()` method
|
||||
|
||||
# v1.7.0-rc.7
|
||||
## 03/05/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added `Session::regenerateId()` method to properly prevent session fixation issues
|
||||
* Added configuration option `system.strict_mode.blueprint_compat` to maintain old `validation: strict` behavior [#1273](https://github.com/getgrav/grav/issues/1273)
|
||||
1. [](#improved)
|
||||
* Improved Flex events
|
||||
* Updated CLI commands to use the new methods to initialize Grav
|
||||
1. [](#bugfix)
|
||||
* Fixed Flex Pages having broken `isFirst()`, `isLast()`, `prevSibling()`, `nextSibling()` and `adjacentSibling()`
|
||||
* Fixed broken ordering sometimes when saving/moving visible `Flex Page` [#2837](https://github.com/getgrav/grav/issues/2837)
|
||||
* Fixed ordering being lost when saving modular `Flex Page`
|
||||
* Fixed `validation: strict` not working in blueprints (see `system.strict_mode.blueprint_compat` setting) [#1273](https://github.com/getgrav/grav/issues/1273)
|
||||
* Fixed `Blueprint::extend()` and `Blueprint::embed()` not initializing dynamic properties
|
||||
* Fixed fatal error on storing flex flash using new object without a key
|
||||
* Regression: Fixed unchecking toggleable having no effect in Flex forms
|
||||
* Fixed changing page template in Flex Pages [#2828](https://github.com/getgrav/grav/issues/2828)
|
||||
|
||||
# v1.7.0-rc.6
|
||||
## 02/11/2020
|
||||
|
||||
1. [](#new)
|
||||
* Plugins & Themes: Call `$plugin->autoload()` and `$theme->autoload()` automatically when object gets initialized
|
||||
* CLI: Added `$grav->initializeCli()` method
|
||||
* Flex Directory: Implemented customizable configuration
|
||||
* Flex Storages: Added support for renaming directory entries
|
||||
1. [](#improved)
|
||||
* Vendor updates to latest
|
||||
1. [](#bugfix)
|
||||
* Regression: Fixed fatal error in blueprints [#2811](https://github.com/getgrav/grav/issues/2811)
|
||||
* Regression: Fixed bad method call in FlexDirectory::getAuthorizeRule()
|
||||
* Regression: Fixed fatal error in admin if the site has custom permissions in `onAdminRegisterPermissions`
|
||||
* Regression: Fixed flex user index with folder storage
|
||||
* Regression: Fixed fatal error in `bin/plugin` command
|
||||
* Fixed `FlexObject::triggerEvent()` not emitting events [#2816](https://github.com/getgrav/grav/issues/2816)
|
||||
* Grav 1.7: Fixed saving Flex configuration with ignored values becoming null
|
||||
* Grav 1.7: Fixed `bin/plugin` initialization
|
||||
* Grav 1.7: Fixed Flex Page cache key not taking account active language
|
||||
|
||||
# v1.7.0-rc.5
|
||||
## 02/03/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Regression: Flex not working in PHP 7.2 or older
|
||||
* Fixed creating first user from admin not clearing Flex User directory cache [#2809](https://github.com/getgrav/grav/issues/2809)
|
||||
* Fixed Flex Pages allowing root page to be deleted
|
||||
|
||||
# v1.7.0-rc.4
|
||||
## 02/03/2020
|
||||
|
||||
1. [](#new)
|
||||
* _POTENTIAL BREAKING CHANGE:_ Upgraded Parsedown to 1.7 for Parsedown-Extra 0.8. Plugins that extend Parsedown may need a fix to render as HTML
|
||||
* Added `$grav['flex']` to access all registered Flex Directories
|
||||
* Added `$grav->dispatchEvent()` method for PSR-14 events
|
||||
* Added `FlexRegisterEvent` which triggers when `$grav['flex']` is being accessed the first time
|
||||
* Added Flex cache configuration options
|
||||
* Added `PluginsLoadedEvent` which triggers after plugins have been loaded but not yet initialized
|
||||
* Added `SessionStartEvent` which triggers when session is started
|
||||
* Added `PermissionsRegisterEvent` which triggers when `$grav['permissions']` is being accessed the first time
|
||||
* Added support for Flex Directory specific configuration
|
||||
* Added support for more advanced ACL
|
||||
* Added `flatten_array` filter to form field validation
|
||||
* Added support for `security@: or: [admin.super, admin.pages]` in blueprints (nested AND/OR mode support)
|
||||
1. [](#improved)
|
||||
* Blueprint validation: Added `validate: value_type: bool|int|float|string|trim` to `array` to filter all the values inside the array
|
||||
* Twig `url()` takes now third parameter (`true`) to return URL on non-existing file instead of returning false
|
||||
1. [](#bugfix)
|
||||
* Grav 1.7: Fixed blueprint loading issues [#2782](https://github.com/getgrav/grav/issues/2782)
|
||||
* Fixed PHP 7.4 compatibility issue with `Stream`
|
||||
* Fixed new `Flex Users` being stored with wrong filename, login issues [#2785](https://github.com/getgrav/grav/issues/2785)
|
||||
* Fixed `ignore_empty: true` not removing empty values in blueprint filtering
|
||||
* Fixed `{{ false|string }}` twig to return '0' instead of ''
|
||||
* Fixed twig `url()` failing if stream has extra slash in it (e.g. `user:///data`)
|
||||
* Fixed `Blueprint::filter()` returning null instead of array if there is nothing to return
|
||||
* Fixed `Cannot use a scalar value as an array` error in `Utils::arrayUnflattenDotNotation()`, ignore nested structure instead
|
||||
* Fixed `Route` instance in multi-site setups
|
||||
* Fixed `system.translations: false` breaking `Inflector` methods
|
||||
* Fixed filtering ignored (eg. `security@: admin.super`) fields causing `Flex Objects` to lose data on save
|
||||
* Grav 1.7: Fixed `Flex Pages` unserialize issues if Flex-Objects Plugin has not been installed
|
||||
* Grav 1.7: Require Flex-Objects Plugin to edit Flex Accounts
|
||||
* Grav 1.7: Fixed bad result on testing `isPage()` when using Flex Pages
|
||||
|
||||
# v1.7.0-rc.3
|
||||
## 01/02/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added root page support for `Flex Pages`
|
||||
1. [](#improved)
|
||||
* Twig filter `|yaml_serialize`: added support for `JsonSerializable` objects and other array-like objects
|
||||
* Added support for returning Flex Page specific permissions for admin and testing
|
||||
* Updated copyright dates to `2020`
|
||||
* Various vendor updates
|
||||
1. [](#bugfix)
|
||||
* Grav 1.7: Fixed error on page initialization [#2753](https://github.com/getgrav/grav/issues/2753)
|
||||
* Fixed checking ACL for another user (who is not currently logged in) in a Flex Object or Directory
|
||||
* Fixed bug in Windows where `Filesystem::dirname()` returns backslashes
|
||||
* Fixed Flex object issues in Windows [#2773](https://github.com/getgrav/grav/issues/2773)
|
||||
|
||||
# v1.7.0-rc.2
|
||||
## 12/04/2019
|
||||
|
||||
1. [](#new)
|
||||
* Updated Symfony Components to 4.4
|
||||
* Added support for page specific CRUD permissions (`Flex Pages` only)
|
||||
* Added new `-r <job-id>` option for Scheduler CLI command to force-run a job [#2720](https://github.com/getgrav/grav/issues/2720)
|
||||
* Added `Utils::isAssoc()` and `Utils::isNegative()` helper methods
|
||||
* Changed `UserInterface::authorize()` to return `null` having the same meaning as `false` if access is denied because of no matching rule
|
||||
* Changed `FlexAuthorizeInterface::isAuthorized()` to return `null` having the same meaning as `false` if access is denied because of no matching rule
|
||||
* Moved all Flex type classes under `Grav\Common\Flex`
|
||||
* DEPRECATED `Grav\Common\User\Group` in favor of `$grav['user_groups']`, which contains Flex UserGroup collection
|
||||
* DEPRECATED `$page->modular()` in favor of `$page->isModule()` for better readability
|
||||
* Fixed phpstan issues in all code up to level 3
|
||||
1. [](#improved)
|
||||
* Improved twig `|array` filter to work with iterators and objects with `toArray()` method
|
||||
* Updated Flex `SimpleStorage` code to feature match the other storages
|
||||
* Improved user and group ACL to support deny permissions (`Flex Users` only)
|
||||
* Improved twig `authorize()` function to work better with nested rule parameters
|
||||
* Output the current username that Scheduler is using if crontab not setup
|
||||
* Translations: rename MODULAR to MODULE everywhere
|
||||
* Optimized `Flex Pages` collection filtering
|
||||
* Frontend optimizations for `Flex Pages`
|
||||
1. [](#bugfix)
|
||||
* Regression: Fixed Grav update bug [#2722](https://github.com/getgrav/grav/issues/2722)
|
||||
* Fixed fatal error when calling `{{ grav.undefined }}`
|
||||
* Grav 1.7: Reverted `$object->getStorageKey()` interface as it was not a good idea, added `getMasterKey()` for pages
|
||||
* Grav 1.7: Fixed logged in user being able to delete his own account from admin account manager
|
||||
|
||||
# v1.7.0-rc.1
|
||||
## 11/06/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `Flex Pages` to Grav core and removed Flex Objects plugin dependency
|
||||
* Added `Utils::simpleTemplate()` method for very simple variable templating
|
||||
* Added `array_diff()` twig function
|
||||
* Added `template_from_string()` twig function
|
||||
* Updated Symfony Components to 4.3
|
||||
1. [](#improved)
|
||||
* Improved `Scheduler` cron command check and more useful CLI information
|
||||
* Improved `Flex Users`: obey blueprints and allow Flex to be used in admin only
|
||||
* Improved `Flex` to support custom site template paths
|
||||
* Changed Twig `{% cache %}` tag to not need unique key, and `lifetime` is now optional
|
||||
* Added mime support for file formatters
|
||||
* Updated built-in `composer.phar` to latest `1.9.0`
|
||||
* Updated vendor libraries
|
||||
* Use `Symfony EventDispatcher` directly and not rockettheme/toolbox wrapper
|
||||
1. [](#bugfix)
|
||||
* Fixed exception caused by missing template type based on `Accept:` header [#2705](https://github.com/getgrav/grav/issues/2705)
|
||||
* Fixed `Page::untranslatedLanguages()` not being symmetrical to `Page::translatedLanguages()`
|
||||
* Fixed `Flex Pages` not calling `onPageProcessed` event when cached
|
||||
* Fixed phpstan issues in Framework up to level 7
|
||||
* Fixed issue with duplicate configuration settings in Flex Directory
|
||||
* Fixed fatal error if there are numeric folders in `Flex Pages`
|
||||
* Fixed error on missing `Flex` templates in if `Flex Objects` plugin isn't installed
|
||||
* Fixed `PageTranslateTrait::getAllLanguages()` and `getAllLanguages()` to include default language
|
||||
* Fixed multi-language saving issues with default language in `Flex Pages`
|
||||
* Selfupgrade CLI: Fixed broken selfupgrade assets reference [#2681](https://github.com/getgrav/grav/issues/2681)
|
||||
* Grav 1.7: Fixed PHP 7.1 compatibility issues
|
||||
* Grav 1.7: Fixed fatal error in multi-site setups
|
||||
* Grav 1.7: Fixed `Flex Pages` routing if using translated slugs or `system.hide_in_urls` setting
|
||||
* Grav 1.7: Fixed bug where Flex index file couldn't be disabled
|
||||
|
||||
# v1.7.0-beta.10
|
||||
## 10/03/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Flex: Removed extra exists check when creating object (messes up "non-existing" pages)
|
||||
* Support customizable null character replacement in `CSVFormatter::decode()`
|
||||
1. [](#bugfix)
|
||||
* Fixed wrong Grav param separator when using `Route` class
|
||||
* Fixed Flex User Avatar not fully backwards compatible with old user
|
||||
* Grav 1.7: Fixed prev/next page missing pages if pagination was turned on in page header
|
||||
* Grav 1.7: Reverted setting language for every page during initialization
|
||||
* Grav 1.7: Fixed numeric language inconsistencies
|
||||
|
||||
# v1.7.0-beta.9
|
||||
## 09/26/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added a new `{% cache %}` Twig tag eliminating need for `twigcache` extension.
|
||||
1. [](#improved)
|
||||
* Improved blueprint initialization in Flex Objects (fixes content aware fields)
|
||||
* Improved Flex FolderStorage class to better hide storage specific logic
|
||||
* Exception will output a badly formatted line in `CsvFormatter::decode()`
|
||||
1. [](#bugfix)
|
||||
* Fixed error when activating Flex Accounts in GRAV system configuration (PHP 7.1)
|
||||
* Fixed Grav parameter handling in `RouteFactory::createFromString()`
|
||||
|
||||
# v1.7.0-beta.8
|
||||
## 09/19/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added new `Security::sanitizeSVG()` function
|
||||
* Backwards compatibility break: `FlexStorageInterface::getStoragePath()` and `getMediaPath()` can now return null
|
||||
1. [](#improved)
|
||||
* Several FlexObject loading improvements
|
||||
* Added `bin/grav page-system-validator [-r|--record] [-c|--check]` to test Flex Pages
|
||||
* Improved language support for `Route` class
|
||||
1. [](#bugfix)
|
||||
* Regression: Fixed language fallback
|
||||
* Regression: Fixed translations when language code is used for non-language purposes
|
||||
* Regression: Allow SVG avatar images for users
|
||||
* Fixed error in `Session::getFlashObject()` if Flex Form is being used
|
||||
* Fixed broken Twig `dump()`
|
||||
* Fixed `Page::modular()` and `Page::modularTwig()` returning `null` for folders and other non-initialized pages
|
||||
* Fixed 404 error when you click to non-routable menu item with children: redirect to the first child instead
|
||||
* Fixed wrong `Pages::dispatch()` calls (with redirect) when we really meant to call `Pages::find()`
|
||||
* Fixed avatars not being displayed with flex users [#2431](https://github.com/getgrav/grav/issues/2431)
|
||||
* Fixed initial Flex Object state when creating a new objects in a form
|
||||
|
||||
# v1.7.0-beta.7
|
||||
## 08/30/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Improved language support
|
||||
1. [](#bugfix)
|
||||
* `FlexForm`: Fixed some compatibility issues with Form plugin
|
||||
|
||||
# v1.7.0-beta.6
|
||||
## 08/29/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added experimental support for `Flex Pages` (**Flex Objects** plugin required)
|
||||
1. [](#improved)
|
||||
* Improved `bin/grav yamllinter` CLI command by adding an option to find YAML Linting issues from the whole site or custom folder
|
||||
* Added support for not instantiating pages, useful to speed up tasks
|
||||
* Greatly improved speed of loading Flex collections
|
||||
1. [](#bugfix)
|
||||
* Fixed `$page->summary()` always striping HTML tags if the summary was set by `$page->setSummary()`
|
||||
* Fixed `Flex->getObject()` when using Flex Key
|
||||
* Grav 1.7: Fixed enabling PHP Debug Bar causes fatal error in Gantry [#2634](https://github.com/getgrav/grav/issues/2634)
|
||||
* Grav 1.7: Fixed broken taxonomies [#2633](https://github.com/getgrav/grav/issues/2633)
|
||||
* Grav 1.7: Fixed unpublished blog posts being displayed on the front-end [#2650](https://github.com/getgrav/grav/issues/2650)
|
||||
|
||||
# v1.7.0-beta.5
|
||||
## 08/11/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added a new `bin/grav server` CLI command to easily run Symfony or PHP built-in webservers
|
||||
* Added `hasFlexFeature()` method to test if `FlexObject` or `FlexCollection` implements a given feature
|
||||
* Added `getFlexFeatures()` method to return all features that `FlexObject` or `FlexCollection` implements
|
||||
* DEPRECATED `FlexDirectory::update()` and `FlexDirectory::remove()`
|
||||
* Added `FlexStorage::getMetaData()` to get updated object meta information for listed keys
|
||||
* Added `Language::getPageExtensions()` to get full list of supported page language extensions
|
||||
* Added `$grav->close()` method to properly terminate the request with a response
|
||||
* Added `Pages::getCollection()` method
|
||||
1. [](#improved)
|
||||
* Better support for Symfony local server `symfony server:start`
|
||||
* Make `Route` objects immutable
|
||||
* `FlexDirectory::getObject()` can now be called without any parameters to create a new object
|
||||
* Flex objects no longer return temporary key if they do not have one; empty key is returned instead
|
||||
* Updated vendor libraries
|
||||
* Moved `collection()` and `evaluate()` logic from `Page` class into `Pages` class
|
||||
1. [](#bugfix)
|
||||
* Fixed `Form` not to use deleted flash object until the end of the request fixing issues with reset
|
||||
* Fixed `FlexForm` to allow multiple form instances with non-existing objects
|
||||
* Fixed `FlexObject` search by using `key`
|
||||
* Grav 1.7: Fixed clockwork messages with arrays and objects
|
||||
|
||||
# v1.7.0-beta.4
|
||||
## 07/01/2019
|
||||
|
||||
1. [](#new)
|
||||
* Updated with Grav 1.6.12 features, improvements & fixes
|
||||
* Added new configuration option `system.debugger.censored` to hide potentially sensitive information
|
||||
* Added new configuration option `system.languages.include_default_lang_file_extension` to keep default language in `.md` files if set to `false`
|
||||
* Added configuration option to set fallback content languages individually for every language
|
||||
1. [](#improved)
|
||||
* Updated Vendor libraries
|
||||
1. [](#bugfix)
|
||||
* Fixed `.md` page to be assigned to the default language and to be listed in translated/untranslated page list
|
||||
* Fixed `Language::getFallbackPageExtensions()` to fall back only to default language instead of going through all languages
|
||||
* Fixed `Language::getFallbackPageExtensions()` returning wrong file extensions when passing custom page extension
|
||||
|
||||
# v1.7.0-beta.3
|
||||
## 06/24/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed Clockwork on Windows machines
|
||||
* Fixed parent field issues on Windows machines
|
||||
* Fixed unreliable Clockwork calls in sub-folders
|
||||
|
||||
# v1.7.0-beta.2
|
||||
## 06/21/2019
|
||||
|
||||
1. [](#new)
|
||||
* Updated with Grav 1.6.11 fixes
|
||||
1. [](#improved)
|
||||
* Updated the Clockwork text
|
||||
|
||||
# v1.7.0-beta.1
|
||||
## 06/14/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added support for [Clockwork](https://underground.works/clockwork) developer tools (now default debugger)
|
||||
* Added support for [Tideways XHProf](https://github.com/tideways/php-xhprof-extension) PHP Extension for profiling method calls
|
||||
* Added Twig profiling for Clockwork debugger
|
||||
* Added support for Twig 2.11 (compatible with Twig 1.40+)
|
||||
* Optimization: Initialize debugbar only after the configuration has been loaded
|
||||
* Optimization: Combine some early Grav processors into a single one
|
||||
|
||||
# v1.6.23
|
||||
## 03/19/2020
|
||||
|
||||
1. [](#new)
|
||||
* Moved `Parsedown` 1.6 and `ParsedownExtra` 0.7 into `Grav\Framework\Parsedown` to allow fixes
|
||||
1. [](#improved)
|
||||
* Upgraded `jQuery` to latest 3.4.1 version [#2859](https://github.com/getgrav/grav/issues/2859)
|
||||
1. [](#bugfix)
|
||||
* Fixed PHP 7.4 issue in ParsedownExtra [#2832](https://github.com/getgrav/grav/issues/2832)
|
||||
* Fix for [user reported](https://twitter.com/OriginalSicksec) CVE path-based open redirect
|
||||
* Fix for `stream_set_option` error with PHP 7.4 via Toolbox#28 [#2850](https://github.com/getgrav/grav/issues/2850)
|
||||
|
||||
# v1.6.22
|
||||
## 03/05/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added `Pages::reset()` method
|
||||
1. [](#improved)
|
||||
* Updated Negotiation library to address issues [#2513](https://github.com/getgrav/grav/issues/2513)
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with search plugins not being able to switch between page translations
|
||||
* Fixed issues with `Pages::baseRoute()` not picking up active language reliably
|
||||
* Reverted `validation: strict` fix as it breaks sites, see [#1273](https://github.com/getgrav/grav/issues/1273)
|
||||
|
||||
# v1.6.21
|
||||
## 02/11/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added `ConsoleCommand::setLanguage()` method to set language to be used from CLI
|
||||
* Added `ConsoleCommand::initializeGrav()` method to properly set up Grav instance to be used from CLI
|
||||
* Added `ConsoleCommand::initializePlugins()`method to properly set up all plugins to be used from CLI
|
||||
* Added `ConsoleCommand::initializeThemes()`method to properly set up current theme to be used from CLI
|
||||
* Added `ConsoleCommand::initializePages()` method to properly set up pages to be used from CLI
|
||||
1. [](#improved)
|
||||
* Vendor updates
|
||||
1. [](#bugfix)
|
||||
* Fixed `bin/plugin` CLI calling `$themes->init()` way too early (removed it, use above methods instead)
|
||||
* Fixed call to `$grav['page']` crashing CLI
|
||||
* Fixed encoding problems when PHP INI setting `default_charset` is not `utf-8` [#2154](https://github.com/getgrav/grav/issues/2154)
|
||||
|
||||
# v1.6.20
|
||||
## 02/03/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed incorrect routing caused by `str_replace()` in `Uri::init()` [#2754](https://github.com/getgrav/grav/issues/2754)
|
||||
* Fixed session cookie is being set twice in the HTTP header [#2745](https://github.com/getgrav/grav/issues/2745)
|
||||
* Fixed session not restarting if user was invalid (downgrading from Grav 1.7)
|
||||
* Fixed filesystem iterator calls with non-existing folders
|
||||
* Fixed `checkbox` field not being saved, requires also Form v4.0.2 [#1225](https://github.com/getgrav/grav/issues/1225)
|
||||
* Fixed `validation: strict` not working in blueprints [#1273](https://github.com/getgrav/grav/issues/1273)
|
||||
* Fixed `Data::filter()` removing empty fields (such as empty list) by default [#2805](https://github.com/getgrav/grav/issues/2805)
|
||||
* Fixed fatal error with non-integer page param value [#2803](https://github.com/getgrav/grav/issues/2803)
|
||||
* Fixed `Assets::addInlineJs()` parameter type mismatch between v1.5 and v1.6 [#2659](https://github.com/getgrav/grav/issues/2659)
|
||||
* Fixed `site.metadata` saving issues [#2615](https://github.com/getgrav/grav/issues/2615)
|
||||
|
||||
# v1.6.19
|
||||
## 12/04/2019
|
||||
|
||||
1. [](#new)
|
||||
* Catch PHP 7.4 deprecation messages and report them in debugbar instead of throwing fatal error
|
||||
1. [](#bugfix)
|
||||
* Fixed fatal error when calling `{{ grav.undefined }}`
|
||||
* Fixed multiple issues when there are no pages in the site
|
||||
* PHP 7.4 fix for [#2750](https://github.com/getgrav/grav/issues/2750)
|
||||
|
||||
# v1.6.18
|
||||
## 12/02/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* PHP 7.4 fix in `Pages::buildSort()`
|
||||
* Updated vendor libraries for PHP 7.4 fixes in Twig and other libraries
|
||||
* Fixed fatal error when `$page->id()` is null [#2731](https://github.com/getgrav/grav/pull/2731)
|
||||
* Fixed cache conflicts on pages with no set id
|
||||
* Fix rewrite rule for for `lighttpd` default config [#721](https://github.com/getgrav/grav/pull/2721)
|
||||
|
||||
# v1.6.17
|
||||
## 11/06/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added working ETag (304 Not Modified) support based on the final rendered HTML
|
||||
1. [](#improved)
|
||||
* Safer file handling + customizable null char replacement in `CsvFormatter::decode()`
|
||||
* Change of Behavior: `Inflector::hyphenize` will now automatically trim dashes at beginning and end of a string.
|
||||
* Change in Behavior for `Folder::all()` so no longer fails if trying to copy non-existent dot file [#2581](https://github.com/getgrav/grav/pull/2581)
|
||||
* renamed composer `test-plugins` script to `phpstan-plugins` to be more explicit [#2637](https://github.com/getgrav/grav/pull/2637)
|
||||
1. [](#bugfix)
|
||||
* Fixed PHP 7.1 bug in FlexMedia
|
||||
* Fix cache image generation when using cropResize [#2639](https://github.com/getgrav/grav/pull/2639)
|
||||
* Fix `array_merge()` exception with non-array page header metadata [#2701](https://github.com/getgrav/grav/pull/2701)
|
||||
|
||||
# v1.6.16
|
||||
## 09/19/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed Flex user creation if file storage is being used [#2444](https://github.com/getgrav/grav/issues/2444)
|
||||
* Fixed `Badly encoded JSON data` warning when uploading files [#2663](https://github.com/getgrav/grav/issues/2663)
|
||||
|
||||
# v1.6.15
|
||||
## 08/20/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Improved robots.txt [#2632](https://github.com/getgrav/grav/issues/2632)
|
||||
1. [](#bugfix)
|
||||
* Fixed broken markdown Twig tag [#2635](https://github.com/getgrav/grav/issues/2635)
|
||||
* Force Symfony 4.2 in Grav 1.6 to remove a bunch of deprecated messages
|
||||
|
||||
# v1.6.14
|
||||
## 08/18/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* Actually include fix for `system\router.php` [#2627](https://github.com/getgrav/grav/issues/2627)
|
||||
|
||||
# v1.6.13
|
||||
## 08/16/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* Regression fix for `system\router.php` [#2627](https://github.com/getgrav/grav/issues/2627)
|
||||
|
||||
# v1.6.12
|
||||
## 08/14/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added support for custom `FormFlash` save locations
|
||||
* Added a new `Utils::arrayLower()` method for lowercasing arrays
|
||||
* Support new GRAV_BASEDIR environment variable [#2541](https://github.com/getgrav/grav/pull/2541)
|
||||
* Allow users to override plugin handler priorities [#2165](https://github.com/getgrav/grav/pull/2165)
|
||||
1. [](#improved)
|
||||
* Use new `Utils::getSupportedPageTypes()` to enforce `html,htm` at the front of the list [#2531](https://github.com/getgrav/grav/issues/2531)
|
||||
* Updated vendor libraries
|
||||
* Markdown filter is now page-aware so that it works with modular references [admin#1731](https://github.com/getgrav/grav-plugin-admin/issues/1731)
|
||||
* Check of `GRAV_USER_INSTANCE` constant is already defined [#2621](https://github.com/getgrav/grav/pull/2621)
|
||||
1. [](#bugfix)
|
||||
* Fixed some potential issues when `$grav['user']` is not set
|
||||
* Fixed error when calling `Media::add($name, null)`
|
||||
* Fixed `url()` returning wrong path if using stream with grav root path in it, eg: `user-data://shop` when Grav is in `/shop`
|
||||
* Fixed `url()` not returning a path to non-existing file (`user-data://shop` => `/user/data/shop`) if it is set to fail gracefully
|
||||
* Fixed `url()` returning false on unknown streams, such as `ftp://domain.com`, they should be treated as external URL
|
||||
* Fixed Flex User to have permissions to save and delete his own user
|
||||
* Fixed new Flex User creation not being possible because of username could not be given
|
||||
* Fixed fatal error 'Expiration date must be an integer, a DateInterval or null, "double" given' [#2529](https://github.com/getgrav/grav/issues/2529)
|
||||
* Fixed non-existing Flex object having a bad media folder
|
||||
* Fixed collections using `page@.self:` should allow modular pages if requested
|
||||
* Fixed an error when trying to delete a file from non-existing Flex Object
|
||||
* Fixed `FlexObject::exists()` failing sometimes just after the object has been saved
|
||||
* Fixed CSV formatter not encoding strings with `"` and `,` properly
|
||||
* Fixed var order in `Validation.php` [#2610](https://github.com/getgrav/grav/issues/2610)
|
||||
|
||||
# v1.6.11
|
||||
## 06/21/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `FormTrait::getAllFlashes()` method to get all the available form flash objects for the form
|
||||
* Added creation and update timestamps to `FormFlash` objects
|
||||
1. [](#improved)
|
||||
* Added `FormFlashInterface`, changed constructor to take `$config` array
|
||||
1. [](#bugfix)
|
||||
* Fixed error in `ImageMedium::url()` if the image cache folder does not exist
|
||||
* Fixed empty form flash name after file upload or form state update
|
||||
* Fixed a bug in `Route::withParam()` method
|
||||
* Fixed issue with `FormFlash` objects when there is no session initialized
|
||||
|
||||
# v1.6.10
|
||||
## 06/14/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Added **page blueprints** to `YamlLinter` CLI and Admin reports
|
||||
* Removed `Gitter` and `Slack` [#2502](https://github.com/getgrav/grav/issues/2502)
|
||||
* Optimizations for Plugin/Theme loading
|
||||
* Generalized markdown classes so they can be used outside of `Page` scope with a custom `Excerpts` class instance
|
||||
* Change minimal port number to 0 (unix socket) [#2452](https://github.com/getgrav/grav/issues/2452)
|
||||
1. [](#bugfix)
|
||||
* Force question to install demo content in theme update [#2493](https://github.com/getgrav/grav/issues/2493)
|
||||
* Fixed GPM errors from blueprints not being logged [#2505](https://github.com/getgrav/grav/issues/2505)
|
||||
* Don't error when IP is invalid [#2507](https://github.com/getgrav/grav/issues/2507)
|
||||
* Fixed regression with `bin/plugin` not listing the plugins available (1c725c0)
|
||||
* Fixed bitwise operator in `TwigExtension::exifFunc()` [#2518](https://github.com/getgrav/grav/issues/2518)
|
||||
* Fixed issue with lang prefix incorrectly identifying as admin [#2511](https://github.com/getgrav/grav/issues/2511)
|
||||
* Fixed issue with `U0ils::pathPrefixedBYLanguageCode()` and trailing slash [#2510](https://github.com/getgrav/grav/issues/2511)
|
||||
* Fixed regresssion issue of `Utils::Url()` not returning `false` on failure. Added new optional `fail_gracefully` 3rd attribute to return string that caused failure [#2524](https://github.com/getgrav/grav/issues/2524)
|
||||
|
||||
# v1.6.9
|
||||
## 05/09/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `Route::withoutParams()` methods
|
||||
* Added `Pages::setCheckMethod()` method to override page configuration in Admin Plugin
|
||||
* Added `Cache::clearCache('invalidate')` parameter for just invalidating the cache without deleting any cached files
|
||||
* Made `UserCollectionInderface` to extend `Countable` to get the count of existing users
|
||||
1. [](#improved)
|
||||
* Flex admin: added default search options for flex objects
|
||||
* Flex collection and object now fall back to the default template if template file doesn't exist
|
||||
* Updated Vendor libraries including Twig 1.40.1
|
||||
* Updated language files from `https://crowdin.com/project/grav-core`
|
||||
1. [](#bugfix)
|
||||
* Fixed `$grav['route']` from being modified when the route instance gets modified
|
||||
* Fixed Assets options array mixed with standalone priority [#2477](https://github.com/getgrav/grav/issues/2477)
|
||||
* Fix for `avatar_url` provided by 3rd party providers
|
||||
* Fixed non standard `lang` code lengths in `Utils` and `Session` detection
|
||||
* Fixed saving a new object in Flex `SimpleStorage`
|
||||
* Fixed exception in `Flex::getDirectories()` if the first parameter is set
|
||||
* Output correct "Last Updated" in `bin/gpm info` command
|
||||
* Checkbox getting interpreted as string, so created new `Validation::filterCheckbox()`
|
||||
* Fixed backwards compatibility to `select` field with `selectize.create` set to true [git-sync#141](https://github.com/trilbymedia/grav-plugin-git-sync/issues/141)
|
||||
* Fixed `YamlFormatter::decode()` to always return array [#2494](https://github.com/getgrav/grav/pull/2494)
|
||||
* Fixed empty `$grav['request']->getAttribute('route')->getExtension()`
|
||||
|
||||
# v1.6.8
|
||||
## 04/23/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `FlexCollection::filterBy()` method
|
||||
1. [](#bugfix)
|
||||
* Revert `Use Null Coalesce Operator` [#2466](https://github.com/getgrav/grav/pull/2466)
|
||||
* Fixed `FormTrait::render()` not providing config variable
|
||||
* Updated `bin/grav clean` to clear `cache/compiled` and `user/config/security.yaml`
|
||||
|
||||
# v1.6.7
|
||||
## 04/22/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added a new `bin/grav yamllinter` CLI command to find YAML Linting issues [#2468](https://github.com/getgrav/grav/issues/2468#issuecomment-485151681)
|
||||
1. [](#improved)
|
||||
* Improve `FormTrait` backwards compatibility with existing forms
|
||||
* Added a new `Utils::getSubnet()` function for IPv4/IPv6 parsing [#2465](https://github.com/getgrav/grav/pull/2465)
|
||||
1. [](#bugfix)
|
||||
* Remove disabled fields from the form schema
|
||||
* Fix issue when excluding `inlineJs` and `inlineCss` from Assets pipeline [#2468](https://github.com/getgrav/grav/issues/2468)
|
||||
* Fix for manually set position on external URLs [#2470](https://github.com/getgrav/grav/issues/2470)
|
||||
|
||||
# v1.6.6
|
||||
## 04/17/2019
|
||||
|
||||
1. [](#new)
|
||||
* `FormInterface` now implements `RenderInterface`
|
||||
* Added new `FormInterface::getTask()` method which reads the task from `form.task` in the blueprint
|
||||
* `FormInterface` now implements `RenderInterface`
|
||||
* Added new `FormInterface::getTask()` method which reads the task from `form.task` in the blueprint
|
||||
1. [](#improved)
|
||||
* Updated vendor libraries to latest
|
||||
1. [](#bugfix)
|
||||
* Rollback `redirect_default_route` logic as it has issues with multi-lang [#2459](https://github.com/getgrav/grav/issues/2459)
|
||||
* Fix potential issue with `|contains` Twig filter on PHP 7.3
|
||||
* Fix potential issue with `|contains` Twig filter on PHP 7.3
|
||||
* Fixed bug in text field filtering: return empty string if value isn't a string or number [#2460](https://github.com/getgrav/grav/issues/2460)
|
||||
* Force Asset `priority` to be an integer and not throw error if invalid string passed [#2461](https://github.com/getgrav/grav/issues/2461)
|
||||
* Fixed bug in text field filtering: return empty string if value isn't a string or number
|
||||
* Fixed `FlexForm` missing getter methods for defining form variables
|
||||
|
||||
|
||||
# v1.6.5
|
||||
## 04/15/2019
|
||||
|
||||
@@ -74,7 +621,7 @@
|
||||
* Added `Grav\Framework\Object\ObjectIndex` class
|
||||
* Added `Grav\Framework\Flex` classes
|
||||
* Added support for hiding form fields in blueprints by using dynamic property like `security@: admin.foobar`, `scope@: object` or `scope-ignore@: object` to any field
|
||||
* New experimental **FlexObjects** powered `Users` for increased performance and capability (**disabled** by default)
|
||||
* New experimental **FlexObjects** powered `Users` for increased performance and capability (**disabled** by default)
|
||||
* Added PSR-7 and PSR-15 classes
|
||||
* Added `Grav\Framework\DI\Container` class
|
||||
* Added `Grav\Framework\RequestHandler\RequestHandler` class
|
||||
@@ -150,7 +697,7 @@
|
||||
* Added ability to reset `Page::metadata` to allow rebuilding from automatically generated values
|
||||
* Added back missing `page.types` field in system content configuration [admin#1612](https://github.com/getgrav/grav-plugin-admin/issues/1612)
|
||||
* Console commands: add method for invalidating cache
|
||||
* Updated languages
|
||||
* Updated languages
|
||||
* Improved `$page->forms()` call, added `$page->addForms()`
|
||||
* Updated languages from crowdin
|
||||
* Fixed `ImageMedium` constructor warning when file does not exist
|
||||
@@ -171,7 +718,7 @@
|
||||
* Added apcu autoloader optimization
|
||||
* Additional helper methods in `Language`, `Languages`, and `LanguageCodes` classes
|
||||
* Call `onFatalException` event also on internal PHP errors
|
||||
* Built-in PHP Webserver: log requests before handling them
|
||||
* Built-in PHP Webserver: log requests before handling them
|
||||
* Added support for syslog and syslog facility logging (default: 'file')
|
||||
* Improved usability of `System` configuration blueprint with side-tabs
|
||||
1. [](#bugfix)
|
||||
@@ -196,7 +743,7 @@
|
||||
* Fixed failed login if user attempts to log in with upper case non-english letters
|
||||
* Removed extra authenticated/authorized fields when saving existing user from a form
|
||||
* Fixed `Grav\Framework\Route::__toString()` returning relative URL, not relative route
|
||||
* Fixed handling of `append_url_extension` inside of `Page::templateFormat()` [#2264](https://github.com/getgrav/grav/issues/2264)
|
||||
* Fixed handling of `append_url_extension` inside of `Page::templateFormat()` [#2264](https://github.com/getgrav/grav/issues/2264)
|
||||
* Fixed a broken language string [#2261](https://github.com/getgrav/grav/issues/2261)
|
||||
* Fixed clearing cache having no effect on Doctrine cache
|
||||
* Fixed `Medium::relativePath()` for streams
|
||||
@@ -249,7 +796,7 @@
|
||||
* Updated vendor libraries
|
||||
1. [](#bugfix)
|
||||
* Support spaces with filenames in responsive images [#2300](https://github.com/getgrav/grav/pull/2300)
|
||||
|
||||
|
||||
# v1.5.6
|
||||
## 12/14/2018
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ The issue tracker is the preferred channel for [bug reports](#bugs),
|
||||
requests](#pull-requests), but please respect the following restrictions:
|
||||
|
||||
* Please **do not** use the issue tracker for support requests. Use
|
||||
[the Forum](http://getgrav.org/forum) or [the Gitter chat](https://gitter.im/getgrav/grav).
|
||||
[the Forum](http://getgrav.org/forum) or [the Chat](https://chat.getgrav.org/).
|
||||
|
||||
|
||||
<a name="bugs"></a>
|
||||
@@ -110,7 +110,8 @@ Good pull requests - patches, improvements, new features - are a fantastic
|
||||
help. They should remain focused in scope and avoid containing unrelated
|
||||
commits.
|
||||
|
||||
**Please ask first** in [Slack](https://getgrav.org/slack) or in the Forum before embarking on any significant pull request (e.g.
|
||||
**Please ask first** in [the Forum](http://getgrav.org/forum) or [the Chat](https://chat.getgrav.org/)
|
||||
before embarking on any significant pull request (e.g.
|
||||
implementing features, refactoring code..),
|
||||
otherwise you risk spending a lot of time working on something that the
|
||||
project's developers might not want to merge into the project.
|
||||
|
||||
305
UPGRADE-1.7.md
Normal file
305
UPGRADE-1.7.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# UPGRADE FROM 1.6 TO 1.7
|
||||
|
||||
## ADMINISTRATORS
|
||||
|
||||
### YAML files
|
||||
|
||||
* Please run `bin/grav yamllinter` to find any YAML parsing errors in your site. You should run this command before and after upgrade. Grav falls back to older YAML parser if it detects an error, but it will slow down your site.
|
||||
|
||||
## Forms
|
||||
|
||||
* **BC BREAK** Fixed `validation: strict`. Please search through all your forms if you were using this feature. If you were, either remove the line or test if the form still works.
|
||||
* Added configuration option `system.strict_mode.blueprint_compat` to maintain old `validation: strict` behavior
|
||||
* If you disable compatibiity, form validation will be much more strict (recommended, but may break existing forms)
|
||||
|
||||
### Pages
|
||||
|
||||
* **BC BREAK** Fixed 404 error page when you go to non-routable page with routable child pages under it. Now you get redirected to the first routable child page instead. This is probably what you wanted in the first place. If you do not want this new behavior, you need to **TODO**
|
||||
|
||||
### Multi-language
|
||||
|
||||
* Improved language support
|
||||
* **BC BREAK** Please check that your fallback languages are correct. Old implementation had a fallback to any other language, now only default language is being used unless you use `system.languages.content_fallback` configuration option to override the default behavior.
|
||||
|
||||
### Admin
|
||||
|
||||
* If you upgrade from older 1.7 RC, you need to go to Flex Objects plugin settings and turn on `Pages`, `User Accounts` and `User Groups` directories (upgrading 1.6 automatically turns them on)
|
||||
* Disabling `User Accounts` and `User Groups` directories in Flex Objects plugin should be kept enabled; fine tuned **ACL** may not work without
|
||||
|
||||
### Sessions
|
||||
|
||||
* Session ID now changes on login to prevent session fixation issues
|
||||
|
||||
### CLI
|
||||
|
||||
* Added new `bin/grav server` CLI command to easily run Symfony or PHP built-in web servers
|
||||
* Added new `bin/grav page-system-validator [-r|--record] [-c|--check]` CLI command to test Flex Pages
|
||||
* Improved `Scheduler` cron command check and more useful CLI information
|
||||
* Added new `-r <job-id>` option for Scheduler CLI command to force-run a job
|
||||
* Improved `bin/grav yamllinter` CLI command by adding an option to find YAML Linting issues from the whole site or custom folder
|
||||
|
||||
### Configuration
|
||||
|
||||
* Added new configuration option `system.debugger.provider` to choose between debugbar and clockwork
|
||||
* Added new configuration option `system.debugger.censored` to hide potentially sensitive information
|
||||
* Added new configuration option `system.pages.type` to enable Flex Pages
|
||||
* Added new configuration option `system.languages.include_default_lang_file_extension` to keep default language in `.md` files if set to `false`
|
||||
* Added new configuration option `system.languages.content_fallback` to set fallback content languages individually for every language
|
||||
* Added new configuration option `security.sanitize_svg` to remove potentially dangerous code from SVG files
|
||||
|
||||
### Debugging
|
||||
|
||||
* Added support for [Clockwork](https://underground.works/clockwork) developer tools (now default debugger)
|
||||
* Added support for [Tideways XHProf](https://github.com/tideways/php-xhprof-extension) PHP Extension for profiling method calls
|
||||
* Added Twig profiling for Clockwork debugger
|
||||
|
||||
## DEVELOPERS
|
||||
|
||||
### Use composer autoloader
|
||||
|
||||
* Please add `composer.json` file to your plugin and run `composer update --no-dev` (and remember to keep it updated):
|
||||
|
||||
composer.json
|
||||
```json
|
||||
{
|
||||
"name": "getgrav/grav-plugin-example",
|
||||
"type": "grav-plugin",
|
||||
"description": "Example plugin for Grav CMS",
|
||||
"keywords": ["example", "plugin"],
|
||||
"homepage": "https://github.com/getgrav/grav-plugin-example",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "...",
|
||||
"email": "...",
|
||||
"homepage": "...",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/getgrav/grav-plugin-example/issues",
|
||||
"docs": "https://github.com/getgrav/grav-plugin-example/blob/master/README.md"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Grav\\Plugin\\Example\\": "classes/",
|
||||
"Grav\\Plugin\\Console\\": "cli/"
|
||||
},
|
||||
"classmap": [
|
||||
"example.php"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See [Composer schema](https://getcomposer.org/doc/04-schema.md)
|
||||
|
||||
* Please use autoloader instead of `require` in the code:
|
||||
|
||||
example.php
|
||||
```php
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
'onPluginsInitialized' => [
|
||||
// This is only required in Grav 1.6. Grav 1.7 automatically calls $plugin->autolaod() method.
|
||||
['autoload', 100000],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Composer autoload.
|
||||
*
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public function autoload()
|
||||
{
|
||||
return require __DIR__ . '/vendor/autoload.php';
|
||||
}
|
||||
```
|
||||
|
||||
* Plugins & Themes: Call `$plugin->autoload()` and `$theme->autoload()` automatically when object gets initialized
|
||||
* Make sure your code does not use `require` or `include` for loading classes
|
||||
|
||||
### Dependencies
|
||||
|
||||
* Make sure you update your plugin/theme dependencies. I recommend setting Grav to either 1.6 or 1.7 and update your code/vendor to PHP 7.1
|
||||
|
||||
blueprints.yaml
|
||||
```yaml
|
||||
dependencies:
|
||||
- { name: grav, version: '>=1.6.0' }
|
||||
```
|
||||
|
||||
### ACL
|
||||
|
||||
* `user.authorize()` now requires user to be authorized (passed 2FA check), unless the rule contains `login` in its name.
|
||||
* Added support for more advanced ACL (CRUD)
|
||||
|
||||
* **BC BREAK** `user.authorize()` and Flex `object.isAuthorized()` now have two deny states: `false` and `null`.
|
||||
|
||||
Make sure you do not have strict checks against false: `$user->authorize($action) === false` (PHP) or `user.authorize(action) is same as(false)` (Twig).
|
||||
|
||||
For the negative checks you should be using `!user->authorize($action)` (PHP) or `not user.authorize(action)` (Twig).
|
||||
|
||||
The change has been done to allow strong deny rules by chaining the actions if previous ones do not match: `user.authorize(action1) ?? user.authorize(action2) ?? user.authorize(action3)`.
|
||||
|
||||
Note that Twig function `authorize()` will still **keeps** the old behavior!
|
||||
|
||||
### Pages
|
||||
|
||||
* Added experimental support for `Flex Pages`
|
||||
* Added page specific permissions support for `Flex Pages`
|
||||
* Added root page support for `Flex Pages`
|
||||
* Fixed wrong `Pages::dispatch()` calls (with redirect) when we really meant to call `Pages::find()`
|
||||
* Added `Pages::getCollection()` method
|
||||
* Moved `collection()` and `evaluate()` logic from `Page` class into `Pages` class
|
||||
* **DEPRECATED** `$page->modular()` in favor of `$page->isModule()`
|
||||
* **BC BREAK** Fixed `Page::modular()` and `Page::modularTwig()` returning `null` for folders and other non-initialized pages. Should not affect your code unless you were checking against `false` or `null`.
|
||||
* **BC BREAK** Always use `\Grav\Common\Page\Interfaces\PageInterface` instead of `\Grav\Common\Page\Page` in method signatures
|
||||
* Admin now uses `Flex Pages` by default, collection will behave in slightly different way
|
||||
|
||||
### Markdown
|
||||
|
||||
* **BC BREAK** Upgraded Parsedown to 1.7 for Parsedown-Extra 0.8. Plugins that extend Parsedown may need a fix to render as HTML
|
||||
|
||||
### Users
|
||||
|
||||
* Improved `Flex Users`: obey blueprints and allow Flex to be used in admin only
|
||||
* Improved `Flex Users`: user and group ACL now supports deny permissions
|
||||
* Changed `UserInterface::authorize()` to return `null` having the same meaning as `false` if access is denied because of no matching rule
|
||||
* **DEPRECATED** `\Grav\Common\User\Group` in favor of `$grav['user_groups']`, which contains Flex UserGroup collection
|
||||
* **BC BREAK** Always use `\Grav\Common\User\Interfaces\UserInterface` instead of `\Grav\Common\User\User` in method signatures
|
||||
|
||||
### Flex
|
||||
|
||||
* Added `$grav['flex']` to access all registered Flex Directories
|
||||
* Added `FlexRegisterEvent` which triggers when `$grav['flex']` is being accessed the first time
|
||||
* Added `hasFlexFeature()` method to test if `FlexObject` or `FlexCollection` implements a given feature
|
||||
* Added `getFlexFeatures()` method to return all features that `FlexObject` or `FlexCollection` implements
|
||||
* Added `FlexStorage::getMetaData()` to get updated object meta information for listed keys
|
||||
* `FlexDirectory::getObject()` can now be called without any parameters to create a new object
|
||||
* **DEPRECATED** `FlexDirectory::update()` and `FlexDirectory::remove()`
|
||||
* **BC BREAK** Moved all Flex type classes under `Grav\Common\Flex`
|
||||
* **BC BREAK** `FlexStorageInterface::getStoragePath()` and `getMediaPath()` can now return null
|
||||
* **BC BREAK** Flex objects no longer return temporary key if they do not have one; empty key is returned instead
|
||||
|
||||
### Templating
|
||||
|
||||
* Added support for Twig 2.12 (still using Twig 1.42)
|
||||
* Added a new `{% cache %}` Twig tag eliminating need for `twigcache` extension.
|
||||
* Added `array_diff()` twig function
|
||||
* Added `template_from_string()` twig function
|
||||
* Improved `url()` twig function to take third parameter (`true`) to return URL on non-existing file instead of returning false
|
||||
* Improved `|array` twig filter to work with iterators and objects with `toArray()` method
|
||||
* Improved `authorize()` twig function to work better with nested rule parameters
|
||||
* Improved `|yaml_serialize` twig filter: added support for `JsonSerializable` objects and other array-like objects
|
||||
|
||||
### Multi-language
|
||||
|
||||
* Improved language support for `Route` class
|
||||
* Translations: rename MODULAR to MODULE everywhere
|
||||
* Added `Language::getPageExtensions()` to get full list of supported page language extensions
|
||||
* **BC BREAK** Fixed `Language::getFallbackPageExtensions()` to fall back only to default language instead of going through all languages
|
||||
|
||||
### Blueprints
|
||||
|
||||
* Added `flatten_array` filter to form field validation
|
||||
* Added support for `security@: or: [admin.super, admin.pages]` in blueprints (nested AND/OR mode support)
|
||||
* Blueprint validation: Added `validate: value_type: bool|int|float|string|trim` to `array` to filter all the values inside the array
|
||||
* If your plugins has blueprints folder, initializing it in the event will be too late. Do this instead:
|
||||
|
||||
```php
|
||||
class MyPlugin extends Plugin
|
||||
{
|
||||
/** @var array */
|
||||
public $features = [
|
||||
'blueprints' => 0, // Use priority 0
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
* Use `Symfony EventDispatcher` directly instead of `rockettheme/toolbox` wrapper.
|
||||
* Added `$grav->dispatchEvent()` method for PSR-14 events
|
||||
* Added `PluginsLoadedEvent` which triggers after plugins have been loaded but not yet initialized
|
||||
* Added `SessionStartEvent` which triggers when session is started
|
||||
* Added `FlexRegisterEvent` which triggers when `$grav['flex']` is being accessed the first time
|
||||
* Added `PermissionsRegisterEvent` which triggers when `$grav['permissions']` is being accessed the first time
|
||||
* Check `onAdminTwigTemplatePaths` event, it should NOT be:
|
||||
|
||||
```php
|
||||
public function onAdminTwigTemplatePaths($event)
|
||||
{
|
||||
// This code breaks all the other plugins in admin, including Flex Objects
|
||||
$event['paths'] = [__DIR__ . '/admin/themes/grav/templates'];
|
||||
}
|
||||
```
|
||||
but:
|
||||
```php
|
||||
public function onAdminTwigTemplatePaths($event)
|
||||
{
|
||||
// Add plugin template path for admin.
|
||||
$paths = $event['paths'];
|
||||
$paths[] = __DIR__ . '/admin/themes/grav/templates';
|
||||
$event['paths'] = $paths;
|
||||
}
|
||||
```
|
||||
|
||||
### Misc
|
||||
|
||||
* Added `Utils::isAssoc()` and `Utils::isNegative()` helper methods
|
||||
* Added `Utils::simpleTemplate()` method for very simple variable templating
|
||||
* Support customizable null character replacement in `CSVFormatter::decode()`
|
||||
* Added new `Security::sanitizeSVG()` function
|
||||
* Added `$grav->close()` method to properly terminate the request with a response
|
||||
* **BC BREAK** Make `Route` objects immutable. This means that you need to do: `{% set route = route.withExtension('.html') %}` (for all `withX` methods) to keep the updated version.
|
||||
|
||||
### CLI
|
||||
|
||||
* **BC BREAK** Many plugins initialize Grav in a wrong way, it is not safe to initialize plugins and theme by yourself
|
||||
* Following calls require Grav 1.6.21 or later, so it is recommended to set Grav dependency to that version
|
||||
* Inside `serve()` method:
|
||||
* Call `$this->setLanguage($langCode);` before doing anything else if you want to set the language (or use default)
|
||||
* Call one of following:
|
||||
* `$this->initializeGrav();` Already called if you're in `bin/plugin`, otherwise you may need to call this one
|
||||
* `$this->initializePlugins();` This initializes grav, plugins (up to `onPluginsInitialized`)
|
||||
* `$this->initializeThemes();` This initializes grav, plugins and theme
|
||||
* `$this->initializePages();` This initializes grav, plugins, theme and everything needed by pages
|
||||
* It is a good idea to prefix your CLI command classes with your plugin name, otherwise there may be naming conflicts (we already have some!)
|
||||
|
||||
### Composer dependencies
|
||||
|
||||
* Updated Symfony Components to 4.4, please update any deprecated features in your code
|
||||
* **BC BREAK** Please run `bin/grav yamllinter -f user://` to find any YAML parsing errors in your site (including your plugins and themes).
|
||||
|
||||
## PLUGINS
|
||||
|
||||
### Admin
|
||||
|
||||
* **BC BREAK** Admin will not initialize frontend pages anymore, this has been done to greatly speed up Admin plugin.
|
||||
|
||||
Please call `$grav['admin']->enablePages()` or `{% do admin.enablePages() %}` if you need to access frontend pages. This call can be safely made multiple times.
|
||||
|
||||
If you're using `Flex Pages`, please use Flex Directory instead, it will make your code so much faster.
|
||||
|
||||
* Admin now uses Flex for editing `Accounts` and `Pages`. If your plugin hooks into either of those, please make sure they still work.
|
||||
|
||||
* Admin cache is enabled by default, make sure your plugin clears cache when needed. Please avoid clearing all cache!
|
||||
|
||||
### Shortcode Core
|
||||
|
||||
* **DEPRECATED** Every shortcode needs to have `init()` method, classes without it will stop working in the future.
|
||||
Binary file not shown.
9
bin/gpm
9
bin/gpm
@@ -28,6 +28,13 @@ if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
|
||||
// Set internal encoding.
|
||||
if (!\extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
@ini_set('default_charset', 'UTF-8');
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
if (!file_exists(GRAV_ROOT . '/index.php')) {
|
||||
exit('FATAL: Must be run from ROOT directory of Grav!');
|
||||
}
|
||||
@@ -55,7 +62,7 @@ $grav->setup($environment);
|
||||
|
||||
$grav['config']->init();
|
||||
$grav['uri']->init();
|
||||
$grav['users'];
|
||||
$grav['accounts'];
|
||||
|
||||
$app = new Application('Grav Package Manager', GRAV_VERSION);
|
||||
$app->addCommands(array(
|
||||
|
||||
50
bin/grav
50
bin/grav
@@ -3,6 +3,7 @@
|
||||
|
||||
use Grav\Common\Composer;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Console\Cli;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
\define('GRAV_CLI', true);
|
||||
@@ -24,27 +25,52 @@ if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
Grav::instance(array('loader' => $autoload));
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
|
||||
// Set internal encoding.
|
||||
if (!\extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
@ini_set('default_charset', 'UTF-8');
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
$climate = new League\CLImate\CLImate;
|
||||
$climate->arguments->add([
|
||||
'environment' => [
|
||||
'prefix' => 'e',
|
||||
'longPrefix' => 'env',
|
||||
'description' => 'Configuration Environment',
|
||||
'defaultValue' => 'localhost'
|
||||
]
|
||||
]);
|
||||
$climate->arguments->parse();
|
||||
|
||||
// Set up environment based on params.
|
||||
$environment = $climate->arguments->get('environment');
|
||||
|
||||
$grav = Grav::instance(array('loader' => $autoload));
|
||||
$grav->setup($environment);
|
||||
|
||||
if (!file_exists(GRAV_ROOT . '/index.php')) {
|
||||
exit('FATAL: Must be run from ROOT directory of Grav!');
|
||||
}
|
||||
|
||||
$app = new Application('Grav CLI Application', GRAV_VERSION);
|
||||
$app->addCommands(array(
|
||||
new \Grav\Console\Cli\InstallCommand(),
|
||||
new \Grav\Console\Cli\ComposerCommand(),
|
||||
new \Grav\Console\Cli\SandboxCommand(),
|
||||
new \Grav\Console\Cli\CleanCommand(),
|
||||
new \Grav\Console\Cli\ClearCacheCommand(),
|
||||
new \Grav\Console\Cli\BackupCommand(),
|
||||
new \Grav\Console\Cli\NewProjectCommand(),
|
||||
new \Grav\Console\Cli\SchedulerCommand(),
|
||||
new \Grav\Console\Cli\SecurityCommand(),
|
||||
new \Grav\Console\Cli\LogViewerCommand(),
|
||||
new Cli\InstallCommand(),
|
||||
new Cli\ComposerCommand(),
|
||||
new Cli\SandboxCommand(),
|
||||
new Cli\CleanCommand(),
|
||||
new Cli\ClearCacheCommand(),
|
||||
new Cli\BackupCommand(),
|
||||
new Cli\NewProjectCommand(),
|
||||
new Cli\SchedulerCommand(),
|
||||
new Cli\SecurityCommand(),
|
||||
new Cli\LogViewerCommand(),
|
||||
new Cli\YamlLinterCommand(),
|
||||
new Cli\ServerCommand(),
|
||||
new Cli\PageSystemValidatorCommand(),
|
||||
));
|
||||
$app->run();
|
||||
|
||||
41
bin/plugin
41
bin/plugin
@@ -32,6 +32,13 @@ if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
|
||||
// Set internal encoding.
|
||||
if (!\extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
@ini_set('default_charset', 'UTF-8');
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
if (!file_exists(GRAV_ROOT . '/index.php')) {
|
||||
exit('FATAL: Must be run from ROOT directory of Grav!');
|
||||
}
|
||||
@@ -49,14 +56,10 @@ $climate->arguments->parse();
|
||||
|
||||
$environment = $climate->arguments->get('environment');
|
||||
|
||||
// Bootstrap Grav container.
|
||||
$grav = Grav::instance(array('loader' => $autoload));
|
||||
$grav->setup($environment);
|
||||
|
||||
$grav['config']->init();
|
||||
$grav['uri']->init();
|
||||
$grav['users'];
|
||||
$grav['plugins']->init();
|
||||
$grav['themes']->init();
|
||||
$grav->initializeCli();
|
||||
|
||||
$app = new Application('Grav Plugins Commands', GRAV_VERSION);
|
||||
$pattern = '([A-Z]\w+Command\.php)';
|
||||
@@ -79,19 +82,6 @@ $output = new ConsoleOutput();
|
||||
$output->getFormatter()->setStyle('red', new OutputFormatterStyle('red', null, array('bold')));
|
||||
$output->getFormatter()->setStyle('white', new OutputFormatterStyle('white', null, array('bold')));
|
||||
|
||||
if (is_null($plugin)) {
|
||||
$output->writeln('');
|
||||
$output->writeln("<red>$name plugin not found</red>");
|
||||
die;
|
||||
}
|
||||
|
||||
if (!$plugin->enabled) {
|
||||
$output->writeln('');
|
||||
$output->writeln("<red>$name not enabled</red>");
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
if (!$name) {
|
||||
$output->writeln('');
|
||||
$output->writeln('<red>Usage:</red>');
|
||||
@@ -125,6 +115,19 @@ if (!$name) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (null === $plugin) {
|
||||
$output->writeln('');
|
||||
$output->writeln("<red>$name plugin not found</red>");
|
||||
die;
|
||||
}
|
||||
|
||||
if (!$plugin->enabled) {
|
||||
$output->writeln('');
|
||||
$output->writeln("<red>$name not enabled</red>");
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
if ($plugin === null) {
|
||||
$output->writeln("<red>Grav Plugin <white>'{$name}'</white> is not installed</red>");
|
||||
exit;
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
"name": "getgrav/grav",
|
||||
"type": "project",
|
||||
"description": "Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS",
|
||||
"keywords": ["cms","flat-file cms","flat cms","flatfile cms","php"],
|
||||
"keywords": [
|
||||
"cms",
|
||||
"flat-file cms",
|
||||
"flat cms",
|
||||
"flatfile cms",
|
||||
"php"
|
||||
],
|
||||
"homepage": "https://getgrav.org",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
@@ -16,46 +22,45 @@
|
||||
"symfony/polyfill-iconv": "^1.9",
|
||||
"symfony/polyfill-php72": "^1.9",
|
||||
"symfony/polyfill-php73": "^1.9",
|
||||
|
||||
"psr/simple-cache": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
|
||||
"kodus/psr7-server": "*",
|
||||
"nyholm/psr7": "^1.0",
|
||||
|
||||
"twig/twig": "~1.35",
|
||||
"erusev/parsedown": "1.6.4",
|
||||
"erusev/parsedown-extra": "~0.7",
|
||||
"symfony/yaml": "~4.2",
|
||||
"symfony/console": "~4.2",
|
||||
"symfony/event-dispatcher": "~4.2",
|
||||
"symfony/var-dumper": "~4.2",
|
||||
"symfony/process": "~4.2",
|
||||
"twig/twig": "~1.0",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"erusev/parsedown-extra": "~0.8",
|
||||
"symfony/contracts": "~1.0",
|
||||
"symfony/yaml": "~4.4.0",
|
||||
"symfony/console": "~4.4.0",
|
||||
"symfony/event-dispatcher": "~4.4.0",
|
||||
"symfony/var-dumper": "~4.4.0",
|
||||
"symfony/process": "~4.4.0",
|
||||
"doctrine/cache": "^1.8",
|
||||
"doctrine/collections": "^1.5",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"filp/whoops": "~2.2",
|
||||
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
"monolog/monolog": "~1.0",
|
||||
"gregwar/image": "2.*",
|
||||
"donatj/phpuseragentparser": "~0.10",
|
||||
"pimple/pimple": "~3.2",
|
||||
"rockettheme/toolbox": "~1.4",
|
||||
"maximebf/debugbar": "~1.15",
|
||||
"rockettheme/toolbox": "~1.5",
|
||||
"maximebf/debugbar": "~1.0",
|
||||
"league/climate": "^3.4",
|
||||
"antoligy/dom-string-iterators": "^1.0",
|
||||
"miljar/php-exif": "^0.6.4",
|
||||
"composer/ca-bundle": "^1.0",
|
||||
"dragonmantank/cron-expression": "^1.2",
|
||||
"phive/twig-extensions-deferred": "^1.0",
|
||||
"willdurand/negotiation": "^2.3"
|
||||
"willdurand/negotiation": "2.x-dev",
|
||||
"itsgoingd/clockwork": "@beta",
|
||||
"enshrined/svg-sanitize": "~0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^2.4",
|
||||
"phpstan/phpstan": "^0.11",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.11.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.11",
|
||||
"phpunit/php-code-coverage": "~6.0",
|
||||
"fzaninotto/faker": "^1.8",
|
||||
"victorjonsson/markdowndocs": "dev-master"
|
||||
@@ -73,26 +78,35 @@
|
||||
"php": "7.1.3"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"repositories": [{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/itsgoingd/clockwork"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Grav\\": "system/src/Grav"
|
||||
},
|
||||
"files": ["system/defines.php"]
|
||||
"files": [
|
||||
"system/defines.php"
|
||||
]
|
||||
},
|
||||
"archive": {
|
||||
"exclude": ["VERSION"]
|
||||
"exclude": [
|
||||
"VERSION"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"api-16": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.16.md",
|
||||
"api-15": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.md",
|
||||
"post-create-project-cmd": "bin/grav install",
|
||||
"phpstan": "vendor/bin/phpstan analyse -l 2 -c ./tests/phpstan/phpstan.neon system/src --memory-limit=256M",
|
||||
"phpstan-framework": "vendor/bin/phpstan analyse -l 5 -c ./tests/phpstan/phpstan.neon system/src/Grav/Framework --memory-limit=256M",
|
||||
"test-plugins": "vendor/bin/phpstan analyse -l 0 -c ./tests/phpstan/plugins.neon user/plugins --memory-limit=256M",
|
||||
"phpstan": "vendor/bin/phpstan analyse -l 3 -c ./tests/phpstan/phpstan.neon system/src --memory-limit=340M",
|
||||
"phpstan-framework": "vendor/bin/phpstan analyse -l 7 -c ./tests/phpstan/phpstan.neon system/src/Grav/Framework --memory-limit=128M",
|
||||
"phpstan-plugins": "vendor/bin/phpstan analyse -l 1 -c ./tests/phpstan/plugins.neon user/plugins --memory-limit=300M",
|
||||
"test": "vendor/bin/codecept run unit",
|
||||
"test-windows": "vendor\\bin\\codecept run unit"
|
||||
},
|
||||
|
||||
1404
composer.lock
generated
1404
composer.lock
generated
File diff suppressed because it is too large
Load Diff
27
index.php
27
index.php
@@ -16,10 +16,24 @@ if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
die(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
|
||||
}
|
||||
|
||||
if (PHP_SAPI === 'cli-server' && !isset($_SERVER['PHP_CLI_ROUTER'])) {
|
||||
die("PHP webserver requires a router to run Grav, please use: <pre>php -S {$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']} system/router.php</pre>");
|
||||
if (PHP_SAPI === 'cli-server') {
|
||||
$symfony_server = stripos(getenv('_'), 'symfony') !== false || stripos($_SERVER['SERVER_SOFTWARE'], 'symfony
|
||||
') !== false;
|
||||
if (!isset($_SERVER['PHP_CLI_ROUTER']) && !$symfony_server) {
|
||||
die("PHP webserver requires a router to run Grav, please use: <pre>php -S {$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']} system/router.php</pre>");
|
||||
}
|
||||
}
|
||||
|
||||
// Set timezone to default, falls back to system if php.ini not set
|
||||
date_default_timezone_set(@date_default_timezone_get());
|
||||
|
||||
// Set internal encoding.
|
||||
if (!\extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
@ini_set('default_charset', 'UTF-8');
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
// Ensure vendor libraries exist
|
||||
$autoload = __DIR__ . '/vendor/autoload.php';
|
||||
if (!is_file($autoload)) {
|
||||
@@ -32,15 +46,6 @@ $loader = require $autoload;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
// Set timezone to default, falls back to system if php.ini not set
|
||||
date_default_timezone_set(@date_default_timezone_get());
|
||||
|
||||
// Set internal encoding if mbstring loaded
|
||||
if (!\extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
// Get the Grav instance
|
||||
$grav = Grav::instance(
|
||||
array(
|
||||
|
||||
4
now.json
Normal file
4
now.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "*.php", "use": "@now/php" }]
|
||||
}
|
||||
@@ -10,3 +10,4 @@ Disallow: /user/
|
||||
Allow: /user/pages/
|
||||
Allow: /user/themes/
|
||||
Allow: /user/images/
|
||||
Allow: /
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
div.phpdebugbar {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.phpdebugbar pre {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header > div > * {
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header, .phpdebugbar a.phpdebugbar-restore-btn {
|
||||
background-image: url(grav.png);
|
||||
}
|
||||
|
||||
.phpdebugbar a.phpdebugbar-restore-btn {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
.phpdebugbar a.phpdebugbar-tab.phpdebugbar-active {
|
||||
background: #3DB9EC;
|
||||
color: #fff;
|
||||
margin-top: -1px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar {
|
||||
border-top: 1px solid #ddd;
|
||||
padding-left: 5px;
|
||||
padding-right: 2px;
|
||||
padding-top: 2px;
|
||||
background-color: #fafafa !important;
|
||||
width: auto !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar input {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar .phpdebugbar-widgets-filter {
|
||||
|
||||
}
|
||||
|
||||
|
||||
.phpdebugbar input[type=text] {
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.phpdebugbar dl.phpdebugbar-widgets-varlist, ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
|
||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
|
||||
text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.phpdebugbar pre, .phpdebugbar code {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
2
system/assets/debugger/clockwork.css
Normal file
2
system/assets/debugger/clockwork.css
Normal file
@@ -0,0 +1,2 @@
|
||||
/** Clockwork Debugger CSS **/
|
||||
.clockwork-badge{position:fixed;z-index:10;bottom:0;left:0;padding:2px 4px;background-color:#eee;border:1px solid #ccc;border-bottom:0;border-left:0;display:flex;align-items:center}.clockwork-badge:hover{width:auto}.clockwork-badge:hover:after{content:'Grav Clockwork debugger enabled. Install Clockwork Browser extension (Chrome or Firefox), open your Developer tools and then select the Clockwork tab.'}.clockwork-badge:after{margin-left:10px;font-family:Monaco,Consolas,"Lucida Console",monospace;font-size:12px;line-height:1.5;color:#666}.clockwork-badge i{display:block;float:left;height:22px;width:22px;min-width:22px;background-size:contain;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA/1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeHh4AAAD///8EBAT7+/sLCwv29vYVFRUvLy/t7e3m5ubCwsKxsbE/Pz+mpqZMTEwcHBzy8vLp6emfn5+AgIA2Njbi4uLf39+rq6tzc3NWVlYhISHa2trW1tbS0tLMzMy7u7uZmZmUlJSMjIxvb29kZGRHR0c7Ozt5eXkqKiq1tbWQkJBqampbW1tSUlLHx8eHh4ckJCRDQ0M3wD42AAAAI3RSTlMA/PibTbQ0x76TVAlw4LhZLOuEYCAN9Hjx0a2ppGZEGYw97djhXHwAAATZSURBVFjDlVcHW+MwDO1eFCjj2McNOzvdpXTTXVbL/P+/5SQ7QSSX5Di1X1onfi/Sk+Q4sTDbKqWK+YuznZ2zi3wxVdqK/Zf92M1nT9gnO8rmd398GX6Z3xaoOFoiAQcx3E5efgmeSuN8F6Xg1x3G06l/wjNpMR1B0uif4EhnIuFb+0diIoFXk3IVfokisR+h52GO4JKgyjmfaMhAFNlSaPR7DpwI+lzn/E4QKIqmKIJirxCMP4izBPPZPXhgXwMBYgULw0nfg/BF5scDbslb7QeJ08yqqTEmGYoB95d4H8ETL8+n9wBqrLu6ao3bBsMwAnxISf/9BHcqxNB8Y7cWl3Zz7TAUfPrvAT6AoNEFFXvsjutL01yOuMrtBxnFXsmT/1wQHmdWAFNnI3uI48Yj0FUcHbKf62GfUfr8eeQt7Uk3mQZpZNoVRPEui5vtEz5zFEpgWnyqVBZMc6oaGNriH2hGVZ0OxEvInPeMaZWJBA7vmPbCr5jjws5HBnAUxvDMH40aCIf4G5BjRQSs8E8HFFYf8bGxgDvD55bzGhwWkoBcuIyHR/AMdaCagxXDhtL6tSqoWpd4BMnlIR+Or+rYTK/a3EAGcc6e4AWHISnWv20iCCojsHoVlQdjrMexFF2C7UMg2A2WEGWbQhXN6l3eXC6XGp4b9qxbuEB2EBGBwtocrK90cVG5mbRXm6vmx/0phq1sIAGKDgLOBiN1MrO5a9aDl+D0W6x0Ar9BCTRuIIANa90Y7LrLVRXzwVtDInCqMRWcf2bUOEAsa4wJqFowQALL9EiAtVRk8QC4OW+1pOM9jIaVASwYagyNXDj+W0NcfuZNzjtXOiL0Zzg30Llj+ptfxQs4+vBPNiL5PawFCBkgXpUaVtqGl+A8dgZHL34BcBUQrwPptToW+o37Ku+UH9eYByJIx3YkAeFnMFuGO7S5gEp7YhXxa5OOAM39RXDPXb0qmpROsswZe+twXdU55oUIZAiEv3bD1UFwIYKkmGqytPCDCwKFQCKK0yL7qtSAPX54UAbtsLuBHkb9zyLmPQSNjsSgmQwKUOIfEY8F8t4B34DvndJY9BA8tNBJq1Nev9axmaStFcQLhgYoCTo0salkIaW8OUDdWjMTR2sHPhrAFZqx6cqcKE4pl2BJJ4K6hfwvqNgAnXfKX/HU6X3Zrhnu0k7tLNZtTBRv1hkwTDBY1NzFU6doDYjJbWdQkQhWwuU7/LvhTh3SDoco4ECL4i5dwURbc8NdDZz2IwKicE8d0KIqWetLE3+lL4hvUuGSeRfVWNLfj/gpOw4smBJBkKQHCzlHGwvAj4woB1gq5NGGLSXtORBPnUQPV5/MPVkDMxbpwG7w4x0xL6Ltxka0A/4NBvV09UVk4DoSn/jl2+JQS9q9KYawisAD4CfhsZ4TH3htylsdEHARIQBusqCKyUpymycgbbkkXEXjT3z7/oKQFTFVuZD2FMJHZIDsO5x2d4aAr2jR+GLwZhtAb028/0yJ9J8dE87jQyKObcjtTXT8dH+fDuKF4/eiPwzH44wTf/yUi6wrpRIOZ9lM1EtXAifFI+CJn9+iX/t2xMQwOMth/UZbASi8btAwR9FHWSpJr75g9Oqbin3VDg+SpwlP6k6TB4ex/7JvmcJx8jydy6XPk8eFTKhyfwCgX71MSvaBHgAAAABJRU5ErkJggg==)}
|
||||
3
system/assets/debugger/clockwork.js
Normal file
3
system/assets/debugger/clockwork.js
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Clockwork Debugger JS **/
|
||||
document.addEventListener("DOMContentLoaded",function () {
|
||||
var e=document.createElement("div");e.appendChild(document.createElement("i")),e.className="clockwork-badge",document.body.appendChild(e)});
|
||||
70
system/assets/debugger/phpdebugbar.css
Normal file
70
system/assets/debugger/phpdebugbar.css
Normal file
@@ -0,0 +1,70 @@
|
||||
div.phpdebugbar {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.phpdebugbar pre {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header > div > * {
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.phpdebugbar div.phpdebugbar-header, .phpdebugbar a.phpdebugbar-restore-btn {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA/1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeHh4AAAD///8EBAT7+/sLCwv29vYVFRUvLy/t7e3m5ubCwsKxsbE/Pz+mpqZMTEwcHBzy8vLp6emfn5+AgIA2Njbi4uLf39+rq6tzc3NWVlYhISHa2trW1tbS0tLMzMy7u7uZmZmUlJSMjIxvb29kZGRHR0c7Ozt5eXkqKiq1tbWQkJBqampbW1tSUlLHx8eHh4ckJCRDQ0M3wD42AAAAI3RSTlMA/PibTbQ0x76TVAlw4LhZLOuEYCAN9Hjx0a2ppGZEGYw97djhXHwAAATZSURBVFjDlVcHW+MwDO1eFCjj2McNOzvdpXTTXVbL/P+/5SQ7QSSX5Di1X1onfi/Sk+Q4sTDbKqWK+YuznZ2zi3wxVdqK/Zf92M1nT9gnO8rmd398GX6Z3xaoOFoiAQcx3E5efgmeSuN8F6Xg1x3G06l/wjNpMR1B0uif4EhnIuFb+0diIoFXk3IVfokisR+h52GO4JKgyjmfaMhAFNlSaPR7DpwI+lzn/E4QKIqmKIJirxCMP4izBPPZPXhgXwMBYgULw0nfg/BF5scDbslb7QeJ08yqqTEmGYoB95d4H8ETL8+n9wBqrLu6ao3bBsMwAnxISf/9BHcqxNB8Y7cWl3Zz7TAUfPrvAT6AoNEFFXvsjutL01yOuMrtBxnFXsmT/1wQHmdWAFNnI3uI48Yj0FUcHbKf62GfUfr8eeQt7Uk3mQZpZNoVRPEui5vtEz5zFEpgWnyqVBZMc6oaGNriH2hGVZ0OxEvInPeMaZWJBA7vmPbCr5jjws5HBnAUxvDMH40aCIf4G5BjRQSs8E8HFFYf8bGxgDvD55bzGhwWkoBcuIyHR/AMdaCagxXDhtL6tSqoWpd4BMnlIR+Or+rYTK/a3EAGcc6e4AWHISnWv20iCCojsHoVlQdjrMexFF2C7UMg2A2WEGWbQhXN6l3eXC6XGp4b9qxbuEB2EBGBwtocrK90cVG5mbRXm6vmx/0phq1sIAGKDgLOBiN1MrO5a9aDl+D0W6x0Ar9BCTRuIIANa90Y7LrLVRXzwVtDInCqMRWcf2bUOEAsa4wJqFowQALL9EiAtVRk8QC4OW+1pOM9jIaVASwYagyNXDj+W0NcfuZNzjtXOiL0Zzg30Llj+ptfxQs4+vBPNiL5PawFCBkgXpUaVtqGl+A8dgZHL34BcBUQrwPptToW+o37Ku+UH9eYByJIx3YkAeFnMFuGO7S5gEp7YhXxa5OOAM39RXDPXb0qmpROsswZe+twXdU55oUIZAiEv3bD1UFwIYKkmGqytPCDCwKFQCKK0yL7qtSAPX54UAbtsLuBHkb9zyLmPQSNjsSgmQwKUOIfEY8F8t4B34DvndJY9BA8tNBJq1Nev9axmaStFcQLhgYoCTo0salkIaW8OUDdWjMTR2sHPhrAFZqx6cqcKE4pl2BJJ4K6hfwvqNgAnXfKX/HU6X3Zrhnu0k7tLNZtTBRv1hkwTDBY1NzFU6doDYjJbWdQkQhWwuU7/LvhTh3SDoco4ECL4i5dwURbc8NdDZz2IwKicE8d0KIqWetLE3+lL4hvUuGSeRfVWNLfj/gpOw4smBJBkKQHCzlHGwvAj4woB1gq5NGGLSXtORBPnUQPV5/MPVkDMxbpwG7w4x0xL6Ltxka0A/4NBvV09UVk4DoSn/jl2+JQS9q9KYawisAD4CfhsZ4TH3htylsdEHARIQBusqCKyUpymycgbbkkXEXjT3z7/oKQFTFVuZD2FMJHZIDsO5x2d4aAr2jR+GLwZhtAb028/0yJ9J8dE87jQyKObcjtTXT8dH+fDuKF4/eiPwzH44wTf/yUi6wrpRIOZ9lM1EtXAifFI+CJn9+iX/t2xMQwOMth/UZbASi8btAwR9FHWSpJr75g9Oqbin3VDg+SpwlP6k6TB4ex/7JvmcJx8jydy6XPk8eFTKhyfwCgX71MSvaBHgAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
||||
.phpdebugbar a.phpdebugbar-restore-btn {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
.phpdebugbar a.phpdebugbar-tab.phpdebugbar-active {
|
||||
background: #3DB9EC;
|
||||
color: #fff;
|
||||
margin-top: -1px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar {
|
||||
border-top: 1px solid #ddd;
|
||||
padding-left: 5px;
|
||||
padding-right: 2px;
|
||||
padding-top: 2px;
|
||||
background-color: #fafafa !important;
|
||||
width: auto !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar input {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.phpdebugbar .phpdebugbar-widgets-toolbar .phpdebugbar-widgets-filter {
|
||||
|
||||
}
|
||||
|
||||
|
||||
.phpdebugbar input[type=text] {
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.phpdebugbar dl.phpdebugbar-widgets-varlist, ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
|
||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
|
||||
text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.phpdebugbar pre, .phpdebugbar code {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.6 KiB |
4
system/assets/jquery/jquery-3.x.min.js
vendored
4
system/assets/jquery/jquery-3.x.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -105,3 +105,15 @@ form:
|
||||
validate:
|
||||
type: commalist
|
||||
|
||||
|
||||
sanitize_svg:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SANITIZE_SVG
|
||||
help: PLUGIN_ADMIN.SANITIZE_SVG_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
default: true
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
@@ -65,7 +65,7 @@ form:
|
||||
|
||||
summary.size:
|
||||
type: text
|
||||
size: x-small
|
||||
size: small
|
||||
append: PLUGIN_ADMIN.CHARACTERS
|
||||
label: PLUGIN_ADMIN.SUMMARY_SIZE
|
||||
help: PLUGIN_ADMIN.SUMMARY_SIZE_HELP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
8
system/blueprints/flex/accounts.yaml
Normal file
8
system/blueprints/flex/accounts.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
title: Flex User Accounts
|
||||
description: Manage your User Accounts in Flex.
|
||||
type: flex-objects
|
||||
|
||||
# Deprecated in Grav 1.7.0-rc.4: file was renamed.
|
||||
extends@:
|
||||
type: user-accounts
|
||||
context: blueprints://flex
|
||||
202
system/blueprints/flex/pages.yaml
Normal file
202
system/blueprints/flex/pages.yaml
Normal file
@@ -0,0 +1,202 @@
|
||||
title: Pages
|
||||
description: Manage your Grav Pages in Flex.
|
||||
type: flex-objects
|
||||
|
||||
# Extends a page (blueprint gets overridden inside the object)
|
||||
extends@:
|
||||
type: default
|
||||
context: blueprints://pages
|
||||
|
||||
#
|
||||
# HIGHLY SPECIALIZED FLEX TYPE, AVOID USING PAGES AS BASE FOR YOUR OWN TYPE.
|
||||
#
|
||||
|
||||
# Flex configuration
|
||||
config:
|
||||
# Administration Configuration (needs Flex Objects plugin)
|
||||
admin:
|
||||
# Admin router
|
||||
router:
|
||||
path: '/pages'
|
||||
|
||||
# Permissions
|
||||
permissions:
|
||||
# Primary permissions
|
||||
admin.pages:
|
||||
type: crudl
|
||||
label: Pages
|
||||
admin.configuration.pages:
|
||||
type: default
|
||||
label: Pages Configuration
|
||||
|
||||
# Admin menu
|
||||
menu:
|
||||
list:
|
||||
route: '/pages'
|
||||
title: PLUGIN_ADMIN.PAGES
|
||||
icon: fa-file-text
|
||||
authorize: ['admin.pages.list', 'admin.super']
|
||||
priority: 5
|
||||
|
||||
# Admin template type (folder)
|
||||
template: pages
|
||||
|
||||
# Allowed admin actions
|
||||
actions:
|
||||
list: true
|
||||
create: true
|
||||
read: true
|
||||
update: true
|
||||
delete: true
|
||||
|
||||
# List view
|
||||
list:
|
||||
# Fields shown in the list view
|
||||
fields:
|
||||
published:
|
||||
width: 8
|
||||
alias: header.published
|
||||
visible:
|
||||
width: 8
|
||||
field:
|
||||
label: Visible
|
||||
type: toggle
|
||||
menu:
|
||||
link: edit
|
||||
alias: header.menu
|
||||
full_route:
|
||||
field:
|
||||
label: Route
|
||||
type: text
|
||||
link: edit
|
||||
sort:
|
||||
field: key
|
||||
name:
|
||||
width: 8
|
||||
field:
|
||||
label: Type
|
||||
type: text
|
||||
translations:
|
||||
width: 8
|
||||
field:
|
||||
label: Translations
|
||||
type: text
|
||||
# updated_date:
|
||||
# alias: header.update_date
|
||||
|
||||
# Extra options
|
||||
options:
|
||||
# Default number of records for pagination
|
||||
per_page: 20
|
||||
# Default ordering
|
||||
order:
|
||||
by: key
|
||||
dir: asc
|
||||
|
||||
# TODO: not used yet
|
||||
buttons:
|
||||
back:
|
||||
icon: reply
|
||||
title: PLUGIN_ADMIN.BACK
|
||||
add:
|
||||
icon: plus
|
||||
label: PLUGIN_ADMIN.ADD
|
||||
|
||||
edit:
|
||||
# TODO: not used yet
|
||||
buttons:
|
||||
back:
|
||||
icon: reply
|
||||
title: PLUGIN_ADMIN.BACK
|
||||
preview:
|
||||
icon: eye
|
||||
title: PLUGIN_ADMIN.PREVIEW
|
||||
add:
|
||||
icon: plus
|
||||
label: PLUGIN_ADMIN.ADD
|
||||
copy:
|
||||
icon: copy
|
||||
label: PLUGIN_ADMIN.COPY
|
||||
move:
|
||||
icon: arrows
|
||||
label: PLUGIN_ADMIN.MOVE
|
||||
delete:
|
||||
icon: close
|
||||
label: PLUGIN_ADMIN.DELETE
|
||||
save:
|
||||
icon: check
|
||||
label: PLUGIN_ADMIN.SAVE
|
||||
|
||||
# Preview View
|
||||
preview:
|
||||
enabled: true
|
||||
|
||||
# Configure view
|
||||
configure:
|
||||
authorize: 'admin.configuration.pages'
|
||||
|
||||
# Site Configuration
|
||||
site:
|
||||
# Hide from flex types
|
||||
hidden: true
|
||||
templates:
|
||||
collection:
|
||||
# Lookup for the template layout files for collections of objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/collection/{LAYOUT}{EXT}'
|
||||
object:
|
||||
# Lookup for the template layout files for objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/object/{LAYOUT}{EXT}'
|
||||
defaults:
|
||||
# Default template {TYPE}; overridden by filename of this blueprint if template folder exists
|
||||
type: pages
|
||||
# Default template {LAYOUT}; can be overridden in render calls (usually Twig in templates)
|
||||
layout: default
|
||||
|
||||
# Default filters for frontend.
|
||||
filter:
|
||||
- withPublished
|
||||
|
||||
# Data Configuration
|
||||
data:
|
||||
object: 'Grav\Common\Flex\Types\Pages\PageObject'
|
||||
collection: 'Grav\Common\Flex\Types\Pages\PageCollection'
|
||||
index: 'Grav\Common\Flex\Types\Pages\PageIndex'
|
||||
storage:
|
||||
class: 'Grav\Common\Flex\Types\Pages\Storage\PageStorage'
|
||||
options:
|
||||
formatter:
|
||||
class: 'Grav\Framework\File\Formatter\MarkdownFormatter'
|
||||
folder: 'page://'
|
||||
# Keep index file in filesystem to speed up lookups
|
||||
indexed: true
|
||||
# Set default ordering of the pages
|
||||
ordering:
|
||||
key: ASC
|
||||
search:
|
||||
# Search options
|
||||
options:
|
||||
contains: 1
|
||||
# Fields to be searched
|
||||
fields:
|
||||
- key
|
||||
- menu
|
||||
- title
|
||||
- name
|
||||
|
||||
# Regular form definition
|
||||
form:
|
||||
fields:
|
||||
lang:
|
||||
type: hidden
|
||||
value: ''
|
||||
|
||||
tabs:
|
||||
fields:
|
||||
security:
|
||||
type: tab
|
||||
title: PLUGIN_ADMIN.SECURITY
|
||||
import@:
|
||||
type: partials/security
|
||||
context: blueprints://pages
|
||||
70
system/blueprints/flex/shared/configure.yaml
Normal file
70
system/blueprints/flex/shared/configure.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
form:
|
||||
validation: loose
|
||||
|
||||
fields:
|
||||
tabs:
|
||||
type: tabs
|
||||
fields:
|
||||
cache:
|
||||
type: tab
|
||||
title: Caching
|
||||
fields:
|
||||
object.cache.index.enabled:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_INDEX_CACHE_ENABLED
|
||||
highlight: 1
|
||||
config-default@: system.flex.cache.index.enabled
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
object.cache.index.lifetime:
|
||||
type: text
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_INDEX_CACHE_LIFETIME
|
||||
config-default@: system.flex.cache.index.lifetime
|
||||
validate:
|
||||
type: int
|
||||
|
||||
object.cache.object.enabled:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_OBJECT_CACHE_ENABLED
|
||||
highlight: 1
|
||||
config-default@: system.flex.cache.object.enabled
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
object.cache.object.lifetime:
|
||||
type: text
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_OBJECT_CACHE_LIFETIME
|
||||
config-default@: system.flex.cache.object.lifetime
|
||||
validate:
|
||||
type: int
|
||||
|
||||
object.cache.render.enabled:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_RENDER_CACHE_ENABLED
|
||||
highlight: 1
|
||||
config-default@: system.flex.cache.render.enabled
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
object.cache.render.lifetime:
|
||||
type: text
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.FLEX_RENDER_CACHE_LIFETIME
|
||||
config-default@: system.flex.cache.render.lifetime
|
||||
validate:
|
||||
type: int
|
||||
131
system/blueprints/flex/user-accounts.yaml
Normal file
131
system/blueprints/flex/user-accounts.yaml
Normal file
@@ -0,0 +1,131 @@
|
||||
title: User Accounts
|
||||
description: Manage your User Accounts in Flex.
|
||||
type: flex-objects
|
||||
|
||||
# Extends user account
|
||||
extends@:
|
||||
type: account
|
||||
context: blueprints://user
|
||||
|
||||
#
|
||||
# HIGHLY SPECIALIZED FLEX TYPE, AVOID USING USER ACCOUNTS AS BASE FOR YOUR OWN TYPE.
|
||||
#
|
||||
|
||||
# Flex configuration
|
||||
config:
|
||||
# Administration Configuration (needs Flex Objects plugin)
|
||||
admin:
|
||||
# Admin router
|
||||
router:
|
||||
path: '/accounts/users'
|
||||
actions:
|
||||
configure:
|
||||
path: '/accounts/configure'
|
||||
redirects:
|
||||
'/user': '/accounts/users'
|
||||
'/accounts': '/accounts/users'
|
||||
|
||||
# Permissions
|
||||
permissions:
|
||||
# Primary permissions
|
||||
admin.users:
|
||||
type: crudl
|
||||
label: User Accounts
|
||||
admin.configuration.users:
|
||||
type: default
|
||||
label: Accounts Configuration
|
||||
|
||||
# Admin menu
|
||||
menu:
|
||||
base:
|
||||
location: '/accounts'
|
||||
route: '/accounts/users'
|
||||
index: 0
|
||||
title: PLUGIN_ADMIN.ACCOUNTS
|
||||
icon: fa-users
|
||||
authorize: ['admin.users.list', 'admin.super']
|
||||
priority: 6
|
||||
|
||||
# Admin template type (folder)
|
||||
template: user-accounts
|
||||
|
||||
# List view
|
||||
list:
|
||||
# Fields shown in the list view
|
||||
fields:
|
||||
username:
|
||||
link: edit
|
||||
search: true
|
||||
email:
|
||||
search: true
|
||||
fullname:
|
||||
search: true
|
||||
# Extra options
|
||||
options:
|
||||
per_page: 20
|
||||
order:
|
||||
by: username
|
||||
dir: asc
|
||||
|
||||
# Edit view
|
||||
edit:
|
||||
title:
|
||||
template: "{{ form.value('fullname') ?? form.value('username') }} <{{ form.value('email') }}>"
|
||||
|
||||
# Configure view
|
||||
configure:
|
||||
hidden: true
|
||||
authorize: 'admin.configuration.users'
|
||||
form: 'accounts'
|
||||
title:
|
||||
template: "{{ 'PLUGIN_ADMIN.ACCOUNTS'|tu }} {{ 'PLUGIN_ADMIN.CONFIGURATION'|tu }}"
|
||||
|
||||
# Site Configuration
|
||||
site:
|
||||
# Hide from flex types
|
||||
hidden: true
|
||||
templates:
|
||||
collection:
|
||||
# Lookup for the template layout files for collections of objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/collection/{LAYOUT}{EXT}'
|
||||
object:
|
||||
# Lookup for the template layout files for objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/object/{LAYOUT}{EXT}'
|
||||
defaults:
|
||||
# Default template {TYPE}; overridden by filename of this blueprint if template folder exists
|
||||
type: user-accounts
|
||||
# Default template {LAYOUT}; can be overridden in render calls (usually Twig in templates)
|
||||
layout: default
|
||||
|
||||
# Data Configuration
|
||||
data:
|
||||
object: 'Grav\Common\Flex\Types\Users\UserObject'
|
||||
collection: 'Grav\Common\Flex\Types\Users\UserCollection'
|
||||
index: 'Grav\Common\Flex\Types\Users\UserIndex'
|
||||
storage:
|
||||
class: 'Grav\Common\Flex\Types\Users\Storage\UserFileStorage'
|
||||
options:
|
||||
formatter:
|
||||
class: 'Grav\Framework\File\Formatter\YamlFormatter'
|
||||
folder: 'account://'
|
||||
pattern: '{FOLDER}/{KEY}{EXT}'
|
||||
indexed: true
|
||||
search:
|
||||
options:
|
||||
contains: 1
|
||||
fields:
|
||||
- key
|
||||
- email
|
||||
|
||||
# Regular form definition
|
||||
form:
|
||||
fields:
|
||||
username:
|
||||
flex-disabled@: exists
|
||||
disabled: false
|
||||
flex-readonly@: exists
|
||||
readonly: false
|
||||
validate:
|
||||
required: true
|
||||
115
system/blueprints/flex/user-groups.yaml
Normal file
115
system/blueprints/flex/user-groups.yaml
Normal file
@@ -0,0 +1,115 @@
|
||||
title: User Groups
|
||||
description: Manage your User Groups in Flex.
|
||||
type: flex-objects
|
||||
|
||||
# Extends user group
|
||||
extends@:
|
||||
type: group
|
||||
context: blueprints://user
|
||||
|
||||
# Flex configuration
|
||||
config:
|
||||
# Administration Configuration (needs Flex Objects plugin)
|
||||
admin:
|
||||
# Admin router
|
||||
router:
|
||||
path: '/accounts/groups'
|
||||
actions:
|
||||
configure:
|
||||
path: '/accounts/configure'
|
||||
redirects:
|
||||
'/accounts': '/accounts/groups'
|
||||
|
||||
# Permissions
|
||||
permissions:
|
||||
# Primary permissions
|
||||
admin.users:
|
||||
type: crudl
|
||||
label: User Accounts
|
||||
admin.configuration.users:
|
||||
type: default
|
||||
label: Accounts Configuration
|
||||
|
||||
# Admin menu
|
||||
menu:
|
||||
base:
|
||||
location: '/accounts'
|
||||
route: '/accounts/groups'
|
||||
index: 1
|
||||
title: PLUGIN_ADMIN.ACCOUNTS
|
||||
icon: fa-users
|
||||
authorize: ['admin.users.list', 'admin.super']
|
||||
priority: 6
|
||||
|
||||
# Admin template type (folder)
|
||||
template: user-groups
|
||||
|
||||
# List view
|
||||
list:
|
||||
# Fields shown in the list view
|
||||
fields:
|
||||
groupname:
|
||||
link: edit
|
||||
search: true
|
||||
readableName:
|
||||
search: true
|
||||
description:
|
||||
search: true
|
||||
# Extra options
|
||||
options:
|
||||
per_page: 20
|
||||
order:
|
||||
by: groupname
|
||||
dir: asc
|
||||
|
||||
# Edit view
|
||||
edit:
|
||||
title:
|
||||
template: "{{ form.value('readableName') ?? form.value('groupname') }}"
|
||||
|
||||
# Configure view
|
||||
configure:
|
||||
hidden: true
|
||||
authorize: 'admin.configuration.users'
|
||||
form: 'accounts'
|
||||
title:
|
||||
template: "{{ 'PLUGIN_ADMIN.ACCOUNTS'|tu }} {{ 'PLUGIN_ADMIN.CONFIGURATION'|tu }}"
|
||||
|
||||
# Site Configuration
|
||||
site:
|
||||
# Hide from flex types
|
||||
hidden: true
|
||||
templates:
|
||||
collection:
|
||||
# Lookup for the template layout files for collections of objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/collection/{LAYOUT}{EXT}'
|
||||
object:
|
||||
# Lookup for the template layout files for objects
|
||||
paths:
|
||||
- 'flex/{TYPE}/object/{LAYOUT}{EXT}'
|
||||
defaults:
|
||||
# Default template {TYPE}; overridden by filename of this blueprint if template folder exists
|
||||
type: user-groups
|
||||
# Default template {LAYOUT}; can be overridden in render calls (usually Twig in templates)
|
||||
layout: default
|
||||
|
||||
# Data Configuration
|
||||
data:
|
||||
object: 'Grav\Common\Flex\Types\UserGroups\UserGroupObject'
|
||||
collection: 'Grav\Common\Flex\Types\UserGroups\UserGroupCollection'
|
||||
index: 'Grav\Common\Flex\Types\UserGroups\UserGroupIndex'
|
||||
storage:
|
||||
class: 'Grav\Framework\Flex\Storage\SimpleStorage'
|
||||
options:
|
||||
formatter:
|
||||
class: 'Grav\Framework\File\Formatter\YamlFormatter'
|
||||
folder: 'user://config/groups.yaml'
|
||||
key: groupname
|
||||
search:
|
||||
options:
|
||||
contains: 1
|
||||
fields:
|
||||
- key
|
||||
- groupname
|
||||
- description
|
||||
@@ -1,4 +1,4 @@
|
||||
title: PLUGIN_ADMIN.MODULAR
|
||||
title: PLUGIN_ADMIN.MODULE
|
||||
extends@: default
|
||||
|
||||
form:
|
||||
@@ -13,7 +13,7 @@ form:
|
||||
|
||||
modular_title:
|
||||
type: spacer
|
||||
title: PLUGIN_ADMIN.MODULAR_SETUP
|
||||
title: PLUGIN_ADMIN.MODULE_SETUP
|
||||
|
||||
header.content.items:
|
||||
type: text
|
||||
@@ -34,5 +34,3 @@ form:
|
||||
help: '"desc" or "asc" are valid values'
|
||||
placeholder: desc
|
||||
size: small
|
||||
|
||||
|
||||
|
||||
71
system/blueprints/pages/partials/security.yaml
Normal file
71
system/blueprints/pages/partials/security.yaml
Normal file
@@ -0,0 +1,71 @@
|
||||
form:
|
||||
fields:
|
||||
_site:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.PAGE_ACCESS
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
|
||||
header.visibility_requires_access:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.PAGE_VISIBILITY_REQUIRES_ACCESS
|
||||
help: PLUGIN_ADMIN.PAGE_VISIBILITY_REQUIRES_ACCESS_HELP
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
|
||||
header.access:
|
||||
type: acl_picker
|
||||
label: PLUGIN_ADMIN.PAGE_ACCESS
|
||||
help: PLUGIN_ADMIN.PAGE_ACCESS_HELP
|
||||
ignore_empty: true
|
||||
data_type: access
|
||||
validate:
|
||||
type: array
|
||||
value_type: bool
|
||||
|
||||
_admin:
|
||||
security@: {or: [admin.super, admin.configuration.pages]}
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.PAGE PERMISSIONS
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
|
||||
header.permissions.inherit:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.PAGE_INHERIT_PERMISSIONS
|
||||
help: PLUGIN_ADMIN.PAGE_INHERIT_PERMISSIONS_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
header.permissions.authors:
|
||||
type: list
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.PAGE_AUTHORS
|
||||
help: PLUGIN_ADMIN.PAGE_AUTHORS_HELP
|
||||
|
||||
fields:
|
||||
value:
|
||||
type: text
|
||||
placeholder: PLUGIN_ADMIN.USERNAME
|
||||
style: vertical
|
||||
|
||||
header.permissions.groups:
|
||||
ignore@: true
|
||||
type: acl_picker
|
||||
label: PLUGIN_ADMIN.PAGE_GROUPS
|
||||
help: PLUGIN_ADMIN.PAGE_GROUPS_HELP
|
||||
ignore_empty: true
|
||||
data_type: permissions
|
||||
16
system/blueprints/pages/root.yaml
Normal file
16
system/blueprints/pages/root.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
title: PLUGIN_ADMIN.ROOT
|
||||
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
|
||||
fields:
|
||||
|
||||
tabs:
|
||||
type: tabs
|
||||
active: 1
|
||||
@@ -121,7 +121,9 @@ form:
|
||||
access:
|
||||
security@: admin.super
|
||||
type: permissions
|
||||
check_authorize: true
|
||||
label: PLUGIN_ADMIN.PERMISSIONS
|
||||
ignore_empty: true
|
||||
validate:
|
||||
type: array
|
||||
value_type: bool
|
||||
|
||||
@@ -12,5 +12,7 @@ form:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.USERNAME
|
||||
help: PLUGIN_ADMIN.USERNAME_HELP
|
||||
unset-disabled@: true
|
||||
unset-readonly@: true
|
||||
validate:
|
||||
required: true
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
title: User Accounts
|
||||
description: User Accounts
|
||||
type: flex-objects
|
||||
|
||||
extends@: 'user/account'
|
||||
|
||||
config:
|
||||
admin:
|
||||
list:
|
||||
fields:
|
||||
username:
|
||||
link: edit
|
||||
search: true
|
||||
email:
|
||||
search: true
|
||||
fullname:
|
||||
search: true
|
||||
options:
|
||||
per_page: 20
|
||||
order:
|
||||
by: username
|
||||
dir: asc
|
||||
|
||||
menu:
|
||||
list:
|
||||
route: '/accounts'
|
||||
title: Accounts
|
||||
icon: fa-users
|
||||
authorize: ['admin.users', 'admin.accounts', 'admin.super']
|
||||
@@ -3,21 +3,19 @@ form:
|
||||
validation: loose
|
||||
|
||||
fields:
|
||||
spacer:
|
||||
type: spacer
|
||||
text: '<br>'
|
||||
|
||||
groupname:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.NAME
|
||||
disabled: true
|
||||
readonly: true
|
||||
label: PLUGIN_ADMIN.GROUP_NAME
|
||||
flex-disabled@: exists
|
||||
flex-readonly@: exists
|
||||
validate:
|
||||
required: true
|
||||
|
||||
readableName:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN_PRO.READABLE_NAME
|
||||
label: PLUGIN_ADMIN.DISPLAY_NAME
|
||||
|
||||
description:
|
||||
type: text
|
||||
@@ -27,11 +25,24 @@ form:
|
||||
icon:
|
||||
type: text
|
||||
size: small
|
||||
label: PLUGIN_ADMIN_PRO.ICON
|
||||
label: PLUGIN_ADMIN.ICON
|
||||
|
||||
enabled:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.ENABLED
|
||||
highlight: 1
|
||||
default: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
access:
|
||||
type: permissions
|
||||
check_authorize: false
|
||||
label: PLUGIN_ADMIN.PERMISSIONS
|
||||
ignore_empty: true
|
||||
validate:
|
||||
type: array
|
||||
value_type: bool
|
||||
|
||||
53
system/config/permissions.yaml
Normal file
53
system/config/permissions.yaml
Normal file
@@ -0,0 +1,53 @@
|
||||
actions:
|
||||
site:
|
||||
type: access
|
||||
label: Site
|
||||
admin:
|
||||
type: access
|
||||
label: Admin
|
||||
admin.pages:
|
||||
type: access
|
||||
label: Pages
|
||||
admin.users:
|
||||
type: access
|
||||
label: User Accounts
|
||||
|
||||
types:
|
||||
default:
|
||||
type: access
|
||||
|
||||
crud:
|
||||
type: compact
|
||||
letters:
|
||||
c:
|
||||
action: create
|
||||
label: PLUGIN_ADMIN.CREATE
|
||||
r:
|
||||
action: read
|
||||
label: PLUGIN_ADMIN.READ
|
||||
u:
|
||||
action: update
|
||||
label: PLUGIN_ADMIN.UPDATE
|
||||
d:
|
||||
action: delete
|
||||
label: PLUGIN_ADMIN.DELETE
|
||||
|
||||
crudp:
|
||||
type: crud
|
||||
letters:
|
||||
p:
|
||||
action: publish
|
||||
label: PLUGIN_ADMIN.PUBLISH
|
||||
|
||||
crudl:
|
||||
type: crud
|
||||
letters:
|
||||
l:
|
||||
action: list
|
||||
label: PLUGIN_ADMIN.LIST
|
||||
|
||||
crudpl:
|
||||
type: crud
|
||||
use:
|
||||
- crudp
|
||||
- crudl
|
||||
@@ -36,3 +36,4 @@ uploads_dangerous_extensions:
|
||||
- htm
|
||||
- js
|
||||
- exe
|
||||
sanitize_svg: true
|
||||
|
||||
@@ -15,8 +15,9 @@ languages:
|
||||
supported: [] # List of languages supported. eg: [en, fr, de]
|
||||
default_lang: # Default is the first supported language. Must be one of the supported languages
|
||||
include_default_lang: true # Include the default lang prefix in all URLs
|
||||
include_default_lang_file_extension: true # If true, include language code for the default language in file extension: default.en.md
|
||||
pages_fallback_only: false # Only fallback to find page content through supported languages
|
||||
translations: true # Enable translations by default
|
||||
translations: true # If false, translation keys are used instead of translated strings
|
||||
translations_fallback: true # Fallback through supported translations if active lang doesn't exist
|
||||
session_store_active: false # Store active language in session
|
||||
http_accept_language: false # Attempt to set the language based on http_accept_language header in the browser
|
||||
@@ -27,6 +28,7 @@ home:
|
||||
hide_in_urls: false # Hide the home route in URLs
|
||||
|
||||
pages:
|
||||
type: regular # EXPERIMENTAL: Page type: regular or flex
|
||||
theme: quark # Default theme (defaults to "quark" theme)
|
||||
order:
|
||||
by: default # Order pages by "default", "alpha" or "date"
|
||||
@@ -125,6 +127,8 @@ log:
|
||||
|
||||
debugger:
|
||||
enabled: false # Enable Grav debugger and following settings
|
||||
provider: clockwork # Debugger provider: debugbar | clockwork
|
||||
censored: false # Censor potentially sensitive information (POST parameters, cookies, files, configuration and most array/object data in log messages)
|
||||
shutdown:
|
||||
close_connection: true # Close the connection before calling onShutdown(). false for debugging
|
||||
|
||||
@@ -154,16 +158,29 @@ session:
|
||||
path:
|
||||
|
||||
gpm:
|
||||
releases: stable # Set to either 'stable' or 'testing'
|
||||
releases: testing # Set to either 'stable' or 'testing'
|
||||
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
|
||||
method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
|
||||
verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help.
|
||||
official_gpm_only: true # By default GPM direct-install will only allow URLs via the official GPM proxy to ensure security
|
||||
|
||||
accounts:
|
||||
type: data # Account type: data or flex
|
||||
storage: file # Flex storage type: file or folder
|
||||
type: regular # EXPERIMENTAL: Account type: regular or flex
|
||||
storage: file # EXPERIMENTAL: Flex storage type: file or folder
|
||||
|
||||
flex:
|
||||
cache:
|
||||
index:
|
||||
enabled: true # Set to true to enable Flex index caching. Is used to cache timestamps in files
|
||||
lifetime: 60 # Lifetime of cached index in seconds (0 = infinite)
|
||||
object:
|
||||
enabled: true # Set to true to enable Flex object caching. Is used to cache object data
|
||||
lifetime: 600 # Lifetime of cached objects in seconds (0 = infinite)
|
||||
render:
|
||||
enabled: true # Set to true to enable Flex render caching. Is used to cache rendered output
|
||||
lifetime: 600 # Lifetime of cached HTML in seconds (0 = infinite)
|
||||
|
||||
strict_mode:
|
||||
yaml_compat: true # Grav 1.5+: Enables YAML backwards compatibility
|
||||
twig_compat: true # Grav 1.5+: Enables deprecated Twig autoescape setting (autoescape: false)
|
||||
blueprint_compat: true # Grav 1.7+: Enables backward compatible strict support for blueprints
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
/**
|
||||
* @package Grav\Core
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.6.6');
|
||||
define('GRAV_TESTING', false);
|
||||
define('GRAV_VERSION', '1.7.0-rc.8');
|
||||
define('GRAV_TESTING', true);
|
||||
define('DS', '/');
|
||||
|
||||
if (!defined('GRAV_PHP_MIN')) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* @package Grav\Core
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -10,8 +10,6 @@ if (!defined('GRAV_ROOT')) {
|
||||
die();
|
||||
}
|
||||
|
||||
use Grav\Installer\Install;
|
||||
|
||||
require_once __DIR__ . '/src/Grav/Installer/Install.php';
|
||||
|
||||
return Install::instance();
|
||||
return Grav\Installer\Install::instance();
|
||||
|
||||
@@ -23,7 +23,7 @@ GRAV:
|
||||
BAD_DATE: Fecha errónea
|
||||
AGO: antes
|
||||
FROM_NOW: desde ahora
|
||||
JUST_NOW: justo ahora
|
||||
JUST_NOW: hace un momento
|
||||
SECOND: segundo
|
||||
MINUTE: minuto
|
||||
HOUR: hora
|
||||
|
||||
@@ -1,11 +1,30 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\npealkiri: %1$s\n---\n\n# Viga: vigane Frontmatter'i\n\nasukoht: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'equipment'
|
||||
- 'informatsioon'
|
||||
- 'rice'
|
||||
- 'money'
|
||||
- 'species'
|
||||
- 'series'
|
||||
- 'kala'
|
||||
- 'lammas'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'inimesed'
|
||||
'man': 'mees'
|
||||
'child': 'lapsed'
|
||||
INFLECTOR_ORDINALS:
|
||||
'default': '.'
|
||||
'first': '.'
|
||||
'second': '.'
|
||||
'third': '.'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Kuupäev määramata
|
||||
BAD_DATE: Vigane kuupäev
|
||||
AGO: tagasi
|
||||
FROM_NOW: praegusest
|
||||
JUST_NOW: just nüüd
|
||||
SECOND: sekund
|
||||
MINUTE: minut
|
||||
HOUR: tundi
|
||||
@@ -60,3 +79,7 @@ GRAV:
|
||||
- 'reede'
|
||||
- 'laupäev'
|
||||
- 'pühapäev'
|
||||
CRON:
|
||||
EVERY: iga
|
||||
EVERY_MONTH: iga kuu
|
||||
TEXT_PERIOD: Iga <b />
|
||||
|
||||
@@ -14,6 +14,8 @@ GRAV:
|
||||
'/sis$/i': 'ses'
|
||||
'/([ti])um$/i': '\1a'
|
||||
'/(buffal|tomat)o$/i': '\1es'
|
||||
'/(bu)s$/i': 'Bus'
|
||||
'/(alias|status)/i': 'alias|status'
|
||||
'/(ax|test)is$/i': '\1s'
|
||||
'/s$/i': 's'
|
||||
'/$/': 's'
|
||||
|
||||
@@ -11,6 +11,8 @@ GRAV:
|
||||
- 'fish'
|
||||
- 'sheep'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Engin dagsetning gefin
|
||||
BAD_DATE: Röng dagsetning
|
||||
AGO: síðan
|
||||
JUST_NOW: í þessu
|
||||
SECOND: sekúndu
|
||||
@@ -45,6 +47,7 @@ GRAV:
|
||||
DEC_PLURAL: árat
|
||||
FORM:
|
||||
VALIDATION_FAIL: <b>Sannvottun mistókst:</b>
|
||||
INVALID_INPUT: Ógilt inntak í
|
||||
MISSING_REQUIRED_FIELD: 'Vantar nauðsynlegan reit:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'janúar'
|
||||
@@ -67,3 +70,11 @@ GRAV:
|
||||
- 'Föstudagur'
|
||||
- 'Laugardagur'
|
||||
- 'Sunnudagur'
|
||||
CRON:
|
||||
TEXT_TIME: ' á <b />:<b />'
|
||||
TEXT_DOW: ' á <b />'
|
||||
TEXT_MONTH: ' af <b />'
|
||||
TEXT_DOM: ' á <b />'
|
||||
ERROR1: Merkið %s er ekki stutt!
|
||||
ERROR3: Það ætti að setja jquery_element inn í stillingar jqCron
|
||||
ERROR4: Óþekkt segð
|
||||
|
||||
@@ -35,3 +35,12 @@ GRAV:
|
||||
- 'Outubro'
|
||||
- 'Novembro'
|
||||
- 'Dezembro'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'equipment'
|
||||
- 'information'
|
||||
- 'arroz'
|
||||
- 'money'
|
||||
- 'species'
|
||||
- 'series'
|
||||
- 'fish'
|
||||
- 'sheep'
|
||||
|
||||
@@ -1,10 +1,75 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Chyba: Chybný frontmatter\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS:
|
||||
'/(quiz)$/i': '\1zes'
|
||||
'/^(ox)$/i': '\1en'
|
||||
'/([m|l])ouse$/i': '\1ice'
|
||||
'/(matr|vert|ind)ix|ex$/i': '\1ices'
|
||||
'/(x|ch|ss|sh)$/i': '\1es'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([^aeiouy]|qu)y$/i': '\1ies'
|
||||
'/(hive)$/i': '\1s'
|
||||
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
|
||||
'/sis$/i': 'ses'
|
||||
'/([ti])um$/i': '\1a'
|
||||
'/(buffal|tomat)o$/i': '\1oes'
|
||||
'/(bu)s$/i': '\1ses'
|
||||
'/(alias|status)/i': '\1es'
|
||||
'/(octop|vir)us$/i': '\1i'
|
||||
'/(ax|test)is$/i': '\1es'
|
||||
'/s$/i': 's'
|
||||
'/$/': 's'
|
||||
INFLECTOR_SINGULAR:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(matr)ices$/i': '\1ix'
|
||||
'/(vert|ind)ices$/i': '\1ex'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1us'
|
||||
'/(cris|ax|test)es$/i': '\1is'
|
||||
'/(shoe)s$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/([m|l])ice$/i': '\1ouse'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
'/(m)ovies$/i': '\1ovie'
|
||||
'/(s)eries$/i': '\1eries'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([lr])ves$/i': '\1f'
|
||||
'/(tive)s$/i': '\1'
|
||||
'/(hive)s$/i': '\1'
|
||||
'/([^f])ves$/i': '\1fe'
|
||||
'/(^analy)ses$/i': '\1sis'
|
||||
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis'
|
||||
'/([ti])a$/i': '\1um'
|
||||
'/(n)ews$/i': '\1ews'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'vybavenie'
|
||||
- 'informácie'
|
||||
- 'ryža'
|
||||
- 'peniaze'
|
||||
- 'druhy'
|
||||
- 'séria'
|
||||
- 'ryba'
|
||||
- 'ovce'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'ľudia'
|
||||
'man': 'muži'
|
||||
'child': 'deti'
|
||||
'sex': 'pohlavia'
|
||||
'move': 'pohyby'
|
||||
INFLECTOR_ORDINALS:
|
||||
'default': '.'
|
||||
'first': '.'
|
||||
'second': '.'
|
||||
'third': '.'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Neposkytnutý žiaden dátum
|
||||
BAD_DATE: Nesprávny dátum
|
||||
AGO: pred
|
||||
FROM_NOW: odteraz
|
||||
JUST_NOW: práve teraz
|
||||
SECOND: sekunda
|
||||
MINUTE: minúta
|
||||
HOUR: hodina
|
||||
@@ -14,10 +79,12 @@ GRAV:
|
||||
YEAR: rok
|
||||
DECADE: desaťročie
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: hod
|
||||
WK: t
|
||||
MO: m
|
||||
YR: r
|
||||
DEC: dec
|
||||
SECOND_PLURAL: sekúnd
|
||||
MINUTE_PLURAL: minút
|
||||
HOUR_PLURAL: hodín
|
||||
@@ -58,3 +125,20 @@ GRAV:
|
||||
- 'Piatok'
|
||||
- 'Sobota'
|
||||
- 'Nedeľa'
|
||||
CRON:
|
||||
EVERY: každý
|
||||
EVERY_HOUR: každú hodinu
|
||||
EVERY_MINUTE: každú minútu
|
||||
EVERY_DAY_OF_WEEK: každý deň v týždni
|
||||
EVERY_DAY_OF_MONTH: každý deň v mesiaci
|
||||
EVERY_MONTH: každý mesiac
|
||||
TEXT_PERIOD: Každý <b />
|
||||
TEXT_MINS: ' at <b /> minute(s) past the hour'
|
||||
TEXT_TIME: ' at <b />:<b />'
|
||||
TEXT_DOW: ' on <b />'
|
||||
TEXT_MONTH: ' of <b />'
|
||||
TEXT_DOM: ' on <b />'
|
||||
ERROR1: Tag %s nieje podporovaný!
|
||||
ERROR2: Chybný počet položiek
|
||||
ERROR3: jquery_element musí byť nastavený v nastaveniach pre jqCron
|
||||
ERROR4: Neznámy výraz
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "--- titel: %1$s --- # Fel: Ogiltig Frontmatter-sökväg: `%2$s` **%3$s** ``` %4$s ```"
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'utrustning'
|
||||
- 'information'
|
||||
- 'ris'
|
||||
- 'pengar'
|
||||
- 'arter'
|
||||
- 'serier'
|
||||
- 'fisk'
|
||||
- 'får'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'personer'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Inget datum har angivits
|
||||
BAD_DATE: Ogiltigt datum
|
||||
|
||||
@@ -1,24 +1,44 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# 錯誤: 不正確的 Frontmatter\n\n路徑: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: 沒有提供日期
|
||||
BAD_DATE: 錯誤日期
|
||||
AGO: 之前
|
||||
FROM_NOW: 之後
|
||||
JUST_NOW: 剛剛
|
||||
SECOND: 秒
|
||||
MINUTE: 分
|
||||
HOUR: 小時
|
||||
DAY: 天
|
||||
WEEK: 週
|
||||
MONTH: 月
|
||||
YEAR: 年
|
||||
DECADE: 十年
|
||||
SEC: 秒
|
||||
MIN: 分
|
||||
HR: 小時
|
||||
WK: 週
|
||||
MO: 月
|
||||
YR: 年
|
||||
DEC: 十年
|
||||
SECOND_PLURAL: 秒
|
||||
MINUTE_PLURAL: 分
|
||||
HOUR_PLURAL: 時
|
||||
DAY_PLURAL: 日
|
||||
WEEK_PLURAL: 周
|
||||
HOUR_PLURAL: 小時
|
||||
DAY_PLURAL: 天
|
||||
WEEK_PLURAL: 週
|
||||
MONTH_PLURAL: 月
|
||||
YEAR_PLURAL: 年
|
||||
DECADE_PLURAL: 十年
|
||||
SEC_PLURAL: 秒
|
||||
MIN_PLURAL: 分
|
||||
HR_PLURAL: 時
|
||||
WK_PLURAL: 周
|
||||
WK_PLURAL: 週
|
||||
MO_PLURAL: 月
|
||||
YR_PLURAL: 年
|
||||
DEC_PLURAL: 十年
|
||||
FORM:
|
||||
MISSING_REQUIRED_FIELD: 遺漏必填欄位:
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- '一月'
|
||||
- '二月'
|
||||
|
||||
@@ -1,57 +1,122 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# 錯誤: 不正確的 Frontmatter\n\n路徑: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
FRONTMATTER_ERROR_PAGE: "---\n标题: %1$s\n---\n\n# 错误:无效参数\n\n位置: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS:
|
||||
'/(quiz)$/i': '\1zes'
|
||||
'/^(ox)$/i': '\1en'
|
||||
'/([m|l])ouse$/i': '\1ice'
|
||||
'/(matr|vert|ind)ix|ex$/i': '\1ices'
|
||||
'/(x|ch|ss|sh)$/i': '\1es'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([^aeiouy]|qu)y$/i': '\1ies'
|
||||
'/(hive)$/i': '\1s'
|
||||
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
|
||||
'/sis$/i': 'ses'
|
||||
'/([ti])um$/i': '\1a'
|
||||
'/(buffal|tomat)o$/i': '\1oes'
|
||||
'/(bu)s$/i': '\1ses'
|
||||
'/(alias|status)/i': '\1es'
|
||||
'/(octop|vir)us$/i': '\1i'
|
||||
'/(ax|test)is$/i': '\1es'
|
||||
'/s$/i': 's'
|
||||
'/$/': 's'
|
||||
INFLECTOR_SINGULAR:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(matr)ices$/i': '\1ix'
|
||||
'/(vert|ind)ices$/i': '\1ex'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1us'
|
||||
'/(cris|ax|test)es$/i': '\1is'
|
||||
'/(shoe)s$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/([m|l])ice$/i': '\1ouse'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
'/(m)ovies$/i': '\1ovie'
|
||||
'/(s)eries$/i': '\1eries'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([lr])ves$/i': '\1f'
|
||||
'/(tive)s$/i': '\1'
|
||||
'/(hive)s$/i': '\1'
|
||||
'/([^f])ves$/i': '\1fe'
|
||||
'/(^analy)ses$/i': '\1sis'
|
||||
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis'
|
||||
'/([ti])a$/i': '\1um'
|
||||
'/(n)ews$/i': '\1ews'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- '装备'
|
||||
- '信息'
|
||||
- '大米'
|
||||
- '钱'
|
||||
- '物种'
|
||||
- '系列'
|
||||
- '鱼'
|
||||
- '羊'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': '人员'
|
||||
'man': '男人'
|
||||
'child': '儿童'
|
||||
'sex': '性别'
|
||||
'move': '移动'
|
||||
INFLECTOR_ORDINALS:
|
||||
'default': 'th'
|
||||
'first': 'st'
|
||||
'second': 'md'
|
||||
'third': 'rd'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: 沒有提供日期
|
||||
BAD_DATE: 錯誤日期
|
||||
AGO: 之前
|
||||
FROM_NOW: 之後
|
||||
JUST_NOW: 剛剛
|
||||
NO_DATE_PROVIDED: 无日期信息
|
||||
BAD_DATE: 无效日期
|
||||
AGO: 前
|
||||
FROM_NOW: 距今
|
||||
JUST_NOW: 刚刚
|
||||
SECOND: 秒
|
||||
MINUTE: 分
|
||||
HOUR: 小時
|
||||
MINUTE: 分钟
|
||||
HOUR: 小时
|
||||
DAY: 天
|
||||
WEEK: 週
|
||||
WEEK: 周
|
||||
MONTH: 月
|
||||
YEAR: 年
|
||||
DECADE: 十年
|
||||
SEC: 秒
|
||||
MIN: 分
|
||||
HR: 小時
|
||||
WK: 週
|
||||
MIN: 分钟
|
||||
HR: 小时
|
||||
WK: 周
|
||||
MO: 月
|
||||
YR: 年
|
||||
DEC: 十年
|
||||
DEC: 年代
|
||||
SECOND_PLURAL: 秒
|
||||
MINUTE_PLURAL: 分
|
||||
HOUR_PLURAL: 小時
|
||||
HOUR_PLURAL: 小时
|
||||
DAY_PLURAL: 天
|
||||
WEEK_PLURAL: 週
|
||||
WEEK_PLURAL: 周
|
||||
MONTH_PLURAL: 月
|
||||
YEAR_PLURAL: 年
|
||||
DECADE_PLURAL: 十年
|
||||
SEC_PLURAL: 秒
|
||||
MIN_PLURAL: 分
|
||||
HR_PLURAL: 時
|
||||
WK_PLURAL: 週
|
||||
HR_PLURAL: 时
|
||||
WK_PLURAL: 周
|
||||
MO_PLURAL: 月
|
||||
YR_PLURAL: 年
|
||||
DEC_PLURAL: 十年
|
||||
DEC_PLURAL: 年代
|
||||
FORM:
|
||||
MISSING_REQUIRED_FIELD: 遺漏必填欄位:
|
||||
VALIDATION_FAIL: <b>验证失败:</b>
|
||||
INVALID_INPUT: 无效输入
|
||||
MISSING_REQUIRED_FIELD: 必填字段缺失:
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- '一月'
|
||||
- '二月'
|
||||
- '三月'
|
||||
- '四月'
|
||||
- '五月'
|
||||
- '六月'
|
||||
- '七月'
|
||||
- '八月'
|
||||
- '九月'
|
||||
- '十月'
|
||||
- '十一月'
|
||||
- '十二月'
|
||||
- '1月'
|
||||
- '2月'
|
||||
- '3月'
|
||||
- '4月'
|
||||
- '5月'
|
||||
- '6月'
|
||||
- '7月'
|
||||
- '8月'
|
||||
- '9月'
|
||||
- '10月'
|
||||
- '11月'
|
||||
- '12月'
|
||||
DAYS_OF_THE_WEEK:
|
||||
- '星期一'
|
||||
- '星期二'
|
||||
@@ -60,4 +125,20 @@ GRAV:
|
||||
- '星期五'
|
||||
- '星期六'
|
||||
- '星期日'
|
||||
|
||||
CRON:
|
||||
EVERY: 每隔
|
||||
EVERY_HOUR: 每小时
|
||||
EVERY_MINUTE: 每分钟
|
||||
EVERY_DAY_OF_WEEK: 一周中的每一天
|
||||
EVERY_DAY_OF_MONTH: 月份中的每一天
|
||||
EVERY_MONTH: 每月
|
||||
TEXT_PERIOD: 所有 <b />
|
||||
TEXT_MINS: ' 在 <b /> 小时过后的分钟'
|
||||
TEXT_TIME: ' 在 <b />:<b />'
|
||||
TEXT_DOW: ' on <b />'
|
||||
TEXT_MONTH: ' of <b />'
|
||||
TEXT_DOM: ' on <b />'
|
||||
ERROR1: 不支持分享类型 %s
|
||||
ERROR2: 无效数字
|
||||
ERROR3: 请在 jqCron 设置中设定 jquery_element
|
||||
ERROR4: 无法识别表达式
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Core
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -17,11 +17,22 @@ if (is_file($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $_SERVER['SCRIPT_N
|
||||
return false;
|
||||
}
|
||||
|
||||
$grav_index = 'index.php';
|
||||
|
||||
/* Check the GRAV_BASEDIR environment variable and use if set */
|
||||
|
||||
$grav_basedir = getenv('GRAV_BASEDIR') ?: '';
|
||||
if ($grav_basedir) {
|
||||
$grav_index = ltrim($grav_basedir, '/') . DIRECTORY_SEPARATOR . $grav_index;
|
||||
$grav_basedir = DIRECTORY_SEPARATOR . trim($grav_basedir, DIRECTORY_SEPARATOR);
|
||||
define('GRAV_ROOT', str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . $grav_basedir);
|
||||
}
|
||||
|
||||
$_SERVER = array_merge($_SERVER, $_ENV);
|
||||
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = DIRECTORY_SEPARATOR . 'index.php';
|
||||
$_SERVER['PHP_SELF'] = DIRECTORY_SEPARATOR . 'index.php';
|
||||
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'] . $grav_basedir .DIRECTORY_SEPARATOR . 'index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = $grav_basedir . DIRECTORY_SEPARATOR . 'index.php';
|
||||
$_SERVER['PHP_SELF'] = $grav_basedir . DIRECTORY_SEPARATOR . 'index.php';
|
||||
|
||||
error_log(sprintf('%s:%d [%d]: %s', $_SERVER['REMOTE_ADDR'], $_SERVER['REMOTE_PORT'], http_response_code(), $_SERVER['REQUEST_URI']), 4);
|
||||
|
||||
require 'index.php';
|
||||
require $grav_index;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -37,29 +37,43 @@ class Assets extends PropertyObject
|
||||
/** @const Regex to match JavaScript files */
|
||||
const JS_REGEX = '/.\.js$/i';
|
||||
|
||||
/** @var string */
|
||||
protected $assets_dir;
|
||||
/** @var string */
|
||||
protected $assets_url;
|
||||
|
||||
/** @var array */
|
||||
protected $assets_css = [];
|
||||
/** @var array */
|
||||
protected $assets_js = [];
|
||||
|
||||
// Config Options
|
||||
// Following variables come from the configuration:
|
||||
/** @var bool */
|
||||
protected $css_pipeline;
|
||||
/** @var bool */
|
||||
protected $css_pipeline_include_externals;
|
||||
/** @var bool */
|
||||
protected $css_pipeline_before_excludes;
|
||||
/** @var bool */
|
||||
protected $js_pipeline;
|
||||
/** @var bool */
|
||||
protected $js_pipeline_include_externals;
|
||||
/** @var bool */
|
||||
protected $js_pipeline_before_excludes;
|
||||
/** @var array */
|
||||
protected $pipeline_options = [];
|
||||
|
||||
|
||||
/** @var \Closure|string */
|
||||
protected $fetch_command;
|
||||
/** @var string */
|
||||
protected $autoload;
|
||||
/** @var bool */
|
||||
protected $enable_asset_timestamp;
|
||||
/** @var array|null */
|
||||
protected $collections;
|
||||
/** @var string */
|
||||
protected $timestamp;
|
||||
|
||||
|
||||
/**
|
||||
* Initialization called in the Grav lifecycle to initialize the Assets with appropriate configuration
|
||||
*/
|
||||
@@ -172,7 +186,8 @@ class Assets extends PropertyObject
|
||||
// If pipeline disabled, set to position if provided, else after
|
||||
if (isset($options['pipeline'])) {
|
||||
if ($options['pipeline'] === false) {
|
||||
$excludes = strtolower($type . '_pipeline_before_excludes');
|
||||
$exclude_type = ($type === $this::JS_TYPE || $type === $this::INLINE_JS_TYPE) ? $this::JS_TYPE : $this::CSS_TYPE;
|
||||
$excludes = strtolower($exclude_type . '_pipeline_before_excludes');
|
||||
if ($this->{$excludes}) {
|
||||
$default = 'after';
|
||||
} else {
|
||||
@@ -201,7 +216,6 @@ class Assets extends PropertyObject
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +225,7 @@ class Assets extends PropertyObject
|
||||
*/
|
||||
public function addCss($asset)
|
||||
{
|
||||
return $this->addType(Assets::CSS_COLLECTION,Assets::CSS_TYPE, $asset, $this->unifyLegacyArguments(\func_get_args(), Assets::CSS_TYPE));
|
||||
return $this->addType(Assets::CSS_COLLECTION, Assets::CSS_TYPE, $asset, $this->unifyLegacyArguments(\func_get_args(), Assets::CSS_TYPE));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,13 +279,12 @@ class Assets extends PropertyObject
|
||||
|
||||
protected function filterAssets($assets, $key, $value, $sort = false)
|
||||
{
|
||||
$results = array_filter($assets, function($asset) use ($key, $value) {
|
||||
$results = array_filter($assets, function ($asset) use ($key, $value) {
|
||||
|
||||
if ($key === 'position' && $value === 'pipeline') {
|
||||
|
||||
$type = $asset->getType();
|
||||
|
||||
if ($asset->getRemote() && $this->{$type . '_pipeline_include_externals'} === false) {
|
||||
if ($asset->getRemote() && $this->{$type . '_pipeline_include_externals'} === false && $asset['position'] === 'pipeline') {
|
||||
if ($this->{$type . '_pipeline_before_excludes'}) {
|
||||
$asset->setPosition('after');
|
||||
} else {
|
||||
@@ -279,9 +292,11 @@ class Assets extends PropertyObject
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
if ($asset[$key] === $value) return true;
|
||||
|
||||
if ($asset[$key] === $value) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -295,11 +310,8 @@ class Assets extends PropertyObject
|
||||
|
||||
protected function sortAssets($assets)
|
||||
{
|
||||
uasort ($assets, function($a, $b) {
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return $a['order'] - $b['order'];
|
||||
}
|
||||
return $b['priority'] - $a['priority'];
|
||||
uasort($assets, static function ($a, $b) {
|
||||
return $b['priority'] <=> $a['priority'] ?: $a['order'] <=> $b['order'];
|
||||
});
|
||||
return $assets;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -25,29 +25,46 @@ abstract class BaseAsset extends PropertyObject
|
||||
/** @const Regex to match CSS import content */
|
||||
protected const CSS_IMPORT_REGEX = '{@import(.*?);}';
|
||||
|
||||
/** @var string|false */
|
||||
protected $asset;
|
||||
|
||||
/** @var string */
|
||||
protected $asset_type;
|
||||
/** @var int */
|
||||
protected $order;
|
||||
/** @var string */
|
||||
protected $group;
|
||||
/** @var string */
|
||||
protected $position;
|
||||
/** @var int */
|
||||
protected $priority;
|
||||
/** @var array */
|
||||
protected $attributes = [];
|
||||
|
||||
|
||||
/** @var string */
|
||||
protected $timestamp;
|
||||
/** @var int|false */
|
||||
protected $modified;
|
||||
/** @var bool */
|
||||
protected $remote;
|
||||
/** @var string */
|
||||
protected $query = '';
|
||||
|
||||
// Private Bits
|
||||
private $base_url;
|
||||
private $fetch_command;
|
||||
/** @var bool */
|
||||
private $css_rewrite = false;
|
||||
/** @var bool */
|
||||
private $css_minify = false;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract function render();
|
||||
|
||||
/**
|
||||
* BaseAsset constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$base_config = [
|
||||
@@ -64,6 +81,11 @@ abstract class BaseAsset extends PropertyObject
|
||||
parent::__construct($elements, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|false $asset
|
||||
* @param array $options
|
||||
* @return $this|false
|
||||
*/
|
||||
public function init($asset, $options)
|
||||
{
|
||||
$config = Grav::instance()['config'];
|
||||
@@ -88,7 +110,6 @@ abstract class BaseAsset extends PropertyObject
|
||||
|
||||
// Move this to render?
|
||||
if (!$this->remote) {
|
||||
|
||||
$asset_parts = parse_url($asset);
|
||||
if (isset($asset_parts['query'])) {
|
||||
$this->query = $asset_parts['query'];
|
||||
@@ -122,19 +143,30 @@ abstract class BaseAsset extends PropertyObject
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|false
|
||||
*/
|
||||
public function getAsset()
|
||||
{
|
||||
return $this->asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getRemote()
|
||||
{
|
||||
return $this->remote;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $position
|
||||
* @return $this
|
||||
*/
|
||||
public function setPosition($position)
|
||||
{
|
||||
$this->position = $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -163,7 +195,7 @@ abstract class BaseAsset extends PropertyObject
|
||||
*
|
||||
* @param string $asset the asset string reference
|
||||
*
|
||||
* @return string the final link url to the asset
|
||||
* @return string|false the final link url to the asset
|
||||
*/
|
||||
protected function buildLocalLink($asset)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,11 @@ use Grav\Common\Utils;
|
||||
|
||||
class Css extends BaseAsset
|
||||
{
|
||||
/**
|
||||
* Css constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$base_options = [
|
||||
@@ -28,10 +33,13 @@ class Css extends BaseAsset
|
||||
parent::__construct($merged_attributes, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if (isset($this->attributes['loading']) && $this->attributes['loading'] === 'inline') {
|
||||
$buffer = $this->gatherLinks( [$this], self::CSS_ASSET);
|
||||
$buffer = $this->gatherLinks([$this], self::CSS_ASSET);
|
||||
return "<style>\n" . trim($buffer) . "\n</style>\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,11 @@ use Grav\Common\Utils;
|
||||
|
||||
class InlineCss extends BaseAsset
|
||||
{
|
||||
/**
|
||||
* InlineCss constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$base_options = [
|
||||
@@ -25,6 +30,9 @@ class InlineCss extends BaseAsset
|
||||
parent::__construct($merged_attributes, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return '<style' . $this->renderAttributes(). ">\n" . trim($this->asset) . "\n</style>\n";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,11 @@ use Grav\Common\Utils;
|
||||
|
||||
class InlineJs extends BaseAsset
|
||||
{
|
||||
/**
|
||||
* InlineJs constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$base_options = [
|
||||
@@ -25,6 +30,9 @@ class InlineJs extends BaseAsset
|
||||
parent::__construct($merged_attributes, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return '<script' . $this->renderAttributes(). ">\n" . trim($this->asset) . "\n</script>\n";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,11 @@ use Grav\Common\Utils;
|
||||
|
||||
class Js extends BaseAsset
|
||||
{
|
||||
/**
|
||||
* Js constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
public function __construct(array $elements = [], $key = null)
|
||||
{
|
||||
$base_options = [
|
||||
@@ -24,10 +29,13 @@ class Js extends BaseAsset
|
||||
parent::__construct($merged_attributes, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if (isset($this->attributes['loading']) && $this->attributes['loading'] === 'inline') {
|
||||
$buffer = $this->gatherLinks( [$this], self::JS_ASSET);
|
||||
$buffer = $this->gatherLinks([$this], self::JS_ASSET);
|
||||
return '<script' . $this->renderAttributes() . ">\n" . trim($buffer) . "\n</script>\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -35,35 +35,40 @@ class Pipeline extends PropertyObject
|
||||
|
||||
protected const FIRST_FORWARDSLASH_REGEX = '{^\/{1}\w}';
|
||||
|
||||
protected $css_minify;
|
||||
protected $css_minify_windows;
|
||||
protected $css_rewrite;
|
||||
// Following variables come from the configuration:
|
||||
/** @var bool */
|
||||
protected $css_minify = false;
|
||||
/** @var bool */
|
||||
protected $css_minify_windows = false;
|
||||
/** @var bool */
|
||||
protected $css_rewrite = false;
|
||||
/** @var bool */
|
||||
protected $css_pipeline_include_externals = true;
|
||||
/** @var bool */
|
||||
protected $js_minify = false;
|
||||
/** @var bool */
|
||||
protected $js_minify_windows = false;
|
||||
/** @var bool */
|
||||
protected $js_pipeline_include_externals = true;
|
||||
|
||||
protected $js_minify;
|
||||
protected $js_minify_windows;
|
||||
|
||||
protected $base_url;
|
||||
/** @var string */
|
||||
protected $assets_dir;
|
||||
/** @var string */
|
||||
protected $assets_url;
|
||||
/** @var string */
|
||||
protected $timestamp;
|
||||
/** @var array */
|
||||
protected $attributes;
|
||||
protected $query;
|
||||
/** @var string */
|
||||
protected $query = '';
|
||||
/** @var string */
|
||||
protected $asset;
|
||||
|
||||
/**
|
||||
* Closure used by the pipeline to fetch assets.
|
||||
*
|
||||
* Useful when file_get_contents() function is not available in your PHP
|
||||
* installation or when you want to apply any kind of preprocessing to
|
||||
* your assets before they get pipelined.
|
||||
*
|
||||
* The closure will receive as the only parameter a string with the path/URL of the asset and
|
||||
* it should return the content of the asset file as a string.
|
||||
*
|
||||
* @var \Closure
|
||||
* Pipeline constructor.
|
||||
* @param array $elements
|
||||
* @param string|null $key
|
||||
*/
|
||||
protected $fetch_command;
|
||||
|
||||
public function __construct(array $elements = [], ?string $key = null)
|
||||
{
|
||||
parent::__construct($elements, $key);
|
||||
@@ -88,7 +93,6 @@ class Pipeline extends PropertyObject
|
||||
* @param array $assets
|
||||
* @param string $group
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return bool|string URL or generated content if available, else false
|
||||
*/
|
||||
public function renderCss($assets, $group, $attributes = [])
|
||||
@@ -152,7 +156,6 @@ class Pipeline extends PropertyObject
|
||||
* @param array $assets
|
||||
* @param string $group
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return bool|string URL or generated content if available, else false
|
||||
*/
|
||||
public function renderJs($assets, $group, $attributes = [])
|
||||
@@ -217,7 +220,6 @@ class Pipeline extends PropertyObject
|
||||
* @param string $file the css source file
|
||||
* @param string $dir , $local relative path to the css file
|
||||
* @param bool $local is this a local or remote asset
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function cssRewrite($file, $dir, $local)
|
||||
@@ -244,16 +246,16 @@ class Pipeline extends PropertyObject
|
||||
|
||||
$new_url = ($local ? $this->base_url: '') . $old_url;
|
||||
|
||||
$fixed = str_replace($matches[2], $new_url, $matches[0]);
|
||||
|
||||
return $fixed;
|
||||
return str_replace($matches[2], $new_url, $matches[0]);
|
||||
}, $file);
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldMinify($type = 'css')
|
||||
{
|
||||
$check = $type . '_minify';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets\Traits
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,23 @@ use Grav\Common\Utils;
|
||||
|
||||
trait AssetUtilsTrait
|
||||
{
|
||||
/**
|
||||
* @var \Closure|null
|
||||
*
|
||||
* Closure used by the pipeline to fetch assets.
|
||||
*
|
||||
* Useful when file_get_contents() function is not available in your PHP
|
||||
* installation or when you want to apply any kind of preprocessing to
|
||||
* your assets before they get pipelined.
|
||||
*
|
||||
* The closure will receive as the only parameter a string with the path/URL of the asset and
|
||||
* it should return the content of the asset file as a string.
|
||||
*/
|
||||
protected $fetch_command;
|
||||
|
||||
/** @var string */
|
||||
protected $base_url;
|
||||
|
||||
/**
|
||||
* Determine whether a link is local or remote.
|
||||
* Understands both "http://" and "https://" as well as protocol agnostic links "//"
|
||||
@@ -38,7 +55,6 @@ trait AssetUtilsTrait
|
||||
*
|
||||
* @param array $assets
|
||||
* @param bool $css
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function gatherLinks(array $assets, $css = true)
|
||||
@@ -69,7 +85,8 @@ trait AssetUtilsTrait
|
||||
$link = ROOT_DIR . $relative_path;
|
||||
}
|
||||
|
||||
$file = ($this->fetch_command instanceof \Closure) ? @$this->fetch_command->__invoke($link) : @file_get_contents($link);
|
||||
// TODO: looks like this is not being used.
|
||||
$file = $this->fetch_command instanceof \Closure ? @$this->fetch_command->__invoke($link) : @file_get_contents($link);
|
||||
|
||||
// No file found, skip it...
|
||||
if ($file === false) {
|
||||
@@ -102,7 +119,6 @@ trait AssetUtilsTrait
|
||||
* Moves @import statements to the top of the file per the CSS specification
|
||||
*
|
||||
* @param string $file the file containing the combined CSS files
|
||||
*
|
||||
* @return string the modified file with any @imports at the top of the file
|
||||
*/
|
||||
protected function moveImports($file)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets\Traits
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,6 @@ use Grav\Common\Assets;
|
||||
|
||||
trait LegacyAssetsTrait
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $args
|
||||
* @param string $type
|
||||
@@ -24,39 +23,50 @@ trait LegacyAssetsTrait
|
||||
// First argument is always the asset
|
||||
array_shift($args);
|
||||
|
||||
if (\count($args) === 0) {
|
||||
if (count($args) === 0) {
|
||||
return [];
|
||||
}
|
||||
if (\count($args) === 1 && \is_array($args[0])) {
|
||||
// New options array format
|
||||
if (count($args) === 1 && is_array($args[0])) {
|
||||
return $args[0];
|
||||
}
|
||||
// Handle obscure case where options array is mixed with a priority
|
||||
if (count($args) === 2 && is_array($args[0]) && is_int($args[1])) {
|
||||
$arguments = $args[0];
|
||||
$arguments['priority'] = $args[1];
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case(Assets::INLINE_CSS_TYPE):
|
||||
$defaults = ['priority' => null, 'group' => null];
|
||||
$arguments = $this->createArgumentsFromLegacy($args, $defaults);
|
||||
break;
|
||||
|
||||
case(Assets::JS_TYPE):
|
||||
case (Assets::JS_TYPE):
|
||||
$defaults = ['priority' => null, 'pipeline' => true, 'loading' => null, 'group' => null];
|
||||
$arguments = $this->createArgumentsFromLegacy($args, $defaults);
|
||||
break;
|
||||
|
||||
case(Assets::INLINE_JS_TYPE):
|
||||
case (Assets::INLINE_JS_TYPE):
|
||||
$defaults = ['priority' => null, 'group' => null, 'attributes' => null];
|
||||
$arguments = $this->createArgumentsFromLegacy($args, $defaults);
|
||||
|
||||
// special case to handle old attributes being passed in
|
||||
if (isset($arguments['attributes'])) {
|
||||
$old_attributes = $arguments['attributes'];
|
||||
$arguments = array_merge($arguments, $old_attributes);
|
||||
if (is_array($old_attributes)) {
|
||||
$arguments = array_merge($arguments, $old_attributes);
|
||||
} else {
|
||||
$arguments['type'] = $old_attributes;
|
||||
}
|
||||
}
|
||||
unset($arguments['attributes']);
|
||||
|
||||
break;
|
||||
|
||||
case (Assets::INLINE_CSS_TYPE):
|
||||
$defaults = ['priority' => null, 'group' => null];
|
||||
$arguments = $this->createArgumentsFromLegacy($args, $defaults);
|
||||
break;
|
||||
|
||||
default:
|
||||
case(Assets::CSS_TYPE):
|
||||
case (Assets::CSS_TYPE):
|
||||
$defaults = ['priority' => null, 'pipeline' => true, 'group' => null, 'loading' => null];
|
||||
$arguments = $this->createArgumentsFromLegacy($args, $defaults);
|
||||
}
|
||||
@@ -64,6 +74,11 @@ trait LegacyAssetsTrait
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args
|
||||
* @param array $defaults
|
||||
* @return array
|
||||
*/
|
||||
protected function createArgumentsFromLegacy(array $args, array $defaults)
|
||||
{
|
||||
// Remove arguments with old default values.
|
||||
@@ -86,8 +101,7 @@ trait LegacyAssetsTrait
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @return \Grav\Common\Assets
|
||||
* @return Assets
|
||||
* @deprecated Please use dynamic method with ['loading' => 'async'].
|
||||
*/
|
||||
public function addAsyncJs($asset, $priority = 10, $pipeline = true, $group = 'head')
|
||||
@@ -104,8 +118,7 @@ trait LegacyAssetsTrait
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @return \Grav\Common\Assets
|
||||
* @return Assets
|
||||
* @deprecated Please use dynamic method with ['loading' => 'defer'].
|
||||
*/
|
||||
public function addDeferJs($asset, $priority = 10, $pipeline = true, $group = 'head')
|
||||
@@ -114,5 +127,4 @@ trait LegacyAssetsTrait
|
||||
|
||||
return $this->addJs($asset, $priority, $pipeline, 'defer', $group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Assets\Traits
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,6 @@ trait TestingAssetsTrait
|
||||
* Determines if an asset exists as a collection, CSS or JS reference
|
||||
*
|
||||
* @param string $asset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($asset)
|
||||
@@ -39,7 +38,6 @@ trait TestingAssetsTrait
|
||||
* Set the array of collections explicitly
|
||||
*
|
||||
* @param array $collections
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCollection($collections)
|
||||
@@ -54,7 +52,7 @@ trait TestingAssetsTrait
|
||||
* If a $key is provided, it will try to return only that asset
|
||||
* else it will return null
|
||||
*
|
||||
* @param null|string $key the asset key
|
||||
* @param string|null $key the asset key
|
||||
* @return array
|
||||
*/
|
||||
public function getCss($key = null)
|
||||
@@ -73,7 +71,7 @@ trait TestingAssetsTrait
|
||||
* If a $key is provided, it will try to return only that asset
|
||||
* else it will return null
|
||||
*
|
||||
* @param null|string $key the asset key
|
||||
* @param string|null $key the asset key
|
||||
* @return array
|
||||
*/
|
||||
public function getJs($key = null)
|
||||
@@ -91,7 +89,6 @@ trait TestingAssetsTrait
|
||||
* Set the whole array of CSS assets
|
||||
*
|
||||
* @param array $css
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCss($css)
|
||||
@@ -105,7 +102,6 @@ trait TestingAssetsTrait
|
||||
* Set the whole array of JS assets
|
||||
*
|
||||
* @param array $js
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setJs($js)
|
||||
@@ -119,7 +115,6 @@ trait TestingAssetsTrait
|
||||
* Removes an item from the CSS array if set
|
||||
*
|
||||
* @param string $key The asset key
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeCss($key)
|
||||
@@ -136,7 +131,6 @@ trait TestingAssetsTrait
|
||||
* Removes an item from the JS array if set
|
||||
*
|
||||
* @param string $key The asset key
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeJs($key)
|
||||
@@ -153,7 +147,6 @@ trait TestingAssetsTrait
|
||||
* Sets the state of CSS Pipeline
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCssPipeline($value)
|
||||
@@ -167,7 +160,6 @@ trait TestingAssetsTrait
|
||||
* Sets the state of JS Pipeline
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setJsPipeline($value)
|
||||
@@ -230,7 +222,7 @@ trait TestingAssetsTrait
|
||||
* Get the timestamp for assets
|
||||
*
|
||||
* @param bool $include_join
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTimestamp($include_join = true)
|
||||
{
|
||||
@@ -246,7 +238,6 @@ trait TestingAssetsTrait
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
* @param string $pattern (regex)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDir($directory, $pattern = self::DEFAULT_REGEX)
|
||||
@@ -296,7 +287,6 @@ trait TestingAssetsTrait
|
||||
* Add all JavaScript assets within $directory
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDirJs($directory)
|
||||
@@ -308,7 +298,6 @@ trait TestingAssetsTrait
|
||||
* Add all CSS assets within $directory
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDirCss($directory)
|
||||
@@ -322,13 +311,14 @@ trait TestingAssetsTrait
|
||||
* @param string $directory
|
||||
* @param string $pattern (regex)
|
||||
* @param string $ltrim Will be trimmed from the left of the file path
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function rglob($directory, $pattern, $ltrim = null)
|
||||
{
|
||||
$iterator = new \RegexIterator(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory,
|
||||
\FilesystemIterator::SKIP_DOTS)), $pattern);
|
||||
$iterator = new \RegexIterator(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
)), $pattern);
|
||||
$offset = \strlen($ltrim);
|
||||
$files = [];
|
||||
|
||||
@@ -338,6 +328,4 @@ trait TestingAssetsTrait
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Backup
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -17,9 +17,9 @@ use Grav\Common\Scheduler\Scheduler;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RocketTheme\Toolbox\Event\EventDispatcher;
|
||||
use RocketTheme\Toolbox\File\JsonFile;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class Backups
|
||||
{
|
||||
@@ -27,9 +27,11 @@ class Backups
|
||||
|
||||
protected const BACKUP_DATE_FORMAT = 'YmdHis';
|
||||
|
||||
/** @var string */
|
||||
protected static $backup_dir;
|
||||
|
||||
protected static $backups = null;
|
||||
/** @var array|null */
|
||||
protected static $backups;
|
||||
|
||||
public function init()
|
||||
{
|
||||
@@ -47,6 +49,9 @@ class Backups
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
*/
|
||||
public function onSchedulerInitialized(Event $event)
|
||||
{
|
||||
/** @var Scheduler $scheduler */
|
||||
@@ -60,38 +65,57 @@ class Backups
|
||||
$name = $inflector::hyphenize($profile['name']);
|
||||
$logs = 'logs/backup-' . $name . '.out';
|
||||
/** @var Job $job */
|
||||
$job = $scheduler->addFunction('Grav\Common\Backup\Backups::backup', [$id], $name );
|
||||
$job = $scheduler->addFunction('Grav\Common\Backup\Backups::backup', [$id], $name);
|
||||
$job->at($at);
|
||||
$job->output($logs);
|
||||
$job->backlink('/tools/backups');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $backup
|
||||
* @param string $base_url
|
||||
* @return string
|
||||
*/
|
||||
public function getBackupDownloadUrl($backup, $base_url)
|
||||
{
|
||||
$param_sep = $param_sep = Grav::instance()['config']->get('system.param_sep', ':');
|
||||
$download = urlencode(base64_encode($backup));
|
||||
$url = rtrim(Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim($base_url,
|
||||
'/') . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form');
|
||||
$url = rtrim(Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim(
|
||||
$base_url,
|
||||
'/'
|
||||
) . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form');
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getBackupProfiles()
|
||||
{
|
||||
return Grav::instance()['config']->get('backups.profiles');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getPurgeConfig()
|
||||
{
|
||||
return Grav::instance()['config']->get('backups.purge');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getBackupNames()
|
||||
{
|
||||
return array_column(static::getBackupProfiles(), 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public static function getTotalBackupsSize()
|
||||
{
|
||||
$backups = static::getAvailableBackups();
|
||||
@@ -100,6 +124,10 @@ class Backups
|
||||
return $size ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $force
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getAvailableBackups($force = false)
|
||||
{
|
||||
if ($force || null === static::$backups) {
|
||||
@@ -113,7 +141,6 @@ class Backups
|
||||
* @var \SplFileInfo $file
|
||||
*/
|
||||
foreach ($backups_itr as $name => $file) {
|
||||
|
||||
if (preg_match(static::BACKUP_FILENAME_REGEXZ, $name, $matches)) {
|
||||
$date = \DateTime::createFromFormat(static::BACKUP_DATE_FORMAT, $matches[2]);
|
||||
$timestamp = $date->getTimestamp();
|
||||
@@ -137,10 +164,9 @@ class Backups
|
||||
/**
|
||||
* Backup
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @param callable|null $status
|
||||
*
|
||||
* @return null|string
|
||||
* @return string|null
|
||||
*/
|
||||
public static function backup($id = 0, callable $status = null)
|
||||
{
|
||||
@@ -158,7 +184,7 @@ class Backups
|
||||
$date = date(static::BACKUP_DATE_FORMAT, time());
|
||||
$filename = trim($name, '_') . '--' . $date . '.zip';
|
||||
$destination = static::$backup_dir . DS . $filename;
|
||||
$max_execution_time = ini_set('max_execution_time', 600);
|
||||
$max_execution_time = ini_set('max_execution_time', '600');
|
||||
$backup_root = $backup->root;
|
||||
|
||||
if ($locator->isStream($backup_root)) {
|
||||
@@ -214,19 +240,21 @@ class Backups
|
||||
return $destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function purge()
|
||||
{
|
||||
$purge_config = static::getPurgeConfig();
|
||||
$trigger = $purge_config['trigger'];
|
||||
$backups = static::getAvailableBackups(true);
|
||||
|
||||
switch ($trigger)
|
||||
{
|
||||
switch ($trigger) {
|
||||
case 'number':
|
||||
$backups_count = count($backups);
|
||||
if ($backups_count > $purge_config['max_backups_count']) {
|
||||
$last = end($backups);
|
||||
unlink ($last->path);
|
||||
unlink($last->path);
|
||||
static::purge();
|
||||
}
|
||||
break;
|
||||
@@ -253,6 +281,10 @@ class Backups
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $exclude
|
||||
* @return array
|
||||
*/
|
||||
protected static function convertExclude($exclude)
|
||||
{
|
||||
$lines = preg_split("/[\s,]+/", $exclude);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Grav\Common;
|
||||
*/
|
||||
class Browser
|
||||
{
|
||||
/** @var string[] */
|
||||
protected $useragent = [];
|
||||
|
||||
/**
|
||||
@@ -108,7 +109,7 @@ class Browser
|
||||
/**
|
||||
* Get the current major version identifier
|
||||
*
|
||||
* @return string the browser major version identifier
|
||||
* @return int the browser major version identifier
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
@@ -135,7 +136,7 @@ class Browser
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if “Do Not Track” is set by browser
|
||||
* @see https://www.w3.org/TR/tracking-dnt/
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@ use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Scheduler\Scheduler;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RocketTheme\Toolbox\Event\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
/**
|
||||
* The GravCache object is used throughout Grav to store and retrieve cached data.
|
||||
@@ -29,36 +29,34 @@ use RocketTheme\Toolbox\Event\EventDispatcher;
|
||||
*/
|
||||
class Cache extends Getters
|
||||
{
|
||||
/**
|
||||
* @var string Cache key.
|
||||
*/
|
||||
/** @var string Cache key. */
|
||||
protected $key;
|
||||
|
||||
/** @var int */
|
||||
protected $lifetime;
|
||||
|
||||
/** @var int */
|
||||
protected $now;
|
||||
|
||||
/** @var Config $config */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var DoctrineCache\CacheProvider
|
||||
*/
|
||||
/** @var DoctrineCache\CacheProvider */
|
||||
protected $driver;
|
||||
|
||||
/**
|
||||
* @var CacheInterface
|
||||
*/
|
||||
/** @var CacheInterface */
|
||||
protected $simpleCache;
|
||||
|
||||
/** @var string */
|
||||
protected $driver_name;
|
||||
|
||||
/** @var string */
|
||||
protected $driver_setting;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
/** @var bool */
|
||||
protected $enabled;
|
||||
|
||||
/** @var string */
|
||||
protected $cache_dir;
|
||||
|
||||
protected static $standard_remove = [
|
||||
@@ -260,8 +258,10 @@ class Cache extends Getters
|
||||
case 'memcache':
|
||||
if (extension_loaded('memcache')) {
|
||||
$memcache = new \Memcache();
|
||||
$memcache->connect($this->config->get('system.cache.memcache.server', 'localhost'),
|
||||
$this->config->get('system.cache.memcache.port', 11211));
|
||||
$memcache->connect(
|
||||
$this->config->get('system.cache.memcache.server', 'localhost'),
|
||||
$this->config->get('system.cache.memcache.port', 11211)
|
||||
);
|
||||
$driver = new DoctrineCache\MemcacheCache();
|
||||
$driver->setMemcache($memcache);
|
||||
} else {
|
||||
@@ -272,8 +272,10 @@ class Cache extends Getters
|
||||
case 'memcached':
|
||||
if (extension_loaded('memcached')) {
|
||||
$memcached = new \Memcached();
|
||||
$memcached->addServer($this->config->get('system.cache.memcached.server', 'localhost'),
|
||||
$this->config->get('system.cache.memcached.port', 11211));
|
||||
$memcached->addServer(
|
||||
$this->config->get('system.cache.memcached.server', 'localhost'),
|
||||
$this->config->get('system.cache.memcached.port', 11211)
|
||||
);
|
||||
$driver = new DoctrineCache\MemcachedCache();
|
||||
$driver->setMemcached($memcached);
|
||||
} else {
|
||||
@@ -290,8 +292,10 @@ class Cache extends Getters
|
||||
if ($socket) {
|
||||
$redis->connect($socket);
|
||||
} else {
|
||||
$redis->connect($this->config->get('system.cache.redis.server', 'localhost'),
|
||||
$this->config->get('system.cache.redis.port', 6379));
|
||||
$redis->connect(
|
||||
$this->config->get('system.cache.redis.server', 'localhost'),
|
||||
$this->config->get('system.cache.redis.port', 6379)
|
||||
);
|
||||
}
|
||||
|
||||
// Authenticate with password if set
|
||||
@@ -319,7 +323,7 @@ class Cache extends Getters
|
||||
*
|
||||
* @param string $id the id of the cached entry
|
||||
*
|
||||
* @return object|bool returns the cached entry, can be any type, or false if doesn't exist
|
||||
* @return mixed|bool returns the cached entry, can be any type, or false if doesn't exist
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
@@ -334,7 +338,7 @@ class Cache extends Getters
|
||||
* Stores a new cached entry.
|
||||
*
|
||||
* @param string $id the id of the cached entry
|
||||
* @param array|object $data the data for the cached entry to store
|
||||
* @param array|object|int $data the data for the cached entry to store
|
||||
* @param int $lifetime the lifetime to store the entry in seconds
|
||||
*/
|
||||
public function save($id, $data, $lifetime = null)
|
||||
@@ -437,13 +441,15 @@ class Cache extends Getters
|
||||
case 'tmp-only':
|
||||
$remove_paths = self::$tmp_remove;
|
||||
break;
|
||||
case 'invalidate':
|
||||
$remove_paths = [];
|
||||
break;
|
||||
default:
|
||||
if (Grav::instance()['config']->get('system.cache.clear_images_by_default')) {
|
||||
$remove_paths = self::$standard_remove;
|
||||
} else {
|
||||
$remove_paths = self::$standard_remove_no_images;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete entries in the doctrine cache if required
|
||||
@@ -456,11 +462,12 @@ class Cache extends Getters
|
||||
Grav::instance()->fireEvent('onBeforeCacheClear', new Event(['remove' => $remove, 'paths' => &$remove_paths]));
|
||||
|
||||
foreach ($remove_paths as $stream) {
|
||||
|
||||
// Convert stream to a real path
|
||||
try {
|
||||
$path = $locator->findResource($stream, true, true);
|
||||
if($path === false) continue;
|
||||
if ($path === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$anything = false;
|
||||
$files = glob($path . '/*');
|
||||
@@ -525,10 +532,8 @@ class Cache extends Getters
|
||||
if (function_exists('opcache_reset')) {
|
||||
@opcache_reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the cache lifetime programmatically
|
||||
*
|
||||
@@ -540,7 +545,7 @@ class Cache extends Getters
|
||||
return;
|
||||
}
|
||||
|
||||
$interval = $future - $this->now;
|
||||
$interval = (int)($future - $this->now);
|
||||
if ($interval > 0 && $interval < $this->getLifetime()) {
|
||||
$this->lifetime = $interval;
|
||||
}
|
||||
@@ -555,7 +560,7 @@ class Cache extends Getters
|
||||
public function getLifetime()
|
||||
{
|
||||
if ($this->lifetime === null) {
|
||||
$this->lifetime = $this->config->get('system.cache.lifetime') ?: 604800; // 1 week default
|
||||
$this->lifetime = (int)($this->config->get('system.cache.lifetime') ?: 604800); // 1 week default
|
||||
}
|
||||
|
||||
return $this->lifetime;
|
||||
@@ -632,7 +637,7 @@ class Cache extends Getters
|
||||
$name = 'cache-purge';
|
||||
$logs = 'logs/' . $name . '.out';
|
||||
|
||||
$job = $scheduler->addFunction('Grav\Common\Cache::purgeJob', [], $name );
|
||||
$job = $scheduler->addFunction('Grav\Common\Cache::purgeJob', [], $name);
|
||||
$job->at($at);
|
||||
$job->output($logs);
|
||||
$job->backlink('/config/system#caching');
|
||||
@@ -643,12 +648,9 @@ class Cache extends Getters
|
||||
$name = 'cache-clear';
|
||||
$logs = 'logs/' . $name . '.out';
|
||||
|
||||
$job = $scheduler->addFunction('Grav\Common\Cache::clearJob', [$clear_type], $name );
|
||||
$job = $scheduler->addFunction('Grav\Common\Cache::clearJob', [$clear_type], $name);
|
||||
$job->at($at);
|
||||
$job->output($logs);
|
||||
$job->backlink('/config/system#caching');
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ class Composer
|
||||
}
|
||||
|
||||
// check for global composer install
|
||||
$path = trim(shell_exec('command -v composer'));
|
||||
$path = trim((string)shell_exec('command -v composer'));
|
||||
|
||||
// fall back to grav bundled composer
|
||||
if (!$path || !preg_match('/(composer|composer\.phar)$/', $path)) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,44 +13,28 @@ use RocketTheme\Toolbox\File\PhpFile;
|
||||
|
||||
abstract class CompiledBase
|
||||
{
|
||||
/**
|
||||
* @var int Version number for the compiled file.
|
||||
*/
|
||||
/** @var int Version number for the compiled file. */
|
||||
public $version = 1;
|
||||
|
||||
/**
|
||||
* @var string Filename (base name) of the compiled configuration.
|
||||
*/
|
||||
/** @var string Filename (base name) of the compiled configuration. */
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string|bool Configuration checksum.
|
||||
*/
|
||||
/** @var string|bool Configuration checksum. */
|
||||
public $checksum;
|
||||
|
||||
/**
|
||||
* @var string Timestamp of compiled configuration
|
||||
*/
|
||||
public $timestamp;
|
||||
/** @var int Timestamp of compiled configuration */
|
||||
public $timestamp = 0;
|
||||
|
||||
/**
|
||||
* @var string Cache folder to be used.
|
||||
*/
|
||||
/** @var string Cache folder to be used. */
|
||||
protected $cacheFolder;
|
||||
|
||||
/**
|
||||
* @var array List of files to load.
|
||||
*/
|
||||
/** @var array List of files to load. */
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string */
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* @var mixed Configuration object.
|
||||
*/
|
||||
/** @var mixed Configuration object. */
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
@@ -68,7 +52,6 @@ abstract class CompiledBase
|
||||
$this->path = $path ? rtrim($path, '\\/') . '/' : '';
|
||||
$this->cacheFolder = $cacheFolder;
|
||||
$this->files = $files;
|
||||
$this->timestamp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +72,9 @@ abstract class CompiledBase
|
||||
/**
|
||||
* Function gets called when cached configuration is saved.
|
||||
*/
|
||||
public function modified() {}
|
||||
public function modified()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timestamp of compiled configuration
|
||||
@@ -136,6 +121,9 @@ abstract class CompiledBase
|
||||
return $this->checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function createFilename()
|
||||
{
|
||||
return "{$this->cacheFolder}/{$this->name()->name}.php";
|
||||
@@ -157,7 +145,7 @@ abstract class CompiledBase
|
||||
* Load single configuration file and append it to the correct position.
|
||||
*
|
||||
* @param string $name Name of the position.
|
||||
* @param string $filename File to be loaded.
|
||||
* @param string|string[] $filename File(s) to be loaded.
|
||||
*/
|
||||
abstract protected function loadFile($name, $filename);
|
||||
|
||||
@@ -197,8 +185,7 @@ abstract class CompiledBase
|
||||
}
|
||||
|
||||
$cache = include $filename;
|
||||
if (
|
||||
!\is_array($cache)
|
||||
if (!\is_array($cache)
|
||||
|| !isset($cache['checksum'], $cache['data'], $cache['@class'])
|
||||
|| $cache['@class'] !== \get_class($this)
|
||||
) {
|
||||
@@ -256,6 +243,9 @@ abstract class CompiledBase
|
||||
$this->modified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getState()
|
||||
{
|
||||
return $this->object->toArray();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,12 @@ use Grav\Common\Grav;
|
||||
*/
|
||||
class CompiledBlueprints extends CompiledBase
|
||||
{
|
||||
/**
|
||||
* CompiledBlueprints constructor.
|
||||
* @param string $cacheFolder
|
||||
* @param array $files
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($cacheFolder, array $files, $path)
|
||||
{
|
||||
parent::__construct($cacheFolder, $files, $path);
|
||||
@@ -45,7 +51,7 @@ class CompiledBlueprints extends CompiledBase
|
||||
/**
|
||||
* Create configuration object.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
*/
|
||||
protected function createObject(array $data = [])
|
||||
{
|
||||
@@ -112,6 +118,9 @@ class CompiledBlueprints extends CompiledBase
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getState()
|
||||
{
|
||||
return $this->object->getState();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,16 +13,18 @@ use Grav\Common\File\CompiledYamlFile;
|
||||
|
||||
class CompiledConfig extends CompiledBase
|
||||
{
|
||||
/**
|
||||
* @var callable Blueprints loader.
|
||||
*/
|
||||
/** @var callable Blueprints loader. */
|
||||
protected $callable;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $withDefaults;
|
||||
/** @var bool */
|
||||
protected $withDefaults = false;
|
||||
|
||||
/**
|
||||
* CompiledConfig constructor.
|
||||
* @param string $cacheFolder
|
||||
* @param array $files
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($cacheFolder, array $files, $path)
|
||||
{
|
||||
parent::__construct($cacheFolder, $files, $path);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,12 @@ use Grav\Common\File\CompiledYamlFile;
|
||||
|
||||
class CompiledLanguages extends CompiledBase
|
||||
{
|
||||
/**
|
||||
* CompiledLanguages constructor.
|
||||
* @param string $cacheFolder
|
||||
* @param array $files
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($cacheFolder, array $files, $path)
|
||||
{
|
||||
parent::__construct($cacheFolder, $files, $path);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@ use Grav\Common\Utils;
|
||||
|
||||
class Config extends Data
|
||||
{
|
||||
/** @var string */
|
||||
public $environment;
|
||||
|
||||
/** @var string */
|
||||
@@ -28,6 +29,9 @@ class Config extends Data
|
||||
/** @var bool */
|
||||
protected $modified = false;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
if (null === $this->key) {
|
||||
@@ -37,6 +41,10 @@ class Config extends Data
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $checksum
|
||||
* @return string|null
|
||||
*/
|
||||
public function checksum($checksum = null)
|
||||
{
|
||||
if ($checksum !== null) {
|
||||
@@ -46,6 +54,10 @@ class Config extends Data
|
||||
return $this->checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $modified
|
||||
* @return bool
|
||||
*/
|
||||
public function modified($modified = null)
|
||||
{
|
||||
if ($modified !== null) {
|
||||
@@ -55,6 +67,10 @@ class Config extends Data
|
||||
return $this->modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $timestamp
|
||||
* @return int
|
||||
*/
|
||||
public function timestamp($timestamp = null)
|
||||
{
|
||||
if ($timestamp !== null) {
|
||||
@@ -64,6 +80,9 @@ class Config extends Data
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function reload()
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@ use Grav\Common\Filesystem\Folder;
|
||||
|
||||
class ConfigFileFinder
|
||||
{
|
||||
/** @var string */
|
||||
protected $base = '';
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -14,22 +14,19 @@ use Grav\Common\Utils;
|
||||
|
||||
class Languages extends Data
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
/** @var string|null */
|
||||
protected $checksum;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $modified;
|
||||
/** @var bool */
|
||||
protected $modified = false;
|
||||
|
||||
/** @var int */
|
||||
protected $timestamp = 0;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
* @param string|null $checksum
|
||||
* @return string
|
||||
*/
|
||||
protected $timestamp;
|
||||
|
||||
|
||||
public function checksum($checksum = null)
|
||||
{
|
||||
if ($checksum !== null) {
|
||||
@@ -39,6 +36,10 @@ class Languages extends Data
|
||||
return $this->checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|null $modified
|
||||
* @return bool
|
||||
*/
|
||||
public function modified($modified = null)
|
||||
{
|
||||
if ($modified !== null) {
|
||||
@@ -48,6 +49,10 @@ class Languages extends Data
|
||||
return $this->modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $timestamp
|
||||
* @return int
|
||||
*/
|
||||
public function timestamp($timestamp = null)
|
||||
{
|
||||
if ($timestamp !== null) {
|
||||
@@ -65,17 +70,28 @@ class Languages extends Data
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function mergeRecursive(array $data)
|
||||
{
|
||||
$this->items = Utils::arrayMergeRecursiveUnique($this->items, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lang
|
||||
* @return array
|
||||
*/
|
||||
public function flattenByLang($lang)
|
||||
{
|
||||
$language = $this->items[$lang];
|
||||
return Utils::arrayFlattenDotNotation($language);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public function unflatten($array)
|
||||
{
|
||||
return Utils::arrayUnflattenDotNotation($array);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Config
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@ class Setup extends Data
|
||||
*/
|
||||
public static $environment;
|
||||
|
||||
/** @var array */
|
||||
protected $streams = [
|
||||
'system' => [
|
||||
'type' => 'ReadOnlyStream',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -20,14 +20,19 @@ class Blueprint extends BlueprintForm
|
||||
/** @var string */
|
||||
protected $context = 'blueprints://';
|
||||
|
||||
/** @var string|null */
|
||||
protected $scope;
|
||||
|
||||
/** @var BlueprintSchema */
|
||||
/** @var BlueprintSchema|null */
|
||||
protected $blueprintSchema;
|
||||
|
||||
/** @var array */
|
||||
/** @var object|null */
|
||||
protected $object;
|
||||
|
||||
/** @var array|null */
|
||||
protected $defaults;
|
||||
|
||||
/** @var array */
|
||||
protected $handlers = [];
|
||||
|
||||
public function __clone()
|
||||
@@ -37,11 +42,22 @@ class Blueprint extends BlueprintForm
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scope
|
||||
*/
|
||||
public function setScope($scope)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
*/
|
||||
public function setObject($object)
|
||||
{
|
||||
$this->object = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default values for field types.
|
||||
*
|
||||
@@ -57,6 +73,29 @@ class Blueprint extends BlueprintForm
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return array|mixed|null
|
||||
* @since 1.7
|
||||
*/
|
||||
public function getDefaultValue(string $name)
|
||||
{
|
||||
$path = explode('.', $name) ?: [];
|
||||
$current = $this->getDefaults();
|
||||
|
||||
foreach ($path as $field) {
|
||||
if (\is_object($current) && isset($current->{$field})) {
|
||||
$current = $current->{$field};
|
||||
} elseif (\is_array($current) && isset($current[$field])) {
|
||||
$current = $current[$field];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested structure containing default values defined in the blueprints.
|
||||
*
|
||||
@@ -111,6 +150,7 @@ class Blueprint extends BlueprintForm
|
||||
foreach ($data as $property => $call) {
|
||||
$action = $call['action'];
|
||||
$method = 'dynamic' . ucfirst($action);
|
||||
$call['object'] = $this->object;
|
||||
|
||||
if (isset($this->handlers[$action])) {
|
||||
$callable = $this->handlers[$action];
|
||||
@@ -124,6 +164,38 @@ class Blueprint extends BlueprintForm
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend blueprint with another blueprint.
|
||||
*
|
||||
* @param BlueprintForm|array $extends
|
||||
* @param bool $append
|
||||
* @return $this
|
||||
*/
|
||||
public function extend($extends, $append = false)
|
||||
{
|
||||
parent::extend($extends, $append);
|
||||
|
||||
$this->deepInit($this->items);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param string $separator
|
||||
* @param bool $append
|
||||
* @return $this
|
||||
*/
|
||||
public function embed($name, $value, $separator = '/', $append = false)
|
||||
{
|
||||
parent::embed($name, $value, $separator, $append);
|
||||
|
||||
$this->deepInit($this->items);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two arrays by using blueprints.
|
||||
*
|
||||
@@ -193,7 +265,7 @@ class Blueprint extends BlueprintForm
|
||||
{
|
||||
$this->initInternals();
|
||||
|
||||
return $this->blueprintSchema->filter($data, $missingValuesAsNull, $keepEmptyValues);
|
||||
return $this->blueprintSchema->filter($data, $missingValuesAsNull, $keepEmptyValues) ?? [];
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +295,10 @@ class Blueprint extends BlueprintForm
|
||||
return $this->blueprintSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param callable $callable
|
||||
*/
|
||||
public function addDynamicHandler(string $name, callable $callable): void
|
||||
{
|
||||
$this->handlers[$name] = $callable;
|
||||
@@ -250,12 +326,12 @@ class Blueprint extends BlueprintForm
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
protected function loadFile($filename)
|
||||
{
|
||||
$file = CompiledYamlFile::instance($filename);
|
||||
$content = $file->content();
|
||||
$content = (array)$file->content();
|
||||
$file->free();
|
||||
|
||||
return $content;
|
||||
@@ -355,12 +431,29 @@ class Blueprint extends BlueprintForm
|
||||
*/
|
||||
protected function dynamicConfig(array &$field, $property, array &$call)
|
||||
{
|
||||
$value = $call['params'];
|
||||
$params = $call['params'];
|
||||
if (\is_array($params)) {
|
||||
$value = array_shift($params);
|
||||
$params = array_shift($params);
|
||||
} else {
|
||||
$value = $params;
|
||||
$params = [];
|
||||
}
|
||||
|
||||
$default = $field[$property] ?? null;
|
||||
$config = Grav::instance()['config']->get($value, $default);
|
||||
if (!empty($field['value_only'])) {
|
||||
$config = array_combine($config, $config);
|
||||
}
|
||||
|
||||
if (null !== $config) {
|
||||
$field[$property] = $config;
|
||||
if (!empty($params['append']) && \is_array($config) && isset($field[$property]) && \is_array($field[$property])) {
|
||||
// Combine field and @config-field together.
|
||||
$field[$property] += $config;
|
||||
} else {
|
||||
// Or create/replace field with @config-field.
|
||||
$field[$property] = $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,16 +471,33 @@ class Blueprint extends BlueprintForm
|
||||
$grav = Grav::instance();
|
||||
$actions = (array)$call['params'];
|
||||
|
||||
/** @var UserInterface $user */
|
||||
if (isset($grav['user'])) {
|
||||
$user = Grav::instance()['user'];
|
||||
foreach ($actions as $action) {
|
||||
if (!$user->authorize($action)) {
|
||||
$this->addPropertyRecursive($field, 'validate', ['ignore' => true]);
|
||||
return;
|
||||
}
|
||||
/** @var UserInterface|null $user */
|
||||
$user = $grav['user'] ?? null;
|
||||
$success = null !== $user;
|
||||
if ($success) {
|
||||
$success = $this->resolveActions($user, $actions);
|
||||
}
|
||||
if (!$success) {
|
||||
$this->addPropertyRecursive($field, 'validate', ['ignore' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function resolveActions(UserInterface $user, array $actions, string $op = 'and')
|
||||
{
|
||||
$c = $i = count($actions);
|
||||
foreach ($actions as $key => $action) {
|
||||
if (!is_int($key) && is_array($actions)) {
|
||||
$i -= $this->resolveActions($user, $action, $key);
|
||||
} elseif ($user->authorize($action)) {
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
|
||||
if ($op === 'and') {
|
||||
return $i === 0;
|
||||
}
|
||||
|
||||
return $c !== $i;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,6 +523,11 @@ class Blueprint extends BlueprintForm
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $field
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function addPropertyRecursive(array &$field, $property, $value)
|
||||
{
|
||||
if (\is_array($value) && isset($field[$property]) && \is_array($field[$property])) {
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||
@@ -18,6 +19,7 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
{
|
||||
use Export;
|
||||
|
||||
/** @var array */
|
||||
protected $ignoreFormKeys = [
|
||||
'title' => true,
|
||||
'help' => true,
|
||||
@@ -53,8 +55,8 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
public function validate(array $data)
|
||||
{
|
||||
try {
|
||||
$messages = $this->validateArray($data, $this->nested);
|
||||
|
||||
$validation = $this->items['']['form']['validation'] ?? 'loose';
|
||||
$messages = $this->validateArray($data, $this->nested, $validation === 'strict');
|
||||
} catch (\RuntimeException $e) {
|
||||
throw (new ValidationException($e->getMessage(), $e->getCode(), $e))->setMessages();
|
||||
}
|
||||
@@ -84,7 +86,9 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
*/
|
||||
public function filter(array $data, $missingValuesAsNull = false, $keepEmptyValues = false)
|
||||
{
|
||||
return $this->filterArray($data, $this->nested, $missingValuesAsNull, $keepEmptyValues);
|
||||
$this->buildIgnoreNested($this->nested);
|
||||
|
||||
return $this->filterArray($data, $this->nested, '', $missingValuesAsNull, $keepEmptyValues) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,31 +133,38 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @param bool $strict
|
||||
* @return array
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function validateArray(array $data, array $rules)
|
||||
protected function validateArray(array $data, array $rules, bool $strict)
|
||||
{
|
||||
$messages = $this->checkRequired($data, $rules);
|
||||
|
||||
foreach ($data as $key => $field) {
|
||||
foreach ($data as $key => $child) {
|
||||
$val = $rules[$key] ?? $rules['*'] ?? null;
|
||||
$rule = \is_string($val) ? $this->items[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
if (!empty($rule['validate']['ignore'])) {
|
||||
if (!empty($rule['disabled']) || !empty($rule['validate']['ignore'])) {
|
||||
// Skip validation in the ignored field.
|
||||
continue;
|
||||
}
|
||||
|
||||
$messages += Validation::validate($field, $rule);
|
||||
} elseif (\is_array($field) && \is_array($val)) {
|
||||
$messages += Validation::validate($child, $rule);
|
||||
} elseif (\is_array($child) && \is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$messages += $this->validateArray($field, $val);
|
||||
} elseif (isset($rules['validation']) && $rules['validation'] === 'strict') {
|
||||
$messages += $this->validateArray($child, $val, $strict);
|
||||
} elseif ($strict) {
|
||||
// Undefined/extra item.
|
||||
throw new \RuntimeException(sprintf('%s is not defined in blueprints', $key));
|
||||
/** @var Config $config */
|
||||
$config = Grav::instance()['config'];
|
||||
if (!$config->get('system.strict_mode.blueprint_strict_compat', true)) {
|
||||
throw new \RuntimeException(sprintf('%s is not defined in blueprints', $key));
|
||||
}
|
||||
|
||||
user_error(sprintf('Having extra key %s in your data is deprecated with blueprint having \'validation: strict\'', $key), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,45 +174,45 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @param string $parent
|
||||
* @param bool $missingValuesAsNull
|
||||
* @param bool $keepEmptyValues
|
||||
* @return array
|
||||
*/
|
||||
protected function filterArray(array $data, array $rules, $missingValuesAsNull, $keepEmptyValues)
|
||||
protected function filterArray(array $data, array $rules, string $parent, bool $missingValuesAsNull, bool $keepEmptyValues)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
if ($missingValuesAsNull) {
|
||||
// First pass is to fill up all the fields with null. This is done to lock the ordering of the fields.
|
||||
foreach ($rules as $key => $rule) {
|
||||
if ($key && !isset($results[$key])) {
|
||||
$val = $rules[$key] ?? $rules['*'] ?? null;
|
||||
$rule = \is_string($val) ? $this->items[$val] : null;
|
||||
|
||||
if (empty($rule['validate']['ignore'])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $field) {
|
||||
$val = $rules[$key] ?? $rules['*'] ?? null;
|
||||
$rule = \is_string($val) ? $this->items[$val] : null;
|
||||
$rule = \is_string($val) ? $this->items[$val] : $this->items[$parent . $key] ?? null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
if (!empty($rule['validate']['ignore'])) {
|
||||
// Skip any data in the ignored field.
|
||||
if (!empty($rule['disabled']) || !empty($rule['validate']['ignore'])) {
|
||||
// Skip any data in the ignored field.
|
||||
unset($results[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $field) {
|
||||
if ($missingValuesAsNull) {
|
||||
$results[$key] = null;
|
||||
} else {
|
||||
unset($results[$key]);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($rule && $rule['type'] !== '_parent') {
|
||||
$field = Validation::filter($field, $rule);
|
||||
} elseif (\is_array($field) && \is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$field = $this->filterArray($field, $val, $missingValuesAsNull, $keepEmptyValues);
|
||||
$field = $this->filterArray($field, $val, $parent . $key . '.', $missingValuesAsNull, $keepEmptyValues);
|
||||
|
||||
if (null === $field) {
|
||||
// Nested parent has no values.
|
||||
unset($results[$key]);
|
||||
continue;
|
||||
}
|
||||
} elseif (isset($rules['validation']) && $rules['validation'] === 'strict') {
|
||||
// Skip any extra data.
|
||||
continue;
|
||||
@@ -215,6 +226,24 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
return $results ?: null;
|
||||
}
|
||||
|
||||
protected function buildIgnoreNested(array $nested, $parent = '')
|
||||
{
|
||||
$ignore = true;
|
||||
foreach ($nested as $key => $val) {
|
||||
$key = $parent . $key;
|
||||
if (is_array($val)) {
|
||||
$ignore = $this->buildIgnoreNested($val, $key . '.') && $ignore; // Keep the order!
|
||||
} else {
|
||||
$child = $this->items[$key] ?? null;
|
||||
$ignore = $ignore && (!$child || !empty($child['disabled']) || !empty($child['validate']['ignore']));
|
||||
}
|
||||
}
|
||||
if ($ignore) {
|
||||
$key = trim($parent, '.');
|
||||
$this->items[$key]['validate']['ignore'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $data
|
||||
* @param array $toggles
|
||||
@@ -240,10 +269,12 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
if (
|
||||
// Not an input field
|
||||
!$field
|
||||
// Field has been disabled
|
||||
|| !empty($field['disabled'])
|
||||
// Field validation is set to be ignored
|
||||
|| !empty($field['validate']['ignore'])
|
||||
// Field is toggleable and the toggle is turned off
|
||||
|| (!empty($field['toggleable']) && empty($toggles[$key]))
|
||||
// Field is overridable and the toggle is turned off
|
||||
|| (!empty($field['overridable']) && empty($toggles[$key]))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -273,14 +304,19 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
$field = $this->items[$field];
|
||||
|
||||
// Skip ignored field, it will not be required.
|
||||
if (!empty($field['validate']['ignore'])) {
|
||||
if (!empty($field['disabled']) || !empty($field['validate']['ignore'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip overridable fields without value.
|
||||
// TODO: We need better overridable support, which is not just ignoring required values but also looking if defaults are good.
|
||||
if (!empty($field['overridable']) && !isset($data[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if required.
|
||||
if (isset($field['validate']['required'])
|
||||
&& $field['validate']['required'] === true) {
|
||||
|
||||
if (isset($data[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,8 @@ class Blueprints
|
||||
public function get($type)
|
||||
{
|
||||
if (!isset($this->instances[$type])) {
|
||||
$this->instances[$type] = $this->loadFile($type);
|
||||
$blueprint = $this->loadFile($type);
|
||||
$this->instances[$type] = $blueprint;
|
||||
}
|
||||
|
||||
return $this->instances[$type];
|
||||
@@ -99,6 +100,15 @@ class Blueprints
|
||||
$blueprint->setContext($this->search);
|
||||
}
|
||||
|
||||
return $blueprint->load()->init();
|
||||
try {
|
||||
$blueprint->load()->init();
|
||||
} catch (\RuntimeException $e) {
|
||||
$log = Grav::instance()['log'];
|
||||
$log->error(sprintf('Blueprint %s cannot be loaded: %s', $name, $e->getMessage()));
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,6 @@ use RocketTheme\Toolbox\ArrayTraits\Countable;
|
||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
|
||||
use RocketTheme\Toolbox\File\File;
|
||||
use RocketTheme\Toolbox\File\FileInterface;
|
||||
|
||||
class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable, ExportInterface
|
||||
@@ -22,19 +21,21 @@ class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable
|
||||
|
||||
/** @var string */
|
||||
protected $gettersVariable = 'items';
|
||||
|
||||
/** @var array */
|
||||
protected $items;
|
||||
|
||||
/** @var Blueprint */
|
||||
/** @var Blueprint|null */
|
||||
protected $blueprints;
|
||||
|
||||
/** @var File */
|
||||
/** @var FileInterface|null */
|
||||
protected $storage;
|
||||
|
||||
/** @var bool */
|
||||
private $missingValuesAsNull = false;
|
||||
/** @var bool */
|
||||
private $keepEmptyValues = true;
|
||||
|
||||
/**
|
||||
* @param array $items
|
||||
* @param Blueprint|callable $blueprints
|
||||
* @param Blueprint|callable|null $blueprints
|
||||
*/
|
||||
public function __construct(array $items = [], $blueprints = null)
|
||||
{
|
||||
@@ -42,6 +43,28 @@ class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable
|
||||
$this->blueprints = $blueprints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setKeepEmptyValues(bool $value)
|
||||
{
|
||||
$this->keepEmptyValues = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setMissingValuesAsNull(bool $value)
|
||||
{
|
||||
$this->missingValuesAsNull = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by using dot notation for nested arrays/objects.
|
||||
*
|
||||
@@ -202,8 +225,8 @@ class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable
|
||||
public function filter()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$missingValuesAsNull = (bool)(array_shift($args) ?: false);
|
||||
$keepEmptyValues = (bool)(array_shift($args) ?: false);
|
||||
$missingValuesAsNull = (bool)(array_shift($args) ?? $this->missingValuesAsNull);
|
||||
$keepEmptyValues = (bool)(array_shift($args) ?? $this->keepEmptyValues);
|
||||
|
||||
$this->items = $this->blueprints()->filter($this->items, $missingValuesAsNull, $keepEmptyValues);
|
||||
|
||||
@@ -227,7 +250,7 @@ class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable
|
||||
*/
|
||||
public function blueprints()
|
||||
{
|
||||
if (!$this->blueprints){
|
||||
if (!$this->blueprints) {
|
||||
$this->blueprints = new Blueprint;
|
||||
} elseif (\is_callable($this->blueprints)) {
|
||||
// Lazy load blueprints.
|
||||
@@ -280,8 +303,8 @@ class Data implements DataInterface, \ArrayAccess, \Countable, \JsonSerializable
|
||||
/**
|
||||
* Set or get the data storage.
|
||||
*
|
||||
* @param FileInterface $storage Optionally enter a new storage.
|
||||
* @return FileInterface
|
||||
* @param FileInterface|null $storage Optionally enter a new storage.
|
||||
* @return FileInterface|null
|
||||
*/
|
||||
public function file(FileInterface $storage = null)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,7 @@ interface DataInterface
|
||||
/**
|
||||
* Set or get the data storage.
|
||||
*
|
||||
* @param FileInterface $storage Optionally enter a new storage.
|
||||
* @param FileInterface|null $storage Optionally enter a new storage.
|
||||
* @return FileInterface
|
||||
*/
|
||||
public function file(FileInterface $storage = null);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,9 @@ class Validation
|
||||
if (!isset($field['type'])) {
|
||||
$field['type'] = 'text';
|
||||
}
|
||||
$type = $validate['type'] ?? $field['type'];
|
||||
|
||||
$validate = (array)($field['validate'] ?? null);
|
||||
$type = $validate['type'] ?? $field['type'];
|
||||
$required = $validate['required'] ?? false;
|
||||
|
||||
// If value isn't required, we will stop validation if empty value is given.
|
||||
@@ -152,6 +153,12 @@ class Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return string
|
||||
*/
|
||||
protected static function filterText($value, array $params, array $field)
|
||||
{
|
||||
if (!\is_string($value) && !is_numeric($value)) {
|
||||
@@ -165,21 +172,68 @@ class Validation
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function filterCheckbox($value, array $params, array $field)
|
||||
{
|
||||
$value = (string)$value;
|
||||
$field_value = (string)($field['value'] ?? '1');
|
||||
|
||||
return $value === $field_value ? $value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array|array[]|false|string[]
|
||||
*/
|
||||
protected static function filterCommaList($value, array $params, array $field)
|
||||
{
|
||||
return \is_array($value) ? $value : preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return bool
|
||||
*/
|
||||
public static function typeCommaList($value, array $params, array $field)
|
||||
{
|
||||
return \is_array($value) ? true : self::typeText($value, $params, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array|array[]|false|string[]
|
||||
*/
|
||||
protected static function filterLines($value, array $params, array $field)
|
||||
{
|
||||
return \is_array($value) ? $value : preg_split('/\s*[\r\n]+\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
protected static function filterLower($value, array $params)
|
||||
{
|
||||
return strtolower($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
protected static function filterUpper($value, array $params)
|
||||
{
|
||||
return strtoupper($value);
|
||||
@@ -245,6 +299,12 @@ class Validation
|
||||
return self::typeArray((array) $value, $params, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array|null
|
||||
*/
|
||||
protected static function filterCheckboxes($value, array $params, array $field)
|
||||
{
|
||||
return self::filterArray($value, $params, $field);
|
||||
@@ -309,6 +369,12 @@ class Validation
|
||||
return self::typeArray((array)$value, $params, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array
|
||||
*/
|
||||
protected static function filterFile($value, array $params, array $field)
|
||||
{
|
||||
return (array)$value;
|
||||
@@ -354,11 +420,23 @@ class Validation
|
||||
return !(isset($params['step']) && fmod($value - $min, $params['step']) === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return float|int
|
||||
*/
|
||||
protected static function filterNumber($value, array $params, array $field)
|
||||
{
|
||||
return (string)(int)$value !== (string)(float)$value ? (float) $value : (int) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return string
|
||||
*/
|
||||
protected static function filterDateTime($value, array $params, array $field)
|
||||
{
|
||||
$format = Grav::instance()['config']->get('system.pages.dateformat.default');
|
||||
@@ -369,7 +447,6 @@ class Validation
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTML5 input: range
|
||||
*
|
||||
@@ -383,6 +460,12 @@ class Validation
|
||||
return self::typeNumber($value, $params, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return float|int
|
||||
*/
|
||||
protected static function filterRange($value, array $params, array $field)
|
||||
{
|
||||
return self::filterNumber($value, $params, $field);
|
||||
@@ -571,6 +654,11 @@ class Validation
|
||||
}
|
||||
}
|
||||
|
||||
// If creating new values is allowed, no further checks are needed.
|
||||
if (!empty($field['selectize']['create'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$options = $field['options'] ?? [];
|
||||
$use = $field['use'] ?? 'values';
|
||||
|
||||
@@ -584,6 +672,25 @@ class Validation
|
||||
return !($options && array_diff($value, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array|null
|
||||
*/
|
||||
protected static function filterFlatten_array($value, $params, $field)
|
||||
{
|
||||
$value = static::filterArray($value, $params, $field);
|
||||
|
||||
return Utils::arrayUnflattenDotNotation($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array|null
|
||||
*/
|
||||
protected static function filterArray($value, $params, $field)
|
||||
{
|
||||
$values = (array) $value;
|
||||
@@ -613,25 +720,87 @@ class Validation
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($field['ignore_empty']) && Utils::isPositive($field['ignore_empty'])) {
|
||||
foreach ($values as $key => $val) {
|
||||
if ($val === '') {
|
||||
$ignoreEmpty = isset($field['ignore_empty']) && Utils::isPositive($field['ignore_empty']);
|
||||
$valueType = $params['value_type'] ?? null;
|
||||
$keyType = $params['key_type'] ?? null;
|
||||
if ($ignoreEmpty || $valueType || $keyType) {
|
||||
$values = static::arrayFilterRecurse($values, ['value_type' => $valueType, 'key_type' => $keyType, 'ignore_empty' => $ignoreEmpty]);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
protected static function arrayFilterRecurse(array $values, array $params): array
|
||||
{
|
||||
foreach ($values as $key => &$val) {
|
||||
if ($params['key_type']) {
|
||||
switch ($params['key_type']) {
|
||||
case 'int':
|
||||
$result = is_int($key);
|
||||
break;
|
||||
case 'string':
|
||||
$result = is_string($key);
|
||||
break;
|
||||
default:
|
||||
$result = false;
|
||||
}
|
||||
if (!$result) {
|
||||
unset($values[$key]);
|
||||
} elseif (\is_array($val)) {
|
||||
foreach ($val as $inner_key => $inner_value) {
|
||||
if ($inner_value === '') {
|
||||
unset($val[$inner_key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (\is_array($val)) {
|
||||
$val = static::arrayFilterRecurse($val, $params);
|
||||
if ($params['ignore_empty'] && empty($val)) {
|
||||
unset($values[$key]);
|
||||
}
|
||||
} else {
|
||||
if ($params['value_type'] && $val !== '' && $val !== null) {
|
||||
switch ($params['value_type']) {
|
||||
case 'bool':
|
||||
if (Utils::isPositive($val)) {
|
||||
$val = true;
|
||||
} elseif (Utils::isNegative($val)) {
|
||||
$val = false;
|
||||
} else {
|
||||
// Ignore invalid bool values.
|
||||
$val = null;
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
$val = (int)$val;
|
||||
break;
|
||||
case 'float':
|
||||
$val = (float)$val;
|
||||
break;
|
||||
case 'string':
|
||||
$val = (string)$val;
|
||||
break;
|
||||
case 'trim':
|
||||
$val = trim($val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$values[$key] = $val;
|
||||
if ($params['ignore_empty'] && ($val === '' || $val === null)) {
|
||||
unset($values[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return bool
|
||||
*/
|
||||
public static function typeList($value, array $params, array $field)
|
||||
{
|
||||
if (!\is_array($value)) {
|
||||
@@ -651,11 +820,22 @@ class Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return array
|
||||
*/
|
||||
protected static function filterList($value, array $params, array $field)
|
||||
{
|
||||
return (array) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
public static function filterYaml($value, $params)
|
||||
{
|
||||
if (!\is_string($value)) {
|
||||
@@ -663,7 +843,6 @@ class Validation
|
||||
}
|
||||
|
||||
return (array) Yaml::parse($value);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -679,6 +858,12 @@ class Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return mixed
|
||||
*/
|
||||
public static function filterIgnore($value, array $params, array $field)
|
||||
{
|
||||
return $value;
|
||||
@@ -697,6 +882,12 @@ class Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
* @param array $field
|
||||
* @return null
|
||||
*/
|
||||
public static function filterUnset($value, array $params, array $field)
|
||||
{
|
||||
return null;
|
||||
@@ -704,6 +895,11 @@ class Validation
|
||||
|
||||
// HTML5 attributes (min, max and range are handled inside the types)
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param bool $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateRequired($value, $params)
|
||||
{
|
||||
if (is_scalar($value)) {
|
||||
@@ -713,79 +909,155 @@ class Validation
|
||||
return (bool) $params !== true || !empty($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param string $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validatePattern($value, $params)
|
||||
{
|
||||
return (bool) preg_match("`^{$params}$`u", $value);
|
||||
}
|
||||
|
||||
|
||||
// Internal types
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateAlpha($value, $params)
|
||||
{
|
||||
return ctype_alpha($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateAlnum($value, $params)
|
||||
{
|
||||
return ctype_alnum($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function typeBool($value, $params)
|
||||
{
|
||||
return \is_bool($value) || $value == 1 || $value == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateBool($value, $params)
|
||||
{
|
||||
return \is_bool($value) || $value == 1 || $value == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
protected static function filterBool($value, $params)
|
||||
{
|
||||
return (bool) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateDigit($value, $params)
|
||||
{
|
||||
return ctype_digit($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateFloat($value, $params)
|
||||
{
|
||||
return \is_float(filter_var($value, FILTER_VALIDATE_FLOAT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return float
|
||||
*/
|
||||
protected static function filterFloat($value, $params)
|
||||
{
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateHex($value, $params)
|
||||
{
|
||||
return ctype_xdigit($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateInt($value, $params)
|
||||
{
|
||||
return is_numeric($value) && (int)$value == $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return int
|
||||
*/
|
||||
protected static function filterInt($value, $params)
|
||||
{
|
||||
return (int)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateArray($value, $params)
|
||||
{
|
||||
return \is_array($value) || ($value instanceof \ArrayAccess && $value instanceof \Traversable && $value instanceof \Countable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return array
|
||||
*/
|
||||
public static function filterItem_List($value, $params)
|
||||
{
|
||||
return array_values(array_filter($value, function($v) { return !empty($v); } ));
|
||||
return array_values(array_filter($value, function ($v) {
|
||||
return !empty($v);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param mixed $params
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateJson($value, $params)
|
||||
{
|
||||
return (bool) (@json_decode($value));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Data
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,9 +13,15 @@ use Grav\Common\Grav;
|
||||
|
||||
class ValidationException extends \RuntimeException
|
||||
{
|
||||
/** @var array */
|
||||
protected $messages = [];
|
||||
|
||||
public function setMessages(array $messages = []) {
|
||||
/**
|
||||
* @param array $messages
|
||||
* @return $this
|
||||
*/
|
||||
public function setMessages(array $messages = [])
|
||||
{
|
||||
$this->messages = $messages;
|
||||
|
||||
$language = Grav::instance()['language'];
|
||||
@@ -31,6 +37,9 @@ class ValidationException extends \RuntimeException
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
return $this->messages;
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
/**
|
||||
* @package Grav\Common
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common;
|
||||
|
||||
use Clockwork\Clockwork;
|
||||
use Clockwork\DataSource\MonologDataSource;
|
||||
use Clockwork\DataSource\PsrMessageDataSource;
|
||||
use Clockwork\DataSource\XdebugDataSource;
|
||||
use Clockwork\Helpers\ServerTiming;
|
||||
use Clockwork\Request\UserData;
|
||||
use Clockwork\Storage\FileStorage;
|
||||
use DebugBar\DataCollector\ConfigCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\ExceptionsCollector;
|
||||
@@ -19,70 +26,90 @@ use DebugBar\DataCollector\RequestDataCollector;
|
||||
use DebugBar\DataCollector\TimeDataCollector;
|
||||
use DebugBar\DebugBar;
|
||||
use DebugBar\JavascriptRenderer;
|
||||
use DebugBar\StandardDebugBar;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Processors\ProcessorInterface;
|
||||
use Grav\Common\Twig\TwigClockworkDataSource;
|
||||
use Grav\Framework\Psr7\Response;
|
||||
use Monolog\Logger;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Twig\Template;
|
||||
use Twig\TemplateWrapper;
|
||||
|
||||
class Debugger
|
||||
{
|
||||
/** @var Grav $grav */
|
||||
/** @var static */
|
||||
protected static $instance;
|
||||
|
||||
/** @var Grav|null */
|
||||
protected $grav;
|
||||
|
||||
/** @var Config $config */
|
||||
/** @var Config|null */
|
||||
protected $config;
|
||||
|
||||
/** @var JavascriptRenderer $renderer */
|
||||
/** @var JavascriptRenderer|null */
|
||||
protected $renderer;
|
||||
|
||||
/** @var StandardDebugBar $debugbar */
|
||||
/** @var DebugBar|null */
|
||||
protected $debugbar;
|
||||
|
||||
/** @var bool */
|
||||
protected $enabled;
|
||||
/** @var Clockwork|null */
|
||||
protected $clockwork;
|
||||
|
||||
/** @var bool */
|
||||
protected $enabled = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $initialized = false;
|
||||
|
||||
/** @var array */
|
||||
protected $timers = [];
|
||||
|
||||
/** @var array $deprecations */
|
||||
/** @var array */
|
||||
protected $deprecations = [];
|
||||
|
||||
/** @var callable */
|
||||
/** @var callable|null */
|
||||
protected $errorHandler;
|
||||
|
||||
/** @var float */
|
||||
protected $requestTime;
|
||||
|
||||
/** @var float */
|
||||
protected $currentTime;
|
||||
|
||||
/** @var int */
|
||||
protected $profiling = 0;
|
||||
|
||||
/** @var bool */
|
||||
protected $censored = false;
|
||||
|
||||
/**
|
||||
* Debugger constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$currentTime = microtime(true);
|
||||
static::$instance = $this;
|
||||
|
||||
$this->currentTime = microtime(true);
|
||||
|
||||
if (!\defined('GRAV_REQUEST_TIME')) {
|
||||
\define('GRAV_REQUEST_TIME', $currentTime);
|
||||
\define('GRAV_REQUEST_TIME', $this->currentTime);
|
||||
}
|
||||
|
||||
// Enable debugger until $this->init() gets called.
|
||||
$this->enabled = true;
|
||||
|
||||
$debugbar = new DebugBar();
|
||||
$debugbar->addCollector(new PhpInfoCollector());
|
||||
$debugbar->addCollector(new MessagesCollector());
|
||||
$debugbar->addCollector(new RequestDataCollector());
|
||||
$debugbar->addCollector(new TimeDataCollector($_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME));
|
||||
|
||||
$debugbar['time']->addMeasure('Server', $debugbar['time']->getRequestStartTime(), GRAV_REQUEST_TIME);
|
||||
$debugbar['time']->addMeasure('Loading', GRAV_REQUEST_TIME, $currentTime);
|
||||
$debugbar['time']->addMeasure('Debugger', $currentTime, microtime(true));
|
||||
|
||||
$this->debugbar = $debugbar;
|
||||
$this->requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
|
||||
|
||||
// Set deprecation collector.
|
||||
$this->setErrorHandler();
|
||||
}
|
||||
|
||||
public function getClockwork(): ?Clockwork
|
||||
{
|
||||
return $this->enabled ? $this->clockwork : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the debugger
|
||||
*
|
||||
@@ -100,25 +127,232 @@ class Debugger
|
||||
|
||||
// Enable/disable debugger based on configuration.
|
||||
$this->enabled = (bool)$this->config->get('system.debugger.enabled');
|
||||
$this->censored = (bool)$this->config->get('system.debugger.censored', false);
|
||||
|
||||
if ($this->enabled()) {
|
||||
if ($this->enabled) {
|
||||
$this->initialized = true;
|
||||
|
||||
$plugins_config = (array)$this->config->get('plugins');
|
||||
$clockwork = $debugbar = null;
|
||||
|
||||
switch ($this->config->get('system.debugger.provider', 'debugbar')) {
|
||||
case 'clockwork':
|
||||
$this->clockwork = $clockwork = new Clockwork();
|
||||
break;
|
||||
default:
|
||||
$this->debugbar = $debugbar = new DebugBar();
|
||||
}
|
||||
|
||||
$plugins_config = (array)$this->config->get('plugins');
|
||||
ksort($plugins_config);
|
||||
|
||||
$debugbar = $this->debugbar;
|
||||
$debugbar->addCollector(new MemoryCollector());
|
||||
$debugbar->addCollector(new ExceptionsCollector());
|
||||
$debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
|
||||
$debugbar->addCollector(new ConfigCollector($plugins_config, 'Plugins'));
|
||||
$this->addMessage('Grav v' . GRAV_VERSION);
|
||||
if ($clockwork) {
|
||||
$log = $this->grav['log'];
|
||||
$clockwork->setStorage(new FileStorage('cache://clockwork'));
|
||||
if (extension_loaded('xdebug')) {
|
||||
$clockwork->addDataSource(new XdebugDataSource());
|
||||
}
|
||||
if ($log instanceof Logger) {
|
||||
$clockwork->addDataSource(new MonologDataSource($log));
|
||||
}
|
||||
|
||||
$clockwork->addDataSource(new TwigClockworkDataSource());
|
||||
|
||||
$timeLine = $clockwork->getTimeline();
|
||||
if ($this->requestTime !== GRAV_REQUEST_TIME) {
|
||||
$timeLine->addEvent('server', 'Server', $this->requestTime, GRAV_REQUEST_TIME);
|
||||
}
|
||||
if ($this->currentTime !== GRAV_REQUEST_TIME) {
|
||||
$timeLine->addEvent('loading', 'Loading', GRAV_REQUEST_TIME, $this->currentTime);
|
||||
}
|
||||
$timeLine->addEvent('setup', 'Site Setup', $this->currentTime, microtime(true));
|
||||
}
|
||||
|
||||
if ($this->censored) {
|
||||
$censored = ['CENSORED' => true];
|
||||
}
|
||||
|
||||
if ($debugbar) {
|
||||
$debugbar->addCollector(new PhpInfoCollector());
|
||||
$debugbar->addCollector(new MessagesCollector());
|
||||
if (!$this->censored) {
|
||||
$debugbar->addCollector(new RequestDataCollector());
|
||||
}
|
||||
$debugbar->addCollector(new TimeDataCollector($this->requestTime));
|
||||
$debugbar->addCollector(new MemoryCollector());
|
||||
$debugbar->addCollector(new ExceptionsCollector());
|
||||
$debugbar->addCollector(new ConfigCollector($censored ?? (array)$this->config->get('system'), 'Config'));
|
||||
$debugbar->addCollector(new ConfigCollector($censored ?? $plugins_config, 'Plugins'));
|
||||
$debugbar->addCollector(new ConfigCollector($this->config->get('streams.schemes'), 'Streams'));
|
||||
|
||||
if ($this->requestTime !== GRAV_REQUEST_TIME) {
|
||||
$debugbar['time']->addMeasure('Server', $debugbar['time']->getRequestStartTime(), GRAV_REQUEST_TIME);
|
||||
}
|
||||
if ($this->currentTime !== GRAV_REQUEST_TIME) {
|
||||
$debugbar['time']->addMeasure('Loading', GRAV_REQUEST_TIME, $this->currentTime);
|
||||
}
|
||||
$debugbar['time']->addMeasure('Site Setup', $this->currentTime, microtime(true));
|
||||
}
|
||||
|
||||
$this->addMessage('Grav v' . GRAV_VERSION . ' - PHP ' . PHP_VERSION);
|
||||
$this->config->debug();
|
||||
|
||||
if ($clockwork) {
|
||||
$clockwork->info('System Configuration', $censored ?? $this->config->get('system'));
|
||||
$clockwork->info('Plugins Configuration', $censored ?? $plugins_config);
|
||||
$clockwork->info('Streams', $this->config->get('streams.schemes'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function finalize(): void
|
||||
{
|
||||
if ($this->clockwork && $this->enabled) {
|
||||
$this->stopProfiling('Profiler Analysis');
|
||||
$this->addMeasures();
|
||||
|
||||
$deprecations = $this->getDeprecations();
|
||||
$count = count($deprecations);
|
||||
if (!$count) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var UserData $userData */
|
||||
$userData = $this->clockwork->userData('Deprecated');
|
||||
$userData->counters([
|
||||
'Deprecated' => count($deprecations)
|
||||
]);
|
||||
foreach ($deprecations as &$deprecation) {
|
||||
$d = $deprecation;
|
||||
unset($d['message']);
|
||||
$this->clockwork->log('deprecated', $deprecation['message'], $d);
|
||||
}
|
||||
unset($deprecation);
|
||||
|
||||
$userData->table('Your site is using following deprecated features', $deprecations);
|
||||
}
|
||||
}
|
||||
|
||||
public function logRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
if (!$this->enabled || !$this->clockwork) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$clockwork = $this->clockwork;
|
||||
|
||||
$this->finalize();
|
||||
|
||||
$clockwork->getTimeline()->finalize($request->getAttribute('request_time'));
|
||||
|
||||
if ($this->censored) {
|
||||
$censored = 'CENSORED';
|
||||
$request = $request
|
||||
->withCookieParams([$censored => ''])
|
||||
->withUploadedFiles([])
|
||||
->withHeader('cookie', $censored);
|
||||
$request = $request->withParsedBody([$censored => '']);
|
||||
}
|
||||
|
||||
$clockwork->addDataSource(new PsrMessageDataSource($request, $response));
|
||||
|
||||
$clockwork->resolveRequest();
|
||||
$clockwork->storeRequest();
|
||||
|
||||
$clockworkRequest = $clockwork->getRequest();
|
||||
|
||||
$response = $response
|
||||
->withHeader('X-Clockwork-Id', $clockworkRequest->id)
|
||||
->withHeader('X-Clockwork-Version', $clockwork::VERSION);
|
||||
|
||||
$basePath = Grav::instance()['uri']->rootUrl();
|
||||
if ($basePath) {
|
||||
$response = $response->withHeader('X-Clockwork-Path', $basePath . '/__clockwork/');
|
||||
}
|
||||
|
||||
return $response->withHeader('Server-Timing', ServerTiming::fromRequest($clockworkRequest)->value());
|
||||
}
|
||||
|
||||
|
||||
public function debuggerRequest(RequestInterface $request): Response
|
||||
{
|
||||
$clockwork = $this->clockwork;
|
||||
|
||||
$headers = [
|
||||
'Content-Type' => 'application/json',
|
||||
'Grav-Internal-SkipShutdown' => 1
|
||||
];
|
||||
|
||||
$path = $request->getUri()->getPath();
|
||||
$clockworkDataUri = '#/__clockwork(?:/(?<id>[0-9-]+))?(?:/(?<direction>(?:previous|next)))?(?:/(?<count>\d+))?#';
|
||||
if (preg_match($clockworkDataUri, $path, $matches) === false) {
|
||||
$response = ['message' => 'Bad Input'];
|
||||
|
||||
return new Response(400, $headers, json_encode($response));
|
||||
}
|
||||
|
||||
$id = $matches['id'] ?? null;
|
||||
$direction = $matches['direction'] ?? null;
|
||||
$count = $matches['count'] ?? null;
|
||||
|
||||
$storage = $clockwork->getStorage();
|
||||
|
||||
if ($direction === 'previous') {
|
||||
$data = $storage->previous($id, $count);
|
||||
} elseif ($direction === 'next') {
|
||||
$data = $storage->next($id, $count);
|
||||
} elseif ($id === 'latest') {
|
||||
$data = $storage->latest();
|
||||
} else {
|
||||
$data = $storage->find($id);
|
||||
}
|
||||
|
||||
if (preg_match('#(?<id>[0-9-]+|latest)/extended#', $path)) {
|
||||
$clockwork->extendRequest($data);
|
||||
}
|
||||
|
||||
if (!$data) {
|
||||
$response = ['message' => 'Not Found'];
|
||||
|
||||
return new Response(404, $headers, json_encode($response));
|
||||
}
|
||||
|
||||
$data = is_array($data) ? array_map(function ($item) {
|
||||
return $item->toArray();
|
||||
}, $data) : $data->toArray();
|
||||
|
||||
return new Response(200, $headers, json_encode($data));
|
||||
}
|
||||
|
||||
protected function addMeasures()
|
||||
{
|
||||
if (!$this->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nowTime = microtime(true);
|
||||
$clkTimeLine = $this->clockwork ? $this->clockwork->getTimeline() : null;
|
||||
$debTimeLine = $this->debugbar ? $this->debugbar['time'] : null;
|
||||
foreach ($this->timers as $name => $data) {
|
||||
$description = $data[0];
|
||||
$startTime = $data[1] ?? null;
|
||||
$endTime = $data[2] ?? $nowTime;
|
||||
if ($endTime - $startTime < 0.001) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($clkTimeLine) {
|
||||
$clkTimeLine->addEvent($name, $description ?? $name, $startTime, $endTime);
|
||||
}
|
||||
|
||||
if ($debTimeLine) {
|
||||
$debTimeLine->addMeasure($description ?? $name, $startTime, $endTime);
|
||||
}
|
||||
}
|
||||
$this->timers = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/get the enabled state of the debugger
|
||||
*
|
||||
@@ -142,8 +376,7 @@ class Debugger
|
||||
*/
|
||||
public function addAssets()
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
|
||||
if ($this->enabled) {
|
||||
// Only add assets if Page is HTML
|
||||
$page = $this->grav['page'];
|
||||
if ($page->templateFormat() !== 'html') {
|
||||
@@ -153,22 +386,32 @@ class Debugger
|
||||
/** @var Assets $assets */
|
||||
$assets = $this->grav['assets'];
|
||||
|
||||
// Add jquery library
|
||||
$assets->add('jquery', 101);
|
||||
|
||||
$this->renderer = $this->debugbar->getJavascriptRenderer();
|
||||
$this->renderer->setIncludeVendors(false);
|
||||
|
||||
// Get the required CSS files
|
||||
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
|
||||
foreach ((array)$css_files as $css) {
|
||||
$assets->addCss($css);
|
||||
// Clockwork specific assets
|
||||
if ($this->clockwork) {
|
||||
$assets->addCss('/system/assets/debugger/clockwork.css', ['loading' => 'inline']);
|
||||
$assets->addJs('/system/assets/debugger/clockwork.js', ['loading' => 'inline']);
|
||||
}
|
||||
|
||||
$assets->addCss('/system/assets/debugger.css');
|
||||
|
||||
foreach ((array)$js_files as $js) {
|
||||
$assets->addJs($js);
|
||||
// Debugbar specific assets
|
||||
if ($this->debugbar) {
|
||||
// Add jquery library
|
||||
$assets->add('jquery', 101);
|
||||
|
||||
$this->renderer = $this->debugbar->getJavascriptRenderer();
|
||||
$this->renderer->setIncludeVendors(false);
|
||||
|
||||
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
|
||||
|
||||
foreach ((array)$css_files as $css) {
|
||||
$assets->addCss($css);
|
||||
}
|
||||
|
||||
$assets->addCss('/system/assets/debugger/phpdebugbar.css', ['loading' => 'inline']);
|
||||
|
||||
foreach ((array)$js_files as $js) {
|
||||
$assets->addJs($js);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +435,9 @@ class Debugger
|
||||
*/
|
||||
public function addCollector($collector)
|
||||
{
|
||||
$this->debugbar->addCollector($collector);
|
||||
if ($this->debugbar && !$this->debugbar->hasCollector($collector->getName())) {
|
||||
$this->debugbar->addCollector($collector);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -200,14 +445,18 @@ class Debugger
|
||||
/**
|
||||
* Returns a data collector
|
||||
*
|
||||
* @param DataCollectorInterface $collector
|
||||
* @param string $name
|
||||
*
|
||||
* @return DataCollectorInterface
|
||||
* @return DataCollectorInterface|null
|
||||
* @throws \DebugBar\DebugBarException
|
||||
*/
|
||||
public function getCollector($collector)
|
||||
public function getCollector($name)
|
||||
{
|
||||
return $this->debugbar->getCollector($collector);
|
||||
if ($this->debugbar && $this->debugbar->hasCollector($name)) {
|
||||
return $this->debugbar->getCollector($name);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,13 +466,14 @@ class Debugger
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
if ($this->enabled && $this->debugbar) {
|
||||
// Only add assets if Page is HTML
|
||||
$page = $this->grav['page'];
|
||||
if (!$this->renderer || $page->templateFormat() !== 'html') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->addMeasures();
|
||||
$this->addDeprecations();
|
||||
|
||||
echo $this->renderer->render();
|
||||
@@ -239,7 +489,8 @@ class Debugger
|
||||
*/
|
||||
public function sendDataInHeaders()
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
if ($this->enabled && $this->debugbar) {
|
||||
$this->addMeasures();
|
||||
$this->addDeprecations();
|
||||
$this->debugbar->sendDataInHeaders();
|
||||
}
|
||||
@@ -250,20 +501,150 @@ class Debugger
|
||||
/**
|
||||
* Returns collected debugger data.
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
if (!$this->enabled()) {
|
||||
if (!$this->enabled || !$this->debugbar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->addMeasures();
|
||||
$this->addDeprecations();
|
||||
$this->timers = [];
|
||||
|
||||
return $this->debugbar->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hierarchical Profiler support.
|
||||
*
|
||||
* @param callable $callable
|
||||
* @param string $message
|
||||
* @return mixed
|
||||
*/
|
||||
public function profile(callable $callable, string $message = null)
|
||||
{
|
||||
$this->startProfiling();
|
||||
$response = $callable();
|
||||
$this->stopProfiling($message);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start profiling code.
|
||||
*/
|
||||
public function startProfiling(): void
|
||||
{
|
||||
if ($this->enabled && extension_loaded('tideways_xhprof')) {
|
||||
$this->profiling++;
|
||||
if ($this->profiling === 1) {
|
||||
\tideways_xhprof_enable(TIDEWAYS_XHPROF_FLAGS_NO_BUILTINS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop profiling code. Returns profiling array or null if profiling couldn't be done.
|
||||
*
|
||||
* @param string $message
|
||||
* @return array|null
|
||||
*/
|
||||
public function stopProfiling(string $message = null): ?array
|
||||
{
|
||||
$timings = null;
|
||||
if ($this->enabled && extension_loaded('tideways_xhprof')) {
|
||||
$profiling = $this->profiling - 1;
|
||||
if ($profiling === 0) {
|
||||
$timings = \tideways_xhprof_disable();
|
||||
$timings = $this->buildProfilerTimings($timings);
|
||||
|
||||
if ($this->clockwork) {
|
||||
/** @var UserData $userData */
|
||||
$userData = $this->clockwork->userData('Profiler');
|
||||
$userData->counters([
|
||||
'Calls' => count($timings)
|
||||
]);
|
||||
$userData->table('Profiler', $timings);
|
||||
} else {
|
||||
$this->addMessage($message ?? 'Profiler Analysis', 'debug', $timings);
|
||||
}
|
||||
}
|
||||
$this->profiling = max(0, $profiling);
|
||||
}
|
||||
|
||||
return $timings;
|
||||
}
|
||||
|
||||
protected function buildProfilerTimings(array $timings): array
|
||||
{
|
||||
// Filter method calls which take almost no time.
|
||||
$timings = array_filter($timings, function ($value) {
|
||||
return $value['wt'] > 50;
|
||||
});
|
||||
|
||||
uasort($timings, function (array $a, array $b) {
|
||||
return $b['wt'] <=> $a['wt'];
|
||||
});
|
||||
|
||||
$table = [];
|
||||
foreach ($timings as $key => $timing) {
|
||||
$parts = explode('==>', $key);
|
||||
$method = $this->parseProfilerCall(array_pop($parts));
|
||||
$context = $this->parseProfilerCall(array_pop($parts));
|
||||
|
||||
// Skip redundant method calls.
|
||||
if ($context === 'Grav\Framework\RequestHandler\RequestHandler::handle()') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not profile library calls.
|
||||
if (strpos($context, 'Grav\\') !== 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$table[] = [
|
||||
'Context' => $context,
|
||||
'Method' => $method,
|
||||
'Calls' => $timing['ct'],
|
||||
'Time (ms)' => $timing['wt'] / 1000,
|
||||
];
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
protected function parseProfilerCall(?string $call)
|
||||
{
|
||||
if (null === $call) {
|
||||
return '';
|
||||
}
|
||||
if (strpos($call, '@')) {
|
||||
[$call,] = explode('@', $call);
|
||||
}
|
||||
if (strpos($call, '::')) {
|
||||
[$class, $call] = explode('::', $call);
|
||||
}
|
||||
|
||||
if (!isset($class)) {
|
||||
return $call;
|
||||
}
|
||||
|
||||
// It is also possible to display twig files, but they are being logged in views.
|
||||
/*
|
||||
if (strpos($class, '__TwigTemplate_') === 0 && class_exists($class)) {
|
||||
$env = new Environment();
|
||||
/ ** @var Template $template * /
|
||||
$template = new $class($env);
|
||||
|
||||
return $template->getTemplateName();
|
||||
}
|
||||
*/
|
||||
|
||||
return "{$class}::{$call}()";
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a timer with an associated name and description
|
||||
*
|
||||
@@ -274,10 +655,7 @@ class Debugger
|
||||
*/
|
||||
public function startTimer($name, $description = null)
|
||||
{
|
||||
if (strpos($name, '_') === 0 || $this->enabled()) {
|
||||
$this->debugbar['time']->startMeasure($name, $description);
|
||||
$this->timers[] = $name;
|
||||
}
|
||||
$this->timers[$name] = [$description, microtime(true)];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -291,8 +669,9 @@ class Debugger
|
||||
*/
|
||||
public function stopTimer($name)
|
||||
{
|
||||
if (\in_array($name, $this->timers, true) && (strpos($name, '_') === 0 || $this->enabled())) {
|
||||
$this->debugbar['time']->stopMeasure($name);
|
||||
if (isset($this->timers[$name])) {
|
||||
$endTime = microtime(true);
|
||||
$this->timers[$name][] = $endTime;
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -303,14 +682,74 @@ class Debugger
|
||||
*
|
||||
* @param mixed $message
|
||||
* @param string $label
|
||||
* @param bool $isString
|
||||
* @param mixed|bool $isString
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addMessage($message, $label = 'info', $isString = true)
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
$this->debugbar['messages']->addMessage($message, $label, $isString);
|
||||
if ($this->enabled) {
|
||||
if ($this->censored) {
|
||||
if (!is_scalar($message)) {
|
||||
$message = 'CENSORED';
|
||||
}
|
||||
if (!is_scalar($isString)) {
|
||||
$isString = ['CENSORED'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->debugbar) {
|
||||
if (is_array($isString)) {
|
||||
$message = $isString;
|
||||
$isString = false;
|
||||
} elseif (is_string($isString)) {
|
||||
$message = $isString;
|
||||
$isString = true;
|
||||
}
|
||||
$this->debugbar['messages']->addMessage($message, $label, $isString);
|
||||
}
|
||||
|
||||
if ($this->clockwork) {
|
||||
if (!is_scalar($message)) {
|
||||
$isString = $message;
|
||||
$message = '';
|
||||
}
|
||||
if (is_bool($isString)) {
|
||||
$isString = [];
|
||||
}
|
||||
if (!is_array($isString)) {
|
||||
$type = gettype($isString);
|
||||
$isString = [$type => $isString];
|
||||
}
|
||||
$this->clockwork->log($label, $message, $isString);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param object $event
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function addEvent(string $name, $event, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
if ($this->enabled) {
|
||||
if ($this->clockwork) {
|
||||
$data = null;
|
||||
if ($event && method_exists($event, '__debugInfo')) {
|
||||
$data = $event;
|
||||
}
|
||||
|
||||
$listeners = [];
|
||||
foreach ($dispatcher->getListeners($name) as $listener) {
|
||||
$listeners[] = $this->resolveCallable($listener);
|
||||
}
|
||||
|
||||
$this->clockwork->addEvent($name, $data, microtime(true), ['listeners' => $listeners]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -319,13 +758,23 @@ class Debugger
|
||||
/**
|
||||
* Dump exception into the Messages tab of the Debug Bar
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @param \Throwable $e
|
||||
* @return Debugger
|
||||
*/
|
||||
public function addException(\Exception $e)
|
||||
public function addException(\Throwable $e)
|
||||
{
|
||||
if ($this->initialized && $this->enabled()) {
|
||||
$this->debugbar['exceptions']->addException($e);
|
||||
if ($this->initialized && $this->enabled) {
|
||||
if ($this->debugbar) {
|
||||
$this->debugbar['exceptions']->addThrowable($e);
|
||||
}
|
||||
|
||||
if ($this->clockwork) {
|
||||
/** @var UserData $exceptions */
|
||||
$exceptions = $this->clockwork->userData('Exceptions');
|
||||
$exceptions->data(['message' => $e->getMessage()]);
|
||||
|
||||
$this->clockwork->alert($e->getMessage(), ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -347,7 +796,7 @@ class Debugger
|
||||
*/
|
||||
public function deprecatedErrorHandler($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
if ($errno !== E_USER_DEPRECATED) {
|
||||
if ($errno !== E_USER_DEPRECATED && $errno !== E_DEPRECATED) {
|
||||
if ($this->errorHandler) {
|
||||
return \call_user_func($this->errorHandler, $errno, $errstr, $errfile, $errline);
|
||||
}
|
||||
@@ -355,7 +804,7 @@ class Debugger
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->enabled()) {
|
||||
if (!$this->enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -540,6 +989,21 @@ class Debugger
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getDeprecations(): array
|
||||
{
|
||||
if (!$this->deprecations) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
/** @var array $deprecated */
|
||||
foreach ($this->deprecations as $deprecated) {
|
||||
$list[] = $this->getDepracatedMessage($deprecated)[0];
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function addDeprecations()
|
||||
{
|
||||
if (!$this->deprecations) {
|
||||
@@ -603,4 +1067,13 @@ class Debugger
|
||||
|
||||
return $trace['function'] . '(' . implode(', ', $trace['args'] ?? []) . ')';
|
||||
}
|
||||
|
||||
protected function resolveCallable(callable $callable)
|
||||
{
|
||||
if (is_array($callable)) {
|
||||
return get_class($callable[0]) . '->' . $callable[1] . '()';
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Errors
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,20 +13,17 @@ use Whoops\Handler\Handler;
|
||||
|
||||
class BareHandler extends Handler
|
||||
{
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$inspector = $this->getInspector();
|
||||
$code = $inspector->getException()->getCode();
|
||||
if ( ($code >= 400) && ($code < 600) )
|
||||
{
|
||||
$this->getRun()->sendHttpCode($code);
|
||||
if (($code >= 400) && ($code < 600)) {
|
||||
$this->getRun()->sendHttpCode($code);
|
||||
}
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Errors
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -40,23 +40,23 @@ class Errors
|
||||
$error_page->setPageTitle('Crikey! There was an error...');
|
||||
$error_page->addResourcePath(GRAV_ROOT . '/system/assets');
|
||||
$error_page->addCustomCss('whoops.css');
|
||||
$whoops->pushHandler($error_page);
|
||||
$whoops->prependHandler($error_page);
|
||||
break;
|
||||
case -1:
|
||||
$whoops->pushHandler(new BareHandler);
|
||||
$whoops->prependHandler(new BareHandler);
|
||||
break;
|
||||
default:
|
||||
$whoops->pushHandler(new SimplePageHandler);
|
||||
$whoops->prependHandler(new SimplePageHandler);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Whoops\Util\Misc::isAjaxRequest() || $jsonRequest) {
|
||||
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
|
||||
$whoops->prependHandler(new Whoops\Handler\JsonResponseHandler);
|
||||
}
|
||||
|
||||
if (isset($config['log']) && $config['log']) {
|
||||
$logger = $grav['log'];
|
||||
$whoops->pushHandler(function($exception, $inspector, $run) use ($logger) {
|
||||
$whoops->prependHandler(function ($exception, $inspector, $run) use ($logger) {
|
||||
try {
|
||||
$logger->addCritical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Errors
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -15,8 +15,10 @@ use Whoops\Util\TemplateHelper;
|
||||
|
||||
class SimplePageHandler extends Handler
|
||||
{
|
||||
private $searchPaths = array();
|
||||
private $resourceCache = array();
|
||||
/** @var array */
|
||||
private $searchPaths = [];
|
||||
/** @var array */
|
||||
private $resourceCache = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -25,7 +27,7 @@ class SimplePageHandler extends Handler
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -36,9 +38,8 @@ class SimplePageHandler extends Handler
|
||||
$cssFile = $this->getResource('error.css');
|
||||
|
||||
$code = $inspector->getException()->getCode();
|
||||
if ( ($code >= 400) && ($code < 600) )
|
||||
{
|
||||
$this->getRun()->sendHttpCode($code);
|
||||
if (($code >= 400) && ($code < 600)) {
|
||||
$this->getRun()->sendHttpCode($code);
|
||||
}
|
||||
$message = $inspector->getException()->getMessage();
|
||||
|
||||
@@ -60,7 +61,6 @@ class SimplePageHandler extends Handler
|
||||
|
||||
/**
|
||||
* @param string $resource
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
@@ -90,6 +90,9 @@ class SimplePageHandler extends Handler
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*/
|
||||
public function addResourcePath($path)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
@@ -101,6 +104,9 @@ class SimplePageHandler extends Handler
|
||||
array_unshift($this->searchPaths, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResourcePaths()
|
||||
{
|
||||
return $this->searchPaths;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Errors
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace Grav\Common\Errors;
|
||||
|
||||
class SystemFacade extends \Whoops\Util\SystemFacade
|
||||
{
|
||||
/** @var callable */
|
||||
protected $whoopsShutdownHandler;
|
||||
|
||||
/**
|
||||
* @param callable $function
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerShutdownFunction(callable $function)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\File
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,7 @@ trait CompiledFile
|
||||
* Get/set parsed file contents.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @return string
|
||||
* @return string|array
|
||||
*/
|
||||
public function content($var = null)
|
||||
{
|
||||
@@ -38,8 +38,7 @@ trait CompiledFile
|
||||
$cache = $file->exists() ? $file->content() : null;
|
||||
|
||||
// Load real file if cache isn't up to date (or is invalid).
|
||||
if (
|
||||
!isset($cache['@class'])
|
||||
if (!isset($cache['@class'])
|
||||
|| $cache['@class'] !== $class
|
||||
|| $cache['modified'] !== $modified
|
||||
|| $cache['filename'] !== $this->filename
|
||||
@@ -76,7 +75,6 @@ trait CompiledFile
|
||||
|
||||
$this->content = $cache['data'];
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Failed to read %s: %s', basename($this->filename), $e->getMessage()), 500, $e);
|
||||
}
|
||||
@@ -86,6 +84,8 @@ trait CompiledFile
|
||||
|
||||
/**
|
||||
* Serialize file.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\File
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ class CompiledJsonFile extends JsonFile
|
||||
*
|
||||
* @param string $var
|
||||
* @param bool $assoc
|
||||
* @return array mixed
|
||||
* @return array
|
||||
*/
|
||||
protected function decode($var, $assoc = true)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\File
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\File
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,13 +13,19 @@ use Grav\Common\Utils;
|
||||
|
||||
abstract class Archiver
|
||||
{
|
||||
/** @var array */
|
||||
protected $options = [
|
||||
'exclude_files' => ['.DS_Store'],
|
||||
'exclude_paths' => []
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
protected $archive_file;
|
||||
|
||||
/**
|
||||
* @param string $compression
|
||||
* @return ZipArchiver
|
||||
*/
|
||||
public static function create($compression)
|
||||
{
|
||||
if ($compression === 'zip') {
|
||||
@@ -29,12 +35,20 @@ abstract class Archiver
|
||||
return new ZipArchiver();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $archive_file
|
||||
* @return $this
|
||||
*/
|
||||
public function setArchive($archive_file)
|
||||
{
|
||||
$this->archive_file = $archive_file;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @return $this
|
||||
*/
|
||||
public function setOptions($options)
|
||||
{
|
||||
// Set infinite PHP execution time if possible.
|
||||
@@ -46,12 +60,31 @@ abstract class Archiver
|
||||
return $this;
|
||||
}
|
||||
|
||||
public abstract function compress($folder, callable $status = null);
|
||||
/**
|
||||
* @param string $folder
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
abstract public function compress($folder, callable $status = null);
|
||||
|
||||
public abstract function extract($destination, callable $status = null);
|
||||
/**
|
||||
* @param string $destination
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
abstract public function extract($destination, callable $status = null);
|
||||
|
||||
public abstract function addEmptyFolders($folders, callable $status = null);
|
||||
/**
|
||||
* @param array $folders
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
abstract public function addEmptyFolders($folders, callable $status = null);
|
||||
|
||||
/**
|
||||
* @param string $rootPath
|
||||
* @return \RecursiveIteratorIterator
|
||||
*/
|
||||
protected function getArchiveFiles($rootPath)
|
||||
{
|
||||
$exclude_paths = $this->options['exclude_paths'];
|
||||
@@ -62,5 +95,4 @@ abstract class Archiver
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,10 @@ abstract class Folder
|
||||
*/
|
||||
public static function lastModifiedFolder($path)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$last_modified = 0;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
@@ -51,11 +55,14 @@ abstract class Folder
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $extensions which files to search for specifically
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function lastModifiedFile($path, $extensions = 'md|yaml')
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$last_modified = 0;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
@@ -92,21 +99,24 @@ abstract class Folder
|
||||
*/
|
||||
public static function hashAllFiles($path)
|
||||
{
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS;
|
||||
$files = [];
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
if ($locator->isStream($path)) {
|
||||
$directory = $locator->getRecursiveIterator($path, $flags);
|
||||
} else {
|
||||
$directory = new \RecursiveDirectoryIterator($path, $flags);
|
||||
}
|
||||
if (file_exists($path)) {
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS;
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
if ($locator->isStream($path)) {
|
||||
$directory = $locator->getRecursiveIterator($path, $flags);
|
||||
} else {
|
||||
$directory = new \RecursiveDirectoryIterator($path, $flags);
|
||||
}
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$files[] = $file->getPathname() . '?'. $file->getMTime();
|
||||
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$files[] = $file->getPathname() . '?'. $file->getMTime();
|
||||
}
|
||||
}
|
||||
|
||||
return md5(serialize($files));
|
||||
@@ -115,9 +125,8 @@ abstract class Folder
|
||||
/**
|
||||
* Get relative path between target and base path. If path isn't relative, return full path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param mixed|string $base
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $base
|
||||
* @return string
|
||||
*/
|
||||
public static function getRelativePath($path, $base = GRAV_ROOT)
|
||||
@@ -196,9 +205,12 @@ abstract class Folder
|
||||
*/
|
||||
public static function all($path, array $params = [])
|
||||
{
|
||||
if ($path === false) {
|
||||
if (!$path) {
|
||||
throw new \RuntimeException("Path doesn't exist.");
|
||||
}
|
||||
if (!file_exists($path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$compare = isset($params['compare']) ? 'get' . $params['compare'] : null;
|
||||
$pattern = $params['pattern'] ?? null;
|
||||
@@ -235,7 +247,7 @@ abstract class Folder
|
||||
/** @var \RecursiveDirectoryIterator $file */
|
||||
foreach ($iterator as $file) {
|
||||
// Ignore hidden files.
|
||||
if (strpos($file->getFilename(), '.') === 0) {
|
||||
if (strpos($file->getFilename(), '.') === 0 && $file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
if (!$folders && $file->isDir()) {
|
||||
@@ -472,6 +484,21 @@ abstract class Folder
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a directory contain children
|
||||
*
|
||||
* @param $dir
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasChildren($directory) {
|
||||
if (!is_dir($directory)) {
|
||||
return false;
|
||||
}
|
||||
$directories = glob($directory . '/*', GLOB_ONLYDIR);
|
||||
|
||||
return !empty($directories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $folder
|
||||
* @param bool $include_target
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -11,8 +11,11 @@ namespace Grav\Common\Filesystem;
|
||||
|
||||
class RecursiveDirectoryFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
/** @var string */
|
||||
protected static $root;
|
||||
/** @var array */
|
||||
protected static $ignore_folders;
|
||||
/** @var array */
|
||||
protected static $ignore_files;
|
||||
|
||||
/**
|
||||
@@ -57,6 +60,9 @@ class RecursiveDirectoryFilterIterator extends \RecursiveFilterIterator
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecursiveDirectoryFilterIterator|\RecursiveFilterIterator
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
/** @var RecursiveDirectoryFilterIterator $iterator */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@ use Grav\Common\Grav;
|
||||
|
||||
class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
/** @var array */
|
||||
protected static $ignore_folders;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,11 @@ namespace Grav\Common\Filesystem;
|
||||
|
||||
class ZipArchiver extends Archiver
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $destination
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
public function extract($destination, callable $status = null)
|
||||
{
|
||||
$zip = new \ZipArchive();
|
||||
@@ -31,6 +35,11 @@ class ZipArchiver extends Archiver
|
||||
throw new \RuntimeException('ZipArchiver: Failed to open ' . $this->archive_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
public function compress($source, callable $status = null)
|
||||
{
|
||||
if (!extension_loaded('zip')) {
|
||||
@@ -81,6 +90,11 @@ class ZipArchiver extends Archiver
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $folders
|
||||
* @param callable|null $status
|
||||
* @return $this
|
||||
*/
|
||||
public function addEmptyFolders($folders, callable $status = null)
|
||||
{
|
||||
if (!extension_loaded('zip')) {
|
||||
@@ -97,7 +111,7 @@ class ZipArchiver extends Archiver
|
||||
'message' => 'Adding empty folders...'
|
||||
]);
|
||||
|
||||
foreach($folders as $folder) {
|
||||
foreach ($folders as $folder) {
|
||||
$zip->addEmptyDir($folder);
|
||||
$status && $status([
|
||||
'type' => 'progress',
|
||||
|
||||
51
system/src/Grav/Common/Flex/Traits/FlexCollectionTrait.php
Normal file
51
system/src/Grav/Common/Flex/Traits/FlexCollectionTrait.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Flex
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Flex\Traits;
|
||||
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
/**
|
||||
* Trait FlexCollectionTrait
|
||||
* @package Grav\Common\Flex\Traits
|
||||
*/
|
||||
trait FlexCollectionTrait
|
||||
{
|
||||
use FlexCommonTrait;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param object|null $event
|
||||
* @return $this
|
||||
*/
|
||||
public function triggerEvent(string $name, $event = null)
|
||||
{
|
||||
if (null === $event) {
|
||||
$event = new Event([
|
||||
'type' => 'flex',
|
||||
'directory' => $this->getFlexDirectory(),
|
||||
'collection' => $this
|
||||
]);
|
||||
}
|
||||
if (strpos($name, 'onFlexCollection') !== 0 && strpos($name, 'on') === 0) {
|
||||
$name = 'onFlexCollection' . substr($name, 2);
|
||||
}
|
||||
|
||||
$container = $this->getContainer();
|
||||
if ($event instanceof Event) {
|
||||
$container->fireEvent($name, $event);
|
||||
} else {
|
||||
$container->dispatchEvent($event);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
54
system/src/Grav/Common/Flex/Traits/FlexCommonTrait.php
Normal file
54
system/src/Grav/Common/Flex/Traits/FlexCommonTrait.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Flex
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Flex\Traits;
|
||||
|
||||
use Grav\Common\Debugger;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Twig\Twig;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Template;
|
||||
use Twig\TemplateWrapper;
|
||||
|
||||
/**
|
||||
* Trait FlexCommonTrait
|
||||
* @package Grav\Common\Flex\Traits
|
||||
*/
|
||||
trait FlexCommonTrait
|
||||
{
|
||||
/**
|
||||
* @param string $layout
|
||||
* @return Template|TemplateWrapper
|
||||
* @throws LoaderError
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
protected function getTemplate($layout)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
|
||||
/** @var Twig $twig */
|
||||
$twig = $container['twig'];
|
||||
|
||||
try {
|
||||
return $twig->twig()->resolveTemplate($this->getTemplatePaths($layout));
|
||||
} catch (LoaderError $e) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = Grav::instance()['debugger'];
|
||||
$debugger->addException($e);
|
||||
|
||||
return $twig->twig()->resolveTemplate(['flex/404.html.twig']);
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected function getTemplatePaths(string $layout): array;
|
||||
abstract protected function getContainer(): Grav;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user