Compare commits
711
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f51dd9458c | ||
|
|
962225080d | ||
|
|
deb094b5c9 | ||
|
|
d425133cae | ||
|
|
9b6ae9f9f8 | ||
|
|
4a95a9692d | ||
|
|
06439bc9a0 | ||
|
|
12683df0ab | ||
|
|
0cb53b2d80 | ||
|
|
5fd9b1871f | ||
|
|
fb51ae80ac | ||
|
|
b9d141c4f1 | ||
|
|
af4edac469 | ||
|
|
0451f9942c | ||
|
|
657c030033 | ||
|
|
d761914786 | ||
|
|
625bdbb2e2 | ||
|
|
d5f9e1fc2b | ||
|
|
ce058ae824 | ||
|
|
dee5060a24 | ||
|
|
c70e8a6b0d | ||
|
|
cb9b96c861 | ||
|
|
4bd5a61fde | ||
|
|
46ff310b01 | ||
|
|
96b05a7b25 | ||
|
|
563528cdc6 | ||
|
|
efa3289491 | ||
|
|
3460f607b5 | ||
|
|
0384fab421 | ||
|
|
b3ac9b9eec | ||
|
|
bfa0685f2e | ||
|
|
59226dbdc4 | ||
|
|
446e8352b5 | ||
|
|
190ca25b2a | ||
|
|
f121ee356b | ||
|
|
b3d59fc182 | ||
|
|
20f6295f84 | ||
|
|
2c36203690 | ||
|
|
458d8ec61c | ||
|
|
284dfa3fe8 | ||
|
|
08e97fe2cb | ||
|
|
7e63047313 | ||
|
|
d9834fe068 | ||
|
|
dc43a9503d | ||
|
|
a75425ca12 | ||
|
|
8c20654280 | ||
|
|
bceef69a72 | ||
|
|
1e310f0da5 | ||
|
|
ab90b907f8 | ||
|
|
f1aacf8008 | ||
|
|
ce82b67c47 | ||
|
|
3024ae8b23 | ||
|
|
7dcb8e280c | ||
|
|
f9dfe076a0 | ||
|
|
db88079f26 | ||
|
|
3f1ae0f5a1 | ||
|
|
f699d2c569 | ||
|
|
fdb63fcd8a | ||
|
|
52fb27b4fe | ||
|
|
7234fa0810 | ||
|
|
581e32e98b | ||
|
|
06780015d4 | ||
|
|
35bdd38f4c | ||
|
|
eacba1bec3 | ||
|
|
975cc50272 | ||
|
|
52b0ec7c72 | ||
|
|
de02944d0d | ||
|
|
da1c8652e6 | ||
|
|
012ba1fd36 | ||
|
|
cbfc5fcee5 | ||
|
|
232e1d5ec9 | ||
|
|
aca3c778e0 | ||
|
|
88a2463d13 | ||
|
|
f3e797a59a | ||
|
|
0869ac7c24 | ||
|
|
304518fbe7 | ||
|
|
49577a7e1a | ||
|
|
606ee2016d | ||
|
|
8608a2d67b | ||
|
|
3bac8dc09b | ||
|
|
f61b8a7bcc | ||
|
|
b6d3daaa35 | ||
|
|
33a928febb | ||
|
|
06c84867ec | ||
|
|
8a9543cd2d | ||
|
|
4f67b69984 | ||
|
|
28df8681e4 | ||
|
|
4222dbc243 | ||
|
|
2f27e7f5c9 | ||
|
|
c5fb951546 | ||
|
|
ecd7aa27f0 | ||
|
|
ecd01e1396 | ||
|
|
76b226629f | ||
|
|
97fae9bf9d | ||
|
|
5621b5acba | ||
|
|
ff237599a8 | ||
|
|
679ca91fc9 | ||
|
|
1dea234cb7 | ||
|
|
e42d06904e | ||
|
|
cb2fa84ade | ||
|
|
0a0b0e7518 | ||
|
|
65dc4fd37e | ||
|
|
b13f6bbea9 | ||
|
|
10e463b8b4 | ||
|
|
316f7a9a16 | ||
|
|
5e79d0208a | ||
|
|
5cdca60cce | ||
|
|
86a2d277f6 | ||
|
|
ad59bc0adc | ||
|
|
556d863b45 | ||
|
|
673531ae22 | ||
|
|
a9d5c0de28 | ||
|
|
b43e37fa83 | ||
|
|
6c4b30f1f7 | ||
|
|
c4a4354aff | ||
|
|
ad77de0424 | ||
|
|
c4d4ac2bfe | ||
|
|
0718772740 | ||
|
|
0ace8c9cb6 | ||
|
|
0482121441 | ||
|
|
0df8eaa2e3 | ||
|
|
66a570bbf7 | ||
|
|
0badc52f17 | ||
|
|
4cf1fedc61 | ||
|
|
341b5dc9ec | ||
|
|
f5e2aec818 | ||
|
|
77a65b71a2 | ||
|
|
5f1cf06e36 | ||
|
|
b734c3de18 | ||
|
|
808bb0eb86 | ||
|
|
682f3b75bf | ||
|
|
5b9b5c0d38 | ||
|
|
3a0a132701 | ||
|
|
60c3582947 | ||
|
|
9039334138 | ||
|
|
5ee403ab28 | ||
|
|
fdf44e8b4a | ||
|
|
91cdbec3af | ||
|
|
45354a3192 | ||
|
|
846cfef1b8 | ||
|
|
80dba6d9b7 | ||
|
|
bf615f8494 | ||
|
|
4c67d442d6 | ||
|
|
36615aac21 | ||
|
|
4e6fc7c074 | ||
|
|
e0357d0003 | ||
|
|
8533c8cdc6 | ||
|
|
bb3d000e5e | ||
|
|
842b54d879 | ||
|
|
256e24c5a4 | ||
|
|
07df49c481 | ||
|
|
a11a29de19 | ||
|
|
044eb7e532 | ||
|
|
7f93a5035c | ||
|
|
358027a8e0 | ||
|
|
98fe43e12c | ||
|
|
c096a30b81 | ||
|
|
02157f332e | ||
|
|
cd28625309 | ||
|
|
6868af609f | ||
|
|
445f369ff2 | ||
|
|
2a1ffb4259 | ||
|
|
4876cb631e | ||
|
|
4c35d95a73 | ||
|
|
8f4e6268a4 | ||
|
|
d7b60690b2 | ||
|
|
4de93f9fd9 | ||
|
|
f26c384257 | ||
|
|
78213e6f41 | ||
|
|
a188c707d8 | ||
|
|
ff4585327e | ||
|
|
fa1d302ea6 | ||
|
|
52394c6289 | ||
|
|
76fa76a5af | ||
|
|
d6a441cb96 | ||
|
|
85bbc384a7 | ||
|
|
80105c857e | ||
|
|
09151e97d1 | ||
|
|
9802161af1 | ||
|
|
00d7bd562c | ||
|
|
124ad2f061 | ||
|
|
a37767c2e8 | ||
|
|
d5950d9cd7 | ||
|
|
82283e65be | ||
|
|
2f760fd56d | ||
|
|
939610cf9d | ||
|
|
6d107d0881 | ||
|
|
b7434d0a0b | ||
|
|
55ef5e4af1 | ||
|
|
dc289723a9 | ||
|
|
b15bbae037 | ||
|
|
7cd084e621 | ||
|
|
0857b4efd9 | ||
|
|
0c01b35188 | ||
|
|
9d33ae6d49 | ||
|
|
a9aaf797cd | ||
|
|
4b6f0b14ad | ||
|
|
a111b67c53 | ||
|
|
91ef424bd0 | ||
|
|
7589051216 | ||
|
|
fbb59277b9 | ||
|
|
0d8e927b08 | ||
|
|
72f7b9a047 | ||
|
|
139373145a | ||
|
|
0357417163 | ||
|
|
d5d4216a80 | ||
|
|
b982831fbf | ||
|
|
75c4a4a649 | ||
|
|
fb977ce1b9 | ||
|
|
7d051d1f6a | ||
|
|
f5e1e24df8 | ||
|
|
5ddb31b57b | ||
|
|
01a28fc65a | ||
|
|
67cd7fb36f | ||
|
|
5f8dab0068 | ||
|
|
40949eaa90 | ||
|
|
f25ef4ab1b | ||
|
|
f3873ed61c | ||
|
|
bbffbd5616 | ||
|
|
d9feb92612 | ||
|
|
5662dc7cf7 | ||
|
|
39279a1633 | ||
|
|
e8b91db6f2 | ||
|
|
df9ff7b259 | ||
|
|
a0f3409f82 | ||
|
|
694724945d | ||
|
|
5cbe19064b | ||
|
|
4ac084139c | ||
|
|
f92c1d0089 | ||
|
|
bcd19058ea | ||
|
|
d43073a011 | ||
|
|
8bd30d0301 | ||
|
|
f087da1b43 | ||
|
|
7a681fd7f7 | ||
|
|
2e483c7598 | ||
|
|
f98065e849 | ||
|
|
48294842bf | ||
|
|
65e9ca1c32 | ||
|
|
233f2007b0 | ||
|
|
5b29082ca6 | ||
|
|
48c0abbe89 | ||
|
|
8476d5fbd7 | ||
|
|
ea5aa8d873 | ||
|
|
3229a84ee5 | ||
|
|
f8127f3ed6 | ||
|
|
44677aea78 | ||
|
|
5b7b81ff4d | ||
|
|
68d37e87f6 | ||
|
|
51d6850cd6 | ||
|
|
8f66a96ec0 | ||
|
|
9ce9f62a45 | ||
|
|
a33023a4aa | ||
|
|
d2d0a48e9c | ||
|
|
e55672bdcd | ||
|
|
5ef2630810 | ||
|
|
8c4b1ad69b | ||
|
|
59dede6049 | ||
|
|
f304ef0141 | ||
|
|
3cfadc380d | ||
|
|
b73b575b71 | ||
|
|
9b64b54d7b | ||
|
|
e826b474b8 | ||
|
|
9d63c8d8b0 | ||
|
|
aa4161e451 | ||
|
|
9029f14523 | ||
|
|
98c8313475 | ||
|
|
8351137206 | ||
|
|
79ec8e1d2e | ||
|
|
418d9ac4ca | ||
|
|
d0be4d1e49 | ||
|
|
4cfd93161b | ||
|
|
05efb6b9f2 | ||
|
|
66caf7ce05 | ||
|
|
9c02c63704 | ||
|
|
8458622e32 | ||
|
|
f1121107c5 | ||
|
|
d954743e8b | ||
|
|
0a6528a845 | ||
|
|
f744ca81ca | ||
|
|
3a82696d62 | ||
|
|
cd6f1b4cfa | ||
|
|
28478ba165 | ||
|
|
d746d5b52b | ||
|
|
f6fd924cbd | ||
|
|
0d1d692c45 | ||
|
|
6f6497d540 | ||
|
|
7889548a7e | ||
|
|
fc1141184c | ||
|
|
0993d812cb | ||
|
|
be81834aad | ||
|
|
e389760204 | ||
|
|
6f799f00bb | ||
|
|
debe80a314 | ||
|
|
af3db57b29 | ||
|
|
8edde44c0d | ||
|
|
cd369c327f | ||
|
|
206e5201b8 | ||
|
|
aa462c2454 | ||
|
|
ae1123ba39 | ||
|
|
bd06797c24 | ||
|
|
5b79fd4323 | ||
|
|
53d532da82 | ||
|
|
fa21c407b4 | ||
|
|
d54f160d6a | ||
|
|
5df5fa8480 | ||
|
|
ddd3530993 | ||
|
|
befb95a4ac | ||
|
|
dc185bdc2e | ||
|
|
42967e72cd | ||
|
|
85e10b5631 | ||
|
|
54e5927bb1 | ||
|
|
9517d07692 | ||
|
|
93abfd2485 | ||
|
|
5aec27478a | ||
|
|
9f955d4544 | ||
|
|
597d161a38 | ||
|
|
48d301330f | ||
|
|
03f0d71dbb | ||
|
|
778c87ffa3 | ||
|
|
ed0b35f9d7 | ||
|
|
cfc3a148e7 | ||
|
|
a698d7a7db | ||
|
|
ba107184e1 | ||
|
|
7abd60e785 | ||
|
|
0d5e6d4133 | ||
|
|
790cc772a9 | ||
|
|
0d8148f22d | ||
|
|
bef37a5cce | ||
|
|
be4a136476 | ||
|
|
5fc4393729 | ||
|
|
097d76de93 | ||
|
|
0076cfba2e | ||
|
|
6b24c8a461 | ||
|
|
3733d24da8 | ||
|
|
b2b8084cfe | ||
|
|
ab3d8eab41 | ||
|
|
b89941b909 | ||
|
|
bce98e6eaf | ||
|
|
f90aee4108 | ||
|
|
2189bbed5e | ||
|
|
ebc7330717 | ||
|
|
bab897f01e | ||
|
|
fb2c705ac4 | ||
|
|
6021f1ea9a | ||
|
|
181e1fb721 | ||
|
|
5b54f6d45f | ||
|
|
15a29de894 | ||
|
|
db912c4c91 | ||
|
|
949b1f7c61 | ||
|
|
fc88a82888 | ||
|
|
bfcab20dad | ||
|
|
93bafee2e7 | ||
|
|
3a6211c875 | ||
|
|
e072e0e4af | ||
|
|
070e929bf7 | ||
|
|
6dd6394ff1 | ||
|
|
5c6b72f83a | ||
|
|
6a4cbb0a5c | ||
|
|
098ea3e7b1 | ||
|
|
a48bed04b1 | ||
|
|
288b1043b5 | ||
|
|
492225e176 | ||
|
|
951a8314b7 | ||
|
|
c99cee7a27 | ||
|
|
e94fff384a | ||
|
|
08026b286a | ||
|
|
5b97335536 | ||
|
|
8b157052e0 | ||
|
|
01d9df4dd0 | ||
|
|
971fc796a8 | ||
|
|
fa28de48ca | ||
|
|
037d0c8dff | ||
|
|
18ead80b5f | ||
|
|
d75c2838d3 | ||
|
|
25860ae501 | ||
|
|
56e2636e6c | ||
|
|
509ae17fca | ||
|
|
a20b9144a5 | ||
|
|
59503baa9c | ||
|
|
b996ef493d | ||
|
|
5bc077989f | ||
|
|
725c379cd7 | ||
|
|
eb8e7badd6 | ||
|
|
0cc1916346 | ||
|
|
5116fedac0 | ||
|
|
474405c69d | ||
|
|
74838f96fa | ||
|
|
d231065fb8 | ||
|
|
7fc01fa1ec | ||
|
|
5858820cb7 | ||
|
|
43051501bd | ||
|
|
e3d715d2d0 | ||
|
|
a4af5e2bac | ||
|
|
666557b585 | ||
|
|
85c33e9ada | ||
|
|
6690d7423e | ||
|
|
d996c4c800 | ||
|
|
de287abf24 | ||
|
|
fc9f3a403b | ||
|
|
dcce436c59 | ||
|
|
543cce17fa | ||
|
|
2f7a3790b9 | ||
|
|
d721aaf185 | ||
|
|
303a84904e | ||
|
|
e2f6fed4b1 | ||
|
|
87e4e96ca5 | ||
|
|
d7e5351d5b | ||
|
|
1efaaaa4e0 | ||
|
|
2eeb3227d3 | ||
|
|
b7c70bab7e | ||
|
|
c3085180c0 | ||
|
|
885dc691b2 | ||
|
|
4594e84945 | ||
|
|
c42f860e9f | ||
|
|
0ba38d146c | ||
|
|
a42c1fb6c7 | ||
|
|
b46c99efc4 | ||
|
|
dddabe7724 | ||
|
|
afc2af6e9b | ||
|
|
9fe7e04e2f | ||
|
|
ced6f978a8 | ||
|
|
522110aea1 | ||
|
|
5d1254da18 | ||
|
|
7446e2f4ef | ||
|
|
9570ad3da3 | ||
|
|
54f0566ee2 | ||
|
|
d17a0ec8ef | ||
|
|
ae1772652f | ||
|
|
19ad81a432 | ||
|
|
dac9de0024 | ||
|
|
281a1ed0ba | ||
|
|
9d2488e589 | ||
|
|
d3437aa2de | ||
|
|
1a33c74c6d | ||
|
|
439b048590 | ||
|
|
743c6bdb07 | ||
|
|
51b60440be | ||
|
|
ceaf9e7d6a | ||
|
|
30dcd045a6 | ||
|
|
a020e72dc5 | ||
|
|
3c90e20dd3 | ||
|
|
33bd049d92 | ||
|
|
b06c2bf5a0 | ||
|
|
090aed23cb | ||
|
|
d0411feebf | ||
|
|
3613c0fcf5 | ||
|
|
aff8e992d6 | ||
|
|
2d25e00d76 | ||
|
|
0f18b6361e | ||
|
|
f27ad7c421 | ||
|
|
753b0cf2e2 | ||
|
|
85dcf29c41 | ||
|
|
503d209319 | ||
|
|
ccf71dba81 | ||
|
|
3646c79e1d | ||
|
|
1f3cc2eebb | ||
|
|
8a33f1b4c7 | ||
|
|
08cb40b004 | ||
|
|
96d6f517dc | ||
|
|
d4ad1406bf | ||
|
|
9b2451fd98 | ||
|
|
90b6979237 | ||
|
|
97ba21df98 | ||
|
|
c481f374a0 | ||
|
|
d3f31c578f | ||
|
|
7947926f8d | ||
|
|
a989421036 | ||
|
|
d0438f56dd | ||
|
|
7de45fe377 | ||
|
|
9f8eb230e8 | ||
|
|
1914c17deb | ||
|
|
181f8a7e23 | ||
|
|
3a84279916 | ||
|
|
cfa9e2b09c | ||
|
|
5178c7236b | ||
|
|
1e6bc86800 | ||
|
|
a620bf9e32 | ||
|
|
7cc04bc9ce | ||
|
|
a56fdfb6ce | ||
|
|
213283b51f | ||
|
|
369cefe15f | ||
|
|
284837bf12 | ||
|
|
a0ec4fc02f | ||
|
|
f11c673173 | ||
|
|
ce030a40d4 | ||
|
|
31c1648597 | ||
|
|
7bb63aca3f | ||
|
|
497708283f | ||
|
|
2797ff0a89 | ||
|
|
307dbe0459 | ||
|
|
9f4cc158db | ||
|
|
19e0977bbb | ||
|
|
3900462229 | ||
|
|
c48b99eaf0 | ||
|
|
34060ebf2e | ||
|
|
bc73fbc208 | ||
|
|
32604653fb | ||
|
|
8de2c67323 | ||
|
|
f9afcae389 | ||
|
|
b9f721006d | ||
|
|
3f7c048ad0 | ||
|
|
acd85a1cad | ||
|
|
811f2162c9 | ||
|
|
3f03af7e03 | ||
|
|
7a71bbe90e | ||
|
|
5e51edcd48 | ||
|
|
f0f95cc04f | ||
|
|
7a23ca1d3f | ||
|
|
9cda47f93d | ||
|
|
a478f1491e | ||
|
|
5f050a7dea | ||
|
|
c2f024f8b8 | ||
|
|
f90f43fcd6 | ||
|
|
8838ecc6b1 | ||
|
|
efd2465b8b | ||
|
|
0c1162589c | ||
|
|
509ef1752e | ||
|
|
10dfe6b22e | ||
|
|
5661a3d849 | ||
|
|
cf2b4ac529 | ||
|
|
2b61709ade | ||
|
|
6378d17753 | ||
|
|
590e1eeaca | ||
|
|
7d674357fe | ||
|
|
e789b02a93 | ||
|
|
acc7541ab9 | ||
|
|
5045dca3d4 | ||
|
|
c99e7c156d | ||
|
|
bc80ccc8e5 | ||
|
|
5494121dfb | ||
|
|
26e5a52943 | ||
|
|
7a51c913d3 | ||
|
|
c49f4f2c5f | ||
|
|
980fec83c0 | ||
|
|
473342490c | ||
|
|
b40815eec7 | ||
|
|
7317a51a24 | ||
|
|
b228fe4615 | ||
|
|
c0f3c2cf07 | ||
|
|
9b9362b8e9 | ||
|
|
7ef09ec326 | ||
|
|
86d7ffdab9 | ||
|
|
d6f0489b5f | ||
|
|
64aec15c8a | ||
|
|
28c065e106 | ||
|
|
98090f69df | ||
|
|
c2463f5e59 | ||
|
|
7788a598f4 | ||
|
|
6c7122b494 | ||
|
|
29b0eab314 | ||
|
|
12f05586ed | ||
|
|
35fe7aada3 | ||
|
|
55ee35d14b | ||
|
|
3c9c53e04d | ||
|
|
6f50549072 | ||
|
|
b3da43921b | ||
|
|
c4e65e18c4 | ||
|
|
afbf3d1327 | ||
|
|
4d19d4388a | ||
|
|
81f6f4e46f | ||
|
|
72d00c8e64 | ||
|
|
8a94f1dbab | ||
|
|
a237133227 | ||
|
|
9ac8c24673 | ||
|
|
bee7e732cc | ||
|
|
e7c5a69f81 | ||
|
|
6d13576185 | ||
|
|
14f2673842 | ||
|
|
1bd00f1a4f | ||
|
|
4326105304 | ||
|
|
c3008f3dcc | ||
|
|
e6880c82ec | ||
|
|
ca2318a529 | ||
|
|
b707d27c3f | ||
|
|
f9562d55aa | ||
|
|
a39a402011 | ||
|
|
892a597912 | ||
|
|
85e9e6ebb6 | ||
|
|
2941d694da | ||
|
|
2a6672934d | ||
|
|
0313a1239f | ||
|
|
603e989b1e | ||
|
|
62a600b5fc | ||
|
|
1353fbfd79 | ||
|
|
df3bc22954 | ||
|
|
069367a816 | ||
|
|
8af9943100 | ||
|
|
97fc32c3ae | ||
|
|
063ba90ce8 | ||
|
|
141df72356 | ||
|
|
a9a4cb70f0 | ||
|
|
0a1a25b300 | ||
|
|
d0601c4fdd | ||
|
|
eed7e15650 | ||
|
|
9f5bd46ca3 | ||
|
|
3407707046 | ||
|
|
03dbf22eb0 | ||
|
|
661d5c486d | ||
|
|
d52dcbcf55 | ||
|
|
d7565ec7bf | ||
|
|
d7b247a2e3 | ||
|
|
a67417380f | ||
|
|
f79fc78868 | ||
|
|
fc58a4d31c | ||
|
|
fe9e76bf28 | ||
|
|
8aa2ebd0b0 | ||
|
|
bb7106d706 | ||
|
|
464eaf8b17 | ||
|
|
b6a1a4d444 | ||
|
|
f97ac0e868 | ||
|
|
b8f8c75146 | ||
|
|
6723381384 | ||
|
|
6e6be7f790 | ||
|
|
fa97ccc032 | ||
|
|
57e08b76a8 | ||
|
|
53395bc47a | ||
|
|
d082cee7b5 | ||
|
|
f3dde68481 | ||
|
|
66c9d7907a | ||
|
|
214cc9f3f9 | ||
|
|
2c95acfe76 | ||
|
|
4e85799403 | ||
|
|
ad457db740 | ||
|
|
6a7402248a | ||
|
|
d7c7e642a4 | ||
|
|
03086f7fd3 | ||
|
|
37a698b631 | ||
|
|
6d0e6e26f6 | ||
|
|
36fc280f55 | ||
|
|
9269d8c0b9 | ||
|
|
c75a6bd364 | ||
|
|
3b1ca7c1a7 | ||
|
|
b344c928b4 | ||
|
|
b5b41a0888 | ||
|
|
81a0fc83b9 | ||
|
|
c1e65d5651 | ||
|
|
e8f994ff5f | ||
|
|
1d553d1a15 | ||
|
|
8ba8a45938 | ||
|
|
ccc2d918c9 | ||
|
|
043c842aef | ||
|
|
da3046c990 | ||
|
|
677acf3dcb | ||
|
|
88d9ca48a3 | ||
|
|
b290fb3ff5 | ||
|
|
012b8b7588 | ||
|
|
d7dbdf7fc5 | ||
|
|
4a1ca1fcd8 | ||
|
|
2ab3896ee7 | ||
|
|
9de95c24c8 | ||
|
|
39591c11c3 | ||
|
|
5f38ad2e3a | ||
|
|
c73bc1452b | ||
|
|
a5e8eb8fc4 | ||
|
|
1a8b07971e | ||
|
|
3e9477ddc3 | ||
|
|
bd38e3fd98 | ||
|
|
e98032a3e1 | ||
|
|
eb28696d82 | ||
|
|
df1e1390e7 | ||
|
|
d414e53789 | ||
|
|
24144f6aa4 | ||
|
|
58a3386277 | ||
|
|
8763a5da95 | ||
|
|
fc33c06613 | ||
|
|
1c14bdd390 | ||
|
|
8fe0558374 | ||
|
|
2e276335af | ||
|
|
aeabe03911 | ||
|
|
620a5545d8 | ||
|
|
0216d923d4 | ||
|
|
f262be1dcb | ||
|
|
780ee89d21 | ||
|
|
270f77f451 | ||
|
|
3a0f7c7cd4 | ||
|
|
a880ab9e15 | ||
|
|
ee55715093 | ||
|
|
593506c646 | ||
|
|
3902a75b2c | ||
|
|
b7d0258f06 | ||
|
|
b3c543f06c | ||
|
|
4a8facc046 | ||
|
|
7054ce53b6 | ||
|
|
5fabc08a99 | ||
|
|
859d3ce753 | ||
|
|
26873a2db4 | ||
|
|
527b482ab8 | ||
|
|
da23bb4100 | ||
|
|
0c7a138e43 | ||
|
|
703adfcb78 | ||
|
|
73ff4e9331 | ||
|
|
1b2d7db8f3 | ||
|
|
0f4ad90cd8 | ||
|
|
d9b678036a | ||
|
|
8210eafad5 | ||
|
|
e63f78e67b | ||
|
|
ff80cbca4f | ||
|
|
4506b62387 | ||
|
|
63c05ba6f9 | ||
|
|
cac5b1dfb9 | ||
|
|
19ee504075 | ||
|
|
5db999e3b1 | ||
|
|
35a93091ff | ||
|
|
79d5277a13 | ||
|
|
686ce63ca7 | ||
|
|
76f865566e | ||
|
|
c4dd6cc229 | ||
|
|
cc832d5249 | ||
|
|
195ba54005 | ||
|
|
0302de734b | ||
|
|
452280a6fe |
+12
-16
@@ -1,23 +1,19 @@
|
||||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_KEY=SomeRandomString
|
||||
APP_KEY=
|
||||
APP_ENV=
|
||||
APP_DEBUG=
|
||||
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
DB_HOST=
|
||||
DB_DATABASE=
|
||||
DB_USERNAME=
|
||||
DB_PASSWORD=
|
||||
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
MAIL_USERNAME=@binarity.cz
|
||||
MAIL_PASSWORD=
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
SITE_URL=/
|
||||
UPLOAD_URL=/public/uploads
|
||||
THUMBNAILS_URL=/uploads/thumbnails
|
||||
+25
-5
@@ -1,9 +1,29 @@
|
||||
# published files from modules
|
||||
/public/modules
|
||||
/public/assets
|
||||
/resources/views/modules
|
||||
/resources/views/visitor
|
||||
/resources/views/vendor
|
||||
!/resources/views/vendor/.gitkeep
|
||||
|
||||
# directories with custom templates
|
||||
**/views/**/custom/*
|
||||
!**/views/**/custom/.gitkeep
|
||||
|
||||
# module config - generated in ModuleManager service provider
|
||||
**/module.json
|
||||
|
||||
# uploaded files
|
||||
/public/uploads/*
|
||||
!/public/uploads/.gitkeep
|
||||
|
||||
# environment settings
|
||||
/.env
|
||||
|
||||
# dependecies - installed using Composer
|
||||
/vendor
|
||||
|
||||
# PhpStorm project directory
|
||||
/.idea
|
||||
/node_modules
|
||||
Homestead.yaml
|
||||
Homestead.json
|
||||
.env
|
||||
|
||||
# meta information created by installer
|
||||
.install
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)/$ /$1 [L,R=301]
|
||||
|
||||
RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.gif|\.woff|robots\.txt)$ [NC]
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_URI} !^/public/
|
||||
RewriteRule ^(assets)/(.*)$ public/$1/$2 [L,NC]
|
||||
|
||||
# disable viewing all hiden files
|
||||
RedirectMatch 403 /\..*$
|
||||
|
||||
# disable browsing other files in root
|
||||
RedirectMatch 403 /composer.*
|
||||
RedirectMatch 403 /artisan
|
||||
RedirectMatch 403 /phpunit.xml
|
||||
|
||||
# disable browsing directories
|
||||
# this should be solved also with Option -Indexes, however...
|
||||
RedirectMatch 403 ^/app
|
||||
RedirectMatch 403 ^/artisan
|
||||
RedirectMatch 403 ^/bootstrap
|
||||
RedirectMatch 403 ^/config
|
||||
RedirectMatch 403 ^/database
|
||||
RedirectMatch 403 ^/modules
|
||||
RedirectMatch 403 ^/scripts
|
||||
RedirectMatch 403 ^/storage
|
||||
RedirectMatch 403 ^/tests
|
||||
RedirectMatch 403 ^/vendor
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Language;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class AddLanguage extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'language:add {code} {translation} {native} {script?}';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Insert new language into database';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$code = $this->argument('code');
|
||||
$translation = $this->argument('translation');
|
||||
$native = $this->argument('native');
|
||||
$script = $this->argument('script');
|
||||
|
||||
// check if language does not exist
|
||||
$exist = Language::find($code);
|
||||
|
||||
if ($exist) {
|
||||
$this->error('Language ' . $code . ' already exists!');
|
||||
return;
|
||||
}
|
||||
|
||||
Language::create([
|
||||
'code' => $code,
|
||||
'name' => $translation,
|
||||
'native' => $native,
|
||||
'script' => $script ? $script : 'Latn'
|
||||
]);
|
||||
|
||||
$this->line('Successfully installed.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class ChangePassword extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:change-password {userID} {newPassword}';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Change password for user with given ID';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$id = $this->argument('userID');
|
||||
$newPassword = $this->argument('newPassword');
|
||||
|
||||
try {
|
||||
$user = User::findOrFail($id);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
$this->error('Invalid user ID ' . $id . '. Please see table `users` for correct IDs.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// set new password
|
||||
$user->password = Hash::make($newPassword);
|
||||
$user->save();
|
||||
|
||||
$this->info('Password successfully changed.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class InitDatabaseSchema extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'db:init {schema.sql}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$schema = $this->argument('schema.sql');
|
||||
|
||||
if (!file_exists($schema)) throw new NotFoundHttpException('File '.$schema.' does not exist.');
|
||||
|
||||
DB::unprepared(file_get_contents($schema));
|
||||
|
||||
$this->line('Successfully imported');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class InstallAllModules extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'install-all-modules';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Crawl /modules directory and install all modules';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// crawl all subdirectories in modules path
|
||||
$modules = File::directories(config('modules.paths.modules'));
|
||||
|
||||
foreach ($modules as $module) {
|
||||
$moduleName = basename($module);
|
||||
|
||||
// try to install each module
|
||||
try {
|
||||
$this->call('install-module', ['name' => $moduleName]);
|
||||
} catch (\Exception $e) {
|
||||
$this->line('Module ' . $moduleName . ' already installed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Module;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
|
||||
|
||||
class InstallModule extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'install-module {name} {parentModuleId?}';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Custom installation of CMS module. Name given as directory name in /modules.';
|
||||
protected $moduleName;
|
||||
protected $parentModuleId;
|
||||
protected $modulesPath;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->modulesPath = config('modules.paths.modules');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->moduleName = $name = $this->argument('name');
|
||||
$this->parentModuleId = $this->argument('parentModuleId');
|
||||
|
||||
// invalid module name provided
|
||||
if (!is_dir($this->modulesPath . DIRECTORY_SEPARATOR . $name)) {
|
||||
throw new InvalidArgumentException('Invalid module ' . $name . '. No directory under ' . $this->modulesPath . DIRECTORY_SEPARATOR . $name . ' found!');
|
||||
}
|
||||
|
||||
// get config
|
||||
$config = $this->loadConfig();
|
||||
|
||||
if (empty($config))
|
||||
return;
|
||||
|
||||
// check if it is valid
|
||||
$this->checkMandatoryFields($config);
|
||||
|
||||
// all mandatory fields are present, we can write it into database and create modules.json
|
||||
$this->installModule($config);
|
||||
|
||||
// inform user
|
||||
$this->line('Module ' . $name . ' successfuly installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load config from Config/config.php in module files. We cannot use config() because the file have not published
|
||||
* yet.
|
||||
*
|
||||
* @return array
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function loadConfig()
|
||||
{
|
||||
$basePath = $this->modulesPath . DIRECTORY_SEPARATOR . $this->moduleName . DIRECTORY_SEPARATOR;
|
||||
$path = $basePath . 'Config' . DIRECTORY_SEPARATOR . 'config.php';
|
||||
|
||||
if (basename($basePath) == 'Database')
|
||||
return [];
|
||||
|
||||
// check if module has Config/config.php file
|
||||
if (!file_exists($path)) {
|
||||
$path = $basePath . 'info.php';
|
||||
|
||||
// does module has info.php? If not, throw error, because we have no info about this module
|
||||
if (!file_exists($path)) {
|
||||
throw new FileNotFoundException('Missing config file. Create /Config/config.php or /info.php (for module with submodules) in ' . $basePath);
|
||||
}
|
||||
}
|
||||
|
||||
// we cannot rely on config() helper, because this module does not have to be published
|
||||
$config = @include($path);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if config contains all mandatory entries.
|
||||
*
|
||||
* @param $config
|
||||
*/
|
||||
private function checkMandatoryFields($config)
|
||||
{
|
||||
$fields = ['name'];
|
||||
foreach ($fields as $field) {
|
||||
if (!isset($config[$field])) {
|
||||
throw new MissingMandatoryParametersException('Missing *' . $field . '* in config file! Cannot install ' . $this->moduleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs module into database.
|
||||
*
|
||||
* This method calls Module::install, which handles specific installation of module. In this way we should be able
|
||||
* to install any module even with some other database structures.
|
||||
*
|
||||
* @param $config
|
||||
*
|
||||
* @return Module
|
||||
* @throws \ErrorException
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function installModule($config)
|
||||
{
|
||||
$name = isset($config['translatedName']) ? $config['translatedName'] : $config['name'];
|
||||
$description = isset($config['translatedDescription']) ? $config['translatedDescription'] : null;
|
||||
$alias = isset($config['alias']) ? $config['alias'] : null;
|
||||
$handler = isset($config['handler']) ? $config['handler'] : null;
|
||||
$providers = isset($config['providers']) ? $config['providers'] : [];
|
||||
|
||||
// check if module is not installed yet
|
||||
$module = Module::where('name', $name);
|
||||
|
||||
if ($handler) {
|
||||
$module = $module->where('handler', $handler);
|
||||
}
|
||||
|
||||
$module = $module->first();
|
||||
|
||||
if ($module && (!isset($config['hasSubmodules']) || !$config['hasSubmodules'])) {
|
||||
throw new \Exception('Module ' . $config['name'] . ' already exists in database.');
|
||||
}
|
||||
|
||||
if (!$module) {
|
||||
// insert module into database
|
||||
$settings = [
|
||||
'staticName' => $this->moduleName,
|
||||
'providers' => $providers,
|
||||
'aliases' => isset($config['aliases']) ? $config['aliases'] : [],
|
||||
'order' => isset($config['order']) ? $config['order'] : 0,
|
||||
'files' => isset($config['files']) ? $config['files'] : []
|
||||
];
|
||||
|
||||
$module = Module::install($name, $alias, $description, $handler, $this->parentModuleId, $settings);
|
||||
}
|
||||
|
||||
// try to install submodules
|
||||
if (isset($config['hasSubmodules']) && $config['hasSubmodules']) {
|
||||
$this->installSubmodules($this->modulesPath . DIRECTORY_SEPARATOR . $this->moduleName, $module);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl all subdirectories in module and try to install submodules
|
||||
*
|
||||
* @param $path string path to module base directory
|
||||
* @param $parentModule
|
||||
*/
|
||||
private function installSubmodules($path, Module $parentModule)
|
||||
{
|
||||
$submodules = File::directories($path);
|
||||
|
||||
foreach ($submodules as $submodulePath) {
|
||||
$submodule = str_replace($this->modulesPath . DIRECTORY_SEPARATOR, '', $submodulePath);
|
||||
|
||||
try {
|
||||
$this->call('install-module', ['name' => $submodule, 'parentModuleId' => $parentModule->id]);
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enumerations\UserRoles;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
|
||||
class NewUser extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:new {email} {password} {role}';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Creates new user';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$email = $this->argument('email');
|
||||
$password = $this->argument('password');
|
||||
$role = $this->argument('role');
|
||||
|
||||
// check if given role is valid
|
||||
$roles = UserRoles::getSimple();
|
||||
if (!in_array($role, $roles)) {
|
||||
throw new InvalidArgumentException('Invalid role specified. valid roles are: ' . implode(', ', $roles));
|
||||
}
|
||||
|
||||
// create new user
|
||||
$user = new User();
|
||||
$user->username = $user->email = $email;
|
||||
$user->password = Hash::make($password);
|
||||
$user->role = $role;
|
||||
$user->save();
|
||||
|
||||
$this->info('User ' . $email . ' successfully created.');
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -3,23 +3,22 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
|
||||
class Inspire extends Command
|
||||
class PublishTemplateResources extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'inspire';
|
||||
protected $signature = 'template:publish';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Display an inspiring quote';
|
||||
protected $description = 'Publish assets and views for currently set template';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
@@ -28,6 +27,7 @@ class Inspire extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);
|
||||
$this->call('vendor:publish', ['--tag' => 'module-views', '--force' => true]);
|
||||
$this->call('vendor:publish', ['--tag' => 'public-assets', '--force' => true]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Module;
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class SetTemplate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'template:set {template} {publish?}';
|
||||
/**
|
||||
* The console command description.
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Install template';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$template = $this->argument('template');
|
||||
$publish = $this->argument('publish') !== 'no-publish';
|
||||
|
||||
$templatePath = app_path('../templates/' . $template);
|
||||
if (!is_dir($templatePath) || !file_exists($templatePath . '/config.php')) {
|
||||
throw new NotFoundHttpException('Invalid template ' . $template . '!');
|
||||
}
|
||||
|
||||
// try to find currently installed template
|
||||
$current = Module::where('is_template', true)
|
||||
->first();
|
||||
|
||||
// install template
|
||||
$config = @include $templatePath . '/config.php';
|
||||
$config['staticName'] = $template;
|
||||
|
||||
if ($current) {
|
||||
$info = json_decode($current->module_settings);
|
||||
|
||||
$this->line('Template is already installed. Currently using template ' . trans($current->name) . ' located in /templates/' . $info->staticName . '.');
|
||||
$confirm = $this->confirm('Uninstall it and install *' . trans($config['name']) . '*? All data associated with installed template will be lost!');
|
||||
|
||||
if ($confirm) {
|
||||
$this->line('Uninstalling ' . $current->name . '.');
|
||||
$current->uninstall();
|
||||
} else {
|
||||
$this->line('Aborting installation.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Module::install($config['name'], $config['alias'], $config['description'], $config['handler'], false, $config);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Cannot install template ' . $template . '. Message: ' . $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// theme written
|
||||
$this->line('Template successfully set up.');
|
||||
|
||||
// run again artisan for publishing resources
|
||||
// it cannot be done using $this->call, because we need to load different template into service providers
|
||||
exec('php artisan vendor:publish');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SetupDatabase extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'db:setup {host} {user} {password} {database}';
|
||||
/**
|
||||
* The console command description.
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Setup database credentials';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
echo "zpracovavam";
|
||||
$host = $this->argument('host');
|
||||
$user = $this->argument('user');
|
||||
$password = $this->argument('password');
|
||||
$database = $this->argument('database');
|
||||
|
||||
// try to connect with this settings
|
||||
// @todo add credentials verification
|
||||
|
||||
// if pass, proceed to creating .env file
|
||||
$parameters = [
|
||||
'DB_HOST' => $host,
|
||||
'DB_USERNAME' => $user,
|
||||
'DB_PASSWORD' => $password,
|
||||
'DB_DATABASE' => $database
|
||||
];
|
||||
|
||||
$envPath = base_path('.env');
|
||||
$env = file_get_contents($envPath);
|
||||
if (!file_exists($envPath))
|
||||
$env = file_get_contents($envPath.'.example');
|
||||
|
||||
foreach ($parameters as $parameter => $value) {
|
||||
$env = preg_replace('/'.$parameter.'=(.*)/i', $parameter.'='.$value, $env);
|
||||
}
|
||||
|
||||
file_put_contents($envPath, $env);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class TranslateAll extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'translate:all';
|
||||
/**
|
||||
* The console command description.
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Checks for missing translations in all modules.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->call('translate:dir', ['dir' => 'resources/lang']);
|
||||
|
||||
$this->crawlDirectory('modules');
|
||||
$this->crawlDirectory('templates', ['templates/Base']);
|
||||
$this->crawlDirectory('templates/Base');
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl directories and search for directories with translations
|
||||
*
|
||||
* @param $directory
|
||||
* @param array $ignoredDirectories
|
||||
*/
|
||||
protected function crawlDirectory($directory, $ignoredDirectories = [])
|
||||
{
|
||||
$directories = File::directories($directory);
|
||||
foreach ($directories as $dir) {
|
||||
|
||||
if (in_array($dir, $ignoredDirectories)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->call('translate:dir', ['dir' => $dir . '/Resources/lang']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TranslateDirectory extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'translate:dir {dir}';
|
||||
/**
|
||||
* The console command description.
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Checks for missing translations in given directory.';
|
||||
/**
|
||||
* @var array All translations
|
||||
*/
|
||||
protected $translations = [];
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$dir = rtrim($this->argument('dir'), '/');
|
||||
$defaultLocales = config('app.fallback_locale');
|
||||
$currentLocales = config('app.locale');
|
||||
|
||||
$defaultLocalesDir = base_path($dir . '/' . $defaultLocales);
|
||||
$currentLocalesDir = base_path($dir . '/' . $currentLocales);
|
||||
|
||||
if (!is_dir($defaultLocalesDir)) {
|
||||
// this is the place for checking for submodules
|
||||
|
||||
$modulePath = dirname(dirname($dir));
|
||||
|
||||
// does exist directory with translations?
|
||||
if (is_dir(base_path($modulePath . '/Resources/lang')) || file_exists(base_path($modulePath.DIRECTORY_SEPARATOR.'info.php'))) {
|
||||
$modules = File::directories($modulePath);
|
||||
foreach ($modules as $module) {
|
||||
$this->call('translate:dir', ['dir' => $module . '/Resources/lang']);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_dir($currentLocalesDir)) {
|
||||
File::makeDirectory($currentLocalesDir);
|
||||
}
|
||||
|
||||
$this->compareTranslationsInDirectory($defaultLocalesDir, $currentLocalesDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl given defaul directory and compare all files in default and current directory.
|
||||
*
|
||||
* @param $defaultDir string path to directory with default (fallback) locales
|
||||
* @param $currentDir string path to directory with currently selected localse
|
||||
*/
|
||||
private function compareTranslationsInDirectory($defaultDir, $currentDir)
|
||||
{
|
||||
$files = File::files($defaultDir);
|
||||
foreach ($files as $file) {
|
||||
if (!Str::endsWith($file, '.php')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileName = basename($file);
|
||||
$default = include($file);
|
||||
$checked = file_exists($currentDir . '/' . $fileName) ? include $currentDir . '/' . $fileName : [];
|
||||
$this->translations = &$checked;
|
||||
|
||||
$this->checkForMissingTranslations($default, $checked, $currentDir, $fileName);
|
||||
}
|
||||
|
||||
// iterate over directories
|
||||
$this->crawlSubdirectories($defaultDir, $currentDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check translations and ask for missing ones.
|
||||
*
|
||||
* @param $default
|
||||
* @param $checked
|
||||
* @param $currentLocalesDir
|
||||
* @param $fileName
|
||||
*/
|
||||
private function checkForMissingTranslations($default, &$checked, $currentLocalesDir, $fileName)
|
||||
{
|
||||
foreach ($default as $key => $translation) {
|
||||
if (!isset($checked[$key])) {
|
||||
// translate only plain text fields
|
||||
if (is_array($default[$key])) {
|
||||
|
||||
if (!isset($checked[$key])) {
|
||||
$checked[$key] = [];
|
||||
}
|
||||
|
||||
$this->checkForMissingTranslations($default[$key], $checked[$key], $currentLocalesDir, $fileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->info($fileName . ':' . $key);
|
||||
$this->line($translation);
|
||||
$newTranslation = $this->ask('Translate');
|
||||
|
||||
$checked[$key] = $newTranslation;
|
||||
$this->saveTranslation($currentLocalesDir, $fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new/reset file and fill it with translations
|
||||
*
|
||||
* @param $checked
|
||||
* @param $dir
|
||||
* @param $fileName
|
||||
*/
|
||||
private function saveTranslation($dir, $fileName)
|
||||
{
|
||||
$file = $dir . '/' . $fileName;
|
||||
|
||||
$this->resetFile($file);
|
||||
$this->writeRow('<?php', null, $file, false);
|
||||
$this->writeRow('return [', null, $file, false);
|
||||
|
||||
// write real translation data
|
||||
$this->writeTranslations($this->translations, $dir, $fileName);
|
||||
|
||||
$this->writeRow('];', '', $file, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write translation as PHP array
|
||||
*
|
||||
* @param $checked
|
||||
* @param $dir
|
||||
* @param $fileName
|
||||
*/
|
||||
private function writeTranslations($checked, $dir, $fileName)
|
||||
{
|
||||
$file = $dir . '/' . $fileName;
|
||||
|
||||
ksort($checked);
|
||||
|
||||
foreach ($checked as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->writeRow($key, '[', $file, false);
|
||||
$this->writeTranslations($value, $dir, $fileName);
|
||||
$this->writeRow('],', null, $file, false);
|
||||
} else {
|
||||
$this->writeRow($key, $value, $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets content of given file
|
||||
*
|
||||
* @param $file
|
||||
*/
|
||||
private function resetFile($file)
|
||||
{
|
||||
file_put_contents($file, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write row with translations
|
||||
*
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @param $file
|
||||
* @param bool $arrayItem
|
||||
*/
|
||||
private function writeRow($key, $value, $file, $arrayItem = true)
|
||||
{
|
||||
if ($value != null) {
|
||||
if ($arrayItem) {
|
||||
$value = strpos($value, '"') !== false ? '\'' . $value . '\'' : '"' . $value . '"';
|
||||
$value .= ",\n";
|
||||
}
|
||||
|
||||
file_put_contents($file, '"' . $key . '" => ' . $value, FILE_APPEND);
|
||||
} else {
|
||||
file_put_contents($file, $key . "\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl subdirectories and compare translations there
|
||||
*
|
||||
* @param $defaultDir
|
||||
* @param $currentDir
|
||||
*/
|
||||
private function crawlSubdirectories($defaultDir, $currentDir)
|
||||
{
|
||||
$directories = File::directories($defaultDir);
|
||||
|
||||
foreach ($directories as $directory) {
|
||||
$dirname = basename($directory);
|
||||
|
||||
if (!is_dir($currentDir . '/' . $dirname)) {
|
||||
File::makeDirectory($currentDir . '/' . $dirname);
|
||||
}
|
||||
|
||||
$this->compareTranslationsInDirectory($directory, $currentDir . '/' . $dirname);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\PublishTemplateResources;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
@@ -13,13 +14,23 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
// Commands\Inspire::class,
|
||||
Commands\NewUser::class,
|
||||
Commands\ChangePassword::class,
|
||||
Commands\InstallModule::class,
|
||||
Commands\InstallAllModules::class,
|
||||
Commands\TranslateDirectory::class,
|
||||
Commands\TranslateAll::class,
|
||||
Commands\InitDatabaseSchema::class,
|
||||
Commands\SetTemplate::class,
|
||||
Commands\AddLanguage::class,
|
||||
PublishTemplateResources::class
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\ActionLogType;
|
||||
|
||||
class ActionLogTypes extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all action log types
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$types = ActionLogType::all(['id', 'name']);
|
||||
|
||||
foreach ($types as $type) {
|
||||
self::push($type->id, $type->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\ActionLogType;
|
||||
|
||||
class ActionLogTypesForLogger extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$types = ActionLogType::all(['string_id', 'id']);
|
||||
|
||||
foreach ($types as $type) {
|
||||
self::push($type->string_id, $type->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,11 @@ abstract class BaseEnumeration
|
||||
$className::init();
|
||||
}
|
||||
|
||||
// it can happen that even after init no enumerations are available
|
||||
if (empty(self::$items[$className])) {
|
||||
self::$items[$className] = [];
|
||||
}
|
||||
|
||||
self::$initiliazed[] = $className;
|
||||
}
|
||||
}
|
||||
@@ -42,7 +47,7 @@ abstract class BaseEnumeration
|
||||
public static function push($key, $translation, $overwrite = false)
|
||||
{
|
||||
// item exists and we do not want to overwrite items
|
||||
if (!$overwrite && isset(self::$items[get_called_class()][$key])) {
|
||||
if (!$overwrite && !is_null($key) && isset(self::$items[get_called_class()][$key])) {
|
||||
throw new EnumerationExistsException(get_called_class() . ': ' . $key . ' already in ' . $translation);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Content;
|
||||
|
||||
class ContentStatuses extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$roles = [
|
||||
Content::STATUS_DRAFT => 'admin/contents.status_' . Content::STATUS_DRAFT,
|
||||
Content::STATUS_PROTECTED => 'admin/contents.status_' . Content::STATUS_PROTECTED,
|
||||
Content::STATUS_PUBLIC => 'admin/contents.status_' . Content::STATUS_PUBLIC
|
||||
];
|
||||
|
||||
foreach ($roles as $role => $translation) {
|
||||
self::push($role, $translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Module;
|
||||
|
||||
class ModuleNamesWithIds extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all installed modules
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$modules = Module::all(['id', 'name']);
|
||||
|
||||
foreach ($modules as $module) {
|
||||
self::push($module->id, $module->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Module;
|
||||
|
||||
class Modules extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all installed modules
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$modules = Module::all(['handler', 'name']);
|
||||
|
||||
foreach ($modules as $module) {
|
||||
self::push($module->handler, $module->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Module;
|
||||
|
||||
class ModulesHandlerToId extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all installed modules
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$modules = Module::all(['handler', 'id']);
|
||||
|
||||
foreach ($modules as $module) {
|
||||
self::push($module->handler, $module->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePaths extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::all(['id', 'path']);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePathsHumanReadable extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::all(['id', 'name']);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePathsHumanReadableRootOnly extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::where('parent_id', null)
|
||||
->select(['id', 'name'])
|
||||
->get();
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 15:50
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Template;
|
||||
|
||||
class Templates extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$templates = Template::all(['id', 'template_name']);
|
||||
|
||||
foreach ($templates as $template) {
|
||||
self::push($template->id, $template->template_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ class UserStates extends BaseEnumeration
|
||||
public static function init()
|
||||
{
|
||||
$items = [
|
||||
User::STATE_DELETED => 'admin/userManagement.status_' . User::STATE_DELETED,
|
||||
User::STATE_BLOCKED => 'admin/userManagement.status_' . User::STATE_BLOCKED,
|
||||
User::STATE_ACTIVE => 'admin/userManagement.status_' . User::STATE_ACTIVE
|
||||
];
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\WidgetType;
|
||||
|
||||
class WidgetTypes extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all installed modules
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$widgets = WidgetType::all(['id', 'name']);
|
||||
|
||||
foreach ($widgets as $widget) {
|
||||
self::push($widget->id, $widget->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\WidgetType;
|
||||
|
||||
class WidgetTypesWithHandlers extends BaseEnumeration
|
||||
{
|
||||
/**
|
||||
* Init list of all installed modules
|
||||
*
|
||||
* @throws Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected static function init()
|
||||
{
|
||||
$modules = WidgetType::all(['handler', 'name']);
|
||||
|
||||
foreach ($modules as $module) {
|
||||
self::push($module->handler, $module->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Widget;
|
||||
use App\Models\WidgetArea;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class AssignWidget extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Widget
|
||||
*/
|
||||
public $widget;
|
||||
/**
|
||||
* @var WidgetArea
|
||||
*/
|
||||
public $widgetArea;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Widget $widget
|
||||
* @param WidgetArea $widgetArea
|
||||
*/
|
||||
public function __construct(Widget $widget, WidgetArea $widgetArea)
|
||||
{
|
||||
$this->widget = $widget;
|
||||
$this->widgetArea = $widgetArea;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class AttemptToEditInvalidContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $contentId;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($contentId)
|
||||
{
|
||||
$this->contentId = $contentId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class ChangeSettings extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class CreateNewContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Content $page)
|
||||
{
|
||||
$this->page = $page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class CreateNewCustomField extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var CustomField
|
||||
*/
|
||||
public $customField;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function __construct(CustomField $customField)
|
||||
{
|
||||
$this->customField = $customField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class CreateNewUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Widget;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CreateNewWidget extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Widget
|
||||
*/
|
||||
public $widget;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Widget $widget
|
||||
*/
|
||||
public function __construct(Widget $widget)
|
||||
{
|
||||
//
|
||||
$this->widget = $widget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\WidgetArea;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CreateNewWidgetArea extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var WidgetArea
|
||||
*/
|
||||
public $widgetArea;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param WidgetArea $widgetArea
|
||||
*/
|
||||
public function __construct(WidgetArea $widgetArea)
|
||||
{
|
||||
$this->widgetArea = $widgetArea;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DeleteContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Content $page
|
||||
* @param $revision
|
||||
*/
|
||||
public function __construct(Content $page)
|
||||
{
|
||||
$this->page = $page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class DeleteCustomField extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var CustomField
|
||||
*/
|
||||
public $customField;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function __construct(CustomField $customField)
|
||||
{
|
||||
$this->customField = $customField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\WidgetArea;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DeleteWidgetArea extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var WidgetArea
|
||||
*/
|
||||
public $widgetArea;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param WidgetArea $widgetArea
|
||||
*/
|
||||
public function __construct(WidgetArea $widgetArea)
|
||||
{
|
||||
//
|
||||
$this->widgetArea = $widgetArea;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class EditContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
public $revision;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Content $page
|
||||
* @param $revision
|
||||
*/
|
||||
|
||||
public function __construct(Content $page, $revision)
|
||||
{
|
||||
$this->page = $page;
|
||||
$this->revision = $revision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class EditCustomField extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var CustomField
|
||||
*/
|
||||
public $customField;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function __construct(CustomField $customField)
|
||||
{
|
||||
$this->customField = $customField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\File;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class EditFile extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
public $file;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param File $file
|
||||
*/
|
||||
public function __construct(File $file)
|
||||
{
|
||||
//
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should be broadcast on.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class EditUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Widget;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class EditWidget extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Widget
|
||||
*/
|
||||
public $widget;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Widget $widget
|
||||
*/
|
||||
public function __construct(Widget $widget)
|
||||
{
|
||||
$this->widget = $widget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\WidgetArea;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class EditWidgetArea extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var WidgetArea
|
||||
*/
|
||||
public $widgetArea;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param WidgetArea $widgetArea
|
||||
*/
|
||||
public function __construct(WidgetArea $widgetArea)
|
||||
{
|
||||
$this->widgetArea = $widgetArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should be broadcast on.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class MakeDraftFromContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $revision;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Content $page, $revision)
|
||||
{
|
||||
$this->page = $page;
|
||||
$this->revision = $revision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PublishContent extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
public $revision;
|
||||
|
||||
public function __construct(Content $page, $revision)
|
||||
{
|
||||
$this->page = $page;
|
||||
$this->revision = $revision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Widget;
|
||||
use App\Models\WidgetArea;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class RemoveWidgetFromArea extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Widget
|
||||
*/
|
||||
public $widget;
|
||||
/**
|
||||
* @var WidgetArea
|
||||
*/
|
||||
public $widgetArea;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Widget $widget
|
||||
* @param WidgetArea $widgetArea
|
||||
*/
|
||||
public function __construct(Widget $widget, WidgetArea $widgetArea)
|
||||
{
|
||||
$this->widget = $widget;
|
||||
$this->widgetArea = $widgetArea;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
use App\Models\Content;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class SetHomepage extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
public $page;
|
||||
public $revision;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Content $page
|
||||
* @param $revision
|
||||
*/
|
||||
public function __construct(Content $page, $revision)
|
||||
{
|
||||
$this->page = $page;
|
||||
$this->revision = $revision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
class UploadFile extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var UploadedFile
|
||||
*/
|
||||
private $uploadedFile;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param File $uploadedFile
|
||||
* @param $id
|
||||
*/
|
||||
public function __construct(File $uploadedFile, $id)
|
||||
{
|
||||
$this->uploadedFile = $uploadedFile;
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should be broadcast on.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
@@ -45,6 +46,11 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
public function render($request, Exception $e)
|
||||
{
|
||||
if ($e instanceof TokenMismatchException){
|
||||
//redirect to form an example of how I handle mine
|
||||
return redirect($request->fullUrl())->with('error', trans('validation.csrf'));
|
||||
}
|
||||
|
||||
return parent::render($request, $e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Enumerations\TemplatePathsHumanReadableRootOnly;
|
||||
use App\Enumerations\WidgetTypes;
|
||||
use App\Handlers\Contracts\AppHandler;
|
||||
use App\Handlers\Contracts\BaseModuleHandler;
|
||||
use App\Models\User;
|
||||
|
||||
abstract class BaseHandler implements BaseModuleHandler
|
||||
{
|
||||
/**
|
||||
* Register admin menu (or multiple ones)
|
||||
*
|
||||
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
|
||||
* starting any middleware..
|
||||
*
|
||||
* @param User $user model of logged user
|
||||
*/
|
||||
public static function registerAdminMenu(User $user)
|
||||
{
|
||||
$menu = \Menu::instance('mainMenu');
|
||||
if (!is_null($menu)) {
|
||||
// menus were already defined
|
||||
return;
|
||||
}
|
||||
|
||||
// create instance of main menu
|
||||
\Menu::create('mainMenu', function ($menu) {
|
||||
// $menu->route('admin.dashboard', trans('admin/mainMenu.dashboard'), [], 10, ['icon' => 'fa fa-fw fa-dashboard']);
|
||||
|
||||
/**
|
||||
* Content pages
|
||||
*
|
||||
* Submenus can be registered later
|
||||
*/
|
||||
$menu->dropdown(trans('admin/mainMenu.contentPages'), function ($sub) {
|
||||
$sub->addDivider(9999);
|
||||
$sub->route('content.overview', trans('admin/mainMenu.contentPageOverview'), [], 10000, ['icon' => 'fa fa-fw fa-list']);
|
||||
}, 20, ['icon' => 'fa fa-fw fa-database']);
|
||||
|
||||
/**
|
||||
* File manager
|
||||
*/
|
||||
$menu->route('upload.overview', trans('admin/mainMenu.fileManager'), [], 40, ['icon' => 'fa fa-fw fa-folder']);
|
||||
|
||||
/**
|
||||
* Widgets and widget areas
|
||||
*/
|
||||
$menu->dropdown(trans('admin/mainMenu.widgets'), function ($sub) {
|
||||
// create list of all widget types
|
||||
$widgets = WidgetTypes::getWithTranslations();
|
||||
|
||||
if (!empty($widgets)) {
|
||||
$sub->dropdown(trans('admin/mainMenu.newWidget'), function ($sub) use ($widgets) {
|
||||
$i = 1;
|
||||
foreach ($widgets as $type => $name) {
|
||||
$sub->route('widgets.new', $name, ['type' => $type], $i++);
|
||||
}
|
||||
}, 10, ['icon' => 'fa fa-fw fa-plus']);
|
||||
}
|
||||
|
||||
$sub->route('widgets.overview', trans('admin/mainMenu.widgetsOverview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
|
||||
|
||||
// menu for widget areas
|
||||
$sub->dropdown(trans('admin/mainMenu.widgetAreas'), function ($sub) {
|
||||
$sub->route('widgetareas.new', trans('admin/mainMenu.newWidgetArea'), [], 1, ['icon' => 'fa fa-fw fa-plus']);
|
||||
$sub->route('widgetareas.overview', trans('admin/mainMenu.widgetAreaOverview'), [], 2, ['icon' => 'fa fa-fw fa-list']);
|
||||
}, 50, ['icon' => 'fa fa-fw fa-object-group']);
|
||||
}, 50, ['icon' => 'fa fa-fw fa-puzzle-piece']);
|
||||
|
||||
/**
|
||||
* Divide system entries and other links in menu
|
||||
*/
|
||||
$menu->addDivider(9999);
|
||||
|
||||
$menu->dropdown(trans('admin/mainMenu.system'), function ($sub) {
|
||||
|
||||
/**
|
||||
* User management
|
||||
*/
|
||||
$sub->dropdown(trans('admin/mainMenu.userManagement'), function ($sub) {
|
||||
$sub->route('users.new', trans('admin/mainMenu.newUser'), [], 10, ['icon' => 'fa fa-fw fa-user-plus']);
|
||||
$sub->route('users.overview', trans('admin/mainMenu.usersOverview'), [], 30, ['icon' => 'fa fa-fw fa-users']);
|
||||
}, 20, ['icon' => 'fa fa-fw fa-users']);
|
||||
|
||||
/**
|
||||
* Templates
|
||||
*/
|
||||
$templatePaths = TemplatePathsHumanReadableRootOnly::getWithTranslations();
|
||||
if (!empty($templatePaths)) {
|
||||
$sub->dropdown(trans('admin/mainMenu.templates'), function ($sub) use ($templatePaths) {
|
||||
$i = 1;
|
||||
foreach ($templatePaths as $id => $name) {
|
||||
$sub->route('templates.overview', $name, ['id' => $id], $i++);
|
||||
}
|
||||
}, 60, ['icon' => 'fa fa-fw fa-file-code-o']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// $menu->dropdown(trans('admin/mainMenu.customFields'), function ($sub) {
|
||||
// $sub->route('customfields.new', trans('admin/mainMenu.customFieldsNew'), [], 10, ['icon' => 'fa fa-fw fa-code']);
|
||||
// $sub->route('customfields.overview', trans('admin/mainMenu.customFieldsOverview'), [], 50, ['icon' => 'fa fa-fw fa-code-fork']);
|
||||
// }, 30, ['icon' => 'fa fa-fw fa-code']);
|
||||
|
||||
$sub->route('log.overview', trans('admin/mainMenu.actionLog'), [], 70, ['icon' => 'fa fa-fw fa-history']);
|
||||
$sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']);
|
||||
}, 10000, ['icon' => 'fa fa-fw fa-gears']);
|
||||
|
||||
|
||||
});
|
||||
|
||||
// order
|
||||
|
||||
// create menu with user profile
|
||||
\Menu::create('profileMenu', function ($menu) {
|
||||
$menu->route('users.detail', trans('admin/userManagement.profile'), [], 10, ['icon' => 'fa fa-fw fa-user icon']);
|
||||
$menu->addDivider(999);
|
||||
$menu->route('logout', trans('admin/common.logout'), [], 1000, ['icon' => 'fa fa-fw fa-power-off icon']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Content;
|
||||
|
||||
interface AppHandler extends BaseModuleHandler
|
||||
{
|
||||
/**
|
||||
* Render given module into visitor area.
|
||||
*
|
||||
* @param Content $content DB model from table contents
|
||||
* @param array $parameters parameters used for modifications/custom settings of given model
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function render(Content $content, $parameters);
|
||||
|
||||
public static function getHistoryHandler();
|
||||
|
||||
/**
|
||||
* Load some extra data for content management form?
|
||||
*
|
||||
* @param Content $content
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function loadExtraData(Content $content);
|
||||
|
||||
/**
|
||||
* Save module-specific values into database
|
||||
*
|
||||
* @param Content $content
|
||||
* @param Request $request
|
||||
*
|
||||
* @return mixed
|
||||
* @internal param Widget $widget
|
||||
*/
|
||||
public static function createNew(Content &$content, Request $request);
|
||||
|
||||
/**
|
||||
* Method used for editing existing content page.
|
||||
*
|
||||
* Reason why it is separated from createNew() method is simple - we need to save history of changes.
|
||||
*
|
||||
* @param Content $content
|
||||
* @param Request $request
|
||||
*
|
||||
* @param $revisionID string ID of revision used
|
||||
*
|
||||
* @return int number of edited fields
|
||||
*/
|
||||
public static function edit(Content &$content, Request $request, $revisionID);
|
||||
|
||||
/**
|
||||
* Method called right after content page is marked as deleted
|
||||
*
|
||||
* This method is supposed to clean after "deleted" page.
|
||||
*
|
||||
* @param Content $content
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function delete(Content $content);
|
||||
|
||||
/**
|
||||
* Getter for section names in creating/editing content resource
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getExtendedFormSections();
|
||||
|
||||
/**
|
||||
* Getter for views used in extended part of form for creating new content
|
||||
*
|
||||
* This method should return pairs <section, view-name>. View is returned only as name in plain text
|
||||
*
|
||||
* @return array of views/templates/html codes divided into section
|
||||
*/
|
||||
public static function getExtendedFormInputsCreate();
|
||||
|
||||
/**
|
||||
* Getter for extended part of form for editing existing content
|
||||
*
|
||||
* Basically, this method may be
|
||||
*
|
||||
* @return array of views/templates/html codes divided into section
|
||||
*/
|
||||
public static function getExtendedFormInputsEdit();
|
||||
|
||||
/**
|
||||
* Does this module support categories?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function supportCategories();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
interface BaseModuleHandler
|
||||
{
|
||||
/**
|
||||
* Register admin menu (or multiple ones)
|
||||
*
|
||||
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
|
||||
* starting any middleware..
|
||||
*
|
||||
* @param User $user model of logged user
|
||||
*/
|
||||
public static function registerAdminMenu(User $user);
|
||||
|
||||
/**
|
||||
* Install module.
|
||||
*
|
||||
* This method is called after inserting info about module into database. It can be called only using Artisan in
|
||||
* CLI.
|
||||
*/
|
||||
public static function install();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
use App\Models\Content;
|
||||
|
||||
/**
|
||||
* Interface ContentTitles
|
||||
*
|
||||
* Classes which implement this interface get the ability to rewrite default text on edit/create/overview of content
|
||||
* page.
|
||||
*
|
||||
* @package App\Handlers\Contracts
|
||||
*/
|
||||
interface ContentTitles
|
||||
{
|
||||
/**
|
||||
* Get translated title for pages overview of given type.
|
||||
*
|
||||
* This value is used for rendering list of all content pages of given type in administration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getOverviewTitle();
|
||||
|
||||
/**
|
||||
* Title displayed above for for creating new content page
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCreateNewTitle();
|
||||
|
||||
/**
|
||||
* Title for form displayed for editin content page
|
||||
*
|
||||
* @param Content $content
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getEditTitle(Content $content);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
interface HistoryHandler
|
||||
{
|
||||
public static function parseColumnName($name);
|
||||
|
||||
public static function parseChangedValue($changeset);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
interface SearchHandler {
|
||||
public function getId();
|
||||
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Search for given patttern/term
|
||||
*
|
||||
* @param string $term searched word
|
||||
*
|
||||
* @return array list of found objects
|
||||
*/
|
||||
public function search($term);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
interface SearchPresenterHandler
|
||||
{
|
||||
/**
|
||||
* Method for rendering list of found results
|
||||
*
|
||||
* @param $foundItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($foundItems);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace App\Handlers\Contracts;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Content;
|
||||
use App\Models\Module;
|
||||
|
||||
/**
|
||||
* Interface TemplateHandler
|
||||
*
|
||||
* Inerface used for registering template into CMS core.
|
||||
*
|
||||
* @package App\Handlers\Contracts
|
||||
*/
|
||||
interface TemplateHandler extends BaseModuleHandler
|
||||
{
|
||||
/**
|
||||
* Uninstall template
|
||||
*
|
||||
* Delete some items in database, delete files etc.
|
||||
*
|
||||
* @param Module $template
|
||||
*/
|
||||
public static function uninstall(Module $template);
|
||||
|
||||
/**
|
||||
* Get list of registered templates and supported modules.
|
||||
*
|
||||
* Returned array is expected to be array of arrays with following items: module, namespace and templateName.
|
||||
* Example:
|
||||
* return [
|
||||
* ['module' => 'Article', 'templateName' => 'article::template.name']
|
||||
* ];
|
||||
*
|
||||
* When no "namespace" is specified, value strtolower(module) is used instaed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getPublicTemplatePaths();
|
||||
|
||||
/**
|
||||
* Prepare Content object to be rendered using Blade template
|
||||
*
|
||||
* @param Content $content
|
||||
*/
|
||||
public static function beforeRender(Content & $content);
|
||||
|
||||
/**
|
||||
* Modify input data into format which can be understood by edit template
|
||||
*
|
||||
* @param Content $content
|
||||
*/
|
||||
public static function beforePopulatingEditForm(Content & $content);
|
||||
|
||||
/**
|
||||
* Slightly modify Content object before saving into database.
|
||||
*
|
||||
* This way we can do almost whatever we want - even in template
|
||||
*
|
||||
* @param Content $content
|
||||
* @param Request $request
|
||||
*/
|
||||
public static function beforeSave(Content & $content, Request $request);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Handlers\Contracts\AppHandler;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Content;
|
||||
|
||||
/**
|
||||
* Class Handler
|
||||
*
|
||||
* Handler is a class which handles module-specific behaviour which cannot be done by module itself, resp. cannot be
|
||||
* done by some abstract magic.
|
||||
*
|
||||
* @package App\Handlers
|
||||
*/
|
||||
abstract class Handler extends BaseHandler implements AppHandler
|
||||
{
|
||||
/**
|
||||
* todo: Temporary method, will be implemented for each Handler
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function supportCategories()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getHistoryHandler()
|
||||
{
|
||||
return History::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render given module into visitor area.
|
||||
*
|
||||
* @param Content $content DB model from table contents
|
||||
* @param array $parameters parameters used for modifications/custom settings of given model
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function render(Content $content, $parameters)
|
||||
{
|
||||
return Controller::VisitorsView($content->template, ['page' => $content, 'extra' => $parameters]);
|
||||
}
|
||||
|
||||
public static function getExtendedFormSections()
|
||||
{
|
||||
return [
|
||||
'basicInfo' => trans('admin/contents.basicInfo'),
|
||||
'meta' => trans('admin/contents.metaOptions'),
|
||||
'publication' => trans('admin/contents.publicationOptions'),
|
||||
'appearance' => trans('admin/contents.appearance'),
|
||||
'files' => trans('admin/contents.files')
|
||||
];
|
||||
}
|
||||
|
||||
public static function getExtendedFormInputsCreate()
|
||||
{
|
||||
return [
|
||||
'basicInfo' => 'admin.content.formParts.basicInformation',
|
||||
'meta' => 'admin.content.formParts.metaInformation',
|
||||
'publication' => 'admin.content.formParts.publicationSetup',
|
||||
'appearance' => 'admin.content.formParts.appearance',
|
||||
'files' => 'admin.content.formParts.files'
|
||||
];
|
||||
}
|
||||
|
||||
public static function delete(Content $content)
|
||||
{
|
||||
// temporarily nothing to do
|
||||
}
|
||||
|
||||
public static function loadExtraData(Content $content) {
|
||||
// temporarily nothing to do
|
||||
}
|
||||
|
||||
public static function getExtendedFormInputsEdit()
|
||||
{
|
||||
return self::getExtendedFormInputsCreate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Enumerations\ContentStatuses;
|
||||
use App\Handlers\Contracts\HistoryHandler;
|
||||
use App\Helpers\Differ;
|
||||
|
||||
class History implements HistoryHandler
|
||||
{
|
||||
public static function parseColumnName($column)
|
||||
{
|
||||
return trans('admin/history.column' . ucfirst($column));
|
||||
}
|
||||
|
||||
public static function parseChangedValue($changeset)
|
||||
{
|
||||
switch ($changeset->column) {
|
||||
case 'pageContent':
|
||||
$route = route('history.diff', [
|
||||
'revision' => $changeset->edit_batch,
|
||||
'id' => $changeset->id
|
||||
]);
|
||||
|
||||
return "(<a href='" . $route . "'>" . trans('admin/history.diff') . "</a>)";
|
||||
break;
|
||||
case 'metaDescription':
|
||||
return Differ::htmlDiff($changeset->old_value, $changeset->new_value);
|
||||
break;
|
||||
case 'file':
|
||||
if (!$changeset->old_value) {
|
||||
// old value is null -> new file was uploaded
|
||||
return trans('admin/history.uploadedFile', ['file' => $changeset->new_value]);
|
||||
} else {
|
||||
return trans('admin/history.deletedFile', ['file' => $changeset->old_value]);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'status':
|
||||
$statuses = ContentStatuses::getWithTranslations();
|
||||
|
||||
return trans('admin/history.changedFromTo', [
|
||||
'from' => $statuses[$changeset->old_value],
|
||||
'to' => $statuses[$changeset->new_value]
|
||||
]);
|
||||
break;
|
||||
case 'is_homepage':
|
||||
return trans('admin/history.setupAsHomepage');
|
||||
break;
|
||||
default:
|
||||
return trans('admin/history.changedFromTo', [
|
||||
'from' => is_null($changeset->old_value) ? trans('admin/history.emptyValue') : $changeset->old_value,
|
||||
'to' => is_null($changeset->new_value) ? trans('admin/history.emptyValue') : $changeset->new_value,
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators\Items;
|
||||
|
||||
class SettingExtension
|
||||
{
|
||||
/**
|
||||
* @var string human readable ID of settings section (used e.g. as ID parameter in html)
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @var string translations string used for describing briefly settings section
|
||||
*/
|
||||
protected $name;
|
||||
/**
|
||||
* @var string view used for rendering given settings part
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* SettingExtension constructor.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $name
|
||||
* @param string $view
|
||||
*/
|
||||
public function __construct($id, $name, $view)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getView()
|
||||
{
|
||||
return $this->view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Widgets\Contracts\MenuExtensionHandler;
|
||||
|
||||
class MenuExtensionRegistrator {
|
||||
|
||||
protected $menuExtensions;
|
||||
|
||||
/**
|
||||
* @param MenuExtensionHandler $handler
|
||||
*/
|
||||
public function register(MenuExtensionHandler $handler) {
|
||||
$this->menuExtensions[] = $handler;
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return $this->menuExtensions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Enumerations\Exceptions\EnumerationExistsException;
|
||||
use App\Handlers\Contracts\SearchHandler;
|
||||
use App\Handlers\Contracts\SearchPresenterHandler;
|
||||
use App\Handlers\Registrators\Items\SearchEngine;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
class SearchEngineRegistrator
|
||||
{
|
||||
const ADMIN = 'admin';
|
||||
const VISITOR = 'visitor';
|
||||
protected $searchEngines;
|
||||
|
||||
function __construct($app)
|
||||
{
|
||||
$this->searchEngines = [
|
||||
self::ADMIN => [],
|
||||
self::VISITOR => []
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for registering new settings extensions/parts
|
||||
*
|
||||
* @param SearchHandler $search
|
||||
* @param SearchPresenterHandler $presenter
|
||||
*
|
||||
* @param $type
|
||||
*
|
||||
* @throws EnumerationExistsException
|
||||
*/
|
||||
public function register(SearchHandler $search, SearchPresenterHandler $presenter, $type)
|
||||
{
|
||||
$this->checkIfRegistered($type, $search->getId());
|
||||
|
||||
// register new extension
|
||||
$this->searchEngines[$type][$search->getId()] = [$search, $presenter];
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for all registered extensions
|
||||
*
|
||||
* @param $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get($type)
|
||||
{
|
||||
if (!isset($this->searchEngines[$type])) {
|
||||
throw new InvalidArgumentException('Invalid type ' . $type);
|
||||
}
|
||||
|
||||
return $this->searchEngines[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this section is not already defined
|
||||
*
|
||||
* @param $type
|
||||
* @param $id
|
||||
*
|
||||
* @throws EnumerationExistsException
|
||||
*/
|
||||
private function checkIfRegistered($type, $id)
|
||||
{
|
||||
if (isset($this->searchEngines[$type][$id])) {
|
||||
throw new EnumerationExistsException('Already existing search engine ' . $id . ' in ' . $type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Enumerations\Exceptions\EnumerationExistsException;
|
||||
use App\Handlers\Registrators\Items\SettingExtension;
|
||||
|
||||
class SettingsExtensionRegistrator
|
||||
{
|
||||
protected $settingsExtensions;
|
||||
|
||||
function __construct($app)
|
||||
{
|
||||
$this->settingsExtensions = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for registering new settings extensions/parts
|
||||
*
|
||||
* @param $sectionId
|
||||
* @param $sectionName
|
||||
* @param $sectionView
|
||||
*
|
||||
* @throws EnumerationExistsException
|
||||
*/
|
||||
public function register($sectionId, $sectionName, $sectionView)
|
||||
{
|
||||
$this->checkIfRegistered($sectionId);
|
||||
|
||||
// register new extension
|
||||
$this->settingsExtensions[$sectionId] = new SettingExtension($sectionId, $sectionName, $sectionView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new setting part - only as SettingExtension directly
|
||||
*
|
||||
* @param SettingExtension $extension
|
||||
*/
|
||||
public function registerObject(SettingExtension $extension)
|
||||
{
|
||||
$this->checkIfRegistered($extension->getId());
|
||||
|
||||
$this->settingsExtensions[$extension->getId()] = $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for all registered extensions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
// sort registered extensions by key
|
||||
ksort($this->settingsExtensions);
|
||||
|
||||
return $this->settingsExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this section is not already defined
|
||||
*
|
||||
* @param $sectionId
|
||||
*
|
||||
* @throws EnumerationExistsException
|
||||
*/
|
||||
private function checkIfRegistered($sectionId)
|
||||
{
|
||||
if (isset($this->settingsExtensions[$sectionId])) {
|
||||
throw new EnumerationExistsException('Already existing key ' . $sectionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Enumerations\TemplatePaths;
|
||||
use App\Enumerations\Templates;
|
||||
use App\Models\Template;
|
||||
use App\Models\TemplatePath;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
class TemplateRegistrator
|
||||
{
|
||||
/**
|
||||
* @var string absolute path to base directory of registered template paths
|
||||
*/
|
||||
protected $baseDirectory;
|
||||
/**
|
||||
* @var string namespace of registered templates
|
||||
*/
|
||||
protected $namespace;
|
||||
/**
|
||||
* @var string absolute path to currently registered directory
|
||||
* This variable is set in register() method as $baseDirectory/$path
|
||||
*/
|
||||
protected $registeredPath;
|
||||
/**
|
||||
* @var int ID of module
|
||||
*/
|
||||
protected $moduleId;
|
||||
/**
|
||||
* @var array list of all registered template paths
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* Set base path
|
||||
*
|
||||
* @param mixed $baseDirectory
|
||||
*/
|
||||
public function setBaseDirectory($baseDirectory)
|
||||
{
|
||||
$baseDirectory = str_replace('/', DIRECTORY_SEPARATOR, $baseDirectory);
|
||||
$baseDirectory = base_path($baseDirectory);
|
||||
$baseDirectory = rtrim($baseDirectory, DIRECTORY_SEPARATOR);
|
||||
|
||||
if (!is_dir($baseDirectory)) {
|
||||
throw new InvalidArgumentException('Invalid path ' . $baseDirectory);
|
||||
}
|
||||
|
||||
$this->baseDirectory = $baseDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set module ID for registered path
|
||||
*
|
||||
* @param int $moduleId
|
||||
*/
|
||||
public function setModuleId($moduleId)
|
||||
{
|
||||
$this->moduleId = $moduleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set namespace for registered template path
|
||||
*
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets namespace
|
||||
*/
|
||||
public function unsetNamespace()
|
||||
{
|
||||
$this->namespace = null;
|
||||
$this->setModuleId(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new template path.
|
||||
* This method registeres given path itself with all subdirectories
|
||||
*
|
||||
* @param $baseDirectory
|
||||
* @param string $path path relatively to root of the project
|
||||
* @param string $name human readable identification of given template path
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register($baseDirectory, $path, $name)
|
||||
{
|
||||
$this->paths[] = [
|
||||
'namespace' => $this->namespace,
|
||||
'moduleId' => $this->moduleId,
|
||||
'baseDirectory' => $baseDirectory,
|
||||
'path' => $this->baseDirectory . DIRECTORY_SEPARATOR . $path,
|
||||
'name' => $name
|
||||
];
|
||||
$this->unsetNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save templates into database
|
||||
*/
|
||||
public function saveTemplates()
|
||||
{
|
||||
if (!is_array($this->paths) || empty($this->paths)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
if (!empty($path['namespace'])) {
|
||||
$this->setNamespace($path['namespace'] . '::');
|
||||
}
|
||||
$this->setModuleId($path['moduleId']);
|
||||
$this->setBaseDirectory($path['baseDirectory']);
|
||||
|
||||
$this->registeredPath = $this->baseDirectory . DIRECTORY_SEPARATOR . $path['path'];
|
||||
// register path
|
||||
$this->registerPath($this->registeredPath, $path['name']);
|
||||
$this->unsetNamespace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relative path to project root
|
||||
*
|
||||
* @param $directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function relativePath($directory)
|
||||
{
|
||||
return trim(str_replace(base_path(), '', $directory), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl subdirectories and register them
|
||||
*
|
||||
* @param string $directory path relative to $baseDirectory variable
|
||||
* @param string $name name of parent directory
|
||||
*/
|
||||
protected function scanForSubdirectories($directory, $name)
|
||||
{
|
||||
$directories = File::directories($directory);
|
||||
|
||||
foreach ($directories as $dir) {
|
||||
$base = basename($dir);
|
||||
$name = preg_replace('/\.(.+)/', '.' . $base, $name);
|
||||
|
||||
$this->registerPath($dir, $name, $directory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers template path and templates into system
|
||||
*
|
||||
* @param string $path relative path to $baseDirectory variable
|
||||
* @param string $name human readable name of this path (used in overview)
|
||||
* @param null|string $parent path to parent directory
|
||||
*/
|
||||
protected function registerPath($path, $name, $parent = null)
|
||||
{
|
||||
// skip custom directories (contains updated templates only)
|
||||
$dirName = basename($path);
|
||||
$ignoredDirectories = [
|
||||
Template::EDITED_TEMPLATES_DIRECTORY,
|
||||
Template::ASSETS_DIRECTORY,
|
||||
Template::MODULES_DIRECTORY
|
||||
];
|
||||
|
||||
if (in_array($dirName, $ignoredDirectories)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// save template path into database
|
||||
$templatePathId = $this->saveTemplatePath($path, $name, $parent);
|
||||
|
||||
// save all templates into database
|
||||
$this->registerTemplates($path, $templatePathId);
|
||||
|
||||
// try to find some subdirectories and other templates
|
||||
$this->scanForSubdirectories($path, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all templates
|
||||
* This method takes all templates in given directory and registers them into database. Templates registered in
|
||||
* this way may be used for further manipulation.
|
||||
*
|
||||
* @param $path
|
||||
* @param $templatePathId
|
||||
*
|
||||
* @throws \App\Enumerations\Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected function registerTemplates($path, $templatePathId)
|
||||
{
|
||||
$templates = File::files($path);
|
||||
|
||||
foreach ($templates as $template) {
|
||||
|
||||
// skip all non-template files - we assume that every file with suffix ".blade.php" is Blade template
|
||||
if (!Str::endsWith($template, Template::TEMPLATE_SUFFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get all templates and template name (path/to/template.blade.php -> path.to.template)
|
||||
$templateName = $this->getTemplateName($template);
|
||||
$registeredTemplates = Templates::getWithTranslations();
|
||||
|
||||
if (!in_array($templateName, $registeredTemplates)) {
|
||||
$params = [
|
||||
'template_name' => $templateName,
|
||||
'name' => $templateName,
|
||||
'path' => $templatePathId,
|
||||
'module_id' => $this->moduleId,
|
||||
'description' => '',
|
||||
'editable' => 1
|
||||
];
|
||||
|
||||
// save template into database
|
||||
$newTemplate = Template::create($params);
|
||||
|
||||
// push template into enumeration - so it will not be registered again
|
||||
Templates::push($newTemplate->id, $templateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save template into database and return its ID
|
||||
*
|
||||
* @param $path
|
||||
* @param $name
|
||||
* @param null $parent
|
||||
*
|
||||
* @return mixed|null
|
||||
* @throws \App\Enumerations\Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected function saveTemplatePath($path, $name, $parent = null)
|
||||
{
|
||||
$registeredPaths = TemplatePaths::getWithTranslations();
|
||||
$relativePath = $this->relativePath($path);
|
||||
|
||||
if (!in_array($relativePath, $registeredPaths)) {
|
||||
$parentId = $this->getId($this->relativePath($parent));
|
||||
|
||||
$params = [
|
||||
'path' => $relativePath,
|
||||
'name' => $name,
|
||||
'namespace' => $this->namespace,
|
||||
'parent_id' => $parentId
|
||||
];
|
||||
|
||||
// save into database
|
||||
$path = TemplatePath::create($params);
|
||||
|
||||
// add to enumeration
|
||||
TemplatePaths::push($path->id, $relativePath);
|
||||
|
||||
return $path->id;
|
||||
}
|
||||
|
||||
return $this->getId($relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ID of registered template
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return null|int null when parent not found, ID of parent otherwise
|
||||
*/
|
||||
private function getId($path)
|
||||
{
|
||||
// get registered paths
|
||||
$paths = TemplatePaths::getWithTranslations();
|
||||
$paths = array_flip($paths);
|
||||
|
||||
if (is_null($path) || !isset($paths[$path])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $paths[$path];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template name
|
||||
* Converts path to template to corresponding name
|
||||
*
|
||||
* @param $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getTemplateName($template)
|
||||
{
|
||||
$templateName = str_replace($this->registeredPath . DIRECTORY_SEPARATOR, '', $template);
|
||||
$templateName = str_replace(DIRECTORY_SEPARATOR, '.', $templateName);
|
||||
$templateName = str_replace(Template::TEMPLATE_SUFFIX, '', $templateName);
|
||||
|
||||
return $this->namespace . $templateName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Enumerations\WidgetTypesWithHandlers;
|
||||
use App\Models\WidgetType;
|
||||
|
||||
class WidgetRegistrator
|
||||
{
|
||||
protected $registeredWidgets = [];
|
||||
|
||||
|
||||
/**
|
||||
* Method used for registering new widgets
|
||||
*
|
||||
* @param $classname
|
||||
* @param null $templateId
|
||||
* @param null $moduleId
|
||||
*/
|
||||
public function register($classname, $templateId = null, $moduleId = null)
|
||||
{
|
||||
$this->registeredWidgets[] = [
|
||||
'class' => $classname,
|
||||
'templateId' => $templateId,
|
||||
'moduleId' => $moduleId
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Install all non-installed widgets
|
||||
*/
|
||||
public function installWidgets()
|
||||
{
|
||||
$installed = WidgetTypesWithHandlers::getSimple();
|
||||
foreach ($this->registeredWidgets as $registeredWidget) {
|
||||
$classname = $registeredWidget['class'];
|
||||
$templateId = $registeredWidget['templateId'];
|
||||
$moduleId = $registeredWidget['moduleId'];
|
||||
|
||||
// register widget as new widget type
|
||||
if (!in_array($classname, $installed)) {
|
||||
$widgetName = call_user_func($classname . '::getName');
|
||||
$widgetDescription = call_user_func($classname . '::getDescription');
|
||||
|
||||
// create row in widget types
|
||||
WidgetType::create([
|
||||
'handler' => $classname,
|
||||
'name' => $widgetName,
|
||||
'module_id' => $moduleId,
|
||||
'template_id' => $templateId,
|
||||
'description' => $widgetDescription
|
||||
]);
|
||||
|
||||
// install widget (if neccessary)
|
||||
call_user_func($classname . '::install');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace App\Handlers\Search;
|
||||
|
||||
use App\Models\Content as ContentModel;
|
||||
|
||||
class Content extends Search
|
||||
{
|
||||
/**
|
||||
* Search for given patttern/term
|
||||
*
|
||||
* @param string $term searched word
|
||||
*
|
||||
* @return array list of found objects
|
||||
*/
|
||||
public function search($term)
|
||||
{
|
||||
$token = $this->tokenize($term);
|
||||
|
||||
return ContentModel::where('content', 'LIKE', $token)
|
||||
->orWhere('meta_description', 'LIKE', $token)
|
||||
->orWhere('meta_keywords', 'LIKE', $token)
|
||||
->orWhere('title', 'LIKE', $token)
|
||||
->orWhere('url', 'LIKE', $token)
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return 'content';
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return trans('search.content');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace App\Handlers\Search;
|
||||
|
||||
use App\Models\File;
|
||||
|
||||
class Files extends Search
|
||||
{
|
||||
public function getId()
|
||||
{
|
||||
return "files";
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return trans('search.files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for given patttern/term
|
||||
*
|
||||
* @param string $term searched word
|
||||
*
|
||||
* @return array list of found objects
|
||||
*/
|
||||
public function search($term)
|
||||
{
|
||||
$token = $this->tokenize($term);
|
||||
|
||||
return File::where('original_filename', 'LIKE', $token)
|
||||
->orWhere('name', 'LIKE', $token)
|
||||
->orWhere('keywords', 'LIKE', $token)
|
||||
->orWhere('description', 'LIKE', $token)
|
||||
->orWhere('mime_type', 'LIKE', $token)
|
||||
->get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace App\Handlers\Search\Presenters;
|
||||
|
||||
use App\Enumerations\ContentStatuses;
|
||||
use App\Handlers\Contracts\SearchPresenterHandler;
|
||||
|
||||
class AdminContent implements SearchPresenterHandler
|
||||
{
|
||||
public function render($foundItems)
|
||||
{
|
||||
return view('admin.search.results.content', [
|
||||
'pages' => $foundItems,
|
||||
'statuses' => ContentStatuses::getWithTranslations(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace App\Handlers\Search\Presenters;
|
||||
|
||||
use App\Handlers\Contracts\SearchPresenterHandler;
|
||||
|
||||
class AdminFiles implements SearchPresenterHandler
|
||||
{
|
||||
/**
|
||||
* Method for rendering list of found results
|
||||
*
|
||||
* @param $foundItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($foundItems)
|
||||
{
|
||||
return view('admin.fileManager.filesTiles', ['files' => $foundItems, 'hideDelete' => true]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
namespace App\Handlers\Search;
|
||||
|
||||
use App\Handlers\Contracts\SearchHandler;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
abstract class Search implements SearchHandler
|
||||
{
|
||||
/**
|
||||
* Tokenize string for usage in LIKE clausules
|
||||
*
|
||||
* @param $term
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function tokenize($term)
|
||||
{
|
||||
$term = trim($term);
|
||||
|
||||
if (empty($term)) {
|
||||
throw new InvalidArgumentException(trans('search.emptyString'));
|
||||
}
|
||||
|
||||
return '%' . str_replace(' ', '%', $term) . '%';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Module;
|
||||
use DebugBar\Bridge\MonologCollector;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Monolog\Logger;
|
||||
|
||||
class CurrentTemplate
|
||||
{
|
||||
protected static $template;
|
||||
protected static $initialized = false;
|
||||
|
||||
/**
|
||||
* Getter for currently set template
|
||||
* @return Module
|
||||
* @throws \ErrorException
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (!self::$initialized) {
|
||||
try {
|
||||
self::$template = Module::where('is_template', true)
|
||||
->where('enabled', true)
|
||||
->first();
|
||||
} catch (QueryException $e) {
|
||||
throw new \ErrorException('DB not migrated, please, do so!');
|
||||
}
|
||||
if (self::$template) {
|
||||
self::$template->module_settings = json_decode(self::$template->module_settings);
|
||||
}
|
||||
|
||||
self::$initialized = true;
|
||||
}
|
||||
|
||||
return self::$template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for getting template handler
|
||||
*
|
||||
* @return string
|
||||
* @throws \ErrorException
|
||||
*/
|
||||
public static function handler()
|
||||
{
|
||||
$template = self::get();
|
||||
|
||||
if (!$template) {
|
||||
throw new \ErrorException('No template selected, no handler available!');
|
||||
}
|
||||
|
||||
return $template->handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset currently set template and load another one on next call of get() method.
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$initialized = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
class Date
|
||||
{
|
||||
/**
|
||||
* Print date in configured format
|
||||
*
|
||||
* @param $datestamp
|
||||
* @param bool $withTime
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function date($datestamp, $withTime = true)
|
||||
{
|
||||
$timestamp = strtotime($datestamp);
|
||||
|
||||
if ($timestamp <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$format = $withTime ? config('app.datetime_format') : config('app.date_format');
|
||||
|
||||
return date($format, $timestamp);
|
||||
}
|
||||
|
||||
public static function dateFormatted($format, $datestamp)
|
||||
{
|
||||
$timestamp = strtotime($datestamp);
|
||||
|
||||
if ($timestamp <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return date($format, $timestamp);
|
||||
}
|
||||
|
||||
public static function monthName($datestamp) {
|
||||
$timestamp = strtotime($datestamp);
|
||||
|
||||
if ($timestamp <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$months = [
|
||||
trans('common.months.january'),
|
||||
trans('common.months.february'),
|
||||
trans('common.months.march'),
|
||||
trans('common.months.april'),
|
||||
trans('common.months.may'),
|
||||
trans('common.months.june'),
|
||||
trans('common.months.july'),
|
||||
trans('common.months.august'),
|
||||
trans('common.months.semptember'),
|
||||
trans('common.months.october'),
|
||||
trans('common.months.november'),
|
||||
trans('common.months.december'),
|
||||
];
|
||||
|
||||
$monthNumber = date('n', $timestamp);
|
||||
|
||||
return $months[$monthNumber - 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
/*
|
||||
Paul's Simple Differ Algorithm v 0.1
|
||||
(C) Paul Butler 2007 <http://www.paulbutler.org/>
|
||||
May be used and distributed under the zlib/libpng license.
|
||||
|
||||
This code is intended for learning purposes; it was written with short
|
||||
code taking priority over performance. It could be used in a practical
|
||||
application, but there are a few ways it could be optimized.
|
||||
|
||||
Given two arrays, the function diff will return an array of the changes.
|
||||
I won't describe the format of the array, but it will be obvious
|
||||
if you use print_r() on the result of a diff on some test data.
|
||||
|
||||
htmlDiff is a wrapper for the diff command, it takes two strings and
|
||||
returns the differences in HTML. The tags used are <ins> and <del>,
|
||||
which can easily be styled with CSS.
|
||||
|
||||
@url https://github.com/paulgb/simplediff/blob/master/php/simplediff.php
|
||||
|
||||
Sorry for this kind of magic, I have no idea how this works.. :(
|
||||
*/
|
||||
|
||||
class Differ
|
||||
{
|
||||
public static function diff($old, $new)
|
||||
{
|
||||
$matrix = [];
|
||||
$maxlen = 0;
|
||||
foreach ($old as $oindex => $ovalue) {
|
||||
$nkeys = array_keys($new, $ovalue);
|
||||
foreach ($nkeys as $nindex) {
|
||||
$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
|
||||
if ($matrix[$oindex][$nindex] > $maxlen) {
|
||||
$maxlen = $matrix[$oindex][$nindex];
|
||||
$omax = $oindex + 1 - $maxlen;
|
||||
$nmax = $nindex + 1 - $maxlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($maxlen == 0) {
|
||||
return [['d' => $old, 'i' => $new]];
|
||||
}
|
||||
|
||||
return array_merge(self::diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)), array_slice($new, $nmax, $maxlen), self::diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
|
||||
}
|
||||
|
||||
public static function htmlDiff($old, $new)
|
||||
{
|
||||
$ret = '';
|
||||
$diff = self::diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new));
|
||||
foreach ($diff as $k) {
|
||||
if (is_array($k)) {
|
||||
$ret .= (!empty($k['d']) ? "<del>" . implode(' ', $k['d']) . "</del> " : '') . (!empty($k['i']) ? "<ins>" . implode(' ', $k['i']) . "</ins> " : '');
|
||||
} else {
|
||||
$ret .= $k . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\File;
|
||||
|
||||
class FileManager
|
||||
{
|
||||
/**
|
||||
* @param File $file
|
||||
*
|
||||
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
|
||||
*/
|
||||
public static function getPreview(File $file)
|
||||
{
|
||||
list($type, $subtype) = explode('/', $file->mime_type);
|
||||
|
||||
switch ($type) {
|
||||
case 'image':
|
||||
|
||||
$url = Template::thumbnail($file->filename);
|
||||
|
||||
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
||||
break;
|
||||
case 'text':
|
||||
return self::getIcon($file, 'fa-file-text-o');
|
||||
break;
|
||||
case 'application':
|
||||
switch ($subtype) {
|
||||
case 'pdf':
|
||||
return self::getIcon($file, 'fa-file-pdf-o');
|
||||
break;
|
||||
default:
|
||||
return self::getIcon($file, 'fa-newspaper-o');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return self::getIcon($file, 'fa-question');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for displaying icons
|
||||
*
|
||||
* @param $file
|
||||
* @param $icon
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getIcon($file, $icon)
|
||||
{
|
||||
return '<p><i class="fa fa-2x ' . $icon . '"></i><br /><span>' . e(str_limit($file->original_filename, 15)) . '</span></p>';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param File $file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getFormattedSize(File $file)
|
||||
{
|
||||
$bytes = $file->file_size;
|
||||
|
||||
$label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||
for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++) {
|
||||
;
|
||||
}
|
||||
|
||||
return (round($bytes, 2) . " " . $label[$i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get preview for file detail
|
||||
*
|
||||
* @param File $file
|
||||
*
|
||||
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
|
||||
*/
|
||||
public static function getLargePreview(File $file)
|
||||
{
|
||||
list($type, $subtype) = explode('/', $file->mime_type);
|
||||
|
||||
$url = config('app.upload_url') . '/' . $file->filename;
|
||||
$path = config('app.upload_path') . DIRECTORY_SEPARATOR . $file->filename;
|
||||
|
||||
switch ($type) {
|
||||
case 'image':
|
||||
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
||||
break;
|
||||
case 'text':
|
||||
$string = '<pre><code>';
|
||||
$string .= htmlspecialchars(file_get_contents($path));
|
||||
$string .= '</pre></code>';
|
||||
|
||||
return $string;
|
||||
break;
|
||||
case 'application':
|
||||
return '<iframe src = "'.asset('resources/assets/admin/js/viewerJs/').'/#'.Template::upload($file->filename).'" style="width: 100%; height: 50em" allowfullscreen webkitallowfullscreen></iframe>';
|
||||
break;
|
||||
default:
|
||||
return self::getPreview($file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param File $file
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAdditionalInfo(File $file)
|
||||
{
|
||||
list($type, $subtype) = explode('/', $file->mime_type);
|
||||
|
||||
$path = config('app.upload_path') . DIRECTORY_SEPARATOR . $file->filename;
|
||||
|
||||
switch ($type) {
|
||||
case 'text':
|
||||
return [trans('admin/fileManager.encoding') => mb_detect_encoding(file_get_contents($path))];
|
||||
break;
|
||||
|
||||
case 'image':
|
||||
list ($width, $height) = getimagesize($path);
|
||||
return [trans('admin/fileManager.resolution') => $height . ' x ' . $width,];
|
||||
break;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
class Gravatar
|
||||
{
|
||||
public static function img($email, $size = 50)
|
||||
{
|
||||
return "//www.gravatar.com/avatar/" . md5(strtolower(trim($email))) . "?s=" . $size;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Handlers\Contracts\AppHandler;
|
||||
use App\Models\Content;
|
||||
use Webwizo\Shortcodes\Facades\Shortcode;
|
||||
|
||||
/**
|
||||
* Class PageRenderer
|
||||
*
|
||||
* Simple class for rendering page for visitor
|
||||
*
|
||||
* @package App\Helpers
|
||||
*/
|
||||
class PageRenderer
|
||||
{
|
||||
/**
|
||||
* Render page
|
||||
*
|
||||
* @param Content $page
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function render(Content $page)
|
||||
{
|
||||
// decode module settings
|
||||
$page->module_settings = json_decode($page->module_settings);
|
||||
|
||||
// do something template-specific
|
||||
$parameters = call_user_func_array([CurrentTemplate::handler(), 'beforeRender'], [&$page]);
|
||||
|
||||
/**
|
||||
* @var $handler AppHandler
|
||||
*/
|
||||
// get handler
|
||||
$handler = new $page->module_handler;
|
||||
|
||||
$page->content = Shortcode::compile($page->content);
|
||||
|
||||
// render page
|
||||
return $handler->render($page, $parameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Settings as SettingsModel;
|
||||
|
||||
/**
|
||||
* Class Settings
|
||||
*
|
||||
* Helper class for easier obtaining system settings
|
||||
*
|
||||
* @package App\Helpers
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
/**
|
||||
* @var array List of all used settings
|
||||
*/
|
||||
protected static $settings;
|
||||
/**
|
||||
* @var bool Are data already initialized?
|
||||
*/
|
||||
protected static $initialized = false;
|
||||
|
||||
/**
|
||||
* Getter for settings determined with key.
|
||||
*
|
||||
* @param string $key settings key
|
||||
* @param string|null $default default value, which will be returned when given key does not exist
|
||||
*
|
||||
* @param null $exists
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public static function get($key, $default = null, & $exists = null)
|
||||
{
|
||||
self::init();
|
||||
|
||||
if (isset(self::$settings->$key)) {
|
||||
$exists = true;
|
||||
self::$initialized = true;
|
||||
return self::$settings->$key;
|
||||
}
|
||||
|
||||
$exists = false;
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for obtaining settings saved as JSON
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getJson($key)
|
||||
{
|
||||
return json_decode(self::get($key, '{}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
self::init();
|
||||
|
||||
return self::$settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize settings array
|
||||
*/
|
||||
private static function init()
|
||||
{
|
||||
if (!self::$initialized) {
|
||||
$model = new SettingsModel();
|
||||
self::$settings = $model->getAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
class Template
|
||||
{
|
||||
/**
|
||||
* Getter for real template name
|
||||
*
|
||||
* @param $template
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public static function name($template, $throwExceptions = true)
|
||||
{
|
||||
$namespace = null;
|
||||
if (strpos($template, '::')) {
|
||||
list($namespace, $template) = explode('::', $template);
|
||||
$namespace .= '::';
|
||||
}
|
||||
|
||||
// list of prefixes
|
||||
$prefixes = ['custom.', ''];
|
||||
|
||||
$view = null;
|
||||
foreach ($prefixes as $prefix) {
|
||||
if (view()->exists($namespace . 'visitor.' . $prefix . $template)) {
|
||||
$view = $namespace . 'visitor.' . $prefix . $template;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($view)) {
|
||||
if ($throwExceptions) {
|
||||
throw new InvalidArgumentException('Cannot find template for ' . $namespace . $template);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL to uploaded file
|
||||
*
|
||||
* @param $filename
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function upload($filename)
|
||||
{
|
||||
// for debug environment check if file exists
|
||||
if (env('APP_DEBUG') && !file_exists(config('app.upload_path') . '/' . $filename)) {
|
||||
throw new NotFoundHttpException('File ' . $filename . ' cannot be found in ' . config('app.upload_path') . '.');
|
||||
}
|
||||
|
||||
// return url to uploaded file
|
||||
return config('app.upload_url') . '/' . $filename;
|
||||
}
|
||||
|
||||
public static function thumbnail($filename)
|
||||
{
|
||||
// try to check if file have thumbnail
|
||||
if (file_exists(config('app.thumbnail_path') . '/' . $filename)) {
|
||||
$url = config('app.thumbnail_url') . '/' . $filename;
|
||||
} else {
|
||||
$url = self::upload($filename);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to given asset
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function asset($path)
|
||||
{
|
||||
if (env('APP_DEBUG')) {
|
||||
if (empty($path)) {
|
||||
throw new InvalidArgumentException('No asset name defined!');
|
||||
}
|
||||
|
||||
// check if asset exists and is file
|
||||
if (!file_exists(public_path('assets/' . config('app.theme') . '/' . $path))) {
|
||||
throw new NotFoundHttpException('Cannot find any asset in ' . public_path('assets/' . config('app.theme') . '/' . $path) . '. Try to check your paths.');
|
||||
}
|
||||
}
|
||||
|
||||
return config('app.url') . '/assets/' . config('app.theme') . '/' . $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print date in configured format
|
||||
*
|
||||
* @param $datestamp
|
||||
* @param bool $withTime
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function date($datestamp, $withTime = true)
|
||||
{
|
||||
$timestamp = strtotime($datestamp);
|
||||
|
||||
if ($timestamp <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$format = $withTime ? config('app.datetime_format') : config('app.date_format');
|
||||
|
||||
return date($format, $timestamp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\WidgetArea;
|
||||
|
||||
class WidgetAreas
|
||||
{
|
||||
/**
|
||||
* @var array list of inicialized widget areas
|
||||
*/
|
||||
protected static $widgetAreas = [];
|
||||
protected static $initialized = false;
|
||||
|
||||
protected static function saveRenderedWidgetArea($widgets)
|
||||
{
|
||||
foreach ($widgets as $widget) {
|
||||
if (!isset(self::$widgetAreas[$widget->widget_area_code]))
|
||||
self::$widgetAreas[$widget->widget_area_code] = '';
|
||||
|
||||
$handler = $widget->widget_type_handler;
|
||||
$widget->settings = json_decode($widget->settings);
|
||||
$presenter = call_user_func([$handler, 'getPresenter']);
|
||||
|
||||
self::$widgetAreas[$widget->widget_area_code] .= call_user_func([$presenter, 'render'], $widget);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function loadWidgetArea($uniqueCode)
|
||||
{
|
||||
$widgetArea = new WidgetArea();
|
||||
$widgets = $widgetArea->getWidgets($uniqueCode)
|
||||
->get();
|
||||
|
||||
WidgetArea::where('code', $uniqueCode)
|
||||
->increment('viewed');
|
||||
|
||||
self::saveRenderedWidgetArea($widgets);
|
||||
}
|
||||
|
||||
protected static function initWidgetAreas()
|
||||
{
|
||||
if (self::$initialized)
|
||||
return;
|
||||
|
||||
$widgetArea = new WidgetArea();
|
||||
$widgets = $widgetArea->getWidgets()
|
||||
->get();
|
||||
|
||||
self::saveRenderedWidgetArea($widgets);
|
||||
self::$initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderer for whole widget area.
|
||||
*
|
||||
* @param $uniqueCode
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function render($uniqueCode)
|
||||
{
|
||||
if (!self::$initialized) {
|
||||
self::initWidgetAreas();
|
||||
}
|
||||
|
||||
if (!isset(self::$widgetAreas[$uniqueCode])) {
|
||||
self::loadWidgetArea($uniqueCode);
|
||||
}
|
||||
|
||||
echo isset(self::$widgetAreas[$uniqueCode]) ? self::$widgetAreas[$uniqueCode] : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Define function for escaping characters.
|
||||
*
|
||||
* This funcion prevents of creating build-in function, which escapes also accents...
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function e($value)
|
||||
{
|
||||
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for \App\Helpers\Settings::get()
|
||||
*
|
||||
* @param $key
|
||||
* @param null $default
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
function setting($key, $default = null) {
|
||||
return \App\Helpers\Settings::get($key, $default);
|
||||
}
|
||||
|
||||
function asset_path($path) {
|
||||
return env('SITE_URL').'/assets/'.$path;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\ActionLog;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Models\ActionLog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class Overview extends Controller
|
||||
{
|
||||
/**
|
||||
* @var ActionLog
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* ActionLog constructor.
|
||||
*
|
||||
* @param ActionLog $log
|
||||
*/
|
||||
public function __construct(ActionLog $log)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->log = $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get overview of logged actions
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getOverview()
|
||||
{
|
||||
$user = null;
|
||||
$userId = Input::get('userId');
|
||||
|
||||
$actions = $this->log->getLogActionsQuery(true);
|
||||
|
||||
if ($userId) {
|
||||
$user = User::findOrFail($userId);
|
||||
$actions->where('users.id', $userId);
|
||||
}
|
||||
|
||||
$actions = $actions->paginate(25);
|
||||
|
||||
$this->log->translateLogMessages($actions);
|
||||
|
||||
return view('admin.actionLog.overview', ['actions' => $actions, 'user' => $user]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\Contents;
|
||||
|
||||
use App\Enumerations\ContentStatuses;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Models\Content;
|
||||
use App\Models\Module;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class ContentOverview extends Controller
|
||||
{
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
private $content;
|
||||
|
||||
public function __construct(Content $content)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overview for all content pages.
|
||||
*
|
||||
* @param bool|false $moduleId
|
||||
* @param null $status
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getOverview($moduleId = false, $status = null)
|
||||
{
|
||||
$moduleFilterHandler = false;
|
||||
$perPage = Input::get('perPage') ? Input::get('perPage') : 20;
|
||||
$pageHeading = 'admin/contents.overview';
|
||||
|
||||
// does user want to filter results using module?
|
||||
if (is_numeric($moduleId)) {
|
||||
$module = Module::findOrFail($moduleId);
|
||||
$moduleFilterHandler = $module->handler;
|
||||
|
||||
if (is_callable([$module->handler, 'getOverviewTitle'])) {
|
||||
$pageHeading = call_user_func([$module->handler, 'getOverviewTitle']);
|
||||
}
|
||||
}
|
||||
|
||||
// get pages for overview
|
||||
$pages = $this->content->getOverview($moduleFilterHandler, $status, true, true)
|
||||
->paginate($perPage);
|
||||
|
||||
// get homepage - for checking if homepage is set and available
|
||||
$homepage = $this->content->getHomepage();
|
||||
|
||||
return view('admin.content.overview', [
|
||||
'pages' => $pages,
|
||||
'homepage' => $homepage,
|
||||
'pageHeading' => $pageHeading,
|
||||
'statuses' => ContentStatuses::getWithTranslations(),
|
||||
'module' => isset($module) ? $module : null
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\Contents;
|
||||
|
||||
use App\Enumerations\ContentStatuses;
|
||||
use App\Events\CreateNewContent as CreateNewContentEvent;
|
||||
use App\Helpers\CurrentTemplate;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\CreateNewContentRequest;
|
||||
use App\Models\Content;
|
||||
use App\Models\File;
|
||||
use App\Models\Module;
|
||||
use App\Models\Template;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Str;
|
||||
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
||||
use Modules\Categories\Entities\Category;
|
||||
use Pingpong\Modules\Facades\Module as ModuleInstance;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class CreateNewContent
|
||||
*
|
||||
* Controller for creating new content page.
|
||||
*
|
||||
* @package App\Http\Controllers\Admin\Contents
|
||||
*/
|
||||
class CreateNewContent extends Controller
|
||||
{
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
private $file;
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* CreateNewContent constructor.
|
||||
*
|
||||
* Sets File and Content models into class variables
|
||||
*
|
||||
* @param File $file
|
||||
* @param Content $content
|
||||
*/
|
||||
public function __construct(File $file, Content $content)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->file = $file;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display form for new content page
|
||||
*
|
||||
* @param $moduleId
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getNew($moduleId)
|
||||
{
|
||||
$module = Module::findOrFail($moduleId);
|
||||
$statuses = ContentStatuses::getWithTranslations();
|
||||
|
||||
// set default page title
|
||||
$pageHeading = trans('admin/contents.new', ['name' => trans($module->name)]);
|
||||
if (is_callable([$module->handler, 'getCreateNewTitle'])) {
|
||||
$pageHeading = call_user_func([$module->handler, 'getCreateNewTitle']);
|
||||
}
|
||||
|
||||
// get list of usable templates
|
||||
$templates = Template::where('module_id', $moduleId)
|
||||
->select(['template_name', 'name', 'description'])
|
||||
->get();
|
||||
|
||||
// add categories, if supported
|
||||
$categoryModule = ModuleInstance::get('categories');
|
||||
$categories = [];
|
||||
if ($module->support_categories && !is_null($categoryModule) && $categoryModule->enabled()) {
|
||||
$categories = Category::where('module_id', $moduleId)
|
||||
->get();
|
||||
}
|
||||
|
||||
// create default content object
|
||||
$this->content->status = Content::STATUS_DRAFT;
|
||||
|
||||
// render view
|
||||
return view('admin.content.new', [
|
||||
'pageHeading' => $pageHeading,
|
||||
'contentStatuses' => $statuses,
|
||||
'templates' => $templates,
|
||||
'moduleId' => $moduleId,
|
||||
'module' => $module,
|
||||
'categories' => $categories,
|
||||
'page' => $this->content,
|
||||
'rootPages' => $this->content->getOverview()
|
||||
->get(),
|
||||
'moduleName' => trans($module->name),
|
||||
'extraData' => call_user_func([$module->handler, 'loadExtraData'], $this->content),
|
||||
'formSectionNames' => call_user_func([$module->handler, 'getExtendedFormSections']),
|
||||
'formSections' => call_user_func([$module->handler, 'getExtendedFormInputsCreate']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save new content page
|
||||
*
|
||||
* @param CreateNewContentRequest $request
|
||||
* @param $moduleId
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postNew(CreateNewContentRequest $request, $moduleId)
|
||||
{
|
||||
try {
|
||||
$module = Module::findOrFail($moduleId);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->withInput()
|
||||
->with('error', trans('admin/contents.invalidModule'));
|
||||
}
|
||||
|
||||
// create new page
|
||||
$page = new Content();
|
||||
$page->template = $request->template;
|
||||
|
||||
// setup basic info
|
||||
$page->user_id = \Auth::user()->id;
|
||||
$page->language = LaravelLocalization::getCurrentLocale();
|
||||
$page->title = $request->title;
|
||||
$page->url = Str::slug($request->url);
|
||||
$page->published_from = empty($request->publishedFrom) ? null : $request->publishedFrom;
|
||||
$page->published_to = empty($request->publishedTo) ? null : $request->publishedTo;
|
||||
$page->meta_keywords = $request->metaKeywords;
|
||||
$page->meta_description = $request->metaDescription;
|
||||
$page->content = $request->pageContent;
|
||||
$page->status = $request->status;
|
||||
$page->module_handler = $module->handler;
|
||||
$page->category_id = (int)$request->category > 0 ? $request->category : null;
|
||||
|
||||
// is any parent page specified?
|
||||
if ($request->parentPage) {
|
||||
$page->parent_id = $request->parentPage;
|
||||
}
|
||||
|
||||
// upload file - if provided
|
||||
$file = $page->uploadTitlePhoto($request);
|
||||
|
||||
$page->title_photo = $file ? $file['filename'] : null;
|
||||
|
||||
// save module-specific stuff
|
||||
call_user_func_array([$module->handler, 'createNew'], [&$page, $request]);
|
||||
|
||||
// let template to modify request and content page
|
||||
call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]);
|
||||
|
||||
// save content of page before (possible) uploading related files
|
||||
$page->save();
|
||||
|
||||
// upload files assigned to content page
|
||||
$page->uploadRelatedFiles($request);
|
||||
|
||||
// fire event about creating new content page
|
||||
Event::fire(new CreateNewContentEvent($page));
|
||||
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.successfullyCreated'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\Contents;
|
||||
|
||||
use App\Enumerations\ContentStatuses;
|
||||
use App\Events\AttemptToEditInvalidContent;
|
||||
use App\Events\DeleteContent;
|
||||
use App\Events\EditContent as EditContentEvent;
|
||||
use App\Events\MakeDraftFromContent;
|
||||
use App\Events\PublishContent;
|
||||
use App\Events\SetHomepage;
|
||||
use App\Helpers\CurrentTemplate;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\EditContentRequest;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Content;
|
||||
use App\Models\ContentHistory;
|
||||
use App\Models\File;
|
||||
use App\Models\Module;
|
||||
use App\Models\Template;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Str;
|
||||
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
||||
use Modules\Categories\Entities\Category;
|
||||
use Pingpong\Modules\Facades\Module as ModuleInstance;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class EditContent extends Controller
|
||||
{
|
||||
/**
|
||||
* @var ContentHistory
|
||||
*/
|
||||
private $history;
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* EditContent constructor.
|
||||
*
|
||||
* Load ContentHistory and File into this controller
|
||||
*
|
||||
* @param ContentHistory $history
|
||||
* @param File $file
|
||||
*/
|
||||
public function __construct(ContentHistory $history, File $file)
|
||||
{
|
||||
$this->history = $history;
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display form for editing static page
|
||||
*
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getEdit($id)
|
||||
{
|
||||
// select all content statuses
|
||||
$statuses = ContentStatuses::getWithTranslations();
|
||||
|
||||
// try to find requested page
|
||||
$page = Content::findOrFail($id);
|
||||
$page->module_settings = json_decode($page->module_settings);
|
||||
|
||||
// get module ID
|
||||
$module = Module::where('handler', $page->module_handler)
|
||||
->firstOrFail();
|
||||
|
||||
$pageHeading = trans('admin/contents.edit', ['name' => e($page->title)]);
|
||||
if (is_callable([$module->handler, 'getCreateNewTitle'])) {
|
||||
$pageHeading = call_user_func([$module->handler, 'getEditTitle'], $page);
|
||||
}
|
||||
|
||||
// get all Blade templates for rendering page
|
||||
$templates = Template::where('module_id', $module->id)
|
||||
->select(['template_name', 'name', 'description'])
|
||||
->get();
|
||||
|
||||
// get module for Categories - PingPong module
|
||||
$categoryModule = ModuleInstance::get('categories');
|
||||
|
||||
// add categories, if supported
|
||||
$categories = [];
|
||||
if ($module->support_categories && !is_null($categoryModule) && $categoryModule->enabled()) {
|
||||
$categories = Category::where('module_id', $module->id)
|
||||
->get();
|
||||
}
|
||||
|
||||
// modify data for edit form according to installed template
|
||||
call_user_func_array([CurrentTemplate::handler(), 'beforePopulatingEditForm'], [&$page]);
|
||||
|
||||
$history = $this->history->getStructuredHistoryOf($page);
|
||||
|
||||
// render view
|
||||
return view('admin.content.edit', [
|
||||
'pageHeading' => $pageHeading,
|
||||
'contentStatuses' => $statuses,
|
||||
'page' => $page,
|
||||
'module' => $module,
|
||||
'categories' => $categories,
|
||||
'rootPages' => $page->getOverview()
|
||||
->where('contents.id', '!=', $page->id)
|
||||
->get(),
|
||||
'templates' => $templates,
|
||||
'extraData' => call_user_func([$page->module_handler, 'loadExtraData'], $page),
|
||||
'formSectionNames' => call_user_func([$page->module_handler, 'getExtendedFormSections']),
|
||||
'formSections' => call_user_func([$page->module_handler, 'getExtendedFormInputsEdit']),
|
||||
'historySize' => count($history['changesets'])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit static page and save changes into history.
|
||||
*
|
||||
* @param EditContentRequest $request
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postEdit(EditContentRequest $request, $id)
|
||||
{
|
||||
try {
|
||||
/**
|
||||
* @var $page Content
|
||||
*/
|
||||
$page = Content::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
|
||||
// log attempt of invalid edit
|
||||
Event::fire(new AttemptToEditInvalidContent($id));
|
||||
|
||||
// page for editing not found
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('error', trans('admin/contents.invalidPage'));
|
||||
}
|
||||
|
||||
// upload file - if provided
|
||||
$file = $page->uploadTitlePhoto($request);
|
||||
|
||||
// let template to modify request and content page
|
||||
call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]);
|
||||
|
||||
$request->url = Str::slug($request->url);
|
||||
$request->parentPage = $request->parentPage ? $request->parentPage : null;
|
||||
|
||||
$request->publishedFrom = empty($request->publishedFrom) ? null : $request->publishedFrom;
|
||||
$request->publishedTo = empty($request->publishedTo) ? null : $request->publishedTo;
|
||||
|
||||
if (!$file) {
|
||||
$request->titlePhotoFilename = empty($request->existingTitlePhoto) ? null : $request->existingTitlePhoto;
|
||||
} else {
|
||||
$request->titlePhotoFilename = $file['filename'];
|
||||
}
|
||||
|
||||
// array of fields in database and fields from request
|
||||
$fields = [
|
||||
'title' => 'title',
|
||||
'url' => 'url',
|
||||
'template' => 'template',
|
||||
'published_from' => 'publishedFrom',
|
||||
'published_to' => 'publishedTo',
|
||||
'meta_keywords' => 'metaKeywords',
|
||||
'meta_description' => 'metaDescription',
|
||||
'content' => 'pageContent',
|
||||
'parent_id' => 'parentPage',
|
||||
'status' => 'status',
|
||||
'title_photo' => 'titlePhotoFilename',
|
||||
'category_id' => 'category'
|
||||
];
|
||||
|
||||
// save new values with history
|
||||
$data = self::getFields($request, array_values($fields));
|
||||
|
||||
list($revision, $changedColumns) = $page->updateWithHistory($fields, $data);
|
||||
|
||||
$changedColumns += call_user_func_array([$page->module_handler, 'edit'], [&$page, $request, $revision]);
|
||||
$changedColumns += $page->uploadRelatedFiles($request, $revision);
|
||||
|
||||
// was something changed?
|
||||
if ($changedColumns == 0) {
|
||||
return redirect()
|
||||
->route('content.edit', ['id' => $page->id])
|
||||
->with('error', trans('admin/contents.nothingToEdit'));
|
||||
}
|
||||
|
||||
// fire event with
|
||||
Event::fire(new EditContentEvent($page, $revision));
|
||||
|
||||
// something was changed, inform user
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.successfullyEdited'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for changing page status
|
||||
* This method is called in static page overview from quick actions. It checks if status is valid, if page exists
|
||||
* and updates status.
|
||||
*
|
||||
* @param $id
|
||||
* @param $status
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeStatus($id, $status)
|
||||
{
|
||||
// get possible statuses
|
||||
$statuses = ContentStatuses::getWithTranslations();
|
||||
|
||||
// check if given status is valid
|
||||
if (!isset($statuses[$status])) {
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('error', trans('admin/contents.invalidStatus'));
|
||||
}
|
||||
|
||||
try {
|
||||
// try to find this page
|
||||
$page = Content::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
// page not found
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('error', trans('admin/contents.invalidPage'));
|
||||
}
|
||||
|
||||
// try to change the page
|
||||
list ($revision, $changedColumns) = $page->updateWithHistory(['status' => 'status'], ['status' => $status]);
|
||||
|
||||
// was something changed?
|
||||
if ($changedColumns == 0) {
|
||||
return redirect()
|
||||
->route('content.edit', ['id' => $page->id])
|
||||
->with('error', trans('admin/contents.nothingToEdit'));
|
||||
}
|
||||
|
||||
// fire events
|
||||
if ($status != Content::STATUS_DRAFT) {
|
||||
Event::fire(new PublishContent($page, $revision));
|
||||
} else {
|
||||
Event::fire(new MakeDraftFromContent($page, $revision));
|
||||
}
|
||||
|
||||
// redirect back to overview with info for user
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.statusChanged'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete page
|
||||
*
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function deletePage($id)
|
||||
{
|
||||
try {
|
||||
// try to find this page
|
||||
$page = Content::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
// page not found
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('error', trans('admin/contents.invalidPage'));
|
||||
}
|
||||
|
||||
// change url to something unique
|
||||
$oldURL = $page->url;
|
||||
$page->url .= uniqid('deleted_');
|
||||
$page->save();
|
||||
|
||||
// delete page
|
||||
$page->delete();
|
||||
|
||||
// let module to delete some extra content created during page's life
|
||||
call_user_func([$page->module_handler, 'delete'], $page);
|
||||
|
||||
// trigger delete event
|
||||
Event::fire(new DeleteContent($page));
|
||||
|
||||
// redirect back to overview with info for user
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.pageDeleted', [
|
||||
'name' => $page->title,
|
||||
'url' => $oldURL
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets page as homepage
|
||||
*
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function setHomepage($id)
|
||||
{
|
||||
try {
|
||||
// try to find this page
|
||||
/**
|
||||
* @var $page Content
|
||||
*/
|
||||
$page = Content::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
// page not found
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans('admin/contents.invalidPage'));
|
||||
}
|
||||
|
||||
// disable any other existing homepage
|
||||
Content::where('is_homepage', 1)
|
||||
->where('language', LaravelLocalization::getCurrentLocale())
|
||||
->update(['is_homepage' => 0]);
|
||||
|
||||
// set new homepage
|
||||
list ($revision, $changedColumns) = $page->updateWithHistory(['is_homepage' => 'is_homepage'], ['is_homepage' => 1]);
|
||||
|
||||
// was something changed?
|
||||
if ($changedColumns == 0) {
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans('admin/contents.nothingToEdit'));
|
||||
}
|
||||
|
||||
// trigger delete event
|
||||
Event::fire(new SetHomepage($page, $revision));
|
||||
|
||||
// redirect back to overview with info for user
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success', trans('admin/contents.homepageSetup', [
|
||||
'name' => $page->title,
|
||||
'url' => $page->url
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object of all request data into array of only wanted fields
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $fields
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getFields(Request $request, $fields)
|
||||
{
|
||||
$requestData = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$requestData[$field] = $request->$field;
|
||||
}
|
||||
|
||||
return $requestData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\Contents;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Models\Content;
|
||||
use App\Models\ContentHistory;
|
||||
|
||||
class History extends Controller
|
||||
{
|
||||
/**
|
||||
* @var ContentHistory
|
||||
*/
|
||||
private $history;
|
||||
|
||||
public function __construct(ContentHistory $history)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->history = $history;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getOverview($id)
|
||||
{
|
||||
// test if given content id is static page and if exists
|
||||
$content = Content::findOrFail($id);
|
||||
|
||||
$history = $this->history->getStructuredHistoryOf($content);
|
||||
|
||||
return view('admin/history.overview', [
|
||||
'history' => $history,
|
||||
'page' => $content
|
||||
]);
|
||||
}
|
||||
|
||||
public function getDiff($revision, $id)
|
||||
{
|
||||
$change = $this->history->findOrFail($id);
|
||||
$diff = $this->history->getDiff($change);
|
||||
|
||||
return view('admin/history.diff', [
|
||||
'change' => $change,
|
||||
'columnName' => 'Page content',
|
||||
'diff' => $diff
|
||||
]);
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -1,11 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
namespace App\Http\Controllers\Admin\CustomFields;
|
||||
|
||||
use App\Enumerations\CustomFieldResources;
|
||||
use App\Enumerations\CustomFieldTypes;
|
||||
use App\Events\CreateNewCustomField as CreateNewCustomFieldEvent;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\NewCustomFieldRequest;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class CreateNewCustomField extends Controller
|
||||
{
|
||||
@@ -59,6 +62,9 @@ class CreateNewCustomField extends Controller
|
||||
|
||||
$customField->save();
|
||||
|
||||
// fire event about creating new custom field
|
||||
Event::fire(new CreateNewCustomFieldEvent($customField));
|
||||
|
||||
return redirect()
|
||||
->route('customfields.new')
|
||||
->with('success', trans('admin/customFields.successfullyCreated'));
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
namespace App\Http\Controllers\Admin\CustomFields;
|
||||
|
||||
use App\Enumerations\CustomFieldResources;
|
||||
use App\Enumerations\CustomFieldTypes;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Models\CustomField;
|
||||
|
||||
class CustomFieldsOverview extends Controller
|
||||
+11
-3
@@ -1,13 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
namespace App\Http\Controllers\Admin\CustomFields;
|
||||
|
||||
use App\Enumerations\CustomFieldResources;
|
||||
use App\Enumerations\CustomFieldTypes;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Events\DeleteCustomField;
|
||||
use App\Events\EditCustomField as EditCustomFieldEvent;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\EditCustomFieldRequest;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EditCustomField extends Controller
|
||||
{
|
||||
@@ -60,6 +62,9 @@ class EditCustomField extends Controller
|
||||
// save changes into database
|
||||
$customField->save();
|
||||
|
||||
// fire event about editing custom field
|
||||
Event::fire(new EditCustomFieldEvent($customField));
|
||||
|
||||
return redirect()
|
||||
->route('customfields.edit', ['id' => $id])
|
||||
->with('success', trans('admin/customFields.successfullyEdited'));
|
||||
@@ -89,6 +94,9 @@ class EditCustomField extends Controller
|
||||
// delete item
|
||||
$field->delete();
|
||||
|
||||
// fire event about editing custom field
|
||||
Event::fire(new DeleteCustomField($field));
|
||||
|
||||
// redirect back to overview
|
||||
return redirect()
|
||||
->route('customfields.overview')
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class Dashboard extends Controller
|
||||
{
|
||||
public function getIndex(Request $request) {
|
||||
return view('admin.dashboard');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Dashboard;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class Dashboard extends Controller
|
||||
{
|
||||
public function getIndex(Request $request)
|
||||
{
|
||||
return redirect()->route('content.overview');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\FileManager;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Models\Directory;
|
||||
|
||||
class CreateNewDirectory extends Controller
|
||||
{
|
||||
/**
|
||||
* Create new directory
|
||||
*
|
||||
* @param Requests\CreateNewDirectoryRequest $request
|
||||
*
|
||||
* @return $this|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postNew(Requests\CreateNewDirectoryRequest $request)
|
||||
{
|
||||
// check if created folder does not exist in current directory
|
||||
$exists = Directory::where('name', $request->name)
|
||||
->where('parent_id', $request->parentDirectory)
|
||||
->exists();
|
||||
if ($exists) {
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'status' => 'failed',
|
||||
'message' => trans('admin/fileManager.subdirectoryExists')
|
||||
]);
|
||||
} else {
|
||||
return redirect()
|
||||
->route('upload.overview', ['id' => $request->parentDirectory])
|
||||
->withInput()
|
||||
->with('error', trans('admin/fileManager.subdirectoryExists'));
|
||||
}
|
||||
}
|
||||
|
||||
// create new database entry
|
||||
$directory = new Directory();
|
||||
$directory->name = $request->name;
|
||||
$directory->parent_id = $request->parentDirectory;
|
||||
$directory->user_id = \Auth::user()->id;
|
||||
$directory->description = $request->description;
|
||||
|
||||
$directory->save();
|
||||
|
||||
$message = trans('admin/fileManager.newDirectorySuccess');
|
||||
if (!$request->ajax()) {
|
||||
return redirect()
|
||||
->route('upload.overview', ['id' => $request->parentDirectory])
|
||||
->with('success', $message);
|
||||
} else {
|
||||
$payload = [
|
||||
'status' => 'success',
|
||||
'message' => $message,
|
||||
'parentDirectory' => $request->parentDirectory
|
||||
];
|
||||
|
||||
return response()->json($payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\FileManager;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Models\Directory;
|
||||
|
||||
class EditDirectory extends Controller
|
||||
{
|
||||
/**
|
||||
* @param Requests\EditDirectoryRequest $request
|
||||
* @param $directoryId
|
||||
*
|
||||
* @return $this|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postEdit(Requests\EditDirectoryRequest $request, $directoryId)
|
||||
{
|
||||
$directory = Directory::findOrFail($directoryId);
|
||||
|
||||
// check if given name is not used in parent directory
|
||||
|
||||
$exists = Directory::where('parent_id', $directory->parent_id)
|
||||
->where('name', $request->name)
|
||||
->where('id', '!=', $directoryId)
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'status' => 'failed',
|
||||
'message' => trans('admin/fileManager.subdirectoryExists')
|
||||
]);
|
||||
} else {
|
||||
return redirect()
|
||||
->route('upload.overview', ['id' => $directoryId])
|
||||
->withInput()
|
||||
->with('error', trans('admin/fileManager.subdirectoryExists'));
|
||||
}
|
||||
}
|
||||
|
||||
$directory->name = $request->name;
|
||||
$directory->description = $request->description;
|
||||
|
||||
$directory->save();
|
||||
|
||||
$message = trans('admin/fileManager.editDirectorySuccess');
|
||||
if (!$request->ajax()) {
|
||||
return redirect()
|
||||
->route('upload.overview', ['id' => $directory->id])
|
||||
->with('success', $message);
|
||||
} else {
|
||||
$payload = [
|
||||
'status' => 'success',
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
return response()->json($payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\FileManager;
|
||||
|
||||
use App\Events\EditFile;
|
||||
use App\Helpers\FileManager;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\EditUploadedFileRequest;
|
||||
use App\Models\File;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class EditUploadedFile extends Controller
|
||||
{
|
||||
/**
|
||||
* Edit form
|
||||
*
|
||||
* Render edit form for displaying details and updating given file
|
||||
*
|
||||
* @param int $id file id
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function getDetail($id)
|
||||
{
|
||||
try {
|
||||
$file = File::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
return $this->fileNotFound();
|
||||
}
|
||||
|
||||
return view('admin.fileManager.edit', [
|
||||
'file' => $file,
|
||||
'extraInfo' => FileManager::getAdditionalInfo($file)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates file
|
||||
*
|
||||
* User can change only keywords, original filename and description. Mime type, hash and other fields remain
|
||||
* unchanged
|
||||
*
|
||||
* @param EditUploadedFileRequest $request
|
||||
* @param $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postEdit(EditUploadedFileRequest $request, $id)
|
||||
{
|
||||
try {
|
||||
$file = File::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
return $this->fileNotFound();
|
||||
}
|
||||
|
||||
// set values from form
|
||||
$file->name = $request->name;
|
||||
$file->keywords = $request->keywords;
|
||||
$file->description = $request->description;
|
||||
$file->save();
|
||||
|
||||
// fire action
|
||||
Event::fire(new EditFile($file));
|
||||
|
||||
// update successfull
|
||||
return redirect()
|
||||
->route('upload.detail', ['id' => $id])
|
||||
->with('success', trans('admin/fileManager.successfullyChanged'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes file
|
||||
*
|
||||
* @param $id
|
||||
*/
|
||||
public function deleteFile($id)
|
||||
{
|
||||
try {
|
||||
$file = File::findOrFail($id);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
return $this->fileNotFound();
|
||||
}
|
||||
|
||||
$directoryId = $file->directory_id;
|
||||
$file->delete();
|
||||
|
||||
return redirect()
|
||||
->route('upload.overview', ['id' => $directoryId])
|
||||
->with('success', trans('admin/fileManager.fileDeleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects user to files overview
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
private function fileNotFound()
|
||||
{
|
||||
return redirect()
|
||||
->route('upload.overview')
|
||||
->with('error', trans('admin/fileManager.fileNotFound'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\FileManager;
|
||||
|
||||
use App\Helpers\Template;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\File;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||
|
||||
class UploadFile extends Controller
|
||||
{
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
private $file;
|
||||
|
||||
function __construct(File $file)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads any file
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postFile(Request $request)
|
||||
{
|
||||
if (Input::get('CKEditor')) {
|
||||
return $this->ckEditorUpload($request);
|
||||
} else {
|
||||
return $this->internalUpload($request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file using internal file uploader
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
private function internalUpload(Request $request)
|
||||
{
|
||||
try {
|
||||
$uploadedFiles = [];
|
||||
$files = $request->all()['files'];
|
||||
|
||||
$successfullUploads = 0;
|
||||
foreach ($files as $file) {
|
||||
$uploadedFile = $this->file->upload($file, $request);
|
||||
$successfullUploads++;
|
||||
|
||||
$uploadedFiles[] = $uploadedFile;
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success', trans_choice('admin/fileManager.uploadSuccessfull', $successfullUploads));
|
||||
} catch (FileException $e) {
|
||||
return $this->invalidUpload('invalidFile');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file using CKEditor
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
private function ckEditorUpload(Request $request)
|
||||
{
|
||||
$file = $request->file('upload');
|
||||
|
||||
$uploadedFile = $this->file->upload($file, $request);
|
||||
|
||||
return view('admin.snippets.ckEditorUploaded', [
|
||||
'ckEditor' => Input::get('CKEditor'),
|
||||
'funcNumber' => Input::get('CKEditorFuncNum'),
|
||||
'fileUrl' => Template::upload($uploadedFile['filename'])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message and redirect to upload.overview when upload failed
|
||||
*
|
||||
* @param $message
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function invalidUpload($message)
|
||||
{
|
||||
return redirect()
|
||||
->route('upload.overview')
|
||||
->with('error', trans('admin/fileManager.' . $message));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Admin\FileManager;
|
||||
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use App\Models\Directory;
|
||||
use App\Models\File;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class UploadedFilesOverview extends Controller
|
||||
{
|
||||
/**
|
||||
* List of all files and directories
|
||||
*
|
||||
* @param null $directoryId
|
||||
* @param null $fileType
|
||||
* @param null $fileSubtype
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getOverview($directoryId = null, $fileType = null, $fileSubtype = null)
|
||||
{
|
||||
// get directory information
|
||||
$directory = is_null($directoryId) ? new Directory() : Directory::findOrFail($directoryId);
|
||||
|
||||
// get all files in this directory
|
||||
$files = File::orderBy('updated_at', 'DESC')
|
||||
->where('directory_id', $directory->id);
|
||||
|
||||
// try to filter by given type
|
||||
if (!is_null($fileType)) {
|
||||
if (is_null($fileSubtype)) {
|
||||
$files = $files->where('mime_type', 'LIKE', $fileType . '%');
|
||||
} else {
|
||||
$files = $files->where('mime_type', $fileType . '/' . $fileSubtype);
|
||||
}
|
||||
}
|
||||
|
||||
// include hidden directories?
|
||||
$includeHidden = Input::get('hidden');
|
||||
|
||||
return view('admin.fileManager.overview', [
|
||||
'directory' => $directory,
|
||||
'subdirectories' => $directory->subdirectories($includeHidden),
|
||||
'files' => $files->get()
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,10 @@
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Http\Requests\LoginRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
/**
|
||||
* Class Login
|
||||
@@ -20,6 +17,16 @@ use Illuminate\Support\Facades\Session;
|
||||
*/
|
||||
class Login extends Controller
|
||||
{
|
||||
/**
|
||||
* Display login form
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getLogin()
|
||||
{
|
||||
return view('admin.loginForm');
|
||||
}
|
||||
|
||||
/**
|
||||
* Login handler
|
||||
*
|
||||
@@ -45,13 +52,32 @@ class Login extends Controller
|
||||
if (Hash::check($request->password, $user->password)) {
|
||||
Auth::login($user);
|
||||
|
||||
return redirect()->intended(route('admin.dashboard'));
|
||||
$redirect = $request->redirectTo ? $request->redirectTo : route('admin.dashboard');
|
||||
|
||||
return redirect()->intended($redirect);
|
||||
}
|
||||
|
||||
// login invalid, redirect and inform the user
|
||||
return $this->loginFailed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out user
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
|
||||
// remove user information
|
||||
\Auth::logout();
|
||||
|
||||
// redirect to login form with info about successfull logout
|
||||
return redirect()
|
||||
->route('login')
|
||||
->with('success', trans('admin/common.logoutSuccessfull'));
|
||||
}
|
||||
|
||||
private function loginFailed()
|
||||
{
|
||||
return redirect()
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Handlers\Contracts\SearchHandler;
|
||||
use App\Handlers\Contracts\SearchPresenterHandler;
|
||||
use App\Handlers\Registrators\SearchEngineRegistrator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
class Search extends Controller
|
||||
{
|
||||
/**
|
||||
* Create form for searching
|
||||
*
|
||||
* @return $this|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function getSearch()
|
||||
{
|
||||
$results = [];
|
||||
$term = Input::get('search');
|
||||
|
||||
if (!is_null($term)) {
|
||||
try {
|
||||
$results = $this->performSearch($term);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
// user entered empty string (or something like empty string)
|
||||
return redirect()
|
||||
->route('search')
|
||||
->with('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return view('admin.search.page', ['search' => $term, 'results' => $results]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used for performing search.
|
||||
*
|
||||
* This method iterates over all registered search engines and returns results for each engine apart.
|
||||
*
|
||||
* @param string $term search text
|
||||
*
|
||||
* @return array array of results. One item per each engine
|
||||
*/
|
||||
protected function performSearch($term)
|
||||
{
|
||||
$engines = App::make('registerSearchEngine')
|
||||
->get(SearchEngineRegistrator::ADMIN);
|
||||
|
||||
$resultsParts = [];
|
||||
foreach ($engines as $engine) {
|
||||
/**
|
||||
* @var SearchHandler $search
|
||||
* @var SearchPresenterHandler $presenter
|
||||
*/
|
||||
list ($search, $presenter) = $engine;
|
||||
|
||||
// try to find given term
|
||||
$results = $search->search($term);
|
||||
|
||||
// create result object
|
||||
$resultsParts[$search->getId()] = [
|
||||
'name' => $search->getName(),
|
||||
'content' => $presenter->render($results),
|
||||
'count' => count($results)
|
||||
];
|
||||
}
|
||||
|
||||
return $resultsParts;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user