Compare commits
510 Commits
1.0.0-rc.1
...
1.0.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b48449d782 | ||
|
|
ee20bf70e0 | ||
|
|
8cb098c6e0 | ||
|
|
3054a67078 | ||
|
|
8ca14c7c65 | ||
|
|
6e2d9ca3cc | ||
|
|
eff72b73ab | ||
|
|
eb29d68958 | ||
|
|
e0632dee09 | ||
|
|
4549574908 | ||
|
|
0866a62a1f | ||
|
|
1a7fd382a9 | ||
|
|
cdc96ca574 | ||
|
|
d121aa3415 | ||
|
|
6aaeb9e1f1 | ||
|
|
fa39629104 | ||
|
|
9e13593c11 | ||
|
|
0b3970d7c1 | ||
|
|
95c09f2ce5 | ||
|
|
c78619aad3 | ||
|
|
566da30513 | ||
|
|
f8c8ac4371 | ||
|
|
3c4dd26c20 | ||
|
|
f5fc509f14 | ||
|
|
2d00203a1f | ||
|
|
ac23ab21b8 | ||
|
|
0261df0d48 | ||
|
|
2709938f9f | ||
|
|
53e1c790d8 | ||
|
|
f2f9fc4ed6 | ||
|
|
3cbf9c7101 | ||
|
|
c655d9e8fc | ||
|
|
2ef7f7cf36 | ||
|
|
418f0972a9 | ||
|
|
9a777efd52 | ||
|
|
aa8a329c7b | ||
|
|
e4930a144f | ||
|
|
194014007f | ||
|
|
dc8f2c1466 | ||
|
|
6ee48c74f7 | ||
|
|
136a9e8218 | ||
|
|
34045ea62b | ||
|
|
267edbee7d | ||
|
|
da882ebcd2 | ||
|
|
ed0ba1ed98 | ||
|
|
ef9dd3aa28 | ||
|
|
73b9abd38b | ||
|
|
6e399fe0ed | ||
|
|
5f9ed17091 | ||
|
|
1f4b3913b6 | ||
|
|
dc9b9509d7 | ||
|
|
b4f34c8643 | ||
|
|
52544a8b25 | ||
|
|
017500a6b5 | ||
|
|
425ae30e62 | ||
|
|
1aa09d8987 | ||
|
|
a45196dc97 | ||
|
|
8d7ab6fdd3 | ||
|
|
87870bcde7 | ||
|
|
9b85c1b0f7 | ||
|
|
104012228c | ||
|
|
e3deb40f69 | ||
|
|
492b290845 | ||
|
|
3eb2a5664a | ||
|
|
15fd233e56 | ||
|
|
912f697cff | ||
|
|
d827228dc2 | ||
|
|
84073a53cb | ||
|
|
f562573640 | ||
|
|
66aa66954c | ||
|
|
99275dfe59 | ||
|
|
efded08d6e | ||
|
|
d726f15aa3 | ||
|
|
7c6cd30aea | ||
|
|
f0145aa659 | ||
|
|
879b5ef272 | ||
|
|
91a57e1a16 | ||
|
|
3698afb8a6 | ||
|
|
8e1b2bc6e4 | ||
|
|
37dd107281 | ||
|
|
2d3b41c62d | ||
|
|
c9b8fc0e1b | ||
|
|
7eb57b674a | ||
|
|
25b33d0204 | ||
|
|
d47faed870 | ||
|
|
9a8efdf9cd | ||
|
|
593fd20a15 | ||
|
|
ef75582e20 | ||
|
|
7440074491 | ||
|
|
9688ed0f51 | ||
|
|
45d415e547 | ||
|
|
b2c7e22634 | ||
|
|
4581077dcd | ||
|
|
729f83b3d4 | ||
|
|
bf361db5fc | ||
|
|
328e9b20de | ||
|
|
484a34cd92 | ||
|
|
5ab4d916b0 | ||
|
|
f0974e0d24 | ||
|
|
06a5aa6d01 | ||
|
|
a88829bd57 | ||
|
|
c023c74ae5 | ||
|
|
a8ad14222d | ||
|
|
6c6871f607 | ||
|
|
5764e5e686 | ||
|
|
b89044a709 | ||
|
|
5fc4755d3b | ||
|
|
2f2adaaee8 | ||
|
|
e2ae24faa9 | ||
|
|
55bc84c118 | ||
|
|
a47d5d00b3 | ||
|
|
05c2b98929 | ||
|
|
c5d3098b25 | ||
|
|
6805f32a13 | ||
|
|
b8aa250a22 | ||
|
|
bf05a36dfe | ||
|
|
8f9cdad916 | ||
|
|
d2ed424a7c | ||
|
|
08cbd9553f | ||
|
|
369d2cb390 | ||
|
|
dcaa9a35c3 | ||
|
|
4a80691e07 | ||
|
|
215b2cdfa8 | ||
|
|
425831a7ae | ||
|
|
984e0455b1 | ||
|
|
00ecfb30f3 | ||
|
|
c18f20e483 | ||
|
|
71c5ff8c51 | ||
|
|
1996dd7de8 | ||
|
|
e87daa2361 | ||
|
|
987feb1385 | ||
|
|
8d048c689f | ||
|
|
139ef04e0a | ||
|
|
4c01e6c93e | ||
|
|
27744ba747 | ||
|
|
3d3c6f4eba | ||
|
|
fb4abc5f5f | ||
|
|
f29b141d69 | ||
|
|
1cecd09423 | ||
|
|
0142e76270 | ||
|
|
5f8c7f41ec | ||
|
|
451baff26e | ||
|
|
78accfe98b | ||
|
|
0e8e27877e | ||
|
|
d8a993bc86 | ||
|
|
ec7dbbdc8b | ||
|
|
c45652de81 | ||
|
|
e152cfd10f | ||
|
|
747daa46f1 | ||
|
|
17a0590ee4 | ||
|
|
653edb064b | ||
|
|
40f5d57737 | ||
|
|
566c5cb38f | ||
|
|
7e3058e3f0 | ||
|
|
053d8a3fd5 | ||
|
|
0e810c15e2 | ||
|
|
6b9154d1f3 | ||
|
|
4a5a400b89 | ||
|
|
2d7a3232cc | ||
|
|
96d7c4790f | ||
|
|
c0b9ada21c | ||
|
|
7b116b41ae | ||
|
|
fcdd0bc0e9 | ||
|
|
0619f7c656 | ||
|
|
f7696b61d3 | ||
|
|
48083b203a | ||
|
|
f8aa9fed91 | ||
|
|
c55521ac4a | ||
|
|
2bb23efa7c | ||
|
|
cdcb76cc55 | ||
|
|
def726a012 | ||
|
|
7d1291e2b9 | ||
|
|
a0297e9d65 | ||
|
|
e4e0c06ea8 | ||
|
|
f46ad2d032 | ||
|
|
0c807b6108 | ||
|
|
3a47d6a580 | ||
|
|
52947b3a2c | ||
|
|
eacfc798f4 | ||
|
|
5c0e5f3c01 | ||
|
|
985141b842 | ||
|
|
1aac2ab95d | ||
|
|
aa7d5ddf59 | ||
|
|
e87505378d | ||
|
|
53f097c2b3 | ||
|
|
6ea7fe9dba | ||
|
|
0206f1b0c7 | ||
|
|
ef9f2c77dd | ||
|
|
822292f541 | ||
|
|
ec08cd9374 | ||
|
|
8fb4063cf2 | ||
|
|
8a2b444c48 | ||
|
|
9c6f243902 | ||
|
|
d5bd99b363 | ||
|
|
5554c07cbf | ||
|
|
acd95aac6f | ||
|
|
8ad5f2624d | ||
|
|
8adc0e1c17 | ||
|
|
fab66cf3a5 | ||
|
|
5df48e7a68 | ||
|
|
079a8c5728 | ||
|
|
d9196426a1 | ||
|
|
2f686f5b74 | ||
|
|
c4b5df20a9 | ||
|
|
06608a6d3c | ||
|
|
fd63911faf | ||
|
|
66a1e55867 | ||
|
|
af2eb2e75d | ||
|
|
9b4f32cafd | ||
|
|
9179fbd1a2 | ||
|
|
24ea7f1f55 | ||
|
|
9b95053110 | ||
|
|
71ffb9c72f | ||
|
|
f29f698f61 | ||
|
|
f1f8579a0b | ||
|
|
4ca8fab750 | ||
|
|
b80ed731b0 | ||
|
|
23a9a73600 | ||
|
|
dc8c0b6522 | ||
|
|
e695b1942c | ||
|
|
3f543e7e84 | ||
|
|
7f6f9e82e3 | ||
|
|
51529eb0ce | ||
|
|
05b24a4b75 | ||
|
|
ca5819489f | ||
|
|
1d2acf8096 | ||
|
|
98278e965b | ||
|
|
7bc990688c | ||
|
|
b86aa6d473 | ||
|
|
dba7347c1e | ||
|
|
fa52e18e3f | ||
|
|
b605753a6d | ||
|
|
0af4fb351c | ||
|
|
90edf95077 | ||
|
|
ab3843442a | ||
|
|
023b9dd708 | ||
|
|
0ac882314e | ||
|
|
0fe9264582 | ||
|
|
b1e16b2206 | ||
|
|
a67c1780c1 | ||
|
|
1170f2f58d | ||
|
|
199c0a08ea | ||
|
|
84ad152536 | ||
|
|
5b0f905ae3 | ||
|
|
a2bba8f09d | ||
|
|
2007975428 | ||
|
|
e484997515 | ||
|
|
af5c52c52f | ||
|
|
f3d0e10378 | ||
|
|
b33ab43ff9 | ||
|
|
c580399db6 | ||
|
|
00d8717d7c | ||
|
|
6e2f4607a6 | ||
|
|
3a7abeb18b | ||
|
|
84a5984c65 | ||
|
|
1465c26b1f | ||
|
|
b399d8e3b9 | ||
|
|
b5c04bdc9b | ||
|
|
b4725800c3 | ||
|
|
2b1a102efa | ||
|
|
500c548af4 | ||
|
|
fc7017f822 | ||
|
|
5b254f4cf8 | ||
|
|
43783f3ce6 | ||
|
|
ae39aabee1 | ||
|
|
df7a94148b | ||
|
|
63890661fe | ||
|
|
793ac1a1bb | ||
|
|
77db54c50d | ||
|
|
b259927348 | ||
|
|
e8972a6aa5 | ||
|
|
8d8420c0d6 | ||
|
|
7a6707f597 | ||
|
|
b0ec66cce8 | ||
|
|
edfd7db88b | ||
|
|
fb3e68e16e | ||
|
|
080ab9e289 | ||
|
|
f67e441b83 | ||
|
|
9c07d69c45 | ||
|
|
13207f13ad | ||
|
|
34f83ebde2 | ||
|
|
14ed805656 | ||
|
|
385233c508 | ||
|
|
8a3b987cd5 | ||
|
|
bdd17fc56a | ||
|
|
29b3c081ee | ||
|
|
b1d80b6c5f | ||
|
|
e00560f81a | ||
|
|
20f17130a2 | ||
|
|
583156d2f3 | ||
|
|
88f36f4987 | ||
|
|
965c8cfbe9 | ||
|
|
b8f00243e6 | ||
|
|
1d97f98515 | ||
|
|
9764cf3f65 | ||
|
|
1f5df81496 | ||
|
|
5f76a0255c | ||
|
|
17f3ca6eba | ||
|
|
b29d79738b | ||
|
|
020cdd7324 | ||
|
|
1e39f3b22d | ||
|
|
37035a488d | ||
|
|
745b418cd7 | ||
|
|
2a02c8bc4f | ||
|
|
a15e063b92 | ||
|
|
2051fed5b7 | ||
|
|
268714863e | ||
|
|
60c6532307 | ||
|
|
50c6e81c09 | ||
|
|
2a0a9a225c | ||
|
|
aee92b58c7 | ||
|
|
16db950009 | ||
|
|
bde33e7188 | ||
|
|
267efbe164 | ||
|
|
f9e137c994 | ||
|
|
e7f9751403 | ||
|
|
9adf81294d | ||
|
|
3033818589 | ||
|
|
06d663680c | ||
|
|
1bbdca5032 | ||
|
|
c1654a988e | ||
|
|
18a540c867 | ||
|
|
99fc8df322 | ||
|
|
2d21cb8b1e | ||
|
|
d8008654b9 | ||
|
|
146295fb1e | ||
|
|
09ed480628 | ||
|
|
5dd1554e5d | ||
|
|
748f329c8e | ||
|
|
7228b25393 | ||
|
|
63e083ea37 | ||
|
|
b1630feb5d | ||
|
|
1185a91c90 | ||
|
|
dce6d7894b | ||
|
|
375ee0d1fa | ||
|
|
ce0574f897 | ||
|
|
c515111446 | ||
|
|
7d6393628e | ||
|
|
24fde7261a | ||
|
|
3d922abf1a | ||
|
|
7f1d3a94fe | ||
|
|
3d774b7585 | ||
|
|
b0083548b6 | ||
|
|
905dae3b16 | ||
|
|
d79979371b | ||
|
|
c4bff94f7d | ||
|
|
7c4fd3858c | ||
|
|
3b9af8883d | ||
|
|
29b34d7de0 | ||
|
|
90fcf448c7 | ||
|
|
5193551d04 | ||
|
|
d2660e0755 | ||
|
|
2d8ac27fdd | ||
|
|
dd2ddfeb40 | ||
|
|
ac3396e6c4 | ||
|
|
49a5b38589 | ||
|
|
6e2f792bb9 | ||
|
|
da098fd46a | ||
|
|
3e081b340f | ||
|
|
698015a03d | ||
|
|
000a10f936 | ||
|
|
c764e31c8a | ||
|
|
c18021d52a | ||
|
|
3d0cc67415 | ||
|
|
3f94a6fda9 | ||
|
|
7f0eefbde5 | ||
|
|
280377985f | ||
|
|
d5b3f070a5 | ||
|
|
3505ef046d | ||
|
|
a6bc565356 | ||
|
|
a1ee3cf4e4 | ||
|
|
e96445abe3 | ||
|
|
c22fae0d3d | ||
|
|
d888dcd085 | ||
|
|
184cb9ea3a | ||
|
|
3cf6e8762c | ||
|
|
f0cdd7c03e | ||
|
|
5e40201888 | ||
|
|
f2c2debb28 | ||
|
|
997c772b7c | ||
|
|
bc4a09f80d | ||
|
|
0e3e7497ac | ||
|
|
72313ac9ec | ||
|
|
dc80228f0b | ||
|
|
a83642a7e3 | ||
|
|
00d8403095 | ||
|
|
e1ec8e9742 | ||
|
|
0725af5367 | ||
|
|
65e543af02 | ||
|
|
b49e8315eb | ||
|
|
c5a89112b4 | ||
|
|
94ec474ffa | ||
|
|
da4593fdc1 | ||
|
|
b8413cefaf | ||
|
|
d3097e4fd0 | ||
|
|
51753f0716 | ||
|
|
b7ada873b8 | ||
|
|
ed8b08a9e4 | ||
|
|
e1fdb6803d | ||
|
|
5cb9f2f42f | ||
|
|
fcf48ed2e5 | ||
|
|
050512536a | ||
|
|
99207fca13 | ||
|
|
55890b4fd8 | ||
|
|
6fdfaccc92 | ||
|
|
76e01e7aea | ||
|
|
87378562ea | ||
|
|
77d80f12f3 | ||
|
|
e400207a65 | ||
|
|
4b68036a1b | ||
|
|
a95b716aa7 | ||
|
|
dc8efded34 | ||
|
|
e016b17276 | ||
|
|
b99876f0b4 | ||
|
|
66abc842b7 | ||
|
|
9f36158c67 | ||
|
|
18c1ca3919 | ||
|
|
0c729e5b0a | ||
|
|
55f3b78ab1 | ||
|
|
a73b796ca7 | ||
|
|
bb0bca7ef1 | ||
|
|
b3144ee921 | ||
|
|
a86ce7cb28 | ||
|
|
ccf2a780b6 | ||
|
|
b0c1dbe4b7 | ||
|
|
ec73eef695 | ||
|
|
467d68344e | ||
|
|
8899b3ebb8 | ||
|
|
5478cfaf9f | ||
|
|
4b6a85f30a | ||
|
|
e62ff07726 | ||
|
|
a045107cc7 | ||
|
|
c97edb60a5 | ||
|
|
695793b752 | ||
|
|
c953ffb471 | ||
|
|
3d7fa06129 | ||
|
|
49d4fbcf3d | ||
|
|
fc18a40c35 | ||
|
|
1e81d5e38c | ||
|
|
daf8b53c0d | ||
|
|
8de55a745d | ||
|
|
6bf669815d | ||
|
|
8ba49e163d | ||
|
|
26918d90ab | ||
|
|
929b0806dc | ||
|
|
3e32e61db1 | ||
|
|
038693bffb | ||
|
|
9445aa43e6 | ||
|
|
bb16dbab78 | ||
|
|
658212e7be | ||
|
|
e91554770c | ||
|
|
8f9671ad32 | ||
|
|
7f134e39f4 | ||
|
|
c87e3f419d | ||
|
|
07b2767ac9 | ||
|
|
0ca24a9786 | ||
|
|
c84c1366e7 | ||
|
|
ebf9bb5c18 | ||
|
|
70b67a0805 | ||
|
|
545b97716f | ||
|
|
7e540e0623 | ||
|
|
f7140522f6 | ||
|
|
bd2f7088e9 | ||
|
|
5260c181a1 | ||
|
|
a9538adf2b | ||
|
|
8bba0fd332 | ||
|
|
abf6d6638e | ||
|
|
36e52146f5 | ||
|
|
24eaa24839 | ||
|
|
fafd72fcd8 | ||
|
|
df9b219a16 | ||
|
|
5c9c378889 | ||
|
|
47e1eab6c1 | ||
|
|
d88f56316d | ||
|
|
8b414c388d | ||
|
|
acb828eacf | ||
|
|
293dfad87e | ||
|
|
e4e1927126 | ||
|
|
edf6f86cb5 | ||
|
|
d086664a61 | ||
|
|
b0c171f453 | ||
|
|
feed15f75b | ||
|
|
95fd54d909 | ||
|
|
79f6380aae | ||
|
|
8478d690a0 | ||
|
|
5db8197db2 | ||
|
|
8407e5b295 | ||
|
|
3e3b4548e9 | ||
|
|
868a61dd34 | ||
|
|
a7a5625a8b | ||
|
|
a614c8c7cc | ||
|
|
f65633043a | ||
|
|
de61d88d29 | ||
|
|
9d86c0a9db | ||
|
|
67fefb53ad | ||
|
|
0ff5dc0016 | ||
|
|
ae17a77789 | ||
|
|
5f11ae7482 | ||
|
|
4d33eb2173 | ||
|
|
fe7873ddbe | ||
|
|
f95a4f5cc6 | ||
|
|
f973b61b5e | ||
|
|
f1d4192ae7 | ||
|
|
fb500d3e1c | ||
|
|
14347ebf88 | ||
|
|
3e0188e40b | ||
|
|
b82f17f367 | ||
|
|
3f28dc59ea | ||
|
|
77deea8ad4 | ||
|
|
e27f638fe3 |
4
.gitignore
vendored
@@ -16,12 +16,15 @@ logs/*
|
|||||||
!logs/.*
|
!logs/.*
|
||||||
images/*
|
images/*
|
||||||
!images/.*
|
!images/.*
|
||||||
|
user/accounts/*
|
||||||
|
!user/accounts/.*
|
||||||
user/data/*
|
user/data/*
|
||||||
!user/data/.*
|
!user/data/.*
|
||||||
user/plugins/*
|
user/plugins/*
|
||||||
!user/plugins/.*
|
!user/plugins/.*
|
||||||
user/themes/*
|
user/themes/*
|
||||||
!user/themes/.*
|
!user/themes/.*
|
||||||
|
user/localhost/config/security.yaml
|
||||||
|
|
||||||
# OS Generated
|
# OS Generated
|
||||||
.DS_Store*
|
.DS_Store*
|
||||||
@@ -32,3 +35,4 @@ Thumbs.db
|
|||||||
|
|
||||||
# phpstorm
|
# phpstorm
|
||||||
.idea/*
|
.idea/*
|
||||||
|
user/config/security.yaml
|
||||||
|
|||||||
12
.htaccess
@@ -44,15 +44,17 @@ RewriteRule .* index.php [L]
|
|||||||
|
|
||||||
## Begin - Security
|
## Begin - Security
|
||||||
# Block all direct access for these folders
|
# Block all direct access for these folders
|
||||||
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [L]
|
RewriteRule ^(.git|cache|bin|logs|backup|webserver-configs)/(.*) error [F]
|
||||||
# Block access to specific file types for these folders
|
# Block access to specific file types for these system folders
|
||||||
RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L]
|
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||||
|
# Block access to specific file types for these user folders
|
||||||
|
RewriteRule ^(user)/(.*)\.(txt|md|yaml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||||
# Block all direct access to .md files:
|
# Block all direct access to .md files:
|
||||||
RewriteRule \.md$ error [L]
|
RewriteRule \.md$ error [F]
|
||||||
# Block all direct access to files and folders beginning with a dot
|
# Block all direct access to files and folders beginning with a dot
|
||||||
RewriteRule (^\.|/\.) - [F]
|
RewriteRule (^\.|/\.) - [F]
|
||||||
# Block access to specific files in the root folder
|
# Block access to specific files in the root folder
|
||||||
RewriteRule ^(LICENSE|composer.lock|composer.json|nginx.conf|web.config)$ error [F]
|
RewriteRule ^(LICENSE.txt|composer.lock|composer.json|\.htaccess)$ error [F]
|
||||||
## End - Security
|
## End - Security
|
||||||
|
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|||||||
10
.travis.yml
@@ -40,8 +40,10 @@ env:
|
|||||||
- TRAVIS_TAG=$(curl --fail --user ${GH_API_USER} -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
|
- TRAVIS_TAG=$(curl --fail --user ${GH_API_USER} -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- export TZ=Pacific/Honolulu
|
||||||
- composer self-update
|
- composer self-update
|
||||||
- go get github.com/aktau/github-release
|
- go get github.com/aktau/github-release
|
||||||
|
- echo "Travis Date - `date`"
|
||||||
- git clone --quiet --depth=50 --branch=master https://${BB_TOKEN}bitbucket.org/rockettheme/grav-devtools.git $RT_DEVTOOLS &>/dev/null;
|
- git clone --quiet --depth=50 --branch=master https://${BB_TOKEN}bitbucket.org/rockettheme/grav-devtools.git $RT_DEVTOOLS &>/dev/null;
|
||||||
- if [ ! -z "$TRAVIS_TAG" ]; then
|
- if [ ! -z "$TRAVIS_TAG" ]; then
|
||||||
cd "${RT_DEVTOOLS}";
|
cd "${RT_DEVTOOLS}";
|
||||||
@@ -52,7 +54,11 @@ script:
|
|||||||
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
|
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
|
||||||
for file in ${FILES[@]}; do
|
for file in ${FILES[@]}; do
|
||||||
NAME=${file##*/};
|
NAME=${file##*/};
|
||||||
REPO="$(echo ${NAME} | rev | cut -f 2- -d "-" | rev)";
|
if [[ "$NAME" == *"-rc"* ]]; then
|
||||||
|
REPO="$(echo ${NAME} | rev | cut -f 3- -d "-" | rev)";
|
||||||
|
else
|
||||||
|
REPO="$(echo ${NAME} | rev | cut -f 2- -d "-" | rev)";
|
||||||
|
fi;
|
||||||
if [[ $REPO == 'grav' || $REPO == 'grav-admin' || $REPO == 'grav-update' ]]; then
|
if [[ $REPO == 'grav' || $REPO == 'grav-admin' || $REPO == 'grav-update' ]]; then
|
||||||
REPO="grav";
|
REPO="grav";
|
||||||
fi;
|
fi;
|
||||||
@@ -60,7 +66,7 @@ script:
|
|||||||
ASSETS="$(echo "${API}" | node gh-assets.js)";
|
ASSETS="$(echo "${API}" | node gh-assets.js)";
|
||||||
TAG="$(echo "${API}" | grep tag_name | head -n 1 | cut -d '"' -f 4)";
|
TAG="$(echo "${API}" | grep tag_name | head -n 1 | cut -d '"' -f 4)";
|
||||||
if [ $REPO == "grav" ]; then
|
if [ $REPO == "grav" ]; then
|
||||||
TAG=$TRAVIS_TAG;
|
TAG="$TRAVIS_TAG";
|
||||||
fi;
|
fi;
|
||||||
if [ ! -z "$ASSETS" ]; then
|
if [ ! -z "$ASSETS" ]; then
|
||||||
for asset in ${ASSETS[@]}; do
|
for asset in ${ASSETS[@]}; do
|
||||||
|
|||||||
246
CHANGELOG.md
@@ -1,3 +1,245 @@
|
|||||||
|
# v1.0.8
|
||||||
|
## 01/08/2016
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added `rotate`, `flip` and `fixOrientation` image medium methods
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Removed IP from Nonce generation. Should be more reliably in a variety of scenarios
|
||||||
|
|
||||||
|
# v1.0.7
|
||||||
|
## 01/07/2016
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added `composer create-project` as an additional installation method #585
|
||||||
|
* New optional system config setting to strip home from page routs and urls #561
|
||||||
|
* Added Greek, Finnish, Norwegian, Polish, Portuguese, and Romanian languages
|
||||||
|
* Added new `Page->topParent()` method to return top most parent of a page
|
||||||
|
* Added plugins configuration tab to debugger
|
||||||
|
* Added support for APCu and PHP7.0 via new Doctrine Cache release
|
||||||
|
* Added global setting for `twig_first` processing (false by default)
|
||||||
|
* New configuration options for Session settings #553
|
||||||
|
1. [](#improved)
|
||||||
|
* Switched to SSL for GPM calls
|
||||||
|
* Use `URI->host()` for session domain
|
||||||
|
* Add support for `open_basedir` when installing packages via GPM
|
||||||
|
* Improved `Utils::generateNonceString()` method to handle reverse proxies
|
||||||
|
* Optimized core thumbnails saving 38% in file size
|
||||||
|
* Added new `bin/gpm index --installed-only` option
|
||||||
|
* Improved GPM errors to provider more helpful diagnostic of issues
|
||||||
|
* Removed old hardcoded PHP version references
|
||||||
|
* Moved `onPageContentProcessed()` event so it's fired more reliably
|
||||||
|
* Maintain md5 keys during sorting of Assets #566
|
||||||
|
* Update to Caddyfile for Caddy web server
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fixed an issue with cache/config checksum not being set on cache load
|
||||||
|
* Fix for page blueprint and theme inheritance issue #534
|
||||||
|
* Set `ZipBackup` timeout to 10 minutes if possible
|
||||||
|
* Fix case where we only have inline data for CSS or JS #565
|
||||||
|
* Fix `bin/grav sandbox` command to work with new `webserver-config` folder
|
||||||
|
* Fix for markdown attributes on external URLs
|
||||||
|
* Fixed issue where `data:` page header was acting as `publish_date:`
|
||||||
|
* Fix for special characters in URL parameters (e.g. /tag:c++) #541
|
||||||
|
* Safety check for an array of nonces to only use the first one
|
||||||
|
|
||||||
|
# v1.0.6
|
||||||
|
## 12/22/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Set minimum requirements to [PHP 5.5.9](http://bit.ly/1Jt9OXO)
|
||||||
|
* Added `saveConfig` to Themes
|
||||||
|
1. [](#improved)
|
||||||
|
* Updated Whoops to new 2.0 version (PHP 7.0 compatible)
|
||||||
|
* Moved sample web server configs into dedicated directory
|
||||||
|
* FastCGI will use Apache's `mod_deflate` if gzip turned off
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix broken media image operators
|
||||||
|
* Only call extra method of blueprints if blueprints exist
|
||||||
|
* Fix lang prefix in url twig variables #523
|
||||||
|
* Fix case insensitive HTTPS check #535
|
||||||
|
* Field field validation handles case `multiple` missing
|
||||||
|
|
||||||
|
# v1.0.5
|
||||||
|
## 12/18/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Add ability to extend markdown with plugins
|
||||||
|
* Added support for plugins to have individual language files
|
||||||
|
* Added `7z` to media formats
|
||||||
|
* Use Grav's fork of Parsedown until PR is merged
|
||||||
|
* New function to persist plugin configuration to disk
|
||||||
|
* GPM `selfupgrade` will now check PHP version requirements
|
||||||
|
1. [](#improved)
|
||||||
|
* If the field allows multiple files, return array
|
||||||
|
* Handle non-array values in file validation
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix when looping `fields` param in a `list` field
|
||||||
|
* Properly convert commas to spaces for media attributes
|
||||||
|
* Forcing Travis VM to HI timezone to address future files in zip file
|
||||||
|
|
||||||
|
# v1.0.4
|
||||||
|
## 12/12/2015
|
||||||
|
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Needed to put default image folder permissions for YAML compatibility
|
||||||
|
|
||||||
|
# v1.0.3
|
||||||
|
## 12/11/2015
|
||||||
|
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fixed issue when saving config causing incorrect image cache folder perms
|
||||||
|
|
||||||
|
# v1.0.2
|
||||||
|
## 12/11/2015
|
||||||
|
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix for timing display in debugbar
|
||||||
|
|
||||||
|
# v1.0.1
|
||||||
|
## 12/11/2015
|
||||||
|
|
||||||
|
1. [](#improved)
|
||||||
|
* Reduced package sizes by removing extra vendor dev bits
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix issue when you enable debugger from admin plugin
|
||||||
|
|
||||||
|
# v1.0.0
|
||||||
|
## 12/11/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Add new link attributes via markdown media
|
||||||
|
* Added setters to set state of CSS/JS pipelining
|
||||||
|
* Added `user/accounts` to `.gitignore`
|
||||||
|
* Added configurable permissions option for Image cache
|
||||||
|
1. [](#improved)
|
||||||
|
* Hungarian translation updated
|
||||||
|
* Refactored Theme initialization for improved flexibility
|
||||||
|
* Wrapped security section of account blueprints in an 'super user' authorize check
|
||||||
|
* Minor performance optimizations
|
||||||
|
* Updated core page blueprints with markdown preview option
|
||||||
|
* Added useful cache info output to Debugbar
|
||||||
|
* Added `iconv` polyfill library used by Symfony 2.8
|
||||||
|
* Force lowercase of username in a few places for case sensitive filesystems
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix for GPM problems "Call to a member function set() on null"
|
||||||
|
* Fix for individual asset pipeline values not functioning
|
||||||
|
* Fix `Page::copy()` and `Page::move()` to support multiple moves at once
|
||||||
|
* Fixed page moving of a page with no content
|
||||||
|
* Fix for wrong ordering when moving many pages
|
||||||
|
* Escape root path in page medium files to work with special characters
|
||||||
|
* Add missing parent constructor to Themes class
|
||||||
|
* Fix missing file error in `bin/grav sandbox` command
|
||||||
|
* Fixed changelog differ when upgrading Grav
|
||||||
|
* Fixed a logic error in `Validation->validate()`
|
||||||
|
* Make `$container` available in `setup.php` to fix multi-site
|
||||||
|
|
||||||
|
# v1.0.0-rc.6
|
||||||
|
## 12/01/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Refactor Config classes for improved performance!
|
||||||
|
* Refactor Data classes to use `NestedArrayAccess` instead of `DataMutatorTrait`
|
||||||
|
* Added support for `classes` and `id` on medium objects to set CSS values
|
||||||
|
* Data objects: Allow function call chaining
|
||||||
|
* Data objects: Lazy load blueprints only if needed
|
||||||
|
* Automatically create unique security salt for each configuration
|
||||||
|
* Added Hungarian translation
|
||||||
|
* Added support for User groups
|
||||||
|
1. [](#improved)
|
||||||
|
* Improved robots.txt to disallow crawling of non-user folders
|
||||||
|
* Nonces only generated once per action and process
|
||||||
|
* Added IP into Nonce string calculation
|
||||||
|
* Nonces now use random string with random salt to improve performance
|
||||||
|
* Improved list form handling #475
|
||||||
|
* Vendor library updates
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fixed help output for `bin/plugin`
|
||||||
|
* Fix for nested logic for lists and form parsing #273
|
||||||
|
* Fix for array form fields and last entry not getting deleted
|
||||||
|
* Should not be able to set parent to self #308
|
||||||
|
|
||||||
|
# v1.0.0-rc.5
|
||||||
|
## 11/20/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added **nonce** functionality for all admin forms for improved security
|
||||||
|
* Implemented the ability for Plugins to provide their own CLI commands through `bin/plugin`
|
||||||
|
* Added Croatian translation
|
||||||
|
* Added missing `umask_fix` property to `system.yaml`
|
||||||
|
* Added current theme's config to global config. E.g. `config.theme.dropdown_enabled`
|
||||||
|
* Added `append_url_extension` option to system config & page headers
|
||||||
|
* Users have a new `state` property to allow disabling/banning
|
||||||
|
* Added new `Page.relativePagePath()` helper method
|
||||||
|
* Added new `|pad` Twig filter for strings (uses `str_pad()`)
|
||||||
|
* Added `lighttpd.conf` for Lightly web server
|
||||||
|
1. [](#improved)
|
||||||
|
* Clear previously applied operations when doing a reset on image media
|
||||||
|
* Password no longer required when editing user
|
||||||
|
* Improved support for trailing `/` URLs
|
||||||
|
* Improved `.nginx.conf` configuration file
|
||||||
|
* Improved `.htaccess` security
|
||||||
|
* Updated vendor libs
|
||||||
|
* Updated `composer.phar`
|
||||||
|
* Use streams instead of paths for `clearCache()`
|
||||||
|
* Use PCRE_UTF8 so unicode strings can be regexed in Truncator
|
||||||
|
* Handle case when login plugin is disabled
|
||||||
|
* Improved `quality` functionality in media handling
|
||||||
|
* Added some missing translation strings
|
||||||
|
* Deprecated `bin/grav newuser` in favor of `bin/plugin login new-user`
|
||||||
|
* Moved fallback types to use any valid media type
|
||||||
|
* Renamed `system.pages.fallback_types` to `system.media.allowed_fallback_types`
|
||||||
|
* Removed version number in default `generator` meta tag
|
||||||
|
* Disable time limit in case of slow downloads
|
||||||
|
* Removed default hash in `system.yaml`
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fix for media using absolute URLs causing broken links
|
||||||
|
* Fix theme auto-loading #432
|
||||||
|
* Don't create empty `<style>` or `<script>` scripts if no data
|
||||||
|
* Code cleanups
|
||||||
|
* Fix undefined variable in Config class
|
||||||
|
* Fix exception message when label is not set
|
||||||
|
* Check in `Plugins::get()` to ensure plugins exists
|
||||||
|
* Fixed GZip compression making output buffering work correctly with all servers and browsers
|
||||||
|
* Fixed date representation in system config
|
||||||
|
|
||||||
|
# v1.0.0-rc.4
|
||||||
|
## 10/29/2015
|
||||||
|
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Fixed a fatal error if you have a collection with missing or invalid `@page: /route`
|
||||||
|
|
||||||
|
# v1.0.0-rc.3
|
||||||
|
## 10/29/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* New Page collection options! `@self.parent, @self.siblings, @self.descendants` + more
|
||||||
|
* White list of file types for fallback route functionality (images by default)
|
||||||
|
1. [](#improved)
|
||||||
|
* Assets switched from defines to streams
|
||||||
|
1. [](#bugfix)
|
||||||
|
* README.md typos fixed
|
||||||
|
* Fixed issue with routes that have lang string in them (`/en/english`)
|
||||||
|
* Trim strings before validation so whitespace is not satisfy 'required'
|
||||||
|
|
||||||
|
# v1.0.0-rc.2
|
||||||
|
## 10/27/2015
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added support for CSS Asset groups
|
||||||
|
* Added a `wrapped_site` system option for themes/plugins to use
|
||||||
|
* Pass `Page` object as event to `onTwigPageVariables()` event hook
|
||||||
|
* New `Data.items()` method to get all items
|
||||||
|
1. [](#improved)
|
||||||
|
* Missing pipelined remote asset will now fail quietly
|
||||||
|
* More reliably handle inline JS and CSS to remove only surrounding HTML tags
|
||||||
|
* `Medium.meta` returns new Data object so null checks are possible
|
||||||
|
* Improved Medium metadata merging to allow for automatic title/alt/class attributes
|
||||||
|
* Moved Grav object to global variable rather than template variable (useful for macros)
|
||||||
|
* German language improvements
|
||||||
|
* Updated bundled composer
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Accept variety of `true` values in `User.authorize()` method
|
||||||
|
* Fix for `Validation` throwing an error if no label set
|
||||||
|
|
||||||
# v1.0.0-rc.1
|
# v1.0.0-rc.1
|
||||||
## 10/23/2015
|
## 10/23/2015
|
||||||
|
|
||||||
@@ -18,7 +260,7 @@
|
|||||||
1. [](#improved)
|
1. [](#improved)
|
||||||
* Moved hardcoded mimetypes to `media.yaml` to be treated as Page media files
|
* Moved hardcoded mimetypes to `media.yaml` to be treated as Page media files
|
||||||
* Set `errors: display: false` by default in `system.yaml`
|
* Set `errors: display: false` by default in `system.yaml`
|
||||||
* Strip out extra slashes in the URI
|
* Strip out extra slashes in the URI
|
||||||
* Validate hostname to ensure it is valid
|
* Validate hostname to ensure it is valid
|
||||||
* Ignore more SCM folders in Backups
|
* Ignore more SCM folders in Backups
|
||||||
* Removed `home_redirect` settings from `system.yaml`
|
* Removed `home_redirect` settings from `system.yaml`
|
||||||
@@ -29,7 +271,7 @@
|
|||||||
* Debugbar vendor library update
|
* Debugbar vendor library update
|
||||||
* Always fallback to english if other translations are not available
|
* Always fallback to english if other translations are not available
|
||||||
1. [](#bugfix)
|
1. [](#bugfix)
|
||||||
* Fix for redirecting external URL with multi-language
|
* Fix for redirecting external URL with multi-language
|
||||||
* Fix for Asset pipeline not respecting asset groups
|
* Fix for Asset pipeline not respecting asset groups
|
||||||
* Fix language files with child/parent theme relationships
|
* Fix language files with child/parent theme relationships
|
||||||
* Fixed a regression issue resulting in incorrect default language
|
* Fixed a regression issue resulting in incorrect default language
|
||||||
|
|||||||
122
CONTRIBUTING.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# Contributing to Grav
|
||||||
|
|
||||||
|
:+1::tada: First, thanks for getting involved with Grav! :tada::+1:
|
||||||
|
|
||||||
|
Please take a moment to review this document in order to make the contribution
|
||||||
|
process easy and effective for everyone involved.
|
||||||
|
|
||||||
|
Following these guidelines helps to communicate that you respect the time of
|
||||||
|
the developers managing and developing this open source project. In return,
|
||||||
|
they should reciprocate that respect in addressing your issue or assessing
|
||||||
|
patches and features.
|
||||||
|
|
||||||
|
## Grav, Plugins, Themes and Skeletons
|
||||||
|
|
||||||
|
Grav is a large open source project—it's made up of over 100 repositories. When you initially consider contributing to Grav, you might be unsure about which of those 200 repositories implements the functionality you want to change or report a bug for.
|
||||||
|
|
||||||
|
[https://github.com/getgrav/grav](https://github.com/getgrav/grav) is the main Grav repository. The core of Grav is provided by this repo.
|
||||||
|
|
||||||
|
[https://github.com/getgrav/grav-plugin-admin](https://github.com/getgrav/grav-plugin-admin) is the Admin Plugin repository.
|
||||||
|
|
||||||
|
Every Plugin and Theme has its own repository. If you have a problem you think is specific to a Theme or Plugin, please report it in its corresponding repository. Please read the Plugin or Theme documentation to ensure the problem is not addressed there already.
|
||||||
|
|
||||||
|
Every Skeleton also has its own repository, so if an issue is not specific to a theme or plugin but rather to its usage in the skeleton, report it in the skeleton repository.
|
||||||
|
|
||||||
|
## Using the issue tracker
|
||||||
|
|
||||||
|
The issue tracker is the preferred channel for [bug reports](#bugs),
|
||||||
|
[features requests](#features) and [submitting pull
|
||||||
|
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).
|
||||||
|
|
||||||
|
|
||||||
|
<a name="bugs"></a>
|
||||||
|
## Bug reports
|
||||||
|
|
||||||
|
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||||
|
Good bug reports are extremely helpful - thank you!
|
||||||
|
|
||||||
|
Guidelines for bug reports:
|
||||||
|
|
||||||
|
1. **Check you satisfy the Grav requirements** — [http://learn.getgrav.org/basics/requirements](http://learn.getgrav.org/basics/requirements)
|
||||||
|
|
||||||
|
2. **Check this happens on a clean Grav install** — check if the issue happens on any Grav site, or just with a specific configuration of plugins / theme
|
||||||
|
|
||||||
|
3. **Use the GitHub issue search** — check if the issue has already been
|
||||||
|
reported.
|
||||||
|
|
||||||
|
4. **Check if the issue is already being solved in a PR** — check the open Pull Requests to see if one already solves the problem you're having
|
||||||
|
|
||||||
|
5. **Check if the issue has been fixed** — try to reproduce it using the
|
||||||
|
latest `develop` branch in the repository.
|
||||||
|
|
||||||
|
6. **Isolate the problem** — create a [reduced test
|
||||||
|
case](http://css-tricks.com/reduced-test-cases/) and provide a step-by-step instruction set on how to recreate the problem. Include code samples, page snippets or yaml configurations if needed.
|
||||||
|
|
||||||
|
A good bug report shouldn't leave others needing to chase you up for more
|
||||||
|
information. Please try to be as detailed as possible in your report.
|
||||||
|
|
||||||
|
What is your environment? Is it localhost, OSX, Linux, on a remote server? Same happening locally and or the server, or just locally or just on Linux?
|
||||||
|
|
||||||
|
What steps will reproduce the issue? What browser(s) and OS experience the problem?
|
||||||
|
|
||||||
|
What would you expect to be the outcome?
|
||||||
|
|
||||||
|
Did the problem start happening recently (e.g. after updating to a new version of Grav) or was this always a problem?
|
||||||
|
|
||||||
|
If the problem started happening recently, can you reproduce the problem in an older version of Grav? What's the most recent version in which the problem doesn't happen? You can download older versions of Grav from the releases page on Github.
|
||||||
|
|
||||||
|
Can you reliably reproduce the issue? If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||||
|
|
||||||
|
|
||||||
|
All these details will help people to fix any potential bugs.
|
||||||
|
|
||||||
|
Important: [include Code Samples in triple backticks](https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks) so that Github will provide a proper indentation. [Add the language name after the backticks](https://help.github.com/articles/github-flavored-markdown/#syntax-highlighting) to add syntax highlighting to the code snippets.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
> Short and descriptive example bug report title
|
||||||
|
>
|
||||||
|
> A summary of the issue and the browser/OS environment in which it occurs. If
|
||||||
|
> suitable, include the steps required to reproduce the bug.
|
||||||
|
>
|
||||||
|
> 1. This is the first step
|
||||||
|
> 2. This is the second step
|
||||||
|
> 3. Further steps, etc.
|
||||||
|
>>
|
||||||
|
> Any other information you want to share that is relevant to the issue being
|
||||||
|
> reported. This might include the lines of code that you have identified as
|
||||||
|
> causing the bug, and potential solutions (and your opinions on their
|
||||||
|
> merits).
|
||||||
|
|
||||||
|
|
||||||
|
<a name="features"></a>
|
||||||
|
## Feature requests
|
||||||
|
|
||||||
|
Feature requests are welcome. But take a moment to find out whether your idea
|
||||||
|
fits with the scope and aims of the project. It's up to *you* to make a strong
|
||||||
|
case to convince the project's developers of the merits of this feature. Please
|
||||||
|
provide as much detail and context as possible.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="pull-requests"></a>
|
||||||
|
## Pull requests
|
||||||
|
|
||||||
|
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 Gitter or in the Forum 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.
|
||||||
|
|
||||||
|
Please adhere to the coding conventions used throughout the project (indentation,
|
||||||
|
accurate comments, etc.) and any other requirements.
|
||||||
|
|
||||||
|
See [Using Pull Request](https://help.github.com/articles/using-pull-requests/) and [Fork a Repo](https://help.github.com/articles/fork-a-repo/) if you're not familiar with Pull Requests.
|
||||||
|
|
||||||
|
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
|
||||||
|
license your work under the same license as that used by the project.
|
||||||
22
README.md
@@ -9,26 +9,34 @@ The underlying architecture of Grav is designed to use well-established and _bes
|
|||||||
* [Twig Templating](http://twig.sensiolabs.org/): for powerful control of the user interface
|
* [Twig Templating](http://twig.sensiolabs.org/): for powerful control of the user interface
|
||||||
* [Markdown](http://en.wikipedia.org/wiki/Markdown): for easy content creation
|
* [Markdown](http://en.wikipedia.org/wiki/Markdown): for easy content creation
|
||||||
* [YAML](http://yaml.org): for simple configuration
|
* [YAML](http://yaml.org): for simple configuration
|
||||||
* [Parsedown](http://parsedown.org/): for fast Markdown and Mardown Extra support
|
* [Parsedown](http://parsedown.org/): for fast Markdown and Markdown Extra support
|
||||||
* [Doctrine Cache](http://docs.doctrine-project.org/en/2.0.x/reference/caching.html): layer for performance
|
* [Doctrine Cache](http://docs.doctrine-project.org/en/2.0.x/reference/caching.html): layer for performance
|
||||||
* [Pimple Dependency Injection Container](http://pimple.sensiolabs.org/): for extensibility and maintainability
|
* [Pimple Dependency Injection Container](http://pimple.sensiolabs.org/): for extensibility and maintainability
|
||||||
* [Symfony Event Dispacher](http://symfony.com/doc/current/components/event_dispatcher/introduction.html): for plugin event handling
|
* [Symfony Event Dispatcher](http://symfony.com/doc/current/components/event_dispatcher/introduction.html): for plugin event handling
|
||||||
* [Symfony Console](http://symfony.com/doc/current/components/console/introduction.html): for CLI interface
|
* [Symfony Console](http://symfony.com/doc/current/components/console/introduction.html): for CLI interface
|
||||||
* [Gregwar Image Library](https://github.com/Gregwar/Image): for dynamic image manipulation
|
* [Gregwar Image Library](https://github.com/Gregwar/Image): for dynamic image manipulation
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
- PHP 5.4 or higher. Check the [required modules list](http://learn.getgrav.org/basics/requirements#php-requirements)
|
- PHP 5.5.9 or higher. Check the [required modules list](http://learn.getgrav.org/basics/requirements#php-requirements)
|
||||||
- Check the [Apache](http://learn.getgrav.org/basics/requirements#apache-requirements) or [IIS](http://learn.getgrav.org/basics/requirements#iis-requirements) requirements
|
- Check the [Apache](http://learn.getgrav.org/basics/requirements#apache-requirements) or [IIS](http://learn.getgrav.org/basics/requirements#iis-requirements) requirements
|
||||||
|
|
||||||
# QuickStart
|
# QuickStart
|
||||||
|
|
||||||
You have two options to get Grav:
|
These are the options to get Grav:
|
||||||
|
|
||||||
### Downloading a Grav Package
|
### Downloading a Grav Package
|
||||||
|
|
||||||
You can download a **ready-built** package from the [Downloads page on http://getgrav.org](http://getgrav.org/downloads)
|
You can download a **ready-built** package from the [Downloads page on http://getgrav.org](http://getgrav.org/downloads)
|
||||||
|
|
||||||
|
### With composer
|
||||||
|
|
||||||
|
You can create a new project with the latest **stable** Grav release with the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ composer create-project getgrav/grav ~/webroot/grav
|
||||||
|
```
|
||||||
|
|
||||||
### From GitHub
|
### From GitHub
|
||||||
|
|
||||||
1. Clone the Grav repository from [https://github.com/getgrav/grav]() to a folder in the webroot of your server, e.g. `~/webroot/grav`. Launch a **terminal** or **console** and navigate to the webroot folder:
|
1. Clone the Grav repository from [https://github.com/getgrav/grav]() to a folder in the webroot of your server, e.g. `~/webroot/grav`. Launch a **terminal** or **console** and navigate to the webroot folder:
|
||||||
@@ -53,7 +61,7 @@ You can download [plugins](http://getgrav.org/downloads/plugins) or [themes](htt
|
|||||||
$ bin/gpm index
|
$ bin/gpm index
|
||||||
```
|
```
|
||||||
|
|
||||||
This will display all the available plugins and then you can install one ore more with:
|
This will display all the available plugins and then you can install one or more with:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ bin/gpm install <plugin/theme>
|
$ bin/gpm install <plugin/theme>
|
||||||
@@ -76,7 +84,7 @@ $ bin/gpm update
|
|||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement.
|
We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement.
|
||||||
However, we ask that any contribution follow our simple guidelines in order to be properly received.
|
However, we ask that any contributions follow our simple guidelines in order to be properly received.
|
||||||
|
|
||||||
All our projects follow the [GitFlow branching model][gitflow-model], from development to release. If you are not familiar with it, there are several guides and tutorials to make you understand what it is about.
|
All our projects follow the [GitFlow branching model][gitflow-model], from development to release. If you are not familiar with it, there are several guides and tutorials to make you understand what it is about.
|
||||||
|
|
||||||
@@ -103,7 +111,7 @@ What you mainly want to know is that:
|
|||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
See [LICENSE](LICENSE)
|
See [LICENSE](LICENSE.txt)
|
||||||
|
|
||||||
|
|
||||||
[gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/
|
[gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/
|
||||||
|
|||||||
10
bin/gpm
@@ -2,10 +2,6 @@
|
|||||||
<?php
|
<?php
|
||||||
define('GRAV_CLI', true);
|
define('GRAV_CLI', true);
|
||||||
|
|
||||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
|
||||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . '/../vendor')){
|
if (!file_exists(__DIR__ . '/../vendor')){
|
||||||
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||||
}
|
}
|
||||||
@@ -25,6 +21,10 @@ use Grav\Common\Grav;
|
|||||||
|
|
||||||
$autoload = require_once(__DIR__ . '/../vendor/autoload.php');
|
$autoload = require_once(__DIR__ . '/../vendor/autoload.php');
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
if (!ini_get('date.timezone')) {
|
if (!ini_get('date.timezone')) {
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,6 @@ if (!function_exists('curl_version')) {
|
|||||||
$grav = Grav::instance(array('loader' => $autoload));
|
$grav = Grav::instance(array('loader' => $autoload));
|
||||||
$grav['config']->init();
|
$grav['config']->init();
|
||||||
$grav['streams'];
|
$grav['streams'];
|
||||||
$grav['plugins']->init();
|
|
||||||
$grav['themes']->init();
|
|
||||||
|
|
||||||
$app = new Application('Grav Package Manager', GRAV_VERSION);
|
$app = new Application('Grav Package Manager', GRAV_VERSION);
|
||||||
$app->addCommands(array(
|
$app->addCommands(array(
|
||||||
|
|||||||
8
bin/grav
@@ -2,10 +2,6 @@
|
|||||||
<?php
|
<?php
|
||||||
define('GRAV_CLI', true);
|
define('GRAV_CLI', true);
|
||||||
|
|
||||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
|
||||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . '/../vendor')){
|
if (!file_exists(__DIR__ . '/../vendor')){
|
||||||
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||||
}
|
}
|
||||||
@@ -24,6 +20,10 @@ use Symfony\Component\Console\Application;
|
|||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
if (!ini_get('date.timezone')) {
|
if (!ini_get('date.timezone')) {
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
}
|
}
|
||||||
|
|||||||
116
bin/plugin
Executable file
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
define('GRAV_CLI', true);
|
||||||
|
|
||||||
|
if (!file_exists(__DIR__ . '/../vendor')) {
|
||||||
|
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
use Grav\Common\Composer;
|
||||||
|
|
||||||
|
if (!file_exists(__DIR__ . '/../vendor')) {
|
||||||
|
// Before we can even start, we need to run composer first
|
||||||
|
$composer = Composer::getComposerExecutor();
|
||||||
|
echo "Preparing to install vendor dependencies...\n\n";
|
||||||
|
echo system($composer . ' --working-dir="' . __DIR__ . '/../" --no-interaction --no-dev --prefer-dist -o install');
|
||||||
|
echo "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Application;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||||
|
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||||
|
use Grav\Common\Grav;
|
||||||
|
use Grav\Common\Filesystem\Folder;
|
||||||
|
|
||||||
|
$autoload = require_once(__DIR__ . '/../vendor/autoload.php');
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ini_get('date.timezone')) {
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists(ROOT_DIR . 'index.php')) {
|
||||||
|
exit('FATAL: Must be run from ROOT directory of Grav!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$grav = Grav::instance(array('loader' => $autoload));
|
||||||
|
$grav['config']->init();
|
||||||
|
$grav['streams'];
|
||||||
|
$grav['plugins']->init();
|
||||||
|
$grav['themes']->init();
|
||||||
|
|
||||||
|
$app = new Application('Grav Plugins Commands', GRAV_VERSION);
|
||||||
|
$pattern = '([A-Z]\w+Command\.php)';
|
||||||
|
|
||||||
|
// get arguments and strip the application name
|
||||||
|
if (null === $argv) {
|
||||||
|
$argv = $_SERVER['argv'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$bin = array_shift($argv);
|
||||||
|
$name = array_shift($argv);
|
||||||
|
$argv = array_merge([$bin], $argv);
|
||||||
|
|
||||||
|
$input = new ArgvInput($argv);
|
||||||
|
|
||||||
|
$plugin = $grav['plugins']->get($name);
|
||||||
|
|
||||||
|
$output = new ConsoleOutput();
|
||||||
|
$output->getFormatter()->setStyle('red', new OutputFormatterStyle('red', null, array('bold')));
|
||||||
|
$output->getFormatter()->setStyle('white', new OutputFormatterStyle('white', null, array('bold')));
|
||||||
|
|
||||||
|
if (!$name) {
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln("<red>Usage:</red>");
|
||||||
|
$output->writeln(" {$bin} [slug] [command] [arguments]");
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln("<red>Example:</red>");
|
||||||
|
$output->writeln(" {$bin} error log -l 1 --trace");
|
||||||
|
$list = Folder::all('plugins://', ['compare' => 'Pathname', 'pattern' => '/\/cli\/' . $pattern . '$/usm']);
|
||||||
|
|
||||||
|
if (count($list)) {
|
||||||
|
$available = [];
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln('<red>Plugins with CLI available:</red>');
|
||||||
|
foreach ($list as $index => $entry) {
|
||||||
|
$split = explode('/', $entry);
|
||||||
|
$entry = array_shift($split);
|
||||||
|
$index = str_pad($index++ + 1, 2, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
|
if (in_array($entry, $available)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$available[] = $entry;
|
||||||
|
$output->writeln(' ' . $index . ". <red>" . str_pad($entry, 15) . "</red> <white>${bin} ${entry} list</white>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($plugin === null) {
|
||||||
|
$output->writeln("<red>Grav Plugin <white>'{$name}'</white> is not installed</red>");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = 'plugins://' . $name . '/cli';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$commands = Folder::all($path, ['compare' => 'Filename', 'pattern' => '/' . $pattern . '$/usm']);
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
$output->writeln("<red>No Console Commands for <white>'{$name}'</white> where found in <white>'{$path}'</white></red>");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
require_once "plugins://{$name}/cli/{$command}";
|
||||||
|
$command = 'Grav\Plugin\Console\\' . preg_replace('/.php$/', '', $command);
|
||||||
|
$app->add(new $command());
|
||||||
|
}
|
||||||
|
|
||||||
|
$app->run($input);
|
||||||
@@ -1,29 +1,36 @@
|
|||||||
{
|
{
|
||||||
"name": "getgrav/grav",
|
"name": "getgrav/grav",
|
||||||
"type": "library",
|
"type": "project",
|
||||||
"description": "Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS",
|
"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": "http://getgrav.org",
|
"homepage": "http://getgrav.org",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.4.0",
|
"php": ">=5.5.9",
|
||||||
"twig/twig": "~1.16",
|
"twig/twig": "~1.23",
|
||||||
"erusev/parsedown-extra": "~0.7",
|
"erusev/parsedown-extra": "~0.7",
|
||||||
"symfony/yaml": "~2.7",
|
"symfony/yaml": "~2.8",
|
||||||
"symfony/console": "~2.7",
|
"symfony/console": "~2.8",
|
||||||
"symfony/event-dispatcher": "~2.7",
|
"symfony/event-dispatcher": "~2.8",
|
||||||
"symfony/var-dumper": "~2.7",
|
"symfony/var-dumper": "~2.8",
|
||||||
"doctrine/cache": "~1.4",
|
"symfony/polyfill-iconv": "~1.0",
|
||||||
"filp/whoops": "1.2.*@dev",
|
"doctrine/cache": "~1.5",
|
||||||
|
"filp/whoops": "2.0.0-alpha2",
|
||||||
"monolog/monolog": "~1.0",
|
"monolog/monolog": "~1.0",
|
||||||
"gregwar/image": "~2.0",
|
"gregwar/image": "~2.0",
|
||||||
"ircmaxell/password-compat": "1.0.*",
|
"ircmaxell/password-compat": "1.0.*",
|
||||||
"mrclay/minify": "~2.2",
|
"mrclay/minify": "~2.2",
|
||||||
"donatj/phpuseragentparser": "~0.3",
|
"donatj/phpuseragentparser": "~0.3",
|
||||||
"pimple/pimple": "~3.0",
|
"pimple/pimple": "~3.0",
|
||||||
"rockettheme/toolbox": "1.1.*",
|
"rockettheme/toolbox": "~1.2",
|
||||||
"maximebf/debugbar": "~1.10"
|
"maximebf/debugbar": "~1.10"
|
||||||
},
|
},
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/getgrav/parsedown"
|
||||||
|
}
|
||||||
|
],
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Grav\\": "system/src/Grav"
|
"Grav\\": "system/src/Grav"
|
||||||
@@ -32,5 +39,13 @@
|
|||||||
},
|
},
|
||||||
"archive": {
|
"archive": {
|
||||||
"exclude": ["VERSION"]
|
"exclude": ["VERSION"]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-create-project-cmd": "bin/grav install"
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-develop": "1.x-dev"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
343
composer.lock
generated
@@ -1,45 +1,46 @@
|
|||||||
{
|
{
|
||||||
"_readme": [
|
"_readme": [
|
||||||
"This file locks the dependencies of your project to a known state",
|
"This file locks the dependencies of your project to a known state",
|
||||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "e1db721096772d41f16003b39b47c85a",
|
"hash": "85173a1bfa9ece106f687d69402d99d8",
|
||||||
|
"content-hash": "410b016e6cd8af6cd8ee9cdb6d5fd7a4",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/cache",
|
"name": "doctrine/cache",
|
||||||
"version": "v1.4.2",
|
"version": "v1.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/cache.git",
|
"url": "https://github.com/doctrine/cache.git",
|
||||||
"reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca"
|
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/8c434000f420ade76a07c64cbe08ca47e5c101ca",
|
"url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||||
"reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca",
|
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.2"
|
"php": "~5.5|~7.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"doctrine/common": ">2.2,<2.4"
|
"doctrine/common": ">2.2,<2.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": ">=3.7",
|
"phpunit/phpunit": "~4.8|~5.0",
|
||||||
"predis/predis": "~1.0",
|
"predis/predis": "~1.0",
|
||||||
"satooshi/php-coveralls": "~0.6"
|
"satooshi/php-coveralls": "~0.6"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.5.x-dev"
|
"dev-master": "1.6.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Cache\\": "lib/"
|
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
"cache",
|
"cache",
|
||||||
"caching"
|
"caching"
|
||||||
],
|
],
|
||||||
"time": "2015-08-31 12:36:41"
|
"time": "2015-12-31 16:37:02"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "donatj/phpuseragentparser",
|
"name": "donatj/phpuseragentparser",
|
||||||
@@ -132,12 +133,12 @@
|
|||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/erusev/parsedown.git",
|
"url": "https://github.com/getgrav/parsedown.git",
|
||||||
"reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7"
|
"reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
|
"url": "https://api.github.com/repos/getgrav/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
|
||||||
"reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
|
"reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
@@ -147,7 +148,6 @@
|
|||||||
"Parsedown": ""
|
"Parsedown": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
"license": [
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
@@ -164,20 +164,23 @@
|
|||||||
"markdown",
|
"markdown",
|
||||||
"parser"
|
"parser"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/getgrav/parsedown/tree/1.6.0"
|
||||||
|
},
|
||||||
"time": "2015-10-04 16:44:32"
|
"time": "2015-10-04 16:44:32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "erusev/parsedown-extra",
|
"name": "erusev/parsedown-extra",
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/erusev/parsedown-extra.git",
|
"url": "https://github.com/erusev/parsedown-extra.git",
|
||||||
"reference": "11a44e076d02ffcc4021713398a60cd73f78b6f5"
|
"reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/11a44e076d02ffcc4021713398a60cd73f78b6f5",
|
"url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/0db5cce7354e4b76f155d092ab5eb3981c21258c",
|
||||||
"reference": "11a44e076d02ffcc4021713398a60cd73f78b6f5",
|
"reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -208,40 +211,45 @@
|
|||||||
"parsedown",
|
"parsedown",
|
||||||
"parser"
|
"parser"
|
||||||
],
|
],
|
||||||
"time": "2015-01-25 14:52:34"
|
"time": "2015-11-01 10:19:22"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "filp/whoops",
|
"name": "filp/whoops",
|
||||||
"version": "dev-master",
|
"version": "2.0.0-alpha2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/filp/whoops.git",
|
"url": "https://github.com/filp/whoops.git",
|
||||||
"reference": "9a393ceb80f7497b6513feb574638e87048fed55"
|
"reference": "eb1ce6439db161a9f00cd57f33a9cfa1355229ec"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/filp/whoops/zipball/9a393ceb80f7497b6513feb574638e87048fed55",
|
"url": "https://api.github.com/repos/filp/whoops/zipball/eb1ce6439db161a9f00cd57f33a9cfa1355229ec",
|
||||||
"reference": "9a393ceb80f7497b6513feb574638e87048fed55",
|
"reference": "eb1ce6439db161a9f00cd57f33a9cfa1355229ec",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0"
|
"php": ">=5.5.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"mockery/mockery": "0.9.*"
|
"mockery/mockery": "0.9.*",
|
||||||
|
"phpunit/phpunit": "^4.8 || ^5.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
|
||||||
|
"whoops/soap": "Formats errors as SOAP responses"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.2-dev"
|
"dev-master": "2.0-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"Whoops": "src/"
|
"Whoops\\": "src/Whoops/"
|
||||||
},
|
},
|
||||||
"classmap": [
|
"files": [
|
||||||
"src/deprecated"
|
"src/Whoops/functions.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@@ -262,11 +270,10 @@
|
|||||||
"exception",
|
"exception",
|
||||||
"handling",
|
"handling",
|
||||||
"library",
|
"library",
|
||||||
"silex-provider",
|
|
||||||
"whoops",
|
"whoops",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
"time": "2015-09-27 09:47:06"
|
"time": "2015-12-15 12:27:17"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gregwar/cache",
|
"name": "gregwar/cache",
|
||||||
@@ -403,25 +410,25 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "maximebf/debugbar",
|
"name": "maximebf/debugbar",
|
||||||
"version": "v1.10.5",
|
"version": "v1.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/maximebf/php-debugbar.git",
|
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||||
"reference": "30e53e8a28284b69dd223c9f5ee8957befd72636"
|
"reference": "07741d84d39d10f00551c94284cdefcc69703e77"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/30e53e8a28284b69dd223c9f5ee8957befd72636",
|
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/07741d84d39d10f00551c94284cdefcc69703e77",
|
||||||
"reference": "30e53e8a28284b69dd223c9f5ee8957befd72636",
|
"reference": "07741d84d39d10f00551c94284cdefcc69703e77",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0",
|
"php": ">=5.3.0",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "^1.0",
|
||||||
"symfony/var-dumper": "~2.6"
|
"symfony/var-dumper": "^2.6|^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "~4.0"
|
"phpunit/phpunit": "^4.0|^5.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"kriswallsmith/assetic": "The best way to manage assets",
|
"kriswallsmith/assetic": "The best way to manage assets",
|
||||||
@@ -431,12 +438,12 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.10-dev"
|
"dev-master": "1.11-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"DebugBar": "src/"
|
"DebugBar\\": "src/DebugBar/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@@ -448,14 +455,19 @@
|
|||||||
"name": "Maxime Bouroumeau-Fuseau",
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
"email": "maxime.bouroumeau@gmail.com",
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
"homepage": "http://maximebf.com"
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Debug bar in the browser for php application",
|
"description": "Debug bar in the browser for php application",
|
||||||
"homepage": "https://github.com/maximebf/php-debugbar",
|
"homepage": "https://github.com/maximebf/php-debugbar",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"debug"
|
"debug",
|
||||||
|
"debugbar"
|
||||||
],
|
],
|
||||||
"time": "2015-10-19 20:35:12"
|
"time": "2015-12-10 09:50:24"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
@@ -665,16 +677,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rockettheme/toolbox",
|
"name": "rockettheme/toolbox",
|
||||||
"version": "1.1.4",
|
"version": "1.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rockettheme/toolbox.git",
|
"url": "https://github.com/rockettheme/toolbox.git",
|
||||||
"reference": "ff677d8f66d1addd3590d0cb85bcbaff4174d9c9"
|
"reference": "0c7a3b4b6e4d73be8512e89f7acde6899334b7f2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rockettheme/toolbox/zipball/ff677d8f66d1addd3590d0cb85bcbaff4174d9c9",
|
"url": "https://api.github.com/repos/rockettheme/toolbox/zipball/0c7a3b4b6e4d73be8512e89f7acde6899334b7f2",
|
||||||
"reference": "ff677d8f66d1addd3590d0cb85bcbaff4174d9c9",
|
"reference": "0c7a3b4b6e4d73be8512e89f7acde6899334b7f2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -710,30 +722,30 @@
|
|||||||
"php",
|
"php",
|
||||||
"rockettheme"
|
"rockettheme"
|
||||||
],
|
],
|
||||||
"time": "2015-10-15 23:27:40"
|
"time": "2015-11-24 17:04:24"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v2.7.5",
|
"version": "v2.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "06cb17c013a82f94a3d840682b49425cd00a2161"
|
"reference": "2e06a5ccb19dcf9b89f1c6a677a39a8df773635a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/06cb17c013a82f94a3d840682b49425cd00a2161",
|
"url": "https://api.github.com/repos/symfony/console/zipball/2e06a5ccb19dcf9b89f1c6a677a39a8df773635a",
|
||||||
"reference": "06cb17c013a82f94a3d840682b49425cd00a2161",
|
"reference": "2e06a5ccb19dcf9b89f1c6a677a39a8df773635a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/event-dispatcher": "~2.1",
|
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||||
"symfony/phpunit-bridge": "~2.7",
|
"symfony/process": "~2.1|~3.0.0"
|
||||||
"symfony/process": "~2.1"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"psr/log": "For using the console logger",
|
"psr/log": "For using the console logger",
|
||||||
@@ -743,13 +755,16 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.7-dev"
|
"dev-master": "2.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Component\\Console\\": ""
|
"Symfony\\Component\\Console\\": ""
|
||||||
}
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -767,20 +782,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2015-09-25 08:32:23"
|
"time": "2015-12-22 10:25:57"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v2.7.5",
|
"version": "v2.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
"reference": "ae4dcc2a8d3de98bd794167a3ccda1311597c5d9"
|
"reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae4dcc2a8d3de98bd794167a3ccda1311597c5d9",
|
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a5eb815363c0388e83247e7e9853e5dbc14999cc",
|
||||||
"reference": "ae4dcc2a8d3de98bd794167a3ccda1311597c5d9",
|
"reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -788,11 +803,10 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/config": "~2.0,>=2.0.5",
|
"symfony/config": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/dependency-injection": "~2.6",
|
"symfony/dependency-injection": "~2.6|~3.0.0",
|
||||||
"symfony/expression-language": "~2.6",
|
"symfony/expression-language": "~2.6|~3.0.0",
|
||||||
"symfony/phpunit-bridge": "~2.7",
|
"symfony/stopwatch": "~2.3|~3.0.0"
|
||||||
"symfony/stopwatch": "~2.3"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/dependency-injection": "",
|
"symfony/dependency-injection": "",
|
||||||
@@ -801,13 +815,16 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.7-dev"
|
"dev-master": "2.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Component\\EventDispatcher\\": ""
|
"Symfony\\Component\\EventDispatcher\\": ""
|
||||||
}
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -825,27 +842,146 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2015-09-22 13:49:29"
|
"time": "2015-10-30 20:15:42"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/polyfill-iconv",
|
||||||
"version": "v2.7.5",
|
"version": "v1.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/polyfill-iconv.git",
|
||||||
"reference": "ba8c9a0edf18f70a7efcb8d3eb35323a10263338"
|
"reference": "541cce29a46d6ee18bb9271c6ac3ca783b0faab0"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/ba8c9a0edf18f70a7efcb8d3eb35323a10263338",
|
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/541cce29a46d6ee18bb9271c6ac3ca783b0faab0",
|
||||||
"reference": "ba8c9a0edf18f70a7efcb8d3eb35323a10263338",
|
"reference": "541cce29a46d6ee18bb9271c6ac3ca783b0faab0",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.3"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-iconv": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Iconv\\": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for the Iconv extension",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"iconv",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"time": "2015-11-20 09:19:13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
"version": "v1.0.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
|
"reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/49ff736bd5d41f45240cec77b44967d76e0c3d25",
|
||||||
|
"reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.3"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for the Mbstring extension",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"mbstring",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"time": "2015-11-20 09:19:13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/var-dumper",
|
||||||
|
"version": "v2.8.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
|
"reference": "f943f29ae69c42511a2d85adee9d13d835b5c803"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/f943f29ae69c42511a2d85adee9d13d835b5c803",
|
||||||
|
"reference": "f943f29ae69c42511a2d85adee9d13d835b5c803",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "~2.7"
|
"twig/twig": "~1.20|~2.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-symfony_debug": ""
|
"ext-symfony_debug": ""
|
||||||
@@ -853,7 +989,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.7-dev"
|
"dev-master": "2.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -862,7 +998,10 @@
|
|||||||
],
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Component\\VarDumper\\": ""
|
"Symfony\\Component\\VarDumper\\": ""
|
||||||
}
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -884,38 +1023,38 @@
|
|||||||
"debug",
|
"debug",
|
||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"time": "2015-09-22 14:41:01"
|
"time": "2015-12-05 11:09:21"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v2.7.5",
|
"version": "v2.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "31cb2ad0155c95b88ee55fe12bc7ff92232c1770"
|
"reference": "ac84cbb98b68a6abbc9f5149eb96ccc7b07b8966"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/31cb2ad0155c95b88ee55fe12bc7ff92232c1770",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/ac84cbb98b68a6abbc9f5149eb96ccc7b07b8966",
|
||||||
"reference": "31cb2ad0155c95b88ee55fe12bc7ff92232c1770",
|
"reference": "ac84cbb98b68a6abbc9f5149eb96ccc7b07b8966",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
|
||||||
"symfony/phpunit-bridge": "~2.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.7-dev"
|
"dev-master": "2.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Component\\Yaml\\": ""
|
"Symfony\\Component\\Yaml\\": ""
|
||||||
}
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -933,20 +1072,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2015-09-14 14:14:09"
|
"time": "2015-12-26 13:37:56"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v1.22.3",
|
"version": "v1.23.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "ebfc36b7e77b0c1175afe30459cf943010245540"
|
"reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/ebfc36b7e77b0c1175afe30459cf943010245540",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d9b6333ae8dd2c8e3fd256e127548def0bc614c6",
|
||||||
"reference": "ebfc36b7e77b0c1175afe30459cf943010245540",
|
"reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -959,7 +1098,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.22-dev"
|
"dev-master": "1.23-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -994,19 +1133,19 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"templating"
|
"templating"
|
||||||
],
|
],
|
||||||
"time": "2015-10-13 07:07:02"
|
"time": "2015-11-05 12:49:06"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"filp/whoops": 20
|
"filp/whoops": 15
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=5.4.0"
|
"php": ">=5.5.9"
|
||||||
},
|
},
|
||||||
"platform-dev": []
|
"platform-dev": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav;
|
namespace Grav;
|
||||||
|
|
||||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
|
||||||
throw new \RuntimeException(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure vendor libraries exist
|
// Ensure vendor libraries exist
|
||||||
$autoload = __DIR__ . '/vendor/autoload.php';
|
$autoload = __DIR__ . '/vendor/autoload.php';
|
||||||
@@ -16,6 +13,10 @@ use Grav\Common\Grav;
|
|||||||
// Register the auto-loader.
|
// Register the auto-loader.
|
||||||
$loader = require_once $autoload;
|
$loader = require_once $autoload;
|
||||||
|
|
||||||
|
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||||
|
throw new \RuntimeException(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
|
||||||
|
}
|
||||||
|
|
||||||
// Set timezone to default, falls back to system if php.ini not set
|
// Set timezone to default, falls back to system if php.ini not set
|
||||||
date_default_timezone_set(@date_default_timezone_get());
|
date_default_timezone_set(@date_default_timezone_get());
|
||||||
|
|
||||||
|
|||||||
87
nginx.conf
@@ -1,87 +0,0 @@
|
|||||||
worker_processes 1;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
sendfile on;
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root html;
|
|
||||||
index index.php;
|
|
||||||
if (!-e $request_filename){ rewrite ^(.*)$ /index.php last; }
|
|
||||||
}
|
|
||||||
|
|
||||||
# if you want grav in a sub-directory of your main site
|
|
||||||
# (for example, example.com/mygrav) then you need this rewrite:
|
|
||||||
location /mygrav {
|
|
||||||
index index.php;
|
|
||||||
if (!-e $request_filename){ rewrite ^(.*)$ /mygrav/$2 last; }
|
|
||||||
try_files $uri $uri/ /index.php?$args;
|
|
||||||
}
|
|
||||||
|
|
||||||
# if using grav in a sub-directory of your site,
|
|
||||||
# prepend the actual path to each location
|
|
||||||
# for example: /mygrav/images
|
|
||||||
# and: /mygrav/user
|
|
||||||
# and: /mygrav/cache
|
|
||||||
# and so on
|
|
||||||
|
|
||||||
location /images/ {
|
|
||||||
# Serve images as static
|
|
||||||
}
|
|
||||||
|
|
||||||
location /user {
|
|
||||||
rewrite ^/user/accounts/(.*)$ /error redirect;
|
|
||||||
rewrite ^/user/config/(.*)$ /error redirect;
|
|
||||||
rewrite ^/user/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /cache {
|
|
||||||
rewrite ^/cache/(.*) /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /bin {
|
|
||||||
rewrite ^/bin/(.*)$ /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /backup {
|
|
||||||
rewrite ^/backup/(.*) /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /system {
|
|
||||||
rewrite ^/system/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /vendor {
|
|
||||||
rewrite ^/vendor/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remember to change 127.0.0.1:9000 to the Ip/port
|
|
||||||
# you configured php-cgi.exe to run from
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
try_files $uri =404;
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
||||||
fastcgi_pass 127.0.0.1:9000;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
include fastcgi_params;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
11
robots.txt
@@ -1,2 +1,11 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow:
|
Disallow: /backup/
|
||||||
|
Disallow: /bin/
|
||||||
|
Disallow: /cache/
|
||||||
|
Disallow: /grav/
|
||||||
|
Disallow: /logs/
|
||||||
|
Disallow: /system/
|
||||||
|
Disallow: /vendor/
|
||||||
|
Disallow: /user/
|
||||||
|
Allow: /user/pages/
|
||||||
|
Allow: /user/themes/
|
||||||
|
|||||||
@@ -1,110 +1,19 @@
|
|||||||
body {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
body header {
|
body header {
|
||||||
background: #349886;
|
background: #8552A2;
|
||||||
border-left: 8px solid #29796B;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body .clipboard {
|
body .left-panel {
|
||||||
width: 28px;
|
background: inherit;
|
||||||
height: 28px;
|
|
||||||
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcAQMAAABIw03XAAAAA3NCSVQICAjb4U/gAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAFnRFWHRDcmVhdGlvbiBUaW1lADEwLzE1LzE0xr/LJAAAADhJREFUCJlj+P///wcGBPGDQR5E8OMi2IEEczOIaAQRHSCioQBGHAAR/7AT/z+DiA8MMALVXhABAJf9Sr5aY+UFAAAAAElFTkSuQmCC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body .exc-title-primary {
|
body .exc-title-primary {
|
||||||
color: #1C3631;
|
color: #fff;
|
||||||
text-shadow: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body .exc-title {
|
body .exc-title {
|
||||||
color: #2F5B52;
|
color: #ddd;
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .data-table-container label {
|
|
||||||
color: #0082BA;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frames-container {
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .active .frame-class {
|
|
||||||
color: #E3D8E9;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-class {
|
|
||||||
color: #9055AF;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame.active {
|
|
||||||
border: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
background-color: #9055AF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body .frame:not(.active):hover {
|
body .frame:not(.active):hover {
|
||||||
background: #e9e9e9;
|
background: #e6e6e6;
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-file, body .data-table tbody {
|
|
||||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-code {
|
|
||||||
background: #305669;
|
|
||||||
border-left: 8px solid #253A47;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-code .frame-file {
|
|
||||||
background: #253A47;
|
|
||||||
color: #eee;
|
|
||||||
text-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-code .frame-file strong {
|
|
||||||
color: #fff;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-comments {
|
|
||||||
background: #283E4D;
|
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .frame-comments.empty:before {
|
|
||||||
color: #789AAB;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .details-container {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .details {
|
|
||||||
background-color: #eee;
|
|
||||||
border-left: 8px solid #ddd;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .code-block {
|
|
||||||
background: #2C4454;
|
|
||||||
box-shadow: none;
|
|
||||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .handler.active {
|
|
||||||
background: #666;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,18 @@ form:
|
|||||||
show_root: false
|
show_root: false
|
||||||
help: PLUGIN_ADMIN.HOME_PAGE_HELP
|
help: PLUGIN_ADMIN.HOME_PAGE_HELP
|
||||||
|
|
||||||
|
home.hide_in_urls:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.HIDE_HOME_IN_URLS
|
||||||
|
help: PLUGIN_ADMIN.HIDE_HOME_IN_URLS_HELP
|
||||||
|
highlight: 0
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
|
|
||||||
pages.theme:
|
pages.theme:
|
||||||
type: themeselect
|
type: themeselect
|
||||||
classes: fancy
|
classes: fancy
|
||||||
@@ -73,7 +85,7 @@ form:
|
|||||||
options:
|
options:
|
||||||
"F jS \\a\\t g:ia": Date1
|
"F jS \\a\\t g:ia": Date1
|
||||||
"l jS \\of F g:i A": Date2
|
"l jS \\of F g:i A": Date2
|
||||||
"D, m M Y G:i:s": Date3
|
"D, d M Y G:i:s": Date3
|
||||||
"d-m-y G:i": Date4
|
"d-m-y G:i": Date4
|
||||||
"jS M Y": Date5
|
"jS M Y": Date5
|
||||||
|
|
||||||
@@ -86,7 +98,7 @@ form:
|
|||||||
options:
|
options:
|
||||||
"F jS \\a\\t g:ia": Date1
|
"F jS \\a\\t g:ia": Date1
|
||||||
"l jS \\of F g:i A": Date2
|
"l jS \\of F g:i A": Date2
|
||||||
"D, m M Y G:i:s": Date3
|
"D, d M Y G:i:s": Date3
|
||||||
"d-m-y G:i": Date4
|
"d-m-y G:i": Date4
|
||||||
"jS M Y": Date5
|
"jS M Y": Date5
|
||||||
|
|
||||||
@@ -142,6 +154,12 @@ form:
|
|||||||
twig: Twig Events
|
twig: Twig Events
|
||||||
use: keys
|
use: keys
|
||||||
|
|
||||||
|
pages.append_url_extension:
|
||||||
|
type: text
|
||||||
|
placeholder: "e.g. .html"
|
||||||
|
label: PLUGIN_ADMIN.APPEND_URL_EXT
|
||||||
|
help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP
|
||||||
|
|
||||||
pages.redirect_default_route:
|
pages.redirect_default_route:
|
||||||
type: toggle
|
type: toggle
|
||||||
label: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE
|
label: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE
|
||||||
@@ -215,6 +233,19 @@ form:
|
|||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
|
|
||||||
|
pages.twig_first:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.TWIG_FIRST
|
||||||
|
highlight: asc
|
||||||
|
default: desc
|
||||||
|
help: PLUGIN_ADMIN.TWIG_FIRST_HELP
|
||||||
|
highlight: 0
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
languages:
|
languages:
|
||||||
type: section
|
type: section
|
||||||
title: PLUGIN_ADMIN.LANGUAGES
|
title: PLUGIN_ADMIN.LANGUAGES
|
||||||
@@ -225,6 +256,7 @@ form:
|
|||||||
languages.supported:
|
languages.supported:
|
||||||
type: selectize
|
type: selectize
|
||||||
size: large
|
size: large
|
||||||
|
placeholder: "e.g. en, fr"
|
||||||
label: PLUGIN_ADMIN.SUPPORTED
|
label: PLUGIN_ADMIN.SUPPORTED
|
||||||
help: PLUGIN_ADMIN.SUPPORTED_HELP
|
help: PLUGIN_ADMIN.SUPPORTED_HELP
|
||||||
classes: fancy
|
classes: fancy
|
||||||
@@ -509,6 +541,17 @@ form:
|
|||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
|
|
||||||
|
twig.umask_fix:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.TWIG_UMASK_FIX
|
||||||
|
help: PLUGIN_ADMIN.TWIG_UMASK_FIX_HELP
|
||||||
|
highlight: 0
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
assets:
|
assets:
|
||||||
type: section
|
type: section
|
||||||
title: PLUGIN_ADMIN.ASSETS
|
title: PLUGIN_ADMIN.ASSETS
|
||||||
@@ -681,6 +724,17 @@ form:
|
|||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
|
|
||||||
|
images.cache_perms:
|
||||||
|
type: select
|
||||||
|
size: small
|
||||||
|
label: PLUGIN_ADMIN.CACHE_PERMS
|
||||||
|
help: PLUGIN_ADMIN.CACHE_PERMS_HELP
|
||||||
|
highlight: '0755'
|
||||||
|
options:
|
||||||
|
'0755': '0755'
|
||||||
|
'0775': '0775'
|
||||||
|
|
||||||
|
|
||||||
images.debug:
|
images.debug:
|
||||||
type: toggle
|
type: toggle
|
||||||
label: PLUGIN_ADMIN.IMAGES_DEBUG
|
label: PLUGIN_ADMIN.IMAGES_DEBUG
|
||||||
@@ -711,6 +765,26 @@ form:
|
|||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
media.allowed_fallback_types:
|
||||||
|
type: selectize
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN.FALLBACK_TYPES
|
||||||
|
help: PLUGIN_ADMIN.FALLBACK_TYPES_HELP
|
||||||
|
classes: fancy
|
||||||
|
validate:
|
||||||
|
type: commalist
|
||||||
|
|
||||||
|
media.unsupported_inline_types:
|
||||||
|
type: selectize
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN.INLINE_TYPES
|
||||||
|
help: PLUGIN_ADMIN.INLINE_TYPES_HELP
|
||||||
|
classes: fancy
|
||||||
|
validate:
|
||||||
|
type: commalist
|
||||||
|
|
||||||
session:
|
session:
|
||||||
type: section
|
type: section
|
||||||
title: PLUGIN_ADMIN.SESSION
|
title: PLUGIN_ADMIN.SESSION
|
||||||
@@ -718,13 +792,14 @@ form:
|
|||||||
|
|
||||||
fields:
|
fields:
|
||||||
session.enabled:
|
session.enabled:
|
||||||
type: toggle
|
type: hidden
|
||||||
label: PLUGIN_ADMIN.ENABLED
|
label: PLUGIN_ADMIN.ENABLED
|
||||||
help: PLUGIN_ADMIN.SESSION_ENABLED_HELP
|
help: PLUGIN_ADMIN.SESSION_ENABLED_HELP
|
||||||
highlight: 1
|
highlight: 1
|
||||||
options:
|
options:
|
||||||
1: PLUGIN_ADMIN.YES
|
1: PLUGIN_ADMIN.YES
|
||||||
0: PLUGIN_ADMIN.NO
|
0: PLUGIN_ADMIN.NO
|
||||||
|
default: true
|
||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
|
|
||||||
@@ -743,6 +818,29 @@ form:
|
|||||||
label: PLUGIN_ADMIN.NAME
|
label: PLUGIN_ADMIN.NAME
|
||||||
help: PLUGIN_ADMIN.SESSION_NAME_HELP
|
help: PLUGIN_ADMIN.SESSION_NAME_HELP
|
||||||
|
|
||||||
|
session.secure:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.SESSION_SECURE
|
||||||
|
help: PLUGIN_ADMIN.SESSION_SECURE_HELP
|
||||||
|
highlight: 1
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
default: false
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
|
session.httponly:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.SESSION_HTTPONLY
|
||||||
|
help: PLUGIN_ADMIN.SESSION_HTTPONLY_HELP
|
||||||
|
highlight: 1
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
default: true
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
advanced:
|
advanced:
|
||||||
type: section
|
type: section
|
||||||
@@ -750,6 +848,17 @@ form:
|
|||||||
underline: true
|
underline: true
|
||||||
|
|
||||||
fields:
|
fields:
|
||||||
|
wrapped_site:
|
||||||
|
type: toggle
|
||||||
|
label: PLUGIN_ADMIN.WRAPPED_SITE
|
||||||
|
highlight: 0
|
||||||
|
help: PLUGIN_ADMIN.WRAPPED_SITE_HELP
|
||||||
|
options:
|
||||||
|
1: PLUGIN_ADMIN.YES
|
||||||
|
0: PLUGIN_ADMIN.NO
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
absolute_urls:
|
absolute_urls:
|
||||||
type: toggle
|
type: toggle
|
||||||
label: PLUGIN_ADMIN.ABSOLUTE_URLS
|
label: PLUGIN_ADMIN.ABSOLUTE_URLS
|
||||||
@@ -763,6 +872,7 @@ form:
|
|||||||
|
|
||||||
param_sep:
|
param_sep:
|
||||||
type: select
|
type: select
|
||||||
|
size: medium
|
||||||
label: PLUGIN_ADMIN.PARAMETER_SEPARATOR
|
label: PLUGIN_ADMIN.PARAMETER_SEPARATOR
|
||||||
classes: fancy
|
classes: fancy
|
||||||
help: PLUGIN_ADMIN.PARAMETER_SEPARATOR_HELP
|
help: PLUGIN_ADMIN.PARAMETER_SEPARATOR_HELP
|
||||||
|
|||||||
7
system/blueprints/media/meta.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
fields:
|
||||||
|
|
||||||
|
alt_text:
|
||||||
|
type: string
|
||||||
|
label: Alt Text
|
||||||
8
system/blueprints/media/move.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
fields:
|
||||||
|
route:
|
||||||
|
type: select
|
||||||
|
label: PLUGIN_ADMIN.PAGE
|
||||||
|
classes: fancy
|
||||||
|
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||||
8
system/blueprints/media/rename.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
fields:
|
||||||
|
new_file_name:
|
||||||
|
type: text
|
||||||
|
label: PLUGIN_ADMIN_PRO.NEW_FILE_NAME
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
@@ -29,7 +29,7 @@ form:
|
|||||||
|
|
||||||
content:
|
content:
|
||||||
type: markdown
|
type: markdown
|
||||||
label: PLUGIN_ADMIN.CONTENT
|
showPreview: true
|
||||||
validate:
|
validate:
|
||||||
type: textarea
|
type: textarea
|
||||||
|
|
||||||
@@ -88,7 +88,6 @@ form:
|
|||||||
placeholder_key: PLUGIN_ADMIN.METADATA_KEY
|
placeholder_key: PLUGIN_ADMIN.METADATA_KEY
|
||||||
placeholder_value: PLUGIN_ADMIN.METADATA_VALUE
|
placeholder_value: PLUGIN_ADMIN.METADATA_VALUE
|
||||||
|
|
||||||
|
|
||||||
taxonomies:
|
taxonomies:
|
||||||
type: section
|
type: section
|
||||||
title: PLUGIN_ADMIN.TAXONOMIES
|
title: PLUGIN_ADMIN.TAXONOMIES
|
||||||
@@ -264,6 +263,12 @@ form:
|
|||||||
default: default
|
default: default
|
||||||
'@data-options': '\Grav\Common\Page\Pages::types'
|
'@data-options': '\Grav\Common\Page\Pages::types'
|
||||||
|
|
||||||
|
header.append_url_extension:
|
||||||
|
type: text
|
||||||
|
label: PLUGIN_ADMIN.APPEND_URL_EXT
|
||||||
|
toggleable: true
|
||||||
|
help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP
|
||||||
|
|
||||||
header.order_by:
|
header.order_by:
|
||||||
type: hidden
|
type: hidden
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ form:
|
|||||||
|
|
||||||
content:
|
content:
|
||||||
type: markdown
|
type: markdown
|
||||||
label: PLUGIN_ADMIN.CONTENT
|
showPreview: true
|
||||||
|
|
||||||
uploads:
|
uploads:
|
||||||
type: pagemedia
|
type: pagemedia
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ form:
|
|||||||
|
|
||||||
content:
|
content:
|
||||||
type: markdown
|
type: markdown
|
||||||
label: PLUGIN_ADMIN.CONTENT
|
showPreview: true
|
||||||
|
|
||||||
uploads:
|
uploads:
|
||||||
type: pagemedia
|
type: pagemedia
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ form:
|
|||||||
size: large
|
size: large
|
||||||
label: PLUGIN_ADMIN.PASSWORD
|
label: PLUGIN_ADMIN.PASSWORD
|
||||||
validate:
|
validate:
|
||||||
required: true
|
required: false
|
||||||
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
|
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
|
||||||
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
|
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
|
||||||
|
|
||||||
@@ -54,3 +54,32 @@ form:
|
|||||||
default: 'en'
|
default: 'en'
|
||||||
help: PLUGIN_ADMIN.LANGUAGE_HELP
|
help: PLUGIN_ADMIN.LANGUAGE_HELP
|
||||||
|
|
||||||
|
security:
|
||||||
|
title: PLUGIN_ADMIN.ACCESS_LEVELS
|
||||||
|
type: section
|
||||||
|
security: admin.super
|
||||||
|
|
||||||
|
fields:
|
||||||
|
groups:
|
||||||
|
type: selectize
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN.GROUPS
|
||||||
|
'@data-options': '\Grav\User\Groups::groups'
|
||||||
|
classes: fancy
|
||||||
|
help: PLUGIN_ADMIN.GROUPS_HELP
|
||||||
|
validate:
|
||||||
|
type: commalist
|
||||||
|
|
||||||
|
access.admin:
|
||||||
|
type: array
|
||||||
|
label: PLUGIN_ADMIN.ADMIN_ACCESS
|
||||||
|
multiple: false
|
||||||
|
validate:
|
||||||
|
type: array
|
||||||
|
|
||||||
|
access.site:
|
||||||
|
type: array
|
||||||
|
label: PLUGIN_ADMIN.SITE_ACCESS
|
||||||
|
multiple: false
|
||||||
|
validate:
|
||||||
|
type: array
|
||||||
|
|||||||
44
system/blueprints/user/group.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
title: Group
|
||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
|
||||||
|
fields:
|
||||||
|
spacer:
|
||||||
|
type: spacer
|
||||||
|
text: '<br>'
|
||||||
|
|
||||||
|
groupname:
|
||||||
|
type: text
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN.NAME
|
||||||
|
disabled: true
|
||||||
|
readonly: true
|
||||||
|
|
||||||
|
readableName:
|
||||||
|
type: text
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN_PRO.READABLE_NAME
|
||||||
|
|
||||||
|
description:
|
||||||
|
type: text
|
||||||
|
size: large
|
||||||
|
label: PLUGIN_ADMIN.DESCRIPTION
|
||||||
|
|
||||||
|
icon:
|
||||||
|
type: text
|
||||||
|
size: small
|
||||||
|
label: PLUGIN_ADMIN_PRO.ICON
|
||||||
|
|
||||||
|
access.admin:
|
||||||
|
type: array
|
||||||
|
label: PLUGIN_ADMIN.ADMIN_ACCESS
|
||||||
|
multiple: false
|
||||||
|
validate:
|
||||||
|
type: array
|
||||||
|
|
||||||
|
access.site:
|
||||||
|
type: array
|
||||||
|
label: PLUGIN_ADMIN.SITE_ACCESS
|
||||||
|
multiple: false
|
||||||
|
validate:
|
||||||
|
type: array
|
||||||
16
system/blueprints/user/group_new.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
title: PLUGIN_ADMIN_PRO.ADD_GROUP
|
||||||
|
|
||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
fields:
|
||||||
|
|
||||||
|
content:
|
||||||
|
type: section
|
||||||
|
title: PLUGIN_ADMIN_PRO.ADD_GROUP
|
||||||
|
|
||||||
|
groupname:
|
||||||
|
type: text
|
||||||
|
label: PLUGIN_ADMIN_PRO.GROUP_NAME
|
||||||
|
help: PLUGIN_ADMIN_PRO.GROUP_NAME_HELP
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
@@ -168,6 +168,10 @@ zip:
|
|||||||
type: file
|
type: file
|
||||||
thumb: media/thumb-zip.png
|
thumb: media/thumb-zip.png
|
||||||
mime: application/zip
|
mime: application/zip
|
||||||
|
7z:
|
||||||
|
type: file
|
||||||
|
thumb: media/thumb-7zip.png
|
||||||
|
mime: application/x-7z-compressed
|
||||||
gz:
|
gz:
|
||||||
type: file
|
type: file
|
||||||
thumb: media/thumb-gz.png
|
thumb: media/thumb-gz.png
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
schemes:
|
schemes:
|
||||||
asset:
|
|
||||||
type: ReadOnlyStream
|
|
||||||
paths:
|
|
||||||
- assets
|
|
||||||
|
|
||||||
image:
|
image:
|
||||||
type: ReadOnlyStream
|
type: ReadOnlyStream
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -1,110 +1,116 @@
|
|||||||
absolute_urls: false # Absolute or relative URLs for `base_url`
|
absolute_urls: false # Absolute or relative URLs for `base_url`
|
||||||
timezone: '' # Valid values: http://php.net/manual/en/timezones.php
|
timezone: '' # Valid values: http://php.net/manual/en/timezones.php
|
||||||
default_locale: # Default locale (defaults to system)
|
default_locale: # Default locale (defaults to system)
|
||||||
param_sep: ':' # Parameter separator, use ';' for Apache on windows
|
param_sep: ':' # Parameter separator, use ';' for Apache on windows
|
||||||
|
wrapped_site: false # For themes/plugins to know if Grav is wrapped by another platform
|
||||||
|
|
||||||
languages:
|
languages:
|
||||||
supported: [] # List of languages supported. eg: [en, fr, de]
|
supported: [] # List of languages supported. eg: [en, fr, de]
|
||||||
include_default_lang: true # Include the default lang prefix in all URLs
|
include_default_lang: true # Include the default lang prefix in all URLs
|
||||||
translations: true # Enable translations by default
|
translations: true # Enable translations by default
|
||||||
translations_fallback: true # Fallback through supported translations if active lang doesn't exist
|
translations_fallback: true # Fallback through supported translations if active lang doesn't exist
|
||||||
session_store_active: false # Store active language in session
|
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
|
http_accept_language: false # Attempt to set the language based on http_accept_language header in the browser
|
||||||
override_locale: false # Override the default or system locale with language specific one
|
override_locale: false # Override the default or system locale with language specific one
|
||||||
|
|
||||||
home:
|
home:
|
||||||
alias: '/home' # Default path for home, ie /
|
alias: '/home' # Default path for home, ie /
|
||||||
|
hide_in_urls: false # Hide the home route in URLs
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
theme: antimatter # Default theme (defaults to "antimatter" theme)
|
theme: antimatter # Default theme (defaults to "antimatter" theme)
|
||||||
order:
|
order:
|
||||||
by: default # Order pages by "default", "alpha" or "date"
|
by: default # Order pages by "default", "alpha" or "date"
|
||||||
dir: asc # Default ordering direction, "asc" or "desc"
|
dir: asc # Default ordering direction, "asc" or "desc"
|
||||||
list:
|
list:
|
||||||
count: 20 # Default item count per page
|
count: 20 # Default item count per page
|
||||||
dateformat:
|
dateformat:
|
||||||
default: # The default date format Grav expects in the `date: ` field
|
default: # The default date format Grav expects in the `date: ` field
|
||||||
short: 'jS M Y' # Short date format
|
short: 'jS M Y' # Short date format
|
||||||
long: 'F jS \a\t g:ia' # Long date format
|
long: 'F jS \a\t g:ia' # Long date format
|
||||||
publish_dates: true # automatically publish/unpublish based on dates
|
publish_dates: true # automatically publish/unpublish based on dates
|
||||||
process:
|
process:
|
||||||
markdown: true # Process Markdown
|
markdown: true # Process Markdown
|
||||||
twig: false # Process Twig
|
twig: false # Process Twig
|
||||||
|
twig_first: false # Process Twig before markdown when processing both on a page
|
||||||
events:
|
events:
|
||||||
page: true # Enable page level events
|
page: true # Enable page level events
|
||||||
twig: true # Enable twig level events
|
twig: true # Enable twig level events
|
||||||
markdown:
|
markdown:
|
||||||
extra: false # Enable support for Markdown Extra support (GFM by default)
|
extra: false # Enable support for Markdown Extra support (GFM by default)
|
||||||
auto_line_breaks: false # Enable automatic line breaks
|
auto_line_breaks: false # Enable automatic line breaks
|
||||||
auto_url_links: false # Enable automatic HTML links
|
auto_url_links: false # Enable automatic HTML links
|
||||||
escape_markup: false # Escape markup tags into entities
|
escape_markup: false # Escape markup tags into entities
|
||||||
special_chars: # List of special characters to automatically convert to entities
|
special_chars: # List of special characters to automatically convert to entities
|
||||||
'>': 'gt'
|
'>': 'gt'
|
||||||
'<': 'lt'
|
'<': 'lt'
|
||||||
types: [txt,xml,html,json,rss,atom] # list of valid page types
|
types: [txt,xml,html,htm,json,rss,atom] # list of valid page types
|
||||||
expires: 604800 # Page expires time in seconds (604800 seconds = 7 days)
|
append_url_extension: '' # Append page's extension in Page urls (e.g. '.html' results in /path/page.html)
|
||||||
last_modified: false # Set the last modified date header based on file modifcation timestamp
|
expires: 604800 # Page expires time in seconds (604800 seconds = 7 days)
|
||||||
etag: false # Set the etag header tag
|
last_modified: false # Set the last modified date header based on file modifcation timestamp
|
||||||
vary_accept_encoding: false # Add `Vary: Accept-Encoding` header
|
etag: false # Set the etag header tag
|
||||||
redirect_default_route: false # Automatically redirect to a page's default route
|
vary_accept_encoding: false # Add `Vary: Accept-Encoding` header
|
||||||
redirect_default_code: 301 # Default code to use for redirects
|
redirect_default_route: false # Automatically redirect to a page's default route
|
||||||
redirect_trailing_slash: true # Handle automatically or 301 redirect a trailing / URL
|
redirect_default_code: 301 # Default code to use for redirects
|
||||||
ignore_files: [.DS_Store] # Files to ignore in Pages
|
redirect_trailing_slash: true # Handle automatically or 301 redirect a trailing / URL
|
||||||
ignore_folders: [.git, .idea] # Folders to ignore in Pages
|
ignore_files: [.DS_Store] # Files to ignore in Pages
|
||||||
ignore_hidden: true # Ignore all Hidden files and folders
|
ignore_folders: [.git, .idea] # Folders to ignore in Pages
|
||||||
url_taxonomy_filters: true # Enable auto-magic URL-based taxonomy filters for page collections
|
ignore_hidden: true # Ignore all Hidden files and folders
|
||||||
|
url_taxonomy_filters: true # Enable auto-magic URL-based taxonomy filters for page collections
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
enabled: true # Set to true to enable caching
|
enabled: true # Set to true to enable caching
|
||||||
check:
|
check:
|
||||||
method: file # Method to check for updates in pages: file|folder|none
|
method: file # Method to check for updates in pages: file|folder|none
|
||||||
driver: auto # One of: auto|file|apc|xcache|memcache|wincache
|
driver: auto # One of: auto|file|apc|xcache|memcache|wincache
|
||||||
prefix: 'g' # Cache prefix string (prevents cache conflicts)
|
prefix: 'g' # Cache prefix string (prevents cache conflicts)
|
||||||
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)
|
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)
|
||||||
gzip: false # GZip compress the page output
|
gzip: false # GZip compress the page output
|
||||||
|
|
||||||
twig:
|
twig:
|
||||||
cache: true # Set to true to enable twig caching
|
cache: true # Set to true to enable twig caching
|
||||||
debug: false # Enable Twig debug
|
debug: false # Enable Twig debug
|
||||||
auto_reload: true # Refresh cache on changes
|
auto_reload: true # Refresh cache on changes
|
||||||
autoescape: false # Autoescape Twig vars
|
autoescape: false # Autoescape Twig vars
|
||||||
undefined_functions: true # Allow undefined functions
|
undefined_functions: true # Allow undefined functions
|
||||||
undefined_filters: true # Allow undefined filters
|
undefined_filters: true # Allow undefined filters
|
||||||
|
umask_fix: false # By default Twig creates cached files as 755, fix switches this to 775
|
||||||
|
|
||||||
assets: # Configuration for Assets Manager (JS, CSS)
|
assets: # Configuration for Assets Manager (JS, CSS)
|
||||||
css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file
|
css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file
|
||||||
css_minify: true # Minify the CSS during pipelining
|
css_minify: true # Minify the CSS during pipelining
|
||||||
css_minify_windows: false # Minify Override for Windows platforms. False by default due to ThreadStackSize
|
css_minify_windows: false # Minify Override for Windows platforms. False by default due to ThreadStackSize
|
||||||
css_rewrite: true # Rewrite any CSS relative URLs during pipelining
|
css_rewrite: true # Rewrite any CSS relative URLs during pipelining
|
||||||
js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file
|
js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file
|
||||||
js_minify: true # Minify the JS during pipelining
|
js_minify: true # Minify the JS during pipelining
|
||||||
enable_asset_timestamp: false # Enable asset timestamps
|
enable_asset_timestamp: false # Enable asset timestamps
|
||||||
collections:
|
collections:
|
||||||
jquery: system://assets/jquery/jquery-2.1.4.min.js
|
jquery: system://assets/jquery/jquery-2.1.4.min.js
|
||||||
|
|
||||||
errors:
|
errors:
|
||||||
display: false # Display full backtrace-style error page
|
display: false # Display full backtrace-style error page
|
||||||
log: true # Log errors to /logs folder
|
log: true # Log errors to /logs folder
|
||||||
|
|
||||||
debugger:
|
debugger:
|
||||||
enabled: false # Enable Grav debugger and following settings
|
enabled: false # Enable Grav debugger and following settings
|
||||||
shutdown:
|
shutdown:
|
||||||
close_connection: true # Close the connection before calling onShutdown(). false for debugging
|
close_connection: true # Close the connection before calling onShutdown(). false for debugging
|
||||||
|
|
||||||
images:
|
images:
|
||||||
default_image_quality: 85 # Default image quality to use when resampling images (85%)
|
default_image_quality: 85 # Default image quality to use when resampling images (85%)
|
||||||
cache_all: false # Cache all image by default
|
cache_all: false # Cache all image by default
|
||||||
debug: false # Show an overlay over images indicating the pixel depth of the image when working with retina for example
|
cache_perms: '0755' # MUST BE IN QUOTES!! Default cache folder perms. Usually '0755' or '0775'
|
||||||
|
debug: false # Show an overlay over images indicating the pixel depth of the image when working with retina for example
|
||||||
|
|
||||||
media:
|
media:
|
||||||
enable_media_timestamp: false # Enable media timetsamps
|
enable_media_timestamp: false # Enable media timetsamps
|
||||||
upload_limit: 0 # Set maximum upload size in bytes (0 is unlimited)
|
upload_limit: 0 # Set maximum upload size in bytes (0 is unlimited)
|
||||||
unsupported_inline_types: [] # Array of unsupported media file types to try to display inline
|
unsupported_inline_types: [] # Array of supported media types to try to display inline
|
||||||
|
allowed_fallback_types: [] # Array of allowed media types of files found if accessed via Page route
|
||||||
|
|
||||||
session:
|
session:
|
||||||
enabled: true # Enable Session support
|
enabled: true # Enable Session support
|
||||||
timeout: 1800 # Timeout in seconds
|
timeout: 1800 # Timeout in seconds
|
||||||
name: grav-site # Name prefix of the session cookie
|
name: grav-site # Name prefix of the session cookie. Use alphanumeric, dashes or underscores only. Do not use dots in the session name
|
||||||
|
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
|
||||||
security:
|
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
|
||||||
default_hash: $2y$10$kwsyMVwM8/7j0K/6LHT.g.Fs49xOCTp2b8hh/S5.dPJuJcJB6T.UK
|
|
||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
// Some standard defines
|
// Some standard defines
|
||||||
define('GRAV', true);
|
define('GRAV', true);
|
||||||
define('GRAV_VERSION', '1.0.0-rc.1');
|
define('GRAV_VERSION', '1.0.8');
|
||||||
define('DS', '/');
|
define('DS', '/');
|
||||||
|
define('GRAV_PHP_MIN', '5.5.9');
|
||||||
|
|
||||||
// Directories and Paths
|
// Directories and Paths
|
||||||
if (!defined('GRAV_ROOT')) {
|
if (!defined('GRAV_ROOT')) {
|
||||||
@@ -13,14 +14,14 @@ define('ROOT_DIR', GRAV_ROOT . '/');
|
|||||||
define('USER_PATH', 'user/');
|
define('USER_PATH', 'user/');
|
||||||
define('USER_DIR', ROOT_DIR . USER_PATH);
|
define('USER_DIR', ROOT_DIR . USER_PATH);
|
||||||
define('SYSTEM_DIR', ROOT_DIR .'system/');
|
define('SYSTEM_DIR', ROOT_DIR .'system/');
|
||||||
define('ASSETS_DIR', ROOT_DIR . 'assets/');
|
|
||||||
define('CACHE_DIR', ROOT_DIR . 'cache/');
|
define('CACHE_DIR', ROOT_DIR . 'cache/');
|
||||||
define('IMAGES_DIR', ROOT_DIR . 'images/');
|
|
||||||
define('LOG_DIR', ROOT_DIR .'logs/');
|
define('LOG_DIR', ROOT_DIR .'logs/');
|
||||||
define('ACCOUNTS_DIR', USER_DIR .'accounts/');
|
|
||||||
define('PAGES_DIR', USER_DIR .'pages/');
|
|
||||||
|
|
||||||
// DEPRECATED: Do not use!
|
// DEPRECATED: Do not use!
|
||||||
|
define('ASSETS_DIR', ROOT_DIR . 'assets/');
|
||||||
|
define('IMAGES_DIR', ROOT_DIR . 'images/');
|
||||||
|
define('ACCOUNTS_DIR', USER_DIR .'accounts/');
|
||||||
|
define('PAGES_DIR', USER_DIR .'pages/');
|
||||||
define('DATA_DIR', USER_DIR .'data/');
|
define('DATA_DIR', USER_DIR .'data/');
|
||||||
define('LIB_DIR', SYSTEM_DIR .'src/');
|
define('LIB_DIR', SYSTEM_DIR .'src/');
|
||||||
define('PLUGINS_DIR', USER_DIR .'plugins/');
|
define('PLUGINS_DIR', USER_DIR .'plugins/');
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
system/images/media/thumb.png
Normal file
|
After Width: | Height: | Size: 123 B |
@@ -35,3 +35,5 @@ NICETIME:
|
|||||||
MO_PLURAL: m
|
MO_PLURAL: m
|
||||||
YR_PLURAL: r
|
YR_PLURAL: r
|
||||||
DEC_PLURAL: dek
|
DEC_PLURAL: dek
|
||||||
|
MONTHS_OF_THE_YEAR: ['Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec']
|
||||||
|
DAYS_OF_THE_WEEK: ['Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle']
|
||||||
|
|||||||
@@ -1,43 +1,45 @@
|
|||||||
INFLECTOR_IRREGULAR:
|
INFLECTOR_IRREGULAR:
|
||||||
'person': 'personen'
|
'person': 'Personen'
|
||||||
'man': 'menschen'
|
'man': 'Menschen'
|
||||||
'child': 'kinder'
|
'child': 'Kinder'
|
||||||
'sex': 'geschlecht'
|
'sex': 'Geschlecht'
|
||||||
'move': 'züge'
|
'move': 'Züge'
|
||||||
NICETIME:
|
NICETIME:
|
||||||
NO_DATE_PROVIDED: Keine Daten vorhanden
|
NO_DATE_PROVIDED: Keine Daten vorhanden
|
||||||
BAD_DATE: Falsches Datum
|
BAD_DATE: Falsches Datum
|
||||||
AGO: her
|
AGO: her
|
||||||
FROM_NOW: ab jetzt
|
FROM_NOW: ab jetzt
|
||||||
SECOND: sekunde
|
SECOND: Sekunde
|
||||||
MINUTE: minute
|
MINUTE: Minute
|
||||||
HOUR: stunde
|
HOUR: Stunde
|
||||||
DAY: tag
|
DAY: Tag
|
||||||
WEEK: woche
|
WEEK: Woche
|
||||||
MONTH: monat
|
MONTH: Monat
|
||||||
YEAR: jahr
|
YEAR: Jahr
|
||||||
DECADE: dekade
|
DECADE: Dekade
|
||||||
SEC: sek
|
SEC: sek
|
||||||
MIN: min
|
MIN: min
|
||||||
HR: std
|
HR: std
|
||||||
DAY: tag
|
DAY: Tag
|
||||||
WK: wo
|
WK: wo
|
||||||
MO: mo
|
MO: mo
|
||||||
YR: yh
|
YR: yh
|
||||||
DEC: dec
|
DEC: dec
|
||||||
SECOND_PLURAL: sekunden
|
SECOND_PLURAL: Sekunden
|
||||||
MINUTE_PLURAL: minuten
|
MINUTE_PLURAL: Minuten
|
||||||
HOUR_PLURAL: stunden
|
HOUR_PLURAL: Stunden
|
||||||
DAY_PLURAL: tage
|
DAY_PLURAL: Tage
|
||||||
WEEK_PLURAL: wochen
|
WEEK_PLURAL: Wochen
|
||||||
MONTH_PLURAL: monate
|
MONTH_PLURAL: Monate
|
||||||
YEAR_PLURAL: jahre
|
YEAR_PLURAL: Jahre
|
||||||
DECADE_PLURAL: dekaden
|
DECADE_PLURAL: Dekaden
|
||||||
SEC_PLURAL: sekunden
|
SEC_PLURAL: Sekunden
|
||||||
MIN_PLURAL: minuten
|
MIN_PLURAL: Minuten
|
||||||
HR_PLURAL: stunden
|
HR_PLURAL: Stunden
|
||||||
DAY_PLURAL: tage
|
DAY_PLURAL: Tage
|
||||||
WK_PLURAL: wochen
|
WK_PLURAL: Wochen
|
||||||
MO_PLURAL: monate
|
MO_PLURAL: Monate
|
||||||
YR_PLURAL: jahre
|
YR_PLURAL: Jahre
|
||||||
DEC_PLURAL: dekaden
|
DEC_PLURAL: Dekaden
|
||||||
|
MONTHS_OF_THE_YEAR: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']
|
||||||
|
DAYS_OF_THE_WEEK: ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']
|
||||||
|
|||||||
2
system/languages/el.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHS_OF_THE_YEAR: ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος']
|
||||||
|
DAYS_OF_THE_WEEK: ['Δευτέρα', 'Τρλιτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σαββάτο', 'Κυριακή']
|
||||||
@@ -92,3 +92,9 @@ NICETIME:
|
|||||||
MO_PLURAL: mos
|
MO_PLURAL: mos
|
||||||
YR_PLURAL: yrs
|
YR_PLURAL: yrs
|
||||||
DEC_PLURAL: decs
|
DEC_PLURAL: decs
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>Validation failed:</b>
|
||||||
|
INVALID_INPUT: Invalid input in
|
||||||
|
MISSING_REQUIRED_FIELD: Missing required field:
|
||||||
|
MONTHS_OF_THE_YEAR: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||||
|
DAYS_OF_THE_WEEK: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||||
|
|||||||
44
system/languages/es.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
NICETIME:
|
||||||
|
NO_DATE_PROVIDED: No se proporcionó fecha
|
||||||
|
BAD_DATE: Fecha erronea
|
||||||
|
AGO: antes
|
||||||
|
FROM_NOW: desde ahora
|
||||||
|
SECOND: segundo
|
||||||
|
MINUTE: minuto
|
||||||
|
HOUR: hora
|
||||||
|
DAY: dia
|
||||||
|
WEEK: semana
|
||||||
|
MONTH: mes
|
||||||
|
YEAR: año
|
||||||
|
DECADE: decada
|
||||||
|
SEC: seg
|
||||||
|
MIN: min
|
||||||
|
HR: hr
|
||||||
|
DAY: dia
|
||||||
|
WK: sem
|
||||||
|
MO: mes
|
||||||
|
YR: yr
|
||||||
|
DEC: dec
|
||||||
|
SECOND_PLURAL: segundos
|
||||||
|
MINUTE_PLURAL: minutos
|
||||||
|
HOUR_PLURAL: horas
|
||||||
|
DAY_PLURAL: días
|
||||||
|
WEEK_PLURAL: semanas
|
||||||
|
MONTH_PLURAL: meses
|
||||||
|
YEAR_PLURAL: años
|
||||||
|
DECADE_PLURAL: decadas
|
||||||
|
SEC_PLURAL: segs
|
||||||
|
MIN_PLURAL: mins
|
||||||
|
HR_PLURAL: hrs
|
||||||
|
DAY_PLURAL: dias
|
||||||
|
WK_PLURAL: sem
|
||||||
|
MO_PLURAL: mes
|
||||||
|
YR_PLURAL: años
|
||||||
|
DEC_PLURAL: decs
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>Falló la validación. </b>
|
||||||
|
INVALID_INPUT: "Dato inválido en: "
|
||||||
|
MISSING_REQUIRED_FIELD: "Falta el campo requerido: "
|
||||||
|
MONTHS_OF_THE_YEAR: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Augosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
|
||||||
|
DAYS_OF_THE_WEEK: ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo']
|
||||||
|
|
||||||
2
system/languages/fi.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHSOFTHE_YEAR: ['Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu', 'Kesäkuu', 'Heinäkuu', 'Elokuu', 'Syyskuu', 'Lokakuu', 'Marraskuu', 'Joulukuu']
|
||||||
|
DAYSOFTHE_WEEK: ['Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai', 'Sunnuntai']
|
||||||
@@ -1,26 +1,60 @@
|
|||||||
|
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Erreur : Frontmatter invalide\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||||
INFLECTOR_PLURALS:
|
INFLECTOR_PLURALS:
|
||||||
'/$/': 's'
|
'/(quiz)$/i': '\1zes'
|
||||||
'/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/': '\1x'
|
'/^(ox)$/i': '\1en'
|
||||||
'/(bleu|émeu|landau|lieu|pneu|sarrau)$/': '\1s'
|
'/([m|l])ouse$/i': '\1ice'
|
||||||
'/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/': '\1aux'
|
'/(matr|vert|ind)ix|ex$/i': '\1ices'
|
||||||
'/(s|x|z)$/': '\1'
|
'/(x|ch|ss|sh)$/i': '\1es'
|
||||||
'/ail$/': 'ails'
|
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||||
'/al$/': 'aux'
|
'/([^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$/i': 's'
|
||||||
|
'/$/': 's'
|
||||||
INFLECTOR_SINGULAR:
|
INFLECTOR_SINGULAR:
|
||||||
'/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/': '\1'
|
'/(quiz)zes$/i': '\1'
|
||||||
'/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/': '\1ail'
|
'/(matr)ices$/i': '\1ix'
|
||||||
'/(journ|chev)aux$/': '\1al'
|
'/(vert|ind)ices$/i': '\1ex'
|
||||||
'/ails$/': 'ail'
|
'/^(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'
|
||||||
'/s$/i': ''
|
'/s$/i': ''
|
||||||
|
INFLECTOR_UNCOUNTABLE: ['équipement', 'information', 'riz', 'argent', 'espèces', 'séries', 'poisson', 'mouton']
|
||||||
INFLECTOR_IRREGULAR:
|
INFLECTOR_IRREGULAR:
|
||||||
'madame': 'mesdames'
|
'person': 'personnes'
|
||||||
'mademoiselle': 'mesdemoiselles'
|
'man': 'hommes'
|
||||||
'monsieur': 'messieurs'
|
'child': 'enfants'
|
||||||
|
'sex': 'sexes'
|
||||||
|
'move': 'déplacements'
|
||||||
INFLECTOR_ORDINALS:
|
INFLECTOR_ORDINALS:
|
||||||
'default': 'ème'
|
'default': 'ème'
|
||||||
'first': 'er'
|
'first': 'er'
|
||||||
'second': 'nd'
|
'second': 'nd'
|
||||||
|
'third': 'ème'
|
||||||
NICETIME:
|
NICETIME:
|
||||||
NO_DATE_PROVIDED: Aucune date
|
NO_DATE_PROVIDED: Aucune date
|
||||||
BAD_DATE: Date erronée
|
BAD_DATE: Date erronée
|
||||||
@@ -48,7 +82,7 @@ NICETIME:
|
|||||||
DAY_PLURAL: jours
|
DAY_PLURAL: jours
|
||||||
WEEK_PLURAL: semaines
|
WEEK_PLURAL: semaines
|
||||||
MONTH_PLURAL: mois
|
MONTH_PLURAL: mois
|
||||||
YEAR_PLURAL: ans
|
YEAR_PLURAL: années
|
||||||
DECADE_PLURAL: décennies
|
DECADE_PLURAL: décennies
|
||||||
SEC_PLURAL: s
|
SEC_PLURAL: s
|
||||||
MIN_PLURAL: m
|
MIN_PLURAL: m
|
||||||
@@ -58,3 +92,9 @@ NICETIME:
|
|||||||
MO_PLURAL: m
|
MO_PLURAL: m
|
||||||
YR_PLURAL: a
|
YR_PLURAL: a
|
||||||
DEC_PLURAL: d
|
DEC_PLURAL: d
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>La validation a échoué :</b>
|
||||||
|
INVALID_INPUT: Saisie non valide
|
||||||
|
MISSING_REQUIRED_FIELD: Champ obligatoire manquant :
|
||||||
|
MONTHS_OF_THE_YEAR: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
|
||||||
|
DAYS_OF_THE_WEEK: ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
|
||||||
|
|||||||
52
system/languages/hr.yaml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
INFLECTOR_IRREGULAR:
|
||||||
|
'person': 'Osoba'
|
||||||
|
'man': 'Čovjek'
|
||||||
|
'child': 'Dijete'
|
||||||
|
'sex': 'Spol'
|
||||||
|
'move': 'Pomakni'
|
||||||
|
NICETIME:
|
||||||
|
NO_DATE_PROVIDED: Datum nije upisan
|
||||||
|
BAD_DATE: Pogrešan datum
|
||||||
|
AGO: prije
|
||||||
|
FROM_NOW: od sad
|
||||||
|
SECOND: sekundi
|
||||||
|
MINUTE: minuta
|
||||||
|
HOUR: godina
|
||||||
|
DAY: dan
|
||||||
|
WEEK: tjedan
|
||||||
|
MONTH: mjesec
|
||||||
|
YEAR: godina
|
||||||
|
DECADE: desetljeće
|
||||||
|
SEC: sek
|
||||||
|
MIN: min
|
||||||
|
HR: sat
|
||||||
|
DAY: dan
|
||||||
|
WK: t
|
||||||
|
MO: m
|
||||||
|
YR: g
|
||||||
|
DEC: des
|
||||||
|
SECOND_PLURAL: sekundi
|
||||||
|
SECOND_PLURAL_MORE_THAN_TWO: sekunde
|
||||||
|
MINUTE_PLURAL: minuta
|
||||||
|
MINUTE_PLURAL_MORE_THAN_TWO: minute
|
||||||
|
HOUR_PLURAL: sati
|
||||||
|
HOUR_PLURAL_MORE_THAN_TWO: sata
|
||||||
|
DAY_PLURAL: dana
|
||||||
|
WEEK_PLURAL: tjedana
|
||||||
|
WEEK_PLURAL_MORE_THAN_TWO: tjedna
|
||||||
|
MONTH_PLURAL: mjeseci
|
||||||
|
MONTH_PLURAL_MORE_THAN_TWO: mjeseca
|
||||||
|
YEAR_PLURAL: godina
|
||||||
|
YEAR_PLURAL_MORE_THAN_TWO: godine
|
||||||
|
DECADE_PLURAL: desetljeća
|
||||||
|
SEC_PLURAL: sek
|
||||||
|
MIN_PLURAL: min
|
||||||
|
HR_PLURAL: sat
|
||||||
|
DAY_PLURAL: dan
|
||||||
|
WK_PLURAL: t
|
||||||
|
MO_PLURAL: m
|
||||||
|
YR_PLURAL: g
|
||||||
|
DEC_PLURAL: des
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>Validacija nije uspjela:</b>
|
||||||
|
INVALID_INPUT: Unos nije valjan
|
||||||
53
system/languages/hu.yaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
FRONTMATTER_ERROR_PAGE: "---\ncím: %1$s\n---\n\n# Hiba: Érvénytelen Frontmatter\n\nElérési út: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||||
|
INFLECTOR_IRREGULAR:
|
||||||
|
'person': 'személyek'
|
||||||
|
'man': 'férfiak'
|
||||||
|
'child': 'gyerekek'
|
||||||
|
'sex': 'nemek'
|
||||||
|
'move': 'lépések'
|
||||||
|
INFLECTOR_ORDINALS:
|
||||||
|
'default': '.'
|
||||||
|
'first': '.'
|
||||||
|
'second': '.'
|
||||||
|
'third': '.'
|
||||||
|
NICETIME:
|
||||||
|
NO_DATE_PROVIDED: Nincs dátum megadva
|
||||||
|
BAD_DATE: Hibás dátum
|
||||||
|
AGO: elteltével
|
||||||
|
FROM_NOW: mostantól
|
||||||
|
SECOND: másodperc
|
||||||
|
MINUTE: perc
|
||||||
|
HOUR: óra
|
||||||
|
DAY: nap
|
||||||
|
WEEK: hét
|
||||||
|
MONTH: hónap
|
||||||
|
YEAR: év
|
||||||
|
DECADE: évtized
|
||||||
|
SEC: mp
|
||||||
|
MIN: p
|
||||||
|
HR: ó
|
||||||
|
DAY: nap
|
||||||
|
WK: hét
|
||||||
|
MO: hó
|
||||||
|
YR: év
|
||||||
|
DEC: évt
|
||||||
|
SECOND_PLURAL: másodperc
|
||||||
|
MINUTE_PLURAL: perc
|
||||||
|
HOUR_PLURAL: óra
|
||||||
|
DAY_PLURAL: nap
|
||||||
|
WEEK_PLURAL: hét
|
||||||
|
MONTH_PLURAL: hónap
|
||||||
|
YEAR_PLURAL: év
|
||||||
|
DECADE_PLURAL: évtized
|
||||||
|
SEC_PLURAL: mp
|
||||||
|
MIN_PLURAL: perc
|
||||||
|
HR_PLURAL: ó
|
||||||
|
DAY_PLURAL: nap
|
||||||
|
WK_PLURAL: hét
|
||||||
|
MO_PLURAL: hó
|
||||||
|
YR_PLURAL: év
|
||||||
|
DEC_PLURAL: évt
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>A validáció hibát talált:</b>
|
||||||
|
INVALID_INPUT: Az itt megadott érték érvénytelen:
|
||||||
|
MISSING_REQUIRED_FIELD: Ez a kötelező mező nincs kitöltve:
|
||||||
@@ -19,3 +19,9 @@ NICETIME:
|
|||||||
MONTH_PLURAL: mesi
|
MONTH_PLURAL: mesi
|
||||||
YEAR_PLURAL: anni
|
YEAR_PLURAL: anni
|
||||||
DECADE_PLURAL: decadi
|
DECADE_PLURAL: decadi
|
||||||
|
FORM:
|
||||||
|
VALIDATION_FAIL: <b>Validazione fallita:</b>
|
||||||
|
INVALID_INPUT: Input invalido in
|
||||||
|
MISSING_REQUIRED_FIELD: Campo richiesto mancante:
|
||||||
|
MONTHS_OF_THE_YEAR: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre']
|
||||||
|
DAYS_OF_THE_WEEK: ['Lunedi', 'Martedi', 'Mercoledi', 'Giovedi', 'Venerdi', 'Sabato', 'Domenica']
|
||||||
|
|||||||
2
system/languages/nb.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHS_OF_THE_YEAR: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember']
|
||||||
|
DAYS_OF_THE_WEEK: ['mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag', 'søndag']
|
||||||
@@ -41,3 +41,5 @@ NICETIME:
|
|||||||
MO_PLURAL: maanden
|
MO_PLURAL: maanden
|
||||||
YR_PLURAL: jaren
|
YR_PLURAL: jaren
|
||||||
DEC_PLURAL: decs
|
DEC_PLURAL: decs
|
||||||
|
MONTHS_OF_THE_YEAR: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December']
|
||||||
|
DAYS_OF_THE_WEEK: ['Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag', 'Zondag']
|
||||||
|
|||||||
2
system/languages/pl.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHS_OF_THE_YEAR: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień']
|
||||||
|
DAYS_OF_THE_WEEK: ['Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota', 'Niedziela']
|
||||||
2
system/languages/pt.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHS_OF_THE_YEAR: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']
|
||||||
|
DAYS_OF_THE_WEEK: ['Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado', 'Domingo']
|
||||||
2
system/languages/ro.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MONTHS_OF_THE_YEAR: ['Ianuarie', 'Februarie', 'Martie', 'Aprilue', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie']
|
||||||
|
DAYS_OF_THE_WEEK: ['Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă', 'Duminică']
|
||||||
@@ -41,3 +41,5 @@ NICETIME:
|
|||||||
MO_PLURAL: мес
|
MO_PLURAL: мес
|
||||||
YR_PLURAL: г.
|
YR_PLURAL: г.
|
||||||
DEC_PLURAL: гг.
|
DEC_PLURAL: гг.
|
||||||
|
MONTHS_OF_THE_YEAR: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
|
||||||
|
DAYS_OF_THE_WEEK: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']
|
||||||
|
|||||||
37
system/languages/tr.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
NICETIME:
|
||||||
|
NO_DATE_PROVIDED: Tarih yok
|
||||||
|
BAD_DATE: Yanlış tarih
|
||||||
|
AGO: önce
|
||||||
|
FROM_NOW: (şimdiden)
|
||||||
|
SECOND: saniye
|
||||||
|
MINUTE: dakika
|
||||||
|
HOUR: saat
|
||||||
|
DAY: gün
|
||||||
|
WEEK: hafta
|
||||||
|
MONTH: ay
|
||||||
|
YEAR: yıl
|
||||||
|
DECADE: onyıl
|
||||||
|
SEC: sn
|
||||||
|
MIN: dk
|
||||||
|
HR: sa
|
||||||
|
DAY: gün
|
||||||
|
WK: hft
|
||||||
|
MO: ay
|
||||||
|
YR: yl
|
||||||
|
DEC: onyl
|
||||||
|
SECOND_PLURAL: saniye
|
||||||
|
MINUTE_PLURAL: dakika
|
||||||
|
HOUR_PLURAL: saat
|
||||||
|
DAY_PLURAL: gün
|
||||||
|
WEEK_PLURAL: hafta
|
||||||
|
MONTH_PLURAL: ay
|
||||||
|
YEAR_PLURAL: yıl
|
||||||
|
DECADE_PLURAL: onyıl
|
||||||
|
SEC_PLURAL: sn
|
||||||
|
MIN_PLURAL: dk
|
||||||
|
HR_PLURAL: sa
|
||||||
|
DAY_PLURAL: gün
|
||||||
|
WK_PLURAL: hft
|
||||||
|
MO_PLURAL: ay
|
||||||
|
YR_PLURAL: yl
|
||||||
|
DEC_PLURAL: onyl
|
||||||
@@ -42,6 +42,8 @@ class Assets
|
|||||||
/** @const Regex to match CSS import content */
|
/** @const Regex to match CSS import content */
|
||||||
const CSS_IMPORT_REGEX = '{@import(.*);}';
|
const CSS_IMPORT_REGEX = '{@import(.*);}';
|
||||||
|
|
||||||
|
const HTML_TAG_REGEX = '#(<([A-Z][A-Z0-9]*)>)+(.*)(<\/\2>)#is';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closure used by the pipeline to fetch assets.
|
* Closure used by the pipeline to fetch assets.
|
||||||
@@ -72,6 +74,8 @@ class Assets
|
|||||||
protected $config;
|
protected $config;
|
||||||
protected $base_url;
|
protected $base_url;
|
||||||
protected $timestamp = '';
|
protected $timestamp = '';
|
||||||
|
protected $assets_dir;
|
||||||
|
protected $assets_url;
|
||||||
|
|
||||||
// Default values for pipeline settings
|
// Default values for pipeline settings
|
||||||
protected $css_minify = true;
|
protected $css_minify = true;
|
||||||
@@ -115,7 +119,7 @@ class Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pipeline requires public dir
|
// Pipeline requires public dir
|
||||||
if (($this->js_pipeline || $this->css_pipeline) && !is_dir(ASSETS_DIR)) {
|
if (($this->js_pipeline || $this->css_pipeline) && !is_dir($this->assets_dir)) {
|
||||||
throw new \Exception('Assets: Public dir not found');
|
throw new \Exception('Assets: Public dir not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +177,16 @@ class Assets
|
|||||||
$base_url = self::getGrav()['base_url'];
|
$base_url = self::getGrav()['base_url'];
|
||||||
$asset_config = (array)$config->get('system.assets');
|
$asset_config = (array)$config->get('system.assets');
|
||||||
|
|
||||||
|
/** @var Locator $locator */
|
||||||
|
$locator = self::$grav['locator'];
|
||||||
|
$this->assets_dir = self::getGrav()['locator']->findResource('asset://') . DS;
|
||||||
|
$this->assets_url = self::getGrav()['locator']->findResource('asset://', false);
|
||||||
|
|
||||||
$this->config($asset_config);
|
$this->config($asset_config);
|
||||||
$this->base_url = $base_url . '/';
|
$this->base_url = $base_url . '/';
|
||||||
|
|
||||||
// Register any preconfigured collections
|
// Register any preconfigured collections
|
||||||
foreach ($config->get('system.assets.collections') as $name => $collection) {
|
foreach ($config->get('system.assets.collections', []) as $name => $collection) {
|
||||||
$this->registerCollection($name, (array)$collection);
|
$this->registerCollection($name, (array)$collection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +203,7 @@ class Assets
|
|||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function add($asset, $priority = null, $pipeline = null)
|
public function add($asset, $priority = null, $pipeline = true)
|
||||||
{
|
{
|
||||||
// More than one asset
|
// More than one asset
|
||||||
if (is_array($asset)) {
|
if (is_array($asset)) {
|
||||||
@@ -227,21 +236,22 @@ class Assets
|
|||||||
* It checks for duplicates.
|
* It checks for duplicates.
|
||||||
* You may add more than one asset passing an array as argument.
|
* You may add more than one asset passing an array as argument.
|
||||||
*
|
*
|
||||||
* @param mixed $asset
|
* @param mixed $asset
|
||||||
* @param int $priority the priority, bigger comes first
|
* @param int $priority the priority, bigger comes first
|
||||||
* @param bool $pipeline false if this should not be pipelined
|
* @param bool $pipeline false if this should not be pipelined
|
||||||
|
* @param null $group
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function addCss($asset, $priority = null, $pipeline = null)
|
public function addCss($asset, $priority = null, $pipeline = true, $group = null)
|
||||||
{
|
{
|
||||||
if (is_array($asset)) {
|
if (is_array($asset)) {
|
||||||
foreach ($asset as $a) {
|
foreach ($asset as $a) {
|
||||||
$this->addCss($a, $priority, $pipeline);
|
$this->addCss($a, $priority, $pipeline, $group);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
} elseif (isset($this->collections[$asset])) {
|
} elseif (isset($this->collections[$asset])) {
|
||||||
$this->add($this->collections[$asset], $priority, $pipeline);
|
$this->add($this->collections[$asset], $priority, $pipeline, $group);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,15 +259,20 @@ class Assets
|
|||||||
$asset = $this->buildLocalLink($asset);
|
$asset = $this->buildLocalLink($asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for existence
|
||||||
|
if ($asset === false) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'asset' => $asset,
|
'asset' => $asset,
|
||||||
'priority' => intval($priority ?: 10),
|
'priority' => intval($priority ?: 10),
|
||||||
'order' => count($this->css),
|
'order' => count($this->css),
|
||||||
'pipeline' => $pipeline ?: true
|
'pipeline' => (bool) $pipeline,
|
||||||
|
'group' => $group ?: 'head'
|
||||||
];
|
];
|
||||||
|
|
||||||
// check for dynamic array and merge with defaults
|
// check for dynamic array and merge with defaults
|
||||||
$count_args = func_num_args();
|
|
||||||
if (func_num_args() == 2) {
|
if (func_num_args() == 2) {
|
||||||
$dynamic_arg = func_get_arg(1);
|
$dynamic_arg = func_get_arg(1);
|
||||||
if (is_array($dynamic_arg)) {
|
if (is_array($dynamic_arg)) {
|
||||||
@@ -286,7 +301,7 @@ class Assets
|
|||||||
* @param string $group name of the group
|
* @param string $group name of the group
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function addJs($asset, $priority = null, $pipeline = null, $loading = null, $group = null)
|
public function addJs($asset, $priority = null, $pipeline = true, $loading = null, $group = null)
|
||||||
{
|
{
|
||||||
if (is_array($asset)) {
|
if (is_array($asset)) {
|
||||||
foreach ($asset as $a) {
|
foreach ($asset as $a) {
|
||||||
@@ -302,17 +317,21 @@ class Assets
|
|||||||
$asset = $this->buildLocalLink($asset);
|
$asset = $this->buildLocalLink($asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for existence
|
||||||
|
if ($asset === false) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'asset' => $asset,
|
'asset' => $asset,
|
||||||
'priority' => intval($priority ?: 10),
|
'priority' => intval($priority ?: 10),
|
||||||
'order' => count($this->js),
|
'order' => count($this->js),
|
||||||
'pipeline' => $pipeline ?: true,
|
'pipeline' => (bool) $pipeline,
|
||||||
'loading' => $loading ?: '',
|
'loading' => $loading ?: '',
|
||||||
'group' => $group ?: 'head'
|
'group' => $group ?: 'head'
|
||||||
];
|
];
|
||||||
|
|
||||||
// check for dynamic array and merge with defaults
|
// check for dynamic array and merge with defaults
|
||||||
$count_args = func_num_args();
|
|
||||||
if (func_num_args() == 2) {
|
if (func_num_args() == 2) {
|
||||||
$dynamic_arg = func_get_arg(1);
|
$dynamic_arg = func_get_arg(1);
|
||||||
if (is_array($dynamic_arg)) {
|
if (is_array($dynamic_arg)) {
|
||||||
@@ -340,7 +359,7 @@ class Assets
|
|||||||
*
|
*
|
||||||
* @return \Grav\Common\Assets
|
* @return \Grav\Common\Assets
|
||||||
*/
|
*/
|
||||||
public function addAsyncJs($asset, $priority = null, $pipeline = null, $group = null)
|
public function addAsyncJs($asset, $priority = null, $pipeline = true, $group = null)
|
||||||
{
|
{
|
||||||
return $this->addJs($asset, $priority, $pipeline, 'async', $group);
|
return $this->addJs($asset, $priority, $pipeline, 'async', $group);
|
||||||
}
|
}
|
||||||
@@ -357,7 +376,7 @@ class Assets
|
|||||||
*
|
*
|
||||||
* @return \Grav\Common\Assets
|
* @return \Grav\Common\Assets
|
||||||
*/
|
*/
|
||||||
public function addDeferJs($asset, $priority = null, $pipeline = null, $group = null)
|
public function addDeferJs($asset, $priority = null, $pipeline = true, $group = null)
|
||||||
{
|
{
|
||||||
return $this->addJs($asset, $priority, $pipeline, 'defer', $group);
|
return $this->addJs($asset, $priority, $pipeline, 'defer', $group);
|
||||||
}
|
}
|
||||||
@@ -369,20 +388,27 @@ class Assets
|
|||||||
* For adding chunks of string-based inline CSS
|
* For adding chunks of string-based inline CSS
|
||||||
*
|
*
|
||||||
* @param mixed $asset
|
* @param mixed $asset
|
||||||
* @param int $priority the priority, bigger comes first
|
* @param int $priority the priority, bigger comes first
|
||||||
|
* @param null $group
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function addInlineCss($asset, $priority = null)
|
public function addInlineCss($asset, $priority = null, $group = null)
|
||||||
{
|
{
|
||||||
|
$asset = trim($asset);
|
||||||
|
|
||||||
if (is_a($asset, 'Twig_Markup')) {
|
if (is_a($asset, 'Twig_Markup')) {
|
||||||
$asset = strip_tags((string)$asset);
|
preg_match(self::HTML_TAG_REGEX, $asset, $matches );
|
||||||
|
if (isset($matches[3])) {
|
||||||
|
$asset = $matches[3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'priority' => intval($priority ?: 10),
|
'priority' => intval($priority ?: 10),
|
||||||
'order' => count($this->inline_css),
|
'order' => count($this->inline_css),
|
||||||
'asset' => $asset
|
'asset' => $asset,
|
||||||
|
'group' => $group ?: 'head'
|
||||||
];
|
];
|
||||||
|
|
||||||
// check for dynamic array and merge with defaults
|
// check for dynamic array and merge with defaults
|
||||||
@@ -395,7 +421,7 @@ class Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
$key = md5($asset);
|
$key = md5($asset);
|
||||||
if (is_string($asset) && !array_key_exists($key, $this->inline_css)) {
|
if ($asset && is_string($asset) && !array_key_exists($key, $this->inline_css)) {
|
||||||
$this->inline_css[$key] = $data;
|
$this->inline_css[$key] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,8 +442,13 @@ class Assets
|
|||||||
*/
|
*/
|
||||||
public function addInlineJs($asset, $priority = null, $group = null)
|
public function addInlineJs($asset, $priority = null, $group = null)
|
||||||
{
|
{
|
||||||
|
$asset = trim($asset);
|
||||||
|
|
||||||
if (is_a($asset, 'Twig_Markup')) {
|
if (is_a($asset, 'Twig_Markup')) {
|
||||||
$asset = strip_tags((string)$asset);
|
preg_match(self::HTML_TAG_REGEX, $asset, $matches );
|
||||||
|
if (isset($matches[3])) {
|
||||||
|
$asset = $matches[3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
@@ -437,7 +468,7 @@ class Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
$key = md5($asset);
|
$key = md5($asset);
|
||||||
if (is_string($asset) && !array_key_exists($key, $this->inline_js)) {
|
if ($asset && is_string($asset) && !array_key_exists($key, $this->inline_js)) {
|
||||||
$this->inline_js[$key] = $data;
|
$this->inline_js[$key] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,26 +478,27 @@ class Assets
|
|||||||
/**
|
/**
|
||||||
* Build the CSS link tags.
|
* Build the CSS link tags.
|
||||||
*
|
*
|
||||||
|
* @param string $group name of the group
|
||||||
* @param array $attributes
|
* @param array $attributes
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function css($attributes = [])
|
public function css($group = 'head', $attributes = [])
|
||||||
{
|
{
|
||||||
if (!$this->css) {
|
if (!$this->css && !$this->inline_css) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort array by priorities (larger priority first)
|
// Sort array by priorities (larger priority first)
|
||||||
if (self::getGrav()) {
|
if (self::getGrav()) {
|
||||||
usort($this->css, function ($a, $b) {
|
uasort($this->css, function ($a, $b) {
|
||||||
if ($a['priority'] == $b['priority']) {
|
if ($a['priority'] == $b['priority']) {
|
||||||
return $b['order'] - $a['order'];
|
return $b['order'] - $a['order'];
|
||||||
}
|
}
|
||||||
return $a['priority'] - $b['priority'];
|
return $a['priority'] - $b['priority'];
|
||||||
});
|
});
|
||||||
|
|
||||||
usort($this->inline_css, function ($a, $b) {
|
uasort($this->inline_css, function ($a, $b) {
|
||||||
if ($a['priority'] == $b['priority']) {
|
if ($a['priority'] == $b['priority']) {
|
||||||
return $b['order'] - $a['order'];
|
return $b['order'] - $a['order'];
|
||||||
}
|
}
|
||||||
@@ -479,29 +511,37 @@ class Assets
|
|||||||
$attributes = $this->attributes(array_merge(['type' => 'text/css', 'rel' => 'stylesheet'], $attributes));
|
$attributes = $this->attributes(array_merge(['type' => 'text/css', 'rel' => 'stylesheet'], $attributes));
|
||||||
|
|
||||||
$output = '';
|
$output = '';
|
||||||
|
$inline_css = '';
|
||||||
|
|
||||||
if ($this->css_pipeline) {
|
if ($this->css_pipeline) {
|
||||||
$pipeline_result = $this->pipelineCss();
|
$pipeline_result = $this->pipelineCss($group);
|
||||||
if ($pipeline_result) {
|
if ($pipeline_result) {
|
||||||
$output .= '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n";
|
$output .= '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n";
|
||||||
}
|
}
|
||||||
foreach ($this->css_no_pipeline as $file) {
|
foreach ($this->css_no_pipeline as $file) {
|
||||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
if ($group && $file['group'] == $group) {
|
||||||
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
|
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||||
|
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($this->css as $file) {
|
foreach ($this->css as $file) {
|
||||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
if ($group && $file['group'] == $group) {
|
||||||
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
|
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||||
|
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Inline CSS
|
// Render Inline CSS
|
||||||
if (count($this->inline_css) > 0) {
|
foreach ($this->inline_css as $inline) {
|
||||||
$output .= "<style>\n";
|
if ($group && $inline['group'] == $group) {
|
||||||
foreach ($this->inline_css as $inline) {
|
$inline_css .= $inline['asset'] . "\n";
|
||||||
$output .= $inline['asset'] . "\n";
|
|
||||||
}
|
}
|
||||||
$output .= "</style>\n";
|
}
|
||||||
|
|
||||||
|
if ($inline_css) {
|
||||||
|
$output .= "\n<style>\n" . $inline_css . "\n</style>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -518,19 +558,19 @@ class Assets
|
|||||||
*/
|
*/
|
||||||
public function js($group = 'head', $attributes = [])
|
public function js($group = 'head', $attributes = [])
|
||||||
{
|
{
|
||||||
if (!$this->js) {
|
if (!$this->js && !$this->inline_js) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort array by priorities (larger priority first)
|
// Sort array by priorities (larger priority first)
|
||||||
usort($this->js, function ($a, $b) {
|
uasort($this->js, function ($a, $b) {
|
||||||
if ($a['priority'] == $b['priority']) {
|
if ($a['priority'] == $b['priority']) {
|
||||||
return $b['order'] - $a['order'];
|
return $b['order'] - $a['order'];
|
||||||
}
|
}
|
||||||
return $a['priority'] - $b['priority'];
|
return $a['priority'] - $b['priority'];
|
||||||
});
|
});
|
||||||
|
|
||||||
usort($this->inline_js, function ($a, $b) {
|
uasort($this->inline_js, function ($a, $b) {
|
||||||
if ($a['priority'] == $b['priority']) {
|
if ($a['priority'] == $b['priority']) {
|
||||||
return $b['order'] - $a['order'];
|
return $b['order'] - $a['order'];
|
||||||
}
|
}
|
||||||
@@ -582,7 +622,7 @@ class Assets
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function pipelineCss()
|
protected function pipelineCss($group = 'head')
|
||||||
{
|
{
|
||||||
/** @var Cache $cache */
|
/** @var Cache $cache */
|
||||||
$cache = self::getGrav()['cache'];
|
$cache = self::getGrav()['cache'];
|
||||||
@@ -594,10 +634,10 @@ class Assets
|
|||||||
// clear no-pipeline assets lists
|
// clear no-pipeline assets lists
|
||||||
$this->css_no_pipeline = [];
|
$this->css_no_pipeline = [];
|
||||||
|
|
||||||
$file = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite) . '.css';
|
$file = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite . $group) . '.css';
|
||||||
|
|
||||||
$relative_path = "{$this->base_url}" . basename(ASSETS_DIR) . "/{$file}";
|
$relative_path = "{$this->base_url}{$this->assets_url}/{$file}";
|
||||||
$absolute_path = ASSETS_DIR . $file;
|
$absolute_path = $this->assets_dir . $file;
|
||||||
|
|
||||||
// If pipeline exist return it
|
// If pipeline exist return it
|
||||||
if (file_exists($absolute_path)) {
|
if (file_exists($absolute_path)) {
|
||||||
@@ -606,10 +646,12 @@ class Assets
|
|||||||
|
|
||||||
// Remove any non-pipeline files
|
// Remove any non-pipeline files
|
||||||
foreach ($this->css as $id => $asset) {
|
foreach ($this->css as $id => $asset) {
|
||||||
if (!$asset['pipeline']) {
|
if ($asset['group'] == $group) {
|
||||||
$this->css_no_pipeline[$id] = $asset;
|
if (!$asset['pipeline']) {
|
||||||
} else {
|
$this->css_no_pipeline[$id] = $asset;
|
||||||
$temp_css[$id] = $asset;
|
} else {
|
||||||
|
$temp_css[$id] = $asset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,8 +704,8 @@ class Assets
|
|||||||
|
|
||||||
$file = md5(json_encode($this->js) . $this->js_minify . $group) . '.js';
|
$file = md5(json_encode($this->js) . $this->js_minify . $group) . '.js';
|
||||||
|
|
||||||
$relative_path = "{$this->base_url}" . basename(ASSETS_DIR) . "/{$file}";
|
$relative_path = "{$this->base_url}{$this->assets_url}/{$file}";
|
||||||
$absolute_path = ASSETS_DIR . $file;
|
$absolute_path = $this->assets_dir . $file;
|
||||||
|
|
||||||
// If pipeline exist return it
|
// If pipeline exist return it
|
||||||
if (file_exists($absolute_path)) {
|
if (file_exists($absolute_path)) {
|
||||||
@@ -825,12 +867,12 @@ class Assets
|
|||||||
public function addDir($directory, $pattern = self::DEFAULT_REGEX)
|
public function addDir($directory, $pattern = self::DEFAULT_REGEX)
|
||||||
{
|
{
|
||||||
// Check if public_dir exists
|
// Check if public_dir exists
|
||||||
if (!is_dir(ASSETS_DIR)) {
|
if (!is_dir($this->assets_dir)) {
|
||||||
throw new Exception('Assets: Public dir not found');
|
throw new Exception('Assets: Public dir not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get files
|
// Get files
|
||||||
$files = $this->rglob(ASSETS_DIR . DIRECTORY_SEPARATOR . $directory, $pattern, ASSETS_DIR);
|
$files = $this->rglob($this->assets_dir . DIRECTORY_SEPARATOR . $directory, $pattern, $this->assets_dir);
|
||||||
|
|
||||||
// No luck? Nothing to do
|
// No luck? Nothing to do
|
||||||
if (!$files) {
|
if (!$files) {
|
||||||
@@ -930,6 +972,7 @@ class Assets
|
|||||||
* Download and concatenate the content of several links.
|
* Download and concatenate the content of several links.
|
||||||
*
|
*
|
||||||
* @param array $links
|
* @param array $links
|
||||||
|
* @param bool $css
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -960,7 +1003,12 @@ class Assets
|
|||||||
$link = ROOT_DIR . $relative_path;
|
$link = ROOT_DIR . $relative_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
$file = ($this->fetch_command instanceof Closure) ? $this->fetch_command->__invoke($link) : file_get_contents($link);
|
$file = ($this->fetch_command instanceof Closure) ? @$this->fetch_command->__invoke($link) : @file_get_contents($link);
|
||||||
|
|
||||||
|
// No file found, skip it...
|
||||||
|
if ($file === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Double check last character being
|
// Double check last character being
|
||||||
if (!$css) {
|
if (!$css) {
|
||||||
@@ -1084,6 +1132,36 @@ class Assets
|
|||||||
return $this->addDir($directory, self::JS_REGEX);
|
return $this->addDir($directory, self::JS_REGEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of CSS Pipeline
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
*/
|
||||||
|
public function setCssPipeline($value)
|
||||||
|
{
|
||||||
|
$this->css_pipeline = (bool) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of JS Pipeline
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
*/
|
||||||
|
public function setJsPipeline($value)
|
||||||
|
{
|
||||||
|
$this->js_pipeline = (bool) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly set's a timestamp for assets
|
||||||
|
*
|
||||||
|
* @param $value
|
||||||
|
*/
|
||||||
|
public function setTimestamp($value)
|
||||||
|
{
|
||||||
|
$this->timestamp = '?'.$value;
|
||||||
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ class ZipBackup
|
|||||||
$zip = new \ZipArchive();
|
$zip = new \ZipArchive();
|
||||||
$zip->open($destination, \ZipArchive::CREATE);
|
$zip->open($destination, \ZipArchive::CREATE);
|
||||||
|
|
||||||
|
$max_execution_time = ini_set('max_execution_time', 600);
|
||||||
|
|
||||||
static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager);
|
static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager);
|
||||||
|
|
||||||
$messager && $messager([
|
$messager && $messager([
|
||||||
@@ -85,6 +87,10 @@ class ZipBackup
|
|||||||
|
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
|
if ($max_execution_time !== false) {
|
||||||
|
ini_set('max_execution_time', $max_execution_time);
|
||||||
|
}
|
||||||
|
|
||||||
return $destination;
|
return $destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ use Grav\Common\Filesystem\Folder;
|
|||||||
*/
|
*/
|
||||||
class Cache extends Getters
|
class Cache extends Getters
|
||||||
{
|
{
|
||||||
|
use GravTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Cache key.
|
* @var string Cache key.
|
||||||
*/
|
*/
|
||||||
@@ -36,6 +38,10 @@ class Cache extends Getters
|
|||||||
*/
|
*/
|
||||||
protected $driver;
|
protected $driver;
|
||||||
|
|
||||||
|
protected $driver_name;
|
||||||
|
|
||||||
|
protected $driver_setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
@@ -44,30 +50,30 @@ class Cache extends Getters
|
|||||||
protected $cache_dir;
|
protected $cache_dir;
|
||||||
|
|
||||||
protected static $standard_remove = [
|
protected static $standard_remove = [
|
||||||
'cache/twig/',
|
'cache://twig/',
|
||||||
'cache/doctrine/',
|
'cache://doctrine/',
|
||||||
'cache/compiled/',
|
'cache://compiled/',
|
||||||
'cache/validated-',
|
'cache://validated-',
|
||||||
'images/',
|
'cache://images',
|
||||||
'assets/',
|
'asset://',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $all_remove = [
|
protected static $all_remove = [
|
||||||
'cache/',
|
'cache://',
|
||||||
'images/',
|
'cache://images',
|
||||||
'assets/'
|
'asset://'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $assets_remove = [
|
protected static $assets_remove = [
|
||||||
'assets/'
|
'asset://'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $images_remove = [
|
protected static $images_remove = [
|
||||||
'images/'
|
'cache://images'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $cache_remove = [
|
protected static $cache_remove = [
|
||||||
'cache/'
|
'cache://'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,10 +110,16 @@ class Cache extends Getters
|
|||||||
// Cache key allows us to invalidate all cache on configuration changes.
|
// Cache key allows us to invalidate all cache on configuration changes.
|
||||||
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
|
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
|
||||||
|
|
||||||
|
$this->driver_setting = $this->config->get('system.cache.driver');
|
||||||
|
|
||||||
$this->driver = $this->getCacheDriver();
|
$this->driver = $this->getCacheDriver();
|
||||||
|
|
||||||
// Set the cache namespace to our unique key
|
// Set the cache namespace to our unique key
|
||||||
$this->driver->setNamespace($this->key);
|
$this->driver->setNamespace($this->key);
|
||||||
|
|
||||||
|
// Dump Cache state
|
||||||
|
$grav['debugger']->addMessage('Cache: [' . ($this->enabled ? 'true' : 'false') . '] Setting: [' . $this->driver_setting . '] Driver: [' . $this->driver_name . ']');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,11 +131,13 @@ class Cache extends Getters
|
|||||||
*/
|
*/
|
||||||
public function getCacheDriver()
|
public function getCacheDriver()
|
||||||
{
|
{
|
||||||
$setting = $this->config->get('system.cache.driver');
|
$setting = $this->driver_setting;
|
||||||
$driver_name = 'file';
|
$driver_name = 'file';
|
||||||
|
|
||||||
if (!$setting || $setting == 'auto') {
|
if (!$setting || $setting == 'auto') {
|
||||||
if (extension_loaded('apc')) {
|
if (extension_loaded('apcu')) {
|
||||||
|
$driver_name = 'apcu';
|
||||||
|
} elseif (extension_loaded('apc')) {
|
||||||
$driver_name = 'apc';
|
$driver_name = 'apc';
|
||||||
} elseif (extension_loaded('wincache')) {
|
} elseif (extension_loaded('wincache')) {
|
||||||
$driver_name = 'wincache';
|
$driver_name = 'wincache';
|
||||||
@@ -134,11 +148,17 @@ class Cache extends Getters
|
|||||||
$driver_name = $setting;
|
$driver_name = $setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->driver_name = $driver_name;
|
||||||
|
|
||||||
switch ($driver_name) {
|
switch ($driver_name) {
|
||||||
case 'apc':
|
case 'apc':
|
||||||
$driver = new \Doctrine\Common\Cache\ApcCache();
|
$driver = new \Doctrine\Common\Cache\ApcCache();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'apcu':
|
||||||
|
$driver = new \Doctrine\Common\Cache\ApcuCache();
|
||||||
|
break;
|
||||||
|
|
||||||
case 'wincache':
|
case 'wincache':
|
||||||
$driver = new \Doctrine\Common\Cache\WinCacheCache();
|
$driver = new \Doctrine\Common\Cache\WinCacheCache();
|
||||||
break;
|
break;
|
||||||
@@ -221,7 +241,7 @@ class Cache extends Getters
|
|||||||
*/
|
*/
|
||||||
public static function clearCache($remove = 'standard')
|
public static function clearCache($remove = 'standard')
|
||||||
{
|
{
|
||||||
|
$locator = self::getGrav()['locator'];
|
||||||
$output = [];
|
$output = [];
|
||||||
$user_config = USER_DIR . 'config/system.yaml';
|
$user_config = USER_DIR . 'config/system.yaml';
|
||||||
|
|
||||||
@@ -243,10 +263,16 @@ class Cache extends Getters
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach ($remove_paths as $path) {
|
foreach ($remove_paths as $stream) {
|
||||||
|
|
||||||
|
// Convert stream to a real path
|
||||||
|
$path = $locator->findResource($stream, true, true);
|
||||||
|
// Make sure path exists before proceeding, otherwise we would wipe ROOT_DIR
|
||||||
|
if (!$path)
|
||||||
|
throw new \RuntimeException("Stream '{$stream}' not found", 500);
|
||||||
|
|
||||||
$anything = false;
|
$anything = false;
|
||||||
$files = glob(ROOT_DIR . $path . '*');
|
$files = glob($path . '/*');
|
||||||
|
|
||||||
if (is_array($files)) {
|
if (is_array($files)) {
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
@@ -263,7 +289,7 @@ class Cache extends Getters
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($anything) {
|
if ($anything) {
|
||||||
$output[] = '<red>Cleared: </red>' . $path . '*';
|
$output[] = '<red>Cleared: </red>' . $path . '/*';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Grav\Common\Config;
|
|
||||||
|
|
||||||
use Grav\Common\File\CompiledYamlFile;
|
|
||||||
use Grav\Common\Grav;
|
|
||||||
use Grav\Common\Filesystem\Folder;
|
|
||||||
use RocketTheme\Toolbox\Blueprints\Blueprints as BaseBlueprints;
|
|
||||||
use RocketTheme\Toolbox\File\PhpFile;
|
|
||||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Blueprints class contains configuration rules.
|
|
||||||
*
|
|
||||||
* @author RocketTheme
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
class Blueprints extends BaseBlueprints
|
|
||||||
{
|
|
||||||
protected $grav;
|
|
||||||
protected $files = [];
|
|
||||||
protected $blueprints;
|
|
||||||
|
|
||||||
public function __construct(array $serialized = null, Grav $grav = null)
|
|
||||||
{
|
|
||||||
parent::__construct($serialized);
|
|
||||||
$this->grav = $grav ?: Grav::instance();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
/** @var UniformResourceLocator $locator */
|
|
||||||
$locator = $this->grav['locator'];
|
|
||||||
|
|
||||||
$blueprints = $locator->findResources('blueprints://config');
|
|
||||||
$plugins = $locator->findResources('plugins://');
|
|
||||||
|
|
||||||
$blueprintFiles = $this->getBlueprintFiles($blueprints, $plugins);
|
|
||||||
|
|
||||||
$this->loadCompiledBlueprints($plugins + $blueprints, $blueprintFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function loadCompiledBlueprints($blueprints, $blueprintFiles)
|
|
||||||
{
|
|
||||||
$checksum = md5(serialize($blueprints));
|
|
||||||
$filename = CACHE_DIR . 'compiled/blueprints/' . $checksum .'.php';
|
|
||||||
$checksum .= ':'.md5(serialize($blueprintFiles));
|
|
||||||
$class = get_class($this);
|
|
||||||
$file = PhpFile::instance($filename);
|
|
||||||
|
|
||||||
if ($file->exists()) {
|
|
||||||
$cache = $file->exists() ? $file->content() : null;
|
|
||||||
} else {
|
|
||||||
$cache = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Load real file if cache isn't up to date (or is invalid).
|
|
||||||
if (
|
|
||||||
!is_array($cache)
|
|
||||||
|| empty($cache['checksum'])
|
|
||||||
|| empty($cache['$class'])
|
|
||||||
|| $cache['checksum'] != $checksum
|
|
||||||
|| $cache['@class'] != $class
|
|
||||||
) {
|
|
||||||
// Attempt to lock the file for writing.
|
|
||||||
$file->lock(false);
|
|
||||||
|
|
||||||
// Load blueprints.
|
|
||||||
$this->blueprints = new Blueprints();
|
|
||||||
foreach ($blueprintFiles as $key => $files) {
|
|
||||||
$this->loadBlueprints($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache = [
|
|
||||||
'@class' => $class,
|
|
||||||
'checksum' => $checksum,
|
|
||||||
'files' => $blueprintFiles,
|
|
||||||
'data' => $this->blueprints->toArray()
|
|
||||||
];
|
|
||||||
|
|
||||||
// If compiled file wasn't already locked by another process, save it.
|
|
||||||
if ($file->locked() !== false) {
|
|
||||||
$file->save($cache);
|
|
||||||
$file->unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->blueprints = new Blueprints($cache['data']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load global blueprints.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param array $files
|
|
||||||
*/
|
|
||||||
public function loadBlueprints($key, array $files = null)
|
|
||||||
{
|
|
||||||
if (is_null($files)) {
|
|
||||||
$files = $this->files[$key];
|
|
||||||
}
|
|
||||||
foreach ($files as $name => $item) {
|
|
||||||
$file = CompiledYamlFile::instance($item['file']);
|
|
||||||
$this->blueprints->embed($name, $file->content(), '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all blueprint files (including plugins).
|
|
||||||
*
|
|
||||||
* @param array $blueprints
|
|
||||||
* @param array $plugins
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getBlueprintFiles(array $blueprints, array $plugins)
|
|
||||||
{
|
|
||||||
$list = [];
|
|
||||||
foreach (array_reverse($plugins) as $folder) {
|
|
||||||
$list += $this->detectPlugins($folder, true);
|
|
||||||
}
|
|
||||||
foreach (array_reverse($blueprints) as $folder) {
|
|
||||||
$list += $this->detectConfig($folder, true);
|
|
||||||
}
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects all plugins with a configuration file and returns last modification time.
|
|
||||||
*
|
|
||||||
* @param string $lookup Location to look up from.
|
|
||||||
* @param bool $blueprints
|
|
||||||
* @return array
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
protected function detectPlugins($lookup = SYSTEM_DIR, $blueprints = false)
|
|
||||||
{
|
|
||||||
$find = $blueprints ? 'blueprints.yaml' : '.yaml';
|
|
||||||
$location = $blueprints ? 'blueprintFiles' : 'configFiles';
|
|
||||||
$path = trim(Folder::getRelativePath($lookup), '/');
|
|
||||||
if (isset($this->{$location}[$path])) {
|
|
||||||
return [$path => $this->{$location}[$path]];
|
|
||||||
}
|
|
||||||
|
|
||||||
$list = [];
|
|
||||||
|
|
||||||
if (is_dir($lookup)) {
|
|
||||||
$iterator = new \DirectoryIterator($lookup);
|
|
||||||
|
|
||||||
/** @var \DirectoryIterator $directory */
|
|
||||||
foreach ($iterator as $directory) {
|
|
||||||
if (!$directory->isDir() || $directory->isDot()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $directory->getBasename();
|
|
||||||
$filename = "{$path}/{$name}/" . ($find && $find[0] != '.' ? $find : $name . $find);
|
|
||||||
|
|
||||||
if (is_file($filename)) {
|
|
||||||
$list["plugins/{$name}"] = ['file' => $filename, 'modified' => filemtime($filename)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->{$location}[$path] = $list;
|
|
||||||
|
|
||||||
return [$path => $list];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects all plugins with a configuration file and returns last modification time.
|
|
||||||
*
|
|
||||||
* @param string $lookup Location to look up from.
|
|
||||||
* @param bool $blueprints
|
|
||||||
* @return array
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
protected function detectConfig($lookup = SYSTEM_DIR, $blueprints = false)
|
|
||||||
{
|
|
||||||
$location = $blueprints ? 'blueprintFiles' : 'configFiles';
|
|
||||||
$path = trim(Folder::getRelativePath($lookup), '/');
|
|
||||||
if (isset($this->{$location}[$path])) {
|
|
||||||
return [$path => $this->{$location}[$path]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($lookup)) {
|
|
||||||
// Find all system and user configuration files.
|
|
||||||
$options = [
|
|
||||||
'compare' => 'Filename',
|
|
||||||
'pattern' => '|\.yaml$|',
|
|
||||||
'filters' => [
|
|
||||||
'key' => '|\.yaml$|',
|
|
||||||
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
|
|
||||||
return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
|
|
||||||
}],
|
|
||||||
'key' => 'SubPathname'
|
|
||||||
];
|
|
||||||
|
|
||||||
$list = Folder::all($lookup, $options);
|
|
||||||
} else {
|
|
||||||
$list = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->{$location}[$path] = $list;
|
|
||||||
|
|
||||||
return [$path => $list];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
238
system/src/Grav/Common/Config/CompiledBase.php
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use RocketTheme\Toolbox\File\PhpFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compiled base class.
|
||||||
|
*/
|
||||||
|
abstract class CompiledBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Version number for the compiled file.
|
||||||
|
*/
|
||||||
|
public $version = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Filename (base name) of the compiled configuration.
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|bool Configuration checksum.
|
||||||
|
*/
|
||||||
|
public $checksum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Cache folder to be used.
|
||||||
|
*/
|
||||||
|
protected $cacheFolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array List of files to load.
|
||||||
|
*/
|
||||||
|
protected $files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed Configuration object.
|
||||||
|
*/
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $cacheFolder Cache folder to be used.
|
||||||
|
* @param array $files List of files as returned from ConfigFileFinder class.
|
||||||
|
* @param string $path Base path for the file list.
|
||||||
|
* @throws \BadMethodCallException
|
||||||
|
*/
|
||||||
|
public function __construct($cacheFolder, array $files, $path)
|
||||||
|
{
|
||||||
|
if (!$cacheFolder) {
|
||||||
|
throw new \BadMethodCallException('Cache folder not defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheFolder = $cacheFolder;
|
||||||
|
$this->files = $files;
|
||||||
|
$this->path = $path ? rtrim($path, '\\/') . '/' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get filename for the compiled PHP file.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function name($name = null)
|
||||||
|
{
|
||||||
|
if (!$this->name) {
|
||||||
|
$this->name = $name ?: md5(json_encode(array_keys($this->files)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function gets called when cached configuration is saved.
|
||||||
|
*/
|
||||||
|
public function modified() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the configuration.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function load()
|
||||||
|
{
|
||||||
|
if ($this->object) {
|
||||||
|
return $this->object;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = $this->createFilename();
|
||||||
|
if (!$this->loadCompiledFile($filename) && $this->loadFiles()) {
|
||||||
|
$this->saveCompiledFile($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns checksum from the configuration files.
|
||||||
|
*
|
||||||
|
* You can set $this->checksum = false to disable this check.
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function checksum()
|
||||||
|
{
|
||||||
|
if (!isset($this->checksum)) {
|
||||||
|
$this->checksum = md5(json_encode($this->files) . $this->version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createFilename()
|
||||||
|
{
|
||||||
|
return "{$this->cacheFolder}/{$this->name()->name}.php";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create configuration object.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
abstract protected function createObject(array $data = []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize configuration object.
|
||||||
|
*/
|
||||||
|
abstract protected function finalizeObject();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
abstract protected function loadFile($name, $filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load and join all configuration files.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function loadFiles()
|
||||||
|
{
|
||||||
|
$this->createObject();
|
||||||
|
|
||||||
|
$list = array_reverse($this->files);
|
||||||
|
foreach ($list as $files) {
|
||||||
|
foreach ($files as $name => $item) {
|
||||||
|
$this->loadFile($name, $this->path . $item['file']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->finalizeObject();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load compiled file.
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function loadCompiledFile($filename)
|
||||||
|
{
|
||||||
|
if (!file_exists($filename)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = include $filename;
|
||||||
|
if (
|
||||||
|
!is_array($cache)
|
||||||
|
|| !isset($cache['checksum'])
|
||||||
|
|| !isset($cache['data'])
|
||||||
|
|| !isset($cache['@class'])
|
||||||
|
|| $cache['@class'] != get_class($this)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load real file if cache isn't up to date (or is invalid).
|
||||||
|
if ($cache['checksum'] !== $this->checksum()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->createObject($cache['data']);
|
||||||
|
|
||||||
|
$this->finalizeObject();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save compiled file.
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
* @throws \RuntimeException
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function saveCompiledFile($filename)
|
||||||
|
{
|
||||||
|
$file = PhpFile::instance($filename);
|
||||||
|
|
||||||
|
// Attempt to lock the file for writing.
|
||||||
|
try {
|
||||||
|
$file->lock(false);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Another process has locked the file; we will check this in a bit.
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file->locked() === false) {
|
||||||
|
// File was already locked by another process.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = [
|
||||||
|
'@class' => get_class($this),
|
||||||
|
'timestamp' => time(),
|
||||||
|
'checksum' => $this->checksum(),
|
||||||
|
'files' => $this->files,
|
||||||
|
'data' => $this->object->toArray()
|
||||||
|
];
|
||||||
|
|
||||||
|
$file->save($cache);
|
||||||
|
$file->unlock();
|
||||||
|
$file->free();
|
||||||
|
|
||||||
|
$this->modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
system/src/Grav/Common/Config/CompiledBlueprints.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use Grav\Common\File\CompiledYamlFile;
|
||||||
|
use RocketTheme\Toolbox\Blueprints\Blueprints;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compiled Blueprints class.
|
||||||
|
*/
|
||||||
|
class CompiledBlueprints extends CompiledBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Version number for the compiled file.
|
||||||
|
*/
|
||||||
|
public $version = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Blueprints Blueprints object.
|
||||||
|
*/
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create configuration object.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
protected function createObject(array $data = [])
|
||||||
|
{
|
||||||
|
$this->object = new Blueprints($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize configuration object.
|
||||||
|
*/
|
||||||
|
protected function finalizeObject() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
protected function loadFile($name, $filename)
|
||||||
|
{
|
||||||
|
$file = CompiledYamlFile::instance($filename);
|
||||||
|
$this->object->embed($name, $file->content(), '/');
|
||||||
|
$file->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
98
system/src/Grav/Common/Config/CompiledConfig.php
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use Grav\Common\File\CompiledYamlFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compiled Configuration class.
|
||||||
|
*/
|
||||||
|
class CompiledConfig extends CompiledBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Version number for the compiled file.
|
||||||
|
*/
|
||||||
|
public $version = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Config Configuration object.
|
||||||
|
*/
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var callable Blueprints loader.
|
||||||
|
*/
|
||||||
|
protected $callable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $withDefaults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set blueprints for the configuration.
|
||||||
|
*
|
||||||
|
* @param callable $blueprints
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setBlueprints(callable $blueprints)
|
||||||
|
{
|
||||||
|
$this->callable = $blueprints;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $withDefaults
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function load($withDefaults = false)
|
||||||
|
{
|
||||||
|
$this->withDefaults = $withDefaults;
|
||||||
|
|
||||||
|
return parent::load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create configuration object.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
protected function createObject(array $data = [])
|
||||||
|
{
|
||||||
|
if ($this->withDefaults && empty($data) && is_callable($this->callable)) {
|
||||||
|
$blueprints = $this->callable;
|
||||||
|
$data = $blueprints()->getDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->object = new Config($data, $this->callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize configuration object.
|
||||||
|
*/
|
||||||
|
protected function finalizeObject()
|
||||||
|
{
|
||||||
|
$this->object->checksum($this->checksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function gets called when cached configuration is saved.
|
||||||
|
*/
|
||||||
|
public function modified()
|
||||||
|
{
|
||||||
|
$this->object->modified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
protected function loadFile($name, $filename)
|
||||||
|
{
|
||||||
|
$file = CompiledYamlFile::instance($filename);
|
||||||
|
$this->object->join($name, $file->content(), '/');
|
||||||
|
$file->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
64
system/src/Grav/Common/Config/CompiledLanguages.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use Grav\Common\File\CompiledYamlFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compiled Languages class.
|
||||||
|
*/
|
||||||
|
class CompiledLanguages extends CompiledBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Version number for the compiled file.
|
||||||
|
*/
|
||||||
|
public $version = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Languages Configuration object.
|
||||||
|
*/
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create configuration object.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
protected function createObject(array $data = [])
|
||||||
|
{
|
||||||
|
$this->object = new Languages($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize configuration object.
|
||||||
|
*/
|
||||||
|
protected function finalizeObject()
|
||||||
|
{
|
||||||
|
$this->object->checksum($this->checksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function gets called when cached configuration is saved.
|
||||||
|
*/
|
||||||
|
public function modified()
|
||||||
|
{
|
||||||
|
$this->object->modified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
protected function loadFile($name, $filename)
|
||||||
|
{
|
||||||
|
$file = CompiledYamlFile::instance($filename);
|
||||||
|
if (preg_match('|languages\.yaml$|', $filename)) {
|
||||||
|
$this->object->mergeRecursive($file->content());
|
||||||
|
} else {
|
||||||
|
$this->object->join($name, $file->content(), '/');
|
||||||
|
}
|
||||||
|
$file->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\Config;
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
use Grav\Common\File\CompiledYamlFile;
|
use Grav\Common\Debugger;
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
use Grav\Common\Data\Data;
|
use Grav\Common\Data\Data;
|
||||||
use RocketTheme\Toolbox\Blueprints\Blueprints;
|
use Grav\Common\Service\ConfigServiceProvider;
|
||||||
use RocketTheme\Toolbox\File\PhpFile;
|
|
||||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Config class contains configuration information.
|
* The Config class contains configuration information.
|
||||||
@@ -16,464 +14,84 @@ use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
|||||||
*/
|
*/
|
||||||
class Config extends Data
|
class Config extends Data
|
||||||
{
|
{
|
||||||
protected $grav;
|
|
||||||
protected $streams = [
|
|
||||||
'system' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['system'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'user' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'blueprints' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://blueprints', 'system/blueprints'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'config' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://config', 'system/config'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'plugins' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://plugins'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'plugin' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://plugins'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'themes' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://themes'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'languages' => [
|
|
||||||
'type' => 'ReadOnlyStream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['user://languages', 'system/languages'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'cache' => [
|
|
||||||
'type' => 'Stream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['cache'],
|
|
||||||
'images' => ['images']
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'log' => [
|
|
||||||
'type' => 'Stream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['logs']
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'backup' => [
|
|
||||||
'type' => 'Stream',
|
|
||||||
'prefixes' => [
|
|
||||||
'' => ['backup']
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $setup = [];
|
|
||||||
|
|
||||||
protected $blueprintFiles = [];
|
|
||||||
protected $configFiles = [];
|
|
||||||
protected $languageFiles = [];
|
|
||||||
protected $checksum;
|
protected $checksum;
|
||||||
protected $timestamp;
|
protected $modified = false;
|
||||||
|
|
||||||
protected $configLookup;
|
|
||||||
protected $blueprintLookup;
|
|
||||||
protected $pluginLookup;
|
|
||||||
protected $languagesLookup;
|
|
||||||
|
|
||||||
protected $finder;
|
|
||||||
protected $environment;
|
|
||||||
protected $messages = [];
|
|
||||||
|
|
||||||
protected $languages;
|
|
||||||
|
|
||||||
public function __construct(array $setup = array(), Grav $grav = null, $environment = null)
|
|
||||||
{
|
|
||||||
$this->grav = $grav ?: Grav::instance();
|
|
||||||
$this->finder = new ConfigFinder;
|
|
||||||
$this->environment = $environment ?: 'localhost';
|
|
||||||
$this->messages[] = 'Environment Name: ' . $this->environment;
|
|
||||||
|
|
||||||
// Make sure that
|
|
||||||
if (!isset($setup['streams']['schemes'])) {
|
|
||||||
$setup['streams']['schemes'] = [];
|
|
||||||
}
|
|
||||||
$setup['streams']['schemes'] += $this->streams;
|
|
||||||
|
|
||||||
$setup = $this->autoDetectEnvironmentConfig($setup);
|
|
||||||
|
|
||||||
$this->setup = $setup;
|
|
||||||
parent::__construct($setup);
|
|
||||||
|
|
||||||
$this->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function key()
|
public function key()
|
||||||
{
|
{
|
||||||
return $this->checksum();
|
return $this->checksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reload()
|
public function checksum($checksum = null)
|
||||||
{
|
{
|
||||||
$this->items = $this->setup;
|
if ($checksum !== null) {
|
||||||
$this->check();
|
$this->checksum = $checksum;
|
||||||
$this->init();
|
|
||||||
$this->debug();
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function check()
|
|
||||||
{
|
|
||||||
$streams = isset($this->items['streams']['schemes']) ? $this->items['streams']['schemes'] : null;
|
|
||||||
if (!is_array($streams)) {
|
|
||||||
throw new \InvalidArgumentException('Configuration is missing streams.schemes!');
|
|
||||||
}
|
|
||||||
$diff = array_keys(array_diff_key($this->streams, $streams));
|
|
||||||
if ($diff) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
sprintf('Configuration is missing keys %s from streams.schemes!', implode(', ', $diff))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function debug()
|
|
||||||
{
|
|
||||||
foreach ($this->messages as $message) {
|
|
||||||
$this->grav['debugger']->addMessage($message);
|
|
||||||
}
|
|
||||||
$this->messages = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
/** @var UniformResourceLocator $locator */
|
|
||||||
$locator = $this->grav['locator'];
|
|
||||||
|
|
||||||
$this->configLookup = $locator->findResources('config://');
|
|
||||||
$this->blueprintLookup = $locator->findResources('blueprints://config');
|
|
||||||
$this->pluginLookup = $locator->findResources('plugins://');
|
|
||||||
|
|
||||||
|
|
||||||
$this->loadCompiledBlueprints($this->blueprintLookup, $this->pluginLookup, 'master');
|
|
||||||
$this->loadCompiledConfig($this->configLookup, $this->pluginLookup, 'master');
|
|
||||||
|
|
||||||
// process languages if supported
|
|
||||||
if ($this->get('system.languages.translations', true)) {
|
|
||||||
$this->languagesLookup = $locator->findResources('languages://');
|
|
||||||
$this->loadCompiledLanguages($this->languagesLookup, $this->pluginLookup, 'master');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initializeLocator($locator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function checksum()
|
|
||||||
{
|
|
||||||
if (empty($this->checksum)) {
|
|
||||||
$checkBlueprints = $this->get('system.cache.check.blueprints', false);
|
|
||||||
$checkLanguages = $this->get('system.cache.check.languages', false);
|
|
||||||
$checkConfig = $this->get('system.cache.check.config', true);
|
|
||||||
$checkSystem = $this->get('system.cache.check.system', true);
|
|
||||||
|
|
||||||
if (!$checkBlueprints && !!$checkLanguages && $checkConfig && !$checkSystem) {
|
|
||||||
$this->messages[] = 'Skip configuration timestamp check.';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate checksum according to the configuration settings.
|
|
||||||
if (!$checkConfig) {
|
|
||||||
// Just check changes in system.yaml files and ignore all the other files.
|
|
||||||
$cc = $checkSystem ? $this->finder->locateConfigFile($this->configLookup, 'system') : [];
|
|
||||||
} else {
|
|
||||||
// Check changes in all configuration files.
|
|
||||||
$cc = $this->finder->locateConfigFiles($this->configLookup, $this->pluginLookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($checkBlueprints) {
|
|
||||||
$cb = $this->finder->locateBlueprintFiles($this->blueprintLookup, $this->pluginLookup);
|
|
||||||
} else {
|
|
||||||
$cb = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($checkLanguages) {
|
|
||||||
$cl = $this->finder->locateLanguageFiles($this->languagesLookup, $this->pluginLookup);
|
|
||||||
} else {
|
|
||||||
$cl = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->checksum = md5(json_encode([$cc, $cb, $cl]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->checksum;
|
return $this->checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function autoDetectEnvironmentConfig($items)
|
public function modified($modified = null)
|
||||||
{
|
{
|
||||||
$environment = $this->environment;
|
if ($modified !== null) {
|
||||||
$env_stream = 'user://'.$environment.'/config';
|
$this->modified = $modified;
|
||||||
|
|
||||||
if (file_exists(USER_DIR.$environment.'/config')) {
|
|
||||||
array_unshift($items['streams']['schemes']['config']['prefixes'][''], $env_stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $items;
|
return $this->modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadCompiledBlueprints($blueprints, $plugins, $filename = null)
|
public function reload()
|
||||||
{
|
{
|
||||||
$checksum = md5(json_encode($blueprints));
|
$grav = Grav::instance();
|
||||||
$filename = $filename
|
|
||||||
? CACHE_DIR . 'compiled/blueprints/' . $filename . '-' . $this->environment . '.php'
|
|
||||||
: CACHE_DIR . 'compiled/blueprints/' . $checksum . '-' . $this->environment . '.php';
|
|
||||||
$file = PhpFile::instance($filename);
|
|
||||||
$cache = $file->exists() ? $file->content() : null;
|
|
||||||
$blueprintFiles = $this->finder->locateBlueprintFiles($blueprints, $plugins);
|
|
||||||
$checksum .= ':'.md5(json_encode($blueprintFiles));
|
|
||||||
$class = get_class($this);
|
|
||||||
|
|
||||||
// Load real file if cache isn't up to date (or is invalid).
|
// Load new configuration.
|
||||||
if (
|
$config = ConfigServiceProvider::load($grav);
|
||||||
!is_array($cache)
|
|
||||||
|| !isset($cache['checksum'])
|
|
||||||
|| !isset($cache['@class'])
|
|
||||||
|| $cache['checksum'] != $checksum
|
|
||||||
|| $cache['@class'] != $class
|
|
||||||
) {
|
|
||||||
// Attempt to lock the file for writing.
|
|
||||||
$file->lock(false);
|
|
||||||
|
|
||||||
// Load blueprints.
|
/** @var Debugger $debugger */
|
||||||
$this->blueprints = new Blueprints;
|
$debugger = $grav['debugger'];
|
||||||
foreach ($blueprintFiles as $files) {
|
|
||||||
$this->loadBlueprintFiles($files);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache = [
|
if ($config->modified()) {
|
||||||
'@class' => $class,
|
// Update current configuration.
|
||||||
'checksum' => $checksum,
|
$this->items = $config->toArray();
|
||||||
'files' => $blueprintFiles,
|
$this->checksum($config->checksum());
|
||||||
'data' => $this->blueprints->toArray()
|
$this->modified(true);
|
||||||
];
|
|
||||||
// If compiled file wasn't already locked by another process, save it.
|
$debugger->addMessage('Configuration was changed and saved.');
|
||||||
if ($file->locked() !== false) {
|
}
|
||||||
$this->messages[] = 'Saving compiled blueprints.';
|
|
||||||
$file->save($cache);
|
return $this;
|
||||||
$file->unlock();
|
}
|
||||||
}
|
|
||||||
} else {
|
public function debug()
|
||||||
$this->blueprints = new Blueprints($cache['data']);
|
{
|
||||||
|
/** @var Debugger $debugger */
|
||||||
|
$debugger = Grav::instance()['debugger'];
|
||||||
|
|
||||||
|
$debugger->addMessage('Environment Name: ' . $this->environment);
|
||||||
|
if ($this->modified()) {
|
||||||
|
$debugger->addMessage('Configuration reloaded and cached.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadCompiledConfig($configs, $plugins, $filename = null)
|
public function init()
|
||||||
{
|
{
|
||||||
$filename = $filename
|
$setup = Grav::instance()['setup']->toArray();
|
||||||
? CACHE_DIR . 'compiled/config/' . $filename . '-' . $this->environment . '.php'
|
foreach ($setup as $key => $value) {
|
||||||
: CACHE_DIR . 'compiled/config/' . $checksum . '-' . $this->environment . '.php';
|
if ($key === 'streams' || !is_array($value)) {
|
||||||
$file = PhpFile::instance($filename);
|
// Optimized as streams and simple values are fully defined in setup.
|
||||||
$cache = $file->exists() ? $file->content() : null;
|
$this->items[$key] = $value;
|
||||||
$class = get_class($this);
|
} else {
|
||||||
$checksum = $this->checksum();
|
$this->joinDefaults($key, $value);
|
||||||
|
|
||||||
if (
|
|
||||||
!is_array($cache)
|
|
||||||
|| !isset($cache['checksum'])
|
|
||||||
|| !isset($cache['@class'])
|
|
||||||
|| $cache['@class'] != $class
|
|
||||||
) {
|
|
||||||
$this->messages[] = 'No cached configuration, compiling new configuration..';
|
|
||||||
} else if ($cache['checksum'] !== $checksum) {
|
|
||||||
$this->messages[] = 'Configuration checksum mismatch, reloading configuration..';
|
|
||||||
} else {
|
|
||||||
$this->messages[] = 'Configuration checksum matches, using cached version.';
|
|
||||||
|
|
||||||
$this->items = $cache['data'];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$configFiles = $this->finder->locateConfigFiles($configs, $plugins);
|
|
||||||
|
|
||||||
// Attempt to lock the file for writing.
|
|
||||||
$file->lock(false);
|
|
||||||
|
|
||||||
// Load configuration.
|
|
||||||
foreach ($configFiles as $files) {
|
|
||||||
$this->loadConfigFiles($files);
|
|
||||||
}
|
|
||||||
$cache = [
|
|
||||||
'@class' => $class,
|
|
||||||
'timestamp' => time(),
|
|
||||||
'checksum' => $checksum,
|
|
||||||
'data' => $this->toArray()
|
|
||||||
];
|
|
||||||
|
|
||||||
// If compiled file wasn't already locked by another process, save it.
|
|
||||||
if ($file->locked() !== false) {
|
|
||||||
$this->messages[] = 'Saving compiled configuration.';
|
|
||||||
$file->save($cache);
|
|
||||||
$file->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->items = $cache['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $languages
|
|
||||||
* @param $plugins
|
|
||||||
* @param null $filename
|
|
||||||
*/
|
|
||||||
protected function loadCompiledLanguages($languages, $plugins, $filename = null)
|
|
||||||
{
|
|
||||||
$checksum = md5(json_encode($languages));
|
|
||||||
$filename = $filename
|
|
||||||
? CACHE_DIR . 'compiled/languages/' . $filename . '-' . $this->environment . '.php'
|
|
||||||
: CACHE_DIR . 'compiled/languages/' . $checksum . '-' . $this->environment . '.php';
|
|
||||||
$file = PhpFile::instance($filename);
|
|
||||||
$cache = $file->exists() ? $file->content() : null;
|
|
||||||
$languageFiles = $this->finder->locateLanguageFiles($languages, $plugins);
|
|
||||||
$checksum .= ':' . md5(json_encode($languageFiles));
|
|
||||||
$class = get_class($this);
|
|
||||||
|
|
||||||
// Load real file if cache isn't up to date (or is invalid).
|
|
||||||
if (
|
|
||||||
!is_array($cache)
|
|
||||||
|| !isset($cache['checksum'])
|
|
||||||
|| !isset($cache['@class'])
|
|
||||||
|| $cache['checksum'] != $checksum
|
|
||||||
|| $cache['@class'] != $class
|
|
||||||
) {
|
|
||||||
// Attempt to lock the file for writing.
|
|
||||||
$file->lock(false);
|
|
||||||
|
|
||||||
// Load languages.
|
|
||||||
$this->languages = new Languages;
|
|
||||||
$pluginPaths = str_ireplace(GRAV_ROOT . '/', '', array_reverse($plugins));
|
|
||||||
foreach ($pluginPaths as $path) {
|
|
||||||
if (isset($languageFiles[$path])) {
|
|
||||||
foreach ((array) $languageFiles[$path] as $plugin => $item) {
|
|
||||||
$lang_file = CompiledYamlFile::instance($item['file']);
|
|
||||||
$content = $lang_file->content();
|
|
||||||
$this->languages->mergeRecursive($content);
|
|
||||||
}
|
|
||||||
unset($languageFiles[$path]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($languageFiles as $location) {
|
|
||||||
foreach ($location as $lang => $item) {
|
|
||||||
$lang_file = CompiledYamlFile::instance($item['file']);
|
|
||||||
$content = $lang_file->content();
|
|
||||||
$this->languages->join($lang, $content, '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache = [
|
|
||||||
'@class' => $class,
|
|
||||||
'checksum' => $checksum,
|
|
||||||
'files' => $languageFiles,
|
|
||||||
'data' => $this->languages->toArray()
|
|
||||||
];
|
|
||||||
// If compiled file wasn't already locked by another process, save it.
|
|
||||||
if ($file->locked() !== false) {
|
|
||||||
$this->messages[] = 'Saving compiled languages.';
|
|
||||||
$file->save($cache);
|
|
||||||
$file->unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->languages = new Languages($cache['data']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load blueprints.
|
|
||||||
*
|
|
||||||
* @param array $files
|
|
||||||
*/
|
|
||||||
public function loadBlueprintFiles(array $files)
|
|
||||||
{
|
|
||||||
foreach ($files as $name => $item) {
|
|
||||||
$file = CompiledYamlFile::instance($item['file']);
|
|
||||||
$this->blueprints->embed($name, $file->content(), '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load configuration.
|
|
||||||
*
|
|
||||||
* @param array $files
|
|
||||||
*/
|
|
||||||
public function loadConfigFiles(array $files)
|
|
||||||
{
|
|
||||||
foreach ($files as $name => $item) {
|
|
||||||
$file = CompiledYamlFile::instance($item['file']);
|
|
||||||
$this->join($name, $file->content(), '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize resource locator by using the configuration.
|
|
||||||
*
|
|
||||||
* @param UniformResourceLocator $locator
|
|
||||||
*/
|
|
||||||
public function initializeLocator(UniformResourceLocator $locator)
|
|
||||||
{
|
|
||||||
$locator->reset();
|
|
||||||
|
|
||||||
$schemes = (array) $this->get('streams.schemes', []);
|
|
||||||
|
|
||||||
foreach ($schemes as $scheme => $config) {
|
|
||||||
if (isset($config['paths'])) {
|
|
||||||
$locator->addPath($scheme, '', $config['paths']);
|
|
||||||
}
|
|
||||||
if (isset($config['prefixes'])) {
|
|
||||||
foreach ($config['prefixes'] as $prefix => $paths) {
|
|
||||||
$locator->addPath($scheme, $prefix, $paths);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get available streams and their types from the configuration.
|
* @return mixed
|
||||||
*
|
* @deprecated
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function getStreams()
|
|
||||||
{
|
|
||||||
$schemes = [];
|
|
||||||
foreach ((array) $this->get('streams.schemes') as $scheme => $config) {
|
|
||||||
$type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream';
|
|
||||||
if ($type[0] != '\\') {
|
|
||||||
$type = '\\RocketTheme\\Toolbox\\StreamWrapper\\' . $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
$schemes[$scheme] = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $schemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLanguages()
|
public function getLanguages()
|
||||||
{
|
{
|
||||||
return $this->languages;
|
return Grav::instance()['languages'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
258
system/src/Grav/Common/Config/ConfigFileFinder.php
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use Grav\Common\Filesystem\Folder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Configuration & Blueprints Finder class.
|
||||||
|
*/
|
||||||
|
class ConfigFileFinder
|
||||||
|
{
|
||||||
|
protected $base = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $base
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setBase($base)
|
||||||
|
{
|
||||||
|
$this->base = $base ? "{$base}/" : '';
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all locations for all the files with a timestamp.
|
||||||
|
*
|
||||||
|
* @param array $paths List of folders to look from.
|
||||||
|
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
|
||||||
|
* @param int $levels Maximum number of recursive directories.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function locateFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
foreach ($paths as $folder) {
|
||||||
|
$list += $this->detectRecursive($folder, $pattern, $levels);
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all locations for all the files with a timestamp.
|
||||||
|
*
|
||||||
|
* @param array $paths List of folders to look from.
|
||||||
|
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
|
||||||
|
* @param int $levels Maximum number of recursive directories.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
foreach ($paths as $folder) {
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
|
||||||
|
$files = $this->detectRecursive($folder, $pattern, $levels);
|
||||||
|
|
||||||
|
$list += $files[trim($path, '/')];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all paths for all the files with a timestamp.
|
||||||
|
*
|
||||||
|
* @param array $paths List of folders to look from.
|
||||||
|
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
|
||||||
|
* @param int $levels Maximum number of recursive directories.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function listFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
foreach ($paths as $folder) {
|
||||||
|
$list = array_merge_recursive($list, $this->detectAll($folder, $pattern, $levels));
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find filename from a list of folders.
|
||||||
|
*
|
||||||
|
* Note: Only finds the last override.
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
* @param array $folders
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function locateFileInFolder($filename, array $folders)
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
foreach ($folders as $folder) {
|
||||||
|
$list += $this->detectInFolder($folder, $filename);
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find filename from a list of folders.
|
||||||
|
*
|
||||||
|
* @param array $folders
|
||||||
|
* @param string $filename
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function locateInFolders(array $folders, $filename = null)
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
foreach ($folders as $folder) {
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
$list[$path] = $this->detectInFolder($folder, $filename);
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all existing locations for a single file with a timestamp.
|
||||||
|
*
|
||||||
|
* @param array $paths Filesystem paths to look up from.
|
||||||
|
* @param string $name Configuration file to be located.
|
||||||
|
* @param string $ext File extension (optional, defaults to .yaml).
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function locateFile(array $paths, $name, $ext = '.yaml')
|
||||||
|
{
|
||||||
|
$filename = preg_replace('|[.\/]+|', '/', $name) . $ext;
|
||||||
|
|
||||||
|
$list = [];
|
||||||
|
foreach ($paths as $folder) {
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
|
||||||
|
if (is_file("{$folder}/{$filename}")) {
|
||||||
|
$modified = filemtime("{$folder}/{$filename}");
|
||||||
|
} else {
|
||||||
|
$modified = 0;
|
||||||
|
}
|
||||||
|
$basename = $this->base . $name;
|
||||||
|
$list[$path] = [$basename => ['file' => "{$path}/{$filename}", 'modified' => $modified]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects all directories with a configuration file and returns them with last modification time.
|
||||||
|
*
|
||||||
|
* @param string $folder Location to look up from.
|
||||||
|
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
|
||||||
|
* @param int $levels Maximum number of recursive directories.
|
||||||
|
* @return array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function detectRecursive($folder, $pattern, $levels)
|
||||||
|
{
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
|
||||||
|
if (is_dir($folder)) {
|
||||||
|
// Find all system and user configuration files.
|
||||||
|
$options = [
|
||||||
|
'levels' => $levels,
|
||||||
|
'compare' => 'Filename',
|
||||||
|
'pattern' => $pattern,
|
||||||
|
'filters' => [
|
||||||
|
'pre-key' => $this->base,
|
||||||
|
'key' => $pattern,
|
||||||
|
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
|
||||||
|
return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'key' => 'SubPathname'
|
||||||
|
];
|
||||||
|
|
||||||
|
$list = Folder::all($folder, $options);
|
||||||
|
|
||||||
|
ksort($list);
|
||||||
|
} else {
|
||||||
|
$list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$path => $list];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects all directories with the lookup file and returns them with last modification time.
|
||||||
|
*
|
||||||
|
* @param string $folder Location to look up from.
|
||||||
|
* @param string $lookup Filename to be located (defaults to directory name).
|
||||||
|
* @return array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function detectInFolder($folder, $lookup = null)
|
||||||
|
{
|
||||||
|
$folder = rtrim($folder, '/');
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
$base = $path === $folder ? '' : ($path ? substr($folder, 0, -strlen($path)) : $folder . '/');
|
||||||
|
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
if (is_dir($folder)) {
|
||||||
|
$iterator = new \DirectoryIterator($folder);
|
||||||
|
|
||||||
|
/** @var \DirectoryIterator $directory */
|
||||||
|
foreach ($iterator as $directory) {
|
||||||
|
if (!$directory->isDir() || $directory->isDot()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $directory->getBasename();
|
||||||
|
$find = ($lookup ?: $name) . '.yaml';
|
||||||
|
$filename = "{$path}/{$name}/{$find}";
|
||||||
|
|
||||||
|
if (file_exists($base . $filename)) {
|
||||||
|
$basename = $this->base . $name;
|
||||||
|
$list[$basename] = ['file' => $filename, 'modified' => filemtime($base . $filename)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects all plugins with a configuration file and returns them with last modification time.
|
||||||
|
*
|
||||||
|
* @param string $folder Location to look up from.
|
||||||
|
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
|
||||||
|
* @param int $levels Maximum number of recursive directories.
|
||||||
|
* @return array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function detectAll($folder, $pattern, $levels)
|
||||||
|
{
|
||||||
|
$path = trim(Folder::getRelativePath($folder), '/');
|
||||||
|
|
||||||
|
if (is_dir($folder)) {
|
||||||
|
// Find all system and user configuration files.
|
||||||
|
$options = [
|
||||||
|
'levels' => $levels,
|
||||||
|
'compare' => 'Filename',
|
||||||
|
'pattern' => $pattern,
|
||||||
|
'filters' => [
|
||||||
|
'pre-key' => $this->base,
|
||||||
|
'key' => $pattern,
|
||||||
|
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
|
||||||
|
return ["{$path}/{$file->getSubPathname()}" => $file->getMTime()];
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'key' => 'SubPathname'
|
||||||
|
];
|
||||||
|
|
||||||
|
$list = Folder::all($folder, $options);
|
||||||
|
|
||||||
|
ksort($list);
|
||||||
|
} else {
|
||||||
|
$list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Grav\Common\Config;
|
|
||||||
|
|
||||||
use Grav\Common\Filesystem\Folder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Configuration Finder class.
|
|
||||||
*
|
|
||||||
* @author RocketTheme
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
class ConfigFinder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get all locations for blueprint files (including plugins).
|
|
||||||
*
|
|
||||||
* @param array $blueprints
|
|
||||||
* @param array $plugins
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function locateBlueprintFiles(array $blueprints, array $plugins)
|
|
||||||
{
|
|
||||||
$list = [];
|
|
||||||
foreach (array_reverse($plugins) as $folder) {
|
|
||||||
$list += $this->detectInFolder($folder, 'blueprints');
|
|
||||||
}
|
|
||||||
foreach (array_reverse($blueprints) as $folder) {
|
|
||||||
$list += $this->detectRecursive($folder);
|
|
||||||
}
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all locations for configuration files (including plugins).
|
|
||||||
*
|
|
||||||
* @param array $configs
|
|
||||||
* @param array $plugins
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function locateConfigFiles(array $configs, array $plugins)
|
|
||||||
{
|
|
||||||
$list = [];
|
|
||||||
foreach (array_reverse($plugins) as $folder) {
|
|
||||||
$list += $this->detectInFolder($folder);
|
|
||||||
}
|
|
||||||
foreach (array_reverse($configs) as $folder) {
|
|
||||||
$list += $this->detectRecursive($folder);
|
|
||||||
}
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function locateLanguageFiles(array $languages, array $plugins)
|
|
||||||
{
|
|
||||||
$list = [];
|
|
||||||
foreach (array_reverse($plugins) as $folder) {
|
|
||||||
$list += $this->detectLanguagesInFolder($folder, 'languages');
|
|
||||||
}
|
|
||||||
foreach (array_reverse($languages) as $folder) {
|
|
||||||
$list += $this->detectRecursive($folder);
|
|
||||||
}
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all locations for a single configuration file.
|
|
||||||
*
|
|
||||||
* @param array $folders Locations to look up from.
|
|
||||||
* @param string $name Filename to be located.
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function locateConfigFile(array $folders, $name)
|
|
||||||
{
|
|
||||||
$filename = "{$name}.yaml";
|
|
||||||
|
|
||||||
$list = [];
|
|
||||||
foreach ($folders as $folder) {
|
|
||||||
$path = trim(Folder::getRelativePath($folder), '/');
|
|
||||||
|
|
||||||
if (is_file("{$folder}/{$filename}")) {
|
|
||||||
$modified = filemtime("{$folder}/{$filename}");
|
|
||||||
} else {
|
|
||||||
$modified = 0;
|
|
||||||
}
|
|
||||||
$list[$path] = [$name => ['file' => "{$path}/{$filename}", 'modified' => $modified]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects all plugins with a configuration file and returns them with last modification time.
|
|
||||||
*
|
|
||||||
* @param string $folder Location to look up from.
|
|
||||||
* @param string $lookup Filename to be located.
|
|
||||||
* @return array
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
protected function detectInFolder($folder, $lookup = null)
|
|
||||||
{
|
|
||||||
$path = trim(Folder::getRelativePath($folder), '/');
|
|
||||||
|
|
||||||
$list = [];
|
|
||||||
|
|
||||||
if (is_dir($folder)) {
|
|
||||||
$iterator = new \FilesystemIterator($folder);
|
|
||||||
|
|
||||||
/** @var \DirectoryIterator $directory */
|
|
||||||
foreach ($iterator as $directory) {
|
|
||||||
if (!$directory->isDir()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $directory->getBasename();
|
|
||||||
$find = ($lookup ?: $name) . '.yaml';
|
|
||||||
$filename = "{$path}/{$name}/$find";
|
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
$list["plugins/{$name}"] = ['file' => $filename, 'modified' => filemtime($filename)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$path => $list];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function detectLanguagesInFolder($folder, $lookup = null)
|
|
||||||
{
|
|
||||||
$path = trim(Folder::getRelativePath($folder), '/');
|
|
||||||
|
|
||||||
$list = [];
|
|
||||||
|
|
||||||
if (is_dir($folder)) {
|
|
||||||
$iterator = new \FilesystemIterator($folder);
|
|
||||||
|
|
||||||
/** @var \DirectoryIterator $directory */
|
|
||||||
foreach ($iterator as $directory) {
|
|
||||||
if (!$directory->isDir()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $directory->getBasename();
|
|
||||||
$find = ($lookup ?: $name) . '.yaml';
|
|
||||||
$filename = "{$path}/{$name}/$find";
|
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
$list[$name] = ['file' => $filename, 'modified' => filemtime($filename)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$path => $list];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects all plugins with a configuration file and returns them with last modification time.
|
|
||||||
*
|
|
||||||
* @param string $folder Location to look up from.
|
|
||||||
* @return array
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
protected function detectRecursive($folder)
|
|
||||||
{
|
|
||||||
$path = trim(Folder::getRelativePath($folder), '/');
|
|
||||||
|
|
||||||
if (is_dir($folder)) {
|
|
||||||
// Find all system and user configuration files.
|
|
||||||
$options = [
|
|
||||||
'compare' => 'Filename',
|
|
||||||
'pattern' => '|\.yaml$|',
|
|
||||||
'filters' => [
|
|
||||||
'key' => '|\.yaml$|',
|
|
||||||
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
|
|
||||||
return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'key' => 'SubPathname'
|
|
||||||
];
|
|
||||||
|
|
||||||
$list = Folder::all($folder, $options);
|
|
||||||
} else {
|
|
||||||
$list = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$path => $list];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,23 @@ use Grav\Common\Data\Data;
|
|||||||
*/
|
*/
|
||||||
class Languages extends Data
|
class Languages extends Data
|
||||||
{
|
{
|
||||||
|
public function checksum($checksum = null)
|
||||||
|
{
|
||||||
|
if ($checksum !== null) {
|
||||||
|
$this->checksum = $checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function modified($modified = null)
|
||||||
|
{
|
||||||
|
if ($modified !== null) {
|
||||||
|
$this->modified = $modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->modified;
|
||||||
|
}
|
||||||
|
|
||||||
public function reformat()
|
public function reformat()
|
||||||
{
|
{
|
||||||
|
|||||||
254
system/src/Grav/Common/Config/Setup.php
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Common\Config;
|
||||||
|
|
||||||
|
use Grav\Common\File\CompiledYamlFile;
|
||||||
|
use Grav\Common\Data\Data;
|
||||||
|
use Grav\Common\Utils;
|
||||||
|
use RocketTheme\Toolbox\File\YamlFile;
|
||||||
|
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Config class contains configuration information.
|
||||||
|
*
|
||||||
|
* @author RocketTheme
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
class Setup extends Data
|
||||||
|
{
|
||||||
|
protected $streams = [
|
||||||
|
'system' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['system'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'user' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'environment' => [
|
||||||
|
'type' => 'ReadOnlyStream'
|
||||||
|
// If not defined, environment will be set up in the constructor.
|
||||||
|
],
|
||||||
|
'asset' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['assets'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'blueprints' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['environment://blueprints', 'user://blueprints', 'system/blueprints'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'config' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['environment://config', 'user://config', 'system/config'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'plugins' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://plugins'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'plugin' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://plugins'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'themes' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://themes'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'languages' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['environment://languages', 'user://languages', 'system/languages'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'cache' => [
|
||||||
|
'type' => 'Stream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['cache'],
|
||||||
|
'images' => ['images']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'log' => [
|
||||||
|
'type' => 'Stream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['logs']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'backup' => [
|
||||||
|
'type' => 'Stream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['backup']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'image' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://images', 'system://images']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'page' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://pages']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'account' => [
|
||||||
|
'type' => 'ReadOnlyStream',
|
||||||
|
'prefixes' => [
|
||||||
|
'' => ['user://accounts']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct($container)
|
||||||
|
{
|
||||||
|
$environment = $container['uri']->environment();
|
||||||
|
if (!$environment) {
|
||||||
|
$environment = 'localhost';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre-load setup.php which contains our initial configuration.
|
||||||
|
// Configuration may contain dynamic parts, which is why we need to always load it.
|
||||||
|
$file = GRAV_ROOT . '/setup.php';
|
||||||
|
$setup = is_file($file) ? (array) include $file : [];
|
||||||
|
|
||||||
|
// Add default streams defined in beginning of the class.
|
||||||
|
if (!isset($setup['streams']['schemes'])) {
|
||||||
|
$setup['streams']['schemes'] = [];
|
||||||
|
}
|
||||||
|
$setup['streams']['schemes'] += $this->streams;
|
||||||
|
|
||||||
|
// Initialize class.
|
||||||
|
parent::__construct($setup);
|
||||||
|
|
||||||
|
// Set up environment.
|
||||||
|
$this->def('environment', $environment);
|
||||||
|
$this->def('streams.schemes.environment.prefixes', ['' => ["user://{$this->environment}"]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$locator = new UniformResourceLocator(GRAV_ROOT);
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
$guard = 5;
|
||||||
|
do {
|
||||||
|
$check = $files;
|
||||||
|
$this->initializeLocator($locator);
|
||||||
|
$files = $locator->findResources('config://streams.yaml');
|
||||||
|
|
||||||
|
if ($check === $files) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update streams.
|
||||||
|
foreach ($files as $path) {
|
||||||
|
$file = CompiledYamlFile::instance($path);
|
||||||
|
$content = $file->content();
|
||||||
|
if (!empty($content['schemes'])) {
|
||||||
|
$this->items['streams']['schemes'] = $content['schemes'] + $this->items['streams']['schemes'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (--$guard);
|
||||||
|
|
||||||
|
if (!$guard) {
|
||||||
|
throw new \RuntimeException('Setup: Configuration reload loop detected!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have valid setup.
|
||||||
|
$this->check($locator);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize resource locator by using the configuration.
|
||||||
|
*
|
||||||
|
* @param UniformResourceLocator $locator
|
||||||
|
*/
|
||||||
|
public function initializeLocator(UniformResourceLocator $locator)
|
||||||
|
{
|
||||||
|
$locator->reset();
|
||||||
|
|
||||||
|
$schemes = (array) $this->get('streams.schemes', []);
|
||||||
|
|
||||||
|
foreach ($schemes as $scheme => $config) {
|
||||||
|
if (isset($config['paths'])) {
|
||||||
|
$locator->addPath($scheme, '', $config['paths']);
|
||||||
|
}
|
||||||
|
if (isset($config['prefixes'])) {
|
||||||
|
foreach ($config['prefixes'] as $prefix => $paths) {
|
||||||
|
$locator->addPath($scheme, $prefix, $paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get available streams and their types from the configuration.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getStreams()
|
||||||
|
{
|
||||||
|
$schemes = [];
|
||||||
|
foreach ((array) $this->get('streams.schemes') as $scheme => $config) {
|
||||||
|
$type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream';
|
||||||
|
if ($type[0] != '\\') {
|
||||||
|
$type = '\\RocketTheme\\Toolbox\\StreamWrapper\\' . $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
$schemes[$scheme] = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $schemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param UniformResourceLocator $locator
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function check(UniformResourceLocator $locator)
|
||||||
|
{
|
||||||
|
$streams = isset($this->items['streams']['schemes']) ? $this->items['streams']['schemes'] : null;
|
||||||
|
if (!is_array($streams)) {
|
||||||
|
throw new \InvalidArgumentException('Configuration is missing streams.schemes!');
|
||||||
|
}
|
||||||
|
$diff = array_keys(array_diff_key($this->streams, $streams));
|
||||||
|
if ($diff) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf('Configuration is missing keys %s from streams.schemes!', implode(', ', $diff))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$locator->findResource('environment://config', true)) {
|
||||||
|
// If environment does not have its own directory, remove it from the lookup.
|
||||||
|
$this->set('streams.schemes.environment.prefixes', ['config' => []]);
|
||||||
|
$this->initializeLocator($locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create security.yaml if it doesn't exist.
|
||||||
|
$filename = $locator->findResource('config://security.yaml', true, true);
|
||||||
|
$file = YamlFile::instance($filename);
|
||||||
|
if (!$file->exists()) {
|
||||||
|
$file->save(['salt' => Utils::generateRandomString(14)]);
|
||||||
|
$file->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ namespace Grav\Common\Data;
|
|||||||
|
|
||||||
use Grav\Common\GravTrait;
|
use Grav\Common\GravTrait;
|
||||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||||
|
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||||
|
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blueprint handles the inside logic of blueprints.
|
* Blueprint handles the inside logic of blueprints.
|
||||||
@@ -10,9 +12,9 @@ use RocketTheme\Toolbox\ArrayTraits\Export;
|
|||||||
* @author RocketTheme
|
* @author RocketTheme
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
class Blueprint
|
class Blueprint implements \ArrayAccess, ExportInterface
|
||||||
{
|
{
|
||||||
use Export, DataMutatorTrait, GravTrait;
|
use Export, NestedArrayAccessWithGetters, GravTrait;
|
||||||
|
|
||||||
public $name;
|
public $name;
|
||||||
|
|
||||||
@@ -76,7 +78,9 @@ class Blueprint
|
|||||||
try {
|
try {
|
||||||
$this->validateArray($data, $this->nested);
|
$this->validateArray($data, $this->nested);
|
||||||
} catch (\RuntimeException $e) {
|
} catch (\RuntimeException $e) {
|
||||||
throw new \RuntimeException(sprintf('<b>Validation failed:</b> %s', $e->getMessage()));
|
$language = self::getGrav()['language'];
|
||||||
|
$message = sprintf($language->translate('FORM.VALIDATION_FAIL', null, true) . ' %s', $e->getMessage());
|
||||||
|
throw new \RuntimeException($message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,9 +242,6 @@ class Blueprint
|
|||||||
|
|
||||||
if ($rule) {
|
if ($rule) {
|
||||||
// Item has been defined in blueprints.
|
// Item has been defined in blueprints.
|
||||||
if (is_array($field) && count($field) == 1 && reset($field) == '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$field = Validation::filter($field, $rule);
|
$field = Validation::filter($field, $rule);
|
||||||
} elseif (is_array($field) && is_array($val)) {
|
} elseif (is_array($field) && is_array($val)) {
|
||||||
// Array has been defined in blueprints.
|
// Array has been defined in blueprints.
|
||||||
@@ -310,91 +311,107 @@ class Blueprint
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all field definitions from the blueprints.
|
* Gets all field definitions from the blueprints.
|
||||||
*
|
*
|
||||||
* @param array $fields
|
* @param array $fields
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @param string $prefix
|
* @param string $prefix
|
||||||
* @param array $current
|
* @param array $current
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
protected function parseFormFields(array &$fields, $params, $prefix, array &$current)
|
protected function parseFormFields(array &$fields, $params, $prefix, array &$current)
|
||||||
{
|
{
|
||||||
// Go though all the fields in current level.
|
// Go though all the fields in current level.
|
||||||
foreach ($fields as $key => &$field) {
|
foreach ($fields as $key => &$field) {
|
||||||
$current[$key] = &$field;
|
$current[$key] = &$field;
|
||||||
// Set name from the array key.
|
// Set name from the array key.
|
||||||
$field['name'] = $prefix . $key;
|
$field['name'] = $prefix . $key;
|
||||||
$field += $params;
|
$field += $params;
|
||||||
|
|
||||||
if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) {
|
if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) {
|
||||||
// Recursively get all the nested fields.
|
// Recursively get all the nested fields.
|
||||||
$newParams = array_intersect_key($this->filter, $field);
|
$newParams = array_intersect_key($this->filter, $field);
|
||||||
$this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']);
|
$this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']);
|
||||||
} else if ($field['type'] !== 'ignore') {
|
} else if ($field['type'] !== 'ignore') {
|
||||||
// Add rule.
|
|
||||||
$this->rules[$prefix . $key] = &$field;
|
$this->rules[$prefix . $key] = &$field;
|
||||||
$this->addProperty($prefix . $key);
|
$this->addProperty($prefix . $key);
|
||||||
|
|
||||||
foreach ($field as $name => $value) {
|
if ($field['type'] === 'list') {
|
||||||
// Support nested blueprints.
|
// we loop through list to get the actual field
|
||||||
if ($this->context && $name == '@import') {
|
if (isset($field['fields']) && $field['fields']) {
|
||||||
$values = (array) $value;
|
foreach($field['fields'] as $subName => &$subField) {
|
||||||
if (!isset($field['fields'])) {
|
$this->parseFormField($subField);
|
||||||
$field['fields'] = array();
|
|
||||||
}
|
|
||||||
foreach ($values as $bname) {
|
|
||||||
$b = $this->context->get($bname);
|
|
||||||
$field['fields'] = array_merge($field['fields'], $b->fields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support for callable data values.
|
|
||||||
elseif (substr($name, 0, 6) == '@data-') {
|
|
||||||
$property = substr($name, 6);
|
|
||||||
if (is_array($value)) {
|
|
||||||
$func = array_shift($value);
|
|
||||||
} else {
|
|
||||||
$func = $value;
|
|
||||||
$value = array();
|
|
||||||
}
|
|
||||||
list($o, $f) = preg_split('/::/', $func);
|
|
||||||
if (!$f && function_exists($o)) {
|
|
||||||
$data = call_user_func_array($o, $value);
|
|
||||||
} elseif ($f && method_exists($o, $f)) {
|
|
||||||
$data = call_user_func_array(array($o, $f), $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If function returns a value,
|
|
||||||
if (isset($data)) {
|
|
||||||
if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) {
|
|
||||||
// Combine field and @data-field together.
|
|
||||||
$field[$property] += $data;
|
|
||||||
} else {
|
|
||||||
// Or create/replace field with @data-field.
|
|
||||||
$field[$property] = $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elseif (substr($name, 0, 8) == '@config-') {
|
|
||||||
$property = substr($name, 8);
|
|
||||||
$default = isset($field[$property]) ? $field[$property] : null;
|
|
||||||
$config = self::getGrav()['config']->get($value, $default);
|
|
||||||
|
|
||||||
if (!is_null($config)) {
|
|
||||||
$field[$property] = $config;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->parseFormField($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize predefined validation rule.
|
|
||||||
if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') {
|
if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') {
|
||||||
$field['validate'] += $this->getRule($field['validate']['rule']);
|
$field['validate'] += $this->getRule($field['validate']['rule']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Parses individual field definition
|
||||||
|
*
|
||||||
|
* @param array $field
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected function parseFormField(&$field) {
|
||||||
|
foreach ($field as $name => $value) {
|
||||||
|
// Support nested blueprints.
|
||||||
|
if ($this->context && $name == '@import') {
|
||||||
|
$values = (array) $value;
|
||||||
|
if (!isset($field['fields'])) {
|
||||||
|
$field['fields'] = array();
|
||||||
|
}
|
||||||
|
foreach ($values as $bname) {
|
||||||
|
$b = $this->context->get($bname);
|
||||||
|
$field['fields'] = array_merge($field['fields'], $b->fields());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for callable data values.
|
||||||
|
elseif (substr($name, 0, 6) == '@data-') {
|
||||||
|
$property = substr($name, 6);
|
||||||
|
if (is_array($value)) {
|
||||||
|
$func = array_shift($value);
|
||||||
|
} else {
|
||||||
|
$func = $value;
|
||||||
|
$value = array();
|
||||||
|
}
|
||||||
|
list($o, $f) = preg_split('/::/', $func);
|
||||||
|
if (!$f && function_exists($o)) {
|
||||||
|
$data = call_user_func_array($o, $value);
|
||||||
|
} elseif ($f && method_exists($o, $f)) {
|
||||||
|
$data = call_user_func_array(array($o, $f), $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If function returns a value,
|
||||||
|
if (isset($data)) {
|
||||||
|
if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) {
|
||||||
|
// Combine field and @data-field together.
|
||||||
|
$field[$property] += $data;
|
||||||
|
} else {
|
||||||
|
// Or create/replace field with @data-field.
|
||||||
|
$field[$property] = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif (substr($name, 0, 8) == '@config-') {
|
||||||
|
$property = substr($name, 8);
|
||||||
|
$default = isset($field[$property]) ? $field[$property] : null;
|
||||||
|
$config = self::getGrav()['config']->get($value, $default);
|
||||||
|
|
||||||
|
if (!is_null($config)) {
|
||||||
|
$field[$property] = $config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add property to the definition.
|
* Add property to the definition.
|
||||||
@@ -449,7 +466,10 @@ class Blueprint
|
|||||||
if (isset($field['validate']['required'])
|
if (isset($field['validate']['required'])
|
||||||
&& $field['validate']['required'] === true
|
&& $field['validate']['required'] === true
|
||||||
&& empty($data[$name])) {
|
&& empty($data[$name])) {
|
||||||
throw new \RuntimeException("Missing required field: {$field['name']}");
|
$value = isset($field['label']) ? $field['label'] : $field['name'];
|
||||||
|
$language = self::getGrav()['language'];
|
||||||
|
$message = sprintf($language->translate('FORM.MISSING_REQUIRED_FIELD', null, true) . ' %s', $value);
|
||||||
|
throw new \RuntimeException($message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\Data;
|
namespace Grav\Common\Data;
|
||||||
|
|
||||||
use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
|
|
||||||
use RocketTheme\Toolbox\ArrayTraits\Countable;
|
use RocketTheme\Toolbox\ArrayTraits\Countable;
|
||||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||||
|
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||||
|
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
|
||||||
|
use RocketTheme\Toolbox\Blueprints\Blueprints;
|
||||||
use RocketTheme\Toolbox\File\File;
|
use RocketTheme\Toolbox\File\File;
|
||||||
use RocketTheme\Toolbox\File\FileInterface;
|
use RocketTheme\Toolbox\File\FileInterface;
|
||||||
|
|
||||||
@@ -13,9 +15,9 @@ use RocketTheme\Toolbox\File\FileInterface;
|
|||||||
* @author RocketTheme
|
* @author RocketTheme
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
class Data implements DataInterface
|
class Data implements DataInterface, \ArrayAccess, \Countable, ExportInterface
|
||||||
{
|
{
|
||||||
use ArrayAccessWithGetters, Countable, Export, DataMutatorTrait;
|
use NestedArrayAccessWithGetters, Countable, Export;
|
||||||
|
|
||||||
protected $gettersVariable = 'items';
|
protected $gettersVariable = 'items';
|
||||||
protected $items;
|
protected $items;
|
||||||
@@ -32,12 +34,11 @@ class Data implements DataInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $items
|
* @param array $items
|
||||||
* @param Blueprint $blueprints
|
* @param Blueprint|callable $blueprints
|
||||||
*/
|
*/
|
||||||
public function __construct(array $items = array(), Blueprint $blueprints = null)
|
public function __construct(array $items = array(), $blueprints = null)
|
||||||
{
|
{
|
||||||
$this->items = $items;
|
$this->items = $items;
|
||||||
|
|
||||||
$this->blueprints = $blueprints;
|
$this->blueprints = $blueprints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,126 +58,150 @@ class Data implements DataInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set default value by using dot notation for nested arrays/objects.
|
* Join nested values together by using blueprints.
|
||||||
*
|
|
||||||
* @example $data->def('this.is.my.nested.variable', 'default');
|
|
||||||
*
|
|
||||||
* @param string $name Dot separated path to the requested value.
|
|
||||||
* @param mixed $default Default value (or null).
|
|
||||||
* @param string $separator Separator, defaults to '.'
|
|
||||||
*/
|
|
||||||
public function def($name, $default = null, $separator = '.')
|
|
||||||
{
|
|
||||||
$this->set($name, $this->get($name, $default, $separator), $separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join two values together by using blueprints if available.
|
|
||||||
*
|
*
|
||||||
* @param string $name Dot separated path to the requested value.
|
* @param string $name Dot separated path to the requested value.
|
||||||
* @param mixed $value Value to be joined.
|
* @param mixed $value Value to be joined.
|
||||||
* @param string $separator Separator, defaults to '.'
|
* @param string $separator Separator, defaults to '.'
|
||||||
|
* @return $this
|
||||||
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public function join($name, $value, $separator = '.')
|
public function join($name, $value, $separator = '.')
|
||||||
{
|
{
|
||||||
$old = $this->get($name, null, $separator);
|
$old = $this->get($name, null, $separator);
|
||||||
if ($old === null) {
|
if ($old !== null) {
|
||||||
// Variable does not exist yet: just use the incoming value.
|
if (!is_array($old)) {
|
||||||
} elseif ($this->blueprints) {
|
throw new \RuntimeException('Value ' . $old);
|
||||||
// Blueprints: join values by using blueprints.
|
}
|
||||||
$value = $this->blueprints->mergeData($old, $value, $name, $separator);
|
if (is_object($value)) {
|
||||||
} else {
|
$value = (array) $value;
|
||||||
// No blueprints: replace existing top level variables with the new ones.
|
} elseif (!is_array($value)) {
|
||||||
$value = array_merge($old, $value);
|
throw new \RuntimeException('Value ' . $value);
|
||||||
|
}
|
||||||
|
$value = $this->blueprints()->mergeData($old, $value, $name, $separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set($name, $value, $separator);
|
$this->set($name, $value, $separator);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join two values together by using blueprints if available.
|
* Get nested structure containing default values defined in the blueprints.
|
||||||
|
*
|
||||||
|
* Fields without default value are ignored in the list.
|
||||||
|
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDefaults()
|
||||||
|
{
|
||||||
|
return $this->blueprints()->getDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default values by using blueprints.
|
||||||
*
|
*
|
||||||
* @param string $name Dot separated path to the requested value.
|
* @param string $name Dot separated path to the requested value.
|
||||||
* @param mixed $value Value to be joined.
|
* @param mixed $value Value to be joined.
|
||||||
* @param string $separator Separator, defaults to '.'
|
* @param string $separator Separator, defaults to '.'
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function joinDefaults($name, $value, $separator = '.')
|
public function joinDefaults($name, $value, $separator = '.')
|
||||||
{
|
{
|
||||||
|
if (is_object($value)) {
|
||||||
|
$value = (array) $value;
|
||||||
|
}
|
||||||
$old = $this->get($name, null, $separator);
|
$old = $this->get($name, null, $separator);
|
||||||
if ($old === null) {
|
if ($old !== null) {
|
||||||
// Variable does not exist yet: just use the incoming value.
|
$value = $this->blueprints()->mergeData($value, $old, $name, $separator);
|
||||||
} elseif ($this->blueprints) {
|
|
||||||
// Blueprints: join values by using blueprints.
|
|
||||||
$value = $this->blueprints->mergeData($value, $old, $name, $separator);
|
|
||||||
} else {
|
|
||||||
// No blueprints: replace existing top level variables with the new ones.
|
|
||||||
$value = array_merge($value, $old);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set($name, $value, $separator);
|
$this->set($name, $value, $separator);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value from the configuration and join it with given data.
|
||||||
|
*
|
||||||
|
* @param string $name Dot separated path to the requested value.
|
||||||
|
* @param array $value Value to be joined.
|
||||||
|
* @param string $separator Separator, defaults to '.'
|
||||||
|
* @return array
|
||||||
|
* @throws \RuntimeException
|
||||||
|
*/
|
||||||
|
public function getJoined($name, $value, $separator = '.')
|
||||||
|
{
|
||||||
|
if (is_object($value)) {
|
||||||
|
$value = (array) $value;
|
||||||
|
} elseif (!is_array($value)) {
|
||||||
|
throw new \RuntimeException('Value ' . $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$old = $this->get($name, null, $separator);
|
||||||
|
|
||||||
|
if ($old === null) {
|
||||||
|
// No value set; no need to join data.
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($old)) {
|
||||||
|
throw new \RuntimeException('Value ' . $old);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return joined data.
|
||||||
|
return $this->blueprints()->mergeData($old, $value, $name, $separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two sets of data together.
|
* Merge two configurations together.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return void
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function merge(array $data)
|
public function merge(array $data)
|
||||||
{
|
{
|
||||||
if ($this->blueprints) {
|
$this->items = $this->blueprints()->mergeData($this->items, $data);
|
||||||
$this->items = $this->blueprints->mergeData($this->items, $data);
|
|
||||||
} else {
|
return $this;
|
||||||
$this->items = array_merge($this->items, $data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add default data to the set.
|
* Set default values to the configuration if variables were not set.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return void
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setDefaults(array $data)
|
public function setDefaults(array $data)
|
||||||
{
|
{
|
||||||
if ($this->blueprints) {
|
$this->items = $this->blueprints()->mergeData($data, $this->items);
|
||||||
$this->items = $this->blueprints->mergeData($data, $this->items);
|
|
||||||
} else {
|
|
||||||
$this->items = array_merge($data, $this->items);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return $this;
|
||||||
* Return blueprints.
|
|
||||||
*
|
|
||||||
* @return Blueprint
|
|
||||||
*/
|
|
||||||
public function blueprints()
|
|
||||||
{
|
|
||||||
return $this->blueprints;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate by blueprints.
|
* Validate by blueprints.
|
||||||
*
|
*
|
||||||
|
* @return $this
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function validate()
|
public function validate()
|
||||||
{
|
{
|
||||||
if ($this->blueprints) {
|
$this->blueprints()->validate($this->items);
|
||||||
$this->blueprints->validate($this->items);
|
|
||||||
}
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return $this
|
||||||
* Filter all items by using blueprints.
|
* Filter all items by using blueprints.
|
||||||
*/
|
*/
|
||||||
public function filter()
|
public function filter()
|
||||||
{
|
{
|
||||||
if ($this->blueprints) {
|
$this->items = $this->blueprints()->filter($this->items);
|
||||||
$this->items = $this->blueprints->filter($this->items);
|
|
||||||
}
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,6 +214,23 @@ class Data implements DataInterface
|
|||||||
return $this->blueprints ? $this->blueprints->extra($this->items) : array();
|
return $this->blueprints ? $this->blueprints->extra($this->items) : array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return blueprints.
|
||||||
|
*
|
||||||
|
* @return Blueprints
|
||||||
|
*/
|
||||||
|
public function blueprints()
|
||||||
|
{
|
||||||
|
if (!$this->blueprints){
|
||||||
|
$this->blueprints = new Blueprints;
|
||||||
|
} elseif (is_callable($this->blueprints)) {
|
||||||
|
// Lazy load blueprints.
|
||||||
|
$blueprints = $this->blueprints;
|
||||||
|
$this->blueprints = $blueprints();
|
||||||
|
}
|
||||||
|
return $this->blueprints;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save data if storage has been defined.
|
* Save data if storage has been defined.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Grav\Common\Data;
|
|
||||||
|
|
||||||
trait DataMutatorTrait
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get value by using dot notation for nested arrays/objects.
|
|
||||||
*
|
|
||||||
* @example $value = $data->get('this.is.my.nested.variable');
|
|
||||||
*
|
|
||||||
* @param string $name Dot separated path to the requested value.
|
|
||||||
* @param mixed $default Default value (or null).
|
|
||||||
* @param string $separator Separator, defaults to '.'
|
|
||||||
* @return mixed Value.
|
|
||||||
*/
|
|
||||||
public function get($name, $default = null, $separator = '.')
|
|
||||||
{
|
|
||||||
$path = explode($separator, $name);
|
|
||||||
$current = $this->items;
|
|
||||||
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 $default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set value by using dot notation for nested arrays/objects.
|
|
||||||
*
|
|
||||||
* @example $value = $data->set('this.is.my.nested.variable', true);
|
|
||||||
*
|
|
||||||
* @param string $name Dot separated path to the requested value.
|
|
||||||
* @param mixed $value New value.
|
|
||||||
* @param string $separator Separator, defaults to '.'
|
|
||||||
*/
|
|
||||||
public function set($name, $value, $separator = '.')
|
|
||||||
{
|
|
||||||
$path = explode($separator, $name);
|
|
||||||
$current = &$this->items;
|
|
||||||
foreach ($path as $field) {
|
|
||||||
if (is_object($current)) {
|
|
||||||
// Handle objects.
|
|
||||||
if (!isset($current->{$field})) {
|
|
||||||
$current->{$field} = array();
|
|
||||||
}
|
|
||||||
$current = &$current->{$field};
|
|
||||||
} else {
|
|
||||||
// Handle arrays and scalars.
|
|
||||||
if (!is_array($current)) {
|
|
||||||
$current = array($field => array());
|
|
||||||
} elseif (!isset($current[$field])) {
|
|
||||||
$current[$field] = array();
|
|
||||||
}
|
|
||||||
$current = &$current[$field];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$current = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\Data;
|
namespace Grav\Common\Data;
|
||||||
|
|
||||||
use Grav\Common\GravTrait;
|
use Grav\Common\GravTrait;
|
||||||
use Symfony\Component\Yaml\Exception\ParseException;
|
use Symfony\Component\Yaml\Exception\ParseException;
|
||||||
use Symfony\Component\Yaml\Parser;
|
use Symfony\Component\Yaml\Parser;
|
||||||
@@ -30,14 +31,19 @@ class Validation
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special case for files, value is never empty and errors with code 4 instead
|
||||||
|
if (empty($validate['required']) && $field['type'] == 'file' && (isset($value['error']) && ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error'])))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get language class
|
// Get language class
|
||||||
$language = self::getGrav()['language'];
|
$language = self::getGrav()['language'];
|
||||||
|
|
||||||
// Validate type with fallback type text.
|
// Validate type with fallback type text.
|
||||||
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
|
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
|
||||||
$method = 'type'.strtr($type, '-', '_');
|
$method = 'type'.strtr($type, '-', '_');
|
||||||
$name = ucfirst($field['label'] ? $field['label'] : $field['name']);
|
$name = ucfirst(isset($field['label']) ? $field['label'] : $field['name']);
|
||||||
$message = (string) isset($field['validate']['message']) ? $field['validate']['message'] : 'Invalid input in "' . $language->translate($name) . '""';
|
$message = (string) isset($field['validate']['message']) ? $language->translate($field['validate']['message']) : $language->translate('FORM.INVALID_INPUT', null, true) . ' "' . $language->translate($name) . '"';
|
||||||
|
|
||||||
if (method_exists(__CLASS__, $method)) {
|
if (method_exists(__CLASS__, $method)) {
|
||||||
$success = self::$method($value, $validate, $field);
|
$success = self::$method($value, $validate, $field);
|
||||||
@@ -77,6 +83,11 @@ class Validation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special case for files, value is never empty and errors with code 4 instead
|
||||||
|
if (empty($validate['required']) && $field['type'] == 'file' && (isset($value['error']) && ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error'])))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// if this is a YAML field, simply parse it and return the value
|
// if this is a YAML field, simply parse it and return the value
|
||||||
if (isset($field['yaml']) && $field['yaml'] === true) {
|
if (isset($field['yaml']) && $field['yaml'] === true) {
|
||||||
try {
|
try {
|
||||||
@@ -257,6 +268,32 @@ class Validation
|
|||||||
return self::typeArray((array) $value, $params, $field);
|
return self::typeArray((array) $value, $params, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom input: file
|
||||||
|
*
|
||||||
|
* @param mixed $value Value to be validated.
|
||||||
|
* @param array $params Validation parameters.
|
||||||
|
* @param array $field Blueprint for the field.
|
||||||
|
* @return bool True if validation succeeded.
|
||||||
|
*/
|
||||||
|
public static function typeFile($value, array $params, array $field)
|
||||||
|
{
|
||||||
|
return self::typeArray((array) $value, $params, $field);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function filterFile($value, array $params, array $field)
|
||||||
|
{
|
||||||
|
if (isset($field['multiple']) && $field['multiple'] == true) {
|
||||||
|
return (array) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
return reset($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML5 input: select
|
* HTML5 input: select
|
||||||
*
|
*
|
||||||
@@ -588,6 +625,10 @@ class Validation
|
|||||||
|
|
||||||
public static function validateRequired($value, $params)
|
public static function validateRequired($value, $params)
|
||||||
{
|
{
|
||||||
|
if (is_string($value)) {
|
||||||
|
$value = trim($value);
|
||||||
|
}
|
||||||
|
|
||||||
return (bool) $params !== true || !empty($value);
|
return (bool) $params !== true || !empty($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class Debugger
|
|||||||
protected $renderer;
|
protected $renderer;
|
||||||
protected $enabled;
|
protected $enabled;
|
||||||
|
|
||||||
|
protected $timers = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->debugbar = new StandardDebugBar();
|
$this->debugbar = new StandardDebugBar();
|
||||||
@@ -26,7 +28,8 @@ class Debugger
|
|||||||
$this->grav = Grav::instance();
|
$this->grav = Grav::instance();
|
||||||
|
|
||||||
if ($this->enabled()) {
|
if ($this->enabled()) {
|
||||||
$this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('system')));
|
$this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('system'), 'Config'));
|
||||||
|
$this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('plugins'), 'Plugins'));
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -98,15 +101,17 @@ class Debugger
|
|||||||
{
|
{
|
||||||
if ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled')) {
|
if ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled')) {
|
||||||
$this->debugbar['time']->startMeasure($name, $description);
|
$this->debugbar['time']->startMeasure($name, $description);
|
||||||
|
$this->timers[] = $name;
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function stopTimer($name)
|
public function stopTimer($name)
|
||||||
{
|
{
|
||||||
if ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled')) {
|
if (in_array($name, $this->timers) && ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled'))) {
|
||||||
$this->debugbar['time']->stopMeasure($name);
|
$this->debugbar['time']->stopMeasure($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,51 +2,54 @@
|
|||||||
namespace Grav\Common\Errors;
|
namespace Grav\Common\Errors;
|
||||||
|
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
use Whoops\Handler\CallbackHandler;
|
use Whoops;
|
||||||
use Whoops\Handler\HandlerInterface;
|
|
||||||
use Whoops\Run;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Debugger
|
* Class Debugger
|
||||||
* @package Grav\Common
|
* @package Grav\Common
|
||||||
*/
|
*/
|
||||||
class Errors extends \Whoops\Run
|
class Errors
|
||||||
{
|
{
|
||||||
|
|
||||||
public function pushHandler($handler, $key = null)
|
|
||||||
{
|
|
||||||
if (is_callable($handler)) {
|
|
||||||
$handler = new CallbackHandler($handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$handler instanceof HandlerInterface) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"Argument to " . __METHOD__ . " must be a callable, or instance of"
|
|
||||||
. "Whoops\\Handler\\HandlerInterface"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store with key if provided
|
|
||||||
if ($key) {
|
|
||||||
$this->handlerStack[$key] = $handler;
|
|
||||||
} else {
|
|
||||||
$this->handlerStack[] = $handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resetHandlers()
|
public function resetHandlers()
|
||||||
{
|
{
|
||||||
$grav = Grav::instance();
|
$grav = Grav::instance();
|
||||||
$config = $grav['config']->get('system.errors');
|
$config = $grav['config']->get('system.errors');
|
||||||
if (isset($config['display']) && !$config['display']) {
|
|
||||||
unset($this->handlerStack['pretty']);
|
|
||||||
$this->handlerStack = array('simple' => new SimplePageHandler()) + $this->handlerStack;
|
|
||||||
}
|
|
||||||
if (isset($config['log']) && !$config['log']) {
|
|
||||||
unset($this->handlerStack['log']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Setup Whoops-based error handler
|
||||||
|
$whoops = new \Whoops\Run;
|
||||||
|
|
||||||
|
if (isset($config['display'])) {
|
||||||
|
if ($config['display']) {
|
||||||
|
$error_page = new Whoops\Handler\PrettyPageHandler;
|
||||||
|
$error_page->setPageTitle('Crikey! There was an error...');
|
||||||
|
$error_page->addResourcePath(GRAV_ROOT . '/system/assets');
|
||||||
|
$error_page->addCustomCss('whoops.css');
|
||||||
|
$whoops->pushHandler($error_page);
|
||||||
|
} else {
|
||||||
|
$whoops->pushHandler(new SimplePageHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_exists('Whoops\isAjaxRequest')) { //Whoops 2
|
||||||
|
if (Whoops\isAjaxRequest()) {
|
||||||
|
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
|
||||||
|
}
|
||||||
|
} else { //Whoops 1
|
||||||
|
$json_page = new Whoops\Handler\JsonResponseHandler;
|
||||||
|
$json_page->onlyForAjaxRequests(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($config['log']) && $config['log']) {
|
||||||
|
$logger = $grav['log'];
|
||||||
|
$whoops->pushHandler(function($exception, $inspector, $run) use ($logger) {
|
||||||
|
try {
|
||||||
|
$logger->addCritical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
echo $e;
|
||||||
|
}
|
||||||
|
}, 'log');
|
||||||
|
}
|
||||||
|
|
||||||
|
$whoops->register();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ trait CompiledFile
|
|||||||
|| $cache['filename'] != $this->filename
|
|| $cache['filename'] != $this->filename
|
||||||
) {
|
) {
|
||||||
// Attempt to lock the file for writing.
|
// Attempt to lock the file for writing.
|
||||||
$file->lock(false);
|
try {
|
||||||
|
$file->lock(false);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Another process has locked the file; we will check this in a bit.
|
||||||
|
}
|
||||||
|
|
||||||
// Decode RAW file into compiled array.
|
// Decode RAW file into compiled array.
|
||||||
$data = (array) $this->decode($this->raw());
|
$data = (array) $this->decode($this->raw());
|
||||||
@@ -64,6 +68,7 @@ trait CompiledFile
|
|||||||
$file->unlock();
|
$file->unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$file->free();
|
||||||
|
|
||||||
$this->content = $cache['data'];
|
$this->content = $cache['data'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ abstract class Folder
|
|||||||
{
|
{
|
||||||
$last_modified = 0;
|
$last_modified = 0;
|
||||||
|
|
||||||
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
$directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||||
$filterItr = new RecursiveFolderFilterIterator($dirItr);
|
$filter = new RecursiveFolderFilterIterator($directory);
|
||||||
$itr = new \RecursiveIteratorIterator($filterItr, \RecursiveIteratorIterator::SELF_FIRST);
|
$iterator = new \RecursiveIteratorIterator($filter, \RecursiveIteratorIterator::SELF_FIRST);
|
||||||
|
|
||||||
/** @var \RecursiveDirectoryIterator $file */
|
/** @var \RecursiveDirectoryIterator $file */
|
||||||
foreach ($itr as $dir) {
|
foreach ($iterator as $dir) {
|
||||||
$dir_modified = $dir->getMTime();
|
$dir_modified = $dir->getMTime();
|
||||||
if ($dir_modified > $last_modified) {
|
if ($dir_modified > $last_modified) {
|
||||||
$last_modified = $dir_modified;
|
$last_modified = $dir_modified;
|
||||||
@@ -46,12 +46,12 @@ abstract class Folder
|
|||||||
{
|
{
|
||||||
$last_modified = 0;
|
$last_modified = 0;
|
||||||
|
|
||||||
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
$directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||||
$itrItr = new \RecursiveIteratorIterator($dirItr, \RecursiveIteratorIterator::SELF_FIRST);
|
$recursive = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||||
$itr = new \RegexIterator($itrItr, '/^.+\.'.$extensions.'$/i');
|
$iterator = new \RegexIterator($recursive, '/^.+\.'.$extensions.'$/i');
|
||||||
|
|
||||||
/** @var \RecursiveDirectoryIterator $file */
|
/** @var \RecursiveDirectoryIterator $file */
|
||||||
foreach ($itr as $filepath => $file) {
|
foreach ($iterator as $filepath => $file) {
|
||||||
$file_modified = $file->getMTime();
|
$file_modified = $file->getMTime();
|
||||||
if ($file_modified > $last_modified) {
|
if ($file_modified > $last_modified) {
|
||||||
$last_modified = $file_modified;
|
$last_modified = $file_modified;
|
||||||
@@ -81,6 +81,43 @@ abstract class Folder
|
|||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get relative path between target and base path. If path isn't relative, return full path.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param string $base
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getRelativePathDotDot($path, $base)
|
||||||
|
{
|
||||||
|
$base = preg_replace('![\\\/]+!', '/', $base);
|
||||||
|
$path = preg_replace('![\\\/]+!', '/', $path);
|
||||||
|
|
||||||
|
if ($path === $base) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseParts = explode('/', isset($base[0]) && '/' === $base[0] ? substr($base, 1) : $base);
|
||||||
|
$pathParts = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
|
||||||
|
|
||||||
|
array_pop($baseParts);
|
||||||
|
$lastPart = array_pop($pathParts);
|
||||||
|
foreach ($baseParts as $i => $directory) {
|
||||||
|
if (isset($pathParts[$i]) && $pathParts[$i] === $directory) {
|
||||||
|
unset($baseParts[$i], $pathParts[$i]);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$pathParts[] = $lastPart;
|
||||||
|
$path = str_repeat('../', count($baseParts)) . implode('/', $pathParts);
|
||||||
|
|
||||||
|
return '' === $path
|
||||||
|
|| '/' === $path[0]
|
||||||
|
|| false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
|
||||||
|
? "./$path" : $path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shift first directory out of the path.
|
* Shift first directory out of the path.
|
||||||
*
|
*
|
||||||
@@ -96,8 +133,6 @@ abstract class Folder
|
|||||||
return $result ?: null;
|
return $result ?: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return recursive list of all files and directories under given path.
|
* Return recursive list of all files and directories under given path.
|
||||||
*
|
*
|
||||||
@@ -116,13 +151,17 @@ abstract class Folder
|
|||||||
$pattern = isset($params['pattern']) ? $params['pattern'] : null;
|
$pattern = isset($params['pattern']) ? $params['pattern'] : null;
|
||||||
$filters = isset($params['filters']) ? $params['filters'] : null;
|
$filters = isset($params['filters']) ? $params['filters'] : null;
|
||||||
$recursive = isset($params['recursive']) ? $params['recursive'] : true;
|
$recursive = isset($params['recursive']) ? $params['recursive'] : true;
|
||||||
|
$levels = isset($params['levels']) ? $params['levels'] : -1;
|
||||||
$key = isset($params['key']) ? 'get' . $params['key'] : null;
|
$key = isset($params['key']) ? 'get' . $params['key'] : null;
|
||||||
$value = isset($params['value']) ? 'get' . $params['value'] : ($recursive ? 'getSubPathname' : 'getFilename');
|
$value = isset($params['value']) ? 'get' . $params['value'] : ($recursive ? 'getSubPathname' : 'getFilename');
|
||||||
|
$folders = isset($params['folders']) ? $params['folders'] : true;
|
||||||
|
$files = isset($params['files']) ? $params['files'] : true;
|
||||||
|
|
||||||
if ($recursive) {
|
if ($recursive) {
|
||||||
$directory = new \RecursiveDirectoryIterator($path,
|
$directory = new \RecursiveDirectoryIterator($path,
|
||||||
\RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF);
|
\RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF);
|
||||||
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||||
|
$iterator->setMaxDepth(max($levels, -1));
|
||||||
} else {
|
} else {
|
||||||
$iterator = new \FilesystemIterator($path);
|
$iterator = new \FilesystemIterator($path);
|
||||||
}
|
}
|
||||||
@@ -131,6 +170,16 @@ abstract class Folder
|
|||||||
|
|
||||||
/** @var \RecursiveDirectoryIterator $file */
|
/** @var \RecursiveDirectoryIterator $file */
|
||||||
foreach ($iterator as $file) {
|
foreach ($iterator as $file) {
|
||||||
|
// Ignore hidden files.
|
||||||
|
if ($file->getFilename()[0] == '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$folders && $file->isDir()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$files && $file->isFile()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ($compare && $pattern && !preg_match($pattern, $file->{$compare}())) {
|
if ($compare && $pattern && !preg_match($pattern, $file->{$compare}())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -138,7 +187,8 @@ abstract class Folder
|
|||||||
$filePath = $file->{$value}();
|
$filePath = $file->{$value}();
|
||||||
if ($filters) {
|
if ($filters) {
|
||||||
if (isset($filters['key'])) {
|
if (isset($filters['key'])) {
|
||||||
$fileKey = preg_replace($filters['key'], '', $fileKey);
|
$pre = !empty($filters['pre-key']) ? $filters['pre-key'] : '';
|
||||||
|
$fileKey = $pre . preg_replace($filters['key'], '', $fileKey);
|
||||||
}
|
}
|
||||||
if (isset($filters['value'])) {
|
if (isset($filters['value'])) {
|
||||||
$filter = $filters['value'];
|
$filter = $filters['value'];
|
||||||
@@ -146,12 +196,12 @@ abstract class Folder
|
|||||||
$filePath = call_user_func($filter, $file);
|
$filePath = call_user_func($filter, $file);
|
||||||
} else {
|
} else {
|
||||||
$filePath = preg_replace($filter, '', $filePath);
|
$filePath = preg_replace($filter, '', $filePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($fileKey !== null) {
|
if ($fileKey !== null) {
|
||||||
$results[$fileKey] = $filePath;
|
$results[$fileKey] = $filePath;
|
||||||
} else {
|
} else {
|
||||||
$results[] = $filePath;
|
$results[] = $filePath;
|
||||||
}
|
}
|
||||||
@@ -163,11 +213,12 @@ abstract class Folder
|
|||||||
/**
|
/**
|
||||||
* Recursively copy directory in filesystem.
|
* Recursively copy directory in filesystem.
|
||||||
*
|
*
|
||||||
* @param string $source
|
* @param string $source
|
||||||
* @param string $target
|
* @param string $target
|
||||||
|
* @param string $ignore Ignore files matching pattern (regular expression).
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public static function copy($source, $target)
|
public static function copy($source, $target, $ignore = null)
|
||||||
{
|
{
|
||||||
$source = rtrim($source, '\\/');
|
$source = rtrim($source, '\\/');
|
||||||
$target = rtrim($target, '\\/');
|
$target = rtrim($target, '\\/');
|
||||||
@@ -177,19 +228,24 @@ abstract class Folder
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that path to the target exists before copying.
|
// Make sure that path to the target exists before copying.
|
||||||
self::mkdir($target);
|
self::create($target);
|
||||||
|
|
||||||
$success = true;
|
$success = true;
|
||||||
|
|
||||||
// Go through all sub-directories and copy everything.
|
// Go through all sub-directories and copy everything.
|
||||||
$files = self::all($source);
|
$files = self::all($source);
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
|
if ($ignore && preg_match($ignore, $file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$src = $source .'/'. $file;
|
$src = $source .'/'. $file;
|
||||||
$dst = $target .'/'. $file;
|
$dst = $target .'/'. $file;
|
||||||
|
|
||||||
if (is_dir($src)) {
|
if (is_dir($src)) {
|
||||||
// Create current directory.
|
// Create current directory (if it doesn't exist).
|
||||||
$success &= @mkdir($dst);
|
if (!is_dir($dst)) {
|
||||||
|
$success &= @mkdir($dst, 0777, true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Or copy current file.
|
// Or copy current file.
|
||||||
$success &= @copy($src, $dst);
|
$success &= @copy($src, $dst);
|
||||||
@@ -208,8 +264,8 @@ abstract class Folder
|
|||||||
/**
|
/**
|
||||||
* Move directory in filesystem.
|
* Move directory in filesystem.
|
||||||
*
|
*
|
||||||
* @param string $source
|
* @param string $source
|
||||||
* @param string $target
|
* @param string $target
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public static function move($source, $target)
|
public static function move($source, $target)
|
||||||
@@ -218,8 +274,13 @@ abstract class Folder
|
|||||||
throw new \RuntimeException('Cannot move non-existing folder.');
|
throw new \RuntimeException('Cannot move non-existing folder.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't do anything if the source is the same as the new target
|
||||||
|
if ($source == $target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that path to the target exists before moving.
|
// Make sure that path to the target exists before moving.
|
||||||
self::mkdir(dirname($target));
|
self::create(dirname($target));
|
||||||
|
|
||||||
// Just rename the directory.
|
// Just rename the directory.
|
||||||
$success = @rename($source, $target);
|
$success = @rename($source, $target);
|
||||||
@@ -238,16 +299,16 @@ abstract class Folder
|
|||||||
* Recursively delete directory from filesystem.
|
* Recursively delete directory from filesystem.
|
||||||
*
|
*
|
||||||
* @param string $target
|
* @param string $target
|
||||||
* @throws \RuntimeException
|
* @param bool $include_target
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function delete($target)
|
public static function delete($target, $include_target = true)
|
||||||
{
|
{
|
||||||
if (!is_dir($target)) {
|
if (!is_dir($target)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$success = self::doDelete($target);
|
$success = self::doDelete($target, $include_target);
|
||||||
|
|
||||||
if (!$success) {
|
if (!$success) {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
@@ -255,16 +316,31 @@ abstract class Folder
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the change will be detected when caching.
|
// Make sure that the change will be detected when caching.
|
||||||
@touch(dirname($target));
|
if ($include_target) {
|
||||||
|
@touch(dirname($target));
|
||||||
|
} else {
|
||||||
|
@touch($target);
|
||||||
|
}
|
||||||
|
|
||||||
return $success;
|
return $success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $folder
|
* @param string $folder
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public static function mkdir($folder)
|
public static function mkdir($folder)
|
||||||
|
{
|
||||||
|
self::create($folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $folder
|
||||||
|
* @throws \RuntimeException
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public static function create($folder)
|
||||||
{
|
{
|
||||||
if (is_dir($folder)) {
|
if (is_dir($folder)) {
|
||||||
return;
|
return;
|
||||||
@@ -320,10 +396,11 @@ abstract class Folder
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $folder
|
* @param string $folder
|
||||||
|
* @param bool $include_target
|
||||||
* @return bool
|
* @return bool
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
protected static function doDelete($folder)
|
protected static function doDelete($folder, $include_target = true)
|
||||||
{
|
{
|
||||||
// Special case for symbolic links.
|
// Special case for symbolic links.
|
||||||
if (is_link($folder)) {
|
if (is_link($folder)) {
|
||||||
@@ -338,16 +415,16 @@ abstract class Folder
|
|||||||
/** @var \DirectoryIterator $fileinfo */
|
/** @var \DirectoryIterator $fileinfo */
|
||||||
foreach ($files as $fileinfo) {
|
foreach ($files as $fileinfo) {
|
||||||
if ($fileinfo->isDir()) {
|
if ($fileinfo->isDir()) {
|
||||||
if (false === rmdir($fileinfo->getRealPath())) {
|
if (false === @rmdir($fileinfo->getRealPath())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (false === unlink($fileinfo->getRealPath())) {
|
if (false === @unlink($fileinfo->getRealPath())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rmdir($folder);
|
return $include_target ? @rmdir($folder) : true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -323,13 +323,24 @@ class GPM extends Iterator
|
|||||||
return $found;
|
return $found;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->getRepositoryThemes() as $slug => $theme) {
|
$themes = $this->getRepositoryThemes();
|
||||||
|
$plugins = $this->getRepositoryPlugins();
|
||||||
|
|
||||||
|
if (!$themes && !$plugins) {
|
||||||
|
if (!is_writable(ROOT_DIR . '/cache/gpm')) {
|
||||||
|
throw new \RuntimeException("The cache/gpm folder is not writable. Please check the folder permissions.");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \RuntimeException("GPM not reachable. Please check your internet connection or check the Grav site is reachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($themes) foreach ($themes as $slug => $theme) {
|
||||||
if ($search == $slug || $search == $theme->name) {
|
if ($search == $slug || $search == $theme->name) {
|
||||||
return $theme;
|
return $theme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->getRepositoryPlugins() as $slug => $plugin) {
|
if ($plugins) foreach ($plugins as $slug => $plugin) {
|
||||||
if ($search == $slug || $search == $plugin->name) {
|
if ($search == $slug || $search == $plugin->name) {
|
||||||
return $plugin;
|
return $plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,6 +281,10 @@ class Installer
|
|||||||
{
|
{
|
||||||
$msg = 'Unknown Error';
|
$msg = 'Unknown Error';
|
||||||
|
|
||||||
|
if (is_string(self::$error)) {
|
||||||
|
return self::$error;
|
||||||
|
}
|
||||||
|
|
||||||
switch (self::$error) {
|
switch (self::$error) {
|
||||||
case 0:
|
case 0:
|
||||||
$msg = 'No Error';
|
$msg = 'No Error';
|
||||||
@@ -333,7 +337,7 @@ class Installer
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to manually set an error
|
* Allows to manually set an error
|
||||||
* @param $error the Error code
|
* @param int|string $error the Error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static function setError($error)
|
public static function setError($error)
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
namespace Grav\Common\GPM\Local;
|
namespace Grav\Common\GPM\Local;
|
||||||
|
|
||||||
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
||||||
use Grav\Common\GPM\Local\Package;
|
|
||||||
|
|
||||||
abstract class AbstractPackageCollection extends BaseCollection {
|
|
||||||
|
|
||||||
|
abstract class AbstractPackageCollection extends BaseCollection
|
||||||
|
{
|
||||||
public function __construct($items)
|
public function __construct($items)
|
||||||
{
|
{
|
||||||
foreach ($items as $name => $data) {
|
foreach ($items as $name => $data) {
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Grav\Common\GPM;
|
|
||||||
|
|
||||||
use Grav\Common\Data\Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface Package
|
|
||||||
* @package Grav\Common\GPM
|
|
||||||
*/
|
|
||||||
class Package
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var Data
|
|
||||||
*/
|
|
||||||
protected $data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Grav\Common\Data\Blueprint
|
|
||||||
*/
|
|
||||||
protected $blueprints;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Data $package
|
|
||||||
* @param bool $package_type
|
|
||||||
*/
|
|
||||||
public function __construct(Data $package, $package_type = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function isEnabled();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Data
|
|
||||||
*/
|
|
||||||
public function getData();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __toString();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function toJson();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray();
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ namespace Grav\Common\GPM\Remote;
|
|||||||
|
|
||||||
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
||||||
use Grav\Common\GPM\Response;
|
use Grav\Common\GPM\Response;
|
||||||
|
|
||||||
use \Doctrine\Common\Cache\FilesystemCache;
|
use \Doctrine\Common\Cache\FilesystemCache;
|
||||||
|
|
||||||
class AbstractPackageCollection extends BaseCollection
|
class AbstractPackageCollection extends BaseCollection
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use \Doctrine\Common\Cache\FilesystemCache;
|
|||||||
|
|
||||||
class Grav extends AbstractPackageCollection
|
class Grav extends AbstractPackageCollection
|
||||||
{
|
{
|
||||||
protected $repository = 'http://getgrav.org/downloads/grav.json';
|
protected $repository = 'https://getgrav.org/downloads/grav.json';
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
private $version;
|
private $version;
|
||||||
@@ -55,7 +55,7 @@ class Grav extends AbstractPackageCollection
|
|||||||
|
|
||||||
$diffLog = [];
|
$diffLog = [];
|
||||||
foreach ($this->data['changelog'] as $version => $changelog) {
|
foreach ($this->data['changelog'] as $version => $changelog) {
|
||||||
preg_match("/[\d\.]+/", $version, $cleanVersion);
|
preg_match("/[\w-\.]+/", $version, $cleanVersion);
|
||||||
|
|
||||||
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], ">=")) { continue; }
|
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], ">=")) { continue; }
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ class Plugins extends AbstractPackageCollection
|
|||||||
*/
|
*/
|
||||||
protected $type = 'plugins';
|
protected $type = 'plugins';
|
||||||
|
|
||||||
protected $repository = 'http://getgrav.org/downloads/plugins.json';
|
protected $repository = 'https://getgrav.org/downloads/plugins.json';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Plugins Constructor
|
* Local Plugins Constructor
|
||||||
|
* @param bool $refresh
|
||||||
|
* @param callable $callback Either a function or callback in array notation
|
||||||
*/
|
*/
|
||||||
public function __construct($refresh = false, $callback = null)
|
public function __construct($refresh = false, $callback = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ class Themes extends AbstractPackageCollection
|
|||||||
*/
|
*/
|
||||||
protected $type = 'themes';
|
protected $type = 'themes';
|
||||||
|
|
||||||
protected $repository = 'http://getgrav.org/downloads/themes.json';
|
protected $repository = 'https://getgrav.org/downloads/themes.json';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Themes Constructor
|
* Local Themes Constructor
|
||||||
|
* @param bool $refresh
|
||||||
|
* @param callable $callback Either a function or callback in array notation
|
||||||
*/
|
*/
|
||||||
public function __construct($refresh = false, $callback = null)
|
public function __construct($refresh = false, $callback = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,27 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\GPM;
|
namespace Grav\Common\GPM;
|
||||||
|
|
||||||
|
use Grav\Common\Utils;
|
||||||
|
|
||||||
class Response
|
class Response
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The callback for the progress
|
* The callback for the progress
|
||||||
|
*
|
||||||
* @var callable Either a function or callback in array notation
|
* @var callable Either a function or callback in array notation
|
||||||
*/
|
*/
|
||||||
public static $callback = null;
|
public static $callback = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Which method to use for HTTP calls, can be 'curl', 'fopen' or 'auto'. Auto is default and fopen is the preferred method
|
* Which method to use for HTTP calls, can be 'curl', 'fopen' or 'auto'. Auto is default and fopen is the preferred method
|
||||||
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $method = 'auto';
|
private static $method = 'auto';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default parameters for `curl` and `fopen`
|
* Default parameters for `curl` and `fopen`
|
||||||
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $defaults = [
|
private static $defaults = [
|
||||||
|
|
||||||
'curl' => [
|
'curl' => [
|
||||||
CURLOPT_REFERER => 'Grav GPM',
|
CURLOPT_REFERER => 'Grav GPM',
|
||||||
CURLOPT_USERAGENT => 'Grav GPM',
|
CURLOPT_USERAGENT => 'Grav GPM',
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
@@ -49,7 +54,10 @@ class Response
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the preferred method to use for making HTTP calls.
|
* Sets the preferred method to use for making HTTP calls.
|
||||||
|
*
|
||||||
* @param string $method Default is `auto`
|
* @param string $method Default is `auto`
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public static function setMethod($method = 'auto')
|
public static function setMethod($method = 'auto')
|
||||||
{
|
{
|
||||||
@@ -64,8 +72,11 @@ class Response
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a request to the URL by using the preferred method
|
* Makes a request to the URL by using the preferred method
|
||||||
* @param string $uri URL to call
|
*
|
||||||
* @param array $options An array of parameters for both `curl` and `fopen`
|
* @param string $uri URL to call
|
||||||
|
* @param array $options An array of parameters for both `curl` and `fopen`
|
||||||
|
* @param callable $callback Either a function or callback in array notation
|
||||||
|
*
|
||||||
* @return string The response of the request
|
* @return string The response of the request
|
||||||
*/
|
*/
|
||||||
public static function get($uri = '', $options = [], $callback = null)
|
public static function get($uri = '', $options = [], $callback = null)
|
||||||
@@ -74,6 +85,14 @@ class Response
|
|||||||
throw new \RuntimeException('Could not start an HTTP request. `allow_url_open` is disabled and `cURL` is not available');
|
throw new \RuntimeException('Could not start an HTTP request. `allow_url_open` is disabled and `cURL` is not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if this function is available, if so use it to stop any timeouts
|
||||||
|
try {
|
||||||
|
if (!Utils::isFunctionDisabled('set_time_limit') && !ini_get('safe_mode') && function_exists('set_time_limit')) {
|
||||||
|
set_time_limit(0);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
$options = array_replace_recursive(self::$defaults, $options);
|
$options = array_replace_recursive(self::$defaults, $options);
|
||||||
$method = 'get' . ucfirst(strtolower(self::$method));
|
$method = 'get' . ucfirst(strtolower(self::$method));
|
||||||
|
|
||||||
@@ -81,9 +100,31 @@ class Response
|
|||||||
return static::$method($uri, $options, $callback);
|
return static::$method($uri, $options, $callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if cURL is available
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function isCurlAvailable()
|
||||||
|
{
|
||||||
|
return function_exists('curl_version');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the remote fopen request is enabled in PHP
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function isFopenAvailable()
|
||||||
|
{
|
||||||
|
return preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Progress normalized for cURL and Fopen
|
* Progress normalized for cURL and Fopen
|
||||||
|
*
|
||||||
* @param args Variable length of arguments passed in by stream method
|
* @param args Variable length of arguments passed in by stream method
|
||||||
|
*
|
||||||
* @return array Normalized array with useful data.
|
* @return array Normalized array with useful data.
|
||||||
* Format: ['code' => int|false, 'filesize' => bytes, 'transferred' => bytes, 'percent' => int]
|
* Format: ['code' => int|false, 'filesize' => bytes, 'transferred' => bytes, 'percent' => int]
|
||||||
*/
|
*/
|
||||||
@@ -104,7 +145,7 @@ class Response
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($bytes_transferred > 0) {
|
if ($bytes_transferred > 0) {
|
||||||
if ($notification_code == STREAM_NOTIFY_PROGRESS|STREAM_NOTIFY_COMPLETED || $isCurlResource) {
|
if ($notification_code == STREAM_NOTIFY_PROGRESS | STREAM_NOTIFY_COMPLETED || $isCurlResource) {
|
||||||
|
|
||||||
$progress = [
|
$progress = [
|
||||||
'code' => $notification_code,
|
'code' => $notification_code,
|
||||||
@@ -120,31 +161,14 @@ class Response
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if cURL is available
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public static function isCurlAvailable()
|
|
||||||
{
|
|
||||||
return function_exists('curl_version');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the remote fopen request is enabled in PHP
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public static function isFopenAvailable()
|
|
||||||
{
|
|
||||||
return preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automatically picks the preferred method
|
* Automatically picks the preferred method
|
||||||
|
*
|
||||||
* @return string The response of the request
|
* @return string The response of the request
|
||||||
*/
|
*/
|
||||||
private static function getAuto()
|
private static function getAuto()
|
||||||
{
|
{
|
||||||
if (self::isFopenAvailable()) {
|
if (!ini_get('open_basedir') && self::isFopenAvailable()) {
|
||||||
return self::getFopen(func_get_args());
|
return self::getFopen(func_get_args());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,46 +177,9 @@ class Response
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a HTTP request via cURL
|
|
||||||
* @return string The response of the request
|
|
||||||
*/
|
|
||||||
private static function getCurl()
|
|
||||||
{
|
|
||||||
$args = func_get_args();
|
|
||||||
$args = count($args) > 1 ? $args : array_shift($args);
|
|
||||||
|
|
||||||
$uri = $args[0];
|
|
||||||
$options = $args[1];
|
|
||||||
$callback = $args[2];
|
|
||||||
|
|
||||||
$ch = curl_init($uri);
|
|
||||||
curl_setopt_array($ch, $options['curl']);
|
|
||||||
|
|
||||||
if ($callback) {
|
|
||||||
curl_setopt_array(
|
|
||||||
$ch,
|
|
||||||
[
|
|
||||||
CURLOPT_NOPROGRESS => false,
|
|
||||||
CURLOPT_PROGRESSFUNCTION => ['self', 'progress']
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = curl_exec($ch);
|
|
||||||
|
|
||||||
if ($errno = curl_errno($ch)) {
|
|
||||||
$error_message = curl_strerror($errno);
|
|
||||||
throw new \RuntimeException("cURL error ({$errno}):\n {$error_message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a HTTP request via fopen
|
* Starts a HTTP request via fopen
|
||||||
|
*
|
||||||
* @return string The response of the request
|
* @return string The response of the request
|
||||||
*/
|
*/
|
||||||
private static function getFopen()
|
private static function getFopen()
|
||||||
@@ -218,4 +205,99 @@ class Response
|
|||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a HTTP request via cURL
|
||||||
|
*
|
||||||
|
* @return string The response of the request
|
||||||
|
*/
|
||||||
|
private static function getCurl()
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$args = count($args) > 1 ? $args : array_shift($args);
|
||||||
|
|
||||||
|
$uri = $args[0];
|
||||||
|
$options = $args[1];
|
||||||
|
$callback = $args[2];
|
||||||
|
|
||||||
|
$ch = curl_init($uri);
|
||||||
|
|
||||||
|
$response = static::_curl_exec_follow($ch, $options, $callback);
|
||||||
|
|
||||||
|
if ($errno = curl_errno($ch)) {
|
||||||
|
$error_message = curl_strerror($errno);
|
||||||
|
throw new \RuntimeException("cURL error ({$errno}):\n {$error_message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _curl_exec_follow($ch, $options, $callback)
|
||||||
|
{
|
||||||
|
if ($callback) {
|
||||||
|
curl_setopt_array(
|
||||||
|
$ch,
|
||||||
|
[
|
||||||
|
CURLOPT_NOPROGRESS => false,
|
||||||
|
CURLOPT_PROGRESSFUNCTION => ['self', 'progress']
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no open_basedir set, we can proceed normally
|
||||||
|
if (!ini_get('open_basedir')) {
|
||||||
|
curl_setopt_array($ch, $options['curl']);
|
||||||
|
return curl_exec($ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
$max_redirects = isset($options['curl'][CURLOPT_MAXREDIRS]) ? $options['curl'][CURLOPT_MAXREDIRS] : 3;
|
||||||
|
$options['curl'][CURLOPT_FOLLOWLOCATION] = false;
|
||||||
|
|
||||||
|
// open_basedir set but no redirects to follow, we can disable followlocation and proceed normally
|
||||||
|
curl_setopt_array($ch, $options['curl']);
|
||||||
|
if ($max_redirects <= 0) {
|
||||||
|
return curl_exec($ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
|
||||||
|
$rch = curl_copy_handle($ch);
|
||||||
|
|
||||||
|
curl_setopt($rch, CURLOPT_HEADER, true);
|
||||||
|
curl_setopt($rch, CURLOPT_NOBODY, true);
|
||||||
|
curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
|
||||||
|
curl_setopt($rch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
do {
|
||||||
|
curl_setopt($rch, CURLOPT_URL, $uri);
|
||||||
|
$header = curl_exec($rch);
|
||||||
|
|
||||||
|
if (curl_errno($rch)) {
|
||||||
|
$code = 0;
|
||||||
|
} else {
|
||||||
|
$code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
|
||||||
|
if ($code == 301 || $code == 302) {
|
||||||
|
preg_match('/Location:(.*?)\n/', $header, $matches);
|
||||||
|
$uri = trim(array_pop($matches));
|
||||||
|
} else {
|
||||||
|
$code = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ($code && --$max_redirects);
|
||||||
|
|
||||||
|
curl_close($rch);
|
||||||
|
|
||||||
|
if (!$max_redirects) {
|
||||||
|
if ($max_redirects === null) {
|
||||||
|
trigger_error('Too many redirects. When following redirects, libcurl hit the maximum amount.', E_USER_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $uri);
|
||||||
|
|
||||||
|
return curl_exec($ch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\GPM;
|
namespace Grav\Common\GPM;
|
||||||
|
|
||||||
|
use Grav\Common\Grav;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Upgrader
|
||||||
|
*
|
||||||
|
* @package Grav\Common\GPM
|
||||||
|
*/
|
||||||
class Upgrader
|
class Upgrader
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Remote details about latest Grav version
|
* Remote details about latest Grav version
|
||||||
|
*
|
||||||
* @var Packages
|
* @var Packages
|
||||||
*/
|
*/
|
||||||
private $remote;
|
private $remote;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal cache
|
* Internal cache
|
||||||
|
*
|
||||||
* @var Iterator
|
* @var Iterator
|
||||||
*/
|
*/
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new GPM instance with Local and Remote packages available
|
* Creates a new GPM instance with Local and Remote packages available
|
||||||
|
*
|
||||||
* @param boolean $refresh Applies to Remote Packages only and forces a refetch of data
|
* @param boolean $refresh Applies to Remote Packages only and forces a refetch of data
|
||||||
* @param callable $callback Either a function or callback in array notation
|
* @param callable $callback Either a function or callback in array notation
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +37,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the release date of the latest version of Grav
|
* Returns the release date of the latest version of Grav
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getReleaseDate()
|
public function getReleaseDate()
|
||||||
@@ -36,6 +47,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the version of the installed Grav
|
* Returns the version of the installed Grav
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLocalVersion()
|
public function getLocalVersion()
|
||||||
@@ -45,6 +57,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the version of the remotely available Grav
|
* Returns the version of the remotely available Grav
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getRemoteVersion()
|
public function getRemoteVersion()
|
||||||
@@ -54,6 +67,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of assets available to download remotely
|
* Returns an array of assets available to download remotely
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getAssets()
|
public function getAssets()
|
||||||
@@ -63,6 +77,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the changelog list for each version of Grav
|
* Returns the changelog list for each version of Grav
|
||||||
|
*
|
||||||
* @param string $diff the version number to start the diff from
|
* @param string $diff the version number to start the diff from
|
||||||
*
|
*
|
||||||
* @return array return the changelog list for each version
|
* @return array return the changelog list for each version
|
||||||
@@ -72,8 +87,21 @@ class Upgrader
|
|||||||
return $this->remote->getChangelog($diff);
|
return $this->remote->getChangelog($diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function meetsRequirements()
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, GRAV_PHP_MIN, '<')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the currently installed Grav is upgradable to a newer version
|
* Checks if the currently installed Grav is upgradable to a newer version
|
||||||
|
*
|
||||||
* @return boolean True if it's upgradable, False otherwise.
|
* @return boolean True if it's upgradable, False otherwise.
|
||||||
*/
|
*/
|
||||||
public function isUpgradable()
|
public function isUpgradable()
|
||||||
@@ -83,6 +111,7 @@ class Upgrader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if Grav is currently symbolically linked
|
* Checks if Grav is currently symbolically linked
|
||||||
|
*
|
||||||
* @return boolean True if Grav is symlinked, False otherwise.
|
* @return boolean True if Grav is symlinked, False otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ class Grav extends Container
|
|||||||
|
|
||||||
$container['grav'] = $container;
|
$container['grav'] = $container;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$container['debugger'] = new Debugger();
|
$container['debugger'] = new Debugger();
|
||||||
$container['debugger']->startTimer('_init', 'Initialize');
|
$container['debugger']->startTimer('_init', 'Initialize');
|
||||||
|
|
||||||
@@ -114,7 +112,7 @@ class Grav extends Container
|
|||||||
/** @var Uri $uri */
|
/** @var Uri $uri */
|
||||||
$uri = $c['uri'];
|
$uri = $c['uri'];
|
||||||
|
|
||||||
$path = rtrim($uri->path(), '/');
|
$path = $uri->path(); // Don't trim to support trailing slash default routes
|
||||||
$path = $path ?: '/';
|
$path = $path ?: '/';
|
||||||
|
|
||||||
$page = $pages->dispatch($path);
|
$page = $pages->dispatch($path);
|
||||||
@@ -185,8 +183,6 @@ class Grav extends Container
|
|||||||
/** @var Debugger $debugger */
|
/** @var Debugger $debugger */
|
||||||
$debugger = $this['debugger'];
|
$debugger = $this['debugger'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize configuration.
|
// Initialize configuration.
|
||||||
$debugger->startTimer('_config', 'Configuration');
|
$debugger->startTimer('_config', 'Configuration');
|
||||||
$this['config']->init();
|
$this['config']->init();
|
||||||
@@ -201,7 +197,10 @@ class Grav extends Container
|
|||||||
// Use output buffering to prevent headers from being sent too early.
|
// Use output buffering to prevent headers from being sent too early.
|
||||||
ob_start();
|
ob_start();
|
||||||
if ($this['config']->get('system.cache.gzip')) {
|
if ($this['config']->get('system.cache.gzip')) {
|
||||||
ob_start('ob_gzhandler');
|
// Enable zip/deflate with a fallback in case of if browser does not support compressing.
|
||||||
|
if(!ob_start("ob_gzhandler")) {
|
||||||
|
ob_start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the timezone
|
// Initialize the timezone
|
||||||
@@ -227,7 +226,6 @@ class Grav extends Container
|
|||||||
|
|
||||||
$debugger->startTimer('themes', 'Themes');
|
$debugger->startTimer('themes', 'Themes');
|
||||||
$this['themes']->init();
|
$this['themes']->init();
|
||||||
$this->fireEvent('onThemeInitialized');
|
|
||||||
$debugger->stopTimer('themes');
|
$debugger->stopTimer('themes');
|
||||||
|
|
||||||
$task = $this['task'];
|
$task = $this['task'];
|
||||||
@@ -296,7 +294,10 @@ class Grav extends Container
|
|||||||
if ($uri->isExternal($route)) {
|
if ($uri->isExternal($route)) {
|
||||||
$url = $route;
|
$url = $route;
|
||||||
} else {
|
} else {
|
||||||
$url = rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/');
|
if ($this['config']->get('system.pages.redirect_trailing_slash', true))
|
||||||
|
$url = rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/'); // Remove trailing slash
|
||||||
|
else
|
||||||
|
$url = rtrim($uri->rootUrl(), '/') .'/'. ltrim($route, '/'); // Support trailing slash default routes
|
||||||
}
|
}
|
||||||
|
|
||||||
header("Location: {$url}", true, $code);
|
header("Location: {$url}", true, $code);
|
||||||
@@ -412,38 +413,49 @@ class Grav extends Container
|
|||||||
*/
|
*/
|
||||||
public function shutdown()
|
public function shutdown()
|
||||||
{
|
{
|
||||||
if ($this['config']->get('system.debugger.shutdown.close_connection')) {
|
// Prevent user abort allowing onShutdown event to run without interruptions.
|
||||||
//stop user abort
|
if (function_exists('ignore_user_abort')) {
|
||||||
if (function_exists('ignore_user_abort')) {
|
@ignore_user_abort(true);
|
||||||
@ignore_user_abort(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// close the session
|
|
||||||
if (isset($this['session'])) {
|
|
||||||
$this['session']->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush buffer if gzip buffer was started
|
|
||||||
if ($this['config']->get('system.cache.gzip')) {
|
|
||||||
ob_end_flush(); // gzhandler buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// get lengh and close the connection
|
|
||||||
header('Content-Length: ' . ob_get_length());
|
|
||||||
header("Connection: close");
|
|
||||||
|
|
||||||
// flush the regular buffer
|
|
||||||
ob_end_flush();
|
|
||||||
@ob_flush();
|
|
||||||
flush();
|
|
||||||
|
|
||||||
// fix for fastcgi close connection issue
|
|
||||||
if (function_exists('fastcgi_finish_request')) {
|
|
||||||
@fastcgi_finish_request();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the session allowing new requests to be handled.
|
||||||
|
if (isset($this['session'])) {
|
||||||
|
$this['session']->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this['config']->get('system.debugger.shutdown.close_connection', true)) {
|
||||||
|
// Flush the response and close the connection to allow time consuming tasks to be performed without leaving
|
||||||
|
// the connection to the client open. This will make page loads to feel much faster.
|
||||||
|
|
||||||
|
// FastCGI allows us to flush all response data to the client and finish the request.
|
||||||
|
$success = function_exists('fastcgi_finish_request') ? @fastcgi_finish_request() : false;
|
||||||
|
|
||||||
|
if (!$success) {
|
||||||
|
// Unfortunately without FastCGI there is no way to close the connection. We need to ask browser to
|
||||||
|
// close the connection for us.
|
||||||
|
|
||||||
|
if ($this['config']->get('system.cache.gzip')) {
|
||||||
|
// Flush gzhandler buffer if gzip setting was enabled.
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Without gzip we have no other choice than to prevent server from compressing the output.
|
||||||
|
// This action turns off mod_deflate which would prevent us from closing the connection.
|
||||||
|
header('Content-Encoding: none');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get length and close the connection.
|
||||||
|
header('Content-Length: ' . ob_get_length());
|
||||||
|
header("Connection: close");
|
||||||
|
|
||||||
|
// Finally flush the regular buffer.
|
||||||
|
ob_end_flush();
|
||||||
|
@ob_flush();
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run any time consuming tasks.
|
||||||
$this->fireEvent('onShutdown');
|
$this->fireEvent('onShutdown');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,12 +469,26 @@ class Grav extends Container
|
|||||||
/** @var Uri $uri */
|
/** @var Uri $uri */
|
||||||
$uri = $this['uri'];
|
$uri = $this['uri'];
|
||||||
|
|
||||||
|
/** @var Config $config */
|
||||||
|
$config = $this['config'];
|
||||||
|
|
||||||
|
$uri_extension = $uri->extension();
|
||||||
|
$fallback_types = $config->get('system.media.allowed_fallback_types', null);
|
||||||
|
$supported_types = $config->get('media');
|
||||||
|
|
||||||
|
// Check whitelist first, then ensure extension is a valid media type
|
||||||
|
if (!empty($fallback_types) && !in_array($uri_extension, $fallback_types)) {
|
||||||
|
return;
|
||||||
|
} elseif (!array_key_exists($uri_extension, $supported_types)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$path_parts = pathinfo($path);
|
$path_parts = pathinfo($path);
|
||||||
$page = $this['pages']->dispatch($path_parts['dirname'], true);
|
$page = $this['pages']->dispatch($path_parts['dirname'], true);
|
||||||
if ($page) {
|
if ($page) {
|
||||||
$media = $page->media()->all();
|
$media = $page->media()->all();
|
||||||
|
|
||||||
$parsed_url = parse_url(urldecode($uri->basename()));
|
$parsed_url = parse_url(rawurldecode($uri->basename()));
|
||||||
|
|
||||||
$media_file = $parsed_url['path'];
|
$media_file = $parsed_url['path'];
|
||||||
|
|
||||||
@@ -478,7 +504,6 @@ class Grav extends Container
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unsupported media type, try to download it...
|
// unsupported media type, try to download it...
|
||||||
$uri_extension = $uri->extension();
|
|
||||||
if ($uri_extension) {
|
if ($uri_extension) {
|
||||||
$extension = $uri_extension;
|
$extension = $uri_extension;
|
||||||
} else {
|
} else {
|
||||||
@@ -491,7 +516,7 @@ class Grav extends Container
|
|||||||
|
|
||||||
if ($extension) {
|
if ($extension) {
|
||||||
$download = true;
|
$download = true;
|
||||||
if (in_array(ltrim($extension, '.'), $this['config']->get('system.media.unsupported_inline_types', []))) {
|
if (in_array(ltrim($extension, '.'), $config->get('system.media.unsupported_inline_types', []))) {
|
||||||
$download = false;
|
$download = false;
|
||||||
}
|
}
|
||||||
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);
|
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class Truncator {
|
|||||||
$inner .= $txt;
|
$inner .= $txt;
|
||||||
if ($remaining < 0) {
|
if ($remaining < 0) {
|
||||||
if (static::ellipsable($node)) {
|
if (static::ellipsable($node)) {
|
||||||
$inner = preg_replace('/(?:[\s\pP]+|(?:&(?:[a-z]+|#[0-9]+);?))*$/', '', $inner).$opts['ellipsis'];
|
$inner = preg_replace('/(?:[\s\pP]+|(?:&(?:[a-z]+|#[0-9]+);?))*$/u', '', $inner).$opts['ellipsis'];
|
||||||
$opts['ellipsis'] = '';
|
$opts['ellipsis'] = '';
|
||||||
$opts['was_truncated'] = true;
|
$opts['was_truncated'] = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,4 +215,26 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts elements from the list and returns a copy of the list in the proper order
|
||||||
|
*
|
||||||
|
* @param callable|null $callback
|
||||||
|
*
|
||||||
|
* @param bool $desc
|
||||||
|
*
|
||||||
|
* @return $this|array
|
||||||
|
* @internal param bool $asc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function sort(callable $callback = null, $desc = false)
|
||||||
|
{
|
||||||
|
if (!$callback || !is_callable($callback)) { return $this; }
|
||||||
|
|
||||||
|
$items = $this->items;
|
||||||
|
uasort($items, $callback);
|
||||||
|
|
||||||
|
return !$desc ? $items : array_reverse($items, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ class Language
|
|||||||
*/
|
*/
|
||||||
public function setActiveFromUri($uri)
|
public function setActiveFromUri($uri)
|
||||||
{
|
{
|
||||||
$regex = '/(^\/(' . $this->getAvailable() . ')).*/';
|
$regex = '/(^\/(' . $this->getAvailable() . '))(?:\/.*|$)/i';
|
||||||
|
|
||||||
// if languages set
|
// if languages set
|
||||||
if ($this->enabled()) {
|
if ($this->enabled()) {
|
||||||
@@ -352,7 +352,7 @@ class Language
|
|||||||
if ($this->config->get('system.languages.translations_fallback', true)) {
|
if ($this->config->get('system.languages.translations_fallback', true)) {
|
||||||
$languages = $this->getFallbackLanguages();
|
$languages = $this->getFallbackLanguages();
|
||||||
} else {
|
} else {
|
||||||
$languages = (array)$this->getDefault();
|
$languages = (array)$this->getLanguage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ class LanguageCodes
|
|||||||
],
|
],
|
||||||
"fr" => [
|
"fr" => [
|
||||||
"name" => "French",
|
"name" => "French",
|
||||||
"nativeName" => "français"
|
"nativeName" => "Français"
|
||||||
],
|
],
|
||||||
"ff" => [
|
"ff" => [
|
||||||
"name" => "Fula",
|
"name" => "Fula",
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Grav\Common\Markdown;
|
namespace Grav\Common\Markdown;
|
||||||
|
|
||||||
use Grav\Common\Config\Config;
|
|
||||||
use Grav\Common\Debugger;
|
|
||||||
use Grav\Common\GravTrait;
|
use Grav\Common\GravTrait;
|
||||||
use Grav\Common\Page\Medium\Medium;
|
|
||||||
use Grav\Common\Uri;
|
use Grav\Common\Uri;
|
||||||
use Grav\Common\Utils;
|
use RocketTheme\Toolbox\Event\Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A trait to add some custom processing to the identifyLink() method in Parsedown and ParsedownExtra
|
* A trait to add some custom processing to the identifyLink() method in Parsedown and ParsedownExtra
|
||||||
@@ -19,9 +16,11 @@ trait ParsedownGravTrait
|
|||||||
protected $base_url;
|
protected $base_url;
|
||||||
protected $pages_dir;
|
protected $pages_dir;
|
||||||
protected $special_chars;
|
protected $special_chars;
|
||||||
|
|
||||||
protected $twig_link_regex = '/\!*\[(?:.*)\]\((\{([\{%#])\s*(.*?)\s*(?:\2|\})\})\)/';
|
protected $twig_link_regex = '/\!*\[(?:.*)\]\((\{([\{%#])\s*(.*?)\s*(?:\2|\})\})\)/';
|
||||||
|
|
||||||
|
public $completable_blocks = [];
|
||||||
|
public $continuable_blocks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization function to setup key variables needed by the MarkdownGravLinkTrait
|
* Initialization function to setup key variables needed by the MarkdownGravLinkTrait
|
||||||
*
|
*
|
||||||
@@ -30,8 +29,10 @@ trait ParsedownGravTrait
|
|||||||
*/
|
*/
|
||||||
protected function init($page, $defaults)
|
protected function init($page, $defaults)
|
||||||
{
|
{
|
||||||
|
$grav = self::getGrav();
|
||||||
|
|
||||||
$this->page = $page;
|
$this->page = $page;
|
||||||
$this->pages = self::getGrav()['pages'];
|
$this->pages = $grav['pages'];
|
||||||
$this->BlockTypes['{'] [] = "TwigTag";
|
$this->BlockTypes['{'] [] = "TwigTag";
|
||||||
$this->base_url = rtrim(self::getGrav()['base_url'] . self::getGrav()['pages']->base(), '/');
|
$this->base_url = rtrim(self::getGrav()['base_url'] . self::getGrav()['pages']->base(), '/');
|
||||||
$this->pages_dir = self::getGrav()['locator']->findResource('page://');
|
$this->pages_dir = self::getGrav()['locator']->findResource('page://');
|
||||||
@@ -45,8 +46,67 @@ trait ParsedownGravTrait
|
|||||||
$this->setUrlsLinked($defaults['auto_url_links']);
|
$this->setUrlsLinked($defaults['auto_url_links']);
|
||||||
$this->setMarkupEscaped($defaults['escape_markup']);
|
$this->setMarkupEscaped($defaults['escape_markup']);
|
||||||
$this->setSpecialChars($defaults['special_chars']);
|
$this->setSpecialChars($defaults['special_chars']);
|
||||||
|
|
||||||
|
$grav->fireEvent('onMarkdownInitialized', new Event(['markdown' => $this]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Be able to define a new Block type or override an existing one
|
||||||
|
*
|
||||||
|
* @param $type
|
||||||
|
* @param $tag
|
||||||
|
*/
|
||||||
|
public function addBlockType($type, $tag, $continuable = false, $completable = false)
|
||||||
|
{
|
||||||
|
$this->BlockTypes[$type] []= $tag;
|
||||||
|
|
||||||
|
if ($continuable) {
|
||||||
|
$this->continuable_blocks[] = $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($completable) {
|
||||||
|
$this->completable_blocks[] = $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Be able to define a new Inline type or override an existing one
|
||||||
|
*
|
||||||
|
* @param $type
|
||||||
|
* @param $tag
|
||||||
|
*/
|
||||||
|
public function addInlineType($type, $tag)
|
||||||
|
{
|
||||||
|
$this->InlineTypes[$type] []= $tag;
|
||||||
|
$this->inlineMarkerList .= $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the default behavior to allow for plugin-provided blocks to be continuable
|
||||||
|
*
|
||||||
|
* @param $Type
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isBlockContinuable($Type)
|
||||||
|
{
|
||||||
|
$continuable = in_array($Type, $this->continuable_blocks) || method_exists($this, 'block'.$Type.'Continue');
|
||||||
|
return $continuable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the default behavior to allow for plugin-provided blocks to be completable
|
||||||
|
*
|
||||||
|
* @param $Type
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isBlockCompletable($Type)
|
||||||
|
{
|
||||||
|
$completable = in_array($Type, $this->completable_blocks) || method_exists($this, 'block'.$Type.'Complete');
|
||||||
|
return $completable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the element function publicly accessible, Medium uses this to render from Twig
|
* Make the element function publicly accessible, Medium uses this to render from Twig
|
||||||
*
|
*
|
||||||
@@ -77,7 +137,7 @@ trait ParsedownGravTrait
|
|||||||
*/
|
*/
|
||||||
protected function blockTwigTag($Line)
|
protected function blockTwigTag($Line)
|
||||||
{
|
{
|
||||||
if (preg_match('/[{%|{{|{#].*[#}|}}|%}]/', $Line['body'], $matches)) {
|
if (preg_match('/(?:{{|{%|{#)(.*)(?:}}|%}|#})/', $Line['body'], $matches)) {
|
||||||
$Block = array(
|
$Block = array(
|
||||||
'markup' => $Line['body'],
|
'markup' => $Line['body'],
|
||||||
);
|
);
|
||||||
@@ -149,9 +209,9 @@ trait ParsedownGravTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there is a media file that matches the path referenced..
|
// if there is a media file that matches the path referenced..
|
||||||
if ($media && isset($media->all()[$url['path']])) {
|
if ($media && isset($media->all()[$path_parts['basename']])) {
|
||||||
// get the medium object
|
// get the medium object
|
||||||
$medium = $media->all()[$url['path']];
|
$medium = $media->all()[$path_parts['basename']];
|
||||||
|
|
||||||
// if there is a query, then parse it and build action calls
|
// if there is a query, then parse it and build action calls
|
||||||
if (isset($url['query'])) {
|
if (isset($url['query'])) {
|
||||||
@@ -208,13 +268,64 @@ trait ParsedownGravTrait
|
|||||||
if (isset($excerpt['element']['attributes']['href'])) {
|
if (isset($excerpt['element']['attributes']['href'])) {
|
||||||
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href']));
|
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href']));
|
||||||
|
|
||||||
// if there is no scheme, the file is local
|
// if there is a query, then parse it and build action calls
|
||||||
|
if (isset($url['query'])) {
|
||||||
|
$actions = array_reduce(explode('&', $url['query']), function ($carry, $item) {
|
||||||
|
$parts = explode('=', $item, 2);
|
||||||
|
$value = isset($parts[1]) ? $parts[1] : true;
|
||||||
|
$carry[$parts[0]] = $value;
|
||||||
|
|
||||||
|
return $carry;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// valid attributes supported
|
||||||
|
$valid_attributes = ['rel', 'target', 'id', 'class', 'classes'];
|
||||||
|
|
||||||
|
// Unless told to not process, go through actions
|
||||||
|
if (array_key_exists('noprocess', $actions)) {
|
||||||
|
unset($actions['noprocess']);
|
||||||
|
} else {
|
||||||
|
// loop through actions for the image and call them
|
||||||
|
foreach ($actions as $attrib => $value) {
|
||||||
|
$key = $attrib;
|
||||||
|
|
||||||
|
if (in_array($attrib, $valid_attributes)) {
|
||||||
|
// support both class and classes
|
||||||
|
if ($attrib == 'classes') {
|
||||||
|
$attrib = 'class';
|
||||||
|
}
|
||||||
|
$excerpt['element']['attributes'][$attrib] = str_replace(',', ' ', $value);
|
||||||
|
unset($actions[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$url['query']= http_build_query($actions, null, '&', PHP_QUERY_RFC3986);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no query elements left, unset query
|
||||||
|
if (empty($url['query'])) {
|
||||||
|
unset ($url['query']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is no scheme, the file is local and we'll need to convert that URL
|
||||||
if (!isset($url['scheme']) && (count($url) > 0)) {
|
if (!isset($url['scheme']) && (count($url) > 0)) {
|
||||||
// convert the URl is required
|
$excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type, true);
|
||||||
$excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type);
|
} else {
|
||||||
|
$excerpt['element']['attributes']['href'] = Uri::buildUrl($url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $excerpt;
|
return $excerpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For extending this class via plugins
|
||||||
|
public function __call($method, $args)
|
||||||
|
{
|
||||||
|
if (isset($this->$method) === true) {
|
||||||
|
$func = $this->$method;
|
||||||
|
return call_user_func_array($func, $args);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||